/* * Copyright (C) 2009 Virgil Dobjanschi, Jeff Sharkey * * 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 no.java.schedule.activities; import android.app.*; import android.content.*; import android.content.DialogInterface.OnMultiChoiceClickListener; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.content.res.Resources; import android.database.Cursor; import android.net.Uri; import android.os.Bundle; import android.preference.PreferenceManager; import android.provider.BaseColumns; import android.util.Log; import android.view.*; import android.widget.TabHost; import android.widget.TabHost.TabSpec; import android.widget.TextView; import android.widget.Toast; import no.java.schedule.R; import no.java.schedule.activities.adapters.ScheduleSorting; import no.java.schedule.activities.tabs.MoreMenu; import no.java.schedule.activities.tabs.SessionsExpandableListActivity; import no.java.schedule.activities.tasks.LoadDatabaseFromIncogitoWebserviceTask; import no.java.schedule.provider.SessionsContract.Blocks; import no.java.schedule.provider.SessionsContract.Tracks; import no.java.schedule.provider.SessionsContract.TracksColumns; import no.java.schedule.provider.SessionsProvider; import no.java.schedule.util.AppUtil; import static no.java.schedule.activities.tabs.SessionsExpandableListActivity.EXTRA_CHILD_MODE; import static no.java.schedule.activities.tabs.SessionsListActivity.CHILD_MODE.STARRED; import static no.java.schedule.activities.tabs.SessionsListActivity.CHILD_MODE.VISIBLE_TRACKS; import static no.java.schedule.provider.SessionsContract.Tracks.CONTENT_URI; /** * The main activity */ public class MainActivity extends TabActivity { public static final String TAG = "MainActivity"; private TabHost mTabHost; private Resources mResources; private static final String TAG_SCHEDULE = "schedule"; private static final String TAG_STARRED = "starred"; private static final String TAG_TWITTER = "twitter"; private static final String TAG_TRACKS = "tracks"; private static final String TAG_OTHER = "other"; private static final String PREF_STICKY_TAB = "stickyTab"; private boolean expanded = true; //TODO - this is global to all tabs, ie wont be in sync with option menu private static final String EXTRA_SORTING = "no.java.schedule.extra.sorting"; private Dialog loadingDialog; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mTabHost = getTabHost(); mResources = getResources(); if (!localDataNeedsRefresh()) { new LoadDatabaseFromIncogitoWebserviceTask(this).execute(); } // Add various tabs addScheduleTab(ScheduleSorting.SCHEDULE); addStarredTab(); addOtherTab(); // Restore last saved sticky tab SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); int currentTab = prefs.getInt(PREF_STICKY_TAB, 0); mTabHost.setCurrentTab(currentTab); } /** * Check if we have valid data in our local {@link SessionsProvider} * database, which means we can show UI right away. * * @return true if data must be loaded */ protected boolean localDataNeedsRefresh() { Cursor cursor = managedQuery(CONTENT_URI, new String[] {BaseColumns._ID}, null, null, null); return cursor !=null && (cursor.getCount() > 0) ; } /** {@inheritDoc} */ @Override protected void onPause() { super.onPause(); // When closing activity, save current tab as sticky SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences.Editor editor = prefs.edit(); int currentTab = mTabHost.getCurrentTab(); editor.putInt(PREF_STICKY_TAB, currentTab); editor.commit(); } /** * Add tab for full session schedule. */ private void addScheduleTab(ScheduleSorting sorting) { Intent intent = new Intent(this, SessionsExpandableListActivity.class); intent.setData(Blocks.CONTENT_URI); intent.putExtra(EXTRA_SORTING, sorting); intent.putExtra(EXTRA_CHILD_MODE, VISIBLE_TRACKS); TabSpec spec = mTabHost.newTabSpec(TAG_SCHEDULE); spec.setIndicator( mResources.getString(R.string.schedule), mResources.getDrawable(R.drawable.ic_tab_schedule) ); spec.setContent(intent); mTabHost.addTab(spec); } /** * Add tab for starred sessions_menu. */ private void addStarredTab() { Intent intent = new Intent(this, SessionsExpandableListActivity.class); intent.setData(Blocks.CONTENT_URI); intent.putExtra(EXTRA_CHILD_MODE,STARRED); TabSpec spec = mTabHost.newTabSpec(TAG_STARRED); spec.setIndicator(mResources.getString(R.string.starred), mResources .getDrawable(R.drawable.ic_tab_starred)); spec.setContent(intent); mTabHost.addTab(spec); } private void addOtherTab() { Intent intent = new Intent(this, MoreMenu.class); intent.setData(Blocks.CONTENT_URI); TabSpec spec = mTabHost.newTabSpec(TAG_OTHER); spec.setIndicator(mResources.getString(R.string.more), mResources.getDrawable(R.drawable.ic_menu_more)); spec.setContent(intent); mTabHost.addTab(spec); } /** {@inheritDoc} */ @Override public boolean onCreateOptionsMenu(Menu menu) { super.onCreateOptionsMenu(menu); MenuInflater inflater = this.getMenuInflater(); inflater.inflate(R.menu.sessions_menu, menu); return true; } @Override public void onConfigurationChanged(Configuration newConfig) { //TODO handle super.onConfigurationChanged(newConfig); } /** {@inheritDoc} */ @Override public boolean onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); // Show or hide tracks menu option depending on tab //boolean showTracks = (mTabHost.getCurrentTabTag() == TAG_SCHEDULE); //menu.findItem(R.id.menu_tracks).setVisible(showTracks); return true; } /** {@inheritDoc} */ @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_search: this.onSearchRequested(); return true; case R.id.menu_schedule_view: showDialog(R.id.dialog_schedule_view); return true; case R.id.menu_level_1: AppUtil.showLevel(this, 1); return true; case R.id.menu_level_1b: AppUtil.showLevel(this, 1); return true; case R.id.menu_level_2: AppUtil.showLevel(this, 2); return true; case R.id.menu_about: showDialog(R.id.dialog_about); return true; case R.id.menu_expand_or_collapse: toggleExpandAndCollapse(item); return true; case R.id.menu_refresh: new LoadDatabaseFromIncogitoWebserviceTask(this).execute(); } return false; } private void toggleExpandAndCollapse(MenuItem item) { if (expanded){ collapseAll(); item.setTitle(getString(R.string.expand)); } else { expandAll(); item.setTitle(R.string.collapse); } } protected void collapseAll() { //int currentTab = mTabHost.getCurrentTab(); Activity a = getCurrentActivity(); if (a instanceof SessionsExpandableListActivity) { SessionsExpandableListActivity sela = (SessionsExpandableListActivity) a; sela.collapseAll(); Log.i("collapseAll()", "collapsed!"); } expanded = false; } protected void expandAll() { Activity a = getCurrentActivity(); if (a instanceof SessionsExpandableListActivity) { SessionsExpandableListActivity sela = (SessionsExpandableListActivity) a; sela.expandAll(); Log.i("expandAll()", "expanded!"); } expanded = true; } /** {@inheritDoc} */ @Override protected Dialog onCreateDialog(int id) { switch (id) { case R.id.dialog_load: loadingDialog = buildLoadingDialog(); return loadingDialog; //case R.id.dialog_tracks: // return buildTracksDialog(); case R.id.dialog_schedule_view: return buildChooseScheduleView(); case R.id.dialog_about: return buildAboutDialog(); default: return null; } } private Dialog buildChooseScheduleView() { final CharSequence[] items = {"Schedule", "Tracks", "Speakers"}; AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle("View sort"); builder.setSingleChoiceItems(items, -1, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int item) { Toast.makeText(MainActivity.this, items[item], Toast.LENGTH_SHORT).show(); switch(item){ case 0: // Schedule sendChangeSortingIntent(ScheduleSorting.SCHEDULE); break; case 1: // Tracks sendChangeSortingIntent(ScheduleSorting.TRACKS); break; case 2: // Speakers sendChangeSortingIntent(ScheduleSorting.SPEAKERS); break; default: Toast.makeText(MainActivity.this, "Error: Unknown sort selected", Toast.LENGTH_SHORT).show(); } dialog.cancel(); } }); return builder.create(); } private void sendChangeSortingIntent(final ScheduleSorting pScheduleSorting) { if (getCurrentActivity() instanceof ScheduleSortingConfigurable){ ((ScheduleSortingConfigurable)getCurrentActivity()).setSorting(pScheduleSorting); expandAll(); } } /** * Build dialog to show when loading data. * @return */ public ProgressDialog buildLoadingDialog() { ProgressDialog dialog = new ProgressDialog(this); dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); dialog.setMessage(getText(R.string.dialog_loading)); dialog.setIndeterminate(true); dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER); dialog.setCancelable(false); return dialog; } /** * Build dialog to pick the visible tracks. */ private Dialog buildTracksDialog() { final ContentResolver resolver = getContentResolver(); final ContentValues values = new ContentValues(); final Cursor cursor = managedQuery(CONTENT_URI, null, null, null, null); cursor.setNotificationUri(resolver, CONTENT_URI); final int COL_ID = cursor.getColumnIndex(Tracks._ID); // Wrap this dialog in a specific theme so that list items have correct // text color, otherwise they inherit from our white theme. final Context dialogContext = new ContextThemeWrapper(this, android.R.style.Theme_Black); AlertDialog.Builder builder = new AlertDialog.Builder(dialogContext); builder.setInverseBackgroundForced(true); builder.setTitle(R.string.menu_tracks); builder.setPositiveButton(getString(android.R.string.ok), null); builder.setNegativeButton(getString(android.R.string.cancel), null); builder.setMultiChoiceItems(cursor, TracksColumns.VISIBLE, TracksColumns.TRACK, new OnMultiChoiceClickListener() { public void onClick(DialogInterface dialog, int which, boolean isChecked) { // Build Uri for this specific track cursor.moveToPosition(which); long trackId = cursor.getLong(COL_ID); Uri trackUri = ContentUris.withAppendedId(CONTENT_URI, trackId); // Update visible state of this track values.clear(); values.put(TracksColumns.VISIBLE, isChecked ? 1 : 0); resolver.update(trackUri, values, null, null); cursor.requery(); } }); return builder.create(); } private Dialog buildAboutDialog() { String versionName = findVersion(); View view = getLayoutInflater().inflate(R.layout.about, null, false); TextView version = (TextView)view.findViewById(R.id.version); version.setText(getString(R.string.about_version, versionName)); AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setTitle(getString(R.string.app_name)); builder.setIcon(android.R.drawable.ic_dialog_info); builder.setView(view); builder.setPositiveButton(getString(android.R.string.ok), null); builder.setCancelable(true); return builder.create(); } private String findVersion() { try { PackageInfo pi = getPackageManager().getPackageInfo(getPackageName(), 0); return pi.versionName; } catch (PackageManager.NameNotFoundException ignored) { return "unknown"; } } }