Several widget sizes + parcelable
This commit is contained in:
parent
5d82657274
commit
8ea91849c4
@ -48,6 +48,8 @@
|
|||||||
<!-- settings must use action bar icon-->
|
<!-- settings must use action bar icon-->
|
||||||
<activity android:icon="@drawable/icon_action_bar" android:label="@string/c_settings" android:name=".plot.CalculatorPlotPreferenceActivity"/>
|
<activity android:icon="@drawable/icon_action_bar" android:label="@string/c_settings" android:name=".plot.CalculatorPlotPreferenceActivity"/>
|
||||||
|
|
||||||
|
<!-- WIDGET CONFIG -->
|
||||||
|
|
||||||
<receiver android:icon="@drawable/icon" android:label="@string/c_app_name" android:name=".widget.CalculatorWidgetProvider">
|
<receiver android:icon="@drawable/icon" android:label="@string/c_app_name" android:name=".widget.CalculatorWidgetProvider">
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
@ -57,9 +59,35 @@
|
|||||||
<action android:name="org.solovyev.calculator.widget.BUTTON_PRESSED"/>
|
<action android:name="org.solovyev.calculator.widget.BUTTON_PRESSED"/>
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
<meta-data android:name="android.appwidget.provider" android:resource="@xml/calculator_widget_info"/>
|
<meta-data android:name="android.appwidget.provider" android:resource="@xml/calculator_widget_info_3x3"/>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
|
<receiver android:icon="@drawable/icon" android:label="@string/c_app_name" android:name=".widget.CalculatorWidgetProvider3x4">
|
||||||
|
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
|
||||||
|
<action android:name="org.solovyev.calculator.widget.EDITOR_STATE_CHANGED"/>
|
||||||
|
<action android:name="org.solovyev.calculator.widget.DISPLAY_STATE_CHANGED"/>
|
||||||
|
<action android:name="org.solovyev.calculator.widget.BUTTON_PRESSED"/>
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<meta-data android:name="android.appwidget.provider" android:resource="@xml/calculator_widget_info_3x4"/>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
<receiver android:icon="@drawable/icon" android:label="@string/c_app_name" android:name=".widget.CalculatorWidgetProvider4x4">
|
||||||
|
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.appwidget.action.APPWIDGET_UPDATE"/>
|
||||||
|
<action android:name="org.solovyev.calculator.widget.EDITOR_STATE_CHANGED"/>
|
||||||
|
<action android:name="org.solovyev.calculator.widget.DISPLAY_STATE_CHANGED"/>
|
||||||
|
<action android:name="org.solovyev.calculator.widget.BUTTON_PRESSED"/>
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
|
<meta-data android:name="android.appwidget.provider" android:resource="@xml/calculator_widget_info_4x4"/>
|
||||||
|
</receiver>
|
||||||
|
|
||||||
|
<!-- ADMOB + BILLING CONFIG -->
|
||||||
|
|
||||||
<activity android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" android:name="com.google.ads.AdActivity"/>
|
<activity android:configChanges="keyboard|keyboardHidden|orientation|screenLayout|uiMode|screenSize|smallestScreenSize" android:name="com.google.ads.AdActivity"/>
|
||||||
|
|
||||||
<service android:name="net.robotmedia.billing.BillingService"/>
|
<service android:name="net.robotmedia.billing.BillingService"/>
|
||||||
@ -71,6 +99,8 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</receiver>
|
</receiver>
|
||||||
|
|
||||||
|
<!-- ACRA CONFIG -->
|
||||||
|
|
||||||
<activity android:excludeFromRecents="true" android:finishOnTaskLaunch="true" android:launchMode="singleInstance" android:name="org.acra.CrashReportDialog" android:theme="@style/Theme.Sherlock.Dialog"/>
|
<activity android:excludeFromRecents="true" android:finishOnTaskLaunch="true" android:launchMode="singleInstance" android:name="org.acra.CrashReportDialog" android:theme="@style/Theme.Sherlock.Dialog"/>
|
||||||
|
|
||||||
</application>
|
</application>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<appwidget-provider xmlns:a="http://schemas.android.com/apk/res/android"
|
<appwidget-provider xmlns:a="http://schemas.android.com/apk/res/android"
|
||||||
a:minWidth="180dp"
|
a:minWidth="180dp"
|
||||||
a:minHeight="220dp"
|
a:minHeight="180dp"
|
||||||
a:initialLayout="@layout/widget_layout"
|
a:initialLayout="@layout/widget_layout"
|
||||||
a:previewImage="@drawable/widget_preview"
|
a:previewImage="@drawable/widget_preview"
|
||||||
a:resizeMode="horizontal|vertical">
|
a:resizeMode="horizontal|vertical">
|
10
calculatorpp/res/xml/calculator_widget_info_3x4.xml
Normal file
10
calculatorpp/res/xml/calculator_widget_info_3x4.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<appwidget-provider xmlns:a="http://schemas.android.com/apk/res/android"
|
||||||
|
a:minWidth="180dp"
|
||||||
|
a:minHeight="250dp"
|
||||||
|
a:initialLayout="@layout/widget_layout"
|
||||||
|
a:previewImage="@drawable/widget_preview"
|
||||||
|
a:resizeMode="horizontal|vertical">
|
||||||
|
|
||||||
|
</appwidget-provider>
|
10
calculatorpp/res/xml/calculator_widget_info_4x4.xml
Normal file
10
calculatorpp/res/xml/calculator_widget_info_4x4.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
|
<appwidget-provider xmlns:a="http://schemas.android.com/apk/res/android"
|
||||||
|
a:minWidth="250dp"
|
||||||
|
a:minHeight="250dp"
|
||||||
|
a:initialLayout="@layout/widget_layout"
|
||||||
|
a:previewImage="@drawable/widget_preview"
|
||||||
|
a:resizeMode="horizontal|vertical">
|
||||||
|
|
||||||
|
</appwidget-provider>
|
@ -0,0 +1,107 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
import jscl.math.Generic;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.solovyev.android.calculator.jscl.JsclOperation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 11/18/12
|
||||||
|
* Time: 1:40 PM
|
||||||
|
*/
|
||||||
|
public final class ParcelableCalculatorDisplayViewState implements CalculatorDisplayViewState, Parcelable {
|
||||||
|
|
||||||
|
public static final Creator<ParcelableCalculatorDisplayViewState> CREATOR = new Creator<ParcelableCalculatorDisplayViewState>() {
|
||||||
|
@Override
|
||||||
|
public ParcelableCalculatorDisplayViewState createFromParcel(@NotNull Parcel in) {
|
||||||
|
return ParcelableCalculatorDisplayViewState.fromParcel(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParcelableCalculatorDisplayViewState[] newArray(int size) {
|
||||||
|
return new ParcelableCalculatorDisplayViewState[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static ParcelableCalculatorDisplayViewState fromParcel(@NotNull Parcel in) {
|
||||||
|
final int selection = in.readInt();
|
||||||
|
final boolean valid = in.readInt() == 1;
|
||||||
|
final String stringResult = in.readString();
|
||||||
|
final String errorMessage = in.readString();
|
||||||
|
final JsclOperation operation = (JsclOperation) in.readSerializable();
|
||||||
|
|
||||||
|
CalculatorDisplayViewState calculatorDisplayViewState;
|
||||||
|
if (valid) {
|
||||||
|
calculatorDisplayViewState = CalculatorDisplayViewStateImpl.newValidState(operation, null, stringResult, selection);
|
||||||
|
} else {
|
||||||
|
calculatorDisplayViewState = CalculatorDisplayViewStateImpl.newErrorState(operation, errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ParcelableCalculatorDisplayViewState(calculatorDisplayViewState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private CalculatorDisplayViewState viewState;
|
||||||
|
|
||||||
|
public ParcelableCalculatorDisplayViewState(@NotNull CalculatorDisplayViewState viewState) {
|
||||||
|
this.viewState = viewState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public String getText() {
|
||||||
|
return viewState.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSelection() {
|
||||||
|
return viewState.getSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public Generic getResult() {
|
||||||
|
return viewState.getResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid() {
|
||||||
|
return viewState.isValid();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public String getErrorMessage() {
|
||||||
|
return viewState.getErrorMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public JsclOperation getOperation() {
|
||||||
|
return viewState.getOperation();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public String getStringResult() {
|
||||||
|
return viewState.getStringResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(@NotNull Parcel out, int flags) {
|
||||||
|
out.writeInt(viewState.getSelection());
|
||||||
|
out.writeInt(viewState.isValid() ? 1 : 0);
|
||||||
|
out.writeString(viewState.getStringResult());
|
||||||
|
out.writeString(viewState.getErrorMessage());
|
||||||
|
out.writeSerializable(viewState.getOperation());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
package org.solovyev.android.calculator;
|
||||||
|
|
||||||
|
import android.os.Parcel;
|
||||||
|
import android.os.Parcelable;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 11/18/12
|
||||||
|
* Time: 1:40 PM
|
||||||
|
*/
|
||||||
|
public final class ParcelableCalculatorEditorViewState implements CalculatorEditorViewState, Parcelable {
|
||||||
|
|
||||||
|
public static final Creator<ParcelableCalculatorEditorViewState> CREATOR = new Creator<ParcelableCalculatorEditorViewState>() {
|
||||||
|
@Override
|
||||||
|
public ParcelableCalculatorEditorViewState createFromParcel(@NotNull Parcel in) {
|
||||||
|
return ParcelableCalculatorEditorViewState.fromParcel(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ParcelableCalculatorEditorViewState[] newArray(int size) {
|
||||||
|
return new ParcelableCalculatorEditorViewState[size];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private CalculatorEditorViewState viewState;
|
||||||
|
|
||||||
|
public ParcelableCalculatorEditorViewState(@NotNull CalculatorEditorViewState viewState) {
|
||||||
|
this.viewState = viewState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private static ParcelableCalculatorEditorViewState fromParcel(@NotNull Parcel in) {
|
||||||
|
final String text = in.readString();
|
||||||
|
final int selection = in.readInt();
|
||||||
|
return new ParcelableCalculatorEditorViewState(CalculatorEditorViewStateImpl.newInstance(text, selection));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public String getText() {
|
||||||
|
return viewState.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSelection() {
|
||||||
|
return viewState.getSelection();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int describeContents() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeToParcel(@NotNull Parcel out, int flags) {
|
||||||
|
out.writeString(viewState.getText());
|
||||||
|
out.writeInt(viewState.getSelection());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,264 @@
|
|||||||
|
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.os.Parcelable;
|
||||||
|
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.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: Solovyev_S
|
||||||
|
* Date: 19.10.12
|
||||||
|
* Time: 16:18
|
||||||
|
*/
|
||||||
|
abstract class AbstractCalculatorWidgetProvider 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<Long> lastDisplayEventId = new MutableObject<Long>(0L);
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private final MutableObject<Long> lastEditorEventId = new MutableObject<Long>(0L);
|
||||||
|
|
||||||
|
/*
|
||||||
|
**********************************************************************
|
||||||
|
*
|
||||||
|
* CONSTRUCTORS
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
protected AbstractCalculatorWidgetProvider() {
|
||||||
|
final Class<? extends AppWidgetProvider> componentClass = this.getComponentClass();
|
||||||
|
if (!knownAppWidgetProviderClasses.contains(componentClass)) {
|
||||||
|
knownAppWidgetProviderClasses.add(componentClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
**********************************************************************
|
||||||
|
*
|
||||||
|
* 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, getComponentClass()));
|
||||||
|
updateWidget(context, appWidgetManager, appWidgetIds, editorState, displayState);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
protected Class<? extends AbstractCalculatorWidgetProvider> getComponentClass(){
|
||||||
|
return this.getClass();
|
||||||
|
}
|
||||||
|
|
||||||
|
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, getComponentClass());
|
||||||
|
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);
|
||||||
|
|
||||||
|
CalculatorButtons.initMultiplicationButton(views);
|
||||||
|
|
||||||
|
appWidgetManager.updateAppWidget(appWidgetId, views);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
super.onReceive(context, intent);
|
||||||
|
|
||||||
|
if (AbstractCalculatorWidgetProvider.BUTTON_PRESSED_ACTION.equals(intent.getAction())) {
|
||||||
|
final int buttonId = intent.getIntExtra(AbstractCalculatorWidgetProvider.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 Parcelable object = intent.getParcelableExtra(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 Parcelable object = intent.getParcelableExtra(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) + "<font color=\"#" + getCursorColor(context) + "\">|</font>" + text.substring(selection));
|
||||||
|
}
|
||||||
|
CalculatorLocatorImpl.getInstance().getNotifier().showDebugMessage(TAG, "New editor state: " + text);
|
||||||
|
views.setTextViewText(R.id.calculatorEditor, newText);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
**********************************************************************
|
||||||
|
*
|
||||||
|
* STATIC
|
||||||
|
*
|
||||||
|
**********************************************************************
|
||||||
|
*/
|
||||||
|
|
||||||
|
private static final List<Class<? extends AppWidgetProvider>> knownAppWidgetProviderClasses = new ArrayList<Class<? extends AppWidgetProvider>>();
|
||||||
|
|
||||||
|
public static void onEditorStateChanged(@NotNull Context context,
|
||||||
|
@NotNull CalculatorEventData calculatorEventData,
|
||||||
|
@NotNull CalculatorEditorViewState editorViewState) {
|
||||||
|
|
||||||
|
for (Class<? extends AppWidgetProvider> appWidgetProviderClass : knownAppWidgetProviderClasses) {
|
||||||
|
final Intent intent = new Intent(EDITOR_STATE_CHANGED_ACTION);
|
||||||
|
intent.setClass(context, appWidgetProviderClass);
|
||||||
|
intent.putExtra(EVENT_ID_EXTRA, calculatorEventData.getEventId());
|
||||||
|
intent.putExtra(EDITOR_STATE_EXTRA, (Parcelable) new ParcelableCalculatorEditorViewState(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) {
|
||||||
|
for (Class<? extends AppWidgetProvider> appWidgetProviderClass : knownAppWidgetProviderClasses) {
|
||||||
|
final Intent intent = new Intent(DISPLAY_STATE_CHANGED_ACTION);
|
||||||
|
intent.setClass(context, appWidgetProviderClass);
|
||||||
|
intent.putExtra(EVENT_ID_EXTRA, calculatorEventData.getEventId());
|
||||||
|
intent.putExtra(DISPLAY_STATE_EXTRA, (Parcelable)new ParcelableCalculatorDisplayViewState(displayViewState));
|
||||||
|
context.sendBroadcast(intent);
|
||||||
|
CalculatorLocatorImpl.getInstance().getNotifier().showDebugMessage(TAG, "Display state changed broadcast sent");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -32,7 +32,7 @@ public class CalculatorWidgetHelper implements CalculatorEventListener {
|
|||||||
|
|
||||||
CalculatorLocatorImpl.getInstance().getNotifier().showDebugMessage(TAG, "Editor state changed: " + newEditorState.getText());
|
CalculatorLocatorImpl.getInstance().getNotifier().showDebugMessage(TAG, "Editor state changed: " + newEditorState.getText());
|
||||||
|
|
||||||
CalculatorWidgetProvider.onEditorStateChanged(CalculatorApplication.getInstance(), calculatorEventData, newEditorState);
|
AbstractCalculatorWidgetProvider.onEditorStateChanged(CalculatorApplication.getInstance(), calculatorEventData, newEditorState);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case display_state_changed:
|
case display_state_changed:
|
||||||
@ -41,7 +41,7 @@ public class CalculatorWidgetHelper implements CalculatorEventListener {
|
|||||||
|
|
||||||
CalculatorLocatorImpl.getInstance().getNotifier().showDebugMessage(TAG, "Display state changed: " + newDisplayState.getText());
|
CalculatorLocatorImpl.getInstance().getNotifier().showDebugMessage(TAG, "Display state changed: " + newDisplayState.getText());
|
||||||
|
|
||||||
CalculatorWidgetProvider.onDisplayStateChanged(CalculatorApplication.getInstance(), calculatorEventData, newDisplayState);
|
AbstractCalculatorWidgetProvider.onDisplayStateChanged(CalculatorApplication.getInstance(), calculatorEventData, newDisplayState);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,237 +1,9 @@
|
|||||||
package org.solovyev.android.calculator.widget;
|
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
|
* User: serso
|
||||||
* Date: 19.10.12
|
* Date: 11/18/12
|
||||||
* Time: 16:18
|
* Time: 1:00 PM
|
||||||
*/
|
*/
|
||||||
public class CalculatorWidgetProvider extends AppWidgetProvider {
|
public class CalculatorWidgetProvider extends AbstractCalculatorWidgetProvider {
|
||||||
|
|
||||||
/*
|
|
||||||
**********************************************************************
|
|
||||||
*
|
|
||||||
* 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<Long> lastDisplayEventId = new MutableObject<Long>(0L);
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
private final MutableObject<Long> lastEditorEventId = new MutableObject<Long>(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);
|
|
||||||
|
|
||||||
CalculatorButtons.initMultiplicationButton(views);
|
|
||||||
|
|
||||||
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) + "<font color=\"#" + getCursorColor(context) + "\">|</font>" + 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");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
package org.solovyev.android.calculator.widget;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 11/18/12
|
||||||
|
* Time: 1:01 PM
|
||||||
|
*/
|
||||||
|
public class CalculatorWidgetProvider3x4 extends AbstractCalculatorWidgetProvider {
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
package org.solovyev.android.calculator.widget;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User: serso
|
||||||
|
* Date: 11/18/12
|
||||||
|
* Time: 1:01 PM
|
||||||
|
*/
|
||||||
|
public class CalculatorWidgetProvider4x4 extends AbstractCalculatorWidgetProvider {
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user