diff --git a/core/res/drawable-hdpi/widget_preview.png b/core/res/drawable-hdpi/widget_preview.png
new file mode 100644
index 00000000..e6fcab62
Binary files /dev/null and b/core/res/drawable-hdpi/widget_preview.png differ
diff --git a/core/res/layout-v11/activity_widgetconfig.xml b/core/res/layout-v11/activity_widgetconfig.xml
index 7f1169aa..9cf2564f 100644
--- a/core/res/layout-v11/activity_widgetconfig.xml
+++ b/core/res/layout-v11/activity_widgetconfig.xml
@@ -62,13 +62,21 @@
android:id="@+id/filter_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/margin_default" />
+ android:layout_marginTop="@dimen/margin_half" />
+
+
+ android:layout_marginTop="@dimen/margin_half" />
+ android:paddingRight="@dimen/widget_list_item_padding" >
-
-
+ android:layout_width="6dp"
+ android:layout_height="@dimen/widget_list_item_height" />
+
@@ -58,9 +59,10 @@
android:layout_height="wrap_content"
android:layout_alignBaseline="@id/ratio_text"
android:layout_alignParentLeft="true"
- android:layout_marginLeft="@dimen/margin_torrentlistleft"
- android:layout_toLeftOf="@id/priority_image"
+ android:layout_marginLeft="@dimen/widget_list_item_padding_left"
+ android:layout_toLeftOf="@id/ratio_text"
+ android:maxLines="1"
android:textIsSelectable="false"
android:textSize="@dimen/text_small" />
-
+
\ No newline at end of file
diff --git a/core/res/layout-v11/list_item_widget_light.xml b/core/res/layout-v11/list_item_widget_light.xml
index 860ef687..3e7fdd21 100644
--- a/core/res/layout-v11/list_item_widget_light.xml
+++ b/core/res/layout-v11/list_item_widget_light.xml
@@ -18,26 +18,26 @@
+ android:paddingRight="@dimen/widget_list_item_padding" >
-
-
+ android:layout_width="6dp"
+ android:layout_height="@dimen/widget_list_item_height" />
+
@@ -58,9 +59,10 @@
android:layout_height="wrap_content"
android:layout_alignBaseline="@id/ratio_text"
android:layout_alignParentLeft="true"
- android:layout_marginLeft="@dimen/margin_torrentlistleft"
- android:layout_toLeftOf="@id/priority_image"
+ android:layout_marginLeft="@dimen/widget_list_item_padding_left"
+ android:layout_toLeftOf="@id/ratio_text"
+ android:maxLines="1"
android:textIsSelectable="false"
android:textSize="@dimen/text_small" />
-
+
\ No newline at end of file
diff --git a/core/res/layout-v11/widget_torrents_dark.xml b/core/res/layout-v11/widget_torrents_dark.xml
index 3959a922..31b51077 100644
--- a/core/res/layout-v11/widget_torrents_dark.xml
+++ b/core/res/layout-v11/widget_torrents_dark.xml
@@ -1,4 +1,20 @@
+
+
+
+ android:paddingRight="@dimen/margin_half"
+ android:paddingTop="3dp" >
@@ -40,20 +70,22 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="-4dip"
+ android:ellipsize="marquee"
android:fontFamily="sans-serif-light"
+ android:maxLines="1"
android:textColor="@color/text_actionbar_dark"
android:textIsSelectable="false"
android:textSize="@dimen/ui_navigation_server" />
-
-
+
+
+
+ android:paddingRight="@dimen/margin_half"
+ android:paddingTop="3dp" >
@@ -40,20 +70,22 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="-4dip"
+ android:ellipsize="marquee"
android:fontFamily="sans-serif-light"
+ android:maxLines="1"
android:textColor="@color/text_actionbar_light"
android:textIsSelectable="false"
android:textSize="@dimen/ui_navigation_server" />
-
-
diff --git a/core/res/values/dimens.xml b/core/res/values/dimens.xml
index 52c36924..a7e05008 100644
--- a/core/res/values/dimens.xml
+++ b/core/res/values/dimens.xml
@@ -46,5 +46,10 @@
20dp
200dp
-1dp
+ 46dp
+ 6dp
+ 54dp
+ 6dp
+ 12dp
diff --git a/core/res/values/strings.xml b/core/res/values/strings.xml
index b5856e1e..0d90b8cb 100644
--- a/core/res/values/strings.xml
+++ b/core/res/values/strings.xml
@@ -190,11 +190,13 @@
New torrents for %1$s
+ Loading…
Open Transdroid
SERVER VIEW
LOOK & FEEL
- Reverse sort order
- Use dark theme
+ SORT ORDER
+ Reversed sort order
+ Use dark theme (no preview)
DONE
Servers
diff --git a/core/res/xml/appwidget_info.xml b/core/res/xml/appwidget_info.xml
index a236ffa0..7846f411 100644
--- a/core/res/xml/appwidget_info.xml
+++ b/core/res/xml/appwidget_info.xml
@@ -23,7 +23,7 @@
android:minResizeHeight="110dip"
android:minResizeWidth="110dp"
android:minWidth="180dp"
- android:previewImage="@drawable/ic_launcher"
+ android:previewImage="@drawable/widget_preview"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="3600000"
android:widgetCategory="home_screen|keyguard" />
diff --git a/core/src/org/transdroid/core/gui/lists/SimpleListItemSpinnerAdapter.java b/core/src/org/transdroid/core/gui/lists/SimpleListItemSpinnerAdapter.java
new file mode 100644
index 00000000..0d33e654
--- /dev/null
+++ b/core/src/org/transdroid/core/gui/lists/SimpleListItemSpinnerAdapter.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2010-2013 Eric Kok et al.
+ *
+ * Transdroid 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.
+ *
+ * Transdroid 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 Transdroid. If not, see .
+ */
+package org.transdroid.core.gui.lists;
+
+import java.util.List;
+
+import android.content.Context;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ArrayAdapter;
+import android.widget.TextView;
+
+/**
+ * A wrapper around {@link ArrayAdapter} that contains {@link SimpleListItem}s which simply show their name in the
+ * Spinner. The standard Android spinner resources are used for the layout.
+ * @author Eric Kok
+ */
+public class SimpleListItemSpinnerAdapter extends ArrayAdapter {
+
+ /**
+ * Constructs the adapter, supplying the {@link SimpleListItem}s to show in the spinner. The given resource will be
+ * ignored as the standard Android Spinner layout is used instead.
+ * @param context The UI context to inflate the layout in
+ * @param resource This is ignored; android.R.layout.simple_spinner_item is always used instead
+ * @param objects The items to show in the spinner, which can simply display some name
+ */
+ public SimpleListItemSpinnerAdapter(Context context, int resource, List objects) {
+ super(context, android.R.layout.simple_spinner_item, objects);
+ setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ // This relies on the ArrayAdapter implementation and the used standard xml layouts that simply return a
+ // TextView; this can then be filled with the SimpleListItem's name instead of the standard toString()
+ // implementation
+ TextView text = (TextView) super.getView(position, convertView, parent);
+ text.setText(getItem(position).getName());
+ return text;
+ }
+
+ @Override
+ public View getDropDownView(int position, View convertView, ViewGroup parent) {
+ // This relies on the ArrayAdapter implementation and the used standard xml layouts that simply return a
+ // TextView; this can then be filled with the SimpleListItem's name instead of the standard toString()
+ // implementation
+ TextView text = (TextView) super.getDropDownView(position, convertView, parent);
+ text.setText(getItem(position).getName());
+ return text;
+ }
+
+}
diff --git a/core/src/org/transdroid/core/gui/lists/SortByListItem.java b/core/src/org/transdroid/core/gui/lists/SortByListItem.java
index d05c6aef..90e6110d 100644
--- a/core/src/org/transdroid/core/gui/lists/SortByListItem.java
+++ b/core/src/org/transdroid/core/gui/lists/SortByListItem.java
@@ -16,18 +16,42 @@
*/
package org.transdroid.core.gui.lists;
+import org.transdroid.core.R;
import org.transdroid.daemon.TorrentsSortBy;
+import android.content.Context;
+
/**
* Represents a way in which a torrents list can be sorted.
* @author Eric Kok
*/
public class SortByListItem implements SimpleListItem {
- private TorrentsSortBy sortBy;
+ private final TorrentsSortBy sortBy;
+ private final String name;
- public SortByListItem(TorrentsSortBy sortBy) {
+ public SortByListItem(Context context, TorrentsSortBy sortBy) {
this.sortBy = sortBy;
+ switch (sortBy) {
+ case DateAdded:
+ this.name = context.getString(R.string.action_sort_added);
+ break;
+ case DateDone:
+ this.name = context.getString(R.string.action_sort_done);
+ break;
+ case Ratio:
+ this.name = context.getString(R.string.action_sort_ratio);
+ break;
+ case Status:
+ this.name = context.getString(R.string.action_sort_status);
+ break;
+ case UploadSpeed:
+ this.name = context.getString(R.string.action_sort_upspeed);
+ break;
+ default:
+ this.name = context.getString(R.string.action_sort_alpha);
+ break;
+ }
}
/**
@@ -40,7 +64,7 @@ public class SortByListItem implements SimpleListItem {
@Override
public String getName() {
- return sortBy.name();
+ return name;
}
}
diff --git a/core/src/org/transdroid/core/widget/WidgetConfigActivity.java b/core/src/org/transdroid/core/widget/WidgetConfigActivity.java
index 2478623e..01d8276f 100644
--- a/core/src/org/transdroid/core/widget/WidgetConfigActivity.java
+++ b/core/src/org/transdroid/core/widget/WidgetConfigActivity.java
@@ -30,10 +30,9 @@ import org.androidannotations.annotations.ViewById;
import org.transdroid.core.R;
import org.transdroid.core.app.settings.ApplicationSettings;
import org.transdroid.core.app.settings.ServerSetting;
-import org.transdroid.core.gui.lists.SimpleListItem;
+import org.transdroid.core.gui.lists.SimpleListItemSpinnerAdapter;
import org.transdroid.core.gui.lists.SortByListItem;
import org.transdroid.core.gui.lists.TorrentsAdapter;
-import org.transdroid.core.gui.navigation.FilterListItemAdapter;
import org.transdroid.core.gui.navigation.StatusType;
import org.transdroid.core.gui.navigation.StatusType.StatusTypeFilter;
import org.transdroid.core.service.ConnectivityHelper;
@@ -111,18 +110,20 @@ public class WidgetConfigActivity extends SherlockActivity {
@AfterViews
protected void init() {
- // Populate the selection spinners
- List sortOrders = new ArrayList();
+ // Populate the selection spinners with custom array adapters
+ List sortOrders = new ArrayList();
for (TorrentsSortBy order : TorrentsSortBy.values()) {
- sortOrders.add(new SortByListItem(order));
+ sortOrders.add(new SortByListItem(this, order));
}
-
- serverSpinner.setAdapter(new FilterListItemAdapter(this, applicationSettings.getServerSettings()));
- filterSpinner.setAdapter(new FilterListItemAdapter(this, StatusType.getAllStatusTypes(this)));
- sortSpinner.setAdapter(new FilterListItemAdapter(this, sortOrders));
+ serverSpinner.setAdapter(new SimpleListItemSpinnerAdapter(this, 0, applicationSettings
+ .getServerSettings()));
+ filterSpinner.setAdapter(new SimpleListItemSpinnerAdapter(this, 0, StatusType
+ .getAllStatusTypes(this)));
+ sortSpinner.setAdapter(new SimpleListItemSpinnerAdapter(this, 0, sortOrders));
// TODO: Update to AndroidAnnotations 3.0 and use @CheckedChanged
reverseorderCheckBox.setOnCheckedChangeListener(reverseorderCheckedChanged);
torrentsList.setAdapter(previewTorrentsAdapter);
+ torrentsList.setEmptyView(errorText);
// Set up action bar with a done button
// Inspired by NoNonsenseNotes's ListWidgetConfig.java (Apache License, Version 2.0)
@@ -257,4 +258,5 @@ public class WidgetConfigActivity extends SherlockActivity {
}
};
+
}
diff --git a/core/src/org/transdroid/core/widget/WidgetProvider.java b/core/src/org/transdroid/core/widget/WidgetProvider.java
index e599d7ab..c16165c4 100644
--- a/core/src/org/transdroid/core/widget/WidgetProvider.java
+++ b/core/src/org/transdroid/core/widget/WidgetProvider.java
@@ -20,7 +20,7 @@ import org.androidannotations.annotations.Bean;
import org.androidannotations.annotations.EReceiver;
import org.transdroid.core.R;
import org.transdroid.core.app.settings.*;
-import org.transdroid.core.app.settings.ServerSetting;
+import org.transdroid.core.gui.TorrentsActivity_;
import org.transdroid.core.gui.log.Log;
import android.annotation.TargetApi;
@@ -40,46 +40,40 @@ public class WidgetProvider extends AppWidgetProvider {
public static final String INTENT_STARTSERVER = "org.transdroid.START_SERVER";
public static final String EXTRA_TORRENT = "extra_torrent";
public static final String EXTRA_SERVER = "extra_server";
+ public static final String EXTRA_REFRESH = "extra_refresh";
@Bean
protected ApplicationSettings applicationSettings;
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent != null && intent.hasExtra(EXTRA_REFRESH)) {
+ // Manually requested a refresh for the app widget of which the ID was supplied
+ int appWidgetId = intent.getIntExtra(EXTRA_REFRESH, -1);
+ AppWidgetManager.getInstance(context).updateAppWidget(appWidgetId,
+ buildRemoteViews(context, appWidgetId, applicationSettings.getWidgetConfig(appWidgetId)));
+ AppWidgetManager.getInstance(context).notifyAppWidgetViewDataChanged(appWidgetId, R.id.torrents_list);
+ return;
+ }
+ super.onReceive(context, intent);
+ }
+
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
for (int appWidgetId : appWidgetIds) {
appWidgetManager.updateAppWidget(appWidgetId,
buildRemoteViews(context, appWidgetId, applicationSettings.getWidgetConfig(appWidgetId)));
+ appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetId, R.id.torrents_list);
}
}
@Override
public void onDeleted(Context context, int[] appWidgetIds) {
- super.onDeleted(context, appWidgetIds);
for (int appWidgetId : appWidgetIds) {
applicationSettings.removeWidgetConfig(appWidgetId);
}
}
- @Override
- public void onReceive(Context context, Intent intent) {
-
- if (intent == null || intent.getAction() == null || intent.getExtras() == null
- || !intent.hasExtra(EXTRA_SERVER))
- return;
-
- // Launch an Intent to start Transdroid on some specific server; and possibly a specific torrent too
- Intent start = new Intent(INTENT_STARTSERVER);
- start.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
- start.putExtra(EXTRA_SERVER, intent.getIntExtra(EXTRA_SERVER, -1));
- if (intent.getAction().equals(EXTRA_TORRENT)) {
- start.putExtra(EXTRA_TORRENT, intent.getParcelableExtra(EXTRA_TORRENT));
- }
- context.startActivity(start);
-
- super.onReceive(context, intent);
-
- }
-
/**
* Loads and sets up the layout for some specific app widget given the user's widget settings. Note that the views
* for the list view rows are loaded separately in the {@link WidgetViewsFactory}.
@@ -103,26 +97,44 @@ public class WidgetProvider extends AppWidgetProvider {
// Load the dark or light widget layout xml
RemoteViews rv = new RemoteViews(context.getPackageName(),
- config.shouldUseDarkTheme() ? R.layout.list_item_widget_dark : R.layout.list_item_widget_light);
+ config.shouldUseDarkTheme() ? R.layout.widget_torrents_dark : R.layout.widget_torrents_light);
// Set up the widget's list view loading service which refers to the WidgetViewsFactory
- // Use a unique data URI next to the extra to make sure the intents are unique form each widget
- Intent intent = new Intent(context, WidgetService.class);
- intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME) + "//widget/" + appWidgetId + "/server/"
- + config.getServerId()));
- intent.putExtra(EXTRA_SERVER, config.getServerId());
- rv.setRemoteAdapter(appWidgetId, R.id.torrents_list, intent);
+ Intent data = new Intent(context, WidgetService_.class);
+ data.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
+ data.setData(Uri.parse(data.toUri(Intent.URI_INTENT_SCHEME)));
+ rv.setRemoteAdapter(appWidgetId, R.id.torrents_list, data);
+ Intent open = new Intent(context, TorrentsActivity_.class);
+ open.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
rv.setPendingIntentTemplate(R.id.torrents_list,
- PendingIntent.getActivity(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
+ PendingIntent.getActivity(context, appWidgetId, open, PendingIntent.FLAG_UPDATE_CURRENT));
rv.setEmptyView(R.id.torrents_list, R.id.error_text);
- rv.setTextViewText(R.id.error_text, context.getString(R.string.navigation_emptytorrents));
+ rv.setTextViewText(R.id.error_text, context.getString(R.string.widget_loading));
- // Show the server and status type filter from the widget configuration
+ // Show the server and status type filter from the widget configuration in the 'action bar'
ServerSetting server = appSettings.getServerSetting(config.getServerId());
rv.setTextViewText(R.id.server_text, server.getName());
rv.setTextViewText(R.id.filter_text, config.getStatusType().getFilterItem(context).getName());
+
+ // Set up the START_SERVER intent for 'action bar' clicks to start Transdroid normally
+ Intent start = new Intent(context, TorrentsActivity_.class);
+ //start.setData(Uri.parse("intent://widget/" + appWidgetId + "/start/" + config.getServerId()));
+ start.setAction(INTENT_STARTSERVER);
+ start.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ start.putExtra(EXTRA_SERVER, config.getServerId());
rv.setOnClickPendingIntent(R.id.icon_image,
- PendingIntent.getActivity(context, 0, intent.cloneFilter(), PendingIntent.FLAG_UPDATE_CURRENT));
+ PendingIntent.getActivity(context, appWidgetId, start, PendingIntent.FLAG_UPDATE_CURRENT));
+ rv.setOnClickPendingIntent(R.id.navigation_view,
+ PendingIntent.getActivity(context, appWidgetId, start, PendingIntent.FLAG_UPDATE_CURRENT));
+
+ // Set up the widgets refresh button pending intent (calling this WidgetProvider itself)
+ // Make sure that the intent is unique using a custom data path (rather than just the extras)
+ Intent refresh = new Intent(context, WidgetProvider_.class);
+ refresh.setData(Uri.parse("intent://widget/" + appWidgetId + "/refresh"));
+ refresh.putExtra(EXTRA_REFRESH, appWidgetId);
+ refresh.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
+ rv.setOnClickPendingIntent(R.id.refresh_button,
+ PendingIntent.getBroadcast(context, appWidgetId, refresh, PendingIntent.FLAG_UPDATE_CURRENT));
return rv;
diff --git a/core/src/org/transdroid/core/widget/WidgetService.java b/core/src/org/transdroid/core/widget/WidgetService.java
index 915bebd9..7f3ca7e3 100644
--- a/core/src/org/transdroid/core/widget/WidgetService.java
+++ b/core/src/org/transdroid/core/widget/WidgetService.java
@@ -39,7 +39,6 @@ import android.annotation.TargetApi;
import android.appwidget.AppWidgetManager;
import android.content.Context;
import android.content.Intent;
-import android.content.res.Resources;
import android.os.Build;
import android.widget.RemoteViews;
import android.widget.RemoteViewsService;
@@ -131,29 +130,28 @@ class WidgetViewsFactory implements RemoteViewsService.RemoteViewsFactory {
// Bind the torrent details texts and status colour
Torrent torrent = torrents.get(position);
LocalTorrent local = LocalTorrent.fromTorrent(torrent);
- Resources r = context.getResources();
rv.setTextViewText(R.id.name_text, torrent.getName());
- rv.setTextViewText(R.id.progress_text, local.getProgressSizeText(r, false));
- rv.setTextViewText(R.id.ratio_text, local.getProgressEtaRatioText(r));
+ rv.setTextViewText(R.id.progress_text, local.getProgressSizeText(context.getResources(), false));
+ rv.setTextViewText(R.id.ratio_text, local.getProgressEtaRatioText(context.getResources()));
int statusColour;
switch (torrent.getStatusCode()) {
case Downloading:
- statusColour = r.getColor(r.getColor(R.color.torrent_downloading));
+ statusColour = R.color.torrent_downloading;
break;
case Paused:
- statusColour = r.getColor(r.getColor(R.color.torrent_paused));
+ statusColour = R.color.torrent_paused;
break;
case Seeding:
- statusColour = r.getColor(r.getColor(R.color.torrent_seeding));
+ statusColour = R.color.torrent_seeding;
break;
case Error:
- statusColour = r.getColor(r.getColor(R.color.torrent_error));
+ statusColour = R.color.torrent_error;
break;
default: // Checking, Waiting, Queued, Unknown
- statusColour = r.getColor(r.getColor(R.color.torrent_other));
+ statusColour = R.color.torrent_other;
break;
}
- rv.setInt(R.id.status_view, "setBackgroundColor", r.getColor(statusColour));
+ rv.setInt(R.id.status_view, "setBackgroundColor", context.getResources().getColor(statusColour));
Intent startIntent = new Intent();
startIntent.putExtra(WidgetProvider.EXTRA_SERVER, config.getServerId());
startIntent.putExtra(WidgetProvider.EXTRA_TORRENT, torrent);
@@ -170,7 +168,9 @@ class WidgetViewsFactory implements RemoteViewsService.RemoteViewsFactory {
@Override
public void onDestroy() {
- torrents.clear();
+ if (torrents != null)
+ torrents.clear();
+ torrents = null;
}
@Override