/* ******************************************************************************
* 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.gallery;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.draw2d.FigureCanvas;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.RangeModel;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.IFilter;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.IOpenListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.LabelProviderChangedEvent;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.xmind.gef.GraphicalViewer;
import org.xmind.gef.draw2d.geometry.Geometry;
import org.xmind.gef.part.GraphicalRootEditPart;
import org.xmind.gef.part.IGraphicalPart;
import org.xmind.gef.part.IPart;
public class GalleryViewer extends GraphicalViewer
implements IDecorationContext {
/**
* Viewer property key indicating whether frames are laid out horizontally
* or vertically.
* <p>
* Values: true, false
* </p>
*/
public static final String Horizontal = "org.xmind.ui.gallery.horizontal"; //$NON-NLS-1$
/**
* Viewer property key indicating whether frames can wrap.
* <p>
* Values: true, false
* </p>
*/
public static final String Wrap = "org.xmind.ui.gallery.wrap"; //$NON-NLS-1$
/**
* Values: true, false
*/
public static final String HideTitle = "org.xmind.ui.gallery.hideTitle"; //$NON-NLS-1$
/**
* Values: GalleryLayout
*/
public static final String Layout = "org.xmind.ui.gallery.layout"; //$NON-NLS-1$
/**
* Values: true, false
*/
public static final String ImageStretched = "stretched"; //$NON-NLS-1$
/**
* Values: true, false
*/
public static final String ImageConstrained = "constrained"; //$NON-NLS-1$
/**
* Values: {@link org.eclipse.draw2d.geometry.Dimension}
*/
public static final String FrameContentSize = "org.xmind.ui.gallery.frameContentSize"; //$NON-NLS-1$
/**
* Values: true, false
*/
public static final String PackFrameContent = "org.xmind.ui.gallery.packFrameContent"; //$NON-NLS-1$
/**
* Values: true, false
*/
public static final String FlatFrames = "org.xmind.ui.gallery.flatFrames"; //$NON-NLS-1$
/**
* Values: true, false
*/
public static final String SolidFrames = "org.xmind.ui.gallery.solidFrames"; //$NON-NLS-1$
/**
* Values: TITLE_TOP, TITLE_BOTTOM, TITLE_LEFT, TITLE_RIGHT
*/
public static final String TitlePlacement = "org.xmind.ui.gallery.titlePlacement"; //$NON-NLS-1$
/**
* Values: true, false
*/
public static final String SingleClickToOpen = "org.xmind.ui.gallery.singleClickToOpen"; //$NON-NLS-1$
/**
* <p>
* Determines whether this viewer allows empty selection to be set. This
* property does not work when the input contains no elements because the
* selection will always be empty in this case.
* </p>
* Values: true, false
*/
public static final String EmptySelectionIgnored = "org.xmind.ui.gallery.emptySelectionIgnored"; //$NON-NLS-1$
/**
* <p>
* Determines whether this viewer takes use of custom decorator to draw
* content pane.
* </p>
*/
public static final String CustomContentPaneDecorator = "org.xmind.ui.gallery.customDecorateContentPane"; //$NON-NLS-1$
public static final String ContentPaneMargins = "org.xmind.ui.gallery.contentPaneMargins"; //$NON-NLS-1$
public static final String ContentPaneBorderWidth = "org.xmind.ui.gallery.contentPaneBorderWidth"; //$NON-NLS-1$
public static final String ContentPaneBorderColor = "org.xmind.ui.gallery.contentPaneBorderColor"; //$NON-NLS-1$
public static final String ContentPaneSpaceCollaborativeEngine = "org.xmind.ui.gallery.contentPaneSpaceCollaborativeEngine"; //$NON-NLS-1$
public static final String HorizontalLayout = "org.xmind.ui.gallery.horizontalLayout"; //$NON-NLS-1$
/**
* Value for title placement 'top'.
*/
public static final Integer TITLE_TOP = new Integer(PositionConstants.TOP);
/**
* Value for title placement 'bottom'.
*/
public static final Integer TITLE_BOTTOM = new Integer(
PositionConstants.BOTTOM);
/**
* Value for title placement 'left'.
*/
public static final Integer TITLE_LEFT = new Integer(
PositionConstants.LEFT);
/**
* Value for title placement 'right'.
*/
public static final Integer TITLE_RIGHT = new Integer(
PositionConstants.RIGHT);
public static final String POLICY_NAVIGABLE = "org.xmind.ui.gallery.editPolicy.navigable"; //$NON-NLS-1$
public static final String POLICY_MOVABLE = "org.xmind.ui.gallery.editPolicy.movable"; //$NON-NLS-1$
private class GalleryLabelProviderListener
implements ILabelProviderListener {
public void labelProviderChanged(LabelProviderChangedEvent event) {
update(event.getElements());
}
}
private IStructuredContentProvider contentProvider = null;
private IBaseLabelProvider labelProvider = null;
private ILabelProviderListener labelProviderListener = new GalleryLabelProviderListener();
private List<IOpenListener> openListeners = null;
private IFilter titleEditingApprover = null;
public GalleryViewer() {
setPartFactory(GalleryPartFactory.getDefault());
setRootPart(new GraphicalRootEditPart());
}
public <T> T getAdapter(Class<T> adapter) {
if (IBaseLabelProvider.class.equals(adapter))
return adapter.cast(getLabelProvider());
if (IStructuredContentProvider.class.equals(adapter))
return adapter.cast(getContentProvider());
return super.getAdapter(adapter);
}
protected Control internalCreateControl(Composite parent, int style) {
Control control = super.internalCreateControl(parent, style);
control.setBackground(
parent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
return control;
}
public void update() {
update(null);
}
public void update(Object[] elements) {
if (elements == null) {
IPart contents = getRootPart().getContents();
if (contents.getStatus().isActive())
contents.refresh();
for (IPart p : contents.getChildren()) {
if (p.getStatus().isActive()) {
((IGraphicalPart) p).refresh();
}
}
} else {
for (Object element : elements) {
IPart p = findPart(element);
if (p != null && p.getStatus().isActive()) {
((IGraphicalPart) p).refresh();
}
}
}
}
public void setContentProvider(IStructuredContentProvider contentProvider) {
IStructuredContentProvider oldContentProvider = this.contentProvider;
this.contentProvider = contentProvider;
if (oldContentProvider != null) {
Object currentInput = getInput();
oldContentProvider.inputChanged(this, currentInput, null);
oldContentProvider.dispose();
contentProvider.inputChanged(this, null, currentInput);
refresh();
}
}
public IStructuredContentProvider getContentProvider() {
return contentProvider;
}
public IBaseLabelProvider getLabelProvider() {
if (labelProvider == null) {
labelProvider = new LabelProvider();
}
return labelProvider;
}
public void setLabelProvider(IBaseLabelProvider labelProvider) {
if (labelProvider == null)
return;
IBaseLabelProvider oldLabelProvider = this.labelProvider;
if (labelProvider == oldLabelProvider)
return;
if (oldLabelProvider != null) {
oldLabelProvider.removeListener(labelProviderListener);
}
this.labelProvider = labelProvider;
labelProviderListener = new GalleryLabelProviderListener();
labelProvider.addListener(labelProviderListener);
refresh();
if (oldLabelProvider != null) {
oldLabelProvider.dispose();
}
}
@Override
protected void contentsChanged(Object input, Object oldInput) {
IStructuredContentProvider content = getContentProvider();
if (content != null) {
content.inputChanged(this, oldInput, input);
}
super.contentsChanged(input, oldInput);
}
protected void handleDispose(DisposeEvent e) {
if (contentProvider != null) {
contentProvider.inputChanged(this, getInput(), null);
contentProvider.dispose();
contentProvider = null;
}
if (labelProvider != null) {
labelProvider.removeListener(labelProviderListener);
labelProvider.dispose();
labelProvider = null;
}
super.handleDispose(e);
}
public void centerHorizontal() {
FigureCanvas fc = getCanvas();
if (fc.isDisposed())
return;
RangeModel horizontal = fc.getViewport().getHorizontalRangeModel();
int h = (horizontal.getMaximum() - horizontal.getExtent()
+ horizontal.getMinimum()) / 2;
fc.scrollToX(h);
}
public void addOpenListener(IOpenListener listener) {
if (openListeners == null)
openListeners = new ArrayList<IOpenListener>();
openListeners.add(listener);
}
public void removeOpenListener(IOpenListener listener) {
if (openListeners == null)
return;
openListeners.remove(listener);
}
protected void fireOpen(final OpenEvent event) {
if (openListeners == null)
return;
for (final Object l : openListeners.toArray()) {
SafeRunner.run(new SafeRunnable() {
public void run() throws Exception {
((IOpenListener) l).open(event);
}
});
}
}
protected void fireOpen() {
fireOpen(new OpenEvent(this, getSelection()));
}
private List<? extends IPart> toReveal;
protected void revealParts(List<? extends IPart> parts) {
if (toReveal != null) {
toReveal = parts;
} else {
toReveal = parts;
Display.getCurrent().asyncExec(new Runnable() {
public void run() {
if (toReveal == null || getControl() == null
|| getControl().isDisposed())
return;
Rectangle r = null;
for (IPart p : toReveal) {
if (p instanceof IGraphicalPart) {
r = Geometry.union(r, ((IGraphicalPart) p)
.getFigure().getBounds());
}
}
if (r != null) {
ensureVisible(r);
}
toReveal = null;
}
});
}
}
@Override
public void setSelection(ISelection selection) {
setSelection(selection, true);
}
@Override
public void setSelection(ISelection selection, boolean reveal) {
if (getProperties().getBoolean(EmptySelectionIgnored, false)
&& selection.isEmpty())
return;
super.setSelection(selection, reveal);
}
public IFilter getTitleEditingApprover() {
return titleEditingApprover;
}
public void setTitleEditingApprover(IFilter titleEditingApprover) {
this.titleEditingApprover = titleEditingApprover;
}
protected boolean isTitleEditable(IPart p) {
return titleEditingApprover != null && titleEditingApprover.select(p);
}
public Object getProperty(String key, Object defaultValue) {
return getProperties().get(key, defaultValue);
}
}