Use a spinner to select folders in the bookmarks database view. https://redmine...
authorSoren Stoutner <soren@stoutner.com>
Tue, 24 Oct 2017 20:15:58 +0000 (13:15 -0700)
committerSoren Stoutner <soren@stoutner.com>
Tue, 24 Oct 2017 20:15:58 +0000 (13:15 -0700)
22 files changed:
app/src/main/java/com/stoutner/privacybrowser/activities/BookmarksActivity.java
app/src/main/java/com/stoutner/privacybrowser/activities/BookmarksDatabaseViewActivity.java
app/src/main/java/com/stoutner/privacybrowser/dialogs/MoveToFolderDialog.java
app/src/main/java/com/stoutner/privacybrowser/fragments/DomainSettingsFragment.java
app/src/main/java/com/stoutner/privacybrowser/helpers/BookmarksDatabaseHelper.java
app/src/main/res/color/bookmarks_spinner_color_selector_dark.xml [new file with mode: 0644]
app/src/main/res/color/bookmarks_spinner_color_selector_light.xml [new file with mode: 0644]
app/src/main/res/layout/bookmarks_database_view_coordinatorlayout.xml [deleted file]
app/src/main/res/layout/bookmarks_database_view_item_linearlayout.xml [deleted file]
app/src/main/res/layout/bookmarks_databaseview_coordinatorlayout.xml [new file with mode: 0644]
app/src/main/res/layout/bookmarks_databaseview_item_linearlayout.xml [new file with mode: 0644]
app/src/main/res/layout/bookmarks_databaseview_spinner.xml [new file with mode: 0644]
app/src/main/res/layout/bookmarks_databaseview_spinner_dropdown_item.xml [new file with mode: 0644]
app/src/main/res/layout/bookmarks_databaseview_spinner_item.xml [new file with mode: 0644]
app/src/main/res/layout/domain_settings_spinner_dropdown_item.xml [new file with mode: 0644]
app/src/main/res/layout/domain_settings_spinner_item.xml [new file with mode: 0644]
app/src/main/res/layout/spinner_dropdown_item.xml [deleted file]
app/src/main/res/layout/spinner_item.xml [deleted file]
app/src/main/res/values/attrs.xml
app/src/main/res/values/colors.xml
app/src/main/res/values/strings.xml
app/src/main/res/values/styles.xml

index 42b1c0e..e640b79 100644 (file)
@@ -116,8 +116,12 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma
         // Get the intent that launched the activity.
         Intent launchingIntent = getIntent();
 
-        // Get the current folder from the `Intent`.
-        currentFolder = launchingIntent.getStringExtra("Current Folder");
+        // Set the current folder variable.
+        if (launchingIntent.getStringExtra("Current Folder") != null) {  // Set the current folder from the intent.
+            currentFolder = launchingIntent.getStringExtra("Current Folder");
+        } else {  // Set the current folder to be `""`, which is the home folder.
+            currentFolder = "";
+        }
 
         // Set the content view.
         setContentView(R.layout.bookmarks_coordinatorlayout);
index 53fb657..1725cac 100644 (file)
@@ -21,19 +21,24 @@ package com.stoutner.privacybrowser.activities;
 
 import android.content.Context;
 import android.database.Cursor;
+import android.database.MatrixCursor;
+import android.database.MergeCursor;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Typeface;
 import android.os.Bundle;
 import android.support.v4.content.ContextCompat;
 import android.support.v4.widget.CursorAdapter;
+import android.support.v4.widget.ResourceCursorAdapter;
 import android.support.v7.app.ActionBar;
 import android.support.v7.app.AppCompatActivity;
 import android.support.v7.widget.Toolbar;
 import android.view.View;
 import android.view.ViewGroup;
+import android.widget.AdapterView;
 import android.widget.ImageView;
 import android.widget.ListView;
+import android.widget.Spinner;
 import android.widget.TextView;
 
 import com.stoutner.privacybrowser.R;
