diff --git a/AndroidManifest.xml b/AndroidManifest.xml index d2e3b002d..c37aeeb66 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -2,8 +2,8 @@ + + + + @@ -242,6 +246,7 @@ + @@ -375,6 +380,17 @@ + + + + + + + + + + + diff --git a/AndroidManifest.xml.pattern b/AndroidManifest.xml.pattern index 6342b9b8b..3c96ab470 100644 --- a/AndroidManifest.xml.pattern +++ b/AndroidManifest.xml.pattern @@ -229,6 +229,10 @@ + + + + @@ -242,6 +246,7 @@ + @@ -375,6 +380,17 @@ + + + + + + + + + + + diff --git a/ChangeLog b/ChangeLog index a6fa2b411..ab53ac125 100644 --- a/ChangeLog +++ b/ChangeLog @@ -8,6 +8,7 @@ * Customisable main menu * New (material design style) icon * Simple widgets +* More brightness levels ===== 2.5.5 (Aug 14, 2015) ===== * Compatibility with new versions of LEO dictionary diff --git a/VERSION b/VERSION index 0cadbc1e3..5a91dcbe0 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.5.5 +2.6 beta 4 diff --git a/res/drawable-hdpi/classic.png b/res/drawable-hdpi/classic.png new file mode 100644 index 000000000..8efa6284b Binary files /dev/null and b/res/drawable-hdpi/classic.png differ diff --git a/res/drawable-hdpi/fbreader.png b/res/drawable-hdpi/fbreader.png index 8efa6284b..0e6e7e2cd 100644 Binary files a/res/drawable-hdpi/fbreader.png and b/res/drawable-hdpi/fbreader.png differ diff --git a/res/drawable-hdpi/library_old.png b/res/drawable-hdpi/library_old.png new file mode 100644 index 000000000..3a62257e8 Binary files /dev/null and b/res/drawable-hdpi/library_old.png differ diff --git a/res/drawable-ldpi/fbreader.png b/res/drawable-ldpi/classic.png similarity index 100% rename from res/drawable-ldpi/fbreader.png rename to res/drawable-ldpi/classic.png diff --git a/res/drawable-mdpi/classic.png b/res/drawable-mdpi/classic.png new file mode 100644 index 000000000..e91f90be6 Binary files /dev/null and b/res/drawable-mdpi/classic.png differ diff --git a/res/drawable-mdpi/fbreader.png b/res/drawable-mdpi/fbreader.png index e91f90be6..8ab6ccdaf 100644 Binary files a/res/drawable-mdpi/fbreader.png and b/res/drawable-mdpi/fbreader.png differ diff --git a/res/drawable-mdpi/library_old.png b/res/drawable-mdpi/library_old.png new file mode 100644 index 000000000..c4df7b829 Binary files /dev/null and b/res/drawable-mdpi/library_old.png differ diff --git a/res/drawable-xhdpi/classic.png b/res/drawable-xhdpi/classic.png new file mode 100644 index 000000000..a157fcf5a Binary files /dev/null and b/res/drawable-xhdpi/classic.png differ diff --git a/res/drawable-xhdpi/fbreader.png b/res/drawable-xhdpi/fbreader.png index a157fcf5a..6618200f4 100644 Binary files a/res/drawable-xhdpi/fbreader.png and b/res/drawable-xhdpi/fbreader.png differ diff --git a/res/drawable-xxhdpi/classic.png b/res/drawable-xxhdpi/classic.png new file mode 100644 index 000000000..4c75d4a29 Binary files /dev/null and b/res/drawable-xxhdpi/classic.png differ diff --git a/res/drawable-xxhdpi/fbreader.png b/res/drawable-xxhdpi/fbreader.png index 4c75d4a29..f3f0a707e 100644 Binary files a/res/drawable-xxhdpi/fbreader.png and b/res/drawable-xxhdpi/fbreader.png differ diff --git a/res/drawable-xxhdpi/library_old.png b/res/drawable-xxhdpi/library_old.png new file mode 100644 index 000000000..b2ea90420 Binary files /dev/null and b/res/drawable-xxhdpi/library_old.png differ diff --git a/res/drawable-xxxhdpi/fbreader.png b/res/drawable-xxxhdpi/fbreader.png new file mode 100644 index 000000000..db1b4cc39 Binary files /dev/null and b/res/drawable-xxxhdpi/fbreader.png differ diff --git a/res/layout/icon_checkbox.xml b/res/layout/icon_checkbox.xml new file mode 100644 index 000000000..e23141838 --- /dev/null +++ b/res/layout/icon_checkbox.xml @@ -0,0 +1,32 @@ + + + + + + + diff --git a/res/layout/menu_configure_item.xml b/res/layout/menu_configure_item.xml new file mode 100644 index 000000000..2d6e50255 --- /dev/null +++ b/res/layout/menu_configure_item.xml @@ -0,0 +1,50 @@ + + + + + + + + + diff --git a/res/layout/menu_configure_section_head.xml b/res/layout/menu_configure_section_head.xml new file mode 100644 index 000000000..48880329a --- /dev/null +++ b/res/layout/menu_configure_section_head.xml @@ -0,0 +1,20 @@ + + + + diff --git a/res/layout/menu_configure_view.xml b/res/layout/menu_configure_view.xml new file mode 100644 index 000000000..f2f68b8cc --- /dev/null +++ b/res/layout/menu_configure_view.xml @@ -0,0 +1,19 @@ + + diff --git a/res/layout/widget_simple.xml b/res/layout/widget_simple.xml new file mode 100644 index 000000000..0a3724b41 --- /dev/null +++ b/res/layout/widget_simple.xml @@ -0,0 +1,10 @@ + + diff --git a/res/layout/widget_simple_config.xml b/res/layout/widget_simple_config.xml new file mode 100644 index 000000000..904b39005 --- /dev/null +++ b/res/layout/widget_simple_config.xml @@ -0,0 +1,55 @@ + + + + + + + + + + + + + diff --git a/res/values-v14/dimens.xml b/res/values-v14/dimens.xml new file mode 100644 index 000000000..3e3b0c729 --- /dev/null +++ b/res/values-v14/dimens.xml @@ -0,0 +1,4 @@ + + + 0dp + diff --git a/res/values/dimens.xml b/res/values/dimens.xml new file mode 100644 index 000000000..77ffb1a55 --- /dev/null +++ b/res/values/dimens.xml @@ -0,0 +1,4 @@ + + + 8dp + diff --git a/res/values/styles.xml b/res/values/styles.xml index 8cad2f459..a5f21bfa8 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -5,6 +5,9 @@ + diff --git a/res/xml/widget_simple.xml b/res/xml/widget_simple.xml new file mode 100644 index 000000000..034040d46 --- /dev/null +++ b/res/xml/widget_simple.xml @@ -0,0 +1,12 @@ + + diff --git a/src/org/geometerplus/android/fbreader/FBReader.java b/src/org/geometerplus/android/fbreader/FBReader.java index 61086cf01..0058d1f59 100644 --- a/src/org/geometerplus/android/fbreader/FBReader.java +++ b/src/org/geometerplus/android/fbreader/FBReader.java @@ -235,6 +235,7 @@ public final class FBReader extends FBReaderMainActivity implements ZLApplicatio config.requestAllValuesForGroup("Fonts"); config.requestAllValuesForGroup("Colors"); config.requestAllValuesForGroup("Files"); + config.requestAllValuesForGroup("MainMenu"); } }); @@ -539,7 +540,7 @@ public final class FBReader extends FBReaderMainActivity implements ZLApplicatio final int brightnessLevel = getZLibrary().ScreenBrightnessLevelOption.getValue(); if (brightnessLevel != 0) { - setScreenBrightness(brightnessLevel); + getViewWidget().setScreenBrightness(brightnessLevel); } else { setScreenBrightnessAuto(); } @@ -976,29 +977,6 @@ public final class FBReader extends FBReaderMainActivity implements ZLApplicatio } }; - private void setScreenBrightnessAuto() { - final WindowManager.LayoutParams attrs = getWindow().getAttributes(); - attrs.screenBrightness = -1.0f; - getWindow().setAttributes(attrs); - } - - public void setScreenBrightness(int percent) { - if (percent < 1) { - percent = 1; - } else if (percent > 100) { - percent = 100; - } - final WindowManager.LayoutParams attrs = getWindow().getAttributes(); - attrs.screenBrightness = percent / 100.0f; - getWindow().setAttributes(attrs); - getZLibrary().ScreenBrightnessLevelOption.setValue(percent); - } - - public int getScreenBrightness() { - final int level = (int)(100 * getWindow().getAttributes().screenBrightness); - return (level >= 0) ? level : 50; - } - private BookCollectionShadow getCollection() { return (BookCollectionShadow)myFBReaderApp.Collection; } diff --git a/src/org/geometerplus/android/fbreader/FBReaderMainActivity.java b/src/org/geometerplus/android/fbreader/FBReaderMainActivity.java index 6e668f620..0f3a8bb69 100644 --- a/src/org/geometerplus/android/fbreader/FBReaderMainActivity.java +++ b/src/org/geometerplus/android/fbreader/FBReaderMainActivity.java @@ -22,6 +22,7 @@ package org.geometerplus.android.fbreader; import android.app.Activity; import android.content.Intent; import android.os.Bundle; +import android.view.WindowManager; import com.github.johnpersano.supertoasts.SuperActivityToast; @@ -61,6 +62,31 @@ public abstract class FBReaderMainActivity extends Activity { return FBReaderUtil.getZLibrary(this); } + /* ++++++ SCREEN BRIGHTNESS ++++++ */ + protected void setScreenBrightnessAuto() { + final WindowManager.LayoutParams attrs = getWindow().getAttributes(); + attrs.screenBrightness = -1.0f; + getWindow().setAttributes(attrs); + } + + public void setScreenBrightnessSystem(int percent) { + if (percent < 2) { + percent = 2; + } else if (percent > 100) { + percent = 100; + } + final WindowManager.LayoutParams attrs = getWindow().getAttributes(); + attrs.screenBrightness = percent / 100.0f; + getWindow().setAttributes(attrs); + getZLibrary().ScreenBrightnessLevelOption.setValue(percent); + } + + public int getScreenBrightnessSystem() { + final int level = (int)(100 * getWindow().getAttributes().screenBrightness); + return level >= 0 ? level : 50; + } + /* ------ SCREEN BRIGHTNESS ------ */ + /* ++++++ SUPER TOAST ++++++ */ public boolean isToastShown() { final SuperActivityToast toast = myToast; diff --git a/src/org/geometerplus/android/fbreader/MenuData.java b/src/org/geometerplus/android/fbreader/MenuData.java index 675f7948d..35eaf6933 100644 --- a/src/org/geometerplus/android/fbreader/MenuData.java +++ b/src/org/geometerplus/android/fbreader/MenuData.java @@ -22,6 +22,7 @@ package org.geometerplus.android.fbreader; import java.util.*; import org.geometerplus.zlibrary.core.library.ZLibrary; +import org.geometerplus.zlibrary.core.options.ZLIntegerOption; import org.geometerplus.zlibrary.ui.android.R; import org.geometerplus.fbreader.fbreader.ActionCode; @@ -31,12 +32,31 @@ import org.geometerplus.android.util.DeviceType; public abstract class MenuData { private static List ourNodes; + private static final Map ourNodeOptions = + new HashMap(); + private static final Map ourDefaultValues = new HashMap(); + private static final Map ourConfigCodes = new HashMap(); + private static final Set ourAlwaysEnabledCodes = new HashSet(); + + private static final String CONFIG_CODE_DAY_NIGHT = "dayNight"; + private static final String CONFIG_CODE_CHANGE_FONT_SIZE = "changeFontSize"; private static void addToplevelNode(MenuNode node) { - ourNodes.add(node); + addToplevelNode(node, node.Code, false); } - public static synchronized List topLevelNodes() { + private static void addToplevelNode(MenuNode node, String configCode, boolean alwaysEnabled) { + ourConfigCodes.put(node.Code, configCode); + if (!ourDefaultValues.containsKey(configCode)) { + ourDefaultValues.put(configCode, ourDefaultValues.size()); + } + ourNodes.add(node); + if (alwaysEnabled) { + ourAlwaysEnabledCodes.add(configCode); + } + } + + private static synchronized List allTopLevelNodes() { if (ourNodes == null) { ourNodes = new ArrayList(); addToplevelNode(new MenuNode.Item(ActionCode.SHOW_LIBRARY, R.drawable.ic_menu_library)); @@ -47,11 +67,23 @@ public abstract class MenuData { addToplevelNode(new MenuNode.Item(ActionCode.SHOW_NETWORK_LIBRARY, R.drawable.ic_menu_networklibrary)); addToplevelNode(new MenuNode.Item(ActionCode.SHOW_TOC, R.drawable.ic_menu_toc)); addToplevelNode(new MenuNode.Item(ActionCode.SHOW_BOOKMARKS, R.drawable.ic_menu_bookmarks)); - addToplevelNode(new MenuNode.Item(ActionCode.SWITCH_TO_NIGHT_PROFILE, R.drawable.ic_menu_night)); - addToplevelNode(new MenuNode.Item(ActionCode.SWITCH_TO_DAY_PROFILE, R.drawable.ic_menu_day)); + addToplevelNode( + new MenuNode.Item(ActionCode.SWITCH_TO_NIGHT_PROFILE, R.drawable.ic_menu_night), + CONFIG_CODE_DAY_NIGHT, + false + ); + addToplevelNode( + new MenuNode.Item(ActionCode.SWITCH_TO_DAY_PROFILE, R.drawable.ic_menu_day), + CONFIG_CODE_DAY_NIGHT, + false + ); addToplevelNode(new MenuNode.Item(ActionCode.SEARCH, R.drawable.ic_menu_search)); addToplevelNode(new MenuNode.Item(ActionCode.SHARE_BOOK)); - addToplevelNode(new MenuNode.Item(ActionCode.SHOW_PREFERENCES)); + addToplevelNode( + new MenuNode.Item(ActionCode.SHOW_PREFERENCES), + ActionCode.SHOW_PREFERENCES, + true + ); addToplevelNode(new MenuNode.Item(ActionCode.SHOW_BOOK_INFO)); final MenuNode.Submenu orientations = new MenuNode.Submenu("screenOrientation"); orientations.Children.add(new MenuNode.Item(ActionCode.SET_SCREEN_ORIENTATION_SYSTEM)); @@ -63,8 +95,16 @@ public abstract class MenuData { orientations.Children.add(new MenuNode.Item(ActionCode.SET_SCREEN_ORIENTATION_REVERSE_LANDSCAPE)); } addToplevelNode(orientations); - addToplevelNode(new MenuNode.Item(ActionCode.INCREASE_FONT)); - addToplevelNode(new MenuNode.Item(ActionCode.DECREASE_FONT)); + addToplevelNode( + new MenuNode.Item(ActionCode.INCREASE_FONT), + CONFIG_CODE_CHANGE_FONT_SIZE, + false + ); + addToplevelNode( + new MenuNode.Item(ActionCode.DECREASE_FONT), + CONFIG_CODE_CHANGE_FONT_SIZE, + false + ); addToplevelNode(new MenuNode.Item(ActionCode.INSTALL_PLUGINS)); addToplevelNode(new MenuNode.Item(ActionCode.OPEN_WEB_HELP)); addToplevelNode(new MenuNode.Item(ActionCode.OPEN_START_SCREEN)); @@ -72,4 +112,88 @@ public abstract class MenuData { } return ourNodes; } + + private static String code(MenuNode node) { + return ourConfigCodes.get(node.Code); + } + + private static class MenuComparator implements Comparator { + @Override + public int compare(MenuNode lhs, MenuNode rhs) { + return nodeOption(code(lhs)).getValue() - nodeOption(code(rhs)).getValue(); + } + } + + private static class CodeComparator implements Comparator { + @Override + public int compare(String lhs, String rhs) { + return nodeOption(lhs).getValue() - nodeOption(rhs).getValue(); + } + } + + public static ArrayList enabledCodes() { + final ArrayList codes = new ArrayList(); + for (MenuNode node : allTopLevelNodes()) { + final String c = code(node); + if (!codes.contains(c) && isCodeEnabled(c)) { + codes.add(c); + } + } + Collections.sort(codes, new CodeComparator()); + return codes; + } + + public static ArrayList disabledCodes() { + final ArrayList codes = new ArrayList(); + for (MenuNode node : allTopLevelNodes()) { + final String c = code(node); + if (!codes.contains(c) && !isCodeEnabled(c)) { + codes.add(c); + } + } + return codes; + } + + public static int configIconId(String itemCode) { + final List allNodes = allTopLevelNodes(); + Integer iconId = null; + for (MenuNode node : allNodes) { + if (node instanceof MenuNode.Item && itemCode.equals(code(node))) { + iconId = ((MenuNode.Item)node).IconId; + break; + } + } + return iconId != null ? iconId : R.drawable.ic_menu_none; + } + + public static synchronized List topLevelNodes() { + final List allNodes = new ArrayList(allTopLevelNodes()); + final List activeNodes = new ArrayList(allNodes.size()); + for (MenuNode node : allNodes) { + if (isCodeEnabled(code(node))) { + activeNodes.add(node); + } + } + Collections.sort(activeNodes, new MenuComparator()); + return activeNodes; + } + + public static ZLIntegerOption nodeOption(String code) { + synchronized (ourNodeOptions) { + ZLIntegerOption option = ourNodeOptions.get(code); + if (option == null) { + option = new ZLIntegerOption("MainMenu", code, ourDefaultValues.get(code)); + ourNodeOptions.put(code, option); + } + return option; + } + } + + public static boolean isCodeAlwaysEnabled(String code) { + return ourAlwaysEnabledCodes.contains(code); + } + + private static boolean isCodeEnabled(String code) { + return ourAlwaysEnabledCodes.contains(code) || nodeOption(code).getValue() >= 0; + } } diff --git a/src/org/geometerplus/android/fbreader/library/LibraryActivity.java b/src/org/geometerplus/android/fbreader/library/LibraryActivity.java index 776ae2121..e687419e4 100644 --- a/src/org/geometerplus/android/fbreader/library/LibraryActivity.java +++ b/src/org/geometerplus/android/fbreader/library/LibraryActivity.java @@ -58,7 +58,12 @@ public class LibraryActivity extends TreeActivity implements MenuIt protected void onCreate(Bundle icicle) { super.onCreate(icicle); - mySelectedBook = FBReaderIntents.getBookExtra(getIntent(), myCollection); + final Intent intent = getIntent(); + if (intent != null && "android.fbreader.action.EXTERNAL_INTERNAL_LIBRARY".equals(intent.getAction())) { + runOrInstallExternalView(false); + } + + mySelectedBook = FBReaderIntents.getBookExtra(intent, myCollection); new LibraryTreeAdapter(this); @@ -72,7 +77,7 @@ public class LibraryActivity extends TreeActivity implements MenuIt showProgress(!myCollection.status().IsComplete); myRootTree = new RootTree(myCollection, PluginCollection.Instance(Paths.systemInfo(LibraryActivity.this))); myCollection.addListener(LibraryActivity.this); - init(getIntent()); + init(intent); } }); } @@ -119,7 +124,7 @@ public class LibraryActivity extends TreeActivity implements MenuIt protected void onListItemClick(ListView listView, View view, int position, long rowId) { final LibraryTree tree = (LibraryTree)getListAdapter().getItem(position); if (tree instanceof ExternalViewTree) { - runOrInstallExternalView(); + runOrInstallExternalView(true); } else { final Book book = tree.getBook(); if (book != null) { @@ -374,19 +379,21 @@ public class LibraryActivity extends TreeActivity implements MenuIt return true; } case OptionsItemId.ExternalView: - runOrInstallExternalView(); + runOrInstallExternalView(true); return true; default: return true; } } - private void runOrInstallExternalView() { + private void runOrInstallExternalView(boolean install) { try { startActivity(new Intent(FBReaderIntents.Action.EXTERNAL_LIBRARY)); finish(); } catch (ActivityNotFoundException e) { - PackageUtil.installFromMarket(this, "org.fbreader.plugin.library"); + if (install) { + PackageUtil.installFromMarket(this, "org.fbreader.plugin.library"); + } } } diff --git a/src/org/geometerplus/android/fbreader/preferences/PreferenceActivity.java b/src/org/geometerplus/android/fbreader/preferences/PreferenceActivity.java index 8ae79a9e0..b5ab98550 100644 --- a/src/org/geometerplus/android/fbreader/preferences/PreferenceActivity.java +++ b/src/org/geometerplus/android/fbreader/preferences/PreferenceActivity.java @@ -48,21 +48,26 @@ import org.geometerplus.fbreader.network.sync.SyncUtil; import org.geometerplus.fbreader.tips.TipsManager; import org.geometerplus.android.fbreader.FBReader; +import org.geometerplus.android.fbreader.MenuData; import org.geometerplus.android.fbreader.dict.DictionaryUtil; import org.geometerplus.android.fbreader.libraryService.BookCollectionShadow; import org.geometerplus.android.fbreader.network.auth.ActivityNetworkContext; -import org.geometerplus.android.fbreader.preferences.fileChooser.FileChooserCollection; import org.geometerplus.android.fbreader.preferences.background.BackgroundPreference; +import org.geometerplus.android.fbreader.preferences.fileChooser.FileChooserCollection; +import org.geometerplus.android.fbreader.preferences.menu.MenuPreference; import org.geometerplus.android.fbreader.sync.SyncOperations; import org.geometerplus.android.util.UIUtil; import org.geometerplus.android.util.DeviceType; public class PreferenceActivity extends ZLPreferenceActivity { + private static final int BACKGROUND_REQUEST_CODE = 3000; + private static final int MENU_REQUEST_CODE = 3001; + private final ActivityNetworkContext myNetworkContext = new ActivityNetworkContext(this); private final FileChooserCollection myChooserCollection = new FileChooserCollection(this, 2000); - private static final int BACKGROUND_REQUEST_CODE = 3000; private BackgroundPreference myBackgroundPreference; + private MenuPreference myMenuPreference; public PreferenceActivity() { super("Preferences"); @@ -91,6 +96,13 @@ public class PreferenceActivity extends ZLPreferenceActivity { return; } + if (MENU_REQUEST_CODE == requestCode) { + if (myMenuPreference != null) { + myMenuPreference.update(data); + } + return; + } + myChooserCollection.update(requestCode, data); } @@ -105,6 +117,7 @@ public class PreferenceActivity extends ZLPreferenceActivity { config.requestAllValuesForGroup("Scrolling"); config.requestAllValuesForGroup("Colors"); config.requestAllValuesForGroup("Sync"); + config.requestAllValuesForGroup("MainMenu"); setResult(FBReader.RESULT_REPAINT); final ViewOptions viewOptions = new ViewOptions(); @@ -717,6 +730,13 @@ public class PreferenceActivity extends ZLPreferenceActivity { imagesScreen.addOption(imageOptions.ImageViewBackground, "backgroundColor"); imagesScreen.addOption(imageOptions.MatchBackground, "matchBackground"); + myMenuPreference = new MenuPreference( + this, + Resource.getResource("menu"), + MENU_REQUEST_CODE + ); + addPreference(myMenuPreference); + final CancelMenuHelper cancelMenuHelper = new CancelMenuHelper(); final Screen cancelMenuScreen = createPreferenceScreen("cancelMenu"); cancelMenuScreen.addOption(cancelMenuHelper.ShowLibraryItemOption, "library"); diff --git a/src/org/geometerplus/android/fbreader/preferences/menu/ConfigurationActivity.java b/src/org/geometerplus/android/fbreader/preferences/menu/ConfigurationActivity.java new file mode 100644 index 000000000..7437b5ca6 --- /dev/null +++ b/src/org/geometerplus/android/fbreader/preferences/menu/ConfigurationActivity.java @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2009-2015 FBReader.ORG Limited + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +package org.geometerplus.android.fbreader.preferences.menu; + +import java.util.ArrayList; +import java.util.List; + +import android.app.ListActivity; +import android.content.Intent; +import android.os.Bundle; +import android.view.*; +import android.widget.*; + +import com.mobeta.android.dslv.DragSortListView; + +import org.geometerplus.zlibrary.core.resources.ZLResource; +import org.geometerplus.zlibrary.ui.android.R; +import org.geometerplus.android.fbreader.MenuData; +import org.geometerplus.android.util.ViewUtil; + +public class ConfigurationActivity extends ListActivity { + static final String ENABLED_MENU_IDS_KEY = "enabledMenuIds"; + static final String DISABLED_MENU_IDS_KEY = "disabledMenuIds"; + + private final List myAllItems = new ArrayList(); + + @Override + protected void onCreate(Bundle icicle) { + super.onCreate(icicle); + setContentView(R.layout.menu_configure_view); + } + + @Override + protected void onStart() { + super.onStart(); + + myAllItems.clear(); + + final Intent intent = getIntent(); + + myAllItems.add(new SectionItem("enabled")); + final List enabledIds = + intent.getStringArrayListExtra(ENABLED_MENU_IDS_KEY); + if (enabledIds.size() > 0) { + for (String id : enabledIds) { + myAllItems.add(new MenuNodeItem(id, true)); + } + } + + myAllItems.add(new SectionItem("disabled")); + final List disabledIds = + intent.getStringArrayListExtra(DISABLED_MENU_IDS_KEY); + if (disabledIds.size() > 0) { + for (String id : disabledIds) { + myAllItems.add(new MenuNodeItem(id, false)); + } + } + + setListAdapter(new MenuListAdapter()); + } + + @Override + public DragSortListView getListView() { + return (DragSortListView)super.getListView(); + } + + private static interface Item { + } + + private static class SectionItem implements Item { + private final String Title; + + public SectionItem(String key) { + Title = ZLResource.resource("Preferences").getResource("menu").getResource(key).getValue(); + } + } + + private static class MenuNodeItem implements Item { + private final String Id; + private boolean IsChecked; + private final boolean IsEnabled; + + public MenuNodeItem(String id, boolean checked) { + Id = id; + IsChecked = checked; + IsEnabled = !MenuData.isCodeAlwaysEnabled(id); + } + + public String getTitle() { + return ZLResource.resource("menu").getResource(Id).getValue(); + } + } + + private class MenuListAdapter extends ArrayAdapter implements DragSortListView.DropListener, DragSortListView.RemoveListener { + public MenuListAdapter() { + super(ConfigurationActivity.this, R.layout.menu_configure_item, myAllItems); + } + + private int indexOfDisabledSectionItem() { + for (int i = 1; i < getCount(); i++) { + if (getItem(i) instanceof SectionItem) { + return i; + } + } + // should be impossible + return 0; + } + + private void setResultIds() { + final ArrayList eIds = new ArrayList(); + final ArrayList dIds = new ArrayList(); + for (int i = 1; i < getCount(); ++i) { + final Item item = getItem(i); + if (item instanceof SectionItem) { + continue; + } + final MenuNodeItem menuItem = (MenuNodeItem)item; + if (menuItem.IsChecked) { + eIds.add(menuItem.Id); + } else { + dIds.add(menuItem.Id); + } + } + setResult(RESULT_OK, new Intent() + .putStringArrayListExtra(ENABLED_MENU_IDS_KEY, eIds) + .putStringArrayListExtra(DISABLED_MENU_IDS_KEY, dIds)); + } + + @Override + public View getView(int position, View convertView, final ViewGroup parent) { + final Item item = getItem(position); + + final View view; + if (convertView != null && item.getClass().equals(convertView.getTag())) { + view = convertView; + } else { + view = getLayoutInflater().inflate( + item instanceof SectionItem + ? R.layout.menu_configure_section_head : R.layout.menu_configure_item, + null + ); + view.setTag(item.getClass()); + } + + if (item instanceof SectionItem) { + ViewUtil.setSubviewText( + view, R.id.menu_configure_section_head_title, ((SectionItem)item).Title + ); + } else /* if (item instanceof MenuNodeItem) */ { + final MenuNodeItem menuItem = (MenuNodeItem)item; + + final TextView titleView = + ViewUtil.findTextView(view, R.id.menu_configure_item_title); + titleView.setText(menuItem.getTitle()); + + final ImageView iconView = + ViewUtil.findImageView(view, R.id.menu_configure_item_icon); + iconView.setImageResource(MenuData.configIconId(menuItem.Id)); + + final CheckBox checkBox = + (CheckBox)ViewUtil.findView(view, R.id.menu_configure_item_checkbox); + checkBox.setChecked(menuItem.IsChecked); + checkBox.setEnabled(menuItem.IsEnabled); + + if (menuItem.IsEnabled) { + final View.OnClickListener updateCheckbox = new View.OnClickListener() { + public void onClick(View v) { + if (v != checkBox) { + checkBox.performClick(); + } + menuItem.IsChecked = checkBox.isChecked(); + setResultIds(); + } + }; + checkBox.setOnClickListener(updateCheckbox); + iconView.setOnClickListener(updateCheckbox); + titleView.setOnClickListener(updateCheckbox); + } + } + return view; + } + + // method from DragSortListView.DropListener + public void drop(int from, int to) { + to = Math.max(to, 1); + if (from == to) { + return; + } + final Item item = getItem(from); + if (item instanceof MenuNodeItem) { + remove(item); + insert(item, to); + if (((MenuNodeItem)item).IsEnabled) { + ((MenuNodeItem)item).IsChecked = to < indexOfDisabledSectionItem(); + } + getListView().moveCheckState(from, to); + setResultIds(); + } + } + + // method from DragSortListView.RemoveListener + public void remove(int which) { + final Item item = getItem(which); + if (item instanceof MenuNodeItem) { + remove(item); + getListView().removeCheckState(which); + } + } + } +} diff --git a/src/org/geometerplus/android/fbreader/preferences/menu/MenuPreference.java b/src/org/geometerplus/android/fbreader/preferences/menu/MenuPreference.java new file mode 100644 index 000000000..90d2bec22 --- /dev/null +++ b/src/org/geometerplus/android/fbreader/preferences/menu/MenuPreference.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2010-2015 FBReader.ORG Limited + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +package org.geometerplus.android.fbreader.preferences.menu; + +import java.util.*; + +import android.app.Activity; +import android.content.Intent; +import android.preference.Preference; + +import org.geometerplus.android.fbreader.MenuData; +import org.geometerplus.zlibrary.core.resources.ZLResource; + +public class MenuPreference extends Preference { + private final int myRequestCode; + + public MenuPreference(Activity activity, ZLResource resource, int requestCode) { + super(activity); + + setTitle(resource.getValue()); + setSummary(resource.getResource("summary").getValue()); + + myRequestCode = requestCode; + } + + @Override + protected void onClick() { + ((Activity)getContext()).startActivityForResult( + new Intent(getContext(), ConfigurationActivity.class) + .putStringArrayListExtra(ConfigurationActivity.ENABLED_MENU_IDS_KEY, MenuData.enabledCodes()) + .putStringArrayListExtra(ConfigurationActivity.DISABLED_MENU_IDS_KEY, MenuData.disabledCodes()), + myRequestCode + ); + } + + public void update(Intent data) { + int i = 0; + for (String s : data.getStringArrayListExtra(ConfigurationActivity.ENABLED_MENU_IDS_KEY)) { + MenuData.nodeOption(s).setValue(i); + ++i; + } + for (String s : data.getStringArrayListExtra(ConfigurationActivity.DISABLED_MENU_IDS_KEY)) { + MenuData.nodeOption(s).setValue(-1); + } + } +} diff --git a/src/org/geometerplus/android/fbreader/widget/simple/ConfigurationActivity.java b/src/org/geometerplus/android/fbreader/widget/simple/ConfigurationActivity.java new file mode 100644 index 000000000..34d8e18fa --- /dev/null +++ b/src/org/geometerplus/android/fbreader/widget/simple/ConfigurationActivity.java @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2009-2015 FBReader.ORG Limited + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +package org.geometerplus.android.fbreader.widget.simple; + +import java.util.*; + +import android.app.Activity; +import android.appwidget.AppWidgetManager; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; +import android.view.View; +import android.widget.*; + +import org.geometerplus.zlibrary.core.resources.ZLResource; +import org.geometerplus.zlibrary.ui.android.R; + +public class ConfigurationActivity extends Activity { + private int myWidgetId; + private SharedPreferences myPrefs; + + private Button myOkButton; + private View[] myIconContainers; + private Spinner myActionsCombo; + + private final View.OnClickListener myIconCheckboxListener = new View.OnClickListener() { + @Override + public void onClick(View view) { + if (findCheckbox(view).isChecked()) { + return; + } + final int icon = (Integer)view.getTag(); + myPrefs.edit().putInt(Provider.Key.ICON, icon).apply(); + for (View c : myIconContainers) { + findCheckbox(c).setChecked(c == view); + } + myActionsCombo.setSelection(Provider.Action.ALL.indexOf(Provider.defaultAction(icon))); + updateOkButton(); + } + + private CheckBox findCheckbox(View v) { + return (CheckBox)v.findViewById(R.id.icon_checkbox_checkbox); + } + }; + + @Override + protected void onCreate(Bundle savedState) { + super.onCreate(savedState); + setContentView(R.layout.widget_simple_config); + + final ZLResource widgetResource = ZLResource.resource("widget").getResource("simple"); + + myWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID; + final Bundle extras = getIntent().getExtras(); + if (extras != null) { + myWidgetId = extras.getInt( + AppWidgetManager.EXTRA_APPWIDGET_ID, + AppWidgetManager.INVALID_APPWIDGET_ID + ); + } + if (myWidgetId == AppWidgetManager.INVALID_APPWIDGET_ID) { + finish(); + return; + } + myPrefs = Provider.getSharedPreferences(this, myWidgetId); + myPrefs.edit().clear().apply(); + + setResult(RESULT_CANCELED); + + final View buttons = findViewById(R.id.widget_simple_config_buttons); + final ZLResource buttonResource = ZLResource.resource("dialog").getResource("button"); + + myOkButton = (Button)buttons.findViewById(R.id.ok_button); + myOkButton.setText(buttonResource.getResource("ok").getValue()); + myOkButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + Provider.setupViews( + AppWidgetManager.getInstance(ConfigurationActivity.this), + ConfigurationActivity.this, + myWidgetId + ); + setResult( + RESULT_OK, + new Intent().putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, myWidgetId) + ); + finish(); + } + }); + myOkButton.setEnabled(false); + + final Button cancelButton = (Button)buttons.findViewById(R.id.cancel_button); + cancelButton.setText(buttonResource.getResource("cancel").getValue()); + cancelButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View view) { + myPrefs.edit().clear().apply(); + finish(); + } + }); + + final TextView iconLabel = (TextView)findViewById(R.id.widget_simple_config_icon_label); + iconLabel.setText(widgetResource.getResource("selectIcon").getValue()); + myIconContainers = new View[] { + iconContainer(R.id.widget_simple_config_fbreader, Provider.Icon.FBREADER), + iconContainer(R.id.widget_simple_config_classic, Provider.Icon.CLASSIC), + iconContainer(R.id.widget_simple_config_library, Provider.Icon.LIBRARY), + iconContainer(R.id.widget_simple_config_library_old, Provider.Icon.LIBRARY_OLD) + }; + + final List actionCodes = Provider.Action.ALL; + final List actionNames = new ArrayList(actionCodes.size()); + for (String code : actionCodes) { + actionNames.add(widgetResource.getResource(code).getValue()); + } + final TextView actionLabel = (TextView)findViewById(R.id.widget_simple_config_action_label); + actionLabel.setText(widgetResource.getResource("selectAction").getValue()); + myActionsCombo = (Spinner)findViewById(R.id.widget_simple_config_actions); + myActionsCombo.setAdapter(new ArrayAdapter( + this, android.R.layout.select_dialog_item, actionNames + )); + myActionsCombo.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() { + public void onItemSelected(AdapterView parent, View view, int position, long id) { + myPrefs.edit().putString( + Provider.Key.ACTION, actionCodes.get(position) + ).apply(); + } + public void onNothingSelected(AdapterView parent) { + } + }); + } + + private void updateOkButton() { + final Set keys = myPrefs.getAll().keySet(); + myOkButton.setEnabled( + keys.contains(Provider.Key.ICON) && + keys.contains(Provider.Key.ACTION) + ); + } + + private View iconContainer(final int viewId, final int icon) { + final View container = findViewById(viewId); + container.setTag(icon); + ((ImageView)container.findViewById(R.id.icon_checkbox_icon)) + .setImageResource(Provider.iconId(icon)); + container.setOnClickListener(myIconCheckboxListener); + return container; + } +} diff --git a/src/org/geometerplus/android/fbreader/widget/simple/Provider.java b/src/org/geometerplus/android/fbreader/widget/simple/Provider.java new file mode 100644 index 000000000..36a4cf022 --- /dev/null +++ b/src/org/geometerplus/android/fbreader/widget/simple/Provider.java @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2009-2015 FBReader.ORG Limited + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +package org.geometerplus.android.fbreader.widget.simple; + +import java.util.Arrays; +import java.util.List; + +import android.app.PendingIntent; +import android.appwidget.AppWidgetManager; +import android.appwidget.AppWidgetProvider; +import android.content.*; +import android.widget.RemoteViews; + +import org.geometerplus.zlibrary.ui.android.R; +import org.geometerplus.android.fbreader.FBReader; +import org.geometerplus.android.fbreader.library.LibraryActivity; + +public class Provider extends AppWidgetProvider { + @Override + public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { + for (int id : appWidgetIds) { + setupViews(appWidgetManager, context, id); + } + } + + // ++++ these constants are used for storing widget state persistently ++++ + // ++++ never change them, just add new values ++++ + interface Key { + String ICON = "icon"; + String ACTION = "action"; + } + + interface Icon { + int FBREADER = 0; + int CLASSIC = 1; + int LIBRARY = 2; + int LIBRARY_OLD = 3; + } + + interface Action { + String BOOK = "book"; + String LIBRARY = "library"; + + List ALL = Arrays.asList(BOOK, LIBRARY); + } + // ---- these constants are used for storing widget state persistently ---- + + static int iconId(int icon) { + switch (icon) { + default: + case Icon.FBREADER: + return R.drawable.fbreader; + case Icon.CLASSIC: + return R.drawable.classic; + case Icon.LIBRARY: + return R.drawable.library_old; + case Icon.LIBRARY_OLD: + return R.drawable.library_old; + } + } + + static String defaultAction(int icon) { + switch (icon) { + default: + case Icon.FBREADER: + case Icon.CLASSIC: + return Action.BOOK; + case Icon.LIBRARY: + case Icon.LIBRARY_OLD: + return Action.LIBRARY; + } + } + + static void setupViews(AppWidgetManager appWidgetManager, Context context, int widgetId) { + final SharedPreferences prefs = getSharedPreferences(context, widgetId); + final RemoteViews views = + new RemoteViews(context.getPackageName(), R.layout.widget_simple); + + views.setImageViewResource( + R.id.widget_simple, iconId(prefs.getInt(Key.ICON, Icon.FBREADER)) + ); + + final String action = prefs.getString(Key.ACTION, Action.BOOK); + final Intent intent; + if (Action.LIBRARY.equals(action)) { + intent = new Intent(context, LibraryActivity.class); + intent.setAction("android.fbreader.action.EXTERNAL_INTERNAL_LIBRARY"); + } else /* if Action.BOOK.equals(action) */ { + intent = FBReader.defaultIntent(context); + } + intent.addCategory(Intent.CATEGORY_LAUNCHER); + final PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0); + views.setOnClickPendingIntent(R.id.widget_simple, pendingIntent); + + appWidgetManager.updateAppWidget(widgetId, views); + } + + static SharedPreferences getSharedPreferences(Context context, int widgetId) { + return context.getApplicationContext().getSharedPreferences( + "SimpleWidget" + widgetId, Context.MODE_PRIVATE + ); + } +} diff --git a/src/org/geometerplus/zlibrary/text/view/ZLTextParagraphCursor.java b/src/org/geometerplus/zlibrary/text/view/ZLTextParagraphCursor.java index 74dd777ff..6715533dd 100644 --- a/src/org/geometerplus/zlibrary/text/view/ZLTextParagraphCursor.java +++ b/src/org/geometerplus/zlibrary/text/view/ZLTextParagraphCursor.java @@ -158,6 +158,7 @@ public final class ZLTextParagraphCursor { if (index > 0 && spaceState == NO_SPACE) { addWord(data, offset + wordStart, index - wordStart, myOffset + wordStart, hyperlink); } + elements.add(nbSpace); if (spaceState != SPACE) { spaceState = NON_BREAKABLE_SPACE; } @@ -170,7 +171,6 @@ public final class ZLTextParagraphCursor { wordStart = index; break; case NON_BREAKABLE_SPACE: - elements.add(nbSpace); wordStart = index; break; case NO_SPACE: diff --git a/src/org/geometerplus/zlibrary/text/view/ZLTextViewBase.java b/src/org/geometerplus/zlibrary/text/view/ZLTextViewBase.java index e178cacfb..e1243c4f4 100644 --- a/src/org/geometerplus/zlibrary/text/view/ZLTextViewBase.java +++ b/src/org/geometerplus/zlibrary/text/view/ZLTextViewBase.java @@ -227,7 +227,8 @@ abstract class ZLTextViewBase extends ZLView { } final int getElementHeight(ZLTextElement element) { - if (element instanceof ZLTextWord || + if (element == ZLTextElement.NBSpace || + element instanceof ZLTextWord || element instanceof ZLTextFixedHSpaceElement) { return getWordHeight(); } else if (element instanceof ZLTextImageElement) { diff --git a/src/org/geometerplus/zlibrary/ui/android/view/MainView.java b/src/org/geometerplus/zlibrary/ui/android/view/MainView.java new file mode 100644 index 000000000..c1720cbf2 --- /dev/null +++ b/src/org/geometerplus/zlibrary/ui/android/view/MainView.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2007-2015 FBReader.ORG Limited + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +package org.geometerplus.zlibrary.ui.android.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; + +import org.geometerplus.android.fbreader.FBReaderMainActivity; + +public abstract class MainView extends View { + protected Integer myColorLevel; + + public MainView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + public MainView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public MainView(Context context) { + super(context); + } + + public final void setScreenBrightness(int percent) { + final Context context = getContext(); + if (!(context instanceof FBReaderMainActivity)) { + return; + } + ((FBReaderMainActivity)context).setScreenBrightnessSystem(percent); + if (percent >= 50) { + myColorLevel = null; + } else { + myColorLevel = 0x60 + (0xFF - 0x60) * Math.max(percent, 0) / 50; + } + updateColorLevel(); + postInvalidate(); + } + + public final int getScreenBrightness() { + final Context context = getContext(); + if (!(context instanceof FBReaderMainActivity)) { + return 50; + } + return ((FBReaderMainActivity)context).getScreenBrightnessSystem(); + } + + protected abstract void updateColorLevel(); +} diff --git a/src/org/geometerplus/zlibrary/ui/android/view/ViewUtil.java b/src/org/geometerplus/zlibrary/ui/android/view/ViewUtil.java new file mode 100644 index 000000000..c33ba0d95 --- /dev/null +++ b/src/org/geometerplus/zlibrary/ui/android/view/ViewUtil.java @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2007-2015 FBReader.ORG Limited + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +package org.geometerplus.zlibrary.ui.android.view; + +import android.graphics.*; + +public abstract class ViewUtil { + public static void setColorLevel(Paint paint, Integer level) { + if (level != null) { + paint.setColorFilter(new PorterDuffColorFilter( + Color.rgb(level, level, level), PorterDuff.Mode.MULTIPLY + )); + } else { + paint.setColorFilter(null); + } + } +} diff --git a/src/org/geometerplus/zlibrary/ui/android/view/ZLAndroidWidget.java b/src/org/geometerplus/zlibrary/ui/android/view/ZLAndroidWidget.java index 75695968d..a01077377 100644 --- a/src/org/geometerplus/zlibrary/ui/android/view/ZLAndroidWidget.java +++ b/src/org/geometerplus/zlibrary/ui/android/view/ZLAndroidWidget.java @@ -47,10 +47,11 @@ import org.geometerplus.fbreader.fbreader.options.PageTurningOptions; import org.geometerplus.android.fbreader.FBReader; -public class ZLAndroidWidget extends View implements ZLViewWidget, View.OnLongClickListener { +public class ZLAndroidWidget extends MainView implements ZLViewWidget, View.OnLongClickListener { public final ExecutorService PrepareService = Executors.newSingleThreadExecutor(); private final Paint myPaint = new Paint(); + private final BitmapManagerImpl myBitmapManager = new BitmapManagerImpl(this); private Bitmap myFooterBitmap; private final SystemInfo mySystemInfo; @@ -277,7 +278,7 @@ public class ZLAndroidWidget extends View implements ZLViewWidget, View.OnLongCl @Override public void startManualScrolling(int x, int y, ZLView.Direction direction) { final AnimationProvider animator = getAnimationProvider(); - animator.setup(direction, getWidth(), getMainAreaHeight()); + animator.setup(direction, getWidth(), getMainAreaHeight(), myColorLevel); animator.startManualScrolling(x, y); } @@ -298,7 +299,7 @@ public class ZLAndroidWidget extends View implements ZLViewWidget, View.OnLongCl return; } final AnimationProvider animator = getAnimationProvider(); - animator.setup(direction, getWidth(), getMainAreaHeight()); + animator.setup(direction, getWidth(), getMainAreaHeight(), myColorLevel); animator.startAnimatedScrolling(pageIndex, x, y, speed); if (animator.getMode().Auto) { postInvalidate(); @@ -312,7 +313,7 @@ public class ZLAndroidWidget extends View implements ZLViewWidget, View.OnLongCl return; } final AnimationProvider animator = getAnimationProvider(); - animator.setup(direction, getWidth(), getMainAreaHeight()); + animator.setup(direction, getWidth(), getMainAreaHeight(), myColorLevel); animator.startAnimatedScrolling(pageIndex, null, null, speed); if (animator.getMode().Auto) { postInvalidate(); @@ -667,19 +668,8 @@ public class ZLAndroidWidget extends View implements ZLViewWidget, View.OnLongCl return resourceId > 0 ? res.getDimensionPixelSize(resourceId) : 0; } - public void setScreenBrightness(int percent) { - final Context context = getContext(); - if (!(context instanceof FBReader)) { - return; - } - ((FBReader)context).setScreenBrightness(percent); - } - - public int getScreenBrightness() { - final Context context = getContext(); - if (!(context instanceof FBReader)) { - return 50; - } - return ((FBReader)context).getScreenBrightness(); + @Override + protected void updateColorLevel() { + ViewUtil.setColorLevel(myPaint, myColorLevel); } } diff --git a/src/org/geometerplus/zlibrary/ui/android/view/animation/AnimationProvider.java b/src/org/geometerplus/zlibrary/ui/android/view/animation/AnimationProvider.java index 681a65c41..5f6c8eff9 100644 --- a/src/org/geometerplus/zlibrary/ui/android/view/animation/AnimationProvider.java +++ b/src/org/geometerplus/zlibrary/ui/android/view/animation/AnimationProvider.java @@ -55,6 +55,7 @@ public abstract class AnimationProvider { protected int myWidth; protected int myHeight; + protected Integer myColorLevel; protected AnimationProvider(BitmapManager bitmapManager) { myBitmapManager = bitmapManager; @@ -209,10 +210,11 @@ public abstract class AnimationProvider { return myDirection.IsHorizontal ? myEndX - myStartX : myEndY - myStartY; } - public final void setup(ZLViewEnums.Direction direction, int width, int height) { + public final void setup(ZLViewEnums.Direction direction, int width, int height, Integer colorLevel) { myDirection = direction; myWidth = width; myHeight = height; + myColorLevel = colorLevel; } public abstract void doStep(); @@ -240,6 +242,7 @@ public abstract class AnimationProvider { public final void draw(Canvas canvas) { final long start = System.currentTimeMillis(); + setFilter(); drawInternal(canvas); myDrawInfos.add(new DrawInfo(myEndX, myEndY, start, System.currentTimeMillis())); if (myDrawInfos.size() > 3) { @@ -247,7 +250,14 @@ public abstract class AnimationProvider { } } + public final void drawFooterBitmap(Canvas canvas, Bitmap footerBitmap, int voffset) { + setFilter(); + drawFooterBitmapInternal(canvas, footerBitmap, voffset); + } + + protected abstract void setFilter(); protected abstract void drawInternal(Canvas canvas); + protected abstract void drawFooterBitmapInternal(Canvas canvas, Bitmap footerBitmap, int voffset); public abstract ZLViewEnums.PageIndex getPageToScrollTo(int x, int y); @@ -270,6 +280,4 @@ public abstract class AnimationProvider { protected void drawBitmapTo(Canvas canvas, int x, int y, Paint paint) { myBitmapManager.drawBitmap(canvas, x, y, getPageToScrollTo(), paint); } - - public abstract void drawFooterBitmap(Canvas canvas, Bitmap footerBitmap, int voffset); } diff --git a/src/org/geometerplus/zlibrary/ui/android/view/animation/CurlAnimationProvider.java b/src/org/geometerplus/zlibrary/ui/android/view/animation/CurlAnimationProvider.java index c7386853d..baff83451 100644 --- a/src/org/geometerplus/zlibrary/ui/android/view/animation/CurlAnimationProvider.java +++ b/src/org/geometerplus/zlibrary/ui/android/view/animation/CurlAnimationProvider.java @@ -24,7 +24,9 @@ import android.util.FloatMath; import org.geometerplus.zlibrary.core.util.BitmapUtil; import org.geometerplus.zlibrary.core.view.ZLViewEnums; + import org.geometerplus.zlibrary.ui.android.util.ZLAndroidColorUtil; +import org.geometerplus.zlibrary.ui.android.view.ViewUtil; public final class CurlAnimationProvider extends AnimationProvider { private final Paint myPaint = new Paint(); @@ -327,7 +329,14 @@ public final class CurlAnimationProvider extends AnimationProvider { } @Override - public void drawFooterBitmap(Canvas canvas, Bitmap footerBitmap, int voffset) { + public void drawFooterBitmapInternal(Canvas canvas, Bitmap footerBitmap, int voffset) { canvas.drawBitmap(footerBitmap, 0, voffset, myPaint); } + + @Override + protected void setFilter() { + ViewUtil.setColorLevel(myPaint, myColorLevel); + ViewUtil.setColorLevel(myBackPaint, myColorLevel); + ViewUtil.setColorLevel(myEdgePaint, myColorLevel); + } } diff --git a/src/org/geometerplus/zlibrary/ui/android/view/animation/NoneAnimationProvider.java b/src/org/geometerplus/zlibrary/ui/android/view/animation/NoneAnimationProvider.java index 5ae98b8bc..71603d4f6 100644 --- a/src/org/geometerplus/zlibrary/ui/android/view/animation/NoneAnimationProvider.java +++ b/src/org/geometerplus/zlibrary/ui/android/view/animation/NoneAnimationProvider.java @@ -23,6 +23,8 @@ import android.graphics.*; import org.geometerplus.zlibrary.core.view.ZLViewEnums; +import org.geometerplus.zlibrary.ui.android.view.ViewUtil; + public final class NoneAnimationProvider extends AnimationProvider { private final Paint myPaint = new Paint(); @@ -79,7 +81,12 @@ public final class NoneAnimationProvider extends AnimationProvider { } @Override - public void drawFooterBitmap(Canvas canvas, Bitmap footerBitmap, int voffset) { + public void drawFooterBitmapInternal(Canvas canvas, Bitmap footerBitmap, int voffset) { canvas.drawBitmap(footerBitmap, 0, voffset, myPaint); } + + @Override + protected void setFilter() { + ViewUtil.setColorLevel(myPaint, myColorLevel); + } } diff --git a/src/org/geometerplus/zlibrary/ui/android/view/animation/ShiftAnimationProvider.java b/src/org/geometerplus/zlibrary/ui/android/view/animation/ShiftAnimationProvider.java index ddbbae54a..2ef0576a0 100644 --- a/src/org/geometerplus/zlibrary/ui/android/view/animation/ShiftAnimationProvider.java +++ b/src/org/geometerplus/zlibrary/ui/android/view/animation/ShiftAnimationProvider.java @@ -21,6 +21,8 @@ package org.geometerplus.zlibrary.ui.android.view.animation; import android.graphics.*; +import org.geometerplus.zlibrary.ui.android.view.ViewUtil; + public final class ShiftAnimationProvider extends SimpleAnimationProvider { private final Paint myPaint = new Paint(); { @@ -55,7 +57,7 @@ public final class ShiftAnimationProvider extends SimpleAnimationProvider { } @Override - public void drawFooterBitmap(Canvas canvas, Bitmap footerBitmap, int voffset) { + public void drawFooterBitmapInternal(Canvas canvas, Bitmap footerBitmap, int voffset) { canvas.drawBitmap(footerBitmap, 0, voffset, myPaint); if (myDirection.IsHorizontal) { final int dX = myEndX - myStartX; @@ -66,4 +68,9 @@ public final class ShiftAnimationProvider extends SimpleAnimationProvider { } } } + + @Override + protected void setFilter() { + ViewUtil.setColorLevel(myPaint, myColorLevel); + } } diff --git a/src/org/geometerplus/zlibrary/ui/android/view/animation/SlideAnimationProvider.java b/src/org/geometerplus/zlibrary/ui/android/view/animation/SlideAnimationProvider.java index 5c1db45b1..041913a65 100644 --- a/src/org/geometerplus/zlibrary/ui/android/view/animation/SlideAnimationProvider.java +++ b/src/org/geometerplus/zlibrary/ui/android/view/animation/SlideAnimationProvider.java @@ -22,6 +22,8 @@ package org.geometerplus.zlibrary.ui.android.view.animation; import android.graphics.*; import android.graphics.drawable.GradientDrawable; +import org.geometerplus.zlibrary.ui.android.view.ViewUtil; + public final class SlideAnimationProvider extends SimpleAnimationProvider { private final Paint myDarkPaint = new Paint(); private final Paint myPaint = new Paint(); @@ -31,10 +33,16 @@ public final class SlideAnimationProvider extends SimpleAnimationProvider { } private void setDarkFilter(int visible, int full) { - final int color = 145 + 100 * Math.abs(visible) / full; - myDarkPaint.setColorFilter(new PorterDuffColorFilter( - Color.rgb(color, color, color), PorterDuff.Mode.MULTIPLY - )); + int darkColorLevel = 145 + 100 * Math.abs(visible) / full; + if (myColorLevel != null) { + darkColorLevel = darkColorLevel * myColorLevel / 0xFF; + } + ViewUtil.setColorLevel(myDarkPaint, darkColorLevel); + } + + @Override + protected void setFilter() { + ViewUtil.setColorLevel(myPaint, myColorLevel); } private void drawShadow(Canvas canvas, int top, int bottom, int dX) { @@ -79,7 +87,7 @@ public final class SlideAnimationProvider extends SimpleAnimationProvider { } @Override - public void drawFooterBitmap(Canvas canvas, Bitmap footerBitmap, int voffset) { + protected void drawFooterBitmapInternal(Canvas canvas, Bitmap footerBitmap, int voffset) { if (myDirection.IsHorizontal) { final int dX = myEndX - myStartX; setDarkFilter(dX, myWidth); diff --git a/src/org/geometerplus/zlibrary/ui/android/view/animation/SlideOldStyleAnimationProvider.java b/src/org/geometerplus/zlibrary/ui/android/view/animation/SlideOldStyleAnimationProvider.java index 85eb98799..2752a42a7 100644 --- a/src/org/geometerplus/zlibrary/ui/android/view/animation/SlideOldStyleAnimationProvider.java +++ b/src/org/geometerplus/zlibrary/ui/android/view/animation/SlideOldStyleAnimationProvider.java @@ -21,6 +21,8 @@ package org.geometerplus.zlibrary.ui.android.view.animation; import android.graphics.*; +import org.geometerplus.zlibrary.ui.android.view.ViewUtil; + public final class SlideOldStyleAnimationProvider extends SimpleAnimationProvider { private final Paint myPaint = new Paint(); @@ -52,7 +54,7 @@ public final class SlideOldStyleAnimationProvider extends SimpleAnimationProvide } @Override - public void drawFooterBitmap(Canvas canvas, Bitmap footerBitmap, int voffset) { + protected void drawFooterBitmapInternal(Canvas canvas, Bitmap footerBitmap, int voffset) { canvas.drawBitmap(footerBitmap, 0, voffset, myPaint); if (myDirection.IsHorizontal) { final int dX = myEndX - myStartX; @@ -63,4 +65,9 @@ public final class SlideOldStyleAnimationProvider extends SimpleAnimationProvide } } } + + @Override + protected void setFilter() { + ViewUtil.setColorLevel(myPaint, myColorLevel); + } }