/* ******************************************************************************
* 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.wizards;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.jface.viewers.IOpenListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DragSourceAdapter;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetAdapter;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.FileTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
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.Event;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.TabFolder;
import org.eclipse.swt.widgets.TabItem;
import org.xmind.core.style.IStyle;
import org.xmind.core.style.IStyleSheet;
import org.xmind.gef.EditDomain;
import org.xmind.gef.GEF;
import org.xmind.gef.IViewer;
import org.xmind.gef.util.Properties;
import org.xmind.ui.gallery.GalleryLayout;
import org.xmind.ui.gallery.GalleryNavigablePolicy;
import org.xmind.ui.gallery.GallerySelectTool;
import org.xmind.ui.gallery.GalleryViewer;
import org.xmind.ui.internal.ITemplateDescriptor;
import org.xmind.ui.internal.MindMapTemplateManager;
import org.xmind.ui.internal.dialogs.DialogMessages;
import org.xmind.ui.internal.views.ThemesViewer;
import org.xmind.ui.mindmap.IResourceManager;
import org.xmind.ui.mindmap.MindMapUI;
public class ChooseTemplateWizardPage extends WizardPage implements
ISelectionChangedListener, IOpenListener, SelectionListener {
public static final String PAGE_NAME = "org.xmind.ui.wizard.newWorkbookWizard..chooseTemplatePage"; //$NON-NLS-1$
private static final String SELECTED_TEMPLATE = "selectedTemplate"; //$NON-NLS-1$
private static final int FRAME_WIDTH = 130;
private static final int FRAME_HEIGHT = 90;
private static class TemplateThemesViewer extends ThemesViewer {
public TemplateThemesViewer(Composite parent) {
super(parent);
}
@Override
protected void init() {
super.init();
EditDomain editDomain = getEditDomain();
editDomain.installTool(GEF.TOOL_SELECT, new GallerySelectTool());
editDomain.installEditPolicy(GalleryViewer.POLICY_NAVIGABLE,
new GalleryNavigablePolicy());
editDomain.uninstallEditPolicy(GEF.TOOL_EDIT);
Properties properties = getProperties();
properties.set(GalleryViewer.TitlePlacement,
GalleryViewer.TITLE_BOTTOM);
properties.set(GalleryViewer.FlatFrames, true);
properties.set(GalleryViewer.Layout, new GalleryLayout(
GalleryLayout.ALIGN_TOPLEFT, GalleryLayout.ALIGN_TOPLEFT,
10, 10, 10, 10, 10, 10));
}
@Override
public Control createControl(Composite parent, int style) {
return super.createControl(parent, style | SWT.BORDER);
}
}
private ITemplateDescriptor selectedTemplate;
private IViewer templatesViewer;
private IViewer themesViewer;
private TabItem templatesItem;
private TabItem themesItem;
private Button deleteTemplateButton;
protected ChooseTemplateWizardPage() {
super(PAGE_NAME, WizardMessages.ChooseTemplateWizardPage_title, null);
setDescription(WizardMessages.ChooseTemplateWizardPage_description);
}
public void createControl(Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
GridLayout gridLayout = new GridLayout(1, false);
gridLayout.marginWidth = 5;
gridLayout.marginHeight = 5;
gridLayout.verticalSpacing = 5;
gridLayout.horizontalSpacing = 5;
composite.setLayout(gridLayout);
setControl(composite);
createTabFolder(composite);
createExtraButtonBar(composite);
composite.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
saveSettings();
}
});
}
private void createExtraButtonBar(Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
GridLayout gridLayout = new GridLayout(5, false);
gridLayout.marginWidth = 0;
gridLayout.marginHeight = 5;
gridLayout.verticalSpacing = 5;
gridLayout.horizontalSpacing = 5;
composite.setLayout(gridLayout);
createAddCustomTemplateButton(composite);
createDeleteCustomTemplateButton(composite);
}
private void createAddCustomTemplateButton(Composite parent) {
Button button = new Button(parent, SWT.PUSH);
button.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
button.setText(WizardMessages.ChooseTemplateWizardPage_AddTemplate_text);
button.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
FileDialog dialog = new FileDialog(getShell(), SWT.OPEN);
String ext = "*" + MindMapUI.FILE_EXT_TEMPLATE; //$NON-NLS-1$
dialog.setFilterExtensions(new String[] { ext });
dialog.setFilterNames(new String[] { NLS.bind("{0} ({1})", //$NON-NLS-1$
DialogMessages.TemplateFilterName, ext) });
String path = dialog.open();
if (path == null)
return;
ITemplateDescriptor template = MindMapTemplateManager
.getInstance().importCustomTemplate(path);
if (template != null) {
selectViewer(templatesItem);
templatesViewer.setInput(loadTemplatesViewerInput());
templatesViewer.setSelection(new StructuredSelection(
template), true);
}
}
});
}
private void createDeleteCustomTemplateButton(Composite parent) {
Button button = new Button(parent, SWT.PUSH);
button.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
button.setText(WizardMessages.ChooseTemplateWizardPage_DeleteTemplate_text);
button.addListener(SWT.Selection, new Listener() {
public void handleEvent(Event event) {
ITemplateDescriptor template = selectedTemplate;
if (template != null
&& template instanceof FileTemplateDescriptor) {
File file = ((FileTemplateDescriptor) template).getFile();
file.delete();
templatesViewer.setInput(loadTemplatesViewerInput());
}
}
});
deleteTemplateButton = button;
}
private void createTabFolder(Composite parent) {
TabFolder folder = new TabFolder(parent, SWT.TOP);
folder.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
((GridData) folder.getLayoutData()).widthHint = 650;
((GridData) folder.getLayoutData()).heightHint = 320;
templatesItem = new TabItem(folder, SWT.NONE);
templatesItem
.setText(WizardMessages.ChooseTemplateWizardPage_TemplatesGroup_text);
Control templatesContainer = createTemplatesContainer(folder);
templatesItem.setControl(templatesContainer);
themesItem = new TabItem(folder, SWT.NONE);
themesItem
.setText(WizardMessages.ChooseTemplateWizardPage_ThemesGroup_text);
Control themesContainer = createThemesContainer(folder);
themesItem.setControl(themesContainer);
loadSelectedTemplate();
folder.addSelectionListener(this);
}
private Control createTemplatesContainer(Composite parent) {
GalleryViewer viewer = new GalleryViewer();
EditDomain editDomain = new EditDomain();
editDomain.installTool(GEF.TOOL_SELECT, new GallerySelectTool());
editDomain.installEditPolicy(GalleryViewer.POLICY_NAVIGABLE,
new GalleryNavigablePolicy());
viewer.setEditDomain(editDomain);
Properties properties = viewer.getProperties();
properties.set(GalleryViewer.Wrap, true);
properties.set(GalleryViewer.FlatFrames, true);
properties.set(GalleryViewer.Horizontal, true);
properties
.set(GalleryViewer.TitlePlacement, GalleryViewer.TITLE_BOTTOM);
properties.set(GalleryViewer.SolidFrames, true);
properties.set(GalleryViewer.FrameContentSize, new Dimension(
FRAME_WIDTH, FRAME_HEIGHT));
properties.set(GalleryViewer.ImageConstrained, true);
properties.set(GalleryViewer.Layout, new GalleryLayout(
GalleryLayout.ALIGN_TOPLEFT, GalleryLayout.ALIGN_TOPLEFT, 10,
10, 10, 10, 10, 10));
Control control = viewer.createControl(parent, SWT.BORDER);
createTemplateDndSupport(control, viewer);
viewer.setLabelProvider(new TemplateLabelProvider());
List<ITemplateDescriptor> templates = loadTemplatesViewerInput();
viewer.setInput(templates);
if (templates.size() > 0) {
viewer.setSelection(new StructuredSelection(templates.get(0)), true);
}
viewer.addSelectionChangedListener(this);
viewer.addOpenListener(this);
templatesViewer = viewer;
return control;
}
private void createTemplateDndSupport(Control control,
final ISelectionProvider viewer) {
final boolean[] dragging = new boolean[1];
dragging[0] = false;
DropTarget target = new DropTarget(control, DND.DROP_DEFAULT
| DND.DROP_COPY | DND.DROP_LINK);
target.setTransfer(new Transfer[] { FileTransfer.getInstance() });
target.addDropListener(new DropTargetAdapter() {
public void dragEnter(DropTargetEvent event) {
if (dragging[0]) {
event.detail = DND.DROP_NONE;
} else {
event.detail = DND.DROP_COPY;
}
}
public void dragOperationChanged(DropTargetEvent event) {
if (dragging[0]) {
event.detail = DND.DROP_NONE;
} else {
event.detail = DND.DROP_COPY;
}
}
public void drop(DropTargetEvent event) {
if (dragging[0] || event.data == null) {
event.detail = DND.DROP_NONE;
} else {
importTemplates((String[]) event.data);
}
}
});
DragSource source = new DragSource(control, DND.DROP_COPY);
source.setTransfer(new Transfer[] { FileTransfer.getInstance() });
source.addDragListener(new DragSourceAdapter() {
List<String> fileNames = new ArrayList<String>();
public void dragStart(DragSourceEvent event) {
dragging[0] = true;
fileNames.clear();
IStructuredSelection selection = (IStructuredSelection) viewer
.getSelection();
for (Object element : selection.toList()) {
if (element instanceof FileTemplateDescriptor) {
fileNames.add(((FileTemplateDescriptor) element)
.getFile().getAbsolutePath());
}
}
event.doit = !fileNames.isEmpty();
}
public void dragSetData(DragSourceEvent event) {
event.data = fileNames.toArray(new String[fileNames.size()]);
}
public void dragFinished(DragSourceEvent event) {
fileNames.clear();
dragging[0] = false;
}
});
}
private void importTemplates(String[] fileNames) {
List<ITemplateDescriptor> importedTemplates = MindMapTemplateManager
.getInstance().importTemplates(fileNames);
if (!importedTemplates.isEmpty()) {
selectViewer(templatesItem);
templatesViewer.setInput(loadTemplatesViewerInput());
templatesViewer.setSelection(new StructuredSelection(
importedTemplates), true);
}
}
private Control createThemesContainer(Composite parent) {
TemplateThemesViewer viewer = new TemplateThemesViewer(parent);
IStyle theme = MindMapUI.getResourceManager().getDefaultTheme();
if (theme != null)
viewer.setDefaultTheme(theme);
List<IStyle> themes = loadThemesViewerInput();
viewer.setInput(themes);
if (themes.size() > 0) {
viewer.setSelection(new StructuredSelection(themes.get(0)), true);
}
viewer.addSelectionChangedListener(this);
viewer.addOpenListener(this);
themesViewer = viewer;
return viewer.getControl();
}
private void updateButtons() {
setPageComplete(selectedTemplate != null);
if (deleteTemplateButton != null) {
deleteTemplateButton.setEnabled(selectedTemplate != null
&& selectedTemplate instanceof FileTemplateDescriptor);
}
}
private void setSelectedTemplate(ITemplateDescriptor template) {
this.selectedTemplate = template;
updateButtons();
}
public ITemplateDescriptor getTemplate() {
return selectedTemplate;
}
private List<ITemplateDescriptor> loadTemplatesViewerInput() {
return MindMapTemplateManager.getInstance().loadAllTemplates();
}
private List<IStyle> loadThemesViewerInput() {
IResourceManager resourceManager = MindMapUI.getResourceManager();
IStyleSheet systemThemeSheets = resourceManager.getSystemThemeSheet();
Set<IStyle> systemThemes = systemThemeSheets
.getStyles(IStyleSheet.MASTER_STYLES);
IStyleSheet userThemeSheets = resourceManager.getUserThemeSheet();
Set<IStyle> userThemes = userThemeSheets
.getStyles(IStyleSheet.MASTER_STYLES);
List<IStyle> list = new ArrayList<IStyle>(systemThemes.size()
+ userThemes.size() + 1);
list.add(resourceManager.getBlankTheme());
list.addAll(systemThemes);
list.addAll(userThemes);
return list;
}
public void selectionChanged(SelectionChangedEvent event) {
ITemplateDescriptor template = findTemplate(event.getSelection());
setSelectedTemplate(template);
}
public void open(OpenEvent event) {
ITemplateDescriptor template = findTemplate(event.getSelection());
if (template != null) {
applyTemplate(template);
}
}
private ITemplateDescriptor findTemplate(ISelection selection) {
if (selection instanceof IStructuredSelection) {
Object element = ((IStructuredSelection) selection)
.getFirstElement();
if (element instanceof ITemplateDescriptor) {
return (ITemplateDescriptor) element;
} else if (element instanceof IStyle) {
return new ThemeTemplateDescriptor((IStyle) element);
}
}
return null;
}
private void applyTemplate(ITemplateDescriptor template) {
setSelectedTemplate(template);
if (getWizard().canFinish()) {
if (getWizard().performFinish()) {
getContainer().getShell().dispose();
}
} else if (canFlipToNextPage()) {
getContainer().showPage(getNextPage());
}
}
public void widgetSelected(SelectionEvent e) {
TabItem item = (TabItem) e.item;
selectViewer(item);
}
public void widgetDefaultSelected(SelectionEvent e) {
}
private void selectViewer(TabItem item) {
if (item == templatesItem) {
setSelectedTemplate(findTemplate(templatesViewer.getSelection()));
} else if (item == themesItem) {
setSelectedTemplate(findTemplate(themesViewer.getSelection()));
}
item.getParent().setSelection(item);
item.getControl().setFocus();
}
public void setVisible(boolean visible) {
super.setVisible(visible);
setPageComplete(isPageComplete());
}
private void saveSettings() {
getDialogSettings().put(SELECTED_TEMPLATE,
getTemplateSymbolicName(this.selectedTemplate));
}
private String getTemplateSymbolicName(ITemplateDescriptor template) {
if (template instanceof URLTemplateDescriptor) {
return ((URLTemplateDescriptor) template).getURL().toExternalForm();
} else if (template instanceof FileTemplateDescriptor) {
return "file:" + ((FileTemplateDescriptor) template).getFile().getAbsolutePath(); //$NON-NLS-1$
} else if (template instanceof ThemeTemplateDescriptor) {
IStyle theme = ((ThemeTemplateDescriptor) template).getTheme();
if (theme == MindMapUI.getResourceManager().getBlankTheme()) {
return "theme:blank"; //$NON-NLS-1$
} else {
return "theme:" + theme.getId(); //$NON-NLS-1$
}
} else if (template instanceof DefaultTemplateDescriptor) {
return "default:" + ((DefaultTemplateDescriptor) template).getId(); //$NON-NLS-1$
}
return ""; //$NON-NLS-1$
}
private void loadSelectedTemplate() {
String uri = getDialogSettings().get(SELECTED_TEMPLATE);
if (uri != null && !"".equals(uri)) { //$NON-NLS-1$
if (uri.startsWith("theme:")) { //$NON-NLS-1$
IStyle theme = findTheme(uri);
if (theme != null) {
selectTheme(theme);
}
} else if (uri.startsWith("file:")) { //$NON-NLS-1$
String path = uri.substring(5);
File file = new File(path);
if (file.isFile() && file.canRead()) {
ITemplateDescriptor template = new FileTemplateDescriptor(
file);
selectTemplate(template);
} else {
loadSelectedTemplateFromURL(uri);
}
} else if (uri.startsWith("default:")) { //$NON-NLS-1$
String id = uri.substring(8);
selectTemplate(new DefaultTemplateDescriptor(id, "")); //$NON-NLS-1$
} else {
loadSelectedTemplateFromURL(uri);
}
}
}
private void loadSelectedTemplateFromURL(String uri) {
try {
URL url = new URL(uri);
ITemplateDescriptor template = new URLTemplateDescriptor(url, ""); //$NON-NLS-1$
selectTemplate(template);
} catch (MalformedURLException e) {
}
}
private void selectTheme(IStyle theme) {
selectViewer(themesItem);
themesViewer.setSelection(new StructuredSelection(theme), true);
}
private void selectTemplate(ITemplateDescriptor template) {
selectViewer(templatesItem);
templatesViewer.setSelection(new StructuredSelection(template), true);
}
private IStyle findTheme(String uri) {
String styleId = uri.substring(6);
IResourceManager resourceManager = MindMapUI.getResourceManager();
if ("blank".equals(styleId)) { //$NON-NLS-1$
return resourceManager.getBlankTheme();
}
IStyleSheet systemThemeSheet = resourceManager.getSystemThemeSheet();
IStyle style = systemThemeSheet.findStyle(styleId);
if (style != null)
return style;
IStyleSheet userThemeSheet = resourceManager.getUserThemeSheet();
return userThemeSheet.findStyle(styleId);
}
}