/* ******************************************************************************
* Copyright (c) 2006-2012 XMind Ltd. and others.
*
* This file is a part of XMind 3. XMind releases 3 and
* above are dual-licensed under the Eclipse Public License (EPL),
* which is available at http://www.eclipse.org/legal/epl-v10.html
* and the GNU Lesser General Public License (LGPL),
* which is available at http://www.gnu.org/licenses/lgpl.html
* See http://www.xmind.net/license.html for details.
*
* Contributors:
* XMind Ltd. - initial API and implementation
*******************************************************************************/
package org.xmind.ui.internal.views;
import java.util.List;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.draw2d.FigureCanvas;
import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.IOpenListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.part.Page;
import org.xmind.core.Core;
import org.xmind.core.IRevision;
import org.xmind.core.IRevisionManager;
import org.xmind.core.ISheet;
import org.xmind.core.ITopic;
import org.xmind.core.event.CoreEvent;
import org.xmind.core.event.CoreEventRegister;
import org.xmind.core.event.ICoreEventListener;
import org.xmind.core.event.ICoreEventRegister;
import org.xmind.gef.draw2d.RotatableWrapLabel;
import org.xmind.gef.ui.editor.IGraphicalEditorPage;
import org.xmind.ui.internal.MindMapMessages;
import org.xmind.ui.internal.dialogs.RevisionPreviewDialog;
import org.xmind.ui.mindmap.MindMapUI;
import org.xmind.ui.util.TextFormatter;
import org.xmind.ui.viewers.SWTUtils;
/**
* @author Frank Shaka
*
*/
public class RevisionsPage extends Page
implements ICoreEventListener, IAdaptable {
/**
* @author Frank Shaka
*
*/
public static class RevisionContentProvider
implements IStructuredContentProvider {
public void dispose() {
}
public void inputChanged(Viewer viewer, Object oldInput,
Object newInput) {
}
public Object[] getElements(Object inputElement) {
return ((IRevisionManager) inputElement).getRevisions().toArray();
}
}
private static class RevisionNumberLabelProvider
extends ColumnLabelProvider {
@Override
public String getText(Object element) {
IRevision revision = (IRevision) element;
return String.valueOf(revision.getRevisionNumber());
}
}
private static class RevisionTimeLabelProvider extends ColumnLabelProvider {
@Override
public String getText(Object element) {
IRevision revision = (IRevision) element;
return String.format("%tT", revision.getTimestamp()); //$NON-NLS-1$
}
}
private static class RevisionDateLabelProvider extends ColumnLabelProvider {
@Override
public String getText(Object element) {
IRevision revision = (IRevision) element;
return String.format("%tF", revision.getTimestamp()); //$NON-NLS-1$
}
}
private class RevisionOpenListener implements IOpenListener {
public void open(OpenEvent event) {
handleOpen(event.getSelection());
}
}
private ISheet sheet;
private Control control;
private TableViewer viewer;
private RotatableWrapLabel titleLabel;
private IRevisionManager revisionManager;
private ICoreEventRegister coreEventRegister = new CoreEventRegister(this);
private ICoreEventRegister topicEventRegister = new CoreEventRegister(this);
private MenuManager popupMenuManager;
/**
*
*/
public RevisionsPage(IGraphicalEditorPage source) {
this.sheet = (ISheet) source.getInput();
this.revisionManager = this.sheet.getOwnedWorkbook()
.getRevisionRepository()
.getRevisionManager(sheet.getId(), IRevision.SHEET);
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ui.part.Page#createControl(org.eclipse.swt.widgets.Composite)
*/
@Override
public void createControl(Composite parent) {
final Composite composite = new Composite(parent, SWT.NONE);
GridLayout gridLayout = new GridLayout(1, false);
gridLayout.marginWidth = 0;
gridLayout.marginHeight = 0;
gridLayout.verticalSpacing = 0;
gridLayout.horizontalSpacing = 0;
composite.setLayout(gridLayout);
createTitleLabel(composite);
Label separator = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL);
separator.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
Control viewerControl = createViewer(composite);
viewerControl
.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
setControl(composite);
registerCoreEvents();
getSite().setSelectionProvider(viewer);
popupMenuManager = new MenuManager("#popup"); //$NON-NLS-1$
popupMenuManager.add(new GroupMarker("start")); //$NON-NLS-1$
popupMenuManager
.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
popupMenuManager.add(new GroupMarker("end")); //$NON-NLS-1$
getSite().registerContextMenu(MindMapUI.VIEW_REVISIONS,
popupMenuManager, viewer);
final Menu popupMenu = popupMenuManager
.createContextMenu(viewerControl);
viewerControl.setMenu(popupMenu);
composite.addListener(SWT.Resize, new Listener() {
public void handleEvent(Event event) {
titleLabel.setPrefWidth(composite.getSize().x);
}
});
}
private void setControl(Control control) {
this.control = control;
}
private void createTitleLabel(Composite parent) {
FigureCanvas canvas = new FigureCanvas(parent);
canvas.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
canvas.setVisible(true);
canvas.setScrollBarVisibility(FigureCanvas.NEVER);
titleLabel = new RotatableWrapLabel(RotatableWrapLabel.NORMAL);
titleLabel.setSingleLine(true);
titleLabel.setAbbreviated(true);
canvas.setContents(titleLabel);
titleLabel.setText(getTitleText());
}
private Control createViewer(Composite parent) {
viewer = new TableViewer(parent,
SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
viewer.getTable().setHeaderVisible(true);
viewer.getTable().setLinesVisible(true);
viewer.setContentProvider(new RevisionContentProvider());
TableViewerColumn col0 = new TableViewerColumn(viewer, SWT.RIGHT);
col0.getColumn().setText("#"); //$NON-NLS-1$
col0.getColumn().setWidth(36);
col0.setLabelProvider(new RevisionNumberLabelProvider());
TableViewerColumn col1 = new TableViewerColumn(viewer, SWT.LEFT);
col1.getColumn().setText(MindMapMessages.RevisionsView_DateColumn_text);
col1.getColumn().setWidth(120);
col1.setLabelProvider(new RevisionDateLabelProvider());
TableViewerColumn col2 = new TableViewerColumn(viewer, SWT.LEFT);
col2.getColumn().setText(MindMapMessages.RevisionsView_TimeColumn_text);
col2.getColumn().setWidth(120);
col2.setLabelProvider(new RevisionTimeLabelProvider());
viewer.setInput(revisionManager);
viewer.addOpenListener(new RevisionOpenListener());
viewer.getTable().addKeyListener(new KeyListener() {
public void keyReleased(KeyEvent e) {
}
public void keyPressed(KeyEvent e) {
if (SWTUtils.matchKey(e.stateMask, e.keyCode, 0, SWT.SPACE)) {
handleOpen(viewer.getSelection());
}
}
});
viewer.getControl().setToolTipText(
MindMapMessages.RevisionPage_ShowDetails_message);
return viewer.getControl();
}
/**
*
*/
private void registerCoreEvents() {
coreEventRegister.setNextSourceFrom(revisionManager);
coreEventRegister.register(Core.RevisionAdd);
coreEventRegister.register(Core.RevisionRemove);
coreEventRegister.setNextSourceFrom(sheet);
coreEventRegister.register(Core.TitleText);
coreEventRegister.register(Core.RootTopic);
ITopic rootTopic = sheet.getRootTopic();
topicEventRegister.setNextSourceFrom(rootTopic);
topicEventRegister.register(Core.TitleText);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.part.Page#dispose()
*/
@Override
public void dispose() {
if (viewer != null) {
if (viewer.getControl() != null
&& !viewer.getControl().isDisposed()) {
viewer.getControl().setMenu(null);
}
viewer = null;
}
if (popupMenuManager != null) {
popupMenuManager.dispose();
popupMenuManager = null;
}
topicEventRegister.unregisterAll();
coreEventRegister.unregisterAll();
super.dispose();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.part.Page#getControl()
*/
@Override
public Control getControl() {
return control;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.part.Page#setFocus()
*/
@Override
public void setFocus() {
viewer.getControl().setFocus();
}
private void viewRevision(IRevision revision) {
List<IRevision> revisions = revisionManager.getRevisions();
int index = revisions.indexOf(revision);
RevisionPreviewDialog dialog = new RevisionPreviewDialog(
getSite().getShell(), sheet, revisions, index);
dialog.open();
}
/*
* (non-Javadoc)
*
* @see
* org.xmind.core.event.ICoreEventListener#handleCoreEvent(org.xmind.core
* .event.CoreEvent)
*/
public void handleCoreEvent(CoreEvent event) {
String type = event.getType();
if (Core.RevisionAdd.equals(type) || Core.RevisionRemove.equals(type)) {
asyncExec(new Runnable() {
public void run() {
if (viewer != null) {
viewer.refresh();
}
}
});
} else if (Core.TitleText.equals(type)) {
asyncExec(new Runnable() {
public void run() {
// if (titleLabel != null && !titleLabel.isDisposed()) {
if (titleLabel != null) {
titleLabel.setText(getTitleText());
}
}
});
} else if (Core.RootTopic.equals(type)) {
topicEventRegister.unregisterAll();
ITopic rootTopic = sheet.getRootTopic();
topicEventRegister.setNextSourceFrom(rootTopic);
topicEventRegister.register(Core.TitleText);
}
}
private void asyncExec(Runnable runnable) {
getSite().getWorkbenchWindow().getWorkbench().getDisplay()
.asyncExec(runnable);
}
@SuppressWarnings("unchecked")
public Object getAdapter(Class adapter) {
if (adapter == ISelectionProvider.class)
return viewer;
return null;
}
/**
* @param selection
*/
private void handleOpen(ISelection selection) {
if (selection.isEmpty())
return;
IRevision revision = (IRevision) ((IStructuredSelection) selection)
.getFirstElement();
viewRevision(revision);
}
private String getTitleText() {
String text = String.format("%s (%s)", sheet.getTitleText(), //$NON-NLS-1$
sheet.getRootTopic().getTitleText());
return TextFormatter.removeNewLineCharacter(text);
}
}