@@ -46,6 +51,9 @@ public class BookmarksDatabaseViewActivity extends AppCompatActivity {
     // `bookmarksListView` is used in `onCreate()` and `updateBookmarksListView()`.
     private ListView bookmarksListView;
 
+    // `bookmarksCursorAdapter` is used in `onCreate()` and `updateBookmarksListView()`.
+    private CursorAdapter bookmarksCursorAdapter;
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         // Set the activity theme.
@@ -56,26 +64,109 @@ public class BookmarksDatabaseViewActivity extends AppCompatActivity {
         }
 
         super.onCreate(savedInstanceState);
-        setContentView(R.layout.bookmarks_database_view_coordinatorlayout);
+        setContentView(R.layout.bookmarks_databaseview_coordinatorlayout);
 
         // We need to use the `SupportActionBar` from `android.support.v7.app.ActionBar` until the minimum API is >= 21.
         final Toolbar bookmarksDatabaseViewAppBar = (Toolbar) findViewById(R.id.bookmarks_database_view_toolbar);
         setSupportActionBar(bookmarksDatabaseViewAppBar);
 
-        // Display the home arrow on `SupportActionBar`.
+        // Get a handle for the `AppBar`.
         final ActionBar appBar = getSupportActionBar();
-        assert appBar != null;  // This assert removes the incorrect warning in Android Studio on the following line that appBar might be null.
-        appBar.setDisplayHomeAsUpEnabled(true);
 
-        // Initialize the database handler and the ListView.
-        // `this` specifies the context.  The two `null`s do not specify the database name or a `CursorFactory`.
-        // The `0` is to specify a database version, but that is set instead using a constant in `BookmarksDatabaseHelper`.
+        // Remove the incorrect warning in Android Studio that `appBar` might be null.
+        assert appBar != null;
+
+        // Display the `Spinner` and the back arrow in the `AppBar`.
+        appBar.setCustomView(R.layout.bookmarks_databaseview_spinner);
+        appBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM | ActionBar.DISPLAY_HOME_AS_UP);
+
+        // Initialize the database handler.  `this` specifies the context.  The two `null`s do not specify the database name or a `CursorFactory`.  The `0` is to specify a database version, but that is set instead using a constant in `BookmarksDatabaseHelper`.
         bookmarksDatabaseHelper = new BookmarksDatabaseHelper(this, null, null, 0);
+
+        // Setup a `MatrixCursor` for "All Folders" and "Home Folder".
+        String[] matrixCursorColumnNames = {BookmarksDatabaseHelper._ID, BookmarksDatabaseHelper.BOOKMARK_NAME};
+        MatrixCursor matrixCursor = new MatrixCursor(matrixCursorColumnNames);
+        matrixCursor.addRow(new Object[]{-2, getString(R.string.all_folders)});
+        matrixCursor.addRow(new Object[]{-1, getString(R.string.home_folder)});
+
+        // Get a `Cursor` with the list of all the folders.
+        Cursor foldersCursor = bookmarksDatabaseHelper.getAllFoldersCursor();
+
+        // Combine `matrixCursor` and `foldersCursor`.
+        MergeCursor foldersMergeCursor = new MergeCursor(new Cursor[]{matrixCursor, foldersCursor});
+
+        // Create a `ResourceCursorAdapter` for the spinner with `this` context.  `0` specifies no flags.;
+        ResourceCursorAdapter foldersCursorAdapter = new ResourceCursorAdapter(this, R.layout.bookmarks_databaseview_spinner_item, foldersMergeCursor, 0) {
+            @Override
+            public void bindView(View view, Context context, Cursor cursor) {
+                // Get a handle for the spinner item `TextView`.
+                TextView spinnerItemTextView = (TextView) view.findViewById(R.id.spinner_item_textview);
+
+                // Set the `TextView` to display the folder name.
+                spinnerItemTextView.setText(cursor.getString(cursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME)));
+            }
+        };
+
+        // Set the `ResourceCursorAdapter` drop drown view resource.
+        foldersCursorAdapter.setDropDownViewResource(R.layout.bookmarks_databaseview_spinner_dropdown_item);
+
+        // Get a handle for the folder `Spinner`.
+        Spinner folderSpinner = (Spinner) findViewById(R.id.bookmarks_database_view_spinner);
+
+        // Set the adapter for the folder `Spinner`.
+        folderSpinner.setAdapter(foldersCursorAdapter);
+
+        // Handle clicks on the `Spinner` dropdown.
+        folderSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
+            @Override
+            public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
+                // Convert the database ID to an `int`.
+                int databaseId = (int) id;
+
+                // Instantiate the bookmarks `Cursor`.
+                Cursor bookmarksCursor;
+
+                // Populate the bookmarks `ListView` based on the `Spinner` selection.
+                switch (databaseId) {
+                    // Display all the folders.
+                    case -2:
+                        // Get a cursor with all the folders.
+                        bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursor();
+                        break;
+
+                    // Display the home folder.
+                    case -1:
+                        // Get a cursor for the home folder.
+                        bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursor("");
+                        break;
+
+                    // Display the selected folder.
+                    default:
+                        // Get a handle for the selected view.
+                        TextView selectedFolderTextView = (TextView) view.findViewById(R.id.spinner_item_textview);
+
+                        // Extract the name of the selected folder.
+                        String folderName = selectedFolderTextView.getText().toString();
+
+                        // Get a cursor for the selected folder.
+                        bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursor(folderName);
+                }
+
+                // Update the `ListView`.
+                bookmarksCursorAdapter.changeCursor(bookmarksCursor);
+            }
+
+            @Override
+            public void onNothingSelected(AdapterView<?> parent) {
+                // Do nothing.
+            }
+        });
+
+        // Get a handle for the bookmarks `ListView`.
         bookmarksListView = (ListView) findViewById(R.id.bookmarks_database_view_listview);
 
