/*
* Jampa
* Copyright (C) 2008-2009 J. Devauchelle and contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* This program 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.
*/
package org.jampa.gui.views;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Iterator;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TreePath;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DragSourceAdapter;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.ui.part.ViewPart;
import org.jampa.Activator;
import org.jampa.controllers.Controller;
import org.jampa.controllers.events.EventConstants;
import org.jampa.gui.actions.playlist.NewPlaylistAction;
import org.jampa.gui.dialogs.MetaDataDialog;
import org.jampa.gui.translations.Messages;
import org.jampa.logging.Log;
import org.jampa.model.SortMode;
import org.jampa.model.library.LibraryList;
import org.jampa.model.library.AlbumItem;
import org.jampa.model.library.ArtistItem;
import org.jampa.model.library.GenreItem;
import org.jampa.model.library.ILibraryItem;
import org.jampa.model.library.LibraryMode;
import org.jampa.model.library.TitleItem;
import org.jampa.model.playlists.Playlist;
import org.jampa.preferences.PreferenceConstants;
import org.jampa.utils.Constants;
public class LibraryView extends ViewPart implements PropertyChangeListener {
public static String ID = "Jampa.LibraryView"; //$NON-NLS-1$
private Image _genreImage;
private Image _artistImage;
private Image _albumImage;
private Image _titleImage;
private Image _enqueueImage;
private Image _playImage;
private Image _newPlaylistImage;
private Action _artistModeAction;
private Action _albumModeAction;
private Action _genreModeAction;
private Action _ascendingSortMode;
private Action _descendingSortMode;
private TreeViewer treeViewer;
private Menu libraryMenu = null;
private Composite _parent;
public LibraryView() {
Activator.getDefault();
ImageDescriptor imageDescriptor = Activator.getImageDescriptor("/icons/genre_16.png"); //$NON-NLS-1$
_genreImage = imageDescriptor.createImage();
imageDescriptor = Activator.getImageDescriptor("/icons/artist_16.png"); //$NON-NLS-1$
_artistImage = imageDescriptor.createImage();
imageDescriptor = Activator.getImageDescriptor("/icons/album_16.png"); //$NON-NLS-1$
_albumImage = imageDescriptor.createImage();
imageDescriptor = Activator.getImageDescriptor("/icons/title_16.png"); //$NON-NLS-1$
_titleImage = imageDescriptor.createImage();
imageDescriptor = Activator.getImageDescriptor("/icons/enqueue_16.png"); //$NON-NLS-1$
_enqueueImage = imageDescriptor.createImage();
imageDescriptor = Activator.getImageDescriptor("/icons/playing_16.png"); //$NON-NLS-1$
_playImage = imageDescriptor.createImage();
imageDescriptor = Activator.getImageDescriptor("/icons/newplaylist_16.png"); //$NON-NLS-1$
_newPlaylistImage = imageDescriptor.createImage();
}
class ViewContentProvider implements ITreeContentProvider {
private final Object[] EMPTY_ARRAY = new Object[0];
public void inputChanged(Viewer v, Object oldInput, Object newInput) {
// do nothing
}
public void dispose() {
// do nothing
}
@Override
public Object[] getChildren(Object parentElement) {
if (parentElement instanceof ILibraryItem) {
ILibraryItem item = (ILibraryItem) parentElement;
return item.getChildren();
}
return EMPTY_ARRAY;
}
@Override
public Object getParent(Object element) {
if (element instanceof ILibraryItem) {
return ((ILibraryItem)element).getParent();
}
return null;
}
@Override
public boolean hasChildren(Object element) {
if (element instanceof ILibraryItem) {
return ((ILibraryItem) element).hasChildren();
}
return false;
}
@Override
public Object[] getElements(Object inputElement) {
return getChildren(inputElement);
}
}
class ViewLabelProvider extends LabelProvider implements ILabelProvider {
public Image getImage(Object obj) {
if (obj instanceof GenreItem)
return _genreImage;
if (obj instanceof ArtistItem)
return _artistImage;
if (obj instanceof AlbumItem)
return _albumImage;
if (obj instanceof TitleItem)
return _titleImage;
return null;
}
public String getText(Object element) {
return ((ILibraryItem) element).getName();
}
}
private String getFirstSelectedItemName() {
String result = null;
ISelection selection = treeViewer.getSelection();
ILibraryItem selectedItem = (ILibraryItem) ((IStructuredSelection) selection).getFirstElement();
if (selectedItem != null) {
result = selectedItem.getName();
}
return result;
}
@SuppressWarnings("unchecked")
private void enqueueSelectionInPlaylist(String playlistName, boolean playFirst) {
ISelection selection = treeViewer.getSelection();
Object obj;
LibraryList list = new LibraryList();
Iterator iter = ((IStructuredSelection)selection).iterator();
while (iter.hasNext()) {
obj = iter.next();
if (obj != null) {
list.addChild(((ILibraryItem) obj).getName(), (ILibraryItem) obj);
}
}
Log.getInstance(LibraryView.class).debug("Adding items to playlist: " + playlistName); //$NON-NLS-1$
Controller.getInstance().getPlaylistController().addItemToPlaylist(playlistName, list, playFirst);
}
@SuppressWarnings("unchecked")
private void processDoubleClick() {
ISelection selection = treeViewer.getSelection();
boolean playFirst = Controller.getInstance().getPreferenceStore().getString(PreferenceConstants.LIBRARYVIEW_DEFAULT_DOUBLECLICK_ACTION).equals("0"); //$NON-NLS-1$
boolean playDirectory = Controller.getInstance().getPreferenceStore().getString(PreferenceConstants.LIBRARYVIEW_FOLDER_DOUBLECLICK_ACTION).equals("0"); //$NON-NLS-1$
Object obj;
Iterator iter = ((IStructuredSelection)selection).iterator();
while (iter.hasNext()) {
obj = iter.next();
if (obj != null) {
if (obj instanceof TitleItem) {
Log.getInstance(LibraryView.class).debug("Adding title to default playlist: " + ((TitleItem) obj).getName() + " (" + ((TitleItem) obj).getFilePath() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
Controller.getInstance().getPlaylistController().addFileToPlayList(Constants.DEFAULT_PLAYLIST_ID, ((TitleItem) obj).getFilePath(), playFirst, false);
} else if (obj instanceof ILibraryItem) {
// Anything but a TitleItem: item is expandable.
if (playDirectory) {
Log.getInstance(LibraryView.class).debug("Adding items to default playlist."); //$NON-NLS-1$
Controller.getInstance().getPlaylistController().addItemToPlaylist(Constants.DEFAULT_PLAYLIST_ID, (ILibraryItem) obj, playFirst);
} else {
treeViewer.setExpandedState(obj, !treeViewer.getExpandedState(obj));
}
}
}
}
}
@Override
public void createPartControl(Composite parent) {
_parent = parent;
setPartName(Messages.getString("LibraryView.Title")); //$NON-NLS-1$
treeViewer = new TreeViewer(parent);
treeViewer.setContentProvider(new ViewContentProvider());
treeViewer.setLabelProvider(new ViewLabelProvider());
treeViewer.addDoubleClickListener(new IDoubleClickListener() {
public void doubleClick(DoubleClickEvent event) {
processDoubleClick();
}
});
buildActions();
buildMenus();
buildDND();
// Register listener
Controller.getInstance().getEventController().addPlaylistChangeListener(this);
Controller.getInstance().getEventController().addLibraryChangeListener(this);
updateTreeViewer();
}
private void updateTreeViewer() {
// Saved expanded elements.
TreePath[] savedTreePaths = treeViewer.getExpandedTreePaths();
// Disable redraw
treeViewer.getControl().setRedraw(false);
treeViewer.setInput(Controller.getInstance().getLibrary());
// Restore expanded elements.
treeViewer.setExpandedTreePaths(savedTreePaths);
// Redraw
treeViewer.getControl().setRedraw(true);
treeViewer.refresh();
}
private void buildDND() {
// Drag source
Transfer[] types = new Transfer[] { TextTransfer.getInstance() };
DragSource source = new DragSource(treeViewer.getTree(), DND.DROP_COPY);
source.setTransfer(types);
source.addDragListener(new DragSourceAdapter() {
public void dragSetData(DragSourceEvent event) {
event.data = ID;
}
@SuppressWarnings("unchecked")
public void dragStart(DragSourceEvent event) {
event.data = ID;
ISelection selection = treeViewer.getSelection();
Object obj;
LibraryList list = new LibraryList();
Iterator iter = ((IStructuredSelection)selection).iterator();
while (iter.hasNext()) {
obj = iter.next();
if ((obj != null) &&
(obj instanceof ILibraryItem)) {
list.addChild(((ILibraryItem) obj).getName(), (ILibraryItem) obj);
}
}
Controller.getInstance().getDNDController().setSource(ID);
Controller.getInstance().getDNDController().setLibrarySelection(list);
}
public void dragFinished(DragSourceEvent event) {
Controller.getInstance().getDNDController().setSource(null);
Controller.getInstance().getDNDController().setLibrarySelection(null);
}
});
}
private void changeLibraryMode(Action action) {
if (action == _artistModeAction) {
if (_artistModeAction.isChecked()) {
_albumModeAction.setChecked(false);
_genreModeAction.setChecked(false);
} else {
_albumModeAction.setChecked(true);
_genreModeAction.setChecked(false);
}
} else if (action == _albumModeAction) {
if (_albumModeAction.isChecked()) {
_artistModeAction.setChecked(false);
_genreModeAction.setChecked(false);
} else {
_artistModeAction.setChecked(false);
_genreModeAction.setChecked(true);
}
} else if (action == _genreModeAction) {
if (_genreModeAction.isChecked()) {
_albumModeAction.setChecked(false);
_artistModeAction.setChecked(false);
} else {
_artistModeAction.setChecked(true);
_albumModeAction.setChecked(false);
}
}
if (_artistModeAction.isChecked()) {
Controller.getInstance().getLibrary().setLibraryMode(LibraryMode.ArtistMode);
} else if (_albumModeAction.isChecked()) {
Controller.getInstance().getLibrary().setLibraryMode(LibraryMode.AlbumMode);
} else if (_genreModeAction.isChecked()) {
Controller.getInstance().getLibrary().setLibraryMode(LibraryMode.GenreMode);
}
updateTreeViewer();
}
private void changeLibrarySortMode(Action action) {
if (action == _ascendingSortMode) {
_descendingSortMode.setChecked(!_ascendingSortMode.isChecked());
} else if (action == _descendingSortMode) {
_ascendingSortMode.setChecked(!_descendingSortMode.isChecked());
}
if (_ascendingSortMode.isChecked()) {
Controller.getInstance().getLibrary().setLibrarySortMode(SortMode.Ascending);
} else if (_descendingSortMode.isChecked()) {
Controller.getInstance().getLibrary().setLibrarySortMode(SortMode.Descending);
}
updateTreeViewer();
}
private void buildActions() {
_artistModeAction = new Action(Messages.getString("LibraryView.ArtistModeAction")) { //$NON-NLS-1$
public void run() {
changeLibraryMode(_artistModeAction);
}
};
_artistModeAction.setImageDescriptor(Activator.getImageDescriptor("/icons/artist_16.png")); //$NON-NLS-1$
_artistModeAction.setChecked(LibraryMode.getValueOf(Controller.getInstance().getPreferenceStore().getString(PreferenceConstants.LIBRARY_DISPLAY_MODE)) == LibraryMode.ArtistMode ? true : false);
_albumModeAction = new Action(Messages.getString("LibraryView.AlbumModeAction")) { //$NON-NLS-1$
public void run() {
changeLibraryMode(_albumModeAction);
}
};
_albumModeAction.setImageDescriptor(Activator.getImageDescriptor("/icons/album_16.png")); //$NON-NLS-1$
_albumModeAction.setChecked(LibraryMode.getValueOf(Controller.getInstance().getPreferenceStore().getString(PreferenceConstants.LIBRARY_DISPLAY_MODE)) == LibraryMode.AlbumMode ? true : false);
_genreModeAction = new Action(Messages.getString("LibraryView.GenreModeAction")) { //$NON-NLS-1$
public void run() {
changeLibraryMode(_genreModeAction);
}
};
_genreModeAction.setImageDescriptor(Activator.getImageDescriptor("/icons/genre_16.png")); //$NON-NLS-1$); //$NON-NLS-1$
_genreModeAction.setChecked(LibraryMode.getValueOf(Controller.getInstance().getPreferenceStore().getString(PreferenceConstants.LIBRARY_DISPLAY_MODE)) == LibraryMode.GenreMode ? true : false);
_ascendingSortMode = new Action(Messages.getString("LibraryView.AscendingSortAction")) { //$NON-NLS-1$
public void run() {
changeLibrarySortMode(_ascendingSortMode);
}
};
_ascendingSortMode.setImageDescriptor(Activator.getImageDescriptor("/icons/sort_asc_16.png")); //$NON-NLS-1$
_ascendingSortMode.setChecked(SortMode.getValueOf(Controller.getInstance().getPreferenceStore().getString(PreferenceConstants.LIBRARY_SORT_MODE)) == SortMode.Ascending ? true : false);
_descendingSortMode = new Action(Messages.getString("LibraryView.DescendingSortAction")) { //$NON-NLS-1$
public void run() {
changeLibrarySortMode(_descendingSortMode);
}
};
_descendingSortMode.setImageDescriptor(Activator.getImageDescriptor("/icons/sort_desc_16.png")); //$NON-NLS-1$
_descendingSortMode.setChecked(SortMode.getValueOf(Controller.getInstance().getPreferenceStore().getString(PreferenceConstants.LIBRARY_SORT_MODE)) == SortMode.Descending ? true : false);
}
private void buildMenus() {
if (libraryMenu != null)
libraryMenu.dispose();
libraryMenu = new Menu(_parent.getShell(), SWT.POP_UP);
MenuItem playDefaultItem = new MenuItem(libraryMenu, SWT.PUSH);
playDefaultItem.setText(Messages.getString("LibraryView.MenuPlay")); //$NON-NLS-1$
playDefaultItem.setImage(_playImage);
playDefaultItem.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
enqueueSelectionInPlaylist(Constants.DEFAULT_PLAYLIST_ID, true);
}
});
MenuItem enqueueDefaultItem = new MenuItem(libraryMenu, SWT.PUSH);
enqueueDefaultItem.setText(Messages.getString("LibraryView.MenuEnqueue")); //$NON-NLS-1$
enqueueDefaultItem.setImage(_enqueueImage);
enqueueDefaultItem.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
enqueueSelectionInPlaylist(Constants.DEFAULT_PLAYLIST_ID, false);
}
});
new MenuItem(libraryMenu, SWT.SEPARATOR);
MenuItem playItem = new MenuItem(libraryMenu, SWT.CASCADE);
playItem.setText(Messages.getString("LibraryView.MenuPlayPlaylist")); //$NON-NLS-1$
Menu playPlaylistMenu = new Menu(libraryMenu);
playItem.setMenu(playPlaylistMenu);
MenuItem newPlayPlaylistItem = new MenuItem(playPlaylistMenu, SWT.PUSH);
newPlayPlaylistItem.setText(Messages.getString("LibraryView.MenuNewPlaylist")); //$NON-NLS-1$
newPlayPlaylistItem.setImage(_newPlaylistImage);
newPlayPlaylistItem.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
NewPlaylistAction action = new NewPlaylistAction(Display.getDefault().getActiveShell(), getFirstSelectedItemName());
action.run();
if (action.getPlaylistName() != null) {
enqueueSelectionInPlaylist(action.getPlaylistName(), true);
}
}
});
new MenuItem(playPlaylistMenu, SWT.SEPARATOR);
Object[] playlistList = Controller.getInstance().getPlaylistController().getPlaylistList();
for (int i = 0; i < playlistList.length; i++) {
final MenuItem playlistItem = new MenuItem(playPlaylistMenu, SWT.PUSH);
playlistItem.setText(((Playlist) playlistList[i]).getName());
playlistItem.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
enqueueSelectionInPlaylist(playlistItem.getText(), true);
}
});
}
MenuItem enqueueItem = new MenuItem(libraryMenu, SWT.CASCADE);
enqueueItem.setText(Messages.getString("LibraryView.MenuEnqueuePlaylist")); //$NON-NLS-1$
Menu enqueuePlaylistMenu = new Menu(libraryMenu);
enqueueItem.setMenu(enqueuePlaylistMenu);
MenuItem newPlaylistItem = new MenuItem(enqueuePlaylistMenu, SWT.PUSH);
newPlaylistItem.setText(Messages.getString("LibraryView.MenuNewPlaylist")); //$NON-NLS-1$
newPlaylistItem.setImage(_newPlaylistImage);
newPlaylistItem.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
NewPlaylistAction action = new NewPlaylistAction(Display.getDefault().getActiveShell(), getFirstSelectedItemName());
action.run();
if (action.getPlaylistName() != null) {
enqueueSelectionInPlaylist(action.getPlaylistName(), false);
}
}
});
new MenuItem(enqueuePlaylistMenu, SWT.SEPARATOR);
playlistList = Controller.getInstance().getPlaylistController().getPlaylistList();
for (int i = 0; i < playlistList.length; i++) {
final MenuItem playlistItem = new MenuItem(enqueuePlaylistMenu, SWT.PUSH);
playlistItem.setText(((Playlist) playlistList[i]).getName());
playlistItem.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
enqueueSelectionInPlaylist(playlistItem.getText(), false);
}
});
}
new MenuItem(libraryMenu, SWT.SEPARATOR);
MenuItem showMetaDataItem = new MenuItem(libraryMenu, SWT.PUSH);
showMetaDataItem.setText(Messages.getString("LibraryView.MenuMetaData")); //$NON-NLS-1$
//playDefaultItem.setImage(_playImage);
showMetaDataItem.addSelectionListener(new SelectionAdapter() {
@SuppressWarnings("unchecked")
public void widgetSelected(SelectionEvent e) {
ISelection selection = treeViewer.getSelection();
Object obj;
LibraryList list = new LibraryList();
Iterator iter = ((IStructuredSelection)selection).iterator();
while (iter.hasNext()) {
obj = iter.next();
if (obj != null) {
list.addChild(((ILibraryItem) obj).getName(), (ILibraryItem) obj);
}
}
MetaDataDialog dialog = new MetaDataDialog(_parent.getShell(), list);
dialog.open();
}
});
treeViewer.getTree().addListener(SWT.MenuDetect, new Listener() {
public void handleEvent(Event event) {
libraryMenu.setVisible(true);
}
});
// Toolbar
IToolBarManager rootMenuManager = getViewSite().getActionBars().getToolBarManager();
rootMenuManager.removeAll();
rootMenuManager.add(_ascendingSortMode);
rootMenuManager.add(_descendingSortMode);
rootMenuManager.add(new Separator());
rootMenuManager.add(_artistModeAction);
rootMenuManager.add(_albumModeAction);
rootMenuManager.add(_genreModeAction);
}
@Override
public void setFocus() {
treeViewer.getControl().setFocus();
}
public void dispose() {
_genreImage.dispose();
_artistImage.dispose();
_albumImage.dispose();
_titleImage.dispose();
_enqueueImage.dispose();
_playImage.dispose();
_newPlaylistImage.dispose();
// Unregister listener
Controller.getInstance().getEventController().removePlaylistChangeListener(this);
Controller.getInstance().getEventController().removeLibraryChangeListener(this);
super.dispose();
}
public void propertyChange(PropertyChangeEvent arg0) {
if ((arg0.getPropertyName().equals(EventConstants.EVT_ADD_PLAYLIST)) ||
(arg0.getPropertyName().equals(EventConstants.EVT_REMOVE_PLAYLIST)) ||
(arg0.getPropertyName().equals(EventConstants.EVT_SORT_PLAYLIST_LIST))) {
buildMenus();
}
if ((arg0.getPropertyName().equals(EventConstants.EVT_LIBRARY_SCAN_CHANGE))) {
updateTreeViewer();
}
}
}