/* * 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.tablet.presenter.exploration; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import ch.ethz.dcg.jukefox.commons.utils.Pair; import ch.ethz.dcg.jukefox.model.collection.AllAlbumsRepresentative; import ch.ethz.dcg.jukefox.model.collection.AllRelatedAlbumsRepresentative; import ch.ethz.dcg.jukefox.model.collection.BaseArtist; import ch.ethz.dcg.jukefox.model.collection.BaseTag; import ch.ethz.dcg.jukefox.model.collection.CompleteTag; import ch.ethz.dcg.jukefox.model.collection.ListAlbum; import ch.ethz.dcg.jukefox.model.collection.MapAlbum; import ch.ethz.dcg.pancho3.tablet.model.DataFetcher; import ch.ethz.dcg.pancho3.tablet.model.DataFetcher.OnDataFetchedListener; import ch.ethz.dcg.pancho3.tablet.presenter.TabletPresenter; /** * Presenter for the exploration selection view. */ public class ExplorationPresenter { // Reference to the main presenter to display overlays. private final TabletPresenter tabletPresenter; // From here we get our data. private final DataFetcher dataFetcher; // Decides how many values we select from a list of weighted values. private final ValueSelector valueSelector; // We notify this listener once we've loaded data. private IExplorationView view; private PendingCommand pendingCommand; /** * An interface to the exploration view. */ public static interface IExplorationView { /** * Tells the view to display info about a new artist. */ IExplorationViewArtist exploreArtist(BaseArtist artist); IExplorationViewTag exploreTag(BaseTag tag); IExplorationViewAllAlbums exploreAllAlbums(); } public static interface IExplorationViewArtist { /** * Tells the view to display new tags. */ void displayTags(List<Pair<CompleteTag, Float>> tags); /** * Tells the view to display new related albums. TODO comment */ void displayRelatedAlbums(List<? extends MapAlbum> albums); void displayAlbums(List<? extends MapAlbum> albums); } public static interface IExplorationViewTag { /** * Tells the view to display new tags. */ void displayTags(List<Pair<CompleteTag, Float>> tags); /** * Tells the view to display new related albums. TODO comment */ void displayRelatedAlbums(List<? extends MapAlbum> albums); } public static interface IExplorationViewAllAlbums { void displayAlbums(List<? extends MapAlbum> albums); } private static interface PendingCommand { void execute(); } private class PendingExploreAllAlbums implements PendingCommand { @Override public void execute() { exploreAllAlbums(); } } private class PendingExploreArtist implements PendingCommand { private final BaseArtist artist; public PendingExploreArtist(BaseArtist artist) { this.artist = artist; } @Override public void execute() { exploreArtist(artist); } } private class PendingExploreTag implements PendingCommand { private final BaseTag tag; public PendingExploreTag(BaseTag tag) { this.tag = tag; } @Override public void execute() { exploreTag(tag); } } /** * The constructor with the needed references. */ public ExplorationPresenter(TabletPresenter tabletPresenter, DataFetcher dataFetcher, ValueSelector valueSelector) { this.tabletPresenter = tabletPresenter; this.dataFetcher = dataFetcher; this.valueSelector = valueSelector; } /** * The presenter needs this reference to be functional. If the presenter * gets a command to explore an artist before this reference is set it will * execute the command once the view is set and initialized. */ public void setExplorationView(IExplorationView view) { this.view = view; } /** * Called when the user wants to explore an artist. */ public void exploreArtistMaybe(BaseArtist artist) { tabletPresenter.exploreArtistMaybe(artist); } /** * Called when the user wants to explore a tag. */ public void exploreTagMaybe(BaseTag tag) { tabletPresenter.exploreTagMaybe(tag); } public void exploreArtist(final BaseArtist artist) { if (view != null) { final IExplorationViewArtist artistView = view.exploreArtist(artist); dataFetcher.fetchAlbumsOfArtist(artist, new OnDataFetchedListener<List<MapAlbum>>() { @Override public void onDataFetched(List<MapAlbum> albums) { if (albums.size() > 1) { ArrayList<MapAlbum> albumsWithHeader = new ArrayList<MapAlbum>(); albumsWithHeader.add(new AllAlbumsRepresentative(artist)); albumsWithHeader.addAll(albums); artistView.displayAlbums(albumsWithHeader); } else { artistView.displayAlbums(albums); } } }); dataFetcher.fetchRelatedAlbums2(artist, new OnDataFetchedListener<List<MapAlbum>>() { @Override public void onDataFetched(List<MapAlbum> albums) { ArrayList<MapAlbum> albumsWithHeader = new ArrayList<MapAlbum>(); // TODO: we should maybe also add the albums of the artist to the header. albumsWithHeader.add(new AllRelatedAlbumsRepresentative(albums)); albumsWithHeader.addAll(albums); artistView.displayRelatedAlbums(albumsWithHeader); } }); dataFetcher.fetchTagsForArtist(artist, new OnDataFetchedListener<List<Pair<CompleteTag, Float>>>() { @Override public void onDataFetched(final List<Pair<CompleteTag, Float>> data) { List<Float> values = new ArrayList<Float>(); for (Pair<CompleteTag, Float> pair : data) { values.add(pair.second); } int numValues = valueSelector.getNumberOfValuesToSelect(values, 0, 20); List<Pair<CompleteTag, Float>> goodTags = new ArrayList<Pair<CompleteTag, Float>>(); for (int i = 0; i < numValues; i++) { goodTags.add(data.get(i)); } Collections.sort(goodTags, new Comparator<Pair<CompleteTag, Float>>() { @Override public int compare(Pair<CompleteTag, Float> pair1, Pair<CompleteTag, Float> pair2) { return pair1.first.getName().compareToIgnoreCase( pair2.first.getName()); } }); artistView.displayTags(goodTags); } }); } else { pendingCommand = new PendingExploreArtist(artist); } } public void exploreTag(BaseTag tag) { if (view != null) { final IExplorationViewTag tagView = view.exploreTag(tag); dataFetcher.fetchAlbumsForTag(tag, new OnDataFetchedListener<List<MapAlbum>>() { @Override public void onDataFetched(List<MapAlbum> albums) { ArrayList<MapAlbum> albumsWithHeader = new ArrayList<MapAlbum>(); albumsWithHeader.add(new AllRelatedAlbumsRepresentative(albums)); albumsWithHeader.addAll(albums); tagView.displayRelatedAlbums(albumsWithHeader); } }); dataFetcher.fetchRelatedTagsForTag(tag, new OnDataFetchedListener<List<Pair<CompleteTag, Float>>>() { @Override public void onDataFetched(List<Pair<CompleteTag, Float>> data) { tagView.displayTags(data); } }); } else { pendingCommand = new PendingExploreTag(tag); } } public void exploreAllAlbums() { if (view != null) { final IExplorationViewAllAlbums allAlbumsView = view.exploreAllAlbums(); dataFetcher.fetchAllAlbums(new OnDataFetchedListener<List<MapAlbum>>() { @Override public void onDataFetched(List<MapAlbum> albums) { ArrayList<MapAlbum> albumsWithHeader = new ArrayList<MapAlbum>(); //albumsWithHeader.add(new AllSongsRepresentative()); //albumsWithHeader.add(new RecentSongsRepresentative()); albumsWithHeader.addAll(albums); allAlbumsView.displayAlbums(albumsWithHeader); } }); } else { pendingCommand = new PendingExploreAllAlbums(); } } /** * Called when an album in the view has been clicked to display an overlay. */ public void onAlbumClick(ListAlbum album, boolean albumOfCurrentArtist) { tabletPresenter.displayOverlay(album, true, !albumOfCurrentArtist); } /** * Signals that the view has finished initialization. */ public void viewFinishedInit() { if (pendingCommand != null) { pendingCommand.execute(); pendingCommand = null; } } public void onArtistSelected(BaseArtist artist) { exploreArtistMaybe(artist); } public void displayArtistChooser() { tabletPresenter.displayArtistChooser(); } }