diff --git a/app/src/main/java/org/solovyev/android/calculator/BaseFragment.java b/app/src/main/java/org/solovyev/android/calculator/BaseFragment.java index 0cc5e44f..8b537952 100644 --- a/app/src/main/java/org/solovyev/android/calculator/BaseFragment.java +++ b/app/src/main/java/org/solovyev/android/calculator/BaseFragment.java @@ -64,7 +64,7 @@ public abstract class BaseFragment extends Fragment { } @Nonnull - protected static MenuItem addMenu(@Nonnull ContextMenu menu, @StringRes int label, @Nonnull MenuItem.OnMenuItemClickListener listener) { + public static MenuItem addMenu(@Nonnull ContextMenu menu, @StringRes int label, @Nonnull MenuItem.OnMenuItemClickListener listener) { return menu.add(NONE, label, NONE, label).setOnMenuItemClickListener(listener); } } diff --git a/app/src/main/java/org/solovyev/android/calculator/CalculatorDisplayMenuItem.java b/app/src/main/java/org/solovyev/android/calculator/CalculatorDisplayMenuItem.java deleted file mode 100644 index 2bbaf3ae..00000000 --- a/app/src/main/java/org/solovyev/android/calculator/CalculatorDisplayMenuItem.java +++ /dev/null @@ -1,138 +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.content.Context; - -import org.solovyev.android.calculator.jscl.JsclOperation; -import org.solovyev.android.calculator.plot.CalculatorPlotter; -import org.solovyev.android.calculator.view.NumeralBaseConverterDialog; -import org.solovyev.android.menu.LabeledMenuItem; - -import javax.annotation.Nonnull; - -import jscl.math.Generic; - -/** - * User: Solovyev_S - * Date: 21.09.12 - * Time: 10:55 - */ -public enum CalculatorDisplayMenuItem implements LabeledMenuItem { - - copy(R.string.c_copy) { - @Override - public void onClick(@Nonnull DisplayState data, @Nonnull Context context) { - Locator.getInstance().getKeyboard().copyButtonPressed(); - } - }, - - convert_to_bin(R.string.convert_to_bin) { - @Override - public void onClick(@Nonnull DisplayState data, @Nonnull Context context) { - ConversionMenuItem.convert_to_bin.onClick(data, context); - } - - @Override - protected boolean isItemVisibleFor(@Nonnull Generic generic, @Nonnull JsclOperation operation) { - return ConversionMenuItem.convert_to_bin.isItemVisibleFor(generic, operation); - } - }, - - convert_to_dec(R.string.convert_to_dec) { - @Override - public void onClick(@Nonnull DisplayState data, @Nonnull Context context) { - ConversionMenuItem.convert_to_dec.onClick(data, context); - } - - @Override - protected boolean isItemVisibleFor(@Nonnull Generic generic, @Nonnull JsclOperation operation) { - return ConversionMenuItem.convert_to_dec.isItemVisibleFor(generic, operation); - } - }, - - convert_to_hex(R.string.convert_to_hex) { - @Override - public void onClick(@Nonnull DisplayState data, @Nonnull Context context) { - ConversionMenuItem.convert_to_hex.onClick(data, context); - } - - @Override - protected boolean isItemVisibleFor(@Nonnull Generic generic, @Nonnull JsclOperation operation) { - return ConversionMenuItem.convert_to_hex.isItemVisibleFor(generic, operation); - } - }, - - convert(R.string.c_convert) { - @Override - public void onClick(@Nonnull DisplayState data, @Nonnull Context context) { - final Generic result = data.getResult(); - if (result != null) { - new NumeralBaseConverterDialog(result.toString()).show(context); - } - } - - @Override - protected boolean isItemVisibleFor(@Nonnull Generic generic, @Nonnull JsclOperation operation) { - return operation == JsclOperation.numeric && generic.getConstants().isEmpty(); - } - }, - - plot(R.string.c_plot) { - @Override - public void onClick(@Nonnull DisplayState data, @Nonnull Context context) { - final Generic expression = data.getResult(); - if (expression == null) throw new AssertionError(); - - final CalculatorPlotter plotter = Locator.getInstance().getPlotter(); - plotter.plot(expression); - } - - @Override - protected boolean isItemVisibleFor(@Nonnull Generic generic, @Nonnull JsclOperation operation) { - return Locator.getInstance().getPlotter().isPlotPossibleFor(generic); - } - - }; - - private final int captionId; - - CalculatorDisplayMenuItem(int captionId) { - this.captionId = captionId; - } - - public final boolean isItemVisible(@Nonnull DisplayState displayViewState) { - //noinspection ConstantConditions - return displayViewState.valid && displayViewState.getResult() != null && isItemVisibleFor(displayViewState.getResult(), displayViewState.getOperation()); - } - - protected boolean isItemVisibleFor(@Nonnull Generic generic, @Nonnull JsclOperation operation) { - return true; - } - - @Nonnull - @Override - public String getCaption(@Nonnull Context context) { - return context.getString(captionId); - } -} diff --git a/app/src/main/java/org/solovyev/android/calculator/CalculatorDisplayOnClickListener.java b/app/src/main/java/org/solovyev/android/calculator/CalculatorDisplayOnClickListener.java deleted file mode 100644 index 9f501ebe..00000000 --- a/app/src/main/java/org/solovyev/android/calculator/CalculatorDisplayOnClickListener.java +++ /dev/null @@ -1,75 +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.support.v4.app.FragmentActivity; -import android.view.View; - -import org.solovyev.android.menu.ContextMenuBuilder; -import org.solovyev.android.menu.ListContextMenu; - -import java.util.ArrayList; -import java.util.List; - -import javax.annotation.Nonnull; - -/** - * User: Solovyev_S - * Date: 21.09.12 - * Time: 10:58 - */ -public class CalculatorDisplayOnClickListener implements View.OnClickListener { - - @Nonnull - private final FragmentActivity activity; - - public CalculatorDisplayOnClickListener(@Nonnull FragmentActivity activity) { - this.activity = activity; - } - - @Override - public void onClick(View v) { - if (v instanceof DisplayView) { - final Display cd = App.getDisplay(); - - final DisplayState displayViewState = cd.getState(); - - if (displayViewState.valid) { - final List filteredMenuItems = new ArrayList(CalculatorDisplayMenuItem.values().length); - for (CalculatorDisplayMenuItem menuItem : CalculatorDisplayMenuItem.values()) { - if (menuItem.isItemVisible(displayViewState)) { - filteredMenuItems.add(menuItem); - } - } - - if (!filteredMenuItems.isEmpty()) { - ContextMenuBuilder.newInstance(activity, "display-menu", ListContextMenu.newInstance(filteredMenuItems)).build(displayViewState).show(); - } - - } else { - final String errorMessage = displayViewState.text; - Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_evaluation_error, errorMessage, activity); - } - } - } -} diff --git a/app/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java b/app/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java index 6b6f032a..e2ab559b 100644 --- a/app/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java +++ b/app/src/main/java/org/solovyev/android/calculator/CalculatorEventType.java @@ -70,17 +70,6 @@ public enum CalculatorEventType { conversion_finished, - /* - ********************************************************************** - * - * MATH ENTITIES - * - ********************************************************************** - */ - - // @Nonnull Operator - use_operator, - /* ********************************************************************** * diff --git a/app/src/main/java/org/solovyev/android/calculator/Display.java b/app/src/main/java/org/solovyev/android/calculator/Display.java index 8f773815..07547c5a 100644 --- a/app/src/main/java/org/solovyev/android/calculator/Display.java +++ b/app/src/main/java/org/solovyev/android/calculator/Display.java @@ -22,37 +22,56 @@ package org.solovyev.android.calculator; +import android.view.ContextMenu; +import android.view.MenuItem; +import android.view.View; import com.squareup.otto.Bus; - +import com.squareup.otto.Subscribe; +import dagger.Lazy; +import jscl.math.Generic; import org.solovyev.android.Check; +import org.solovyev.android.calculator.jscl.JsclOperation; +import org.solovyev.android.calculator.view.NumeralBaseConverterDialog; import javax.annotation.Nonnull; import javax.annotation.Nullable; import javax.inject.Inject; import javax.inject.Singleton; -import static org.solovyev.android.calculator.CalculatorEventType.calculation_cancelled; -import static org.solovyev.android.calculator.CalculatorEventType.calculation_failed; -import static org.solovyev.android.calculator.CalculatorEventType.calculation_result; -import static org.solovyev.android.calculator.CalculatorEventType.conversion_failed; -import static org.solovyev.android.calculator.CalculatorEventType.conversion_result; +import static org.solovyev.android.calculator.BaseFragment.addMenu; +import static org.solovyev.android.calculator.CalculatorEventType.*; @Singleton -public class Display implements CalculatorEventListener { +public class Display implements CalculatorEventListener, View.OnClickListener, View.OnCreateContextMenuListener, MenuItem.OnMenuItemClickListener { @Nonnull private final CalculatorEventHolder lastEvent; + @Nonnull + private final Bus bus; @Inject - Bus bus; + Lazy keyboard; + @Inject + Lazy clipboard; @Nullable private DisplayView view; @Nonnull private DisplayState state = DisplayState.empty(); @Inject - public Display(@Nonnull Calculator calculator) { + public Display(@Nonnull Calculator calculator, @Nonnull Bus bus) { + this.bus = bus; lastEvent = new CalculatorEventHolder(CalculatorUtils.createFirstEventDataId()); calculator.addCalculatorEventListener(this); + bus.register(this); + } + + @Subscribe + public void onCopy(@Nonnull CopyOperation o) { + if (!state.valid) { + return; + } + clipboard.get().setText(state.text); + Locator.getInstance().getNotifier().showMessage(CalculatorMessage.newInfoMessage(CalculatorMessages.result_copied)); } public void clearView(@Nonnull DisplayView view) { @@ -66,6 +85,7 @@ public class Display implements CalculatorEventListener { public void setView(@Nonnull DisplayView view) { Check.isMainThread(); this.view = view; + this.view.setOnClickListener(this); this.view.setState(state); } @@ -161,6 +181,79 @@ public class Display implements CalculatorEventListener { setState(DisplayState.createValid(displayState.getOperation(), displayState.getResult(), result, calculatorEventData.getSequenceId())); } + @Override + public void onClick(View v) { + if (state.valid) { + v.setOnCreateContextMenuListener(this); + v.showContextMenu(); + v.setOnCreateContextMenuListener(null); + } else { + Locator.getInstance().getCalculator().fireCalculatorEvent(CalculatorEventType.show_evaluation_error, state.text); + } + } + + @Override + public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { + if (!state.valid) { + return; + } + addMenu(menu, R.string.c_copy, this); + + final Generic result = state.getResult(); + final JsclOperation operation = state.getOperation(); + if (result != null) { + if (ConversionMenuItem.convert_to_bin.isItemVisibleFor(result, operation)) { + addMenu(menu, R.string.convert_to_bin, this); + } + if (ConversionMenuItem.convert_to_dec.isItemVisibleFor(result, operation)) { + addMenu(menu, R.string.convert_to_dec, this); + } + if (ConversionMenuItem.convert_to_hex.isItemVisibleFor(result, operation)) { + addMenu(menu, R.string.convert_to_hex, this); + } + if (operation == JsclOperation.numeric && result.getConstants().isEmpty()) { + addMenu(menu, R.string.c_convert, this); + } + if (Locator.getInstance().getPlotter().isPlotPossibleFor(result)) { + addMenu(menu, R.string.c_plot, this); + } + } + } + + @Override + public boolean onMenuItemClick(MenuItem item) { + final Generic result = state.getResult(); + switch (item.getItemId()) { + case R.string.c_copy: + keyboard.get().copyButtonPressed(); + return true; + case R.string.convert_to_bin: + ConversionMenuItem.convert_to_bin.onClick(state, App.getApplication()); + return true; + case R.string.convert_to_dec: + ConversionMenuItem.convert_to_dec.onClick(state, App.getApplication()); + return true; + case R.string.convert_to_hex: + ConversionMenuItem.convert_to_hex.onClick(state, App.getApplication()); + return true; + case R.string.c_convert: + if (result != null) { + new NumeralBaseConverterDialog(result.toString()).show(App.getApplication()); + } + return true; + case R.string.c_plot: + if (result != null) { + Locator.getInstance().getPlotter().plot(result); + } + return true; + default: + return false; + } + } + + public static class CopyOperation { + } + public static class ChangedEvent { @Nonnull diff --git a/app/src/main/java/org/solovyev/android/calculator/DisplayState.java b/app/src/main/java/org/solovyev/android/calculator/DisplayState.java index beaca75a..c1b3c764 100644 --- a/app/src/main/java/org/solovyev/android/calculator/DisplayState.java +++ b/app/src/main/java/org/solovyev/android/calculator/DisplayState.java @@ -25,7 +25,8 @@ package org.solovyev.android.calculator; import android.os.Parcel; import android.os.Parcelable; import android.text.TextUtils; - +import android.view.ContextMenu; +import jscl.math.Generic; import org.json.JSONException; import org.json.JSONObject; import org.solovyev.android.calculator.jscl.JsclOperation; @@ -33,9 +34,7 @@ import org.solovyev.android.calculator.jscl.JsclOperation; import javax.annotation.Nonnull; import javax.annotation.Nullable; -import jscl.math.Generic; - -public class DisplayState implements Parcelable { +public class DisplayState implements Parcelable, ContextMenu.ContextMenuInfo { public static final Creator CREATOR = new Creator() { @Override diff --git a/app/src/main/java/org/solovyev/android/calculator/DisplayView.java b/app/src/main/java/org/solovyev/android/calculator/DisplayView.java index 3377bdbb..bbf22f95 100644 --- a/app/src/main/java/org/solovyev/android/calculator/DisplayView.java +++ b/app/src/main/java/org/solovyev/android/calculator/DisplayView.java @@ -25,7 +25,6 @@ package org.solovyev.android.calculator; import android.app.Service; import android.content.Context; import android.support.annotation.NonNull; -import android.support.v4.app.FragmentActivity; import android.text.TextUtils; import android.util.AttributeSet; import android.util.TypedValue; @@ -70,7 +69,6 @@ public class DisplayView extends AutoResizeTextView { if (!layout.optimized) { setTextSize(TypedValue.COMPLEX_UNIT_SP, getResources().getDimension(R.dimen.cpp_display_text_size_mobile)); } - setOnClickListener(new CalculatorDisplayOnClickListener((FragmentActivity) context)); } @Nonnull diff --git a/app/src/main/java/org/solovyev/android/calculator/Keyboard.java b/app/src/main/java/org/solovyev/android/calculator/Keyboard.java index 6dfa3d02..a582de63 100644 --- a/app/src/main/java/org/solovyev/android/calculator/Keyboard.java +++ b/app/src/main/java/org/solovyev/android/calculator/Keyboard.java @@ -23,6 +23,8 @@ package org.solovyev.android.calculator; import android.text.TextUtils; +import com.squareup.otto.Bus; +import dagger.Lazy; import org.solovyev.android.calculator.math.MathType; import org.solovyev.common.text.Strings; @@ -40,9 +42,9 @@ public class Keyboard { @Inject Editor editor; @Inject - Display display; + Lazy clipboard; @Inject - Clipboard clipboard; + Lazy bus; @Inject public Keyboard() { @@ -112,7 +114,7 @@ public class Keyboard { } public void roundBracketsButtonPressed() { - EditorState viewState = editor.getState(); + EditorState viewState = editor.getState(); final int cursorPosition = viewState.selection; final CharSequence oldText = viewState.text; @@ -121,7 +123,7 @@ public class Keyboard { } public void pasteButtonPressed() { - final String text = clipboard.getText(); + final String text = clipboard.get().getText(); if (!TextUtils.isEmpty(text)) { editor.insert(text); } @@ -132,12 +134,7 @@ public class Keyboard { } public void copyButtonPressed() { - final DisplayState displayState = display.getState(); - if (!displayState.valid) { - return; - } - clipboard.setText(displayState.text); - Locator.getInstance().getNotifier().showMessage(CalculatorMessage.newInfoMessage(CalculatorMessages.result_copied)); + bus.get().post(new Display.CopyOperation()); } public void moveCursorLeft() {