From a0ff19e4cd5206b8cd5776117eb2786d0abf5f7c Mon Sep 17 00:00:00 2001 From: serso Date: Thu, 18 Jun 2015 11:55:53 +0200 Subject: [PATCH] Material themes for widget --- .../calculator/CalculatorBroadcasterTest.java | 2 +- android-app/src/main/AndroidManifest.xml | 5 + .../main/java/org/solovyev/android/Check.java | 6 + .../org/solovyev/android/calculator/App.java | 8 +- .../calculator/CalculatorBroadcaster.java | 14 +- .../android/calculator/Preferences.java | 139 +++++++++++------- .../onscreen/CalculatorOnscreenView.java | 4 +- .../preferences/PreferencesActivity.java | 1 + .../widget/BaseCalculatorWidgetProvider.java | 63 ++++---- .../cpp_simple_button_operators_material.xml | 29 ++++ ...simple_button_operators_material_light.xml | 29 ++++ .../cpp_simple_button_paste_material.xml | 29 ++++ ...cpp_simple_button_paste_material_light.xml | 29 ++++ .../cpp_simple_button_right_material.xml | 28 ++++ ...cpp_simple_button_right_material_light.xml | 28 ++++ .../cpp_simple_button_settings_material.xml | 29 ++++ ..._simple_button_settings_material_light.xml | 29 ++++ .../cpp_simple_button_vars_material.xml | 29 ++++ .../cpp_simple_button_vars_material_light.xml | 29 ++++ .../main/res/layout/widget_display_light.xml | 15 ++ .../src/main/res/layout/widget_editor.xml | 5 +- .../main/res/layout/widget_editor_light.xml | 23 +++ ...imple_keyboard.xml => widget_keyboard.xml} | 0 .../res/layout/widget_keyboard_material.xml | 126 ++++++++++++++++ .../layout/widget_keyboard_material_light.xml | 126 ++++++++++++++++ .../src/main/res/layout/widget_layout.xml | 2 +- .../res/layout/widget_layout_material.xml | 42 ++++++ .../layout/widget_layout_material_light.xml | 42 ++++++ android-app/src/main/res/values/arrays.xml | 6 +- android-app/src/main/res/values/styles.xml | 12 ++ .../src/main/res/values/text_strings.xml | 3 +- android-app/src/main/res/xml/preferences.xml | 3 + .../src/main/res/xml/preferences_onscreen.xml | 5 +- .../src/main/res/xml/preferences_widget.xml | 33 +++++ 34 files changed, 864 insertions(+), 109 deletions(-) create mode 100644 android-app/src/main/res/layout/cpp_simple_button_operators_material.xml create mode 100644 android-app/src/main/res/layout/cpp_simple_button_operators_material_light.xml create mode 100644 android-app/src/main/res/layout/cpp_simple_button_paste_material.xml create mode 100644 android-app/src/main/res/layout/cpp_simple_button_paste_material_light.xml create mode 100644 android-app/src/main/res/layout/cpp_simple_button_right_material.xml create mode 100644 android-app/src/main/res/layout/cpp_simple_button_right_material_light.xml create mode 100644 android-app/src/main/res/layout/cpp_simple_button_settings_material.xml create mode 100644 android-app/src/main/res/layout/cpp_simple_button_settings_material_light.xml create mode 100644 android-app/src/main/res/layout/cpp_simple_button_vars_material.xml create mode 100644 android-app/src/main/res/layout/cpp_simple_button_vars_material_light.xml create mode 100644 android-app/src/main/res/layout/widget_display_light.xml create mode 100644 android-app/src/main/res/layout/widget_editor_light.xml rename android-app/src/main/res/layout/{cpp_simple_keyboard.xml => widget_keyboard.xml} (100%) create mode 100644 android-app/src/main/res/layout/widget_keyboard_material.xml create mode 100644 android-app/src/main/res/layout/widget_keyboard_material_light.xml create mode 100644 android-app/src/main/res/layout/widget_layout_material.xml create mode 100644 android-app/src/main/res/layout/widget_layout_material_light.xml create mode 100644 android-app/src/main/res/xml/preferences_widget.xml diff --git a/android-app-tests/src/test/java/org/solovyev/android/calculator/CalculatorBroadcasterTest.java b/android-app-tests/src/test/java/org/solovyev/android/calculator/CalculatorBroadcasterTest.java index cc2a3305..601689d3 100644 --- a/android-app-tests/src/test/java/org/solovyev/android/calculator/CalculatorBroadcasterTest.java +++ b/android-app-tests/src/test/java/org/solovyev/android/calculator/CalculatorBroadcasterTest.java @@ -32,7 +32,7 @@ public class CalculatorBroadcasterTest { @Before public void setUp() throws Exception { - broadcaster = new CalculatorBroadcaster(application); + broadcaster = new CalculatorBroadcaster(application, preferences); } @Test diff --git a/android-app/src/main/AndroidManifest.xml b/android-app/src/main/AndroidManifest.xml index 037af0b8..08d06286 100644 --- a/android-app/src/main/AndroidManifest.xml +++ b/android-app/src/main/AndroidManifest.xml @@ -120,6 +120,7 @@ + @@ -133,6 +134,7 @@ + @@ -146,6 +148,7 @@ + @@ -159,6 +162,7 @@ + @@ -172,6 +176,7 @@ + diff --git a/android-app/src/main/java/org/solovyev/android/Check.java b/android-app/src/main/java/org/solovyev/android/Check.java index ea893de8..db1877d5 100644 --- a/android-app/src/main/java/org/solovyev/android/Check.java +++ b/android-app/src/main/java/org/solovyev/android/Check.java @@ -96,6 +96,12 @@ public final class Check { throw new AssertionException(message); } + public static void isTrue(boolean expression) { + if (!expression) { + throw new AssertionException(""); + } + } + public static void isTrue(boolean expression, @Nonnull String message) { if (!expression) { throw new AssertionException(message); diff --git a/android-app/src/main/java/org/solovyev/android/calculator/App.java b/android-app/src/main/java/org/solovyev/android/calculator/App.java index 338775c1..0fefb55d 100644 --- a/android-app/src/main/java/org/solovyev/android/calculator/App.java +++ b/android-app/src/main/java/org/solovyev/android/calculator/App.java @@ -165,7 +165,7 @@ public final class App { } } }); - App.broadcaster = new CalculatorBroadcaster(application); + App.broadcaster = new CalculatorBroadcaster(application, preferences); App.vibrator = new Vibrator(application, preferences); App.screenMetrics = new ScreenMetrics(application); @@ -285,15 +285,15 @@ public final class App { } @Nonnull - public static Preferences.Onscreen.Theme getOnscreenTheme() { - return Preferences.Onscreen.getTheme(getPreferences()); + public static Preferences.SimpleTheme getWidgetTheme() { + return Preferences.Widget.getTheme(getPreferences()); } @Nonnull public static Preferences.Gui.Theme getThemeIn(@Nonnull Context context) { if (context instanceof CalculatorOnscreenService) { final SharedPreferences p = getPreferences(); - final Preferences.Onscreen.Theme onscreenTheme = Preferences.Onscreen.getTheme(p); + final Preferences.SimpleTheme onscreenTheme = Preferences.Onscreen.getTheme(p); final Preferences.Gui.Theme appTheme = Preferences.Gui.getTheme(p); return onscreenTheme.resolveThemeFor(appTheme).getAppTheme(); } else { diff --git a/android-app/src/main/java/org/solovyev/android/calculator/CalculatorBroadcaster.java b/android-app/src/main/java/org/solovyev/android/calculator/CalculatorBroadcaster.java index 5ad53464..662912d4 100644 --- a/android-app/src/main/java/org/solovyev/android/calculator/CalculatorBroadcaster.java +++ b/android-app/src/main/java/org/solovyev/android/calculator/CalculatorBroadcaster.java @@ -2,21 +2,24 @@ package org.solovyev.android.calculator; import android.content.Context; import android.content.Intent; +import android.content.SharedPreferences; import javax.annotation.Nonnull; import javax.annotation.Nullable; -public final class CalculatorBroadcaster implements CalculatorEventListener { +public final class CalculatorBroadcaster implements CalculatorEventListener, SharedPreferences.OnSharedPreferenceChangeListener { public static final String ACTION_INIT = "org.solovyev.android.calculator.INIT"; public static final String ACTION_EDITOR_STATE_CHANGED = "org.solovyev.android.calculator.EDITOR_STATE_CHANGED"; public static final String ACTION_DISPLAY_STATE_CHANGED = "org.solovyev.android.calculator.DISPLAY_STATE_CHANGED"; + public static final String ACTION_THEME_CHANGED = "org.solovyev.android.calculator.THEME_CHANGED"; @Nonnull private final Context context; - public CalculatorBroadcaster(@Nonnull Context context) { + public CalculatorBroadcaster(@Nonnull Context context, @Nonnull SharedPreferences preferences) { this.context = context; + preferences.registerOnSharedPreferenceChangeListener(this); } @Override @@ -43,4 +46,11 @@ public final class CalculatorBroadcaster implements CalculatorEventListener { public void sendBroadcastIntent(@Nonnull String action) { context.sendBroadcast(new Intent(action)); } + + @Override + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + if (Preferences.Gui.theme.isSameKey(key) || Preferences.Widget.theme.isSameKey(key)) { + sendBroadcastIntent(ACTION_THEME_CHANGED); + } + } } diff --git a/android-app/src/main/java/org/solovyev/android/calculator/Preferences.java b/android-app/src/main/java/org/solovyev/android/calculator/Preferences.java index 20d97ab8..020b012f 100644 --- a/android-app/src/main/java/org/solovyev/android/calculator/Preferences.java +++ b/android-app/src/main/java/org/solovyev/android/calculator/Preferences.java @@ -31,6 +31,7 @@ import android.support.annotation.StyleRes; import android.util.SparseArray; import android.view.ContextThemeWrapper; +import org.solovyev.android.Check; import org.solovyev.android.calculator.language.Languages; import org.solovyev.android.calculator.math.MathType; import org.solovyev.android.calculator.model.AndroidCalculatorEngine; @@ -44,7 +45,9 @@ import org.solovyev.android.prefs.Preference; import org.solovyev.android.prefs.StringPreference; import java.text.DecimalFormatSymbols; +import java.util.EnumMap; import java.util.Locale; +import java.util.Map; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -65,63 +68,93 @@ public final class Preferences { public static final Preference appVersion = IntegerPreference.of("application.version", -1); public static final Preference appOpenedCounter = IntegerPreference.of("app_opened_counter", 0); + public enum SimpleTheme { + + default_theme(0, 0, null), + metro_blue_theme(R.layout.onscreen_layout, R.layout.widget_layout, Gui.Theme.metro_blue_theme), + material_theme(R.layout.onscreen_layout_material, R.layout.widget_layout_material, Gui.Theme.material_theme), + material_light_theme(R.layout.onscreen_layout_material_light, R.layout.widget_layout_material_light, Gui.Theme.material_light_theme); + + @LayoutRes + private final int onscreenLayout; + + @LayoutRes + private final int widgetLayout; + + @Nullable + private final Gui.Theme appTheme; + + @Nonnull + private final Map cache = new EnumMap<>(Gui.Theme.class); + + SimpleTheme(int onscreenLayout, int widgetLayout, @Nullable Gui.Theme appTheme) { + this.onscreenLayout = onscreenLayout; + this.widgetLayout = widgetLayout; + this.appTheme = appTheme; + } + + public int getOnscreenLayout(@Nonnull Gui.Theme appTheme) { + return resolveThemeFor(appTheme).onscreenLayout; + } + + public int getWidgetLayout(@Nonnull Gui.Theme appTheme) { + return resolveThemeFor(appTheme).widgetLayout; + } + + @Nonnull + public SimpleTheme resolveThemeFor(@Nonnull Gui.Theme appTheme) { + if (this == default_theme) { + SimpleTheme theme = cache.get(appTheme); + if (theme == null) { + theme = lookUpThemeFor(appTheme); + cache.put(appTheme, theme); + } + return theme; + } + return this; + } + + @Nonnull + private SimpleTheme lookUpThemeFor(@Nonnull Gui.Theme appTheme) { + Check.isTrue(this == default_theme); + // find direct match + for (SimpleTheme theme : values()) { + if (theme.appTheme == appTheme) { + return theme; + } + } + + // for metro themes return metro theme + if (appTheme == Gui.Theme.metro_green_theme || appTheme == Gui.Theme.metro_purple_theme) { + return metro_blue_theme; + } + + // for old themes return dark material + return material_theme; + } + + @Nullable + public Gui.Theme getAppTheme() { + return appTheme; + } + } + + public static class Widget { + public static final Preference theme = StringPreference.ofEnum("widget.theme", SimpleTheme.default_theme, SimpleTheme.class); + + @Nonnull + public static SimpleTheme getTheme(@Nonnull SharedPreferences preferences) { + return theme.getPreferenceNoError(preferences); + } + + } public static class Onscreen { public static final Preference startOnBoot = BooleanPreference.of("onscreen_start_on_boot", false); public static final Preference showAppIcon = BooleanPreference.of("onscreen_show_app_icon", true); - public static final Preference theme = StringPreference.ofEnum("onscreen.theme", Theme.default_theme, Theme.class); - - public enum Theme { - - default_theme(0, null), - metro_blue_theme(R.layout.onscreen_layout, Gui.Theme.metro_blue_theme), - material_theme(R.layout.onscreen_layout_material, Gui.Theme.material_theme), - material_light_theme(R.layout.onscreen_layout_material_light, Gui.Theme.material_light_theme); - - @LayoutRes - private final int layout; - - @Nullable - private final Gui.Theme appTheme; - - Theme(int layout, @Nullable Gui.Theme appTheme) { - this.layout = layout; - this.appTheme = appTheme; - } - - public int getLayout(@Nonnull Gui.Theme appTheme) { - return resolveThemeFor(appTheme).layout; - } - - @Nonnull - public Theme resolveThemeFor(@Nonnull Gui.Theme appTheme) { - if (this == default_theme) { - // find direct match - for (Theme theme : values()) { - if (theme.appTheme == appTheme) { - return theme; - } - } - - // for metro themes return metro theme - if (appTheme == Gui.Theme.metro_green_theme || appTheme == Gui.Theme.metro_purple_theme) { - return metro_blue_theme; - } - - // for old themes return dark material - return material_theme; - } - return this; - } - - @Nullable - public Gui.Theme getAppTheme() { - return appTheme; - } - } - + public static final Preference theme = StringPreference.ofEnum("onscreen.theme", SimpleTheme.default_theme, SimpleTheme.class); @Nonnull - public static Theme getTheme(@Nonnull SharedPreferences preferences) { + public static SimpleTheme getTheme(@Nonnull SharedPreferences preferences) { return theme.getPreferenceNoError(preferences); } } @@ -345,6 +378,8 @@ public final class Preferences { applyDefaultPreference(preferences, Onscreen.startOnBoot); applyDefaultPreference(preferences, Onscreen.theme); + applyDefaultPreference(preferences, Widget.theme); + applyDefaultPreference(preferences, Ga.initialReportDone); diff --git a/android-app/src/main/java/org/solovyev/android/calculator/onscreen/CalculatorOnscreenView.java b/android-app/src/main/java/org/solovyev/android/calculator/onscreen/CalculatorOnscreenView.java index bd0607ee..b33316bf 100644 --- a/android-app/src/main/java/org/solovyev/android/calculator/onscreen/CalculatorOnscreenView.java +++ b/android-app/src/main/java/org/solovyev/android/calculator/onscreen/CalculatorOnscreenView.java @@ -150,9 +150,9 @@ public class CalculatorOnscreenView { final CalculatorOnscreenView result = new CalculatorOnscreenView(); final SharedPreferences p = App.getPreferences(); - final Preferences.Onscreen.Theme theme = Preferences.Onscreen.theme.getPreferenceNoError(p); + final Preferences.SimpleTheme theme = Preferences.Onscreen.theme.getPreferenceNoError(p); final Preferences.Gui.Theme appTheme = Preferences.Gui.theme.getPreferenceNoError(p); - result.root = View.inflate(context, theme.getLayout(appTheme), null); + result.root = View.inflate(context, theme.getOnscreenLayout(appTheme), null); result.context = context; result.viewListener = viewListener; diff --git a/android-app/src/main/java/org/solovyev/android/calculator/preferences/PreferencesActivity.java b/android-app/src/main/java/org/solovyev/android/calculator/preferences/PreferencesActivity.java index 5810b684..5b848c31 100644 --- a/android-app/src/main/java/org/solovyev/android/calculator/preferences/PreferencesActivity.java +++ b/android-app/src/main/java/org/solovyev/android/calculator/preferences/PreferencesActivity.java @@ -35,6 +35,7 @@ public class PreferencesActivity extends BaseActivity implements SharedPreferenc preferences.append(R.xml.preferences_plot, new PrefDef("screen-plot", R.string.prefs_graph_screen_title)); preferences.append(R.xml.preferences_other, new PrefDef("screen-other", R.string.c_prefs_other_category)); preferences.append(R.xml.preferences_onscreen, new PrefDef("screen-onscreen", R.string.prefs_onscreen_title)); + preferences.append(R.xml.preferences_widget, new PrefDef("screen-widget", R.string.prefs_widget_title)); } static class PrefDef { diff --git a/android-app/src/main/java/org/solovyev/android/calculator/widget/BaseCalculatorWidgetProvider.java b/android-app/src/main/java/org/solovyev/android/calculator/widget/BaseCalculatorWidgetProvider.java index 35000e3a..503e47fb 100644 --- a/android-app/src/main/java/org/solovyev/android/calculator/widget/BaseCalculatorWidgetProvider.java +++ b/android-app/src/main/java/org/solovyev/android/calculator/widget/BaseCalculatorWidgetProvider.java @@ -34,7 +34,15 @@ import android.os.Build; import android.os.Bundle; import android.text.Html; import android.widget.RemoteViews; -import org.solovyev.android.calculator.*; + +import org.solovyev.android.calculator.App; +import org.solovyev.android.calculator.CalculatorButton; +import org.solovyev.android.calculator.CalculatorButtons; +import org.solovyev.android.calculator.CalculatorDisplayViewState; +import org.solovyev.android.calculator.CalculatorEditorViewState; +import org.solovyev.android.calculator.Locator; +import org.solovyev.android.calculator.Preferences; +import org.solovyev.android.calculator.R; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -42,6 +50,7 @@ import javax.annotation.Nullable; import static android.content.Intent.ACTION_CONFIGURATION_CHANGED; import static org.solovyev.android.calculator.CalculatorBroadcaster.ACTION_DISPLAY_STATE_CHANGED; import static org.solovyev.android.calculator.CalculatorBroadcaster.ACTION_EDITOR_STATE_CHANGED; +import static org.solovyev.android.calculator.CalculatorBroadcaster.ACTION_THEME_CHANGED; import static org.solovyev.android.calculator.CalculatorReceiver.newButtonClickedIntent; /** @@ -56,36 +65,12 @@ public abstract class BaseCalculatorWidgetProvider extends AppWidgetProvider { private static final String OPTION_APPWIDGET_HOST_CATEGORY = "appWidgetCategory"; private static final String ACTION_APPWIDGET_OPTIONS_CHANGED = "android.appwidget.action.APPWIDGET_UPDATE_OPTIONS"; - /* - ********************************************************************** - * - * FIELDS - * - ********************************************************************** - */ - @Nullable private String cursorColor; - /* - ********************************************************************** - * - * CONSTRUCTORS - * - ********************************************************************** - */ - protected BaseCalculatorWidgetProvider() { } - /* - ********************************************************************** - * - * METHODS - * - ********************************************************************** - */ - @Override public void onEnabled(Context context) { super.onEnabled(context); @@ -127,8 +112,9 @@ public abstract class BaseCalculatorWidgetProvider extends AppWidgetProvider { final CalculatorDisplayViewState displayState = Locator.getInstance().getDisplay().getViewState(); final Resources resources = context.getResources(); + final Preferences.SimpleTheme theme = App.getWidgetTheme().resolveThemeFor(App.getTheme()); for (int appWidgetId : appWidgetIds) { - final RemoteViews views = new RemoteViews(context.getPackageName(), getLayout(appWidgetManager, appWidgetId, resources)); + final RemoteViews views = new RemoteViews(context.getPackageName(), getLayout(appWidgetManager, appWidgetId, resources, theme)); for (CalculatorButton button : CalculatorButton.values()) { final PendingIntent pendingIntent = PendingIntent.getBroadcast(context, button.getButtonId(), newButtonClickedIntent(context, button), PendingIntent.FLAG_UPDATE_CURRENT); @@ -138,7 +124,7 @@ public abstract class BaseCalculatorWidgetProvider extends AppWidgetProvider { } updateEditorState(context, views, editorState); - updateDisplayState(context, views, displayState); + updateDisplayState(context, views, displayState, theme); CalculatorButtons.initMultiplicationButton(views); @@ -146,15 +132,15 @@ public abstract class BaseCalculatorWidgetProvider extends AppWidgetProvider { } } - private int getLayout(@Nonnull AppWidgetManager appWidgetManager, int appWidgetId, @Nonnull Resources resources) { + private int getLayout(@Nonnull AppWidgetManager appWidgetManager, int appWidgetId, @Nonnull Resources resources, @Nonnull Preferences.SimpleTheme theme) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { - return getLayoutJellyBean(appWidgetManager, appWidgetId, resources); + return getLayoutJellyBean(appWidgetManager, appWidgetId, resources, theme); } - return R.layout.widget_layout; + return theme.getWidgetLayout(App.getTheme()); } @TargetApi(Build.VERSION_CODES.JELLY_BEAN) - private int getLayoutJellyBean(AppWidgetManager appWidgetManager, int appWidgetId, Resources resources) { + private int getLayoutJellyBean(@Nonnull AppWidgetManager appWidgetManager, int appWidgetId, Resources resources, @Nonnull Preferences.SimpleTheme theme) { final Bundle options = appWidgetManager.getAppWidgetOptions(appWidgetId); if (options != null) { @@ -164,7 +150,7 @@ public abstract class BaseCalculatorWidgetProvider extends AppWidgetProvider { if (category != -1) { // If the value is WIDGET_CATEGORY_KEYGUARD, it's a lockscreen widget final boolean keyguard = category == WIDGET_CATEGORY_KEYGUARD; - if(keyguard) { + if (keyguard) { final int minHeightDp = options.getInt(AppWidgetManager.OPTION_APPWIDGET_MIN_HEIGHT, -1); final int minHeight = resources.getDimensionPixelSize(R.dimen.min_expanded_height_lock_screen); final boolean expanded = (minHeightDp >= minHeight / resources.getDisplayMetrics().density); @@ -176,11 +162,11 @@ public abstract class BaseCalculatorWidgetProvider extends AppWidgetProvider { } } } - return R.layout.widget_layout; + return theme.getWidgetLayout(App.getTheme()); } @Override - public void onReceive(Context context, Intent intent) { + public void onReceive(@Nonnull Context context, @Nonnull Intent intent) { super.onReceive(context, intent); final String action = intent.getAction(); @@ -192,15 +178,18 @@ public abstract class BaseCalculatorWidgetProvider extends AppWidgetProvider { updateState(context); } else if (ACTION_APPWIDGET_OPTIONS_CHANGED.equals(action)) { updateState(context); + } else if (ACTION_THEME_CHANGED.equals(action)) { + updateState(context); } } - private void updateDisplayState(@Nonnull Context context, @Nonnull RemoteViews views, @Nonnull CalculatorDisplayViewState displayState) { + private void updateDisplayState(@Nonnull Context context, @Nonnull RemoteViews views, @Nonnull CalculatorDisplayViewState displayState, @Nonnull Preferences.SimpleTheme theme) { + final Resources resources = context.getResources(); if (displayState.isValid()) { views.setTextViewText(R.id.calculator_display, displayState.getText()); - views.setTextColor(R.id.calculator_display, context.getResources().getColor(R.color.cpp_text)); + views.setTextColor(R.id.calculator_display, resources.getColor(theme == Preferences.SimpleTheme.material_light_theme ? R.color.cpp_text_inverse : R.color.cpp_text)); } else { - views.setTextColor(R.id.calculator_display, context.getResources().getColor(R.color.cpp_text_error)); + views.setTextColor(R.id.calculator_display, resources.getColor(theme == Preferences.SimpleTheme.material_light_theme ? R.color.cpp_text_inverse_error : R.color.cpp_text_error)); } } diff --git a/android-app/src/main/res/layout/cpp_simple_button_operators_material.xml b/android-app/src/main/res/layout/cpp_simple_button_operators_material.xml new file mode 100644 index 00000000..aab482a0 --- /dev/null +++ b/android-app/src/main/res/layout/cpp_simple_button_operators_material.xml @@ -0,0 +1,29 @@ + + + + +