/*
* 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.ArrayList;
import java.util.Iterator;
import java.util.List;
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.util.IPropertyChangeListener;
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.dialogs.RemovableStorageDialog;
import org.jampa.gui.translations.Messages;
import org.jampa.logging.Log;
import org.jampa.model.SortMode;
import org.jampa.model.disk.DirectoryItem;
import org.jampa.model.disk.FileItem;
import org.jampa.model.disk.IDiskItem;
import org.jampa.model.playlists.Playlist;
import org.jampa.preferences.PreferenceConstants;
import org.jampa.utils.Constants;
public class DiskView extends ViewPart implements PropertyChangeListener {
public static String ID = "Jampa.DiskView"; //$NON-NLS-1$
private Image _dirImage;
private Image _libraryDirImage;
private Image _removableDirImage;
private Image _fileImage;
private Image _enqueueImage;
private Image _playImage;
private Image _newPlaylistImage;
private Action _manageRemovableStorage;
private Action _ascendingSortMode;
private Action _descendingSortMode;
private TreeViewer treeViewer;
private Menu diskMenu = null;
private Composite _parent;
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
}
protected Object[] concat(Object[] object, Object[] more) {
Object[] both = new Object[object.length + more.length];
System.arraycopy(object, 0, both, 0, object.length);
System.arraycopy(more, 0, both, object.length, more.length);
return both;
}
@Override
public Object[] getChildren(Object parentElement) {
if (parentElement instanceof DirectoryItem) {
DirectoryItem item = (DirectoryItem) parentElement;
if (Controller.getInstance().getPreferenceStore().getString(PreferenceConstants.DISKVIEW_DISPLAY_MODE).equals("0")) { //$NON-NLS-1$
return concat(item.getDirectoryList().toArray(), item.getFileList().toArray());
} else {
return concat(item.getFileList().toArray(), item.getDirectoryList().toArray());
}
}
return EMPTY_ARRAY;
}
@Override
public Object getParent(Object element) {
if (element instanceof IDiskItem) {
return ((IDiskItem)element).getParent();
}
return null;
}
@Override
public boolean hasChildren(Object element) {
if (element instanceof IDiskItem) {
return ((IDiskItem) 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 DirectoryItem) {
DirectoryItem item = (DirectoryItem) obj;
if (item == Controller.getInstance().getRootDirectoryItem().getLocalParentDir()) {
return _libraryDirImage;
} else if (item == Controller.getInstance().getRootDirectoryItem().getRemovableParentDir()) {
return _removableDirImage;
} else {
return _dirImage;
}
}
if (obj instanceof FileItem) {
return _fileImage;
}
return null;
}
public String getText(Object element) {
return ((IDiskItem) element).getLabel();
}
}
public DiskView() {
Activator.getDefault();
ImageDescriptor imageDescriptor = Activator.getImageDescriptor("/icons/folder_16.png"); //$NON-NLS-1$
_dirImage = imageDescriptor.createImage();
imageDescriptor = Activator.getImageDescriptor("/icons/folder_library_16.png"); //$NON-NLS-1$
_libraryDirImage = imageDescriptor.createImage();
imageDescriptor = Activator.getImageDescriptor("/icons/folder_removable_16.png"); //$NON-NLS-1$
_removableDirImage = imageDescriptor.createImage();
imageDescriptor = Activator.getImageDescriptor("/icons/file_16.png"); //$NON-NLS-1$
_fileImage = 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();
Controller.getInstance().getPreferenceStore().addPropertyChangeListener(new IPropertyChangeListener()
{
@Override
public void propertyChange(org.eclipse.jface.util.PropertyChangeEvent event) {
if (event.getProperty().equals(PreferenceConstants.DISKVIEW_DISPLAY_MODE)) {
updateTreeViewer();
}
}
});
}
private String getFirstSelectedItemName() {
String result = null;
ISelection selection = treeViewer.getSelection();
IDiskItem selectedItem = (IDiskItem) ((IStructuredSelection) selection).getFirstElement();
if (selectedItem != null) {
result = selectedItem.getLabel();
}
return result;
}
@SuppressWarnings("unchecked")
private void enqueueSelectionInPlaylist(String playlistName, boolean playFirst) {
Log.getInstance(DiskView.class).debug("Adding disk items to playlist."); //$NON-NLS-1$
ISelection selection = treeViewer.getSelection();
Object obj;
List<IDiskItem> list = new ArrayList<IDiskItem>();
Iterator iter = ((IStructuredSelection)selection).iterator();
while (iter.hasNext()) {
obj = iter.next();
if ((obj != null) &&
(obj instanceof IDiskItem)) {
list.add((IDiskItem) obj);
}
}
Controller.getInstance().getPlaylistController().addDiskItemsToPlaylist(playlistName, list, playFirst);
}
@SuppressWarnings("unchecked")
private void processDoubleClick() {
ISelection selection = treeViewer.getSelection();
boolean playFirst = Controller.getInstance().getPreferenceStore().getString(PreferenceConstants.DISKVIEW_DEFAULT_DOUBLECLICK_ACTION).equals("0"); //$NON-NLS-1$
boolean playDirectory = Controller.getInstance().getPreferenceStore().getString(PreferenceConstants.DISKVIEW_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 DirectoryItem) {
// First check what we need to do on a directory...
if (playDirectory) {
// Play / Enqueue
Log.getInstance(DiskView.class).debug("Adding directory to playlist : " + ((DirectoryItem) obj).getLabel()); //$NON-NLS-1$
Controller.getInstance().getPlaylistController().addDirectoryToPlaylist(Constants.DEFAULT_PLAYLIST_ID, (DirectoryItem) obj, playFirst);
} else {
// Change expandable state.
treeViewer.setExpandedState(obj, !treeViewer.getExpandedState(obj));
}
}
if (obj instanceof FileItem) {
Log.getInstance(DiskView.class).debug("Adding file to playlist : " + ((FileItem) obj).getLabel()); //$NON-NLS-1$
Controller.getInstance().getPlaylistController().addFileToPlaylist(Constants.DEFAULT_PLAYLIST_ID, (FileItem) obj, playFirst);
}
}
}
}
@Override
public void createPartControl(Composite parent) {
_parent = parent;
setPartName(Messages.getString("DiskView.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(parent);
buildDND();
// Register listener
Controller.getInstance().getEventController().addPlaylistChangeListener(this);
Controller.getInstance().getEventController().addLibraryChangeListener(this);
updateTreeViewer();
}
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;
List<IDiskItem> list = new ArrayList<IDiskItem>();
Iterator iter = ((IStructuredSelection)selection).iterator();
while (iter.hasNext()) {
obj = iter.next();
if ((obj != null) &&
(obj instanceof IDiskItem)) {
list.add((IDiskItem) obj);
}
}
Controller.getInstance().getDNDController().setSource(ID);
Controller.getInstance().getDNDController().setDiskSelection(list);
}
public void dragFinished(DragSourceEvent event) {
Controller.getInstance().getDNDController().setSource(null);
Controller.getInstance().getDNDController().setDiskSelection(null);
}
});
}
private void changeDiskSortMode(Action action) {
if (action == _ascendingSortMode) {
_descendingSortMode.setChecked(!_ascendingSortMode.isChecked());
} else if (action == _descendingSortMode) {
_ascendingSortMode.setChecked(!_descendingSortMode.isChecked());
}
if (_ascendingSortMode.isChecked()) {
Controller.getInstance().getRootDirectoryItem().setSortMode(SortMode.Ascending);
} else if (_descendingSortMode.isChecked()) {
Controller.getInstance().getRootDirectoryItem().setSortMode(SortMode.Descending);
}
updateTreeViewer();
}
private void buildActions() {
_manageRemovableStorage = new Action(Messages.getString("DiskView.ManageRemovableStorage")) { //$NON-NLS-1$
public void run() {
RemovableStorageDialog dialog = new RemovableStorageDialog(_parent.getShell());
dialog.open();
}
};
_manageRemovableStorage.setImageDescriptor(Activator.getImageDescriptor("/icons/folder_removable_16.png")); //$NON-NLS-1$
_ascendingSortMode = new Action(Messages.getString("DiskView.AscendingSortAction")) { //$NON-NLS-1$
public void run() {
changeDiskSortMode(_ascendingSortMode);
}
};
_ascendingSortMode.setImageDescriptor(Activator.getImageDescriptor("/icons/sort_asc_16.png")); //$NON-NLS-1$
_ascendingSortMode.setChecked(SortMode.getValueOf(Controller.getInstance().getPreferenceStore().getString(PreferenceConstants.DISKVIEW_SORT_MODE)) == SortMode.Ascending ? true : false);
_descendingSortMode = new Action(Messages.getString("DiskView.DescendingSortAction")) { //$NON-NLS-1$
public void run() {
changeDiskSortMode(_descendingSortMode);
}
};
_descendingSortMode.setImageDescriptor(Activator.getImageDescriptor("/icons/sort_desc_16.png")); //$NON-NLS-1$
_descendingSortMode.setChecked(SortMode.getValueOf(Controller.getInstance().getPreferenceStore().getString(PreferenceConstants.DISKVIEW_SORT_MODE)) == SortMode.Descending ? true : false);
}
private void buildMenus(Composite parent) {
if (diskMenu != null) {
diskMenu.dispose();
}
diskMenu = new Menu(parent.getShell(), SWT.POP_UP);
MenuItem playDefaultItem = new MenuItem(diskMenu, SWT.PUSH);
playDefaultItem.setText(Messages.getString("DiskView.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(diskMenu, SWT.PUSH);
enqueueDefaultItem.setText(Messages.getString("DiskView.MenuEnqueue")); //$NON-NLS-1$
enqueueDefaultItem.setImage(_enqueueImage);
enqueueDefaultItem.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
enqueueSelectionInPlaylist(Constants.DEFAULT_PLAYLIST_ID, false);
}
});
new MenuItem(diskMenu, SWT.SEPARATOR);
MenuItem playItem = new MenuItem(diskMenu, SWT.CASCADE);
playItem.setText(Messages.getString("DiskView.MenuPlayPlaylist")); //$NON-NLS-1$
Menu playPlaylistMenu = new Menu(diskMenu);
playItem.setMenu(playPlaylistMenu);
MenuItem newPlayPlaylistItem = new MenuItem(playPlaylistMenu, SWT.PUSH);
newPlayPlaylistItem.setText(Messages.getString("DiskView.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(diskMenu, SWT.CASCADE);
enqueueItem.setText(Messages.getString("DiskView.MenuEnqueuePlaylist")); //$NON-NLS-1$
Menu enqueuePlaylistMenu = new Menu(diskMenu);
enqueueItem.setMenu(enqueuePlaylistMenu);
MenuItem newPlaylistItem = new MenuItem(enqueuePlaylistMenu, SWT.PUSH);
newPlaylistItem.setText(Messages.getString("DiskView.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(diskMenu, SWT.SEPARATOR);
MenuItem showMetaDataItem = new MenuItem(diskMenu, SWT.PUSH);
showMetaDataItem.setText(Messages.getString("DiskView.MenuMetaData")); //$NON-NLS-1$
//playDefaultItem.setImage(_playImage);
showMetaDataItem.addSelectionListener(new SelectionAdapter() {
@SuppressWarnings("unchecked")
public void widgetSelected(SelectionEvent e) {
ISelection selection = treeViewer.getSelection();
Object obj;
List<IDiskItem> list = new ArrayList<IDiskItem>();
Iterator iter = ((IStructuredSelection)selection).iterator();
while (iter.hasNext()) {
obj = iter.next();
if (obj != null) {
list.add((IDiskItem) obj);
}
}
MetaDataDialog dialog = new MetaDataDialog(_parent.getShell(), list);
dialog.open();
}
});
treeViewer.getTree().addListener(SWT.MenuDetect, new Listener() {
public void handleEvent(Event event) {
diskMenu.setVisible(true);
}
});
// Toolbar
IToolBarManager rootMenuManager = getViewSite().getActionBars().getToolBarManager();
rootMenuManager.removeAll();
rootMenuManager.add(_ascendingSortMode);
rootMenuManager.add(_descendingSortMode);
rootMenuManager.add(new Separator());
rootMenuManager.add(_manageRemovableStorage);
}
@Override
public void setFocus() {
treeViewer.getControl().setFocus();
}
private void updateTreeViewer() {
// Saved expanded elements.
TreePath[] savedTreePaths = treeViewer.getExpandedTreePaths();
// Disable redraw
treeViewer.getControl().setRedraw(false);
treeViewer.setInput(Controller.getInstance().getRootDirectoryItem());
// If there is removable directories, then there is a parent node for local library,
// and another for removable content. Better to expand those ones.
if ((Controller.getInstance().getRootDirectoryItem() != null) &&
(Controller.getInstance().getRootDirectoryItem().hasRemovableDirectories())) {
treeViewer.expandToLevel(2);
}
// Restore expanded elements.
treeViewer.setExpandedTreePaths(savedTreePaths);
// Redraw
treeViewer.getControl().setRedraw(true);
treeViewer.refresh();
}
public void dispose() {
_dirImage.dispose();
_libraryDirImage.dispose();
_removableDirImage.dispose();
_fileImage.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(_parent);
}
if ((arg0.getPropertyName().equals(EventConstants.EVT_LIBRARY_DIRECTORY_CHANGE))) {
updateTreeViewer();
}
}
}