-        // Display the bookmarks in the ListView.
+        // Display the bookmarks in the `ListView`.
         updateBookmarksListView();
-
     }
 
     private void updateBookmarksListView() {
@@ -83,11 +174,11 @@ public class BookmarksDatabaseViewActivity extends AppCompatActivity {
         final Cursor bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursor();
 
         // Setup `bookmarksCursorAdapter` with `this` context.  The `false` disables autoRequery.
-        CursorAdapter bookmarksCursorAdapter = new CursorAdapter(this, bookmarksCursor, false) {
+        bookmarksCursorAdapter = new CursorAdapter(this, bookmarksCursor, false) {
             @Override
             public View newView(Context context, Cursor cursor, ViewGroup parent) {
                 // Inflate the individual item layout.  `false` does not attach it to the root.
-                return getLayoutInflater().inflate(R.layout.bookmarks_database_view_item_linearlayout, parent, false);
+                return getLayoutInflater().inflate(R.layout.bookmarks_databaseview_item_linearlayout, parent, false);
             }
 
             @Override
index 8ced87d..eff2f77 100644 (file)
@@ -223,13 +223,13 @@ public class MoveToFolderDialog extends AppCompatDialogFragment {
                 }
             }
 
-            // Get a `foldersCursor`.
+            // Get a `Cursor` containing the folders to display.
             foldersCursor = BookmarksActivity.bookmarksDatabaseHelper.getFoldersCursorExcept(exceptFolders);
 
             // Combine `homeFolderMatrixCursor` and `foldersCursor`.
             MergeCursor foldersMergeCursor = new MergeCursor(new Cursor[]{homeFolderMatrixCursor, foldersCursor});
 
-            // Setup `foldersCursorAdaptor` with `this` context.  `false` disables autoRequery.
+            // Setup `foldersCursorAdaptor`.  `false` disables autoRequery.
             foldersCursorAdapter = new CursorAdapter(alertDialog.getContext(), foldersMergeCursor, false) {
                 @Override
                 public View newView(Context context, Cursor cursor, ViewGroup parent) {
index 31dd027..0fd7a69 100644 (file)
@@ -192,18 +192,18 @@ public class DomainSettingsFragment extends Fragment {
         }
 
         // Create `ArrayAdapters` for the `Spinners`and their `entry values`.
-        ArrayAdapter<CharSequence> userAgentArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_user_agent_entries, R.layout.spinner_item);
-        final ArrayAdapter<CharSequence> userAgentEntryValuesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_user_agent_entry_values, R.layout.spinner_item);
-        ArrayAdapter<CharSequence> fontSizeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_font_size_entries, R.layout.spinner_item);
-        ArrayAdapter<CharSequence> fontSizeEntryValuesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_font_size_entry_values, R.layout.spinner_item);
-        final ArrayAdapter<CharSequence> displayImagesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.display_webpage_images_array, R.layout.spinner_item);
-        ArrayAdapter<CharSequence> nightModeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.night_mode_array, R.layout.spinner_item);
+        ArrayAdapter<CharSequence> userAgentArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_user_agent_entries, R.layout.domain_settings_spinner_item);
+        final ArrayAdapter<CharSequence> userAgentEntryValuesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_user_agent_entry_values, R.layout.domain_settings_spinner_item);
+        ArrayAdapter<CharSequence> fontSizeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_font_size_entries, R.layout.domain_settings_spinner_item);
+        ArrayAdapter<CharSequence> fontSizeEntryValuesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.domain_settings_font_size_entry_values, R.layout.domain_settings_spinner_item);
+        final ArrayAdapter<CharSequence> displayImagesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.display_webpage_images_array, R.layout.domain_settings_spinner_item);
+        ArrayAdapter<CharSequence> nightModeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.night_mode_array, R.layout.domain_settings_spinner_item);
 
         // Set the `DropDownViewResource` on the `Spinners`.
-        userAgentArrayAdapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
-        fontSizeArrayAdapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
-        displayImagesArrayAdapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
-        nightModeArrayAdapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
+        userAgentArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_item);
+        fontSizeArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_item);
+        displayImagesArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_item);
+        nightModeArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_item);
 
         // Set the `ArrayAdapters` for the `Spinners`.
         userAgentSpinner.setAdapter(userAgentArrayAdapter);
