From 8cda4424a39b5add0a65eb0a5e1ec855b7707265 Mon Sep 17 00:00:00 2001 From: serso Date: Tue, 23 Oct 2012 11:44:20 +0400 Subject: [PATCH] Multiplication button for widget --- .../android/calculator/CalculatorButtons.java | 479 ++++++++--------- .../widget/CalculatorWidgetProvider.java | 480 +++++++++--------- 2 files changed, 478 insertions(+), 481 deletions(-) diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorButtons.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorButtons.java index 27ae4778..8dfbc6a5 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorButtons.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/CalculatorButtons.java @@ -1,238 +1,241 @@ -package org.solovyev.android.calculator; - -import android.app.Activity; -import android.content.Context; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.preference.PreferenceManager; -import android.util.Log; -import android.view.MotionEvent; -import android.view.View; -import android.widget.Button; -import android.widget.Toast; -import jscl.AngleUnit; -import jscl.NumeralBase; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.AndroidUtils; -import org.solovyev.android.calculator.model.AndroidCalculatorEngine; -import org.solovyev.android.calculator.view.AngleUnitsButton; -import org.solovyev.android.calculator.view.NumeralBasesButton; -import org.solovyev.android.view.ColorButton; -import org.solovyev.android.view.drag.DragButton; -import org.solovyev.android.view.drag.DragDirection; -import org.solovyev.android.view.drag.SimpleOnDragListener; -import org.solovyev.common.math.Point2d; - -/** - * User: serso - * Date: 9/28/12 - * Time: 12:06 AM - */ -public final class CalculatorButtons { - - private CalculatorButtons () { - } - - - public static void processButtons(boolean fixMagicFlames, - @NotNull CalculatorPreferences.Gui.Theme theme, - @NotNull View root) { - if (theme.getThemeType() == CalculatorPreferences.Gui.ThemeType.metro) { - - if (fixMagicFlames) { - // for metro themes we should turn off magic flames - AndroidUtils.processViewsOfType(root, ColorButton.class, new AndroidUtils.ViewProcessor() { - @Override - public void process(@NotNull ColorButton colorButton) { - colorButton.setDrawMagicFlame(false); - } - }); - } - } - } - - static void initMultiplicationButton(@NotNull View root) { - final View multiplicationButton = root.findViewById(R.id.multiplicationButton); - if ( multiplicationButton instanceof Button) { - ((Button) multiplicationButton).setText(CalculatorLocatorImpl.getInstance().getEngine().getMultiplicationSign()); - } - } - - - - public static void toggleEqualsButton(@Nullable SharedPreferences preferences, - @NotNull Activity activity) { - preferences = preferences == null ? PreferenceManager.getDefaultSharedPreferences(activity) : preferences; - - final boolean large = AndroidUtils.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE, activity.getResources().getConfiguration()); - - if (!large) { - if (AndroidUtils.getScreenOrientation(activity) == Configuration.ORIENTATION_PORTRAIT - || !CalculatorPreferences.Gui.autoOrientation.getPreference(preferences)) { - - final DragButton equalsButton = (DragButton)activity.findViewById(R.id.equalsButton); - if (equalsButton != null) { - if (CalculatorPreferences.Gui.showEqualsButton.getPreference(preferences)) { - equalsButton.setVisibility(View.VISIBLE); - } else { - equalsButton.setVisibility(View.GONE); - } - } - } - } - } - - @Nullable - private static AndroidCalculatorDisplayView getCalculatorDisplayView() { - return (AndroidCalculatorDisplayView) CalculatorLocatorImpl.getInstance().getDisplay().getView(); - } - - /* - ********************************************************************** - * - * STATIC CLASSES - * - ********************************************************************** - */ - - static class RoundBracketsDragProcessor implements SimpleOnDragListener.DragProcessor { - @Override - public boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent) { - final boolean result; - - if (dragDirection == DragDirection.left) { - getKeyboard().roundBracketsButtonPressed(); - result = true; - } else { - result = new DigitButtonDragProcessor(getKeyboard()).processDragEvent(dragDirection, dragButton, startPoint2d, motionEvent); - } - - return result; - } - } - - @NotNull - private static CalculatorKeyboard getKeyboard() { - return CalculatorLocatorImpl.getInstance().getKeyboard(); - } - - static class VarsDragProcessor implements SimpleOnDragListener.DragProcessor { - - @NotNull - private Context context; - - VarsDragProcessor(Context context) { - this.context = context; - } - - @Override - public boolean processDragEvent(@NotNull DragDirection dragDirection, - @NotNull DragButton dragButton, - @NotNull Point2d startPoint2d, - @NotNull MotionEvent motionEvent) { - boolean result = false; - - if (dragDirection == DragDirection.up) { - CalculatorActivityLauncher.createVar(context, CalculatorLocatorImpl.getInstance().getDisplay()); - result = true; - } - - return result; - } - } - - static class AngleUnitsChanger implements SimpleOnDragListener.DragProcessor { - - @NotNull - private final DigitButtonDragProcessor processor; - - @NotNull - private final Context context; - - AngleUnitsChanger(@NotNull Context context) { - this.context = context; - this.processor = new DigitButtonDragProcessor(CalculatorLocatorImpl.getInstance().getKeyboard()); - } - - @Override - public boolean processDragEvent(@NotNull DragDirection dragDirection, - @NotNull DragButton dragButton, - @NotNull Point2d startPoint2d, - @NotNull MotionEvent motionEvent) { - boolean result = false; - - if (dragButton instanceof AngleUnitsButton) { - if (dragDirection != DragDirection.left) { - final String directionText = ((AngleUnitsButton) dragButton).getText(dragDirection); - if (directionText != null) { - try { - - final AngleUnit angleUnits = AngleUnit.valueOf(directionText); - - final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); - - final AngleUnit oldAngleUnits = AndroidCalculatorEngine.Preferences.angleUnit.getPreference(preferences); - if (oldAngleUnits != angleUnits) { - AndroidCalculatorEngine.Preferences.angleUnit.putPreference(preferences, angleUnits); - - Toast.makeText(context, context.getString(R.string.c_angle_units_changed_to, angleUnits.name()), Toast.LENGTH_LONG).show(); - } - - result = true; - } catch (IllegalArgumentException e) { - Log.d(this.getClass().getName(), "Unsupported angle units: " + directionText); - } - } - } else if (dragDirection == DragDirection.left) { - result = processor.processDragEvent(dragDirection, dragButton, startPoint2d, motionEvent); - } - } - - return result; - } - } - - static class NumeralBasesChanger implements SimpleOnDragListener.DragProcessor { - - @NotNull - private final Context context; - - NumeralBasesChanger(@NotNull Context context) { - this.context = context; - } - - @Override - public boolean processDragEvent(@NotNull DragDirection dragDirection, - @NotNull DragButton dragButton, - @NotNull Point2d startPoint2d, - @NotNull MotionEvent motionEvent) { - boolean result = false; - - if (dragButton instanceof NumeralBasesButton) { - final String directionText = ((NumeralBasesButton) dragButton).getText(dragDirection); - if (directionText != null) { - try { - - final NumeralBase numeralBase = NumeralBase.valueOf(directionText); - - final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); - - final NumeralBase oldNumeralBase = AndroidCalculatorEngine.Preferences.numeralBase.getPreference(preferences); - if (oldNumeralBase != numeralBase) { - AndroidCalculatorEngine.Preferences.numeralBase.putPreference(preferences, numeralBase); - - Toast.makeText(context, context.getString(R.string.c_numeral_base_changed_to, numeralBase.name()), Toast.LENGTH_LONG).show(); - } - - result = true; - } catch (IllegalArgumentException e) { - Log.d(this.getClass().getName(), "Unsupported numeral base: " + directionText); - } - } - } - - return result; - } - } -} +package org.solovyev.android.calculator; + +import android.app.Activity; +import android.content.Context; +import android.content.SharedPreferences; +import android.content.res.Configuration; +import android.preference.PreferenceManager; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.widget.Button; +import android.widget.RemoteViews; +import android.widget.Toast; +import jscl.AngleUnit; +import jscl.NumeralBase; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.solovyev.android.AndroidUtils; +import org.solovyev.android.calculator.model.AndroidCalculatorEngine; +import org.solovyev.android.calculator.view.AngleUnitsButton; +import org.solovyev.android.calculator.view.NumeralBasesButton; +import org.solovyev.android.view.ColorButton; +import org.solovyev.android.view.drag.DragButton; +import org.solovyev.android.view.drag.DragDirection; +import org.solovyev.android.view.drag.SimpleOnDragListener; +import org.solovyev.common.math.Point2d; + +/** + * User: serso + * Date: 9/28/12 + * Time: 12:06 AM + */ +public final class CalculatorButtons { + + private CalculatorButtons () { + } + + + public static void processButtons(boolean fixMagicFlames, + @NotNull CalculatorPreferences.Gui.Theme theme, + @NotNull View root) { + if (theme.getThemeType() == CalculatorPreferences.Gui.ThemeType.metro) { + + if (fixMagicFlames) { + // for metro themes we should turn off magic flames + AndroidUtils.processViewsOfType(root, ColorButton.class, new AndroidUtils.ViewProcessor() { + @Override + public void process(@NotNull ColorButton colorButton) { + colorButton.setDrawMagicFlame(false); + } + }); + } + } + } + + static void initMultiplicationButton(@NotNull View root) { + final View multiplicationButton = root.findViewById(R.id.multiplicationButton); + if ( multiplicationButton instanceof Button) { + ((Button) multiplicationButton).setText(CalculatorLocatorImpl.getInstance().getEngine().getMultiplicationSign()); + } + } + + public static void initMultiplicationButton(@NotNull RemoteViews views) { + views.setTextViewText(R.id.multiplicationButton, CalculatorLocatorImpl.getInstance().getEngine().getMultiplicationSign()); + } + + public static void toggleEqualsButton(@Nullable SharedPreferences preferences, + @NotNull Activity activity) { + preferences = preferences == null ? PreferenceManager.getDefaultSharedPreferences(activity) : preferences; + + final boolean large = AndroidUtils.isLayoutSizeAtLeast(Configuration.SCREENLAYOUT_SIZE_LARGE, activity.getResources().getConfiguration()); + + if (!large) { + if (AndroidUtils.getScreenOrientation(activity) == Configuration.ORIENTATION_PORTRAIT + || !CalculatorPreferences.Gui.autoOrientation.getPreference(preferences)) { + + final DragButton equalsButton = (DragButton)activity.findViewById(R.id.equalsButton); + if (equalsButton != null) { + if (CalculatorPreferences.Gui.showEqualsButton.getPreference(preferences)) { + equalsButton.setVisibility(View.VISIBLE); + } else { + equalsButton.setVisibility(View.GONE); + } + } + } + } + } + + @Nullable + private static AndroidCalculatorDisplayView getCalculatorDisplayView() { + return (AndroidCalculatorDisplayView) CalculatorLocatorImpl.getInstance().getDisplay().getView(); + } + + /* + ********************************************************************** + * + * STATIC CLASSES + * + ********************************************************************** + */ + + static class RoundBracketsDragProcessor implements SimpleOnDragListener.DragProcessor { + @Override + public boolean processDragEvent(@NotNull DragDirection dragDirection, @NotNull DragButton dragButton, @NotNull Point2d startPoint2d, @NotNull MotionEvent motionEvent) { + final boolean result; + + if (dragDirection == DragDirection.left) { + getKeyboard().roundBracketsButtonPressed(); + result = true; + } else { + result = new DigitButtonDragProcessor(getKeyboard()).processDragEvent(dragDirection, dragButton, startPoint2d, motionEvent); + } + + return result; + } + } + + @NotNull + private static CalculatorKeyboard getKeyboard() { + return CalculatorLocatorImpl.getInstance().getKeyboard(); + } + + static class VarsDragProcessor implements SimpleOnDragListener.DragProcessor { + + @NotNull + private Context context; + + VarsDragProcessor(Context context) { + this.context = context; + } + + @Override + public boolean processDragEvent(@NotNull DragDirection dragDirection, + @NotNull DragButton dragButton, + @NotNull Point2d startPoint2d, + @NotNull MotionEvent motionEvent) { + boolean result = false; + + if (dragDirection == DragDirection.up) { + CalculatorActivityLauncher.createVar(context, CalculatorLocatorImpl.getInstance().getDisplay()); + result = true; + } + + return result; + } + } + + static class AngleUnitsChanger implements SimpleOnDragListener.DragProcessor { + + @NotNull + private final DigitButtonDragProcessor processor; + + @NotNull + private final Context context; + + AngleUnitsChanger(@NotNull Context context) { + this.context = context; + this.processor = new DigitButtonDragProcessor(CalculatorLocatorImpl.getInstance().getKeyboard()); + } + + @Override + public boolean processDragEvent(@NotNull DragDirection dragDirection, + @NotNull DragButton dragButton, + @NotNull Point2d startPoint2d, + @NotNull MotionEvent motionEvent) { + boolean result = false; + + if (dragButton instanceof AngleUnitsButton) { + if (dragDirection != DragDirection.left) { + final String directionText = ((AngleUnitsButton) dragButton).getText(dragDirection); + if (directionText != null) { + try { + + final AngleUnit angleUnits = AngleUnit.valueOf(directionText); + + final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + + final AngleUnit oldAngleUnits = AndroidCalculatorEngine.Preferences.angleUnit.getPreference(preferences); + if (oldAngleUnits != angleUnits) { + AndroidCalculatorEngine.Preferences.angleUnit.putPreference(preferences, angleUnits); + + Toast.makeText(context, context.getString(R.string.c_angle_units_changed_to, angleUnits.name()), Toast.LENGTH_LONG).show(); + } + + result = true; + } catch (IllegalArgumentException e) { + Log.d(this.getClass().getName(), "Unsupported angle units: " + directionText); + } + } + } else if (dragDirection == DragDirection.left) { + result = processor.processDragEvent(dragDirection, dragButton, startPoint2d, motionEvent); + } + } + + return result; + } + } + + static class NumeralBasesChanger implements SimpleOnDragListener.DragProcessor { + + @NotNull + private final Context context; + + NumeralBasesChanger(@NotNull Context context) { + this.context = context; + } + + @Override + public boolean processDragEvent(@NotNull DragDirection dragDirection, + @NotNull DragButton dragButton, + @NotNull Point2d startPoint2d, + @NotNull MotionEvent motionEvent) { + boolean result = false; + + if (dragButton instanceof NumeralBasesButton) { + final String directionText = ((NumeralBasesButton) dragButton).getText(dragDirection); + if (directionText != null) { + try { + + final NumeralBase numeralBase = NumeralBase.valueOf(directionText); + + final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context); + + final NumeralBase oldNumeralBase = AndroidCalculatorEngine.Preferences.numeralBase.getPreference(preferences); + if (oldNumeralBase != numeralBase) { + AndroidCalculatorEngine.Preferences.numeralBase.putPreference(preferences, numeralBase); + + Toast.makeText(context, context.getString(R.string.c_numeral_base_changed_to, numeralBase.name()), Toast.LENGTH_LONG).show(); + } + + result = true; + } catch (IllegalArgumentException e) { + Log.d(this.getClass().getName(), "Unsupported numeral base: " + directionText); + } + } + } + + return result; + } + } +} diff --git a/calculatorpp/src/main/java/org/solovyev/android/calculator/widget/CalculatorWidgetProvider.java b/calculatorpp/src/main/java/org/solovyev/android/calculator/widget/CalculatorWidgetProvider.java index 70246a59..afdc7d3b 100644 --- a/calculatorpp/src/main/java/org/solovyev/android/calculator/widget/CalculatorWidgetProvider.java +++ b/calculatorpp/src/main/java/org/solovyev/android/calculator/widget/CalculatorWidgetProvider.java @@ -1,243 +1,237 @@ -package org.solovyev.android.calculator.widget; - -import android.app.PendingIntent; -import android.appwidget.AppWidgetManager; -import android.appwidget.AppWidgetProvider; -import android.content.ComponentName; -import android.content.Context; -import android.content.Intent; -import android.text.Html; -import android.widget.RemoteViews; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.solovyev.android.calculator.*; -import org.solovyev.common.MutableObject; - -import java.io.Serializable; - -/** - * User: Solovyev_S - * Date: 19.10.12 - * Time: 16:18 - */ -public class CalculatorWidgetProvider extends AppWidgetProvider { - - /* - ********************************************************************** - * - * CONSTANTS - * - ********************************************************************** - */ - private static final String EVENT_ID_EXTRA = "eventId"; - - private static final String BUTTON_ID_EXTRA = "buttonId"; - private static final String BUTTON_PRESSED_ACTION = "org.solovyev.calculator.widget.BUTTON_PRESSED"; - - private static final String EDITOR_STATE_CHANGED_ACTION = "org.solovyev.calculator.widget.EDITOR_STATE_CHANGED"; - private static final String EDITOR_STATE_EXTRA = "editorState"; - - private static final String DISPLAY_STATE_CHANGED_ACTION = "org.solovyev.calculator.widget.DISPLAY_STATE_CHANGED"; - private static final String DISPLAY_STATE_EXTRA = "displayState"; - - private static final String TAG = "Calculator++ Widget"; - - /* - ********************************************************************** - * - * FIELDS - * - ********************************************************************** - */ - - @Nullable - private String cursorColor; - - @NotNull - private final MutableObject lastDisplayEventId = new MutableObject(0L); - - @NotNull - private final MutableObject lastEditorEventId = new MutableObject(0L); - - /* - ********************************************************************** - * - * METHODS - * - ********************************************************************** - */ - - @Override - public void onEnabled(Context context) { - super.onEnabled(context); - - getCursorColor(context); - } - - @NotNull - private String getCursorColor(@NotNull Context context) { - if (cursorColor == null) { - cursorColor = Integer.toHexString(context.getResources().getColor(R.color.widget_cursor_color)).substring(2); - } - return cursorColor; - } - - @Override - public void onUpdate(@NotNull Context context, - @NotNull AppWidgetManager appWidgetManager, - @NotNull int[] appWidgetIds) { - super.onUpdate(context, appWidgetManager, appWidgetIds); - - updateWidget(context, appWidgetManager, appWidgetIds, CalculatorLocatorImpl.getInstance().getEditor().getViewState(), CalculatorLocatorImpl.getInstance().getDisplay().getViewState()); - } - - private void updateWidget(@NotNull Context context, - @NotNull CalculatorEditorViewState editorState, - @NotNull CalculatorDisplayViewState displayState) { - final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); - final int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, CalculatorWidgetProvider.class)); - updateWidget(context, appWidgetManager, appWidgetIds, editorState, displayState); - } - - private void updateWidget(@NotNull Context context, - @NotNull AppWidgetManager appWidgetManager, - @NotNull int[] appWidgetIds, - @NotNull CalculatorEditorViewState editorState, - @NotNull CalculatorDisplayViewState displayState) { - for (int appWidgetId : appWidgetIds) { - final RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout); - - for (WidgetButton button : WidgetButton.values()) { - final Intent onButtonClickIntent = new Intent(context, CalculatorWidgetProvider.class); - onButtonClickIntent.setAction(BUTTON_PRESSED_ACTION); - onButtonClickIntent.putExtra(BUTTON_ID_EXTRA, button.getButtonId()); - final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, button.getButtonId(), onButtonClickIntent, PendingIntent.FLAG_UPDATE_CURRENT); - if (pendingIntent != null) { - views.setOnClickPendingIntent(button.getButtonId(), pendingIntent); - } - } - - updateEditorState(context, views, editorState); - updateDisplayState(context, views, displayState); - - appWidgetManager.updateAppWidget(appWidgetId, views); - } - } - - @Override - public void onReceive(Context context, Intent intent) { - super.onReceive(context, intent); - - if (CalculatorWidgetProvider.BUTTON_PRESSED_ACTION.equals(intent.getAction())) { - final int buttonId = intent.getIntExtra(CalculatorWidgetProvider.BUTTON_ID_EXTRA, 0); - - final WidgetButton button = WidgetButton.getById(buttonId); - if (button != null) { - button.onClick(context); - } - } else if (EDITOR_STATE_CHANGED_ACTION.equals(intent.getAction())) { - CalculatorLocatorImpl.getInstance().getNotifier().showDebugMessage(TAG, "Editor state changed broadcast received!"); - - final Long eventId = intent.getLongExtra(EVENT_ID_EXTRA, 0L); - - boolean updateEditor = false; - synchronized (lastEditorEventId) { - if (eventId > lastEditorEventId.getObject()) { - lastEditorEventId.setObject(eventId); - updateEditor = true; - } - } - - if (updateEditor) { - final Serializable object = intent.getSerializableExtra(EDITOR_STATE_EXTRA); - if (object instanceof CalculatorEditorViewState) { - updateWidget(context, (CalculatorEditorViewState) object, CalculatorLocatorImpl.getInstance().getDisplay().getViewState()); - } - } - } else if (DISPLAY_STATE_CHANGED_ACTION.equals(intent.getAction())) { - CalculatorLocatorImpl.getInstance().getNotifier().showDebugMessage(TAG, "Display state changed broadcast received!"); - - final Long eventId = intent.getLongExtra(EVENT_ID_EXTRA, 0L); - boolean updateDisplay = false; - synchronized (lastDisplayEventId) { - if (eventId > lastDisplayEventId.getObject()) { - lastDisplayEventId.setObject(eventId); - updateDisplay = true; - } - } - - if (updateDisplay) { - final Serializable object = intent.getSerializableExtra(DISPLAY_STATE_EXTRA); - if (object instanceof CalculatorDisplayViewState) { - updateWidget(context, CalculatorLocatorImpl.getInstance().getEditor().getViewState(), (CalculatorDisplayViewState) object); - } - } - } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(intent.getAction())) { - updateWidget(context, CalculatorLocatorImpl.getInstance().getEditor().getViewState(), CalculatorLocatorImpl.getInstance().getDisplay().getViewState()); - } - } - - private void updateDisplayState(@NotNull Context context, @NotNull RemoteViews views, @NotNull CalculatorDisplayViewState displayState) { - if (displayState.isValid()) { - setText(views, R.id.calculatorDisplay, displayState.getText()); - setTextColor(views, R.id.calculatorDisplay, context.getResources().getColor(R.color.default_text_color)); - } else { - setTextColor(views, R.id.calculatorDisplay, context.getResources().getColor(R.color.display_error_text_color)); - } - } - - private void setText(@NotNull RemoteViews views, int textViewId, @Nullable CharSequence text) { - views.setTextViewText(textViewId, text); - } - - private void setTextColor(@NotNull RemoteViews views, int textViewId, int textColor) { - views.setTextColor(textViewId, textColor); - } - - private void updateEditorState(@NotNull Context context, @NotNull RemoteViews views, @NotNull CalculatorEditorViewState editorState) { - String text = editorState.getText(); - - CharSequence newText = text; - int selection = editorState.getSelection(); - if (selection >= 0 && selection <= text.length()) { - // inject cursor - newText = Html.fromHtml(text.substring(0, selection) + "|" + text.substring(selection)); - } - CalculatorLocatorImpl.getInstance().getNotifier().showDebugMessage(TAG, "New editor state: " + text); - setText(views, R.id.calculatorEditor, newText); - } - - /* - ********************************************************************** - * - * STATIC - * - ********************************************************************** - */ - - public static void onEditorStateChanged(@NotNull Context context, - @NotNull CalculatorEventData calculatorEventData, - @NotNull CalculatorEditorViewState editorViewState) { - - final Intent intent = new Intent(EDITOR_STATE_CHANGED_ACTION); - intent.setClass(context, CalculatorWidgetProvider.class); - intent.putExtra(EVENT_ID_EXTRA, calculatorEventData.getEventId()); - intent.putExtra(EDITOR_STATE_EXTRA, editorViewState); - context.sendBroadcast(intent); - CalculatorLocatorImpl.getInstance().getNotifier().showDebugMessage(TAG, "Editor state changed broadcast sent"); - } - - public static void onDisplayStateChanged(@NotNull Context context, - @NotNull CalculatorEventData calculatorEventData, - @NotNull CalculatorDisplayViewState displayViewState) { - - final Intent intent = new Intent(DISPLAY_STATE_CHANGED_ACTION); - intent.setClass(context, CalculatorWidgetProvider.class); - intent.putExtra(EVENT_ID_EXTRA, calculatorEventData.getEventId()); - intent.putExtra(DISPLAY_STATE_EXTRA, displayViewState); - context.sendBroadcast(intent); - CalculatorLocatorImpl.getInstance().getNotifier().showDebugMessage(TAG, "Display state changed broadcast sent"); - } - - -} +package org.solovyev.android.calculator.widget; + +import android.app.PendingIntent; +import android.appwidget.AppWidgetManager; +import android.appwidget.AppWidgetProvider; +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.text.Html; +import android.widget.RemoteViews; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.solovyev.android.calculator.*; +import org.solovyev.common.MutableObject; + +import java.io.Serializable; + +/** + * User: Solovyev_S + * Date: 19.10.12 + * Time: 16:18 + */ +public class CalculatorWidgetProvider extends AppWidgetProvider { + + /* + ********************************************************************** + * + * CONSTANTS + * + ********************************************************************** + */ + private static final String EVENT_ID_EXTRA = "eventId"; + + private static final String BUTTON_ID_EXTRA = "buttonId"; + private static final String BUTTON_PRESSED_ACTION = "org.solovyev.calculator.widget.BUTTON_PRESSED"; + + private static final String EDITOR_STATE_CHANGED_ACTION = "org.solovyev.calculator.widget.EDITOR_STATE_CHANGED"; + private static final String EDITOR_STATE_EXTRA = "editorState"; + + private static final String DISPLAY_STATE_CHANGED_ACTION = "org.solovyev.calculator.widget.DISPLAY_STATE_CHANGED"; + private static final String DISPLAY_STATE_EXTRA = "displayState"; + + private static final String TAG = "Calculator++ Widget"; + + /* + ********************************************************************** + * + * FIELDS + * + ********************************************************************** + */ + + @Nullable + private String cursorColor; + + @NotNull + private final MutableObject lastDisplayEventId = new MutableObject(0L); + + @NotNull + private final MutableObject lastEditorEventId = new MutableObject(0L); + + /* + ********************************************************************** + * + * METHODS + * + ********************************************************************** + */ + + @Override + public void onEnabled(Context context) { + super.onEnabled(context); + + getCursorColor(context); + } + + @NotNull + private String getCursorColor(@NotNull Context context) { + if (cursorColor == null) { + cursorColor = Integer.toHexString(context.getResources().getColor(R.color.widget_cursor_color)).substring(2); + } + return cursorColor; + } + + @Override + public void onUpdate(@NotNull Context context, + @NotNull AppWidgetManager appWidgetManager, + @NotNull int[] appWidgetIds) { + super.onUpdate(context, appWidgetManager, appWidgetIds); + + updateWidget(context, appWidgetManager, appWidgetIds, CalculatorLocatorImpl.getInstance().getEditor().getViewState(), CalculatorLocatorImpl.getInstance().getDisplay().getViewState()); + } + + private void updateWidget(@NotNull Context context, + @NotNull CalculatorEditorViewState editorState, + @NotNull CalculatorDisplayViewState displayState) { + final AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context); + final int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, CalculatorWidgetProvider.class)); + updateWidget(context, appWidgetManager, appWidgetIds, editorState, displayState); + } + + private void updateWidget(@NotNull Context context, + @NotNull AppWidgetManager appWidgetManager, + @NotNull int[] appWidgetIds, + @NotNull CalculatorEditorViewState editorState, + @NotNull CalculatorDisplayViewState displayState) { + for (int appWidgetId : appWidgetIds) { + final RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget_layout); + + for (WidgetButton button : WidgetButton.values()) { + final Intent onButtonClickIntent = new Intent(context, CalculatorWidgetProvider.class); + onButtonClickIntent.setAction(BUTTON_PRESSED_ACTION); + onButtonClickIntent.putExtra(BUTTON_ID_EXTRA, button.getButtonId()); + final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, button.getButtonId(), onButtonClickIntent, PendingIntent.FLAG_UPDATE_CURRENT); + if (pendingIntent != null) { + views.setOnClickPendingIntent(button.getButtonId(), pendingIntent); + } + } + + CalculatorButtons.initMultiplicationButton(views); + + updateEditorState(context, views, editorState); + updateDisplayState(context, views, displayState); + + appWidgetManager.updateAppWidget(appWidgetId, views); + } + } + + @Override + public void onReceive(Context context, Intent intent) { + super.onReceive(context, intent); + + if (CalculatorWidgetProvider.BUTTON_PRESSED_ACTION.equals(intent.getAction())) { + final int buttonId = intent.getIntExtra(CalculatorWidgetProvider.BUTTON_ID_EXTRA, 0); + + final WidgetButton button = WidgetButton.getById(buttonId); + if (button != null) { + button.onClick(context); + } + } else if (EDITOR_STATE_CHANGED_ACTION.equals(intent.getAction())) { + CalculatorLocatorImpl.getInstance().getNotifier().showDebugMessage(TAG, "Editor state changed broadcast received!"); + + final Long eventId = intent.getLongExtra(EVENT_ID_EXTRA, 0L); + + boolean updateEditor = false; + synchronized (lastEditorEventId) { + if (eventId > lastEditorEventId.getObject()) { + lastEditorEventId.setObject(eventId); + updateEditor = true; + } + } + + if (updateEditor) { + final Serializable object = intent.getSerializableExtra(EDITOR_STATE_EXTRA); + if (object instanceof CalculatorEditorViewState) { + updateWidget(context, (CalculatorEditorViewState) object, CalculatorLocatorImpl.getInstance().getDisplay().getViewState()); + } + } + } else if (DISPLAY_STATE_CHANGED_ACTION.equals(intent.getAction())) { + CalculatorLocatorImpl.getInstance().getNotifier().showDebugMessage(TAG, "Display state changed broadcast received!"); + + final Long eventId = intent.getLongExtra(EVENT_ID_EXTRA, 0L); + boolean updateDisplay = false; + synchronized (lastDisplayEventId) { + if (eventId > lastDisplayEventId.getObject()) { + lastDisplayEventId.setObject(eventId); + updateDisplay = true; + } + } + + if (updateDisplay) { + final Serializable object = intent.getSerializableExtra(DISPLAY_STATE_EXTRA); + if (object instanceof CalculatorDisplayViewState) { + updateWidget(context, CalculatorLocatorImpl.getInstance().getEditor().getViewState(), (CalculatorDisplayViewState) object); + } + } + } else if (Intent.ACTION_CONFIGURATION_CHANGED.equals(intent.getAction())) { + updateWidget(context, CalculatorLocatorImpl.getInstance().getEditor().getViewState(), CalculatorLocatorImpl.getInstance().getDisplay().getViewState()); + } + } + + private void updateDisplayState(@NotNull Context context, @NotNull RemoteViews views, @NotNull CalculatorDisplayViewState displayState) { + if (displayState.isValid()) { + views.setTextViewText(R.id.calculatorDisplay, displayState.getText()); + views.setTextColor(R.id.calculatorDisplay, context.getResources().getColor(R.color.default_text_color)); + } else { + views.setTextColor(R.id.calculatorDisplay, context.getResources().getColor(R.color.display_error_text_color)); + } + } + + private void updateEditorState(@NotNull Context context, @NotNull RemoteViews views, @NotNull CalculatorEditorViewState editorState) { + String text = editorState.getText(); + + CharSequence newText = text; + int selection = editorState.getSelection(); + if (selection >= 0 && selection <= text.length()) { + // inject cursor + newText = Html.fromHtml(text.substring(0, selection) + "|" + text.substring(selection)); + } + CalculatorLocatorImpl.getInstance().getNotifier().showDebugMessage(TAG, "New editor state: " + text); + views.setTextViewText(R.id.calculatorEditor, newText); + } + + /* + ********************************************************************** + * + * STATIC + * + ********************************************************************** + */ + + public static void onEditorStateChanged(@NotNull Context context, + @NotNull CalculatorEventData calculatorEventData, + @NotNull CalculatorEditorViewState editorViewState) { + + final Intent intent = new Intent(EDITOR_STATE_CHANGED_ACTION); + intent.setClass(context, CalculatorWidgetProvider.class); + intent.putExtra(EVENT_ID_EXTRA, calculatorEventData.getEventId()); + intent.putExtra(EDITOR_STATE_EXTRA, editorViewState); + context.sendBroadcast(intent); + CalculatorLocatorImpl.getInstance().getNotifier().showDebugMessage(TAG, "Editor state changed broadcast sent"); + } + + public static void onDisplayStateChanged(@NotNull Context context, + @NotNull CalculatorEventData calculatorEventData, + @NotNull CalculatorDisplayViewState displayViewState) { + + final Intent intent = new Intent(DISPLAY_STATE_CHANGED_ACTION); + intent.setClass(context, CalculatorWidgetProvider.class); + intent.putExtra(EVENT_ID_EXTRA, calculatorEventData.getEventId()); + intent.putExtra(DISPLAY_STATE_EXTRA, displayViewState); + context.sendBroadcast(intent); + CalculatorLocatorImpl.getInstance().getNotifier().showDebugMessage(TAG, "Display state changed broadcast sent"); + } + + +}