diff --git a/app/src/main/java/org/solovyev/android/calculator/AppComponent.java b/app/src/main/java/org/solovyev/android/calculator/AppComponent.java
index 20d23489..0bb90f2a 100644
--- a/app/src/main/java/org/solovyev/android/calculator/AppComponent.java
+++ b/app/src/main/java/org/solovyev/android/calculator/AppComponent.java
@@ -70,4 +70,5 @@ public interface AppComponent {
void inject(PreferencesFragment fragment);
void inject(WizardFragment fragment);
void inject(FloatingCalculatorBroadcastReceiver receiver);
+ void inject(MainMenu.ViewProvider viewProvider);
}
diff --git a/app/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java b/app/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java
index 61df72cf..e4e16a1a 100644
--- a/app/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java
+++ b/app/src/main/java/org/solovyev/android/calculator/CalculatorActivity.java
@@ -26,14 +26,13 @@ import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
-import android.support.v7.widget.Toolbar;
+import android.support.v7.widget.PopupMenu;
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 butterknife.ButterKnife;
import org.solovyev.android.calculator.converter.ConverterFragment;
import org.solovyev.android.calculator.history.History;
import org.solovyev.android.calculator.keyboard.PartialKeyboardUi;
@@ -42,8 +41,10 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.inject.Inject;
-public class CalculatorActivity extends BaseActivity implements Toolbar.OnMenuItemClickListener {
+public class CalculatorActivity extends BaseActivity implements View.OnClickListener, PopupMenu.OnMenuItemClickListener {
+ @Nonnull
+ private final MainMenu mainMenu = new MainMenu(this);
@Inject
PreferredPreferences preferredPreferences;
@Inject
@@ -59,10 +60,10 @@ public class CalculatorActivity extends BaseActivity implements Toolbar.OnMenuIt
@Nullable
@Bind(R.id.partial_keyboard)
View partialKeyboard;
- @Bind(R.id.toolbar)
- Toolbar toolbar;
@Bind(R.id.editor)
FrameLayout editor;
+ @Bind(R.id.main_menu)
+ ImageButton mainMenuButton;
private boolean useBackAsPrevious;
public CalculatorActivity() {
@@ -73,8 +74,6 @@ public class CalculatorActivity extends BaseActivity implements Toolbar.OnMenuIt
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- ButterKnife.bind(this);
-
if (savedInstanceState == null) {
final FragmentManager fm = getSupportFragmentManager();
final FragmentTransaction t = fm.beginTransaction();
@@ -88,9 +87,7 @@ public class CalculatorActivity extends BaseActivity implements Toolbar.OnMenuIt
partialKeyboardUi.onCreateView(this, partialKeyboard);
}
- toolbar.inflateMenu(R.menu.main);
- toolbar.setOnMenuItemClickListener(this);
- updateModeMenuItem();
+ mainMenuButton.setOnClickListener(this);
useBackAsPrevious = Preferences.Gui.useBackAsPrevious.getPreference(preferences);
if (savedInstanceState == null) {
@@ -100,13 +97,6 @@ public class CalculatorActivity extends BaseActivity implements Toolbar.OnMenuIt
preferredPreferences.check(this, false);
}
- private void updateModeMenuItem() {
- final Menu menu = toolbar.getMenu();
- final MenuItem modeMenuItem = menu.findItem(R.id.menu_mode);
- final String modeName = getString(getActivityMode().name);
- modeMenuItem.setTitle(getString(R.string.cpp_mode) + ": " + modeName);
- }
-
@Override
protected void inject(@Nonnull AppComponent component) {
super.inject(component);
@@ -169,15 +159,24 @@ public class CalculatorActivity extends BaseActivity implements Toolbar.OnMenuIt
case R.id.menu_about:
launcher.showAbout();
return true;
- case R.id.menu_mode_engineer:
+/* 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 true;*/
}
return false;
}
+
+ @Override
+ public void onClick(View v) {
+ switch (v.getId()) {
+ case R.id.main_menu:
+ mainMenu.toggle();
+ break;
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/org/solovyev/android/calculator/MainMenu.java b/app/src/main/java/org/solovyev/android/calculator/MainMenu.java
new file mode 100644
index 00000000..119b4547
--- /dev/null
+++ b/app/src/main/java/org/solovyev/android/calculator/MainMenu.java
@@ -0,0 +1,94 @@
+package org.solovyev.android.calculator;
+
+import android.annotation.SuppressLint;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.support.annotation.NonNull;
+import android.support.v4.view.ActionProvider;
+import android.support.v7.view.menu.ListMenuItemView;
+import android.support.v7.view.menu.MenuItemImpl;
+import android.view.LayoutInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+import org.solovyev.android.Check;
+import org.solovyev.android.widget.menu.CustomPopupMenu;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.inject.Inject;
+
+final class MainMenu {
+
+ @NonNull
+ private CalculatorActivity activity;
+ @Nullable
+ private CustomPopupMenu popup;
+
+ public MainMenu(@Nonnull CalculatorActivity activity) {
+ this.activity = activity;
+ }
+
+ public void toggle() {
+ if (popup == null) {
+ popup = new CustomPopupMenu(activity, activity.mainMenuButton);
+ popup.inflate(R.menu.main);
+ final int menuButtonHeight = activity.mainMenuButton.getLayoutParams().height;
+ Check.isTrue(menuButtonHeight > 0);
+ popup.setVerticalOffset(menuButtonHeight);
+ popup.setOnMenuItemClickListener(activity);
+ }
+ if (popup.isShowing()) {
+ popup.dismiss();
+ } else {
+ popup.show();
+ }
+ }
+
+ public static final class ViewProvider extends ActionProvider {
+
+ @Nonnull
+ private final LayoutInflater inflater;
+
+ @Inject
+ SharedPreferences preferences;
+
+ public ViewProvider(Context context) {
+ super(context);
+ inflater = LayoutInflater.from(context);
+ App.cast(context).getComponent().inject(this);
+ }
+
+ @Override
+ public View onCreateActionView() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public View onCreateActionView(MenuItem menuItem) {
+ switch (menuItem.getItemId()) {
+ case R.id.menu_mode:
+ return makeModeView(menuItem);
+ }
+ throw new IllegalArgumentException("Can't create a view for menu item: " + menuItem);
+ }
+
+ @Nonnull
+ private View makeModeView(@Nonnull MenuItem menuItem) {
+ final ViewGroup view = makeDefaultView(menuItem);
+ final TextView subtitle = (TextView) view.findViewById(R.id.subtitle);
+ final Preferences.Gui.Mode mode = Preferences.Gui.mode.getPreference(preferences);
+ subtitle.setText(getContext().getString(mode.name));
+ return view;
+ }
+
+ @SuppressLint("InflateParams")
+ private ViewGroup makeDefaultView(@Nonnull MenuItem menuItem) {
+ final ViewGroup view = (ViewGroup) inflater.inflate(R.layout.popup_menu_item_layout, null);
+ final ListMenuItemView listItemView = (ListMenuItemView) view.findViewById(R.id.menu_list_item_view);
+ listItemView.initialize((MenuItemImpl) menuItem, 0);
+ return view;
+ }
+ }
+}
diff --git a/app/src/main/java/org/solovyev/android/calculator/keyboard/KeyboardUi.java b/app/src/main/java/org/solovyev/android/calculator/keyboard/KeyboardUi.java
index a71e717a..51dde3bd 100644
--- a/app/src/main/java/org/solovyev/android/calculator/keyboard/KeyboardUi.java
+++ b/app/src/main/java/org/solovyev/android/calculator/keyboard/KeyboardUi.java
@@ -85,8 +85,10 @@ public class KeyboardUi extends BaseKeyboardUi {
DirectionDragButton periodButton;
@Bind(R.id.cpp_button_round_brackets)
DirectionDragButton bracketsButton;
+ @Nullable
@Bind(R.id.cpp_button_copy)
NumeralBasesButton copyButton;
+ @Nullable
@Bind(R.id.cpp_button_paste)
AngleUnitsButton pasteButton;
@Nullable
@@ -144,10 +146,14 @@ public class KeyboardUi extends BaseKeyboardUi {
prepareButton(button8);
prepareButton(button9);
- prepareButton(copyButton);
- copyButton.setNumeralBase(numeralBase.getPreference(preferences));
- prepareButton(pasteButton);
- pasteButton.setAngleUnit(angleUnit.getPreference(preferences));
+ if (copyButton != null) {
+ prepareButton(copyButton);
+ copyButton.setNumeralBase(numeralBase.getPreference(preferences));
+ }
+ if (pasteButton != null) {
+ prepareButton(pasteButton);
+ pasteButton.setAngleUnit(angleUnit.getPreference(preferences));
+ }
prepareButton(likeButton);
prepareButton(memoryButton);
@@ -179,12 +185,14 @@ public class KeyboardUi extends BaseKeyboardUi {
@Override
public void onSharedPreferenceChanged(SharedPreferences preferences, String key) {
super.onSharedPreferenceChanged(preferences, key);
- if (angleUnit.isSameKey(key)) {
+ if (angleUnit.isSameKey(key) && pasteButton != null) {
pasteButton.setAngleUnit(angleUnit.getPreference(preferences));
}
if (numeralBase.isSameKey(key)) {
toggleNumericDigits();
- copyButton.setNumeralBase(numeralBase.getPreference(preferences));
+ if (copyButton != null) {
+ copyButton.setNumeralBase(numeralBase.getPreference(preferences));
+ }
}
if (multiplicationSign.isSameKey(key)) {
multiplicationButton.setText(multiplicationSign.getPreference(preferences));
diff --git a/app/src/main/java/org/solovyev/android/widget/menu/CustomPopupMenu.java b/app/src/main/java/org/solovyev/android/widget/menu/CustomPopupMenu.java
index 41027687..b1189966 100644
--- a/app/src/main/java/org/solovyev/android/widget/menu/CustomPopupMenu.java
+++ b/app/src/main/java/org/solovyev/android/widget/menu/CustomPopupMenu.java
@@ -25,6 +25,7 @@ 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;
+import android.support.v7.widget.PopupMenu;
import android.view.*;
/**
@@ -40,8 +41,8 @@ public class CustomPopupMenu implements MenuBuilder.Callback, MenuPresenter.Call
private MenuBuilder mMenu;
private View mAnchor;
private CustomPopupMenuHelper mPopup;
- private OnMenuItemClickListener mMenuItemClickListener;
- private OnDismissListener mDismissListener;
+ private PopupMenu.OnMenuItemClickListener mMenuItemClickListener;
+ private PopupMenu.OnDismissListener mDismissListener;
private View.OnTouchListener mDragListener;
/**
@@ -119,6 +120,22 @@ 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);
+ }
+
/**
* Returns an {@link android.view.View.OnTouchListener} that can be added to the anchor view
* to implement drag-to-open behavior.
@@ -208,12 +225,19 @@ public class CustomPopupMenu implements MenuBuilder.Callback, MenuPresenter.Call
mPopup.dismiss();
}
+ /**
+ * @return {@code true} if the popup is currently showing, {@code false} otherwise.
+ */
+ public boolean isShowing() {
+ return mPopup.isShowing();
+ }
+
/**
* Set a listener that will be notified when the user selects an item from the menu.
*
* @param listener Listener to notify
*/
- public void setOnMenuItemClickListener(OnMenuItemClickListener listener) {
+ public void setOnMenuItemClickListener(PopupMenu.OnMenuItemClickListener listener) {
mMenuItemClickListener = listener;
}
@@ -222,7 +246,7 @@ public class CustomPopupMenu implements MenuBuilder.Callback, MenuPresenter.Call
*
* @param listener Listener to notify
*/
- public void setOnDismissListener(OnDismissListener listener) {
+ public void setOnDismissListener(PopupMenu.OnDismissListener listener) {
mDismissListener = listener;
}
@@ -235,7 +259,7 @@ public class CustomPopupMenu implements MenuBuilder.Callback, MenuPresenter.Call
public void onCloseMenu(MenuBuilder menu, boolean allMenusAreClosing) {
if (mDismissListener != null) {
- mDismissListener.onDismiss(this);
+ mDismissListener.onDismiss(null);
}
}
@@ -256,31 +280,4 @@ public class CustomPopupMenu implements MenuBuilder.Callback, MenuPresenter.Call
public void onMenuModeChange(MenuBuilder menu) {
}
-
- /**
- * Callback interface used to notify the application that the menu has closed.
- */
- public interface OnDismissListener {
- /**
- * Called when the associated menu has been dismissed.
- *
- * @param menu The PopupMenu that was dismissed.
- */
- void onDismiss(CustomPopupMenu menu);
- }
-
- /**
- * Interface responsible for receiving menu item click events if the items themselves
- * do not have individual item click listeners.
- */
- public interface OnMenuItemClickListener {
- /**
- * This method will be invoked when a menu item is clicked if the item itself did
- * not already handle the event.
- *
- * @param item {@link MenuItem} that was clicked
- * @return true
if the event was handled, false
otherwise.
- */
- boolean onMenuItemClick(MenuItem item);
- }
}
\ No newline at end of file
diff --git a/app/src/main/java/org/solovyev/android/widget/menu/CustomPopupMenuHelper.java b/app/src/main/java/org/solovyev/android/widget/menu/CustomPopupMenuHelper.java
index 4d5f14c7..7e8fb1d2 100644
--- a/app/src/main/java/org/solovyev/android/widget/menu/CustomPopupMenuHelper.java
+++ b/app/src/main/java/org/solovyev/android/widget/menu/CustomPopupMenuHelper.java
@@ -20,6 +20,8 @@ import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.os.Parcelable;
+import android.support.v4.view.ActionProvider;
+import android.support.v4.view.MenuItemCompat;
import android.support.v7.appcompat.R;
import android.support.v7.view.menu.*;
import android.support.v7.widget.ListPopupWindow;
@@ -27,6 +29,7 @@ import android.view.*;
import android.view.View.MeasureSpec;
import android.widget.*;
+import javax.annotation.Nonnull;
import java.util.ArrayList;
/**
@@ -38,6 +41,9 @@ public class CustomPopupMenuHelper implements AdapterView.OnItemClickListener, V
ViewTreeObserver.OnGlobalLayoutListener, PopupWindow.OnDismissListener,
MenuPresenter {
+ private static final int DEFAULT_VIEW_TAG_KEY = org.solovyev.android.calculator.R.id.cpm_default_view_tag_key;
+ private static final Object DEFAULT_VIEW_TAG = new Object();
+
private final Context mContext;
private final LayoutInflater mInflater;
private final MenuBuilder mMenu;
@@ -63,7 +69,9 @@ public class CustomPopupMenuHelper implements AdapterView.OnItemClickListener, V
*/
private int mContentWidth;
- private int mDropDownGravity = Gravity.NO_GRAVITY;
+ 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);
@@ -107,11 +115,27 @@ public class CustomPopupMenuHelper implements AdapterView.OnItemClickListener, V
}
public int getGravity() {
- return mDropDownGravity;
+ return mGravity;
}
public void setGravity(int gravity) {
- mDropDownGravity = gravity;
+ mGravity = gravity;
+ }
+
+ public void setVerticalOffset(int offset) {
+ mVerticalOffset = offset;
+ }
+
+ public int getVerticalOffset() {
+ return mVerticalOffset;
+ }
+
+ public void setHorizontalOffset(int offset) {
+ mHorizontalOffset = offset;
+ }
+
+ public int getHorizontalOffset() {
+ return mHorizontalOffset;
}
public void show() {
@@ -137,7 +161,9 @@ public class CustomPopupMenuHelper implements AdapterView.OnItemClickListener, V
mTreeObserver = anchor.getViewTreeObserver(); // Refresh to latest
if (addGlobalListener) mTreeObserver.addOnGlobalLayoutListener(this);
mPopup.setAnchorView(anchor);
- mPopup.setDropDownGravity(mDropDownGravity);
+ mPopup.setDropDownGravity(mGravity);
+ mPopup.setHorizontalOffset(mHorizontalOffset);
+ mPopup.setVerticalOffset(mVerticalOffset);
} else {
return false;
}
@@ -361,15 +387,31 @@ public class CustomPopupMenuHelper implements AdapterView.OnItemClickListener, V
}
public View getView(int position, View convertView, ViewGroup parent) {
- if (convertView == null) {
+ final MenuItemImpl item = getItem(position);
+ final ActionProvider actionProvider = MenuItemCompat.getActionProvider(item);
+ if (actionProvider != null) {
+ return actionProvider.onCreateActionView(item);
+ }
+ final View actionView = MenuItemCompat.getActionView(item);
+ if (actionView != null) {
+ ((MenuView.ItemView) actionView).initialize(item, 0);
+ return actionView;
+ }
+ return getDefaultView(item, convertView, parent);
+ }
+
+ @Nonnull
+ private View getDefaultView(MenuItemImpl item, View convertView, ViewGroup parent) {
+ 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);
}
- MenuView.ItemView itemView = (MenuView.ItemView) convertView;
+ final MenuView.ItemView itemView = (MenuView.ItemView) convertView;
if (mForceShowIcon) {
((ListMenuItemView) convertView).setForceShowIcon(true);
}
- itemView.initialize(getItem(position), 0);
+ itemView.initialize(item, 0);
return convertView;
}
diff --git a/app/src/main/res/layout-land/activity_main.xml b/app/src/main/res/layout-land/activity_main.xml
index ae54929d..0a2d67d9 100644
--- a/app/src/main/res/layout-land/activity_main.xml
+++ b/app/src/main/res/layout-land/activity_main.xml
@@ -27,7 +27,7 @@
xmlns:a="http://schemas.android.com/apk/res/android"
a:orientation="vertical">
-
+
-
+
-
+
@@ -84,9 +84,9 @@
a:baselineAligned="false"
a:orientation="horizontal">
-
+
-
+
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 345dcf70..11e6e204 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -30,7 +30,7 @@
a:layout_height="match_parent"
a:orientation="vertical">
-
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_main_editor_with_toolbar.xml b/app/src/main/res/layout/activity_main_editor_with_toolbar.xml
deleted file mode 100644
index 1b5a959b..00000000
--- a/app/src/main/res/layout/activity_main_editor_with_toolbar.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-
-
-
-
-
-
-
diff --git a/app/src/main/res/layout/cpp_app_keyboard.xml b/app/src/main/res/layout/cpp_app_keyboard.xml
index 82df8998..f0b54318 100644
--- a/app/src/main/res/layout/cpp_app_keyboard.xml
+++ b/app/src/main/res/layout/cpp_app_keyboard.xml
@@ -32,9 +32,9 @@
a:layout_height="0dp"
a:layout_weight="1">
-
+
-
+
@@ -75,7 +75,7 @@
-
+
@@ -92,7 +92,7 @@
-
+
diff --git a/app/src/main/res/layout/popup_menu_item_layout.xml b/app/src/main/res/layout/popup_menu_item_layout.xml
new file mode 100644
index 00000000..7e8dc4ba
--- /dev/null
+++ b/app/src/main/res/layout/popup_menu_item_layout.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/menu/main.xml b/app/src/main/res/menu/main.xml
index 26c3105f..f13e0b2a 100644
--- a/app/src/main/res/menu/main.xml
+++ b/app/src/main/res/menu/main.xml
@@ -5,16 +5,8 @@
-
-
-
+ app:actionProviderClass="org.solovyev.android.calculator.MainMenu$ViewProvider"
+ app:showAsAction="never" />
+
+
\ No newline at end of file