diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/EmptyWidget.kt b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/EmptyWidget.kt new file mode 100644 index 000000000..08e8206a0 --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/EmptyWidget.kt @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2016 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +package org.isoron.uhabits.widgets + +import android.content.* +import android.view.* +import org.isoron.uhabits.widgets.views.* + +class EmptyWidget( + context: Context, + widgetId: Int +) : BaseWidget(context, widgetId) { + + override fun getOnClickPendingIntent(context: Context) = null + override fun refreshData(v: View) {} + override fun buildView() = EmptyWidgetView(context) + override fun getDefaultHeight() = 200 + override fun getDefaultWidth() = 200 +} diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidget.kt b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidget.kt index 49d8f69af..d9b2384fc 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidget.kt +++ b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidget.kt @@ -52,7 +52,6 @@ class StackWidget( serviceIntent.data = Uri.parse(serviceIntent.toUri(Intent.URI_INTENT_SCHEME)) remoteViews.setRemoteAdapter(StackWidgetType.getStackWidgetAdapterViewId(widgetType), serviceIntent) manager.notifyAppWidgetViewDataChanged(id, StackWidgetType.getStackWidgetAdapterViewId(widgetType)) - // TODO what should the empty view look like? remoteViews.setEmptyView(StackWidgetType.getStackWidgetAdapterViewId(widgetType), StackWidgetType.getStackWidgetEmptyViewId(widgetType)) return remoteViews diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetService.java b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetService.java index e8c4b606a..b753c2c2d 100644 --- a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetService.java +++ b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/StackWidgetService.java @@ -4,6 +4,7 @@ import android.appwidget.*; import android.content.*; import android.os.*; import android.support.annotation.*; +import android.util.Log; import android.widget.*; import org.isoron.uhabits.*; @@ -33,14 +34,14 @@ class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory private Context context; private int widgetId; private long[] habitIds; - private ArrayList habits = new ArrayList<>(); private StackWidgetType widgetType; + private ArrayList remoteViews = new ArrayList<>(); public StackRemoteViewsFactory(Context context, Intent intent) { this.context = context; widgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, - AppWidgetManager.INVALID_APPWIDGET_ID); + AppWidgetManager.INVALID_APPWIDGET_ID); int widgetTypeValue = intent.getIntExtra(WIDGET_TYPE, -1); String habitIdsStr = intent.getStringExtra(HABIT_IDS); @@ -63,76 +64,30 @@ class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory public int getCount() { - return habits.size(); + return habitIds.length; } @NonNull public WidgetDimensions getDimensionsFromOptions(@NonNull Context ctx, @NonNull Bundle options) { - int maxWidth = - (int) dpToPixels(ctx, options.getInt(OPTION_APPWIDGET_MAX_WIDTH)); - int maxHeight = - (int) dpToPixels(ctx, options.getInt(OPTION_APPWIDGET_MAX_HEIGHT)); - int minWidth = - (int) dpToPixels(ctx, options.getInt(OPTION_APPWIDGET_MIN_WIDTH)); - int minHeight = - (int) dpToPixels(ctx, options.getInt(OPTION_APPWIDGET_MIN_HEIGHT)); + int maxWidth = (int) dpToPixels(ctx, options.getInt(OPTION_APPWIDGET_MAX_WIDTH)); + int maxHeight = (int) dpToPixels(ctx, options.getInt(OPTION_APPWIDGET_MAX_HEIGHT)); + int minWidth = (int) dpToPixels(ctx, options.getInt(OPTION_APPWIDGET_MIN_WIDTH)); + int minHeight = (int) dpToPixels(ctx, options.getInt(OPTION_APPWIDGET_MIN_HEIGHT)); return new WidgetDimensions(minWidth, maxHeight, maxWidth, minHeight); } public RemoteViews getViewAt(int position) { - RemoteViews rv = null; - if (position < getCount()) - { - Habit habit = habits.get(position); - BaseWidget widget = initializeWidget(habit); - Bundle options = - AppWidgetManager.getInstance(context).getAppWidgetOptions(widgetId); - widget.setDimensions(getDimensionsFromOptions(context, options)); - final RemoteViews[] landscape = new RemoteViews[1]; - final RemoteViews[] portrait = new RemoteViews[1]; - - Object lock = new Object(); - final boolean[] flag = {false}; - - new Handler(Looper.getMainLooper()).post(() -> - { - synchronized (lock) - { - landscape[0] = - widget.getLandscapeRemoteViews(); - portrait[0] = - widget.getPortraitRemoteViews(); - flag[0] = true; - lock.notifyAll(); - } - }); - - synchronized (lock) - { - while (!flag[0]) - { - try - { - lock.wait(); - } - catch (InterruptedException e) - { - // ignored - } - } - } - - rv = new RemoteViews(landscape[0], portrait[0]); - } - - return rv; + Log.i("StackRemoteViewsFactory", "getViewAt " + position); + if (position < 0 || position > remoteViews.size()) return null; + return remoteViews.get(position); } - private BaseWidget initializeWidget(Habit habit) + @NonNull + private BaseWidget constructWidget(@NonNull Habit habit) { switch (widgetType) { @@ -147,12 +102,18 @@ class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory case STREAKS: return new StreakWidget(context, widgetId, habit); } - return null; + + throw new IllegalStateException(); } public RemoteViews getLoadingView() { - return null; + Bundle options = AppWidgetManager.getInstance(context).getAppWidgetOptions(widgetId); + EmptyWidget widget = new EmptyWidget(context, widgetId); + widget.setDimensions(getDimensionsFromOptions(context, options)); + RemoteViews landscapeViews = widget.getLandscapeRemoteViews(); + RemoteViews portraitViews = widget.getPortraitRemoteViews(); + return new RemoteViews(landscapeViews, portraitViews); } public int getViewTypeCount() @@ -162,25 +123,41 @@ class StackRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory public long getItemId(int position) { - return position; + return habitIds[position]; } public boolean hasStableIds() { - return false; + return true; } public void onDataSetChanged() { - habits.clear(); + Log.i("StackRemoteViewsFactory", "onDataSetChanged started"); + HabitsApplication app = (HabitsApplication) context.getApplicationContext(); HabitList habitList = app.getComponent().getHabitList(); + Bundle options = AppWidgetManager.getInstance(context).getAppWidgetOptions(widgetId); + ArrayList newRemoteViews = new ArrayList<>(); + + if (Looper.myLooper() == null) Looper.prepare(); for (long id : habitIds) { Habit h = habitList.getById(id); if (h == null) throw new HabitNotFoundException(); - habits.add(h); + + BaseWidget widget = constructWidget(h); + widget.setDimensions(getDimensionsFromOptions(context, options)); + + RemoteViews landscapeViews = widget.getLandscapeRemoteViews(); + RemoteViews portraitViews = widget.getPortraitRemoteViews(); + newRemoteViews.add(new RemoteViews(landscapeViews, portraitViews)); + + Log.i("StackRemoteViewsFactory", "onDataSetChanged constructed widget " + id); } + + remoteViews = newRemoteViews; + Log.i("StackRemoteViewsFactory", "onDataSetChanged ended"); } } diff --git a/uhabits-android/src/main/java/org/isoron/uhabits/widgets/views/EmptyWidgetView.java b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/views/EmptyWidgetView.java new file mode 100644 index 000000000..54b755f8e --- /dev/null +++ b/uhabits-android/src/main/java/org/isoron/uhabits/widgets/views/EmptyWidgetView.java @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2016 Álinson Santos Xavier + * + * This file is part of Loop Habit Tracker. + * + * Loop Habit Tracker is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation, either version 3 of the License, or (at your + * option) any later version. + * + * Loop Habit Tracker is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + */ + +package org.isoron.uhabits.widgets.views; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.widget.TextView; + +import org.isoron.uhabits.R; + +public class EmptyWidgetView extends HabitWidgetView +{ + + private TextView title; + + public EmptyWidgetView(Context context) + { + super(context); + init(); + } + + public void setTitle(String text) + { + title.setText(text); + } + + @Override + @NonNull + protected Integer getInnerLayoutId() + { + return R.layout.widget_graph; + } + + private void init() + { + title = (TextView) findViewById(R.id.title); + title.setVisibility(VISIBLE); + } +} diff --git a/uhabits-android/src/main/res/layout/widget_empty.xml b/uhabits-android/src/main/res/layout/widget_empty.xml new file mode 100644 index 000000000..60c4b3bae --- /dev/null +++ b/uhabits-android/src/main/res/layout/widget_empty.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + \ No newline at end of file