/*******************************************************************************
* Copyright (c) 2012 Torkild U. Resheim.
*
* All rights reserved. This program and the accompanying materials are made
* available under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Torkild U. Resheim - initial API and implementation
*******************************************************************************/
package no.resheim.elibrarium.library.ui.views;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.text.MessageFormat;
import no.resheim.elibrarium.library.Book;
import no.resheim.elibrarium.library.core.ILibraryListener;
import no.resheim.elibrarium.library.core.Librarian;
import no.resheim.elibrarium.library.ui.LibraryLabelProvider;
import org.eclipse.core.filesystem.EFS;
import org.eclipse.core.filesystem.IFileStore;
import org.eclipse.emf.common.util.EList;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.DecoratingLabelProvider;
import org.eclipse.jface.viewers.DecoratingStyledCellLabelProvider;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ILabelDecorator;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.contexts.IContextService;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.part.ViewPart;
public class LibraryView extends ViewPart implements ILibraryListener {
/**
* The ID of the view as specified by the extension.
*/
public static final String VIEW_ID = "no.resheim.elibrarium.library.ui.views.LibraryView";
private TableViewer viewer;
private Action doubleClickAction;
private void refreshView() {
getSite().getShell().getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
if (!viewer.getControl().isDisposed()) {
viewer.refresh();
}
}
});
}
class ViewContentProvider implements IStructuredContentProvider {
public void inputChanged(Viewer v, Object oldInput, Object newInput) {
}
public void dispose() {
}
public Object[] getElements(Object parent) {
EList<Book> books = Librarian.getDefault().getLibrary().getBooks();
return books.toArray();
}
}
/**
* A sorter designed to sort book titles. Will ignore "the" in titles that
* starts with this word.
*
* @author Torkild U. Resheim
*/
class NameSorter extends ViewerSorter {
@Override
public int compare(Viewer viewer, Object e1, Object e2) {
if (e1 instanceof Book && e2 instanceof Book) {
String t1 = ((Book) e1).getTitle().toLowerCase();
String t2 = ((Book) e2).getTitle().toLowerCase();
if (t1.startsWith("the ")) {
t1 = t1.substring(4);
}
if (t2.startsWith("the ")) {
t2 = t2.substring(4);
}
int result = t1.compareTo(t2);
if (result != 0) {
return result;
}
}
// fall back to comparing by label
return super.compare(viewer, e1, e2);
}
}
/**
* The constructor.
*/
public LibraryView() {
}
public class TableDecoratingLabelProvider extends DecoratingLabelProvider implements ITableLabelProvider {
ITableLabelProvider provider;
ILabelDecorator decorator;
/**
* @param provider
* @param decorator
*/
public TableDecoratingLabelProvider(ILabelProvider provider, ILabelDecorator decorator) {
super(provider, decorator);
this.provider = (ITableLabelProvider) provider;
this.decorator = decorator;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jface.viewers.ITableLabelProvider#getColumnImage(java
* .lang.Object, int)
*/
public Image getColumnImage(Object element, int columnIndex) {
Image image = provider.getColumnImage(element, columnIndex);
if (decorator != null) {
Image decorated = decorator.decorateImage(image, element);
if (decorated != null) {
return decorated;
}
}
return image;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jface.viewers.ITableLabelProvider#getColumnText(java.
* lang.Object, int)
*/
public String getColumnText(Object element, int columnIndex) {
String text = provider.getColumnText(element, columnIndex);
if (decorator != null) {
String decorated = decorator.decorateText(text, element);
if (decorated != null) {
return decorated;
}
}
return text;
}
}
@Override
public void createPartControl(Composite parent) {
viewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
viewer.setContentProvider(new ViewContentProvider());
viewer.setSorter(new NameSorter());
viewer.setLabelProvider(new DecoratingStyledCellLabelProvider(new LibraryLabelProvider(), null, null));
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
ISelection selection = event.getSelection();
if (selection instanceof IStructuredSelection) {
Object o = ((IStructuredSelection) selection).getFirstElement();
if (o instanceof Book) {
String urlString = ((Book) o).getBookURL();
try {
URL url = new URL(urlString);
IStatusLineManager manager = getViewSite().getActionBars().getStatusLineManager();
manager.setMessage(url.getFile());
} catch (MalformedURLException e) {
e.printStackTrace();
}
}
}
}
});
// Register the selection provider
getSite().setSelectionProvider(viewer);
makeActions();
hookContextMenu();
hookDoubleClickAction();
// Activate the view specific context
PlatformUI.getWorkbench().getDisplay().asyncExec(new Runnable() {
public void run() {
((IContextService) PlatformUI.getWorkbench().getService(IContextService.class))
.activateContext(VIEW_ID);
}
});
// Set contents
Librarian.getDefault().addListener(this);
viewer.setInput(getViewSite());
}
private void hookContextMenu() {
MenuManager menuMgr = new MenuManager("#PopupMenu");
menuMgr.setRemoveAllWhenShown(true);
menuMgr.addMenuListener(new IMenuListener() {
public void menuAboutToShow(IMenuManager manager) {
LibraryView.this.fillContextMenu(manager);
}
});
Menu menu = menuMgr.createContextMenu(viewer.getControl());
viewer.getControl().setMenu(menu);
getSite().registerContextMenu(menuMgr, viewer);
}
private void fillContextMenu(IMenuManager manager) {
// Other plug-ins can contribute there actions here
manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
}
private void makeActions() {
doubleClickAction = new Action() {
@Override
public void run() {
ISelection selection = viewer.getSelection();
Object obj = ((IStructuredSelection) selection).getFirstElement();
if (obj instanceof Book) {
try {
File fileToOpen = new File(new URI(((Book) obj).getBookURL()));
if (fileToOpen.exists() && fileToOpen.isFile()) {
IFileStore fileStore = EFS.getLocalFileSystem().getStore(fileToOpen.toURI());
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
try {
IDE.openEditorOnFileStore(page, fileStore);
} catch (PartInitException e) {
}
} else {
MessageDialog.openError(
getSite().getShell(),
"Missing book",
MessageFormat.format("The book at \"{0}\" is missing.",
fileToOpen.getAbsolutePath()));
}
} catch (URISyntaxException e1) {
e1.printStackTrace();
}
}
}
};
}
private void hookDoubleClickAction() {
viewer.addDoubleClickListener(new IDoubleClickListener() {
public void doubleClick(DoubleClickEvent event) {
doubleClickAction.run();
}
});
}
/**
* Passing the focus request to the viewer's control.
*/
@Override
public void setFocus() {
viewer.getControl().setFocus();
IContextService contextService = (IContextService) getSite().getService(IContextService.class);
contextService.activateContext(VIEW_ID);
}
@Override
public void bookAdded(final Book book) {
refreshView();
// AbstractUiNotification notification = new
// AbstractUiNotification("no.resheim.elibrarium.library.ui.event") {
//
// @SuppressWarnings("rawtypes")
// @Override
// public Object getAdapter(Class adapter) {
// return null;
// }
//
// @Override
// public String getLabel() {
// return "Book added";
// }
//
// @Override
// public String getDescription() {
// return "Added \"" + book.getTitle() + "\" to library.";
// }
//
// @Override
// public Date getDate() {
// return new Date(System.currentTimeMillis());
// }
//
// @Override
// public Image getNotificationImage() {
// return null;
// }
//
// @Override
// public Image getNotificationKindImage() {
// return
// LibraryUIPlugin.getDefault().getImageRegistry().get(LibraryUIPlugin.IMG_BOOK);
// }
//
// @Override
// public void open() {
// }
// };
// NotificationsUi.getService().notify(Collections.singletonList(notification));
}
@Override
public void bookRemoved(Book book) {
refreshView();
}
}