package org.xmind.ui.internal.views;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.jface.resource.ResourceManager;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.IOpenListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.custom.StackLayout;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
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.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IPropertyListener;
import org.eclipse.ui.forms.HyperlinkGroup;
import org.eclipse.ui.forms.widgets.ScrolledForm;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.forms.widgets.TableWrapData;
import org.eclipse.ui.forms.widgets.TableWrapLayout;
import org.eclipse.ui.internal.forms.widgets.FormUtil;
import org.eclipse.ui.part.IPageSite;
import org.eclipse.ui.part.Page;
import org.xmind.core.Core;
import org.xmind.core.IBoundary;
import org.xmind.core.IFileEntry;
import org.xmind.core.IImage;
import org.xmind.core.IManifest;
import org.xmind.core.IMeta;
import org.xmind.core.IModifiable;
import org.xmind.core.INotes;
import org.xmind.core.INotesContent;
import org.xmind.core.IPlainNotesContent;
import org.xmind.core.IRelationship;
import org.xmind.core.IRevision;
import org.xmind.core.ISheet;
import org.xmind.core.ITopic;
import org.xmind.core.IWorkbook;
import org.xmind.core.event.CoreEvent;
import org.xmind.core.event.CoreEventRegister;
import org.xmind.core.event.ICoreEventListener;
import org.xmind.core.event.ICoreEventSupport;
import org.xmind.core.internal.dom.NumberUtils;
import org.xmind.core.util.HyperlinkUtils;
import org.xmind.gef.command.Command;
import org.xmind.gef.command.CompoundCommand;
import org.xmind.gef.command.ICommandStack;
import org.xmind.ui.commands.ModifyMetadataCommand;
import org.xmind.ui.forms.WidgetFactory;
import org.xmind.ui.internal.AttachmentImageDescriptor;
import org.xmind.ui.internal.MindMapMessages;
import org.xmind.ui.internal.MindMapUIPlugin;
import org.xmind.ui.internal.mindmap.ImageDownloader;
import org.xmind.ui.internal.protocols.FilePathParser;
import org.xmind.ui.mindmap.IMindMapImages;
import org.xmind.ui.mindmap.MindMapUI;
import org.xmind.ui.viewers.FileUtils;
import org.xmind.ui.viewers.IListLayout;
import org.xmind.ui.viewers.IListRenderer;
import org.xmind.ui.viewers.ImageLabel;
import org.xmind.ui.viewers.MListViewer;
import org.xmind.ui.viewers.StraightListLayout;
public class WorkbookMetadataPage extends Page {
private static final int PROP_CONTROL = 1;
private static final int PROP_FOCUS_CONTROL = 2;
private static final int PROP_CONTENT = 3;
private static final int PROP_OUTGOING_SELECTION = 4;
private static final String KEY_WIDGET_FACTORY = WorkbookMetadataPage.class
.getName() + ".widgetFactory"; //$NON-NLS-1$
private static interface IWorkbookMetadataPart {
// section text
String getTitle();
// controls visibility of this part
boolean isVisible();
// layout on the parent should be set in this method
void createControl(Composite parent);
// when triggered upon workbook change, the event is null
// when triggered upon core event, the event is not null
void refresh(IWorkbook workbook, CoreEvent event);
void addPropertyListener(IPropertyListener listener);
void removePropertyListener(IPropertyListener listener);
Control getFocusControl();
}
private static interface IModifiableWorkbookMetadataPart {
Command createModificationCommand(IWorkbook workbook);
}
protected static class WorkbookMetadata {
private final Map<String, Object> delegate = new HashMap<String, Object>();
public boolean set(String key, Object value) {
Object oldValue = delegate.put(key, value);
return value != oldValue
&& (value == null || !value.equals(oldValue));
}
public Object get(String key) {
return delegate.get(key);
}
public boolean delete(String key) {
boolean hadValue = delegate.containsKey(key);
delegate.remove(key);
return hadValue;
}
public boolean deleteAll() {
boolean hadValues = !delegate.isEmpty();
delegate.clear();
return hadValues;
}
// throws ClassCastException if value is not of Integer
public int getInt(String key) {
Object value = delegate.get(key);
if (value != null)
return ((Integer) value).intValue();
return 0;
}
public boolean setInt(String key, int value) {
if (value == 0)
return delete(key);
return set(key, Integer.valueOf(value));
}
public boolean increaseInt(String key, int delta) {
int value = getInt(key);
return setInt(key, value + delta);
}
public boolean decreaseInt(String key, int delta) {
int value = getInt(key);
return setInt(key, value - delta);
}
public long getLong(String key) {
Object value = delegate.get(key);
if (value != null)
return ((Long) value).longValue();
return 0;
}
public boolean setLong(String key, long value) {
if (value == 0)
return delete(key);
return set(key, Long.valueOf(value));
}
public boolean increaseLong(String key, long delta) {
long value = getLong(key);
return setLong(key, value + delta);
}
public boolean decreaseLong(String key, long delta) {
long value = getLong(key);
return setLong(key, value - delta);
}
// throws ClassCastException if value is not of String
public String getString(String key) {
return (String) delegate.get(key);
}
public boolean setString(String key, String value) {
if (value == null)
return delete(key);
return set(key, value);
}
// throws ClassCastException if value is not of Set
@SuppressWarnings("unchecked")
public <T> Set<T> getSet(String key) {
Object value = delegate.get(key);
if (value != null)
return (Set<T>) value;
return Collections.emptySet();
}
@SuppressWarnings("unchecked")
public boolean addToSet(String key, Object object) {
boolean changed = false;
@SuppressWarnings("unchecked")
Set set = (Set) delegate.get(key);
if (set == null) {
set = new HashSet();
delegate.put(key, set);
changed = true;
}
changed |= set.add(object);
return changed;
}
public boolean removeFromSet(String key, Object object) {
boolean changed = false;
@SuppressWarnings("unchecked")
Set set = (Set) delegate.get(key);
if (set != null) {
changed |= set.remove(object);
if (set.isEmpty()) {
delegate.remove(key);
changed = true;
}
}
return changed;
}
public int sizeOfSet(String key) {
Set set = (Set) delegate.get(key);
return set == null ? 0 : set.size();
}
public boolean containsInSet(String key, Object object) {
Set set = (Set) delegate.get(key);
return set != null && set.contains(object);
}
public boolean contains(String key) {
return delegate.containsKey(key);
}
public Collection<String> keys() {
return delegate.keySet();
}
public boolean isEmpty() {
return delegate.isEmpty();
}
@SuppressWarnings("unchecked")
public WorkbookMetadata copy() {
WorkbookMetadata that = new WorkbookMetadata();
for (String key : keys()) {
Object value = get(key);
if (value instanceof Set) {
value = new HashSet((Set) value);
}
that.set(key, value);
}
return that;
}
@Override
public boolean equals(Object obj) {
if (obj == this)
return true;
if (obj == null || !(obj instanceof WorkbookMetadata))
return false;
WorkbookMetadata that = (WorkbookMetadata) obj;
return this.delegate.equals(that.delegate);
}
@Override
public int hashCode() {
return this.delegate.hashCode();
}
@Override
public String toString() {
return this.delegate.toString();
}
}
private static final String METADATA_AUTHOR_EMAIL = "author.email"; //$NON-NLS-1$
private static final String METADATA_AUTHOR_NAME = "author.name"; //$NON-NLS-1$
private static final String METADATA_AUTHOR_ORG = "author.org"; //$NON-NLS-1$
private static final String METADATA_ESTIMATED_SIZE = "estimatedSize"; //$NON-NLS-1$
private static final String METADATA_TOPIC_COUNT = "topicCount"; //$NON-NLS-1$
private static final String METADATA_WORD_COUNT = "wordCount"; //$NON-NLS-1$
private static final String METADATA_REVISION_COUNT = "revisionCount"; //$NON-NLS-1$
private static final String METADATA_MODIFICATION_TIME = "modificationTime"; //$NON-NLS-1$
private static final String METADATA_MODIFIER_NAME = "modifierName"; //$NON-NLS-1$
private static final String METADATA_CREATION_TIME = "creationTime"; //$NON-NLS-1$
private static final String METADATA_ATTACHMENTS = "attachments"; //$NON-NLS-1$
private static final String METADATA_EXTERNAL_FILES = "externalFiles"; //$NON-NLS-1$
private static final String METADATA_HYPERLINKS = "hyperlinks"; //$NON-NLS-1$
private static final String METADATA_IMAGES = "images"; //$NON-NLS-1$
private static abstract class AbstractWorkbookMetadataPart
implements IWorkbookMetadataPart {
private ListenerList listeners = new ListenerList();
private Control focusControl = null;
private Listener focusControlUpdater = new Listener() {
public void handleEvent(Event event) {
focusControl = (Control) event.widget;
firePropertyChange(PROP_FOCUS_CONTROL);
}
};
private boolean refreshScheduled = false;
protected final WorkbookMetadata metadata = new WorkbookMetadata();
public boolean isVisible() {
return !metadata.isEmpty();
}
public void addPropertyListener(IPropertyListener listener) {
listeners.add(listener);
}
public void removePropertyListener(IPropertyListener listener) {
listeners.remove(listener);
}
public Control getFocusControl() {
return focusControl;
}
protected void firePropertyChange(final int propId) {
final Object source = this;
for (final Object listener : listeners.getListeners()) {
SafeRunner.run(new SafeRunnable() {
public void run() throws Exception {
((IPropertyListener) listener).propertyChanged(source,
propId);
}
});
}
}
protected void hookFocusableControl(Control control) {
control.addListener(SWT.FocusIn, focusControlUpdater);
}
protected void updateText(Text control, String text) {
if (control == null || control.isDisposed())
return;
if (text == null)
text = ""; //$NON-NLS-1$
if (text.equals(control.getText()))
return;
Point selection = new Point(text.length(), text.length());
if (control.isFocusControl()) {
selection.x = Math.min(selection.x, control.getSelection().x);
selection.y = Math.min(selection.y, control.getSelection().y);
}
control.setText(text);
if (control.isFocusControl()) {
control.setSelection(selection);
}
firePropertyChange(PROP_CONTROL);
}
protected abstract void refreshControls();
protected void refreshAsynchronously() {
if (refreshScheduled)
return;
Display display = Display.getCurrent();
if (display == null)
return;
display.asyncExec(new Runnable() {
public void run() {
refreshScheduled = false;
refreshControls();
}
});
refreshScheduled = true;
}
}
private static class WorkbookMetadataListRow extends Composite {
private ImageLabel imageLabel;
private Label textLabel;
private boolean selected;
private Color background;
private Listener listener = new Listener() {
public void handleEvent(Event event) {
if (event.type == SWT.MouseDown) {
getParent().setFocus();
handleMouseDown(event);
} else if (event.type == SWT.MouseDoubleClick) {
handleMouseDoubleClick(event);
}
}
};
public WorkbookMetadataListRow(Composite parent,
WidgetFactory factory) {
super(parent, SWT.NO_FOCUS);
selected = false;
background = super.getBackground();
factory.adapt(this, true, true);
setMenu(parent.getMenu());
hookControl(this);
GridLayout layout = new GridLayout(2, false);
layout.marginWidth = 2;
layout.marginHeight = 1;
layout.horizontalSpacing = 2;
layout.verticalSpacing = 0;
setLayout(layout);
imageLabel = new ImageLabel(this, SWT.NO_FOCUS);
factory.adapt(imageLabel, true, true);
imageLabel.setScaleHint(ImageLabel.SCALE_TO_FIT);
imageLabel.setHorizontalAlignment(SWT.CENTER);
imageLabel.setVerticalAlignment(SWT.CENTER);
GridData imageLayoutData = new GridData(SWT.CENTER, SWT.CENTER,
false, true);
imageLayoutData.exclude = true;
imageLabel.setLayoutData(imageLayoutData);
imageLabel.setVisible(false);
imageLabel.setBackground(
parent.getDisplay().getSystemColor(SWT.COLOR_TRANSPARENT));
imageLabel.setMenu(getMenu());
hookControl(imageLabel);
textLabel = factory.createLabel(this, "", SWT.NO_FOCUS); //$NON-NLS-1$
textLabel.setLayoutData(
new GridData(SWT.FILL, SWT.CENTER, true, true));
textLabel.setBackground(
parent.getDisplay().getSystemColor(SWT.COLOR_TRANSPARENT));
textLabel.setMenu(getMenu());
hookControl(textLabel);
}
public void setImageSizeHint(Point hint) {
GridData layoutData = (GridData) imageLabel.getLayoutData();
layoutData.widthHint = hint.x;
layoutData.heightHint = hint.y;
layout(true);
}
private void hookControl(Control c) {
c.addListener(SWT.MouseDown, listener);
c.addListener(SWT.MouseDoubleClick, listener);
}
public void setImage(Image image) {
checkWidget();
imageLabel.setImage(image);
boolean visible = image != null;
imageLabel.setVisible(visible);
((GridData) imageLabel.getLayoutData()).exclude = !visible;
layout(true);
}
public void setText(String text) {
checkWidget();
textLabel.setText(text);
layout(true);
}
public boolean getSelection() {
return selected;
}
public void setSelection(boolean selection) {
checkWidget();
if (selection == this.selected)
return;
this.selected = selection;
updateBackground();
}
@Override
public Color getBackground() {
return background;
}
@Override
public void setBackground(Color color) {
checkWidget();
this.background = color;
updateBackground();
}
private void updateBackground() {
if (getSelection()) {
super.setBackground(
getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION));
} else {
super.setBackground(background);
}
}
private void handleMouseDown(Event event) {
Control[] siblings = getParent().getChildren();
for (int i = 0; i < siblings.length; i++) {
Control item = siblings[i];
if (item instanceof WorkbookMetadataListRow) {
((WorkbookMetadataListRow) item).setSelection(false);
}
}
setSelection(true);
getParent().notifyListeners(SWT.Selection, new Event());
}
private void handleMouseDoubleClick(Event event) {
getParent().notifyListeners(SWT.DefaultSelection, new Event());
}
}
private static class WorkbookMetadataListLabelProvider extends LabelProvider
implements IListRenderer {
private StraightListLayout layout = new StraightListLayout(
SWT.VERTICAL);
public IListLayout getListLayout(MListViewer viewer) {
return layout;
}
public Control createListItemForElement(MListViewer viewer,
Composite parent, Object element) {
WidgetFactory factory = (WidgetFactory) viewer.getControl()
.getData(KEY_WIDGET_FACTORY);
WorkbookMetadataListRow row = new WorkbookMetadataListRow(parent,
factory);
return row;
}
public void updateListItem(MListViewer viewer, Object element,
Control item) {
WorkbookMetadataListRow row = (WorkbookMetadataListRow) item;
row.setText(getText(element));
row.setImage(getImage(element));
}
public int getListItemState(MListViewer viewer, Control item) {
int state = STATE_NONE;
if (item instanceof WorkbookMetadataListRow) {
WorkbookMetadataListRow row = (WorkbookMetadataListRow) item;
if (row.getSelection()) {
state |= STATE_SELECTED;
}
}
return state;
}
public void setListItemState(MListViewer viewer, Control item,
int state) {
if (item instanceof WorkbookMetadataListRow) {
WorkbookMetadataListRow row = (WorkbookMetadataListRow) item;
row.setSelection((state & STATE_SELECTED) != 0);
}
}
}
private static abstract class AbstractWorkbookMetadataListPart
extends AbstractWorkbookMetadataPart implements IAdaptable {
private MListViewer viewer;
protected abstract Object[] getElements(WorkbookMetadata metadata);
protected abstract String getText(Object element);
protected abstract Image getImage(Object element,
ResourceManager resourceManager);
protected Point getImageSizeHint() {
return new Point(SWT.DEFAULT, SWT.DEFAULT);
}
protected void update(Object element) {
viewer.update(element, null);
firePropertyChange(PROP_CONTROL);
}
protected MListViewer getViewer() {
return viewer;
}
public void createControl(final Composite parent) {
WidgetFactory factory = (WidgetFactory) parent
.getData(KEY_WIDGET_FACTORY);
GridLayout layout = new GridLayout();
layout.numColumns = 1;
layout.makeColumnsEqualWidth = false;
layout.marginWidth = 0;
layout.marginHeight = 0;
layout.horizontalSpacing = 3;
layout.verticalSpacing = 3;
parent.setLayout(layout);
viewer = new MListViewer(parent, SWT.NONE);
factory.adapt(viewer.getControl(), true, true);
viewer.getControl().setMenu(parent.getMenu());
viewer.getControl().setData(KEY_WIDGET_FACTORY, factory);
viewer.getControl().setLayoutData(
new GridData(SWT.FILL, SWT.FILL, true, true));
hookFocusableControl(viewer.getControl());
viewer.setContentProvider(createContentProvider());
viewer.setLabelProvider(createLabelProvider());
viewer.setInput(metadata);
viewer.addOpenListener(new IOpenListener() {
public void open(OpenEvent event) {
firePropertyChange(PROP_OUTGOING_SELECTION);
}
});
final ScrolledComposite scrolledComposite = FormUtil
.getScrolledComposite(parent);
if (scrolledComposite != null) {
viewer.getControl().addListener(SWT.FocusOut, new Listener() {
public void handleEvent(Event event) {
Display.getCurrent().asyncExec(new Runnable() {
public void run() {
Display display = Display.getCurrent();
if (display == null || display.isDisposed()
|| scrolledComposite.isDisposed())
return;
Control focusControl = display
.getFocusControl();
if (containsControl(scrolledComposite,
focusControl)
&& !containsControl(parent,
focusControl)) {
viewer.setSelection(
StructuredSelection.EMPTY);
}
}
});
}
private boolean containsControl(Composite composite,
Control c) {
while (c != null) {
if (c == composite)
return true;
c = c.getParent();
}
return false;
}
});
}
}
@Override
protected void refreshControls() {
if (viewer == null || viewer.getControl() == null
|| viewer.getControl().isDisposed())
return;
viewer.refresh();
firePropertyChange(PROP_CONTROL);
}
protected IContentProvider createContentProvider() {
return new IStructuredContentProvider() {
public void inputChanged(Viewer viewer, Object oldInput,
Object newInput) {
}
public void dispose() {
}
public Object[] getElements(Object inputElement) {
WorkbookMetadata metadata = (WorkbookMetadata) inputElement;
return AbstractWorkbookMetadataListPart.this
.getElements(metadata);
}
};
}
private IBaseLabelProvider createLabelProvider() {
return new WorkbookMetadataListLabelProvider() {
ResourceManager rm = new LocalResourceManager(
JFaceResources.getResources());
@Override
public String getText(Object element) {
return AbstractWorkbookMetadataListPart.this
.getText(element);
}
@Override
public Image getImage(Object element) {
return AbstractWorkbookMetadataListPart.this
.getImage(element, rm);
}
@Override
public Control createListItemForElement(MListViewer viewer,
Composite parent, Object element) {
Control item = super.createListItemForElement(viewer,
parent, element);
if (item instanceof WorkbookMetadataListRow) {
((WorkbookMetadataListRow) item)
.setImageSizeHint(getImageSizeHint());
}
return item;
}
@Override
public void dispose() {
super.dispose();
rm.dispose();
}
};
}
public <T> T getAdapter(Class<T> adapter) {
if (adapter == ISelectionProvider.class)
return adapter.cast(viewer);
return null;
}
}
private static class TopicViewerComparator extends ViewerComparator {
@Override
public int compare(Viewer viewer, Object e1, Object e2) {
return Core.getTopicComparator().compare((ITopic) e1, (ITopic) e2);
}
}
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//// Author Info Section
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
private static class AuthorInfoPart extends AbstractWorkbookMetadataPart
implements IModifiableWorkbookMetadataPart {
private Text nameInput;
private Text emailInput;
private Text orgInput;
private Listener modifyListener = new Listener() {
public void handleEvent(Event event) {
firePropertyChange(PROP_CONTENT);
}
};
public boolean isVisible() {
return true;
}
public String getTitle() {
return Messages.AuthorInfoInspectorSection_title;
}
public void createControl(Composite parent) {
WidgetFactory factory = (WidgetFactory) parent
.getData(KEY_WIDGET_FACTORY);
GridLayout layout = new GridLayout();
layout.marginWidth = 0;
layout.marginHeight = 0;
layout.horizontalSpacing = 5;
layout.verticalSpacing = 3;
layout.numColumns = 2;
parent.setLayout(layout);
createLabel(parent, factory,
Messages.AuthorInfoInspectorSection_Name);
nameInput = createText(parent, factory);
createLabel(parent, factory,
Messages.AuthorInfoInspectorSection_Email);
emailInput = createText(parent, factory);
createLabel(parent, factory,
Messages.AuthorInfoInspectorSection_Organization);
orgInput = createText(parent, factory);
}
private Label createLabel(Composite parent, WidgetFactory factory,
String text) {
Label label = factory.createLabel(parent, text);
label.setLayoutData(
new GridData(SWT.BEGINNING, SWT.CENTER, false, false));
return label;
}
private Text createText(Composite parent, WidgetFactory factory) {
Text text = factory.createText(parent, "", SWT.SINGLE); //$NON-NLS-1$
text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
text.addListener(SWT.DefaultSelection, modifyListener);
text.addListener(SWT.FocusOut, modifyListener);
hookFocusableControl(text);
return text;
}
public void refresh(IWorkbook workbook, CoreEvent event) {
boolean changed = false;
if (workbook == null) {
changed |= metadata.setString(METADATA_AUTHOR_NAME, ""); //$NON-NLS-1$
changed |= metadata.setString(METADATA_AUTHOR_EMAIL, ""); //$NON-NLS-1$
changed |= metadata.setString(METADATA_AUTHOR_ORG, ""); //$NON-NLS-1$
} else if (event == null) {
IMeta meta = workbook.getMeta();
changed |= metadata.setString(METADATA_AUTHOR_NAME,
meta.getValue(IMeta.AUTHOR_NAME));
changed |= metadata.setString(METADATA_AUTHOR_EMAIL,
meta.getValue(IMeta.AUTHOR_EMAIL));
changed |= metadata.setString(METADATA_AUTHOR_ORG,
meta.getValue(IMeta.AUTHOR_ORG));
} else if (Core.Metadata.equals(event.getType())) {
if (IMeta.AUTHOR_NAME.equals(event.getTarget())) {
changed |= metadata.setString(METADATA_AUTHOR_NAME,
(String) event.getNewValue());
} else if (IMeta.AUTHOR_EMAIL.equals(event.getTarget())) {
changed |= metadata.setString(METADATA_AUTHOR_EMAIL,
(String) event.getNewValue());
} else if (IMeta.AUTHOR_ORG.equals(event.getTarget())) {
changed |= metadata.setString(METADATA_AUTHOR_ORG,
(String) event.getNewValue());
}
}
if (changed) {
refreshAsynchronously();
}
}
@Override
protected void refreshControls() {
String name = metadata.getString(METADATA_AUTHOR_NAME);
if (name == null || "".equals(name)) //$NON-NLS-1$
name = System.getProperty("user.name"); //$NON-NLS-1$
updateText(nameInput, name);
updateText(emailInput, metadata.getString(METADATA_AUTHOR_EMAIL));
updateText(orgInput, metadata.getString(METADATA_AUTHOR_ORG));
}
public Command createModificationCommand(IWorkbook workbook) {
String newName = nameInput.getText();
String newEmail = emailInput.getText();
String newOrg = orgInput.getText();
Command command = new CompoundCommand( //
new ModifyMetadataCommand(workbook, IMeta.AUTHOR_NAME,
newName), //
new ModifyMetadataCommand(workbook, IMeta.AUTHOR_EMAIL,
newEmail), //
new ModifyMetadataCommand(workbook, IMeta.AUTHOR_ORG,
newOrg) //
);
if (!command.canExecute())
return null;
command.setLabel(MindMapMessages.WorkbookMetadata_ModifyAuthorInfo);
return command;
}
}
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//// Summary Section
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
private static final int PRIMARY_BYTES = 5300;
private static final int TOPIC_DEFAULT_BYTES = 160;
private static class WorkbookSummaryPart
extends AbstractWorkbookMetadataPart {
private Text estimatedSizeText;
private Text topicCountText;
private Text wordCountText;
private Text revisionCountText;
private Text modificationTimeText;
private Text modifierNameText;
private Text creationTimeText;
public boolean isVisible() {
return true;
}
public String getTitle() {
return Messages.FileInfoInspectorSection_title;
}
public void createControl(Composite parent) {
WidgetFactory factory = (WidgetFactory) parent
.getData(KEY_WIDGET_FACTORY);
GridLayout layout = new GridLayout();
layout.marginWidth = 0;
layout.marginHeight = 0;
layout.horizontalSpacing = 5;
layout.verticalSpacing = 3;
layout.numColumns = 2;
parent.setLayout(layout);
estimatedSizeText = createTextWithLabel(parent, factory,
Messages.FileInfoEstimateSize_label);
topicCountText = createTextWithLabel(parent, factory,
Messages.FileInfoTopics_label);
wordCountText = createTextWithLabel(parent, factory,
Messages.FileInfoWords_label);
revisionCountText = createTextWithLabel(parent, factory,
Messages.FileInfoRevisions_label);
modificationTimeText = createTextWithLabel(parent, factory,
Messages.FileInfoModifiedTime_label);
modifierNameText = createTextWithLabel(parent, factory,
Messages.FileInfoModifiedBy_label);
creationTimeText = createTextWithLabel(parent, factory,
Messages.FileInfoCreatedTime_label);
}
private Text createTextWithLabel(Composite parent,
WidgetFactory factory, String labelText) {
Label label = factory.createLabel(parent, labelText);
label.setLayoutData(
new GridData(SWT.BEGINNING, SWT.CENTER, false, false));
Text text = new Text(parent,
SWT.READ_ONLY | SWT.SINGLE | factory.getOrientation());
factory.adapt(text, true, false);
text.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
hookFocusableControl(text);
return text;
}
public void refresh(IWorkbook workbook, CoreEvent event) {
WorkbookMetadata oldMetadata = metadata.copy();
if (workbook == null) {
metadata.deleteAll();
} else if (event == null) {
workbookChanged(workbook);
} else if (Core.SheetAdd.equals(event.getType())) {
sheetAdded((ISheet) event.getTarget());
} else if (Core.SheetRemove.equals(event.getType())) {
sheetRemoved((ISheet) event.getTarget());
} else if (Core.TopicAdd.equals(event.getType())) {
topicAdded((ITopic) event.getTarget());
} else if (Core.TopicRemove.equals(event.getType())) {
topicRemoved((ITopic) event.getTarget());
} else if (Core.TitleText.equals(event.getType())) {
titleTextChanged((String) event.getOldValue(),
(String) event.getNewValue());
} else if (Core.TopicNotes.equals(event.getType())) {
if (INotes.PLAIN.equals(event.getTarget())) {
notesChanged((INotesContent) event.getOldValue(),
(INotesContent) event.getNewValue());
}
} else if (Core.FileEntryAdd.equals(event.getType())) {
fileEntryAdded((IFileEntry) event.getTarget());
} else if (Core.FileEntryRemove.equals(event.getType())) {
fileEntryRemoved((IFileEntry) event.getTarget());
} else if (Core.RelationshipAdd.equals(event.getType())) {
relationshipAdded((IRelationship) event.getTarget());
} else if (Core.RelationshipRemove.equals(event.getType())) {
relationshipRemoved((IRelationship) event.getTarget());
} else if (Core.BoundaryAdd.equals(event.getType())) {
boundaryAdded((IBoundary) event.getTarget());
} else if (Core.BoundaryRemove.equals(event.getType())) {
boundaryRemoved((IBoundary) event.getTarget());
} else if (Core.RevisionAdd.equals(event.getType())) {
metadata.increaseInt(METADATA_REVISION_COUNT, 1);
} else if (Core.RevisionRemove.equals(event.getType())) {
metadata.decreaseInt(METADATA_REVISION_COUNT, 1);
} else if (Core.ModifyTime.equals(event.getType())
|| Core.WorkbookSave.equals(event.getType())) {
IModifiable source = (IModifiable) event.getSource();
metadata.setLong(METADATA_MODIFICATION_TIME,
source.getModifiedTime());
metadata.setString(METADATA_MODIFIER_NAME,
source.getModifiedBy());
}
if (!metadata.equals(oldMetadata)) {
refreshAsynchronously();
}
}
@Override
protected void refreshControls() {
updateText(topicCountText,
String.valueOf(metadata.getInt(METADATA_TOPIC_COUNT)));
updateText(wordCountText,
String.valueOf(metadata.getInt(METADATA_WORD_COUNT)));
updateText(estimatedSizeText, FileUtils.fileLengthToString(
metadata.getLong(METADATA_ESTIMATED_SIZE)));
updateText(revisionCountText,
String.valueOf(metadata.getInt(METADATA_REVISION_COUNT)));
updateText(modificationTimeText, NumberUtils
.formatDate(metadata.getLong(METADATA_MODIFICATION_TIME)));
updateText(modifierNameText,
metadata.getString(METADATA_MODIFIER_NAME));
updateText(creationTimeText,
metadata.getString(METADATA_CREATION_TIME));
}
private void workbookChanged(IWorkbook workbook) {
metadata.deleteAll();
metadata.setLong(METADATA_MODIFICATION_TIME,
workbook.getModifiedTime());
String name = workbook.getModifiedBy();
if (name == null || "".equals(name)) //$NON-NLS-1$
name = System.getProperty("user.name"); //$NON-NLS-1$
metadata.setString(METADATA_MODIFIER_NAME, name);
metadata.setString(METADATA_CREATION_TIME,
workbook.getMeta().getValue(IMeta.CREATED_TIME));
metadata.setLong(METADATA_ESTIMATED_SIZE, PRIMARY_BYTES);
for (ISheet sheet : workbook.getSheets()) {
sheetAdded(sheet);
}
Iterator<IFileEntry> entryIter = workbook.getManifest()
.iterFileEntries();
while (entryIter.hasNext()) {
fileEntryAdded(entryIter.next());
}
}
private void sheetAdded(ISheet sheet) {
titleTextChanged(null, sheet.getTitleText());
topicAdded(sheet.getRootTopic());
metadata.increaseInt(METADATA_REVISION_COUNT,
sheet.getOwnedWorkbook().getRevisionRepository()
.getRevisionManager(sheet.getId(), IRevision.SHEET)
.getRevisions().size());
for (IRelationship r : sheet.getRelationships()) {
relationshipAdded(r);
}
}
private void sheetRemoved(ISheet sheet) {
for (IRelationship r : sheet.getRelationships()) {
relationshipRemoved(r);
}
metadata.decreaseInt(METADATA_REVISION_COUNT,
sheet.getOwnedWorkbook().getRevisionRepository()
.getRevisionManager(sheet.getId(), IRevision.SHEET)
.getRevisions().size());
topicRemoved(sheet.getRootTopic());
titleTextChanged(sheet.getTitleText(), null);
}
private void topicAdded(ITopic topic) {
metadata.increaseInt(METADATA_TOPIC_COUNT, 1);
metadata.increaseLong(METADATA_ESTIMATED_SIZE, TOPIC_DEFAULT_BYTES);
titleTextChanged(null, topic.getTitleText());
notesChanged(null, topic.getNotes().getContent(INotes.PLAIN));
Iterator<ITopic> childIter = topic.getAllChildrenIterator();
while (childIter.hasNext()) {
topicAdded(childIter.next());
}
for (IBoundary boundary : topic.getBoundaries()) {
boundaryAdded(boundary);
}
}
private void topicRemoved(ITopic topic) {
for (IBoundary boundary : topic.getBoundaries()) {
boundaryRemoved(boundary);
}
Iterator<ITopic> childIter = topic.getAllChildrenIterator();
while (childIter.hasNext()) {
topicRemoved(childIter.next());
}
notesChanged(topic.getNotes().getContent(INotes.PLAIN), null);
titleTextChanged(topic.getTitleText(), null);
metadata.decreaseLong(METADATA_ESTIMATED_SIZE, TOPIC_DEFAULT_BYTES);
metadata.decreaseInt(METADATA_TOPIC_COUNT, 1);
}
private void titleTextChanged(String oldTitle, String newTitle) {
if (oldTitle != null) {
metadata.decreaseLong(METADATA_ESTIMATED_SIZE,
oldTitle.length());
metadata.decreaseInt(METADATA_WORD_COUNT, countWords(oldTitle));
}
if (newTitle != null) {
metadata.increaseLong(METADATA_ESTIMATED_SIZE,
newTitle.length());
metadata.increaseInt(METADATA_WORD_COUNT, countWords(newTitle));
}
}
private void notesChanged(INotesContent oldNotes,
INotesContent newNotes) {
if (oldNotes instanceof IPlainNotesContent) {
String content = ((IPlainNotesContent) oldNotes)
.getTextContent();
if (content != null) {
metadata.decreaseInt(METADATA_WORD_COUNT,
countWords(content));
}
}
if (newNotes instanceof IPlainNotesContent) {
String content = ((IPlainNotesContent) newNotes)
.getTextContent();
if (content != null) {
metadata.increaseInt(METADATA_WORD_COUNT,
countWords(content));
}
}
}
private void fileEntryAdded(IFileEntry entry) {
metadata.increaseLong(METADATA_ESTIMATED_SIZE, entry.getSize());
}
private void fileEntryRemoved(IFileEntry entry) {
metadata.decreaseLong(METADATA_ESTIMATED_SIZE, entry.getSize());
}
private void relationshipAdded(IRelationship r) {
titleTextChanged(null, r.getTitleText());
}
private void relationshipRemoved(IRelationship r) {
titleTextChanged(r.getTitleText(), null);
}
private void boundaryAdded(IBoundary b) {
titleTextChanged(null, b.getTitleText());
}
private void boundaryRemoved(IBoundary b) {
titleTextChanged(b.getTitleText(), null);
}
private static int countWords(String s) {
int total = s.length();
int count = 0;
boolean inWord = false;
char c;
for (int i = 0; i < total; i++) {
c = s.charAt(i);
if (isOneWordCharacter(c)) {
if (inWord)
count++;
count++;
inWord = false;
} else if (Character.isLetter(c) || Character.isDigit(c)) {
inWord = true;
} else {
if (inWord)
count++;
inWord = false;
}
}
if (inWord)
count++;
return count;
}
private static boolean isOneWordCharacter(char c) {
Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
|| ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
|| ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
|| ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
|| ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
return true;
}
return false;
}
}
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//// Attachments Section
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
private static class AttachmentListPart
extends AbstractWorkbookMetadataListPart {
public String getTitle() {
return NLS.bind(Messages.AttachmentsInspectorSection_title,
metadata.sizeOfSet(METADATA_ATTACHMENTS));
}
public void refresh(IWorkbook workbook, CoreEvent event) {
WorkbookMetadata oldMetadata = metadata.copy();
Object toUpdate = null;
if (workbook == null) {
metadata.deleteAll();
} else if (event == null) {
metadata.deleteAll();
for (ISheet sheet : workbook.getSheets()) {
topicAdded(sheet.getRootTopic());
}
} else if (Core.TopicAdd.equals(event.getType())) {
topicAdded((ITopic) event.getTarget());
} else if (Core.TopicRemove.equals(event.getType())) {
topicRemoved((ITopic) event.getTarget());
} else if (Core.SheetAdd.equals(event.getType())) {
topicAdded(((ISheet) event.getTarget()).getRootTopic());
} else if (Core.SheetRemove.equals(event.getType())) {
topicRemoved(((ISheet) event.getTarget()).getRootTopic());
} else if (Core.TopicHyperlink.equals(event.getType())) {
ITopic source = (ITopic) event.getSource();
linkChanged(source, (String) event.getOldValue(),
(String) event.getNewValue());
if (metadata.containsInSet(METADATA_ATTACHMENTS, source)) {
toUpdate = source;
}
} else if (Core.TitleText.equals(event.getType())) {
Object source = event.getSource();
if (metadata.containsInSet(METADATA_ATTACHMENTS, source)) {
toUpdate = source;
}
}
if (!metadata.equals(oldMetadata)) {
refreshAsynchronously();
} else if (toUpdate != null) {
update(toUpdate);
}
}
private void topicAdded(ITopic topic) {
linkChanged(topic, null, topic.getHyperlink());
Iterator<ITopic> childIter = topic.getAllChildrenIterator();
while (childIter.hasNext()) {
topicAdded(childIter.next());
}
}
private void topicRemoved(ITopic topic) {
Iterator<ITopic> childIter = topic.getAllChildrenIterator();
while (childIter.hasNext()) {
topicRemoved(childIter.next());
}
linkChanged(topic, topic.getHyperlink(), null);
}
private void linkChanged(ITopic topic, String oldLink, String newLink) {
IFileEntry oldEntry = findFileEntry(topic, oldLink);
if (oldEntry != null) {
metadata.removeFromSet(METADATA_ATTACHMENTS, topic);
}
IFileEntry newEntry = findFileEntry(topic, newLink);
if (newEntry != null) {
metadata.addToSet(METADATA_ATTACHMENTS, topic);
}
}
private IFileEntry findFileEntry(ITopic topic, String link) {
if (link == null || !HyperlinkUtils.isAttachmentURL(link))
return null;
IManifest manifest = topic.getOwnedWorkbook().getManifest();
if (manifest == null)
return null;
return manifest.getFileEntry(HyperlinkUtils.toAttachmentPath(link));
}
@Override
public void createControl(Composite parent) {
super.createControl(parent);
getViewer().setComparator(new TopicViewerComparator());
}
@Override
protected Object[] getElements(WorkbookMetadata metadata) {
return metadata.getSet(METADATA_ATTACHMENTS).toArray();
}
@Override
protected String getText(Object element) {
if (!(element instanceof ITopic))
return ""; //$NON-NLS-1$
ITopic topic = (ITopic) element;
String fileName = topic.getTitleText();
IFileEntry entry = findFileEntry(topic, topic.getHyperlink());
if (entry == null)
return fileName;
long size = entry.getSize();
return String.format("%s (%s)", fileName, //$NON-NLS-1$
FileUtils.fileLengthToString(size));
}
@Override
protected Image getImage(Object element,
ResourceManager resourceManager) {
if (!(element instanceof ITopic))
return null;
ITopic topic = (ITopic) element;
String fileName = topic.getTitleText();
ImageDescriptor icon = MindMapUI.getImages().getFileIcon(fileName,
true);
if (icon == null) {
icon = MindMapUI.getImages().get(IMindMapImages.UNKNOWN_FILE,
true);
}
return (Image) resourceManager.get(icon);
}
}
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//// External Files Section
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
private static class ExternalFileListPart
extends AbstractWorkbookMetadataListPart {
public String getTitle() {
return NLS.bind(Messages.ExternalFilesInspectorSection_title,
metadata.sizeOfSet(METADATA_EXTERNAL_FILES));
}
public void refresh(IWorkbook workbook, CoreEvent event) {
WorkbookMetadata oldMetadata = this.metadata.copy();
Object toUpdate = null;
if (workbook == null) {
metadata.deleteAll();
} else if (event == null) {
metadata.deleteAll();
workbookChanged(workbook);
} else if (Core.SheetAdd.equals(event.getType())) {
topicAdded(((ISheet) event.getTarget()).getRootTopic());
} else if (Core.SheetRemove.equals(event.getType())) {
topicRemoved(((ISheet) event.getTarget()).getRootTopic());
} else if (Core.TopicAdd.equals(event.getType())) {
topicAdded((ITopic) event.getTarget());
} else if (Core.TopicRemove.equals(event.getType())) {
topicRemoved((ITopic) event.getTarget());
} else if (Core.TopicHyperlink.equals(event.getType())) {
ITopic source = (ITopic) event.getSource();
linkChanged(source, (String) event.getOldValue(),
(String) event.getNewValue());
if (metadata.containsInSet(METADATA_EXTERNAL_FILES, source)) {
toUpdate = source;
}
} else if (Core.TitleText.equals(event.getType())) {
Object source = event.getSource();
if (metadata.containsInSet(METADATA_EXTERNAL_FILES, source)) {
toUpdate = source;
}
}
if (!metadata.equals(oldMetadata)) {
refreshAsynchronously();
} else if (toUpdate != null) {
update(toUpdate);
}
}
@Override
public void createControl(Composite parent) {
super.createControl(parent);
getViewer().setComparator(new TopicViewerComparator());
}
@Override
protected Object[] getElements(WorkbookMetadata metadata) {
return metadata.getSet(METADATA_EXTERNAL_FILES).toArray();
}
@Override
protected Image getImage(Object element,
ResourceManager resourceManager) {
if (!(element instanceof ITopic))
return null;
ITopic topic = (ITopic) element;
File file = getFile(topic.getHyperlink());
if (file == null)
return null;
ImageDescriptor icon = MindMapUI.getImages()
.getFileIcon(file.getAbsolutePath(), true);
if (icon == null) {
icon = MindMapUI.getImages().get(IMindMapImages.UNKNOWN_FILE,
true);
}
return (Image) resourceManager.get(icon);
}
@Override
protected String getText(Object element) {
if (!(element instanceof ITopic))
return ""; //$NON-NLS-1$
ITopic topic = (ITopic) element;
File file = getFile(topic.getHyperlink());
if (file == null)
return ""; //$NON-NLS-1$
return file.getName();
}
private void workbookChanged(IWorkbook workbook) {
for (ISheet sheet : workbook.getSheets()) {
topicAdded(sheet.getRootTopic());
}
}
private void topicAdded(ITopic topic) {
linkChanged(topic, null, topic.getHyperlink());
Iterator<ITopic> childrenIterator = topic.getAllChildrenIterator();
while (childrenIterator.hasNext()) {
topicAdded(childrenIterator.next());
}
}
private void topicRemoved(ITopic topic) {
Iterator<ITopic> childrenIterator = topic.getAllChildrenIterator();
while (childrenIterator.hasNext()) {
topicRemoved(childrenIterator.next());
}
linkChanged(topic, topic.getHyperlink(), null);
}
private void linkChanged(ITopic topic, String oldLink, String newLink) {
File oldFile = getFile(oldLink);
if (oldFile != null) {
metadata.removeFromSet(METADATA_EXTERNAL_FILES, topic);
}
File newFile = getFile(newLink);
if (newFile != null) {
metadata.addToSet(METADATA_EXTERNAL_FILES, topic);
}
}
private File getFile(String link) {
if (!FilePathParser.isFileURI(link))
return null;
return new File(FilePathParser.toPath(link));
}
}
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//// Hyperlinks Section
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
private static class HyperlinkListPart
extends AbstractWorkbookMetadataListPart {
public String getTitle() {
return NLS.bind(Messages.HyperlinkInspectorSection_title,
metadata.sizeOfSet(METADATA_HYPERLINKS));
}
public void refresh(IWorkbook workbook, CoreEvent event) {
WorkbookMetadata oldMetadata = this.metadata.copy();
Object toUpdate = null;
if (workbook == null) {
metadata.deleteAll();
} else if (event == null) {
metadata.deleteAll();
workbookChanged(workbook);
} else if (Core.SheetAdd.equals(event.getType())) {
topicAdded(((ISheet) event.getTarget()).getRootTopic());
} else if (Core.SheetRemove.equals(event.getType())) {
topicRemoved(((ISheet) event.getTarget()).getRootTopic());
} else if (Core.TopicAdd.equals(event.getType())) {
topicAdded((ITopic) event.getTarget());
} else if (Core.TopicRemove.equals(event.getType())) {
topicRemoved((ITopic) event.getTarget());
} else if (Core.TopicHyperlink.equals(event.getType())) {
ITopic source = (ITopic) event.getSource();
linkChanged(source, (String) event.getOldValue(),
(String) event.getNewValue());
if (metadata.containsInSet(METADATA_HYPERLINKS, source)) {
toUpdate = source;
}
} else if (Core.TitleText.equals(event.getType())) {
Object source = event.getSource();
if (metadata.containsInSet(METADATA_HYPERLINKS, source)) {
toUpdate = source;
}
}
if (!metadata.equals(oldMetadata)) {
refreshAsynchronously();
} else if (toUpdate != null) {
update(toUpdate);
}
}
@Override
public void createControl(Composite parent) {
super.createControl(parent);
getViewer().setComparator(new TopicViewerComparator());
}
@Override
protected Object[] getElements(WorkbookMetadata metadata) {
return metadata.getSet(METADATA_HYPERLINKS).toArray();
}
@Override
protected Image getImage(Object element,
ResourceManager resourceManager) {
return null;
}
@Override
protected String getText(Object element) {
if (!(element instanceof ITopic))
return ""; //$NON-NLS-1$
ITopic topic = (ITopic) element;
return topic.getHyperlink();
}
private void workbookChanged(IWorkbook workbook) {
for (ISheet sheet : workbook.getSheets()) {
topicAdded(sheet.getRootTopic());
}
}
private void topicAdded(ITopic topic) {
linkChanged(topic, null, topic.getHyperlink());
Iterator<ITopic> childrenIterator = topic.getAllChildrenIterator();
while (childrenIterator.hasNext()) {
topicAdded(childrenIterator.next());
}
}
private void topicRemoved(ITopic topic) {
Iterator<ITopic> childrenIterator = topic.getAllChildrenIterator();
while (childrenIterator.hasNext()) {
topicRemoved(childrenIterator.next());
}
linkChanged(topic, topic.getHyperlink(), null);
}
private void linkChanged(ITopic topic, String oldLink, String newLink) {
if (isNormalHyperlink(oldLink)) {
metadata.removeFromSet(METADATA_HYPERLINKS, topic);
}
if (isNormalHyperlink(newLink)) {
metadata.addToSet(METADATA_HYPERLINKS, topic);
}
}
private boolean isNormalHyperlink(String link) {
return link != null && !HyperlinkUtils.isAttachmentURL(link)
&& !HyperlinkUtils.isInternalURL(link)
&& !FilePathParser.isFileURI(link);
}
}
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//// Images Section
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
private static class ImageListPart
extends AbstractWorkbookMetadataListPart {
public String getTitle() {
return NLS.bind(Messages.ImageInspectorSection_title,
metadata.sizeOfSet(METADATA_IMAGES));
}
public void refresh(IWorkbook workbook, CoreEvent event) {
WorkbookMetadata oldMetadata = this.metadata.copy();
Object toUpdate = null;
if (workbook == null) {
metadata.deleteAll();
} else if (event == null) {
metadata.deleteAll();
workbookChanged(workbook);
} else if (Core.SheetAdd.equals(event.getType())) {
topicAdded(((ISheet) event.getTarget()).getRootTopic());
} else if (Core.SheetRemove.equals(event.getTarget())) {
topicRemoved(((ISheet) event.getTarget()).getRootTopic());
} else if (Core.TopicAdd.equals(event.getType())) {
topicAdded((ITopic) event.getTarget());
} else if (Core.TopicRemove.equals(event.getType())) {
topicRemoved((ITopic) event.getTarget());
} else if (Core.ImageSource.equals(event.getType())) {
ITopic source = ((IImage) event.getSource()).getParent();
imageSourceChanged(source, (String) event.getOldValue(),
(String) event.getNewValue());
if (metadata.containsInSet(METADATA_IMAGES, source)) {
toUpdate = source;
}
} else if (Core.TitleText.equals(event.getType())) {
Object source = event.getSource();
if (metadata.containsInSet(METADATA_IMAGES, source)) {
toUpdate = source;
}
}
if (!metadata.equals(oldMetadata)) {
refreshAsynchronously();
} else if (toUpdate != null) {
update(toUpdate);
}
}
@Override
public void createControl(Composite parent) {
super.createControl(parent);
getViewer().setComparator(new TopicViewerComparator());
}
@Override
protected Object[] getElements(WorkbookMetadata metadata) {
return metadata.getSet(METADATA_IMAGES).toArray();
}
@Override
protected String getText(Object element) {
if (!(element instanceof ITopic))
return ""; //$NON-NLS-1$
ITopic topic = (ITopic) element;
String imageURI = topic.getImage().getSource();
if (HyperlinkUtils.isAttachmentURL(imageURI)) {
String path = HyperlinkUtils.toAttachmentPath(imageURI);
IFileEntry entry = topic.getOwnedWorkbook().getManifest()
.getFileEntry(path);
if (entry != null) {
return String.format("%s (%s)", topic.getTitleText(), //$NON-NLS-1$
FileUtils.fileLengthToString(entry.getSize()));
}
}
return topic.getTitleText();
}
@Override
protected Image getImage(final Object element,
final ResourceManager resourceManager) {
if (!(element instanceof ITopic))
return null;
ITopic topic = (ITopic) element;
String imageURI = topic.getImage().getSource();
if (HyperlinkUtils.isAttachmentURL(imageURI)) {
String path = HyperlinkUtils.toAttachmentPath(imageURI);
IWorkbook workbook = topic.getOwnedWorkbook();
IFileEntry entry = workbook.getManifest().getFileEntry(path);
ImageDescriptor descriptor = AttachmentImageDescriptor
.createFromEntry(workbook, entry);
return (Image) resourceManager.get(descriptor);
} else if (FilePathParser.isFileURI(imageURI)) {
String path = FilePathParser.toPath(imageURI);
ImageDescriptor descriptor = ImageDescriptor
.createFromFile(null, path);
return (Image) resourceManager.get(descriptor);
} else {
ImageDescriptor descriptor = ImageDownloader.getInstance()
.getImage(imageURI);
if (descriptor != null)
return (Image) resourceManager.get(descriptor);
ImageDownloader.getInstance().register(imageURI,
new Runnable() {
public void run() {
if (getViewer() == null
|| getViewer().getControl() == null
|| getViewer().getControl()
.isDisposed())
return;
Display display = getViewer().getControl()
.getDisplay();
if (display == null || display.isDisposed())
return;
display.asyncExec(new Runnable() {
public void run() {
update(element);
}
});
}
});
}
return null;
}
@Override
protected Point getImageSizeHint() {
return new Point(32, 32);
}
private void workbookChanged(IWorkbook workbook) {
for (ISheet sheet : workbook.getSheets()) {
topicAdded(sheet.getRootTopic());
}
}
private void topicAdded(ITopic topic) {
imageSourceChanged(topic, null, topic.getImage().getSource());
Iterator<ITopic> childrenIterator = topic.getAllChildrenIterator();
while (childrenIterator.hasNext()) {
topicAdded(childrenIterator.next());
}
}
private void topicRemoved(ITopic topic) {
Iterator<ITopic> childrenIterator = topic.getAllChildrenIterator();
while (childrenIterator.hasNext()) {
topicRemoved(childrenIterator.next());
}
imageSourceChanged(topic, topic.getImage().getSource(), null);
}
private void imageSourceChanged(ITopic topic, String oldSrc,
String newSrc) {
if (oldSrc != null) {
metadata.removeFromSet(METADATA_IMAGES, topic);
}
if (newSrc != null) {
metadata.addToSet(METADATA_IMAGES, topic);
}
}
}
private IEditorPart sourceEditor;
private IWorkbook workbook;
private CoreEventRegister eventRegister;
private WidgetFactory factory;
private Composite composite;
private ScrolledForm form;
private List<IWorkbookMetadataPart> parts = new ArrayList<IWorkbookMetadataPart>();
private Map<IWorkbookMetadataPart, Section> sections = new HashMap<IWorkbookMetadataPart, Section>();
private IWorkbookMetadataPart activePart = null;
private boolean reflowScheduled = false;
private ICoreEventListener coreEventHandler = new ICoreEventListener() {
public void handleCoreEvent(final CoreEvent event) {
Display display = getDisplay();
if (display == null)
return;
display.asyncExec(new Runnable() {
public void run() {
refreshParts(event);
}
});
}
private Display getDisplay() {
Display display = Display.getCurrent();
if (display != null)
return display;
Control control = getControl();
if (control == null || control.isDisposed())
return null;
return control.getDisplay();
}
};
private IPropertyListener propertyChangeHandler = new IPropertyListener() {
public void propertyChanged(Object source, int propId) {
if (source == sourceEditor && propId == IEditorPart.PROP_INPUT) {
setWorkbook(sourceEditor.getAdapter(IWorkbook.class));
} else if (source instanceof IWorkbookMetadataPart) {
if (propId == PROP_CONTROL) {
updateSection((IWorkbookMetadataPart) source);
scheduleReflow();
} else if (propId == PROP_FOCUS_CONTROL) {
activePart = (IWorkbookMetadataPart) source;
} else if (propId == PROP_CONTENT) {
if (source instanceof IModifiableWorkbookMetadataPart) {
executeCommand(
((IModifiableWorkbookMetadataPart) source)
.createModificationCommand(workbook));
}
} else if (propId == PROP_OUTGOING_SELECTION) {
revealSelectionInEditor((IWorkbookMetadataPart) source);
}
}
}
};
public WorkbookMetadataPage(IEditorPart sourceEditor) {
Assert.isNotNull(sourceEditor);
this.sourceEditor = sourceEditor;
}
@Override
public void init(IPageSite pageSite) {
super.init(pageSite);
sourceEditor.addPropertyListener(propertyChangeHandler);
}
@Override
public void createControl(Composite parent) {
composite = new Composite(parent, SWT.NONE);
StackLayout stack = new StackLayout();
composite.setLayout(stack);
factory = new WidgetFactory(parent.getDisplay());
factory.getHyperlinkGroup()
.setHyperlinkUnderlineMode(HyperlinkGroup.UNDERLINE_HOVER);
form = factory.createScrolledForm(composite);
stack.topControl = form;
final Composite content = form.getBody();
TableWrapLayout layout = new TableWrapLayout();
layout.topMargin = 0;
layout.leftMargin = 0;
layout.rightMargin = 0;
layout.bottomMargin = 0;
layout.horizontalSpacing = 0;
layout.verticalSpacing = 3;
content.setLayout(layout);
createSections(content);
form.getBody().addListener(SWT.MouseDown, new Listener() {
public void handleEvent(Event event) {
form.getBody().setFocus();
}
});
form.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
handleDispose();
}
});
setWorkbook(sourceEditor == null ? null
: MindMapUIPlugin.getAdapter(sourceEditor, IWorkbook.class));
}
@Override
public Control getControl() {
return this.composite;
}
@Override
public void setFocus() {
if (form == null || form.isDisposed())
return;
if (activePart != null && activePart.getFocusControl() != null
&& !activePart.getFocusControl().isDisposed()) {
activePart.getFocusControl().setFocus();
} else {
form.getBody().setFocus();
}
}
@Override
public void dispose() {
sourceEditor.removePropertyListener(propertyChangeHandler);
super.dispose();
}
private void createSections(Composite parent) {
addSection(parent, new AuthorInfoPart());
addSection(parent, new WorkbookSummaryPart());
addSection(parent, new AttachmentListPart());
addSection(parent, new ExternalFileListPart());
addSection(parent, new HyperlinkListPart());
addSection(parent, new ImageListPart());
}
private void addSection(Composite parent,
final IWorkbookMetadataPart part) {
final Section section = factory.createSection(parent,
Section.TITLE_BAR | Section.TWISTIE | Section.EXPANDED
| Section.NO_TITLE_FOCUS_BOX);
section.setText(part.getTitle());
section.setLayoutData(
new TableWrapData(TableWrapData.FILL_GRAB, TableWrapData.FILL));
Composite client = factory.createComposite(section, SWT.WRAP);
client.setData(KEY_WIDGET_FACTORY, factory);
section.setClient(client);
part.createControl(client);
part.refresh(workbook, null);
part.addPropertyListener(propertyChangeHandler);
parts.add(part);
sections.put(part, section);
updateSectionVisibility(part, section, part.isVisible());
}
private void updateSection(IWorkbookMetadataPart part) {
Section section = sections.get(part);
if (section != null && !section.isDisposed()) {
String title = part.getTitle();
String oldTitle = section.getText();
if (!title.equals(oldTitle)) {
section.setText(title);
}
boolean visible = part.isVisible();
boolean oldVisible = section.getVisible();
if (visible != oldVisible) {
updateSectionVisibility(part, section, visible);
}
scheduleReflow();
}
}
private void updateSectionVisibility(IWorkbookMetadataPart part,
Section section, boolean visible) {
if (visible) {
section.setParent(form.getBody());
Section lastVisibleSection = null;
for (IWorkbookMetadataPart p : parts) {
if (p == part)
break;
Section s = sections.get(p);
if (s.getVisible()) {
lastVisibleSection = s;
}
}
if (lastVisibleSection == null) {
section.moveAbove(null);
} else {
section.moveBelow(lastVisibleSection);
}
} else {
section.setParent(composite);
}
section.setVisible(visible);
}
private void handleDispose() {
setWorkbook(null);
for (IWorkbookMetadataPart part : parts) {
part.removePropertyListener(propertyChangeHandler);
}
parts.clear();
activePart = null;
sections.clear();
if (factory != null) {
factory.dispose();
factory = null;
}
form = null;
composite = null;
}
public void setWorkbook(IWorkbook workbook) {
IWorkbook oldWorkbook = this.workbook;
if (workbook == oldWorkbook)
return;
this.workbook = workbook;
workbookChanged(workbook, oldWorkbook);
}
private void workbookChanged(IWorkbook workbook, IWorkbook oldWorkbook) {
if (eventRegister != null) {
eventRegister.unregisterAll();
}
if (getControl() != null && !getControl().isDisposed()) {
for (IWorkbookMetadataPart part : parts) {
part.refresh(workbook, null);
}
scheduleReflow();
}
if (workbook != null) {
ICoreEventSupport support = (ICoreEventSupport) workbook
.getAdapter(ICoreEventSupport.class);
if (support != null) {
if (eventRegister == null) {
eventRegister = new CoreEventRegister(coreEventHandler);
}
eventRegister.setNextSupport(support);
registerCoreEventTypes(eventRegister);
}
}
}
private void registerCoreEventTypes(CoreEventRegister register) {
register.register(Core.Metadata);
register.register(Core.SheetAdd);
register.register(Core.SheetRemove);
register.register(Core.TopicAdd);
register.register(Core.TopicRemove);
register.register(Core.FileEntryAdd);
register.register(Core.FileEntryRemove);
register.register(Core.TopicHyperlink);
register.register(Core.TitleText);
register.register(Core.ImageSource);
register.register(Core.RevisionAdd);
register.register(Core.RevisionRemove);
register.register(Core.ModifyTime);
register.register(Core.WorkbookSave);
register.register(Core.RelationshipAdd);
register.register(Core.RelationshipRemove);
register.register(Core.BoundaryAdd);
register.register(Core.BoundaryRemove);
register.register(Core.TopicNotes);
}
private synchronized void scheduleReflow() {
if (form == null || form.isDisposed())
return;
if (reflowScheduled)
return;
Display.getCurrent().asyncExec(new Runnable() {
public void run() {
reflowScheduled = false;
if (form == null || form.isDisposed())
return;
form.reflow(true);
}
});
reflowScheduled = true;
}
private void executeCommand(Command command) {
ICommandStack commandStack = MindMapUIPlugin.getAdapter(sourceEditor,
ICommandStack.class);
if (commandStack != null) {
commandStack.execute(command);
} else {
command.execute();
}
}
private void refreshParts(final CoreEvent event) {
for (IWorkbookMetadataPart part : parts) {
part.refresh(workbook, event);
}
}
private void revealSelectionInEditor(IWorkbookMetadataPart part) {
ISelectionProvider partSelectionProvider = MindMapUIPlugin
.getAdapter(part, ISelectionProvider.class);
if (partSelectionProvider == null)
return;
ISelectionProvider editorSelectionProvider = sourceEditor.getSite()
.getSelectionProvider();
if (editorSelectionProvider == null)
return;
editorSelectionProvider
.setSelection(partSelectionProvider.getSelection());
sourceEditor.getSite().getPage().activate(sourceEditor);
}
}