index 8448151..532c771 100644 (file)
@@ -231,7 +231,8 @@ public class BookmarksDatabaseHelper extends SQLiteOpenHelper {
 
         // Prepare the SQL statement to get the `Cursor` for all the folders.
         final String GET_ALL_FOLDERS = "SELECT * FROM " + BOOKMARKS_TABLE +
-                " WHERE " + IS_FOLDER + " = " + 1;
+                " WHERE " + IS_FOLDER + " = " + 1 +
+                " ORDER BY " + BOOKMARK_NAME + " ASC";
 
         // Return the results as a `Cursor`.  The second argument is `null` because there are no `selectionArgs`.
         // We can't close the `Cursor` because we need to use it in the parent activity.
@@ -251,6 +252,22 @@ public class BookmarksDatabaseHelper extends SQLiteOpenHelper {
         return bookmarksDatabase.rawQuery(GET_ALL_BOOKMARKS, null);
     }
 
+    // Get a `Cursor` for all bookmarks and folders in the specified folder.
+    public Cursor getAllBookmarksCursor(String folderName) {
+        // Get a readable database handle.
+        SQLiteDatabase bookmarksDatabase = this.getReadableDatabase();
+
+        // SQL escape `folderName`.
+        folderName = DatabaseUtils.sqlEscapeString(folderName);
+
+        // Get everything in the `BOOKMARKS_TABLE` with `folderName` as the `PARENT_FOLDER`.
+        final String GET_ALL_BOOKMARKS = "SELECT * FROM " + BOOKMARKS_TABLE +
+                " WHERE " + PARENT_FOLDER + " = " + folderName;
+
+        // Return the results as a `Cursor`.  The second argument is `null` because there are no `selectionArgs`.  We can't close the `Cursor` because we need to use it in the parent activity.
+        return bookmarksDatabase.rawQuery(GET_ALL_BOOKMARKS, null);
+    }
+
     // Get a `Cursor` for all bookmarks and folders in the specified folder ordered by display order.
     public Cursor getAllBookmarksCursorByDisplayOrder(String folderName) {
         // Get a readable database handle.
diff --git a/app/src/main/res/color/bookmarks_spinner_color_selector_dark.xml b/app/src/main/res/color/bookmarks_spinner_color_selector_dark.xml
new file mode 100644 (file)
index 0000000..dae2ca4
--- /dev/null
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright © 2017 Soren Stoutner <soren@stoutner.com>.
+
+  This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
+
+  Privacy Browser is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  Privacy Browser is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with Privacy Browser.  If not, see <http://www.gnu.org/licenses/>. -->
+
+<!-- Highlight the selected item when the spinner is open. -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android" >
+    <item android:state_checked="true" android:color="@color/gray_300" />
+    <item android:color="@color/gray_500" />
+</selector>
\ No newline at end of file
diff --git a/app/src/main/res/color/bookmarks_spinner_color_selector_light.xml b/app/src/main/res/color/bookmarks_spinner_color_selector_light.xml
new file mode 100644 (file)
index 0000000..3e8f830
--- /dev/null
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright © 2017 Soren Stoutner <soren@stoutner.com>.
+
+  This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
+
+  Privacy Browser is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  Privacy Browser is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with Privacy Browser.  If not, see <http://www.gnu.org/licenses/>. -->
+
+<!-- Highlight the selected item when the spinner is open. -->
+<selector xmlns:android="http://schemas.android.com/apk/res/android" >
+    <item android:state_checked="true" android:color="@color/white" />
+    <item android:color="@color/blue_100" />
+</selector>
\ No newline at end of file
diff --git a/app/src/main/res/layout/bookmarks_database_view_coordinatorlayout.xml b/app/src/main/res/layout/bookmarks_database_view_coordinatorlayout.xml
deleted file mode 100644 (file)
index d81c02d..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
-  Copyright © 2016-2017 Soren Stoutner <soren@stoutner.com>.
-
-  This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
-
-  Privacy Browser is free software: you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation, either version 3 of the License, or
-  (at your option) any later version.
-
-  Privacy Browser is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with Privacy Browser.  If not, see <http://www.gnu.org/licenses/>. -->
-
-<!-- `android:fitsSystemWindows="true"` moves the AppBar below the status bar.
-    When it is specified the theme should include `<item name="android:windowTranslucentStatus">true</item>`
-    to make the status bar a transparent, darkened overlay. -->
-<android.support.design.widget.CoordinatorLayout
-    android:id="@+id/bookmarks_database_view_coordinatorlayout"
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_height="match_parent"
-    android:layout_width="match_parent"
-    android:fitsSystemWindows="true" >
-
-    <!-- the `LinearLayout` with `orientation="vertical"` moves the content below the `AppBarLayout`. -->
-    <LinearLayout
-        android:layout_height="match_parent"
-        android:layout_width="match_parent"
-        android:orientation="vertical" >
-
-        <android.support.design.widget.AppBarLayout
-            android:id="@+id/bookmarks_database_view_appbarlayout"
-            android:layout_height="wrap_content"
-            android:layout_width="match_parent" >
-
-            <android.support.v7.widget.Toolbar
-                android:id="@+id/bookmarks_database_view_toolbar"
-                android:layout_height="wrap_content"
-                android:layout_width="match_parent"
-                android:background="?attr/colorPrimaryDark"
-                android:theme="?attr/appBarTextTheme" />
-        </android.support.design.widget.AppBarLayout>
-
-        <ListView
-            android:id="@+id/bookmarks_database_view_listview"
-            android:layout_height="match_parent"
-            android:layout_width="match_parent" />
-    </LinearLayout>
-</android.support.design.widget.CoordinatorLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/bookmarks_database_view_item_linearlayout.xml b/app/src/main/res/layout/bookmarks_database_view_item_linearlayout.xml
deleted file mode 100644 (file)
index c5f3fa2..0000000
+++ /dev/null
@@ -1,111 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
-  Copyright © 2016-2017 Soren Stoutner <soren@stoutner.com>.
-
-  This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
-
-  Privacy Browser is free software: you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation, either version 3 of the License, or
-  (at your option) any later version.
-
-  Privacy Browser is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with Privacy Browser.  If not, see <http://www.gnu.org/licenses/>. -->
-
-<LinearLayout
-    android:id="@+id/bookmarks_database_view_item_linearlayout"
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:tools="http://schemas.android.com/tools"
-    android:layout_height="wrap_content"
-    android:layout_width="match_parent"
-    android:orientation="vertical" >
-
-    <!-- First row. -->
-    <LinearLayout
-        android:layout_height="wrap_content"
-        android:layout_width="match_parent"
-        android:layout_marginTop="10dp"
-        android:layout_marginStart="10dp"
-        android:layout_marginEnd="10dp"
-        android:orientation="horizontal" >
-
-        <TextView
-            android:id="@+id/bookmarks_database_view_database_id"
-            android:layout_height="wrap_content"
-            android:layout_width="50dp"
-            android:layout_marginEnd="10dp"
-            android:gravity="end"
-            android:textColor="@color/gray_500"
-            android:textSize="22sp" />
-
-        <ImageView
-            android:id="@+id/bookmarks_database_view_favorite_icon"
-            android:layout_width="30dp"
-            android:layout_height="30dp"
-            android:layout_gravity="center_vertical"
-            android:layout_marginEnd="10dp"
-            tools:ignore="ContentDescription" />
-
-        <TextView
-            android:id='@+id/bookmarks_database_view_bookmark_name'
-            android:layout_height="wrap_content"
-            android:layout_width="wrap_content"
-            android:textColor="?android:attr/textColorPrimary"
-            android:textSize="22sp"
-            android:maxLines="1" />
-    </LinearLayout>
-
-    <!-- Second row. -->
-    <LinearLayout
-        android:layout_height="wrap_content"
-        android:layout_width="wrap_content"
-        android:layout_marginStart="10dp"
-        android:layout_marginEnd="10dp"
-        android:orientation="horizontal" >
-
-        <TextView
-            android:id="@+id/bookmarks_database_view_display_order"
-            android:layout_height="wrap_content"
-            android:layout_width="50dp"
-            android:layout_marginEnd="10dp"
-            android:gravity="end"
-            android:textColor="?android:attr/textColorPrimary"
-            android:textSize="22sp" />
-
-        <ImageView
-            android:id="@+id/bookmarks_database_view_parent_folder_icon"
-            android:layout_height="30dp"
-            android:layout_width="30dp"
-            android:layout_gravity="center_vertical"
-            android:layout_marginEnd="10dp"
-            android:src="@drawable/folder_gray"
-            tools:ignore="ContentDescription" />
-
-        <TextView
-            android:id="@+id/bookmarks_database_view_parent_folder"
-            android:layout_height="wrap_content"
-            android:layout_width="wrap_content"
-            android:textSize="22sp"
-            android:textStyle="italic"
-            android:maxLines="1" />
-    </LinearLayout>
-
-    <!-- Third row. -->
-    <TextView
-        android:id="@+id/bookmarks_database_view_bookmark_url"
-        android:layout_height="wrap_content"
-        android:layout_width="wrap_content"
-        android:layout_marginBottom="10dp"
-        android:layout_marginStart="13dp"
-        android:layout_marginEnd="10dp"
-        android:textColor="?android:attr/textColorPrimary"
-        android:textSize="22sp"
-        android:ellipsize="end"
-        android:maxLines="1" />
-</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/bookmarks_databaseview_coordinatorlayout.xml b/app/src/main/res/layout/bookmarks_databaseview_coordinatorlayout.xml
new file mode 100644 (file)
index 0000000..207b19d
--- /dev/null
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright © 2016-2017 Soren Stoutner <soren@stoutner.com>.
+
+  This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
+
+  Privacy Browser is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  Privacy Browser is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with Privacy Browser.  If not, see <http://www.gnu.org/licenses/>. -->
+
+<!-- `android:fitsSystemWindows="true"` moves the AppBar below the status bar.
+    When it is specified the theme should include `<item name="android:windowTranslucentStatus">true</item>`
+    to make the status bar a transparent, darkened overlay. -->
+<android.support.design.widget.CoordinatorLayout
+    android:id="@+id/bookmarks_database_view_coordinatorlayout"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent"
+    android:fitsSystemWindows="true" >
+
+    <!-- The `LinearLayout` with `orientation="vertical"` moves the `ListView` below the `AppBarLayout`. -->
+    <LinearLayout
+        android:layout_height="match_parent"
+        android:layout_width="match_parent"
+        android:orientation="vertical" >
+
+        <android.support.design.widget.AppBarLayout
+            android:id="@+id/bookmarks_database_view_appbarlayout"
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent" >
+
+            <android.support.v7.widget.Toolbar
+                android:id="@+id/bookmarks_database_view_toolbar"
+                android:layout_height="wrap_content"
+                android:layout_width="match_parent"
+                android:background="?attr/colorPrimaryDark"
+                android:theme="?attr/appBarTextTheme" />
+        </android.support.design.widget.AppBarLayout>
+
+        <ListView
+            android:id="@+id/bookmarks_database_view_listview"
+            android:layout_height="match_parent"
+            android:layout_width="match_parent" />
+    </LinearLayout>
+</android.support.design.widget.CoordinatorLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/bookmarks_databaseview_item_linearlayout.xml b/app/src/main/res/layout/bookmarks_databaseview_item_linearlayout.xml
new file mode 100644 (file)
index 0000000..3c91b37
--- /dev/null
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright © 2016-2017 Soren Stoutner <soren@stoutner.com>.
+
+  This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
+
+  Privacy Browser is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  Privacy Browser is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with Privacy Browser.  If not, see <http://www.gnu.org/licenses/>. -->
+
+<LinearLayout
+    android:id="@+id/bookmarks_database_view_item_linearlayout"
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_height="wrap_content"
+    android:layout_width="match_parent"
+    android:orientation="vertical" >
+
+    <!-- First row. -->
+    <LinearLayout
+        android:layout_height="wrap_content"
+        android:layout_width="match_parent"
+        android:layout_marginTop="10dp"
+        android:layout_marginStart="10dp"
+        android:layout_marginEnd="10dp"
+        android:orientation="horizontal" >
+
+        <TextView
+            android:id="@+id/bookmarks_database_view_database_id"
+            android:layout_height="wrap_content"
+            android:layout_width="50dp"
+            android:layout_marginEnd="10dp"
+            android:gravity="end"
+            android:textColor="@color/gray_500"
+            android:textSize="22sp" />
+
+        <ImageView
+            android:id="@+id/bookmarks_database_view_favorite_icon"
+            android:layout_width="30dp"
+            android:layout_height="30dp"
+            android:layout_gravity="center_vertical"
+            android:layout_marginEnd="10dp"
+            tools:ignore="ContentDescription" />
+
+        <TextView
+            android:id='@+id/bookmarks_database_view_bookmark_name'
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:textColor="?android:attr/textColorPrimary"
+            android:textSize="22sp"
+            android:ellipsize="end"
+            android:maxLines="1" />
+    </LinearLayout>
+
+    <!-- Second row. -->
+    <LinearLayout
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:layout_marginStart="10dp"
+        android:layout_marginEnd="10dp"
+        android:orientation="horizontal" >
+
+        <TextView
+            android:id="@+id/bookmarks_database_view_display_order"
+            android:layout_height="wrap_content"
+            android:layout_width="50dp"
+            android:layout_marginEnd="10dp"
+            android:gravity="end"
+            android:textColor="?android:attr/textColorPrimary"
+            android:textSize="22sp" />
+
+        <ImageView
+            android:id="@+id/bookmarks_database_view_parent_folder_icon"
+            android:layout_height="30dp"
+            android:layout_width="30dp"
+            android:layout_gravity="center_vertical"
+            android:layout_marginEnd="10dp"
+            android:src="@drawable/folder_gray"
+            tools:ignore="ContentDescription" />
+
+        <TextView
+            android:id="@+id/bookmarks_database_view_parent_folder"
+            android:layout_height="wrap_content"
+            android:layout_width="wrap_content"
+            android:textSize="22sp"
+            android:textStyle="italic"
+            android:ellipsize="end"
+            android:maxLines="1" />
+    </LinearLayout>
+
+    <!-- Third row. -->
+    <TextView
+        android:id="@+id/bookmarks_database_view_bookmark_url"
+        android:layout_height="wrap_content"
+        android:layout_width="wrap_content"
+        android:layout_marginBottom="10dp"
+        android:layout_marginStart="13dp"
+        android:layout_marginEnd="10dp"
+        android:textColor="?android:attr/textColorPrimary"
+        android:textSize="22sp"
+        android:ellipsize="end"
+        android:maxLines="1" />
+</LinearLayout>
\ No newline at end of file
diff --git a/app/src/main/res/layout/bookmarks_databaseview_spinner.xml b/app/src/main/res/layout/bookmarks_databaseview_spinner.xml
new file mode 100644 (file)
index 0000000..804ac3a
--- /dev/null
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright © 2017 Soren Stoutner <soren@stoutner.com>.
+
+  This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
+
+  Privacy Browser is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  Privacy Browser is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with Privacy Browser.  If not, see <http://www.gnu.org/licenses/>. -->
+
+<Spinner
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/bookmarks_database_view_spinner"
+    android:layout_height="wrap_content"
+    android:layout_width="wrap_content" />
diff --git a/app/src/main/res/layout/bookmarks_databaseview_spinner_dropdown_item.xml b/app/src/main/res/layout/bookmarks_databaseview_spinner_dropdown_item.xml
new file mode 100644 (file)
index 0000000..8df232b
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright © 2017 Soren Stoutner <soren@stoutner.com>.
+
+  This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
+
+  Privacy Browser is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  Privacy Browser is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with Privacy Browser.  If not, see <http://www.gnu.org/licenses/>. -->
+
+<!-- A `CheckedTextView` allows the color of the text to be changed when it is selected (checked). -->
+<CheckedTextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/spinner_item_textview"
+    android:layout_height="wrap_content"
+    android:layout_width="match_parent"
+    android:maxLines="1"
+    android:ellipsize="end"
+    android:paddingStart="20dp"
+    android:paddingEnd="20dp"
+    android:paddingTop="8dp"
+    android:paddingBottom="8dp"
+    android:textSize="18sp"
+    android:textColor="?attr/bookmarksSpinnerTextColorSelector"
+    android:background="?attr/bookmarksSpinnerBackground" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/bookmarks_databaseview_spinner_item.xml b/app/src/main/res/layout/bookmarks_databaseview_spinner_item.xml
new file mode 100644 (file)
index 0000000..62cbb1d
--- /dev/null
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright © 2017 Soren Stoutner <soren@stoutner.com>.
+
+  This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
+
+  Privacy Browser is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  Privacy Browser is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with Privacy Browser.  If not, see <http://www.gnu.org/licenses/>. -->
+
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/spinner_item_textview"
+    android:layout_height="wrap_content"
+    android:layout_width="match_parent"
+    android:maxLines="1"
+    android:ellipsize="end"
+    android:paddingStart="10dp"
+    android:paddingEnd="10dp"
+    android:textSize="18sp"
+    android:textColor="?attr/bookmarksSpinnerHeaderTextColor" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/domain_settings_spinner_dropdown_item.xml b/app/src/main/res/layout/domain_settings_spinner_dropdown_item.xml
new file mode 100644 (file)
index 0000000..bef27af
--- /dev/null
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright © 2017 Soren Stoutner <soren@stoutner.com>.
+
+  This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
+
+  Privacy Browser is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  Privacy Browser is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with Privacy Browser.  If not, see <http://www.gnu.org/licenses/>. -->
+
+<CheckedTextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/spinner_dropdown_item_textview"
+    android:layout_height="wrap_content"
+    android:layout_width="match_parent"
+    android:maxLines="1"
+    android:ellipsize="end"
+    android:gravity="center_vertical"
+    android:paddingStart="16dp"
+    android:paddingEnd="16dp"
+    android:paddingTop="8dp"
+    android:paddingBottom="8dp"
+    android:textSize="18sp"
+    android:textColor="?attr/primaryTextColorSelector"
+    android:checkMark="?android:attr/listChoiceIndicatorSingle" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/domain_settings_spinner_item.xml b/app/src/main/res/layout/domain_settings_spinner_item.xml
new file mode 100644 (file)
index 0000000..d06d7cf
--- /dev/null
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+  Copyright © 2017 Soren Stoutner <soren@stoutner.com>.
+
+  This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
+
+  Privacy Browser is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  Privacy Browser is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with Privacy Browser.  If not, see <http://www.gnu.org/licenses/>. -->
+
+<TextView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/spinner_item_textview"
+    android:layout_height="wrap_content"
+    android:layout_width="match_parent"
+    android:maxLines="1"
+    android:ellipsize="end"
+    android:paddingStart="10dp"
+    android:paddingEnd="10dp"
+    android:textSize="18sp"
+    android:textColor="?attr/primaryTextColorSelector" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/spinner_dropdown_item.xml b/app/src/main/res/layout/spinner_dropdown_item.xml
deleted file mode 100644 (file)
index f62fa71..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
-  Copyright © 2017 Soren Stoutner <soren@stoutner.com>.
-
-  This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
-
-  Privacy Browser is free software: you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation, either version 3 of the License, or
-  (at your option) any later version.
-
-  Privacy Browser is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with Privacy Browser.  If not, see <http://www.gnu.org/licenses/>. -->
-
-<CheckedTextView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@android:id/text1"
-    android:layout_height="wrap_content"
-    android:layout_width="match_parent"
-    android:maxLines="1"
-    android:ellipsize="end"
-    android:gravity="center_vertical"
-    android:paddingStart="16dp"
-    android:paddingEnd="16dp"
-    android:paddingTop="8dp"
-    android:paddingBottom="8dp"
-    android:textSize="18sp"
-    android:textColor="?attr/primaryTextColorSelector"
-    android:checkMark="?android:attr/listChoiceIndicatorSingle" />
\ No newline at end of file
diff --git a/app/src/main/res/layout/spinner_item.xml b/app/src/main/res/layout/spinner_item.xml
deleted file mode 100644 (file)
index 7d35b43..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
-  Copyright © 2017 Soren Stoutner <soren@stoutner.com>.
-
-  This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
-
-  Privacy Browser is free software: you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published by
-  the Free Software Foundation, either version 3 of the License, or
-  (at your option) any later version.
-
-  Privacy Browser is distributed in the hope that it will be useful,
-  but WITHOUT ANY WARRANTY; without even the implied warranty of
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-  GNU General Public License for more details.
-
-  You should have received a copy of the GNU General Public License
-  along with Privacy Browser.  If not, see <http://www.gnu.org/licenses/>. -->
-
-<TextView
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@android:id/text1"
-    android:layout_height="wrap_content"
-    android:layout_width="match_parent"
-    android:maxLines="1"
-    android:ellipsize="end"
-    android:paddingStart="10dp"
-    android:paddingEnd="10dp"
-    android:textSize="18sp"
-    android:textColor="?attr/primaryTextColorSelector" />
\ No newline at end of file
index 55d6c2e..e23ac44 100644 (file)
@@ -32,6 +32,9 @@
     <attr name="sslHeader" format="reference" />
     <attr name="urlHistoryText" format="reference" />
     <attr name="primaryTextColorSelector" format="reference" />
+    <attr name="bookmarksSpinnerHeaderTextColor" format="reference" />
+    <attr name="bookmarksSpinnerTextColorSelector" format="reference" />
+    <attr name="bookmarksSpinnerBackground" format="reference" />
     <attr name="redText" format="reference" />
 
     <attr name="navigationHeaderBackground" format="reference" />
index 821407a..94c863b 100644 (file)
@@ -33,7 +33,9 @@
     <color name="blue_600">#FF1E88E5</color>
     <color name="blue_700">#FF1976D2</color>
     <color name="blue_700_50">#881976D2</color>
+    <color name="blue_750">#FF1770C6</color>
     <color name="blue_800">#FF1565C0</color>
+    <color name="blue_830">#FF1760B5</color>
     <color name="blue_900">#FF0D47A1</color>
     <color name="blue_1000">#FF082B61</color>
     <color name="blue_a700">#FF2962FF</color>
index 42310bb..256bddb 100644 (file)
 
     <!-- Bookmarks Database View. -->
     <string name="bookmarks_database_view">Bookmarks Database View</string>
+    <string name="all_folders">All Folders</string>
     <string name="home_folder">Home Folder</string>
 
     <!-- Domains. -->
index 1f18073..8b5027a 100644 (file)
@@ -46,6 +46,9 @@
         <item name="android:textColorHighlight">@color/blue_200</item>
         <item name="android:actionModeBackground">@color/blue_700</item>
         <item name="primaryTextColorSelector">@color/primary_text_color_selector_light</item>
+        <item name="bookmarksSpinnerHeaderTextColor">@color/white</item>
+        <item name="bookmarksSpinnerTextColorSelector">@color/bookmarks_spinner_color_selector_light</item>
+        <item name="bookmarksSpinnerBackground">@color/blue_750</item>
         <item name="listSelectorDrawable">@drawable/list_selector_light</item>
         <item name="aboutTitle">@color/blue_900</item>
         <item name="aboutText">@color/blue_700</item>
         <item name="colorPrimaryDark">@color/blue_800</item>
         <item name="android:actionModeBackground">@color/blue_800</item>
         <item name="primaryTextColorSelector">@color/primary_text_color_selector_dark</item>
+        <item name="bookmarksSpinnerHeaderTextColor">@color/gray_300</item>
+        <item name="bookmarksSpinnerTextColorSelector">@color/bookmarks_spinner_color_selector_dark</item>
+        <item name="bookmarksSpinnerBackground">@color/blue_830</item>
         <item name="aboutTitle">@color/blue_600</item>
         <item name="aboutText">@color/blue_400</item>
         <item name="aboutBackground">@color/gray_850</item>