/* ******************************************************************************
* 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.dialogs;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.PositionConstants;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.dialogs.TitleAreaDialog;
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.viewers.IFontProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.part.PageBook;
import org.xmind.core.ITopic;
import org.xmind.gef.EditDomain;
import org.xmind.gef.GEF;
import org.xmind.gef.part.IPart;
import org.xmind.gef.util.Properties;
import org.xmind.ui.dialogs.HyperlinkPage;
import org.xmind.ui.dialogs.IHyperlinkPage;
import org.xmind.ui.dialogs.IHyperlinkPageContainer;
import org.xmind.ui.gallery.FrameFigure;
import org.xmind.ui.gallery.FramePart;
import org.xmind.ui.gallery.GalleryLayout;
import org.xmind.ui.gallery.GalleryNavigablePolicy;
import org.xmind.ui.gallery.GalleryPartFactory;
import org.xmind.ui.gallery.GallerySelectTool;
import org.xmind.ui.gallery.GalleryViewer;
import org.xmind.ui.gallery.ShadowedLayer;
import org.xmind.ui.internal.MindMapUIPlugin;
import org.xmind.ui.mindmap.IProtocolDescriptor;
import org.xmind.ui.mindmap.MindMapUI;
import org.xmind.ui.util.Logger;
import org.xmind.ui.viewers.ImageCachedLabelProvider;
/**
* @author Frank Shaka
*/
public class HyperlinkDialog extends TitleAreaDialog
implements IHyperlinkPageContainer {
private static class NullHyperlinkPage extends HyperlinkPage {
private Label label;
public void init(IEditorPart editor, IStructuredSelection selection) {
}
public void createControl(Composite parent) {
label = new Label(parent, SWT.NONE);
label.setText(
DialogMessages.HyperlinkDialog_FailCreatePage_message);
}
public void dispose() {
}
public Control getControl() {
return label;
}
public void setActionBars(IActionBars actionBars) {
}
public void setFocus() {
if (label != null && !label.isDisposed()) {
label.setFocus();
}
}
}
private static class TypeItemPart extends FramePart {
public TypeItemPart(Object model) {
super(model);
}
protected IFigure createFigure() {
IFigure fig = super.createFigure();
FrameFigure ff = (FrameFigure) fig;
ShadowedLayer content = ff.getContentPane();
content.setBackgroundColor(null);
content.setForegroundColor(null);
content.setShadowVisible(false);
content.setShadowAlpha(0);
content.setBorderWidth(0);
content.setOpaque(false);
return fig;
}
}
private static class TypePartFactory extends GalleryPartFactory {
public IPart createPart(IPart context, Object model) {
return super.createPart(context, model);
}
protected IPart createFramePart(IPart parent, Object model) {
return new TypeItemPart(model);
}
}
private class TypeViewerLableProvider extends ImageCachedLabelProvider
implements IFontProvider {
public String getText(Object element) {
if (element instanceof HyperlinkPageDescriptor)
return ((HyperlinkPageDescriptor) element).getName();
return super.getText(element);
}
protected Image createImage(Object element) {
if (element instanceof HyperlinkPageDescriptor) {
ImageDescriptor icon = ((HyperlinkPageDescriptor) element)
.getIcon();
if (icon != null)
return icon.createImage(false);
}
return null;
}
public Font getFont(Object element) {
return resources.createFont(JFaceResources
.getDefaultFontDescriptor().increaseHeight(2));
}
}
public static final int REMOVE = 3;
private static final int REMOVE_ID = IDialogConstants.CLIENT_ID + 1;
private static final String KEY_SASH_WEIGHTS = "sashFormWeights"; //$NON-NLS-1$
private String value;
private IEditorPart editor;
private IStructuredSelection selection;
private Map<String, IHyperlinkPage> pages = new HashMap<String, IHyperlinkPage>();
private IHyperlinkPage currentPage;
// The current page message and description
private String pageMessage;
private int pageMessageType = IMessageProvider.NONE;
private String pageDescription;
private PageBook pageBook;
private GalleryViewer typeViewer;
private SashForm form;
private ResourceManager resources;
public HyperlinkDialog(Shell parentShell, IEditorPart editor,
IStructuredSelection selection) {
super(parentShell);
resources = new LocalResourceManager(JFaceResources.getResources(),
parentShell);
this.editor = editor;
this.selection = selection;
setShellStyle(SWT.RESIZE | SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
}
@Override
protected IDialogSettings getDialogBoundsSettings() {
return MindMapUIPlugin.getDefault()
.getDialogSettings("org.xmind.ui.HyperlinkDialog"); //$NON-NLS-1$
}
public void create() {
super.create();
setTitle(DialogMessages.HyperlinkDialog_title);
pageDescription = DialogMessages.HyperlinkDialog_description;
setMessage(pageDescription);
showInitContents();
updateButtons();
updateMessage();
}
private void showInitContents() {
List<HyperlinkPageDescriptor> descriptors = HyperlinkPageRegistry
.getInstance().getHyperlinkPageDescriptors();
if (!descriptors.isEmpty()) {
value = getHyperlinkValue(selection);
HyperlinkPageDescriptor initDescriptor = null;
if (value != null && !"".equals(value)) { //$NON-NLS-1$
initDescriptor = findInitDescriptor(descriptors, value);
}
if (initDescriptor == null) {
initDescriptor = descriptors.get(0);
}
typeViewer.setSelection(new StructuredSelection(initDescriptor),
false);
if (this.currentPage != null) {
this.currentPage.setValue(value);
this.currentPage.setFocus();
}
}
}
private String getHyperlinkValue(IStructuredSelection selection) {
ITopic last = null;
String lastHyperlink = null;
for (Object topic : selection.toArray()) {
if (topic instanceof ITopic) {
String h = ((ITopic) topic).getHyperlink();
if (last != null) {
if (h != lastHyperlink
&& (h == null || !h.equals(lastHyperlink))) {
return null;
}
} else {
last = ((ITopic) topic);
lastHyperlink = h;
}
}
}
return lastHyperlink;
}
private HyperlinkPageDescriptor findInitDescriptor(
List<HyperlinkPageDescriptor> descriptors, String value) {
IProtocolDescriptor protocolDescriptor = MindMapUI.getProtocolManager()
.findProtocolDescriptor(value);
if (protocolDescriptor != null) {
String id = protocolDescriptor.getId();
for (HyperlinkPageDescriptor pageDescriptor : descriptors) {
if (id.equals(pageDescriptor.getProtocolId()))
return pageDescriptor;
}
}
return null;
}
public void configureShell(Shell shell) {
super.configureShell(shell);
shell.setText(DialogMessages.HyperlinkDialog_windowTitle);
shell.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
handleDispose(e);
}
});
}
private void handleDispose(DisposeEvent e) {
disposePages();
}
/**
*
*/
private void disposePages() {
if (!pages.isEmpty()) {
for (IHyperlinkPage page : pages.values()) {
page.dispose();
}
pages.clear();
}
}
protected Control createDialogArea(Composite parent) {
Composite composite = (Composite) super.createDialogArea(parent);
form = new SashForm(composite, SWT.HORIZONTAL | SWT.SMOOTH);
form.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
((GridData) form.getLayoutData()).widthHint = 400;
((GridData) form.getLayoutData()).heightHint = 300;
form.setBackground(
parent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
form.setSashWidth(4);
createTypeViewer(form);
createPageBook(form);
int[] weights = loadSashFormWeights();
if (weights != null) {
form.setWeights(weights);
} else {
form.setWeights(new int[] { 25, 75 });
}
Label label = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL);
label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
return composite;
}
/**
* @param parent
*/
private void createPageBook(Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
GridLayout gridLayout = new GridLayout(2, false);
gridLayout.marginWidth = 0;
gridLayout.marginHeight = 0;
gridLayout.verticalSpacing = 0;
gridLayout.horizontalSpacing = 0;
composite.setLayout(gridLayout);
Label label = new Label(composite, SWT.SEPARATOR | SWT.VERTICAL);
label.setLayoutData(new GridData(SWT.BEGINNING, SWT.FILL, false, true));
pageBook = new PageBook(composite, SWT.NONE);
pageBook.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
}
/**
* @param parent
*/
private void createTypeViewer(Composite parent) {
typeViewer = new GalleryViewer();
Properties properties = typeViewer.getProperties();
properties.set(GalleryViewer.Horizontal, Boolean.FALSE);
properties.set(GalleryViewer.Wrap, Boolean.FALSE);
properties.set(GalleryViewer.TitlePlacement, PositionConstants.RIGHT);
properties.set(GalleryViewer.FlatFrames, Boolean.TRUE);
properties.set(GalleryViewer.Layout,
new GalleryLayout(GalleryLayout.ALIGN_TOPLEFT,
GalleryLayout.ALIGN_FILL, 0, 1, new Insets(1)));
properties.set(GalleryViewer.SingleClickToOpen, Boolean.FALSE);
properties.set(GEF.SelectionConstraint, GEF.SEL_SINGLE);
// properties.set(GalleryViewer.FrameContentSize, new Dimension(32, 32));
// properties.set(GalleryViewer.ImageConstrained, Boolean.TRUE);
EditDomain editDomain = new EditDomain();
editDomain.installTool(GEF.TOOL_SELECT, new GallerySelectTool());
editDomain.installEditPolicy(GalleryViewer.POLICY_NAVIGABLE,
new GalleryNavigablePolicy());
typeViewer.setEditDomain(editDomain);
typeViewer.setPartFactory(new TypePartFactory());
typeViewer.setLabelProvider(new TypeViewerLableProvider());
typeViewer.createControl(parent);
typeViewer.setInput(HyperlinkPageRegistry.getInstance()
.getHyperlinkPageDescriptors());
typeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
IStructuredSelection selection = (IStructuredSelection) event
.getSelection();
HyperlinkPageDescriptor desc = (HyperlinkPageDescriptor) selection
.getFirstElement();
showPage(desc);
}
});
}
public IHyperlinkPage getCurrentPage() {
return currentPage;
}
protected void showPage(HyperlinkPageDescriptor desc) {
String id = desc.getId();
IHyperlinkPage page = pages.get(id);
if (page == null) {
page = createPage(desc);
page.init(editor, selection);
page.setContainer(this);
pages.put(id, page);
}
showPage(page, desc);
}
private IHyperlinkPage createPage(HyperlinkPageDescriptor desc) {
try {
return desc.createPage();
} catch (CoreException e) {
Logger.log(e);
}
return new NullHyperlinkPage();
}
private void showPage(IHyperlinkPage page,
HyperlinkPageDescriptor descriptor) {
Control control = getPageControl(page, descriptor);
pageBook.showPage(control);
this.currentPage = page;
updateButtons();
updateMessage();
page.setFocus();
}
/**
* @param page
* @return
*/
private Control getPageControl(IHyperlinkPage page,
HyperlinkPageDescriptor descriptor) {
Control control = page.getControl();
if (control == null) {
page.createControl(pageBook);
control = page.getControl();
Assert.isNotNull(control);
}
return control;
}
protected void createButtonsForButtonBar(Composite parent) {
createButton(parent, REMOVE_ID, DialogMessages.HyperlinkDialog_Remove,
false);
super.createButtonsForButtonBar(parent);
}
/*
* (non-Javadoc)
* @see org.eclipse.jface.dialogs.TrayDialog#close()
*/
@Override
public boolean close() {
if (form != null && !form.isDisposed()) {
saveSashFormWeights(form);
}
return super.close();
}
/**
* @param form
*/
private void saveSashFormWeights(SashForm form) {
IDialogSettings settings = getDialogBoundsSettings();
if (settings == null)
return;
int[] weights = form.getWeights();
if (weights == null || weights.length != 2)
return;
settings.put(KEY_SASH_WEIGHTS, String.format("%d,%d", weights[0], //$NON-NLS-1$
weights[1]));
}
private int[] loadSashFormWeights() {
IDialogSettings settings = getDialogBoundsSettings();
if (settings == null)
return null;
String value = settings.get(KEY_SASH_WEIGHTS);
if (value == null)
return null;
int index = value.indexOf(',');
if (index < 0)
return null;
int w1, w2;
try {
w1 = Integer.parseInt(value.substring(0, index));
w2 = Integer.parseInt(value.substring(index + 1));
} catch (NumberFormatException e) {
return null;
}
return new int[] { w1, w2 };
}
public void updateButtons() {
Button okButton = getButton(IDialogConstants.OK_ID);
if (okButton != null && !okButton.isDisposed()) {
okButton.setEnabled(isOkButtonEnabled());
}
}
private boolean isOkButtonEnabled() {
if (currentPage == null)
return false;
return currentPage.canFinish();
}
public void updateMessage() {
if (currentPage == null) {
return;
}
pageMessage = currentPage.getMessage();
if (pageMessage != null) {
pageMessageType = currentPage.getMessageType();
} else {
pageMessageType = IMessageProvider.NONE;
}
if (pageMessage == null) {
setMessage(pageDescription);
} else {
setMessage(pageMessage, pageMessageType);
}
setErrorMessage(currentPage.getErrorMessage());
}
protected void buttonPressed(int buttonId) {
if (buttonId == REMOVE_ID) {
removePressed();
} else {
super.buttonPressed(buttonId);
}
}
protected void removePressed() {
setReturnCode(REMOVE);
close();
}
protected void okPressed() {
getShell().setVisible(false);
if (currentPage != null) {
if (currentPage.tryFinish()) {
this.value = currentPage.getValue();
super.okPressed();
} else {
getShell().setVisible(true);
}
}
}
protected void cancelPressed() {
super.cancelPressed();
}
public String getValue() {
return value;
}
}