/*
* 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.overlay;
import android.app.Activity;
import android.app.Fragment;
import android.app.FragmentManager;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.SparseBooleanArray;
import android.view.ActionMode.Callback;
import android.view.DragEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnDragListener;
import android.view.View.OnLongClickListener;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ImageView;
import android.widget.ImageView.ScaleType;
import android.widget.LinearLayout.LayoutParams;
import android.widget.ListView;
import android.widget.SeekBar;
import android.widget.TextView;
import ch.ethz.dcg.jukefox.commons.utils.JoinableThread;
import ch.ethz.dcg.jukefox.model.collection.BaseAlbum;
import ch.ethz.dcg.jukefox.model.collection.BaseArtist;
import ch.ethz.dcg.jukefox.model.collection.PlaylistSong;
import ch.ethz.dcg.pancho3.R;
import ch.ethz.dcg.pancho3.tablet.TabletFactory;
import ch.ethz.dcg.pancho3.tablet.TabletFactory.TabletFactoryGetter;
import ch.ethz.dcg.pancho3.tablet.interfaces.ISongAdapter;
import ch.ethz.dcg.pancho3.tablet.presenter.overlay.AbstractOverlayPresenter;
import ch.ethz.dcg.pancho3.tablet.presenter.overlay.AbstractOverlayPresenter.IOverlayView;
import ch.ethz.dcg.pancho3.tablet.view.DragManager.DragDataContainer;
import ch.ethz.dcg.pancho3.tablet.view.OnDragTouchListener;
import ch.ethz.dcg.pancho3.tablet.widget.CheckedRelativeLayout;
/**
* Fragment for displaying a popup with a list of songs.
*/
public class OverlayFragment extends Fragment implements IOverlayView {
// The outermost view.
private View mainView;
// An adapter for all the songs in the list.
private ISongAdapter adapter;
// Our presenter.
private AbstractOverlayPresenter presenter;
// The seekbar where the user can increase/decrease the number of displayed songs.
private SeekBar songSeekBar;
// The background of the whole view, we draw some fancy clouds here.
private ImageView backgroundImage;
// The background image of the center part: We possibly display an album art here.
private ImageView albumArt;
// Draws fancy and colorful clouds in the background for some style.
private CloudDrawer cloudDrawer;
// The title of the header item, which represents all the displayed songs.
private TextView headerItemTitle;
// Indicates whether this view has already been hidden again (after it has been shown).
// This is used so we don't pop too much off the back stack.
private boolean hiddenAgain = false;
private View dropArea;
private ViewGroup dropAreaPlayNow;
private ViewGroup dropAreaPlayNext;
private ViewGroup dropAreaEnqueue;
private View songSeekBarDescription;
private ListView listView;
private CheckedRelativeLayout header;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mainView = inflater.inflate(R.layout.tablet_overlay, null);
mainView.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
hide(); // Clicking outside of the popup hides the popup.
}
});
backgroundImage = (ImageView) mainView.findViewById(R.id.imagebackground);
new AsyncTask<Void, Void, TabletFactory>() {
@Override
protected TabletFactory doInBackground(Void... params) {
TabletFactoryGetter tabletFactoryGetter = (TabletFactoryGetter) getActivity();
while (!tabletFactoryGetter.isTabletFactoryReady()) {
try {
JoinableThread.sleep(200);
} catch (InterruptedException e) {
}
}
return tabletFactoryGetter.getTabletFactory();
}
@Override
protected void onPostExecute(TabletFactory tabletFactory) {
View popup = mainView.findViewById(R.id.popup);
popup.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
// NOP. Just to make sure the click event gets killed here.
// Otherwise it would go on to the outerview, which would hide the
// the popup on click.
}
});
presenter = tabletFactory.getCurrentOverlayPresenter();
if (presenter != null) {
adapter = presenter.getSongAdapter();
listView = (ListView) popup.findViewById(R.id.list);
listView.setAdapter(adapter);
listView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
presenter.onCheckedIndicesChange(listView.getCheckedItemCount(),
listView.getCheckedItemPositions(), position);
}
});
tabletFactory.getDragManager().registerSongListViewDragging(listView, adapter);
albumArt = (ImageView) popup.findViewById(R.id.image);
songSeekBar = (SeekBar) mainView.findViewById(R.id.songbar);
songSeekBar.setOnSeekBarChangeListener(presenter);
songSeekBarDescription = mainView.findViewById(R.id.songbar_description);
cloudDrawer = tabletFactory.getCloudDrawer();
header = (CheckedRelativeLayout) popup.findViewById(R.id.headeritem);
header.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
header.performClick();
return presenter.onHeaderItemLongClick(headerItemTitle);
}
});
header.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
presenter.onHeaderItemClick();
}
});
headerItemTitle = (TextView) header.findViewById(R.id.text1);
header.setOnTouchListener(new OnDragTouchListener(
tabletFactory.getDragManager()));
initDropArea();
presenter.viewFinishedInit();
} else {
hide();
}
}
}.execute();
return mainView;
}
public void initDropArea() {
Resources resources = getActivity().getResources();
final int textColor = resources.getColor(R.color.text_color);
final int highlightColor = resources.getColor(R.color.highlight_dark);
dropArea = mainView.findViewById(R.id.droparea);
dropAreaPlayNow = (ViewGroup) dropArea.findViewById(R.id.droparea_playnow);
final TextView dropAreaPlayNowText =
(TextView) dropAreaPlayNow.findViewById(R.id.text);
dropAreaPlayNowText.setText(R.string.command_play_now);
dropAreaPlayNow.setOnDragListener(new OnDragListener() {
@Override
public boolean onDrag(View v, DragEvent event) {
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_LOCATION:
// So that we don't reset the text color all the time.
return true;
case DragEvent.ACTION_DRAG_ENTERED:
dropAreaPlayNowText.setTextColor(highlightColor);
return true;
case DragEvent.ACTION_DROP:
DragDataContainer<PlaylistSong<BaseArtist, BaseAlbum>> data =
(DragDataContainer<PlaylistSong<BaseArtist, BaseAlbum>>)
event.getLocalState();
presenter.playNow(data.getData());
break;
}
dropAreaPlayNowText.setTextColor(textColor);
return true;
}
});
dropAreaPlayNow.findViewById(R.id.text).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
presenter.playNowClicked();
}
});
dropAreaPlayNext = (ViewGroup) dropArea.findViewById(R.id.droparea_playnext);
LayoutParams params = (LayoutParams) dropAreaPlayNext.getLayoutParams();
int margin = Math.round(
getActivity().getResources().getDisplayMetrics().density * 8);
params.topMargin = margin;
params.bottomMargin = margin;
dropAreaPlayNext.setLayoutParams(params);
final TextView dropAreaPlayNextText =
(TextView) dropAreaPlayNext.findViewById(R.id.text);
dropAreaPlayNextText.setText(R.string.command_play_next);
dropAreaPlayNext.setOnDragListener(new OnDragListener() {
@Override
public boolean onDrag(View v, DragEvent event) {
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_LOCATION:
return true;
case DragEvent.ACTION_DRAG_ENTERED:
dropAreaPlayNextText.setTextColor(highlightColor);
return true;
case DragEvent.ACTION_DROP:
DragDataContainer<PlaylistSong<BaseArtist, BaseAlbum>> data =
(DragDataContainer<PlaylistSong<BaseArtist, BaseAlbum>>)
event.getLocalState();
presenter.playNext(data.getData());
break;
}
dropAreaPlayNextText.setTextColor(textColor);
return true;
}
});
dropAreaPlayNext.findViewById(R.id.text).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
presenter.playNextClicked();
}
});
dropAreaEnqueue = (ViewGroup) dropArea.findViewById(R.id.droparea_enqueue);
final TextView dropAreaEnqueueText =
(TextView) dropAreaEnqueue.findViewById(R.id.text);
dropAreaEnqueueText.setText(R.string.command_enqueue);
dropAreaEnqueue.setOnDragListener(new OnDragListener() {
@Override
public boolean onDrag(View v, DragEvent event) {
switch (event.getAction()) {
case DragEvent.ACTION_DRAG_LOCATION:
return true;
case DragEvent.ACTION_DRAG_ENTERED:
dropAreaEnqueueText.setTextColor(highlightColor);
return true;
case DragEvent.ACTION_DROP:
DragDataContainer<PlaylistSong<BaseArtist, BaseAlbum>> data =
(DragDataContainer<PlaylistSong<BaseArtist, BaseAlbum>>)
event.getLocalState();
presenter.enqueue(data.getData());
break;
}
dropAreaEnqueueText.setTextColor(textColor);
return true;
}
});
dropAreaEnqueue.findViewById(R.id.text).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
presenter.enqueueClicked();
}
});
}
@Override
public void uncheckAllSongs() {
SparseBooleanArray indices = listView.getCheckedItemPositions();
int count = indices.size();
for (int i = 0; i < count; i++) {
int key = indices.keyAt(i);
if (indices.get(key)) {
listView.setItemChecked(key, false);
}
}
header.setChecked(false);
}
@Override
public void setAlbumArt(Bitmap bitmap) {
albumArt.setImageBitmap(bitmap);
}
@Override
public void hide() {
if (!hiddenAgain) {
hiddenAgain = true;
if (presenter != null) {
presenter.onHideOverlay();
}
FragmentManager fragmentManager = getFragmentManager();
if (fragmentManager != null) {
fragmentManager.popBackStack();
}
Activity activity = getActivity();
if (activity != null) {
InputMethodManager imm = (InputMethodManager) activity.
getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(mainView.getWindowToken(), 0);
}
}
}
@Override
public void show(Callback callback) {
getActivity().startActionMode(callback);
mainView.setVisibility(View.VISIBLE);
}
@Override
public void initializeSongSeekbar(int numberOfSongs) {
songSeekBar.setMax(numberOfSongs);
songSeekBar.setProgress(numberOfSongs);
songSeekBar.setThumbOffset(0);
}
@Override
public void setHeaderItemTitle(String title) {
headerItemTitle.setText(title);
}
@Override
public void setBackgroundColor(int color) {
Drawable drawable = cloudDrawer.getCloudDrawable(color);
backgroundImage.setScaleType(ScaleType.CENTER_CROP);
backgroundImage.setImageDrawable(drawable);
}
@Override
public void highlight() {
dropAreaPlayNow.setBackgroundResource(R.drawable.d171_box_background_highlight);
dropAreaPlayNext.setBackgroundResource(R.drawable.d171_box_background_highlight);
dropAreaEnqueue.setBackgroundResource(R.drawable.d171_box_background_highlight);
}
@Override
public void unhighlight() {
dropAreaPlayNow.setBackgroundResource(R.drawable.d168_box_background);
dropAreaPlayNext.setBackgroundResource(R.drawable.d168_box_background);
dropAreaEnqueue.setBackgroundResource(R.drawable.d168_box_background);
}
@Override
public void showDropArea() {
dropArea.setVisibility(View.VISIBLE);
InputMethodManager imm = (InputMethodManager) getActivity().
getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(mainView.getWindowToken(), 0);
}
@Override
public void hideDropArea() {
dropArea.setVisibility(View.GONE);
}
@Override
public void hideSongbarDescription() {
songSeekBarDescription.setVisibility(View.GONE);
}
@Override
public void setHeaderChecked(boolean checked, boolean updateListItems) {
header.setChecked(checked);
if (updateListItems || checked) {
for (int i = 0; i < listView.getCount(); i++) {
listView.setItemChecked(i, checked);
}
}
}
@Override
public void setAdapter(ISongAdapter adapter) {
this.adapter = adapter;
listView.setAdapter(adapter);
}
@Override
public ImageView getAlbumArt() {
return albumArt;
}
}