/* * Copyright 2008-2013, ETH Zürich, Samuel Welten, Michael Kuhn, Tobias Langner, * Sandro Affentranger, Lukas Bossard, Michael Grob, Rahul Jain, * Dominic Langenegger, Sonia Mayor Alonso, Roger Odermatt, Tobias Schlueter, * Yannick Stucki, Sebastian Wendland, Samuel Zehnder, Samuel Zihlmann, * Samuel Zweifel * * This file is part of Jukefox. * * Jukefox 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 any later version. Jukefox 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 * Jukefox. If not, see <http://www.gnu.org/licenses/>. */ package ch.ethz.dcg.pancho3.view.statistics; import java.util.List; import java.util.Timer; import java.util.TimerTask; import android.app.ProgressDialog; import android.content.Intent; import android.os.Bundle; import android.view.MotionEvent; import android.view.View; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import ch.ethz.dcg.jukefox.controller.Controller; import ch.ethz.dcg.jukefox.data.db.IDbStatisticsHelper; import ch.ethz.dcg.jukefox.data.db.IDbStatisticsHelper.TimeFilter; import ch.ethz.dcg.jukefox.model.collection.BaseAlbum; import ch.ethz.dcg.jukefox.model.collection.BaseArtist; import ch.ethz.dcg.jukefox.model.collection.statistics.IStatisticsData; import ch.ethz.dcg.jukefox.model.collection.statistics.StatisticsAlbum; import ch.ethz.dcg.jukefox.model.collection.statistics.StatisticsArtist; import ch.ethz.dcg.jukefox.model.collection.statistics.StatisticsGenre; import ch.ethz.dcg.jukefox.model.collection.statistics.StatisticsSong; import ch.ethz.dcg.pancho3.R; import ch.ethz.dcg.pancho3.model.collection.ParcelableAlbum; import ch.ethz.dcg.pancho3.model.collection.ParcelableArtist; import ch.ethz.dcg.pancho3.model.collection.ParcelableGenre; import ch.ethz.dcg.pancho3.model.collection.ParcelableSong; import ch.ethz.dcg.pancho3.view.commons.JukefoxActivity; import ch.ethz.dcg.pancho3.view.commons.SimpleGestureFilter; import ch.ethz.dcg.pancho3.view.commons.SimpleGestureFilter.SimpleGestureListener; import ch.ethz.dcg.pancho3.view.overlays.SongMenu; import ch.ethz.dcg.pancho3.view.statistics.IStatisticsDisplay.OnClickListener; import ch.ethz.dcg.pancho3.view.statistics.IStatisticsDisplay.OnLongClickListener; import ch.ethz.dcg.pancho3.view.tabs.lists.AlbumListMenu; import ch.ethz.dcg.pancho3.view.tabs.lists.ArtistListMenu; import ch.ethz.dcg.pancho3.view.tabs.lists.GenreListMenu; public class StatisticsActivity extends JukefoxActivity { public static final String TAG = StatisticsActivity.class.getSimpleName(); public static final String DATATYPE_KEY = "statistics:dataTypeKey"; public static final int DATATYPE_ALBUM = 0; public static final int DATATYPE_ARTIST = 1; public static final int DATATYPE_GENRE = 2; public static final int DATATYPE_SONG = 3; public static final String WHAT_KEY = "statistics:whatKey"; public static final int WHAT_NEW = 0; public static final int WHAT_TOP = 1; public static final int WHAT_FLOP = 2; public static final int WHAT_SUGGESTIONS = 3; public static final String DISPLAYTYPE_KEY = "statistics:displayType"; public static final int DISPLAYTYPE_LIST = 0; public static final int DISPLAYTYPE_TAGCLOUD = 1; public static int currentDataType = DATATYPE_ARTIST; // Static, so that this will be remembered over multiple calls public static int currentWhat = WHAT_TOP; public static int currentDisplayType = DISPLAYTYPE_LIST; private static int MAX_DATA_ITEMS = 100; private ArtistClickListener artistClickListener; private AlbumClickListener albumClickListener; private GenreClickListener genreClickListener; private SongClickListener songClickListener; private SimpleGestureFilter gestureFilter; private TextView txtTitle; private ImageView btnAlbums; private ImageView btnArtists; private ImageView btnGenres; private ImageView btnSongs; private ImageView btnNew; private ImageView btnTop; private ImageView btnFlop; private ImageView btnSuggestion; private static final int MENU_ARTIST_ACTIVE = R.drawable.d002_artists; private static final int MENU_ALBUM_ACTIVE = R.drawable.d001_albums; private static final int MENU_SONG_ACTIVE = R.drawable.d038_songs; private static final int MENU_GENRE_ACTIVE = R.drawable.d009_genres; private static final int MENU_NEW_ACTIVE = R.drawable.d176_hot; private static final int MENU_TOP_ACTIVE = R.drawable.d173_thumbs_up; private static final int MENU_FLOP_ACTIVE = R.drawable.d174_thumbs_down; private static final int MENU_SUGGESTION_ACTIVE = R.drawable.d175_star; private static final int MENU_ARTIST_INACTIVE = R.drawable.d182_artists_inactive; private static final int MENU_ALBUM_INACTIVE = R.drawable.d181_albums_inactive; private static final int MENU_SONG_INACTIVE = R.drawable.d184_songs_inactive; private static final int MENU_GENRE_INACTIVE = R.drawable.d183_genres_inactive; private static final int MENU_NEW_INACTIVE = R.drawable.d180_hot_inactive; private static final int MENU_TOP_INACTIVE = R.drawable.d177_thumbs_up_inactive; private static final int MENU_FLOP_INACTIVE = R.drawable.d178_thumbs_down_inactive; private static final int MENU_SUGGESTION_INACTIVE = R.drawable.d179_star_inactive; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.statistics); artistClickListener = new ArtistClickListener(); albumClickListener = new AlbumClickListener(); genreClickListener = new GenreClickListener(); songClickListener = new SongClickListener(); txtTitle = (TextView) findViewById(R.id.txtStatisticsTitle); btnAlbums = (ImageView) findViewById(R.id.btnStatisticsAlbums); btnArtists = (ImageView) findViewById(R.id.btnStatisticsArtists); btnGenres = (ImageView) findViewById(R.id.btnStatisticsGenres); btnSongs = (ImageView) findViewById(R.id.btnStatisticsSongs); btnNew = (ImageView) findViewById(R.id.btnStatisticsNewData); btnTop = (ImageView) findViewById(R.id.btnStatisticsTop); btnFlop = (ImageView) findViewById(R.id.btnStatisticsFlop); btnSuggestion = (ImageView) findViewById(R.id.btnStatisticsSuggestions); processIntent(getIntent()); registerEventListeners(); } private void processIntent(Intent intent) { Bundle extras = intent.getExtras(); if (applicationState.isImporting() && !applicationState.isBaseDataCommitted()) { showStatusInfo(getString(R.string.list_not_yet_loaded)); } // Find out which data should be displayed if (extras != null && extras.containsKey(DATATYPE_KEY)) { currentDataType = extras.getInt(DATATYPE_KEY); } // Find out what information should be shown if (extras != null && extras.containsKey(WHAT_KEY)) { currentWhat = extras.getInt(WHAT_KEY); } // Find out what display type should be chosen if (extras != null && extras.containsKey(DISPLAYTYPE_KEY)) { currentDisplayType = extras.getInt(DISPLAYTYPE_KEY); } // Highlight the menus adjustMenu(currentDataType, currentWhat); // Get the display provider final IStatisticsDisplay display; switch (currentWhat) { case WHAT_NEW: display = new StatisticsListDisplay(this, StatisticsListDisplay.DataType.Date, collectionModel); break; case WHAT_TOP: case WHAT_FLOP: case WHAT_SUGGESTIONS: default: switch (currentDisplayType) { case DISPLAYTYPE_TAGCLOUD: display = new StatisticsTagCloudDisplay(this); break; case DISPLAYTYPE_LIST: default: display = new StatisticsListDisplay(this, StatisticsListDisplay.DataType.Rating, collectionModel); break; } break; } // Clear the old display LinearLayout l = (LinearLayout) findViewById(R.id.statistics_layout); l.removeAllViews(); // Load the data in own thread and show progress spinner final ProgressDialog progress = new ProgressDialog(this); progress.setMessage(getString(R.string.loading)); progress.setIndeterminate(true); class ProgressTimerTask extends TimerTask { public boolean showProgress = true; @Override public void run() { runOnUiThread(new Runnable() { @Override public void run() { synchronized (progress) { if (showProgress) { progress.show(); } } } }); } } Timer t = new Timer(); final ProgressTimerTask progressTimerTask = new ProgressTimerTask(); t.schedule(progressTimerTask, 1000); Thread dataLoadThread = new Thread(new Runnable() { @Override public void run() { // Load the data final List<? extends IStatisticsData> data; final OnClickListener onClickListener; final OnLongClickListener onLongClickListener; switch (currentWhat) { case WHAT_NEW: { switch (currentDataType) { case DATATYPE_ALBUM: data = statisticsProvider.getRecentlyImportedAlbums(MAX_DATA_ITEMS); onClickListener = albumClickListener; onLongClickListener = albumClickListener; break; case DATATYPE_GENRE: data = statisticsProvider.getRecentlyImportedGenres(MAX_DATA_ITEMS); onClickListener = genreClickListener; onLongClickListener = null; break; case DATATYPE_SONG: data = statisticsProvider.getRecentlyImportedSongs(MAX_DATA_ITEMS); onClickListener = songClickListener; onLongClickListener = null; break; case DATATYPE_ARTIST: default: data = statisticsProvider.getRecentlyImportedArtists(MAX_DATA_ITEMS); onClickListener = artistClickListener; onLongClickListener = artistClickListener; break; } break; } case WHAT_SUGGESTIONS: { switch (currentDataType) { case DATATYPE_ALBUM: data = statisticsProvider.getSuggestedAlbums(statisticsProvider.allTheTime(), TimeFilter.NONE, MAX_DATA_ITEMS, true); onClickListener = albumClickListener; onLongClickListener = albumClickListener; break; case DATATYPE_GENRE: data = statisticsProvider.getSuggestedGenres(statisticsProvider.allTheTime(), TimeFilter.NONE, MAX_DATA_ITEMS, true); onClickListener = genreClickListener; onLongClickListener = null; break; case DATATYPE_SONG: data = statisticsProvider.getSuggestedSongs(statisticsProvider.allTheTime(), TimeFilter.NONE, MAX_DATA_ITEMS, true); onClickListener = songClickListener; onLongClickListener = null; break; case DATATYPE_ARTIST: default: data = statisticsProvider.getSuggestedArtists(statisticsProvider.allTheTime(), TimeFilter.NONE, MAX_DATA_ITEMS, true); onClickListener = artistClickListener; onLongClickListener = artistClickListener; break; } break; } case WHAT_TOP: case WHAT_FLOP: default: { IDbStatisticsHelper.Direction direction = (currentWhat == WHAT_FLOP) ? IDbStatisticsHelper.Direction.FLOP : IDbStatisticsHelper.Direction.TOP; switch (currentDataType) { case DATATYPE_SONG: data = statisticsProvider.getTopSongs(MAX_DATA_ITEMS, statisticsProvider.allTheTime(), TimeFilter.NONE, direction, true); onClickListener = songClickListener; onLongClickListener = null; break; case DATATYPE_ALBUM: data = statisticsProvider.getTopAlbums(MAX_DATA_ITEMS, statisticsProvider.allTheTime(), TimeFilter.NONE, direction, true); onClickListener = albumClickListener; onLongClickListener = albumClickListener; break; case DATATYPE_ARTIST: default: data = statisticsProvider.getTopArtists(MAX_DATA_ITEMS, statisticsProvider.allTheTime(), TimeFilter.NONE, direction, true); onClickListener = artistClickListener; onLongClickListener = artistClickListener; break; case DATATYPE_GENRE: data = statisticsProvider.getTopGenres(MAX_DATA_ITEMS, statisticsProvider.allTheTime(), TimeFilter.NONE, direction, true); onClickListener = genreClickListener; onLongClickListener = null; break; } break; } } Runnable uiRunnable = new Runnable() { @Override public void run() { // Show the data if (data != null) { display.inflate(data, onClickListener, onLongClickListener, R.id.statistics_layout); } synchronized (progressTimerTask) { progressTimerTask.showProgress = false; // Cancel the loading screen progress.cancel(); } } }; StatisticsActivity.this.runOnUiThread(uiRunnable); } }); dataLoadThread.start(); } @Override public boolean dispatchTouchEvent(MotionEvent me) { gestureFilter.onTouchEvent(me); return super.dispatchTouchEvent(me); } /** * Highlights the selected data type and what button and sets the correct title. * * @param selectedDataType * The data type which should be highlighted * @param selectedWhat * The what which should be highlighted */ private void adjustMenu(int selectedDataType, int selectedWhat) { // Hightlight the correct data type btnAlbums.setImageResource(DATATYPE_ALBUM == selectedDataType ? MENU_ALBUM_ACTIVE : MENU_ALBUM_INACTIVE); btnArtists.setImageResource(DATATYPE_ARTIST == selectedDataType ? MENU_ARTIST_ACTIVE : MENU_ARTIST_INACTIVE); btnGenres.setImageResource(DATATYPE_GENRE == selectedDataType ? MENU_GENRE_ACTIVE : MENU_GENRE_INACTIVE); btnSongs.setImageResource(DATATYPE_SONG == selectedDataType ? MENU_SONG_ACTIVE : MENU_SONG_INACTIVE); // Highlight the correct what btnNew.setImageResource(WHAT_NEW == selectedWhat ? MENU_NEW_ACTIVE : MENU_NEW_INACTIVE); btnTop.setImageResource(WHAT_TOP == selectedWhat ? MENU_TOP_ACTIVE : MENU_TOP_INACTIVE); btnFlop.setImageResource(WHAT_FLOP == selectedWhat ? MENU_FLOP_ACTIVE : MENU_FLOP_INACTIVE); btnSuggestion.setImageResource(WHAT_SUGGESTIONS == selectedWhat ? MENU_SUGGESTION_ACTIVE : MENU_SUGGESTION_INACTIVE); // Set the correct title String mainTitle; switch (selectedWhat) { case WHAT_NEW: mainTitle = getString(R.string.title_new); break; case WHAT_FLOP: mainTitle = getString(R.string.title_flop); break; case WHAT_SUGGESTIONS: mainTitle = getString(R.string.title_suggested); break; case WHAT_TOP: default: mainTitle = getString(R.string.title_top); break; } String subTitle; switch (selectedDataType) { case DATATYPE_ALBUM: subTitle = getString(R.string.albums); break; case DATATYPE_SONG: subTitle = getString(R.string.songs); break; case DATATYPE_GENRE: subTitle = getString(R.string.genres); break; case DATATYPE_ARTIST: default: subTitle = getString(R.string.artists); break; } String title = String.format(mainTitle, subTitle); txtTitle.setText(title); } /** * Registers the event listeners for the different buttons. */ private void registerEventListeners() { BtnClickListener listener = new BtnClickListener(); btnAlbums.setOnClickListener(listener); btnArtists.setOnClickListener(listener); btnGenres.setOnClickListener(listener); btnSongs.setOnClickListener(listener); btnNew.setOnClickListener(listener); btnTop.setOnClickListener(listener); btnFlop.setOnClickListener(listener); btnSuggestion.setOnClickListener(listener); gestureFilter = new SimpleGestureFilter(this, new SimpleGestureListener() { @Override public void onSwipe(int direction) { if ((direction != SimpleGestureFilter.SWIPE_RIGHT) && (direction != SimpleGestureFilter.SWIPE_LEFT)) { return; } if (currentWhat == WHAT_NEW) { // Tag cloud display is not supported for the recently imported view return; } Intent intent = new Intent(); int nextDisplayType = (currentDisplayType == DISPLAYTYPE_LIST) ? DISPLAYTYPE_TAGCLOUD : DISPLAYTYPE_LIST; intent.putExtra(DISPLAYTYPE_KEY, nextDisplayType); controller.doHapticFeedback(); processIntent(intent); } @Override public void onDoubleTap() { return; // We are not interrested in this... } }); gestureFilter.setMode(SimpleGestureFilter.MODE_TRANSPARENT); } /************* EVENT LISTENERS ***********/ class BtnClickListener implements View.OnClickListener { @Override public void onClick(View v) { Intent intent = new Intent(); switch (v.getId()) { case R.id.btnStatisticsAlbums: { intent.putExtra(DATATYPE_KEY, DATATYPE_ALBUM); break; } case R.id.btnStatisticsArtists: { intent.putExtra(DATATYPE_KEY, DATATYPE_ARTIST); break; } case R.id.btnStatisticsGenres: { intent.putExtra(DATATYPE_KEY, DATATYPE_GENRE); break; } case R.id.btnStatisticsSongs: { intent.putExtra(DATATYPE_KEY, DATATYPE_SONG); break; } } switch (v.getId()) { case R.id.btnStatisticsNewData: { intent.putExtra(WHAT_KEY, WHAT_NEW); break; } case R.id.btnStatisticsTop: { intent.putExtra(WHAT_KEY, WHAT_TOP); break; } case R.id.btnStatisticsFlop: { intent.putExtra(WHAT_KEY, WHAT_FLOP); break; } case R.id.btnStatisticsSuggestions: { intent.putExtra(WHAT_KEY, WHAT_SUGGESTIONS); break; } } controller.doHapticFeedback(); processIntent(intent); } } class ArtistClickListener implements OnClickListener, OnLongClickListener { @Override public void onClick(IStatisticsData item) { StatisticsArtist artist = (StatisticsArtist) item; controller.doHapticFeedback(); Intent intent = new Intent(StatisticsActivity.this, ArtistListMenu.class); intent.putExtra(Controller.INTENT_EXTRA_BASE_ARTIST, new ParcelableArtist(artist)); startActivity(intent); } @Override public boolean onLongClick(IStatisticsData item) { StatisticsArtist artist = (StatisticsArtist) item; controller.doHapticFeedback(); controller.showAlbumList(StatisticsActivity.this, artist); return true; } } class AlbumClickListener implements OnClickListener, OnLongClickListener { @Override public void onClick(IStatisticsData item) { StatisticsAlbum album = (StatisticsAlbum) item; controller.doHapticFeedback(); controller.showAlbumDetailInfo(StatisticsActivity.this, album); } @Override public boolean onLongClick(IStatisticsData item) { StatisticsAlbum album = (StatisticsAlbum) item; controller.doHapticFeedback(); Intent intent = new Intent(StatisticsActivity.this, AlbumListMenu.class); intent.putExtra(Controller.INTENT_EXTRA_BASE_ALBUM, new ParcelableAlbum(album)); /* TODO: Implement this?! String albumName = album.getName(); HashMap<String, Integer> albumNameCnts = StatisticsActivity.this.getAlbumNameCnts(); Integer albumNameCnt = albumNameCnts.get(albumName); if (albumNameCnt == null) { albumNameCnt = 0; } intent.putExtra(Controller.INTENT_EXTRA_NUMBER_OF_ALBUMS_WITH_THIS_NAME, albumNameCnt);*/ startActivity(intent); return true; } } class GenreClickListener implements OnClickListener { @Override public void onClick(IStatisticsData item) { StatisticsGenre genre = (StatisticsGenre) item; controller.doHapticFeedback(); Intent intent = new Intent(StatisticsActivity.this, GenreListMenu.class); intent.putExtra(Controller.INTENT_EXTRA_BASE_GENRE, new ParcelableGenre(genre)); startActivity(intent); } } class SongClickListener implements OnClickListener { @Override public void onClick(IStatisticsData item) { @SuppressWarnings("unchecked") StatisticsSong<BaseArtist, BaseAlbum> song = (StatisticsSong<BaseArtist, BaseAlbum>) item; controller.doHapticFeedback(); Intent intent = new Intent(StatisticsActivity.this, SongMenu.class); intent.putExtra(Controller.INTENT_EXTRA_BASE_SONG, new ParcelableSong(song)); startActivity(intent); } } }