/* * 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.view; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Matrix; import android.graphics.Paint; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.View; import android.view.View.DragShadowBuilder; import android.view.ViewGroup; import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemLongClickListener; import android.widget.ImageView; import android.widget.SearchView; import android.widget.TextView; 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.AllSongsRepresentative; import ch.ethz.dcg.jukefox.model.collection.BaseAlbum; import ch.ethz.dcg.jukefox.model.collection.BaseArtist; import ch.ethz.dcg.jukefox.model.collection.BaseSong; import ch.ethz.dcg.jukefox.model.collection.ListAlbum; import ch.ethz.dcg.jukefox.model.collection.MapAlbum; import ch.ethz.dcg.pancho3.R; import ch.ethz.dcg.pancho3.tablet.I18nManager; import ch.ethz.dcg.pancho3.tablet.model.DataFetcher; import ch.ethz.dcg.pancho3.tablet.model.DataFetcher.OnDataFetchedListener; import ch.ethz.dcg.pancho3.tablet.presenter.overlay.SearchOverlayPresenter; import ch.ethz.dcg.pancho3.tablet.widget.AlbumImageView; import ch.ethz.dcg.pancho3.tablet.widget.GridRow; import ch.ethz.dcg.pancho3.tablet.widget.ImageLoadingPool; import ch.ethz.dcg.pancho3.tablet.widget.QueueItem; /** * Factory to create different views... */ public class ViewFactory implements OnDataFetchedListener<List<Pair<Bitmap, BaseAlbum>>> { public static final int DRAG_SHADOW_WIDTH = 200; public static final int DRAG_SHADOW_HEIGHT = 60; private final LayoutInflater layoutInflater; private final DataFetcher dataFetcher; private final MenuInflater menuInflater; private final DragManager dragManager; private final float densityScale; private final I18nManager i18nManager; private final Resources resources; private final ImageLoadingPool imageLoadingPool; private final Bitmap borderBitmap; private HashMap<BaseAlbum, ArrayList<ImageView>> albumWaitMap = new HashMap<BaseAlbum, ArrayList<ImageView>>(); public ViewFactory(LayoutInflater layoutInflater, DataFetcher dataFetcher, MenuInflater menuInflater, Resources resources, DragManager dragManager, float densityScale, I18nManager i18nManager) { this.layoutInflater = layoutInflater; this.dataFetcher = dataFetcher; this.menuInflater = menuInflater; this.dragManager = dragManager; this.densityScale = densityScale; this.i18nManager = i18nManager; this.resources = resources; imageLoadingPool = new ImageLoadingPool(dataFetcher); borderBitmap = BitmapFactory.decodeResource(resources, R.drawable.d158_border); } public QueueItem getSongViewQueue(BaseSong<BaseArtist, BaseAlbum> song, QueueItem convertView, ViewGroup parent, int position) { final QueueItem view; if (convertView == null || convertView.isDismissed()) { view = (QueueItem) layoutInflater.inflate(R.layout.tablet_listitem_queue, parent, false) .findViewById(R.id.item); } else { view = convertView; } ((TextView) view.findViewById(R.id.text1)).setText(song.getTitle()); ((TextView) view.findViewById(R.id.text2)).setText(song.getArtist().getName() + " - " + song.getAlbum().getName()); view.position = position; return view; } public View getArtistView(BaseArtist artist, View convertView, ViewGroup parent) { final View view; if (convertView == null) { view = layoutInflater.inflate(R.layout.tablet_listitem_single, parent, false); view.setOnTouchListener(new OnDragTouchListener(dragManager)); } else { view = convertView; } ((TextView) view.findViewById(R.id.text1)).setText(artist.getTitle()); return view; } public View getSongView(BaseSong<BaseArtist, BaseAlbum> song, View convertView, ViewGroup parent) { final View view; if (convertView == null) { view = layoutInflater.inflate(R.layout.tablet_listitem, parent, false); view.setOnTouchListener(new OnDragTouchListener(dragManager)); } else { view = convertView; } ((TextView) view.findViewById(R.id.text1)).setText(song.getTitle()); ((TextView) view.findViewById(R.id.text2)).setText(song.getArtist().getName() + " - " + song.getAlbum().getName()); return view; } public View getAlbumImageView(MapAlbum album, View convertView, ViewGroup parent) { final View view; if (convertView == null) { view = layoutInflater.inflate(R.layout.tablet_albumitem, parent, false); view.setOnTouchListener(new OnDragTouchListener(dragManager)); } else { view = convertView; } bindAlbumImageView(album, view); return view; } private void bindAlbumImageView(MapAlbum album, View view) { ImageView albumArt = (ImageView) view.findViewById(R.id.image); albumArt.setImageBitmap(borderBitmap); albumArt.setTag(album); if (album instanceof AllAlbumsRepresentative) { applyImageStack(album.getFirstArtist(), albumArt, 200); } else if (album instanceof AllSongsRepresentative) { applyImageStack(albumArt, 200); } else if (album instanceof AllRelatedAlbumsRepresentative) { applyImageStack(((AllRelatedAlbumsRepresentative) album).getRepresentedAlbums(), albumArt, 200); } else { /*synchronized (albumWaitMap) { ArrayList<ImageView> list = albumWaitMap.get(album); if (list == null) { list = new ArrayList<ImageView>(); } list.add(albumArt); albumWaitMap.put(album, list); } dataFetcher.fetchAlbumArt(this, false, false, album);*/ } ((TextView) view.findViewById(R.id.text1)).setText(album.getName()); ((TextView) view.findViewById(R.id.text2)).setText(album.getFirstArtist().getName()); } public View getAlbumRow(List<? extends MapAlbum> albums, int startIndex, int endIndex, final OnItemClickListener onItemClickListener, final OnItemLongClickListener onItemLongClickListener, View convertView, int positionOffset) { final GridRow row; if (convertView != null && convertView instanceof GridRow) { row = (GridRow) convertView; } else { row = new GridRow(layoutInflater.getContext()); for (int i = 0; i < 3; i++) { AlbumImageView view = (AlbumImageView) layoutInflater.inflate(R.layout.tablet_albumitem, null); view.setListeners(onItemClickListener, onItemLongClickListener); row.addView(view); } } int j = 0; for (int i = startIndex; i < endIndex; i++, j++) { AlbumImageView view = (AlbumImageView) row.getChildAt(j); view.bind(albums.get(i), i + positionOffset); view.setVisibility(View.VISIBLE); imageLoadingPool.add(view, albums.get(i)); } for (; j < 3; j++) { row.getChildAt(j).setVisibility(View.GONE); } return row; } @Override public void onDataFetched(List<Pair<Bitmap, BaseAlbum>> data) { Bitmap bitmap = data.get(0).first; BaseAlbum album = data.get(0).second; synchronized (albumWaitMap) { ArrayList<ImageView> albumArts = albumWaitMap.get(album); if (albumArts != null) { for (ImageView albumArt : albumArts) { if (albumArt != null && album.equals(albumArt.getTag())) { albumArt.setImageBitmap(bitmap); albumArt.setVisibility(View.VISIBLE); } } } albumWaitMap.remove(album); } } public void applyImageStack(BaseArtist artist, final ImageView albumArt, final int pixelSize) { dataFetcher.fetchAlbumsOfArtist(artist, new OnDataFetchedListener<List<MapAlbum>>() { @Override public void onDataFetched(List<MapAlbum> albums) { ListAlbum[] array = new ListAlbum[getNumberOfImagesOnStack(albums.size())]; for (int i = 0; i < array.length; i++) { array[i] = albums.get(i); } dataFetcher.fetchAlbumArt( new OnDataFetchedListener<List<Pair<Bitmap, BaseAlbum>>>() { @Override public void onDataFetched(List<Pair<Bitmap, BaseAlbum>> data) { albumArt.setImageBitmap(getImageStackImpl(data, pixelSize)); } }, false, false, array); } }); } public void applyImageStack(final ImageView albumArt, final int pixelSize) { dataFetcher.fetchAllAlbums(new OnDataFetchedListener<List<MapAlbum>>() { @Override public void onDataFetched(List<MapAlbum> albums) { ListAlbum[] array = new ListAlbum[getNumberOfImagesOnStack(albums.size())]; for (int i = 0; i < array.length; i++) { array[i] = albums.get(i); } dataFetcher.fetchAlbumArt( new OnDataFetchedListener<List<Pair<Bitmap, BaseAlbum>>>() { @Override public void onDataFetched(List<Pair<Bitmap, BaseAlbum>> data) { albumArt.setImageBitmap(getImageStackImpl(data, pixelSize)); } }, false, false, array); } }); } public void applyImageStack(List<? extends ListAlbum> albums, final ImageView albumArt, final int pixelSize) { ListAlbum[] array = new ListAlbum[getNumberOfImagesOnStack(albums.size())]; for (int i = 0; i < array.length; i++) { array[i] = albums.get(i); } dataFetcher.fetchAlbumArt( new OnDataFetchedListener<List<Pair<Bitmap, BaseAlbum>>>() { @Override public void onDataFetched(List<Pair<Bitmap, BaseAlbum>> data) { albumArt.setImageBitmap(getImageStackImpl(data, pixelSize)); } }, false, false, array); } private Bitmap getImageStackImpl(List<? extends Pair<Bitmap, ?>> data, int pixelSize) { pixelSize *= densityScale; Bitmap output = Bitmap.createBitmap(pixelSize, pixelSize, Config.ARGB_8888); Canvas canvas = new Canvas(output); Paint paint = new Paint(); int numberOfImagesOnStack = data.size(); for (int i = 0; i < numberOfImagesOnStack; i++) { Bitmap bitmap = data.get(i).first; Matrix matrix = new Matrix(); float xScale; float yScale; float xTranslate; float yTranslate; if (i < 3 || numberOfImagesOnStack <= 4) { xScale = (float) pixelSize / (2 * bitmap.getWidth()); yScale = (float) pixelSize / (2 * bitmap.getHeight()); xTranslate = i % 2 == 0 ? 0 : pixelSize / 2; yTranslate = i < 2 ? 0 : pixelSize / 2; } else { xScale = (float) pixelSize / (4 * bitmap.getWidth()); yScale = (float) pixelSize / (4 * bitmap.getHeight()); xTranslate = i % 2 == 1 ? pixelSize / 2 : 3 * pixelSize / 4; yTranslate = i < 5 ? pixelSize / 2 : 3 * pixelSize / 4; } matrix.postScale(xScale, yScale); matrix.postTranslate(xTranslate, yTranslate); canvas.drawBitmap(bitmap, matrix, paint); } return output; } private int getNumberOfImagesOnStack(int size) { return size < 7 ? Math.min(4, size) : 7; } public void inflateMenuExploreMap(Menu menu, BaseArtist artist, BaseAlbum album) { menu.clear(); menuInflater.inflate(R.menu.overlay_menu_explore_map, menu); menu.findItem(R.id.explore).setTitle(i18nManager.getExploreArtistText(artist)); menu.findItem(R.id.map).setTitle(i18nManager.getMapAlbumText(album)); } public void inflateMenuExplore(Menu menu, BaseArtist artist) { menu.clear(); menuInflater.inflate(R.menu.overlay_menu_explore, menu); menu.findItem(R.id.explore).setTitle(i18nManager.getExploreArtistText(artist)); } public void inflateMenuMap(Menu menu, BaseAlbum album) { menu.clear(); menuInflater.inflate(R.menu.overlay_menu_map, menu); menu.findItem(R.id.map).setTitle(i18nManager.getMapAlbumText(album)); } public View createSearchSongView(ViewGroup parent) { View view = layoutInflater.inflate(R.layout.tablet_listitem, parent, false); view.setOnTouchListener(new OnDragTouchListener(dragManager)); return view; } public SearchView createSearchView(SearchOverlayPresenter presenter) { SearchView searchView = new SearchView(layoutInflater.getContext()); searchView.setIconifiedByDefault(false); searchView.setOnQueryTextListener(presenter); return searchView; } public DragShadowBuilder createDragShadowBuilderSongs(int numberOfSongs) { return createDragShadowBuilderImpl(i18nManager.getNumberOfSongsText(numberOfSongs)); } public DragShadowBuilder createDragShadowBuilderAlbums(int numberOfAlbums) { return createDragShadowBuilderImpl(i18nManager.getNumberOfAlbumsText(numberOfAlbums)); } public DragShadowBuilder createDragShadowBuilderAllSongs() { return createDragShadowBuilderImpl(resources.getString(R.string.all_songs)); } private DragShadowBuilder createDragShadowBuilderImpl(String text) { View view = layoutInflater.inflate(R.layout.tablet_overlay_droparea, null); view.setBackgroundResource(R.drawable.d171_box_background_highlight); ((TextView) view.findViewById(R.id.text)).setText(text); return new TabletDragShadowBuilder(view, (int) (DRAG_SHADOW_WIDTH * densityScale), (int) (DRAG_SHADOW_HEIGHT * densityScale)); } public DragShadowBuilder createDragShadowBuilderArtist() { return createDragShadowBuilderImpl(resources.getString(R.string._1_artist)); } public View getListSectionView(String title, View convertView, ViewGroup parent) { TextView text = new TextView(layoutInflater.getContext()); text.setFocusable(false); text.setEnabled(false); text.setText(title); return text; } }