/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.dodgybits.shuffle.android.widget;
import static org.dodgybits.shuffle.android.core.util.Constants.cIdType;
import static org.dodgybits.shuffle.android.core.util.Constants.cPackage;
import static org.dodgybits.shuffle.android.core.util.Constants.cStringType;
import java.util.HashMap;
import org.dodgybits.android.shuffle.R;
import org.dodgybits.shuffle.android.core.model.Context;
import org.dodgybits.shuffle.android.core.model.Project;
import org.dodgybits.shuffle.android.core.model.Task;
import org.dodgybits.shuffle.android.core.model.TaskQuery;
import org.dodgybits.shuffle.android.core.model.persistence.ContextPersister;
import org.dodgybits.shuffle.android.core.model.persistence.DefaultEntityCache;
import org.dodgybits.shuffle.android.core.model.persistence.EntityCache;
import org.dodgybits.shuffle.android.core.model.persistence.ProjectPersister;
import org.dodgybits.shuffle.android.core.model.persistence.TaskPersister;
import org.dodgybits.shuffle.android.core.view.ContextIcon;
import org.dodgybits.shuffle.android.list.config.StandardTaskQueries;
import org.dodgybits.shuffle.android.persistence.provider.ContextProvider;
import org.dodgybits.shuffle.android.persistence.provider.ProjectProvider;
import org.dodgybits.shuffle.android.persistence.provider.TaskProvider;
import org.dodgybits.shuffle.android.preference.model.Preferences;
import roboguice.inject.ContentResolverProvider;
import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.ComponentName;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.Intent;
import android.content.SharedPreferences.Editor;
import android.database.Cursor;
import android.net.Uri;
import android.util.Log;
import android.view.View;
import android.widget.RemoteViews;
/**
* A widget provider. We have a string that we pull from a preference in order to show
* the configuration settings and the current time when the widget was updated. We also
* register a BroadcastReceiver for time-changed and timezone-changed broadcasts, and
* update then too.
*/
public class WidgetProvider extends AppWidgetProvider {
// log tag
private static final String cTag = "WidgetProvider";
private static final HashMap<String,Integer> sIdCache = new HashMap<String,Integer>();
@Override
public void onReceive(android.content.Context context, Intent intent) {
super.onReceive(context, intent);
String action = intent.getAction();
if (TaskProvider.cUpdateIntent.equals(action) ||
ProjectProvider.cUpdateIntent.equals(action) ||
ContextProvider.cUpdateIntent.equals(action)) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
// Retrieve the identifiers for each instance of your chosen widget.
ComponentName thisWidget = new ComponentName(context, WidgetProvider.class);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
if (appWidgetIds != null && appWidgetIds.length > 0) {
this.onUpdate(context, appWidgetManager, appWidgetIds);
}
}
}
@Override
public void onUpdate(android.content.Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
Log.d(cTag, "onUpdate");
final int N = appWidgetIds.length;
for (int i=0; i<N; i++) {
int appWidgetId = appWidgetIds[i];
String prefKey = Preferences.getWidgetQueryKey(appWidgetId);
String queryName = Preferences.getWidgetQuery(context, prefKey);
updateAppWidget(context, appWidgetManager, appWidgetId, queryName);
}
}
@Override
public void onDeleted(android.content.Context context, int[] appWidgetIds) {
Log.d(cTag, "onDeleted");
// When the user deletes the widget, delete the preference associated with it.
final int N = appWidgetIds.length;
Editor editor = Preferences.getEditor(context);
for (int i=0; i<N; i++) {
String prefKey = Preferences.getWidgetQueryKey(appWidgetIds[i]);
editor.remove(prefKey);
}
editor.commit();
}
@Override
public void onEnabled(android.content.Context context) {
}
@Override
public void onDisabled(android.content.Context context) {
}
static void updateAppWidget(final android.content.Context androidContext, AppWidgetManager appWidgetManager,
int appWidgetId, String queryName) {
Log.d(cTag, "updateAppWidget appWidgetId=" + appWidgetId + " queryName=" + queryName);
// TODO inject
ContentResolverProvider provider = new ContentResolverProvider() {
@Override
public ContentResolver get() {
return androidContext.getContentResolver();
}
};
TaskPersister taskPersister = new TaskPersister(provider);
ProjectPersister projectPersister = new ProjectPersister(provider);
EntityCache<Project> projectCache = new DefaultEntityCache<Project>(projectPersister);
ContextPersister contextPersister = new ContextPersister(provider);
EntityCache<Context> contextCache = new DefaultEntityCache<Context>(contextPersister);
RemoteViews views = new RemoteViews(androidContext.getPackageName(), R.layout.widget);
TaskQuery query = StandardTaskQueries.getQuery(queryName);
if (query == null) return;
int titleId = getIdentifier(androidContext, "title_" + queryName, cStringType);
views.setTextViewText(R.id.title, androidContext.getString(titleId));
Intent intent = new Intent(Intent.ACTION_INSERT, TaskProvider.Tasks.CONTENT_URI);
PendingIntent pendingIntent = PendingIntent.getActivity(androidContext, 0, intent, 0);
views.setOnClickPendingIntent(R.id.add_task, pendingIntent);
Cursor taskCursor = androidContext.getContentResolver().query(
TaskProvider.Tasks.CONTENT_URI,
TaskProvider.Tasks.cFullProjection,
query.getSelection(),
query.getSelectionArgs(),
query.getSortOrder());
for (int taskCount = 1; taskCount <= 4; taskCount++) {
Task task = null;
Project project = null;
Context context = null;
if (taskCursor.moveToNext()) {
task = taskPersister.read(taskCursor);
project = projectCache.findById(task.getProjectId());
context = contextCache.findById(task.getContextId());
}
int descriptionViewId = getIdIdentifier(androidContext, "description_" + taskCount);
views.setTextViewText(descriptionViewId, task != null ? task.getDescription() : "");
// views.setInt(descriptionViewId, "setLines", project == null ? 2 : 1);
int projectViewId = getIdIdentifier(androidContext, "project_" + taskCount);
views.setViewVisibility(projectViewId, project == null ? View.INVISIBLE : View.VISIBLE);
views.setTextViewText(projectViewId, project != null ? project.getName() : "");
int contextIconId = getIdIdentifier(androidContext, "context_icon_" + taskCount);
String iconName = context != null ? context.getIconName() : null;
ContextIcon icon = ContextIcon.createIcon(iconName, androidContext.getResources());
if (icon != ContextIcon.NONE) {
views.setImageViewResource(contextIconId, icon.smallIconId);
views.setViewVisibility(contextIconId, View.VISIBLE);
} else {
views.setViewVisibility(contextIconId, View.INVISIBLE);
}
if (task != null) {
Uri.Builder builder = TaskProvider.Tasks.CONTENT_URI.buildUpon();
ContentUris.appendId(builder, task.getLocalId().getId());
Uri taskUri = builder.build();
intent = new Intent(Intent.ACTION_EDIT, taskUri);
Log.d(cTag, "Adding pending event for viewing uri " + taskUri);
pendingIntent = PendingIntent.getActivity(androidContext, 0, intent, 0);
views.setOnClickPendingIntent(descriptionViewId, pendingIntent);
views.setOnClickPendingIntent(projectViewId, pendingIntent);
views.setOnClickPendingIntent(contextIconId, pendingIntent);
}
}
taskCursor.close();
appWidgetManager.updateAppWidget(appWidgetId, views);
}
static int getIdIdentifier(android.content.Context context, String name) {
Integer id = sIdCache.get(name);
if (id == null) {
id = getIdentifier(context, name, cIdType);
sIdCache.put(name, id);
}
Log.d(cTag, "Got id " + id + " for resource " + name);
return id;
}
static int getIdentifier(android.content.Context context, String name, String type) {
int id = context.getResources().getIdentifier(
name, type, cPackage);
Log.d(cTag, "Got id " + id + " for resource " + name);
return id;
}
}