New main menu
This commit is contained in:
		| @@ -224,17 +224,24 @@ public class BaseActivity extends AppCompatActivity implements SharedPreferences | ||||
|  | ||||
|     @Override | ||||
|     public boolean onKeyUp(int keyCode, KeyEvent event) { | ||||
|         if (keyCode == KeyEvent.KEYCODE_MENU && event.getRepeatCount() == 0 && toolbar != null) { | ||||
|             if (toolbar.isOverflowMenuShowing()) { | ||||
|                 toolbar.hideOverflowMenu(); | ||||
|             } else { | ||||
|                 toolbar.showOverflowMenu(); | ||||
|             } | ||||
|             return true; | ||||
|         if (keyCode == KeyEvent.KEYCODE_MENU && event.getRepeatCount() == 0) { | ||||
|             return toggleMenu(); | ||||
|         } | ||||
|         return super.onKeyUp(keyCode, event); | ||||
|     } | ||||
|  | ||||
|     protected boolean toggleMenu() { | ||||
|         if (toolbar == null) { | ||||
|             return false; | ||||
|         } | ||||
|         if (toolbar.isOverflowMenuShowing()) { | ||||
|             toolbar.hideOverflowMenu(); | ||||
|         } else { | ||||
|             toolbar.showOverflowMenu(); | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void onResume() { | ||||
|         super.onResume(); | ||||
|   | ||||
| @@ -75,8 +75,6 @@ public class Calculator implements SharedPreferences.OnSharedPreferenceChangeLis | ||||
|  | ||||
|     private volatile boolean calculateOnFly = true; | ||||
|  | ||||
|     @Inject | ||||
|     PreferredPreferences preferredPreferences; | ||||
|     @Inject | ||||
|     Editor editor; | ||||
|     @Inject | ||||
| @@ -162,7 +160,6 @@ public class Calculator implements SharedPreferences.OnSharedPreferenceChangeLis | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         preferredPreferences.check(false); | ||||
|         PreparedExpression pe = null; | ||||
|         try { | ||||
|             pe = prepare(e); | ||||
|   | ||||
| @@ -23,30 +23,37 @@ | ||||
| package org.solovyev.android.calculator; | ||||
|  | ||||
| import android.content.SharedPreferences; | ||||
| import android.graphics.Typeface; | ||||
| import android.os.Bundle; | ||||
| import android.support.annotation.StringRes; | ||||
| import android.support.v4.app.FragmentManager; | ||||
| import android.support.v4.app.FragmentTransaction; | ||||
| import android.support.v4.view.GravityCompat; | ||||
| import android.support.v7.widget.PopupMenu; | ||||
| import android.text.SpannableString; | ||||
| import android.text.Spanned; | ||||
| import android.text.style.StyleSpan; | ||||
| import android.view.KeyEvent; | ||||
| import android.view.Menu; | ||||
| import android.view.MenuItem; | ||||
| import android.view.View; | ||||
| import android.widget.FrameLayout; | ||||
| import android.widget.ImageButton; | ||||
| import butterknife.Bind; | ||||
| import jscl.AngleUnit; | ||||
| import jscl.NumeralBase; | ||||
| import org.solovyev.android.calculator.converter.ConverterFragment; | ||||
| import org.solovyev.android.calculator.history.History; | ||||
| import org.solovyev.android.calculator.keyboard.PartialKeyboardUi; | ||||
| import org.solovyev.android.widget.menu.CustomPopupMenu; | ||||
|  | ||||
| import javax.annotation.Nonnull; | ||||
| import javax.annotation.Nullable; | ||||
| import javax.inject.Inject; | ||||
|  | ||||
| public class CalculatorActivity extends BaseActivity implements View.OnClickListener, PopupMenu.OnMenuItemClickListener { | ||||
| public class CalculatorActivity extends BaseActivity implements View.OnClickListener { | ||||
|  | ||||
|     @Nonnull | ||||
|     private final MainMenu mainMenu = new MainMenu(this); | ||||
|     @Inject | ||||
|     PreferredPreferences preferredPreferences; | ||||
|     private final MainMenu mainMenu = new MainMenu(); | ||||
|     @Inject | ||||
|     Keyboard keyboard; | ||||
|     @Inject | ||||
| @@ -63,7 +70,7 @@ public class CalculatorActivity extends BaseActivity implements View.OnClickList | ||||
|     @Bind(R.id.editor) | ||||
|     FrameLayout editor; | ||||
|     @Bind(R.id.main_menu) | ||||
|     ImageButton mainMenuButton; | ||||
|     View mainMenuButton; | ||||
|     private boolean useBackAsPrevious; | ||||
|  | ||||
|     public CalculatorActivity() { | ||||
| @@ -93,8 +100,6 @@ public class CalculatorActivity extends BaseActivity implements View.OnClickList | ||||
|         if (savedInstanceState == null) { | ||||
|             startupHelper.onMainActivityOpened(this); | ||||
|         } | ||||
|  | ||||
|         preferredPreferences.check(this, false); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
| @@ -139,36 +144,7 @@ public class CalculatorActivity extends BaseActivity implements View.OnClickList | ||||
|         if (Preferences.Gui.useBackAsPrevious.isSameKey(key)) { | ||||
|             useBackAsPrevious = Preferences.Gui.useBackAsPrevious.getPreference(preferences); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean onMenuItemClick(MenuItem item) { | ||||
|         switch (item.getItemId()) { | ||||
|             case R.id.menu_settings: | ||||
|                 launcher.showSettings(); | ||||
|                 return true; | ||||
|             case R.id.menu_history: | ||||
|                 launcher.showHistory(); | ||||
|                 return true; | ||||
|             case R.id.menu_plotter: | ||||
|                 launcher.showPlotter(); | ||||
|                 return true; | ||||
|             case R.id.menu_conversion_tool: | ||||
|                 ConverterFragment.show(this); | ||||
|                 return true; | ||||
|             case R.id.menu_about: | ||||
|                 launcher.showAbout(); | ||||
|                 return true; | ||||
| /*            case R.id.menu_mode_engineer: | ||||
|                 Preferences.Gui.mode.putPreference(preferences, Preferences.Gui.Mode.engineer); | ||||
|                 restartIfModeChanged(); | ||||
|                 return true; | ||||
|             case R.id.menu_mode_simple: | ||||
|                 Preferences.Gui.mode.putPreference(preferences, Preferences.Gui.Mode.simple); | ||||
|                 restartIfModeChanged(); | ||||
|                 return true;*/ | ||||
|         } | ||||
|         return false; | ||||
|         mainMenu.onSharedPreferenceChanged(key); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
| @@ -179,4 +155,159 @@ public class CalculatorActivity extends BaseActivity implements View.OnClickList | ||||
|                 break; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected boolean toggleMenu() { | ||||
|         if (!super.toggleMenu()) { | ||||
|             mainMenu.toggle(); | ||||
|         } | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     final class MainMenu implements PopupMenu.OnMenuItemClickListener { | ||||
|  | ||||
|         @Nullable | ||||
|         private CustomPopupMenu popup; | ||||
|  | ||||
|         public void toggle() { | ||||
|             if (popup == null) { | ||||
|                 popup = new CustomPopupMenu(CalculatorActivity.this, mainMenuButton, GravityCompat.END, R.attr.actionOverflowMenuStyle, 0); | ||||
|                 popup.inflate(R.menu.main); | ||||
|                 popup.setOnMenuItemClickListener(this); | ||||
|                 popup.setKeepOnSubMenu(true); | ||||
|                 popup.setForceShowIcon(true); | ||||
|             } | ||||
|             if (popup.isShowing()) { | ||||
|                 popup.dismiss(); | ||||
|             } else { | ||||
|                 updateMode(); | ||||
|                 updateAngleUnits(); | ||||
|                 updateNumeralBase(); | ||||
|                 popup.show(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private void updateMode() { | ||||
|             if (popup == null) { | ||||
|                 return; | ||||
|             } | ||||
|             final Menu menu = popup.getMenu(); | ||||
|             final MenuItem menuItem = menu.findItem(R.id.menu_mode); | ||||
|             menuItem.setTitle(makeTitle(R.string.cpp_mode, getActivityMode().name)); | ||||
|         } | ||||
|  | ||||
|         @Nonnull | ||||
|         private CharSequence makeTitle(@StringRes int prefix, @StringRes int suffix) { | ||||
|             final String p = getString(prefix); | ||||
|             final String s = getString(suffix); | ||||
|             final SpannableString title = new SpannableString(p + ": " + s); | ||||
|             title.setSpan(new StyleSpan(Typeface.BOLD), 0, p.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE); | ||||
|             return title; | ||||
|         } | ||||
|  | ||||
|         private void updateAngleUnits() { | ||||
|             if (popup == null) { | ||||
|                 return; | ||||
|             } | ||||
|             final Menu menu = popup.getMenu(); | ||||
|             final MenuItem menuItem = menu.findItem(R.id.menu_angle_units); | ||||
|             final AngleUnit angles = Engine.Preferences.angleUnit.getPreference(preferences); | ||||
|             menuItem.setTitle(makeTitle(R.string.cpp_angles, getAngleUnitsName(angles))); | ||||
|         } | ||||
|  | ||||
|         private void updateNumeralBase() { | ||||
|             if (popup == null) { | ||||
|                 return; | ||||
|             } | ||||
|             final Menu menu = popup.getMenu(); | ||||
|             final MenuItem menuItem = menu.findItem(R.id.menu_numeral_base); | ||||
|             final NumeralBase numeralBase = Engine.Preferences.numeralBase.getPreference(preferences); | ||||
|             menuItem.setTitle(makeTitle(R.string.cpp_radix, getNumeralBaseName(numeralBase))); | ||||
|         } | ||||
|  | ||||
|         @StringRes | ||||
|         private int getAngleUnitsName(AngleUnit angleUnit) { | ||||
|             switch (angleUnit) { | ||||
|                 case deg: | ||||
|                     return R.string.p_deg; | ||||
|                 case rad: | ||||
|                     return R.string.p_rad; | ||||
|                 case grad: | ||||
|                     return R.string.p_grad; | ||||
|                 case turns: | ||||
|                     return R.string.p_turns; | ||||
|             } | ||||
|             return 0; | ||||
|         } | ||||
|  | ||||
|         @StringRes | ||||
|         private int getNumeralBaseName(NumeralBase numeralBase) { | ||||
|             switch (numeralBase) { | ||||
|                 case bin: | ||||
|                     return R.string.p_bin; | ||||
|                 case oct: | ||||
|                     return R.string.p_oct; | ||||
|                 case dec: | ||||
|                     return R.string.p_dec; | ||||
|                 case hex: | ||||
|                     return R.string.p_hex; | ||||
|             } | ||||
|             return 0; | ||||
|         } | ||||
|  | ||||
|         @Override | ||||
|         public boolean onMenuItemClick(MenuItem item) { | ||||
|             switch (item.getItemId()) { | ||||
|                 case R.id.menu_settings: | ||||
|                     launcher.showSettings(); | ||||
|                     return true; | ||||
|                 case R.id.menu_history: | ||||
|                     launcher.showHistory(); | ||||
|                     return true; | ||||
|                 case R.id.menu_plotter: | ||||
|                     launcher.showPlotter(); | ||||
|                     return true; | ||||
|                 case R.id.menu_conversion_tool: | ||||
|                     ConverterFragment.show(CalculatorActivity.this); | ||||
|                     return true; | ||||
|                 case R.id.menu_about: | ||||
|                     launcher.showAbout(); | ||||
|                     return true; | ||||
|                 case R.id.menu_mode_engineer: | ||||
|                     Preferences.Gui.mode.putPreference(preferences, Preferences.Gui.Mode.engineer); | ||||
|                     restartIfModeChanged(); | ||||
|                     return true; | ||||
|                 case R.id.menu_mode_simple: | ||||
|                     Preferences.Gui.mode.putPreference(preferences, Preferences.Gui.Mode.simple); | ||||
|                     restartIfModeChanged(); | ||||
|                     return true; | ||||
|                 case R.id.menu_au_deg: | ||||
|                     Engine.Preferences.angleUnit.putPreference(preferences, AngleUnit.deg); | ||||
|                     return true; | ||||
|                 case R.id.menu_au_rad: | ||||
|                     Engine.Preferences.angleUnit.putPreference(preferences, AngleUnit.rad); | ||||
|                     return true; | ||||
|                 case R.id.menu_nb_bin: | ||||
|                     Engine.Preferences.numeralBase.putPreference(preferences, NumeralBase.bin); | ||||
|                     return true; | ||||
|                 case R.id.menu_nb_dec: | ||||
|                     Engine.Preferences.numeralBase.putPreference(preferences, NumeralBase.dec); | ||||
|                     return true; | ||||
|                 case R.id.menu_nb_hex: | ||||
|                     Engine.Preferences.numeralBase.putPreference(preferences, NumeralBase.hex); | ||||
|                     return true; | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         public void onSharedPreferenceChanged(String key) { | ||||
|             if (Preferences.Gui.mode.isSameKey(key)) { | ||||
|                 updateMode(); | ||||
|             } else if (Engine.Preferences.angleUnit.isSameKey(key)) { | ||||
|                 updateAngleUnits(); | ||||
|             } else if (Engine.Preferences.numeralBase.isSameKey(key)) { | ||||
|                 updateNumeralBase(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -91,9 +91,6 @@ public class CalculatorApplication extends android.app.Application implements Sh | ||||
|     @Inject | ||||
|     Notifier notifier; | ||||
|  | ||||
|     @Inject | ||||
|     PreferredPreferences preferredPreferences; | ||||
|  | ||||
|     @Inject | ||||
|     ActivityLauncher launcher; | ||||
|  | ||||
|   | ||||
| @@ -58,7 +58,7 @@ public class Display { | ||||
|     @Inject | ||||
|     Lazy<Notifier> notifier; | ||||
|     @Inject | ||||
|     Lazy<PreferredPreferences> preferredPreferences; | ||||
|     Lazy<UiPreferences> uiPreferences; | ||||
|     @Nullable | ||||
|     private DisplayView view; | ||||
|     @Nonnull | ||||
| @@ -88,7 +88,7 @@ public class Display { | ||||
|     public void onCalculationFinished(@Nonnull CalculationFinishedEvent e) { | ||||
|         if (e.sequence < state.sequence) return; | ||||
|         setState(DisplayState.createValid(e.operation, e.result, e.stringResult, e.sequence)); | ||||
|         if (!e.messages.isEmpty() && preferredPreferences.get().isShowWarningDialog()) { | ||||
|         if (!e.messages.isEmpty() && uiPreferences.get().isShowFixableErrorDialog()) { | ||||
|             final Context context = view != null ? view.getContext() : application; | ||||
|             FixableErrorsActivity.show(context, e.messages); | ||||
|         } | ||||
|   | ||||
| @@ -137,8 +137,6 @@ public final class Preferences { | ||||
|         Gui.language.tryPutDefault(preferences, editor); | ||||
|  | ||||
|         Calculations.calculateOnFly.tryPutDefault(preferences, editor); | ||||
|         Calculations.preferredAngleUnits.tryPutDefault(preferences, editor); | ||||
|         Calculations.preferredNumeralBase.tryPutDefault(preferences, editor); | ||||
|  | ||||
|         Onscreen.showAppIcon.tryPutDefault(preferences, editor); | ||||
|         Onscreen.theme.tryPutDefault(preferences, editor); | ||||
| @@ -261,8 +259,6 @@ public final class Preferences { | ||||
|  | ||||
|     public static class Calculations { | ||||
|         public static final Preference<Boolean> calculateOnFly = BooleanPreference.of("calculations_calculate_on_fly", true); | ||||
|         public static final Preference<NumeralBase> preferredNumeralBase = StringPreference.ofEnum("preferred_numeral_base", Engine.Preferences.numeralBase.getDefaultValue(), NumeralBase.class); | ||||
|         public static final Preference<AngleUnit> preferredAngleUnits = StringPreference.ofEnum("preferred_angle_units", Engine.Preferences.angleUnit.getDefaultValue(), AngleUnit.class); | ||||
|     } | ||||
|  | ||||
|     public static class App { | ||||
|   | ||||
| @@ -1,121 +0,0 @@ | ||||
| /* | ||||
|  * Copyright 2013 serso aka se.solovyev | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  *    http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  * | ||||
|  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
|  * Contact details | ||||
|  * | ||||
|  * Email: se.solovyev@gmail.com | ||||
|  * Site:  http://se.solovyev.org | ||||
|  */ | ||||
|  | ||||
| package org.solovyev.android.calculator; | ||||
|  | ||||
| import android.app.Application; | ||||
| import android.content.Context; | ||||
| import android.content.SharedPreferences; | ||||
| import jscl.AngleUnit; | ||||
| import jscl.NumeralBase; | ||||
| import org.solovyev.android.calculator.errors.FixableError; | ||||
| import org.solovyev.android.calculator.errors.FixableErrorType; | ||||
| import org.solovyev.android.calculator.errors.FixableErrorsActivity; | ||||
| import org.solovyev.common.msg.MessageType; | ||||
|  | ||||
| import javax.annotation.Nonnull; | ||||
| import javax.inject.Inject; | ||||
| import javax.inject.Singleton; | ||||
| import java.util.ArrayList; | ||||
| import java.util.concurrent.TimeUnit; | ||||
|  | ||||
| @Singleton | ||||
| public class PreferredPreferences { | ||||
|  | ||||
|     private static final long PREFERRED_PREFS_INTERVAL_TIME = TimeUnit.MINUTES.toMillis(15); | ||||
|  | ||||
|     private long lastCheckTime; | ||||
|     private boolean showWarningDialog = true; | ||||
|  | ||||
|     @Inject | ||||
|     Application application; | ||||
|     @Inject | ||||
|     SharedPreferences preferences; | ||||
|     @Inject | ||||
|     Notifier notifier; | ||||
|  | ||||
|     @Inject | ||||
|     public PreferredPreferences() { | ||||
|     } | ||||
|  | ||||
|     public void check(boolean force) { | ||||
|         check(application, force); | ||||
|     } | ||||
|  | ||||
|     public void check(@Nonnull Context context, boolean force) { | ||||
|         final long now = System.currentTimeMillis(); | ||||
|  | ||||
|         if (!force) { | ||||
|             if (!showWarningDialog) { | ||||
|                 // user has disabled calculation message dialogs until the next session | ||||
|                 return; | ||||
|             } | ||||
|             if (now - lastCheckTime < PREFERRED_PREFS_INTERVAL_TIME) { | ||||
|                 return; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         final NumeralBase preferredNumeralBase = Preferences.Calculations.preferredNumeralBase.getPreference(preferences); | ||||
|         final NumeralBase numeralBase = Engine.Preferences.numeralBase.getPreference(preferences); | ||||
|  | ||||
|         final AngleUnit preferredAngleUnits = Preferences.Calculations.preferredAngleUnits.getPreference(preferences); | ||||
|         final AngleUnit angleUnits = Engine.Preferences.angleUnit.getPreference(preferences); | ||||
|  | ||||
|         final ArrayList<FixableError> messages = new ArrayList<>(2); | ||||
|         if (numeralBase != preferredNumeralBase) { | ||||
|             messages.add(new FixableError(application.getString(R.string.preferred_numeral_base_message, preferredNumeralBase.name(), numeralBase.name()), MessageType.warning, FixableErrorType.preferred_numeral_base)); | ||||
|         } | ||||
|  | ||||
|         if (angleUnits != preferredAngleUnits) { | ||||
|             messages.add(new FixableError(application.getString(R.string.preferred_angle_units_message, preferredAngleUnits.name(), angleUnits.name()), MessageType.warning, FixableErrorType.preferred_angle_units)); | ||||
|         } | ||||
|  | ||||
|         FixableErrorsActivity.show(context, messages); | ||||
|         lastCheckTime = now; | ||||
|     } | ||||
|  | ||||
|     public void setPreferredAngleUnits() { | ||||
|         setAngleUnits(Preferences.Calculations.preferredAngleUnits.getPreference(preferences)); | ||||
|     } | ||||
|  | ||||
|     public void setAngleUnits(@Nonnull AngleUnit angleUnit) { | ||||
|         Engine.Preferences.angleUnit.putPreference(preferences, angleUnit); | ||||
|         notifier.showMessage(R.string.c_angle_units_changed_to, angleUnit.name()); | ||||
|     } | ||||
|  | ||||
|     public void setPreferredNumeralBase() { | ||||
|         setNumeralBase(Preferences.Calculations.preferredNumeralBase.getPreference(preferences)); | ||||
|     } | ||||
|  | ||||
|     public void setNumeralBase(@Nonnull NumeralBase numeralBase) { | ||||
|         Engine.Preferences.numeralBase.putPreference(preferences, numeralBase); | ||||
|         notifier.showMessage(R.string.c_numeral_base_changed_to, numeralBase.name()); | ||||
|     } | ||||
|  | ||||
|     public boolean isShowWarningDialog() { | ||||
|         return showWarningDialog; | ||||
|     } | ||||
|  | ||||
|     public void dontShowWarningDialog() { | ||||
|         showWarningDialog = false; | ||||
|     } | ||||
| } | ||||
| @@ -7,8 +7,11 @@ import org.solovyev.android.prefs.IntegerPreference; | ||||
| import org.solovyev.android.prefs.Preference; | ||||
|  | ||||
| import javax.annotation.Nonnull; | ||||
| import javax.inject.Inject; | ||||
| import javax.inject.Singleton; | ||||
|  | ||||
| final class UiPreferences { | ||||
| @Singleton | ||||
| public final class UiPreferences { | ||||
|     @NonNull | ||||
|     public static final Preference<Integer> opened = IntegerPreference.of("opened", 0); | ||||
|     @NonNull | ||||
| @@ -17,6 +20,11 @@ final class UiPreferences { | ||||
|     public static final Preference<Integer> appVersion = IntegerPreference.of("appVersion", IntegerPreference.DEF_VALUE); | ||||
|     @NonNull | ||||
|     public static final Preference<Boolean> rateUsShown = BooleanPreference.of("rateUsShown", false); | ||||
|     public boolean showFixableErrorDialog = true; | ||||
|  | ||||
|     @Inject | ||||
|     public UiPreferences() { | ||||
|     } | ||||
|  | ||||
|     public static void init(@NonNull SharedPreferences preferences, @NonNull SharedPreferences uiPreferences) { | ||||
|         final int currentVersion = getVersion(uiPreferences); | ||||
| @@ -45,4 +53,12 @@ final class UiPreferences { | ||||
|         } | ||||
|         return 0; | ||||
|     } | ||||
|  | ||||
|     public boolean isShowFixableErrorDialog() { | ||||
|         return showFixableErrorDialog; | ||||
|     } | ||||
|  | ||||
|     public void setShowFixableErrorDialog(boolean showFixableErrorDialog) { | ||||
|         this.showFixableErrorDialog = showFixableErrorDialog; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -7,13 +7,8 @@ import android.support.annotation.NonNull; | ||||
| import android.support.annotation.Nullable; | ||||
| import android.support.v4.app.FragmentManager; | ||||
| import android.support.v7.app.AlertDialog; | ||||
|  | ||||
| import org.solovyev.android.Check; | ||||
| import org.solovyev.android.calculator.App; | ||||
| import org.solovyev.android.calculator.AppComponent; | ||||
| import org.solovyev.android.calculator.BaseDialogFragment; | ||||
| import org.solovyev.android.calculator.PreferredPreferences; | ||||
| import org.solovyev.android.calculator.R; | ||||
| import org.solovyev.android.calculator.*; | ||||
|  | ||||
| import javax.annotation.Nonnull; | ||||
| import javax.inject.Inject; | ||||
| @@ -24,7 +19,7 @@ public class FixableErrorFragment extends BaseDialogFragment { | ||||
|     @Nonnull | ||||
|     private static final String ARG_ERROR = "error"; | ||||
|     @Inject | ||||
|     PreferredPreferences preferredPreferences; | ||||
|     UiPreferences uiPreferences; | ||||
|     private FixableError error; | ||||
|     @Nullable | ||||
|     private FixableErrorsActivity activity; | ||||
| @@ -75,12 +70,12 @@ public class FixableErrorFragment extends BaseDialogFragment { | ||||
|     public void onClick(DialogInterface dialog, int which) { | ||||
|         switch (which) { | ||||
|             case DialogInterface.BUTTON_NEUTRAL: | ||||
|                 preferredPreferences.dontShowWarningDialog(); | ||||
|                 uiPreferences.setShowFixableErrorDialog(false); | ||||
|                 dismiss(); | ||||
|                 break; | ||||
|             case DialogInterface.BUTTON_POSITIVE: | ||||
|                 assert error.error != null; | ||||
|                 error.error.fix(preferredPreferences); | ||||
|                 error.error.fix(preferences); | ||||
|                 dismiss(); | ||||
|                 break; | ||||
|             default: | ||||
|   | ||||
| @@ -22,9 +22,11 @@ | ||||
|  | ||||
| package org.solovyev.android.calculator.errors; | ||||
|  | ||||
| import android.content.SharedPreferences; | ||||
| import jscl.AngleUnit; | ||||
| import jscl.text.msg.Messages; | ||||
| import org.solovyev.android.calculator.PreferredPreferences; | ||||
| import org.solovyev.android.calculator.Engine; | ||||
| import org.solovyev.android.calculator.Preferences; | ||||
|  | ||||
| import javax.annotation.Nonnull; | ||||
| import javax.annotation.Nullable; | ||||
| @@ -35,22 +37,8 @@ public enum FixableErrorType { | ||||
|  | ||||
|     must_be_rad(Messages.msg_23, Messages.msg_24, Messages.msg_25) { | ||||
|         @Override | ||||
|         public void fix(@Nonnull PreferredPreferences preferences) { | ||||
|             preferences.setAngleUnits(AngleUnit.rad); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     preferred_numeral_base() { | ||||
|         @Override | ||||
|         public void fix(@Nonnull PreferredPreferences preferences) { | ||||
|             preferences.setPreferredNumeralBase(); | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     preferred_angle_units() { | ||||
|         @Override | ||||
|         public void fix(@Nonnull PreferredPreferences preferences) { | ||||
|             preferences.setPreferredAngleUnits(); | ||||
|         public void fix(@Nonnull SharedPreferences preferences) { | ||||
|             Engine.Preferences.angleUnit.putPreference(preferences, AngleUnit.rad); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
| @@ -71,5 +59,5 @@ public enum FixableErrorType { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     public abstract void fix(@Nonnull PreferredPreferences preferences); | ||||
|     public abstract void fix(@Nonnull SharedPreferences preferences); | ||||
| } | ||||
|   | ||||
| @@ -29,7 +29,7 @@ import android.os.Bundle; | ||||
| import android.support.v4.app.Fragment; | ||||
| import android.support.v7.app.AppCompatActivity; | ||||
| import org.solovyev.android.calculator.App; | ||||
| import org.solovyev.android.calculator.PreferredPreferences; | ||||
| import org.solovyev.android.calculator.UiPreferences; | ||||
| import org.solovyev.common.msg.Message; | ||||
|  | ||||
| import javax.annotation.Nonnull; | ||||
| @@ -46,7 +46,7 @@ public class FixableErrorsActivity extends AppCompatActivity { | ||||
|     @Inject | ||||
|     SharedPreferences preferences; | ||||
|     @Inject | ||||
|     PreferredPreferences preferredPreferences; | ||||
|     UiPreferences uiPreferences; | ||||
|     private ArrayList<FixableError> errors; | ||||
|  | ||||
|     public static void show(@Nonnull Context context, @Nonnull List<Message> messages) { | ||||
| @@ -96,7 +96,7 @@ public class FixableErrorsActivity extends AppCompatActivity { | ||||
|             finish(); | ||||
|             return; | ||||
|         } | ||||
|         if (!preferredPreferences.isShowWarningDialog()) { | ||||
|         if (!uiPreferences.isShowFixableErrorDialog()) { | ||||
|             finish(); | ||||
|             return; | ||||
|         } | ||||
|   | ||||
| @@ -56,8 +56,6 @@ public abstract class BaseKeyboardUi implements SharedPreferences.OnSharedPrefer | ||||
|     ActivityLauncher launcher; | ||||
|     @Inject | ||||
|     Lazy<Memory> memory; | ||||
|     @Inject | ||||
|     PreferredPreferences preferredPreferences; | ||||
|     protected int orientation = ORIENTATION_PORTRAIT; | ||||
|     private int textSize; | ||||
|     private Preferences.Gui.Mode mode; | ||||
|   | ||||
| @@ -5,14 +5,12 @@ import android.app.Application; | ||||
| import android.content.SharedPreferences; | ||||
| import android.support.annotation.NonNull; | ||||
| import android.support.annotation.Nullable; | ||||
| import android.text.TextUtils; | ||||
| import android.util.Log; | ||||
| import android.view.View; | ||||
| import android.widget.Button; | ||||
| import android.widget.ImageButton; | ||||
| import butterknife.Bind; | ||||
| import butterknife.ButterKnife; | ||||
| import jscl.AngleUnit; | ||||
| import jscl.NumeralBase; | ||||
| import jscl.math.Expression; | ||||
| import jscl.math.Generic; | ||||
| @@ -271,10 +269,6 @@ public class KeyboardUi extends BaseKeyboardUi { | ||||
|                 return false; | ||||
|             case R.id.cpp_button_memory: | ||||
|                 return processMemoryButton(direction); | ||||
|             case R.id.cpp_button_copy: | ||||
|                 return processNumeralBaseButton(direction, (DirectionDragView) view); | ||||
|             case R.id.cpp_button_paste: | ||||
|                 return processAngleUnitsButton(direction, (DirectionDragView) view); | ||||
|             case R.id.cpp_button_round_brackets: | ||||
|                 if (direction == left) { | ||||
|                     keyboard.roundBracketsButtonPressed(); | ||||
| @@ -314,47 +308,8 @@ public class KeyboardUi extends BaseKeyboardUi { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     private boolean processAngleUnitsButton(@Nonnull DragDirection direction, @Nonnull DirectionDragView button) { | ||||
|         if (direction == DragDirection.left) { | ||||
|             return processDefault(direction, button); | ||||
|         } | ||||
|         final String text = button.getText(direction).getValue(); | ||||
|         if (TextUtils.isEmpty(text)) { | ||||
|             return processDefault(direction, button); | ||||
|         } | ||||
|         try { | ||||
|             final AngleUnit newAngleUnits = AngleUnit.valueOf(text); | ||||
|             final AngleUnit oldAngleUnits = Engine.Preferences.angleUnit.getPreference(preferences); | ||||
|             if (oldAngleUnits != newAngleUnits) { | ||||
|                 preferredPreferences.setAngleUnits(newAngleUnits); | ||||
|                 return true; | ||||
|             } | ||||
|         } catch (IllegalArgumentException e) { | ||||
|             Log.d(this.getClass().getName(), "Unsupported angle units: " + text); | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     private boolean processDefault(@Nonnull DragDirection direction, @Nonnull DirectionDragView button) { | ||||
|         final String text = button.getText(direction).getValue(); | ||||
|         return keyboard.buttonPressed(text); | ||||
|     } | ||||
|  | ||||
|     private boolean processNumeralBaseButton(@Nonnull DragDirection direction, @Nonnull DirectionDragView button) { | ||||
|         final String text = button.getText(direction).getValue(); | ||||
|         if (TextUtils.isEmpty(text)) { | ||||
|             return false; | ||||
|         } | ||||
|         try { | ||||
|             final NumeralBase newNumeralBase = NumeralBase.valueOf(text); | ||||
|             final NumeralBase oldNumeralBase = Engine.Preferences.numeralBase.getPreference(preferences); | ||||
|             if (oldNumeralBase != newNumeralBase) { | ||||
|                 preferredPreferences.setNumeralBase(newNumeralBase); | ||||
|                 return true; | ||||
|             } | ||||
|         } catch (IllegalArgumentException e) { | ||||
|             Log.d(this.getClass().getName(), "Unsupported numeral base: " + text); | ||||
|         } | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
| @@ -37,7 +37,6 @@ enum CalculatorMode { | ||||
|             final SharedPreferences.Editor editor = preferences.edit(); | ||||
|  | ||||
|             Preferences.Gui.mode.putPreference(editor, Preferences.Gui.Mode.simple); | ||||
|             Preferences.Calculations.preferredAngleUnits.putPreference(editor, AngleUnit.deg); | ||||
|             Engine.Preferences.angleUnit.putPreference(editor, AngleUnit.deg); | ||||
|             Engine.Preferences.Output.scientificNotation.putPreference(editor, false); | ||||
|             Engine.Preferences.Output.round.putPreference(editor, true); | ||||
| @@ -52,7 +51,6 @@ enum CalculatorMode { | ||||
|             final SharedPreferences.Editor editor = preferences.edit(); | ||||
|  | ||||
|             Preferences.Gui.mode.putPreference(editor, Preferences.Gui.Mode.engineer); | ||||
|             Preferences.Calculations.preferredAngleUnits.putPreference(editor, AngleUnit.rad); | ||||
|             Engine.Preferences.angleUnit.putPreference(editor, AngleUnit.rad); | ||||
|             Engine.Preferences.Output.scientificNotation.putPreference(editor, true); | ||||
|             Engine.Preferences.Output.round.putPreference(editor, false); | ||||
|   | ||||
| @@ -21,7 +21,6 @@ import android.support.annotation.MenuRes; | ||||
| import android.support.v7.appcompat.R; | ||||
| import android.support.v7.view.SupportMenuInflater; | ||||
| import android.support.v7.view.menu.MenuBuilder; | ||||
| import android.support.v7.view.menu.MenuPopupHelper; | ||||
| import android.support.v7.view.menu.MenuPresenter; | ||||
| import android.support.v7.view.menu.SubMenuBuilder; | ||||
| import android.support.v7.widget.ListPopupWindow; | ||||
| @@ -120,20 +119,8 @@ public class CustomPopupMenu implements MenuBuilder.Callback, MenuPresenter.Call | ||||
|         mPopup.setGravity(gravity); | ||||
|     } | ||||
|  | ||||
|     public int getHorizontalOffset() { | ||||
|         return mPopup.getHorizontalOffset(); | ||||
|     } | ||||
|  | ||||
|     public void setVerticalOffset(int offset) { | ||||
|         mPopup.setVerticalOffset(offset); | ||||
|     } | ||||
|  | ||||
|     public int getVerticalOffset() { | ||||
|         return mPopup.getVerticalOffset(); | ||||
|     } | ||||
|  | ||||
|     public void setHorizontalOffset(int offset) { | ||||
|         mPopup.setHorizontalOffset(offset); | ||||
|     public void setForceShowIcon(boolean forceShow) { | ||||
|         mPopup.setForceShowIcon(forceShow); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -194,7 +181,14 @@ public class CustomPopupMenu implements MenuBuilder.Callback, MenuPresenter.Call | ||||
|      * @see #getMenu() | ||||
|      */ | ||||
|     public MenuInflater getMenuInflater() { | ||||
|         return new SupportMenuInflater(mContext); | ||||
|         return new SupportMenuInflater(mContext) { | ||||
|             @Override | ||||
|             public void inflate(int menuRes, Menu menu) { | ||||
|                 final int sizeBefore = menu.size(); | ||||
|                 super.inflate(menuRes, menu); | ||||
|                 CustomPopupMenuHelper.tintMenuItems(mContext, menu, sizeBefore, menu.size()); | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
| @@ -225,6 +219,10 @@ public class CustomPopupMenu implements MenuBuilder.Callback, MenuPresenter.Call | ||||
|         mPopup.dismiss(); | ||||
|     } | ||||
|  | ||||
|     public void setKeepOnSubMenu(boolean keepOnSubMenu) { | ||||
|         mPopup.setKeepOnSubMenu(keepOnSubMenu); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @return {@code true} if the popup is currently showing, {@code false} otherwise. | ||||
|      */ | ||||
| @@ -270,8 +268,6 @@ public class CustomPopupMenu implements MenuBuilder.Callback, MenuPresenter.Call | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         // Current menu will be dismissed by the normal helper, submenu will be shown in its place. | ||||
|         new MenuPopupHelper(mContext, subMenu, mAnchor).show(); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -18,8 +18,12 @@ package org.solovyev.android.widget.menu; | ||||
|  | ||||
| import android.annotation.SuppressLint; | ||||
| import android.content.Context; | ||||
| import android.content.res.ColorStateList; | ||||
| import android.content.res.Resources; | ||||
| import android.content.res.TypedArray; | ||||
| import android.graphics.drawable.Drawable; | ||||
| import android.os.Parcelable; | ||||
| import android.support.v4.graphics.drawable.DrawableCompat; | ||||
| import android.support.v4.view.ActionProvider; | ||||
| import android.support.v4.view.MenuItemCompat; | ||||
| import android.support.v7.appcompat.R; | ||||
| @@ -30,7 +34,9 @@ import android.view.View.MeasureSpec; | ||||
| import android.widget.*; | ||||
|  | ||||
| import javax.annotation.Nonnull; | ||||
| import javax.annotation.Nullable; | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
|  | ||||
| /** | ||||
|  * Presents a menu as a small, simple popup anchored to another view. | ||||
| @@ -42,6 +48,7 @@ public class CustomPopupMenuHelper implements AdapterView.OnItemClickListener, V | ||||
|         MenuPresenter { | ||||
|  | ||||
|     private static final int DEFAULT_VIEW_TAG_KEY = org.solovyev.android.calculator.R.id.cpm_default_view_tag_key; | ||||
|     private static final int[] COLOR_ATTRS = new int[]{R.attr.colorControlNormal}; | ||||
|     private static final Object DEFAULT_VIEW_TAG = new Object(); | ||||
|  | ||||
|     private final Context mContext; | ||||
| @@ -58,6 +65,7 @@ public class CustomPopupMenuHelper implements AdapterView.OnItemClickListener, V | ||||
|     private ViewTreeObserver mTreeObserver; | ||||
|     private Callback mPresenterCallback; | ||||
|     private ViewGroup mMeasureParent; | ||||
|     private boolean mKeepOnSubMenu; | ||||
|  | ||||
|     /** | ||||
|      * Whether the cached content width value is valid. | ||||
| @@ -70,8 +78,6 @@ public class CustomPopupMenuHelper implements AdapterView.OnItemClickListener, V | ||||
|     private int mContentWidth; | ||||
|  | ||||
|     private int mGravity = Gravity.NO_GRAVITY; | ||||
|     private int mVerticalOffset; | ||||
|     private int mHorizontalOffset; | ||||
|  | ||||
|     public CustomPopupMenuHelper(Context context, MenuBuilder menu) { | ||||
|         this(context, menu, null, false, R.attr.popupMenuStyle); | ||||
| @@ -106,6 +112,47 @@ public class CustomPopupMenuHelper implements AdapterView.OnItemClickListener, V | ||||
|         menu.addMenuPresenter(this, context); | ||||
|     } | ||||
|  | ||||
|     static void tintMenuItem(@Nonnull MenuItemImpl item, @Nonnull ColorStateList tintColorStateList) { | ||||
|         Drawable icon = item.getIcon(); | ||||
|         if (icon != null) { | ||||
|             icon = DrawableCompat.wrap(icon); | ||||
|             DrawableCompat.setTintList(icon, tintColorStateList); | ||||
|             item.setIcon(icon); | ||||
|         } | ||||
|         if (item.hasSubMenu()) { | ||||
|             final SubMenu subMenu = item.getSubMenu(); | ||||
|             for (int i = 0; i < subMenu.size(); i++) { | ||||
|                 final MenuItem subItem = subMenu.getItem(i); | ||||
|                 if (subItem instanceof MenuItemImpl) { | ||||
|                     tintMenuItem((MenuItemImpl) subItem, tintColorStateList); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Nullable | ||||
|     static ColorStateList getTintColorStateList(Context context) { | ||||
|         final TypedArray a = context.obtainStyledAttributes(null, COLOR_ATTRS); | ||||
|         try { | ||||
|             return a.getColorStateList(0); | ||||
|         } finally { | ||||
|             a.recycle(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     static void tintMenuItems(Context context, Menu menu, int from, int to) { | ||||
|         final ColorStateList tintColorStateList = getTintColorStateList(context); | ||||
|         if (tintColorStateList == null) { | ||||
|             return; | ||||
|         } | ||||
|         for (int i = from; i < to; i++) { | ||||
|             final MenuItem item = menu.getItem(i); | ||||
|             if (item instanceof MenuItemImpl) { | ||||
|                 tintMenuItem((MenuItemImpl) item, tintColorStateList); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public void setAnchorView(View anchor) { | ||||
|         mAnchorView = anchor; | ||||
|     } | ||||
| @@ -122,20 +169,12 @@ public class CustomPopupMenuHelper implements AdapterView.OnItemClickListener, V | ||||
|         mGravity = gravity; | ||||
|     } | ||||
|  | ||||
|     public void setVerticalOffset(int offset) { | ||||
|         mVerticalOffset = offset; | ||||
|     public boolean isKeepOnSubMenu() { | ||||
|         return mKeepOnSubMenu; | ||||
|     } | ||||
|  | ||||
|     public int getVerticalOffset() { | ||||
|         return mVerticalOffset; | ||||
|     } | ||||
|  | ||||
|     public void setHorizontalOffset(int offset) { | ||||
|         mHorizontalOffset = offset; | ||||
|     } | ||||
|  | ||||
|     public int getHorizontalOffset() { | ||||
|         return mHorizontalOffset; | ||||
|     public void setKeepOnSubMenu(boolean keepOnSubMenu) { | ||||
|         mKeepOnSubMenu = keepOnSubMenu; | ||||
|     } | ||||
|  | ||||
|     public void show() { | ||||
| @@ -162,8 +201,6 @@ public class CustomPopupMenuHelper implements AdapterView.OnItemClickListener, V | ||||
|             if (addGlobalListener) mTreeObserver.addOnGlobalLayoutListener(this); | ||||
|             mPopup.setAnchorView(anchor); | ||||
|             mPopup.setDropDownGravity(mGravity); | ||||
|             mPopup.setHorizontalOffset(mHorizontalOffset); | ||||
|             mPopup.setVerticalOffset(mVerticalOffset); | ||||
|         } else { | ||||
|             return false; | ||||
|         } | ||||
| @@ -291,8 +328,10 @@ public class CustomPopupMenuHelper implements AdapterView.OnItemClickListener, V | ||||
|     @Override | ||||
|     public boolean onSubMenuSelected(SubMenuBuilder subMenu) { | ||||
|         if (subMenu.hasVisibleItems()) { | ||||
|             CustomPopupMenuHelper subPopup = new CustomPopupMenuHelper(mContext, subMenu, mAnchorView); | ||||
|             CustomPopupMenuHelper subPopup = new CustomPopupMenuHelper(mContext, subMenu, mAnchorView, false, mPopupStyleAttr, mPopupStyleRes); | ||||
|             subPopup.setGravity(mGravity); | ||||
|             subPopup.setCallback(mPresenterCallback); | ||||
|             subPopup.setKeepOnSubMenu(mKeepOnSubMenu); | ||||
|  | ||||
|             boolean preserveIconSpacing = false; | ||||
|             final int count = subMenu.size(); | ||||
| @@ -320,6 +359,9 @@ public class CustomPopupMenuHelper implements AdapterView.OnItemClickListener, V | ||||
|         // Only care about the (sub)menu we're presenting. | ||||
|         if (menu != mMenu) return; | ||||
|  | ||||
|         if (isKeepOnSubMenu() && !allMenusAreClosing) { | ||||
|             return; | ||||
|         } | ||||
|         dismiss(); | ||||
|         if (mPresenterCallback != null) { | ||||
|             mPresenterCallback.onCloseMenu(menu, allMenusAreClosing); | ||||
| @@ -402,14 +444,17 @@ public class CustomPopupMenuHelper implements AdapterView.OnItemClickListener, V | ||||
|  | ||||
|         @Nonnull | ||||
|         private View getDefaultView(MenuItemImpl item, View convertView, ViewGroup parent) { | ||||
|             if (convertView == null || convertView.getTag(DEFAULT_VIEW_TAG_KEY) == DEFAULT_VIEW_TAG) { | ||||
|             if (convertView == null || convertView.getTag(DEFAULT_VIEW_TAG_KEY) != DEFAULT_VIEW_TAG) { | ||||
|                 convertView = mInflater.inflate(R.layout.abc_popup_menu_item_layout, parent, false); | ||||
|                 convertView.setTag(DEFAULT_VIEW_TAG_KEY, DEFAULT_VIEW_TAG); | ||||
|             } | ||||
|  | ||||
|             final MenuView.ItemView itemView = (MenuView.ItemView) convertView; | ||||
|             if (mForceShowIcon) { | ||||
|                 ((ListMenuItemView) convertView).setForceShowIcon(true); | ||||
|                 final ListMenuItemView listItemView = (ListMenuItemView) convertView; | ||||
|                 final boolean preserveIconSpacing = ListMenuItemViewCompat.getPreserveIconSpacing(listItemView); | ||||
|                 listItemView.setForceShowIcon(true); | ||||
|                 ListMenuItemViewCompat.setPreserveIconSpacing(listItemView, preserveIconSpacing); | ||||
|             } | ||||
|             itemView.initialize(item, 0); | ||||
|             return convertView; | ||||
| @@ -436,6 +481,17 @@ public class CustomPopupMenuHelper implements AdapterView.OnItemClickListener, V | ||||
|             findExpandedIndex(); | ||||
|             super.notifyDataSetChanged(); | ||||
|         } | ||||
|  | ||||
|         public int indexOf(MenuItem item) { | ||||
|             final List<MenuItemImpl> visibleItems = mMenu.getVisibleItems(); | ||||
|             for (int i = 0; i < visibleItems.size(); i++) { | ||||
|                 MenuItemImpl candidate = visibleItems.get(i); | ||||
|                 if (candidate == item) { | ||||
|                     return i; | ||||
|                 } | ||||
|             } | ||||
|             return -1; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,53 @@ | ||||
| package org.solovyev.android.widget.menu; | ||||
|  | ||||
| import android.support.annotation.NonNull; | ||||
| import android.support.annotation.Nullable; | ||||
| import android.support.v7.view.menu.ListMenuItemView; | ||||
| import android.util.Log; | ||||
|  | ||||
| import java.lang.reflect.Field; | ||||
|  | ||||
| final class ListMenuItemViewCompat { | ||||
|  | ||||
|     @Nullable | ||||
|     private static Field preserveIconSpacingField; | ||||
|  | ||||
|     public static void setPreserveIconSpacing(@NonNull ListMenuItemView view, boolean preserveIconSpacing) { | ||||
|         final Field field = getPreserveIconSpacingField(); | ||||
|         if (field == null) { | ||||
|             return; | ||||
|         } | ||||
|         try { | ||||
|             field.set(view, preserveIconSpacing); | ||||
|         } catch (IllegalAccessException e) { | ||||
|             Log.e("CustomListMenuItemView", e.getMessage(), e); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     public static boolean getPreserveIconSpacing(@NonNull ListMenuItemView view) { | ||||
|         final Field field = getPreserveIconSpacingField(); | ||||
|         if (field == null) { | ||||
|             return false; | ||||
|         } | ||||
|         try { | ||||
|             return field.getBoolean(view); | ||||
|         } catch (IllegalAccessException e) { | ||||
|             Log.e("CustomListMenuItemView", e.getMessage(), e); | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Nullable | ||||
|     private static Field getPreserveIconSpacingField() { | ||||
|         if (preserveIconSpacingField != null) { | ||||
|             return preserveIconSpacingField; | ||||
|         } | ||||
|         try { | ||||
|             preserveIconSpacingField = ListMenuItemView.class.getDeclaredField("mPreserveIconSpacing"); | ||||
|             preserveIconSpacingField.setAccessible(true); | ||||
|             return preserveIconSpacingField; | ||||
|         } catch (NoSuchFieldException e) { | ||||
|             return null; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,102 @@ | ||||
| package org.solovyev.android.widget.menu; | ||||
|  | ||||
| import android.annotation.TargetApi; | ||||
| import android.content.Context; | ||||
| import android.content.res.TypedArray; | ||||
| import android.graphics.drawable.Drawable; | ||||
| import android.os.Build; | ||||
| import android.support.annotation.Nullable; | ||||
| import android.support.v7.view.menu.MenuItemImpl; | ||||
| import android.support.v7.view.menu.MenuView; | ||||
| import android.util.AttributeSet; | ||||
| import android.view.View; | ||||
|  | ||||
| @SuppressWarnings("unused") | ||||
| public class MenuItemDivider extends View implements MenuView.ItemView { | ||||
|  | ||||
|     private static final int[] ATTRS = new int[]{android.R.attr.listDivider}; | ||||
|  | ||||
|     public MenuItemDivider(Context context) { | ||||
|         super(context); | ||||
|     } | ||||
|  | ||||
|     public MenuItemDivider(Context context, AttributeSet attrs) { | ||||
|         super(context, attrs); | ||||
|     } | ||||
|  | ||||
|     public MenuItemDivider(Context context, AttributeSet attrs, int defStyleAttr) { | ||||
|         super(context, attrs, defStyleAttr); | ||||
|     } | ||||
|  | ||||
|     @TargetApi(Build.VERSION_CODES.LOLLIPOP) | ||||
|     public MenuItemDivider(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { | ||||
|         super(context, attrs, defStyleAttr, defStyleRes); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void initialize(MenuItemImpl itemData, int menuType) { | ||||
|         final Drawable divider = getDivider(); | ||||
|         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { | ||||
|             setBackground(divider); | ||||
|         } else { | ||||
|             //noinspection deprecation | ||||
|             setBackgroundDrawable(divider); | ||||
|         } | ||||
|         setEnabled(false); | ||||
|     } | ||||
|  | ||||
|     @Nullable | ||||
|     private Drawable getDivider() { | ||||
|         final TypedArray a = getContext().obtainStyledAttributes(ATTRS); | ||||
|         try { | ||||
|             return a.getDrawable(0); | ||||
|         } finally { | ||||
|             a.recycle(); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public MenuItemImpl getItemData() { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void setTitle(CharSequence title) { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void setEnabled(boolean enabled) { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void setCheckable(boolean checkable) { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void setChecked(boolean checked) { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void setShortcut(boolean showShortcut, char shortcutKey) { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void setIcon(Drawable icon) { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean prefersCondensedTitle() { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean showsIcon() { | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										9
									
								
								app/src/main/res/drawable/ic_chevron_left_24dp.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								app/src/main/res/drawable/ic_chevron_left_24dp.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| <vector xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|         android:width="24dp" | ||||
|         android:height="24dp" | ||||
|         android:viewportWidth="24.0" | ||||
|         android:viewportHeight="24.0"> | ||||
|     <path | ||||
|         android:fillColor="#ffffff" | ||||
|         android:pathData="M15.41,7.41L14,6l-6,6 6,6 1.41,-1.41L10.83,12z"/> | ||||
| </vector> | ||||
| @@ -1,22 +1,35 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <LinearLayout xmlns:a="http://schemas.android.com/apk/res/android" | ||||
| <FrameLayout xmlns:a="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:tools="http://schemas.android.com/tools" | ||||
|     a:layout_width="match_parent" | ||||
|     a:layout_height="0dp" | ||||
|     a:layout_weight="2" | ||||
|     a:orientation="horizontal" | ||||
|     tools:ignore="MergeRootFrame"> | ||||
|  | ||||
|     <FrameLayout | ||||
|         a:id="@+id/editor" | ||||
|         a:layout_width="0dp" | ||||
|         a:layout_height="match_parent" | ||||
|         a:layout_weight="1" /> | ||||
|         a:layout_width="match_parent" | ||||
|         a:layout_height="match_parent" /> | ||||
|  | ||||
|     <ImageButton | ||||
|         style="?attr/actionOverflowButtonStyle" | ||||
|     <!-- make clickable area bigger --> | ||||
|     <FrameLayout | ||||
|         a:id="@+id/main_menu" | ||||
|         a:layout_width="wrap_content" | ||||
|         a:layout_height="?actionBarSize" | ||||
|         a:layout_gravity="top|end" /> | ||||
| </LinearLayout> | ||||
|         style="?attr/actionOverflowButtonStyle" | ||||
|         a:layout_width="40dp" | ||||
|         a:paddingLeft="0dp" | ||||
|         a:paddingRight="0dp" | ||||
|         a:layout_height="?attr/actionBarSize" | ||||
|         a:layout_gravity="top|end"> | ||||
|  | ||||
|         <ImageButton | ||||
|             style="?attr/actionOverflowButtonStyle" | ||||
|             a:paddingLeft="0dp" | ||||
|             a:paddingRight="0dp" | ||||
|             a:layout_width="20dp" | ||||
|             a:layout_height="36dp" | ||||
|             a:clickable="false" | ||||
|             a:focusable="false" | ||||
|             a:focusableInTouchMode="false" | ||||
|             a:layout_gravity="top|end" /> | ||||
|     </FrameLayout> | ||||
| </FrameLayout> | ||||
|   | ||||
| @@ -26,9 +26,4 @@ | ||||
|     android:id="@id/cpp_button_copy" | ||||
|     style="?attr/cpp_button_style_control" | ||||
|     xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|     android:src="@drawable/ic_content_copy_white_48dp" | ||||
|     app:directionTextScale="@dimen/cpp_direction_text_scale_units" | ||||
|     app:directionTextDown="bin" | ||||
|     app:directionTextLeft="hex" | ||||
|     app:directionTextUp="dec"/> | ||||
|     android:src="@drawable/ic_content_copy_white_48dp" /> | ||||
| @@ -26,8 +26,4 @@ | ||||
|     android:id="@id/cpp_button_paste" | ||||
|     style="?attr/cpp_button_style_control" | ||||
|     xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     xmlns:app="http://schemas.android.com/apk/res-auto" | ||||
|     app:directionTextScale="@dimen/cpp_direction_text_scale_units" | ||||
|     android:src="@drawable/ic_content_paste_white_48dp" | ||||
|     app:directionTextDown="rad" | ||||
|     app:directionTextUp="deg"/> | ||||
|     android:src="@drawable/ic_content_paste_white_48dp" /> | ||||
| @@ -24,4 +24,6 @@ | ||||
| <org.solovyev.android.calculator.EditorView | ||||
|     a:id="@+id/calculator_editor" | ||||
|     style="@style/CppText.Editor" | ||||
|     xmlns:a="http://schemas.android.com/apk/res/android"/> | ||||
|     xmlns:a="http://schemas.android.com/apk/res/android" | ||||
|     a:layout_marginEnd="16dp" | ||||
|     a:layout_marginRight="16dp" /> | ||||
| @@ -6,7 +6,7 @@ | ||||
|   ~ or visit http://se.solovyev.org | ||||
|   --> | ||||
|  | ||||
| <org.solovyev.android.calculator.DisplayView a:id="@+id/calculator_display" | ||||
| <org.solovyev.android.calculator.DisplayView | ||||
|     a:id="@+id/calculator_display" | ||||
|     style="@style/CppText.Display.Onscreen" | ||||
|     xmlns:a="http://schemas.android.com/apk/res/android" | ||||
|     a:padding="@dimen/cpp_display_padding" /> | ||||
|     xmlns:a="http://schemas.android.com/apk/res/android" /> | ||||
| @@ -6,7 +6,7 @@ | ||||
|   ~ or visit http://se.solovyev.org | ||||
|   --> | ||||
|  | ||||
| <org.solovyev.android.calculator.DisplayView a:id="@+id/calculator_display" | ||||
| <org.solovyev.android.calculator.DisplayView | ||||
|     a:id="@+id/calculator_display" | ||||
|     style="@style/CppText.Display.Onscreen.Light" | ||||
|     xmlns:a="http://schemas.android.com/apk/res/android" | ||||
|     a:padding="@dimen/cpp_display_padding" /> | ||||
|     xmlns:a="http://schemas.android.com/apk/res/android" /> | ||||
| @@ -6,10 +6,8 @@ | ||||
|   ~ or visit http://se.solovyev.org | ||||
|   --> | ||||
|  | ||||
| <TextView | ||||
|     xmlns:a="http://schemas.android.com/apk/res/android" | ||||
|     a:id="@+id/calculator_display" | ||||
| <TextView a:id="@+id/calculator_display" | ||||
|     style="@style/CppText.Display.Widget" | ||||
|     a:padding="@dimen/cpp_display_padding" | ||||
|     xmlns:a="http://schemas.android.com/apk/res/android" | ||||
|     a:scrollbars="vertical" | ||||
|     a:textIsSelectable="true" /> | ||||
| @@ -6,10 +6,8 @@ | ||||
|   ~ or visit http://se.solovyev.org | ||||
|   --> | ||||
|  | ||||
| <TextView | ||||
|     xmlns:a="http://schemas.android.com/apk/res/android" | ||||
|     a:id="@+id/calculator_display" | ||||
| <TextView a:id="@+id/calculator_display" | ||||
|     style="@style/CppText.Display.Widget.Light" | ||||
|     a:padding="@dimen/cpp_display_padding" | ||||
|     xmlns:a="http://schemas.android.com/apk/res/android" | ||||
|     a:scrollbars="vertical" | ||||
|     a:textIsSelectable="true" /> | ||||
| @@ -38,7 +38,6 @@ | ||||
|             a:layout_width="0dp" | ||||
|             a:layout_height="wrap_content" | ||||
|             a:layout_weight="2" | ||||
|             a:padding="@dimen/cpp_display_padding" | ||||
|             a:scrollbars="vertical" | ||||
|             a:textIsSelectable="true" | ||||
|             a:textSize="@dimen/cpp_widget_display_text_size_collapsed" /> | ||||
|   | ||||
| @@ -5,7 +5,75 @@ | ||||
|     <item | ||||
|         android:id="@+id/menu_mode" | ||||
|         android:title="@string/cpp_mode" | ||||
|         app:actionProviderClass="org.solovyev.android.calculator.MainMenu$ViewProvider" | ||||
|         app:showAsAction="never"> | ||||
|         <menu> | ||||
|             <item | ||||
|                 android:icon="@drawable/ic_chevron_left_24dp" | ||||
|                 android:title="@string/cpp_mode" | ||||
|                 app:showAsAction="never" /> | ||||
|             <item | ||||
|                 android:title="" | ||||
|                 app:actionViewClass="org.solovyev.android.widget.menu.MenuItemDivider" | ||||
|                 app:showAsAction="never" /> | ||||
|             <item | ||||
|                 android:id="@+id/menu_mode_engineer" | ||||
|                 android:title="@string/cpp_wizard_mode_engineer" /> | ||||
|             <item | ||||
|                 android:id="@+id/menu_mode_simple" | ||||
|                 android:title="@string/cpp_wizard_mode_simple" /> | ||||
|         </menu> | ||||
|     </item> | ||||
|  | ||||
|     <item | ||||
|         android:id="@+id/menu_angle_units" | ||||
|         android:title="@string/cpp_angles" | ||||
|         app:showAsAction="never"> | ||||
|         <menu> | ||||
|             <item | ||||
|                 android:icon="@drawable/ic_chevron_left_24dp" | ||||
|                 android:title="@string/cpp_angles" | ||||
|                 app:showAsAction="never" /> | ||||
|             <item | ||||
|                 android:title="" | ||||
|                 app:actionViewClass="org.solovyev.android.widget.menu.MenuItemDivider" | ||||
|                 app:showAsAction="never" /> | ||||
|             <item | ||||
|                 android:id="@+id/menu_au_deg" | ||||
|                 android:title="@string/p_deg" /> | ||||
|             <item | ||||
|                 android:id="@+id/menu_au_rad" | ||||
|                 android:title="@string/p_rad" /> | ||||
|         </menu> | ||||
|     </item> | ||||
|  | ||||
|     <item | ||||
|         android:id="@+id/menu_numeral_base" | ||||
|         android:title="@string/cpp_radix" | ||||
|         app:showAsAction="never"> | ||||
|         <menu> | ||||
|             <item | ||||
|                 android:icon="@drawable/ic_chevron_left_24dp" | ||||
|                 android:title="@string/cpp_radix" | ||||
|                 app:showAsAction="never" /> | ||||
|             <item | ||||
|                 android:title="" | ||||
|                 app:actionViewClass="org.solovyev.android.widget.menu.MenuItemDivider" | ||||
|                 app:showAsAction="never" /> | ||||
|             <item | ||||
|                 android:id="@+id/menu_nb_bin" | ||||
|                 android:title="@string/p_bin" /> | ||||
|             <item | ||||
|                 android:id="@+id/menu_nb_dec" | ||||
|                 android:title="@string/p_dec" /> | ||||
|             <item | ||||
|                 android:id="@+id/menu_nb_hex" | ||||
|                 android:title="@string/p_hex" /> | ||||
|         </menu> | ||||
|     </item> | ||||
|  | ||||
|     <item | ||||
|         android:title="" | ||||
|         app:actionViewClass="org.solovyev.android.widget.menu.MenuItemDivider" | ||||
|         app:showAsAction="never" /> | ||||
|  | ||||
|     <item | ||||
|   | ||||
| @@ -143,4 +143,6 @@ | ||||
|   <string name="cpp_fn_parameter">Параметр</string> | ||||
|   <string name="cpp_fn_duplicate_parameter">Параметр с таким именем уже существует</string> | ||||
|   <string name="cpp_invalid_name">Имя содержит недопустимые символы</string> | ||||
|     <string name="cpp_angles">Углы</string> | ||||
|     <string name="cpp_radix">Система</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -24,9 +24,6 @@ | ||||
|     <dimen name="cpp_onscreen_display_text_size">20sp</dimen> | ||||
|     <dimen name="cpp_onscreen_header_button_text_size">10dp</dimen> | ||||
|  | ||||
|     <!--only for not multipane--> | ||||
|     <dimen name="cpp_editor_padding">5dp</dimen> | ||||
|     <dimen name="cpp_display_padding">3dp</dimen> | ||||
|     <dimen name="cpp_display_padding_side">10dp</dimen> | ||||
|  | ||||
|     <dimen name="cpp_widget_keyboard_button_text_size">20dp</dimen> | ||||
|   | ||||
| @@ -67,7 +67,10 @@ | ||||
|         <item name="android:textColor">?attr/cpp_text_color</item> | ||||
|         <item name="android:inputType">textMultiLine|textNoSuggestions</item> | ||||
|         <item name="android:scrollbars">vertical</item> | ||||
|         <item name="android:padding">@dimen/cpp_editor_padding</item> | ||||
|         <item name="android:paddingRight">3dp</item> | ||||
|         <item name="android:paddingLeft">3dp</item> | ||||
|         <item name="android:paddingTop">3dp</item> | ||||
|         <item name="android:paddingBottom">3dp</item> | ||||
|     </style> | ||||
|  | ||||
|     <style name="CppText.Display" parent="CppText"> | ||||
| @@ -78,10 +81,10 @@ | ||||
|         <item name="android:textSize">@dimen/cpp_display_text_size</item> | ||||
|         <item name="android:scrollHorizontally">false</item> | ||||
|         <item name="android:scrollbars">none</item> | ||||
|         <item name="android:paddingRight">@dimen/cpp_display_padding</item> | ||||
|         <item name="android:paddingLeft">@dimen/cpp_display_padding</item> | ||||
|         <item name="android:paddingTop">@dimen/cpp_display_padding</item> | ||||
|         <item name="android:paddingBottom">@dimen/cpp_display_padding</item> | ||||
|         <item name="android:paddingRight">3dp</item> | ||||
|         <item name="android:paddingLeft">3dp</item> | ||||
|         <item name="android:paddingTop">3dp</item> | ||||
|         <item name="android:paddingBottom">3dp</item> | ||||
|     </style> | ||||
|  | ||||
|     <style name="CppImageButton"> | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <resources> | ||||
|     <string name="cpp_kb_variables" translatable="false">π…</string> | ||||
|     <string name="cpp_kb_variables" translatable="false">π</string> | ||||
|     <string name="cpp_kb_functions" translatable="false">ƒ</string> | ||||
|     <string name="cpp_kb_operators" translatable="false">∂</string> | ||||
|     <string name="cpp_kb_undo" translatable="false">↶</string> | ||||
|   | ||||
| @@ -122,4 +122,6 @@ | ||||
|     <string name="cpp_new_in_version">New in %1$s version</string> | ||||
|     <string name="cpp_release_notes_choose_theme">Do you want to try new Material themes? Choose them from the list:</string> | ||||
|     <string name="cpp_system_language">System language</string> | ||||
|     <string name="cpp_angles">Angles</string> | ||||
|     <string name="cpp_radix">Radix</string> | ||||
| </resources> | ||||
|   | ||||
| @@ -41,6 +41,7 @@ | ||||
|         <item name="cpp_toolbar_style">@style/CppToolbar</item> | ||||
|  | ||||
|         <item name="android:listDivider">@drawable/divider_dark</item> | ||||
|         <item name="actionOverflowMenuStyle">@style/Cpp.Widget.AppCompat.PopupMenu.Overflow</item> | ||||
|     </style> | ||||
|  | ||||
|     <style name="Cpp.Theme.Translucent" parent="@style/Theme.AppCompat.Dialog"> | ||||
| @@ -97,6 +98,7 @@ | ||||
|         <item name="cpp_toolbar_style">@style/CppToolbar.Light</item> | ||||
|  | ||||
|         <item name="android:listDivider">@drawable/divider</item> | ||||
|         <item name="actionOverflowMenuStyle">@style/Cpp.Widget.AppCompat.Light.PopupMenu.Overflow</item> | ||||
|     </style> | ||||
|  | ||||
|     <style name="Cpp.Theme.Light.Dialog" parent="@style/Theme.AppCompat.Light.DialogWhenLarge"> | ||||
| @@ -147,4 +149,12 @@ | ||||
|         <item name="cpp_wizard_button_bg">@color/cpp_wizard_button_selector_light</item> | ||||
|     </style> | ||||
|  | ||||
|     <style name="Cpp.Widget.AppCompat.PopupMenu.Overflow" parent="Widget.AppCompat.PopupMenu.Overflow"> | ||||
|         <item name="android:dropDownVerticalOffset">4dip</item> | ||||
|     </style> | ||||
|  | ||||
|     <style name="Cpp.Widget.AppCompat.Light.PopupMenu.Overflow" parent="Widget.AppCompat.Light.PopupMenu.Overflow"> | ||||
|         <item name="android:dropDownVerticalOffset">4dip</item> | ||||
|     </style> | ||||
|  | ||||
| </resources> | ||||
| @@ -50,13 +50,6 @@ | ||||
|         a:summary="@string/c_calc_grouping_separator_summary" | ||||
|         a:title="@string/c_calc_grouping_separator" /> | ||||
|  | ||||
|     <ListPreference | ||||
|         a:entries="@array/p_angle_units_names" | ||||
|         a:entryValues="@array/p_angle_units" | ||||
|         a:key="preferred_angle_units" | ||||
|         a:summary="@string/p_preferred_angle_units_summary" | ||||
|         a:title="@string/p_preferred_angle_units_title" /> | ||||
|  | ||||
|     <ListPreference | ||||
|         a:entries="@array/p_angle_units_names" | ||||
|         a:entryValues="@array/p_angle_units" | ||||
| @@ -64,13 +57,6 @@ | ||||
|         a:summary="@string/c_angle_units_summary" | ||||
|         a:title="@string/c_calc_angle_units" /> | ||||
|  | ||||
|     <ListPreference | ||||
|         a:entries="@array/p_numeral_bases_names" | ||||
|         a:entryValues="@array/p_numeral_bases" | ||||
|         a:key="preferred_numeral_base" | ||||
|         a:summary="@string/p_preferred_numeral_base_summary" | ||||
|         a:title="@string/p_preferred_numeral_base_title" /> | ||||
|  | ||||
|     <ListPreference | ||||
|         a:entries="@array/p_numeral_bases_names" | ||||
|         a:entryValues="@array/p_numeral_bases" | ||||
|   | ||||
| @@ -26,7 +26,6 @@ public abstract class BaseCalculatorTest { | ||||
|         engine = Tests.makeEngine(); | ||||
|         engine.variablesRegistry.bus = bus; | ||||
|         calculator.engine = engine; | ||||
|         calculator.preferredPreferences = mock(PreferredPreferences.class); | ||||
|         final ToJsclTextProcessor processor = new ToJsclTextProcessor(); | ||||
|         processor.engine = engine; | ||||
|         calculator.preprocessor = processor; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 serso
					serso