package org.xmind.ui.internal.popover;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Insets;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.jface.viewers.IOpenListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
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.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ui.forms.events.HyperlinkAdapter;
import org.eclipse.ui.forms.events.HyperlinkEvent;
import org.eclipse.ui.forms.widgets.Hyperlink;
import org.eclipse.ui.handlers.IHandlerService;
import org.osgi.framework.Bundle;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xmind.core.IBoundary;
import org.xmind.core.IRelationship;
import org.xmind.core.ISheet;
import org.xmind.core.ISummary;
import org.xmind.core.ITopic;
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.IGraphicalViewer;
import org.xmind.gef.Request;
import org.xmind.gef.ui.editor.IGraphicalEditor;
import org.xmind.gef.ui.editor.IGraphicalEditorPage;
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.MindMapUIPlugin;
import org.xmind.ui.internal.e4models.IModelConstants;
import org.xmind.ui.internal.utils.E4Utils;
import org.xmind.ui.internal.views.Messages;
import org.xmind.ui.internal.views.ThemeLabelProvider;
import org.xmind.ui.mindmap.IResourceManager;
import org.xmind.ui.mindmap.ISheetPart;
import org.xmind.ui.mindmap.MindMapUI;
import org.xmind.ui.prefs.PrefConstants;
import org.xmind.ui.resources.ColorUtils;
import org.xmind.ui.util.MindMapUtils;
import org.xml.sax.SAXException;
public class ThemePopoverMenuToolItem extends PopoverMenuToolItem {
private static final String THEME_POPOVER_XML = "styles/themePopover.xml"; //$NON-NLS-1$
private static final String TAG_THEME = "theme"; //$NON-NLS-1$
private static final String ATTR_ID = "id"; //$NON-NLS-1$
private static final String Extract_Theme_Command_ID = "org.xmind.ui.command.extractTheme"; //$NON-NLS-1$
private class ChangeThemeListener implements IOpenListener {
private class ThemeOverrideDialog extends Dialog {
private Button rememberCheck;
protected ThemeOverrideDialog(Shell parentShell) {
super(parentShell);
}
@Override
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setText(Messages.ThemesView_Dialog_title);
}
@Override
protected Control createDialogArea(Composite parent) {
Composite composite = (Composite) super.createDialogArea(
parent);
Label label = new Label(composite, SWT.NONE);
label.setText(Messages.ThemesView_Dialog_message);
createRememberCheck(composite);
return composite;
}
private void createRememberCheck(Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
GridLayout gridLayout = new GridLayout(1, false);
gridLayout.marginTop = 25;
composite.setLayout(gridLayout);
composite.setLayoutData(new GridData(GridData.FILL_BOTH));
rememberCheck = new Button(composite, SWT.CHECK);
rememberCheck.setText(Messages.ThemesView_Dialog_Check);
rememberCheck.setLayoutData(
new GridData(SWT.FILL, SWT.BOTTOM, true, true));
}
protected Control createButtonBar(Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
composite.setLayoutData(
new GridData(SWT.FILL, SWT.FILL, true, false));
GridLayout gridLayout = new GridLayout(2, false);
gridLayout.marginWidth = convertHorizontalDLUsToPixels(
IDialogConstants.HORIZONTAL_MARGIN);
gridLayout.marginHeight = convertVerticalDLUsToPixels(
IDialogConstants.VERTICAL_MARGIN);
gridLayout.marginBottom = convertVerticalDLUsToPixels(
IDialogConstants.VERTICAL_MARGIN);
gridLayout.verticalSpacing = convertVerticalDLUsToPixels(
IDialogConstants.VERTICAL_SPACING);
gridLayout.horizontalSpacing = convertHorizontalDLUsToPixels(
IDialogConstants.HORIZONTAL_SPACING);
composite.setLayout(gridLayout);
createPrefLink(composite);
Composite buttonBar = new Composite(composite, SWT.NONE);
GridLayout layout = new GridLayout();
layout.numColumns = 0; // this is incremented by createButton
layout.makeColumnsEqualWidth = false;
layout.marginWidth = 0;
layout.marginHeight = 0;
layout.horizontalSpacing = convertHorizontalDLUsToPixels(
IDialogConstants.HORIZONTAL_SPACING);
layout.verticalSpacing = convertVerticalDLUsToPixels(
IDialogConstants.VERTICAL_SPACING);
buttonBar.setLayout(layout);
buttonBar.setLayoutData(
new GridData(SWT.END, SWT.CENTER, true, true));
buttonBar.setFont(parent.getFont());
createButtonsForButtonBar(buttonBar);
return buttonBar;
}
private void createPrefLink(Composite parent) {
Hyperlink prefLink = new Hyperlink(parent, SWT.SINGLE);
prefLink.setText(Messages.ThemesView_Dialog_PrefLink);
prefLink.setUnderlined(true);
prefLink.setForeground(
parent.getDisplay().getSystemColor(SWT.COLOR_BLUE));
prefLink.addHyperlinkListener(new HyperlinkAdapter() {
@Override
public void linkActivated(HyperlinkEvent e) {
PreferencesUtil.createPreferenceDialogOn(null,
"org.xmind.ui.ThemePrefPage", null, null) //$NON-NLS-1$
.open();
}
});
}
@Override
protected void createButtonsForButtonBar(Composite parent) {
createButton(parent, IDialogConstants.OK_ID,
Messages.ThemesView_OverrideButton, true);
createButton(parent, IDialogConstants.NO_ID,
Messages.ThemesView_KeepButton, false);
}
@Override
protected void buttonPressed(int buttonId) {
super.buttonPressed(buttonId);
if (IDialogConstants.NO_ID == buttonId)
noPressed();
}
@Override
protected void okPressed() {
if (rememberCheck.getSelection())
pref.setValue(PrefConstants.THEME_APPLY,
PrefConstants.THEME_OVERRIDE);
else
pref.setValue(PrefConstants.THEME_APPLY,
PrefConstants.ASK_USER);
super.okPressed();
}
private void noPressed() {
if (rememberCheck.getSelection())
pref.setValue(PrefConstants.THEME_APPLY,
PrefConstants.THEME_KEEP);
else
pref.setValue(PrefConstants.THEME_APPLY,
PrefConstants.ASK_USER);
setReturnCode(IDialogConstants.NO_ID);
close();
}
}
private IPreferenceStore pref = MindMapUIPlugin.getDefault()
.getPreferenceStore();
public void open(OpenEvent event) {
if (updatingSelection)
return;
String themeApply = pref.getString(PrefConstants.THEME_APPLY);
if (isThemeModified() && (PrefConstants.ASK_USER.equals(themeApply)
|| IPreferenceStore.STRING_DEFAULT_DEFAULT
.equals(themeApply))) {
int code = openCoverDialog();
if (IDialogConstants.CANCEL_ID == code)
return;
if (IDialogConstants.OK_ID == code)
themeApply = PrefConstants.THEME_OVERRIDE;
else if (IDialogConstants.NO_ID == code)
themeApply = PrefConstants.THEME_KEEP;
}
Object o = ((IStructuredSelection) event.getSelection())
.getFirstElement();
if (o != null && o instanceof IStyle) {
changeTheme((IStyle) o, themeApply);
}
}
private int openCoverDialog() {
Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow()
.getShell();
if (shell != null)
return new ThemeOverrideDialog(shell).open();
return IDialogConstants.NO_ID;
}
private boolean isThemeModified() {
ISheet sheet = getCurrentSheet();
if (sheet == null)
return false;
if (sheet.getStyleId() != null)
return true;
List<ITopic> topics = MindMapUtils.getAllTopics(sheet, true, true);
for (ITopic topic : topics) {
if (topic.getStyleId() != null)
return true;
Set<IBoundary> boundaries = topic.getBoundaries();
for (IBoundary boundary : boundaries) {
if (boundary.getStyleId() != null)
return true;
}
Set<ISummary> summaries = topic.getSummaries();
for (ISummary summary : summaries) {
if (summary.getStyleId() != null)
return true;
}
}
Set<IRelationship> relationships = sheet.getRelationships();
for (IRelationship relationship : relationships) {
if (relationship.getStyleId() != null)
return true;
}
return false;
}
private ISheet getCurrentSheet() {
IEditorPart activeEditor = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow().getActivePage()
.getActiveEditor();
if (activeEditor instanceof IGraphicalEditor) {
IGraphicalEditor editor = (IGraphicalEditor) activeEditor;
if (editor.getActivePageInstance() != null) {
ISheet sheet = (ISheet) editor.getActivePageInstance()
.getAdapter(ISheet.class);
return sheet;
}
}
return null;
}
}
private GalleryViewer viewer;
private IGraphicalEditor activeEditor;
private boolean updatingSelection = false;
@Override
protected Control createContents(Composite parent) {
Composite composite = (Composite) super.createContents(parent);
Composite composite2 = new Composite(composite, SWT.NONE);
composite2.setBackground(composite2.getParent().getBackground());
GridData gridData = new GridData(GridData.FILL_BOTH);
composite2.setLayoutData(gridData);
GridLayout layout = new GridLayout();
layout.marginWidth = 0;
layout.marginHeight = 0;
layout.verticalSpacing = 2;
composite2.setLayout(layout);
createThemesContainer(composite2);
createSeperator(composite2);
createHyperlinks(composite2);
return composite;
}
private void createThemesContainer(Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
composite.setBackground(composite.getParent().getBackground());
GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false);
composite.setLayoutData(gridData);
GridLayout layout = new GridLayout();
layout.marginWidth = 0;
layout.marginHeight = 5;
layout.marginTop = 5;
composite.setLayout(layout);
createThemesViewer(composite);
IEditorPart editor = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow().getActivePage().getActiveEditor();
if (editor instanceof IGraphicalEditor) {
setActiveEditor((IGraphicalEditor) editor);
}
}
private void createThemesViewer(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.Horizontal, Boolean.TRUE);
properties.set(GalleryViewer.Wrap, Boolean.TRUE);
properties.set(GalleryViewer.FlatFrames, true);
properties.set(GalleryViewer.SolidFrames, true);
properties.set(GalleryViewer.HideTitle, false);
properties.set(GalleryViewer.TitlePlacement,
GalleryViewer.TITLE_BOTTOM);
properties.set(GalleryViewer.ImageConstrained, true);
properties.set(GalleryViewer.SingleClickToOpen, Boolean.FALSE);
properties.set(GalleryViewer.CustomContentPaneDecorator, true);
properties.set(GalleryViewer.FrameContentSize, new Dimension(94, 48));
properties.set(GalleryViewer.Layout,
new GalleryLayout(GalleryLayout.ALIGN_CENTER,
GalleryLayout.ALIGN_CENTER, 2, 2,
new Insets(0, 0, 0, 0)));
Control control = viewer.createControl(parent);
GridData gridData = new GridData(GridData.FILL_BOTH);
gridData.widthHint = 340;
control.setLayoutData(gridData);
viewer.setLabelProvider(new ThemeLabelProvider());
viewer.addOpenListener(new ChangeThemeListener());
viewer.setInput(getViewerInput());
}
private void createSeperator(Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
composite.setBackground(composite.getParent().getBackground());
GridData gridData = new GridData(GridData.FILL, GridData.CENTER, true,
false);
composite.setLayoutData(gridData);
GridLayout layout = new GridLayout(1, false);
layout.marginWidth = 15;
layout.marginHeight = 0;
composite.setLayout(layout);
Composite seperator = new Composite(composite, SWT.NONE);
seperator.setBackground(
new LocalResourceManager(JFaceResources.getResources(),
composite).createColor(ColorUtils.toRGB("#cbcbcb"))); //$NON-NLS-1$
GridData gridData2 = new GridData(SWT.FILL, SWT.CENTER, true, false);
gridData2.heightHint = 1;
seperator.setLayoutData(gridData2);
seperator.setLayout(new GridLayout());
}
private void createHyperlinks(Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
composite.setBackground(composite.getParent().getBackground());
GridData gridData = new GridData(SWT.FILL, SWT.CENTER, true, false);
composite.setLayoutData(gridData);
GridLayout layout = new GridLayout();
layout.marginWidth = 15;
layout.marginHeight = 5;
layout.marginBottom = 5;
layout.verticalSpacing = 4;
composite.setLayout(layout);
createMoreThemesHyperlink(composite);
createManageThemesHyperlink(composite);
createExtractThemeHyperlink(composite);
}
private void createMoreThemesHyperlink(Composite parent) {
Hyperlink moreThemesHyperlink = createHyperlink(parent,
Messages.ThemesPopover_MoreTheme_label);
moreThemesHyperlink.addHyperlinkListener(new HyperlinkAdapter() {
@Override
public void linkActivated(HyperlinkEvent e) {
E4Utils.showPart(IModelConstants.COMMAND_SHOW_MODEL_PART,
PlatformUI.getWorkbench().getActiveWorkbenchWindow(),
IModelConstants.PART_ID_THEMES, null,
IModelConstants.PART_STACK_ID_RIGHT);
}
});
}
private void createManageThemesHyperlink(Composite parent) {
Hyperlink manageThemesHyperlink = createHyperlink(parent,
Messages.ThemesPopover_ManagerTheme_label);
manageThemesHyperlink.addHyperlinkListener(new HyperlinkAdapter() {
@Override
public void linkActivated(HyperlinkEvent e) {
E4Utils.showPart(IModelConstants.COMMAND_SHOW_DIALOG_PART,
PlatformUI.getWorkbench().getActiveWorkbenchWindow(),
IModelConstants.PART_ID_RESOURCE_MANAGER,
IModelConstants.PAGE_ID_RESOURCE_MANAGER_THEME, null);
}
});
}
private void createExtractThemeHyperlink(Composite parent) {
Hyperlink extractThemeHyperlink = createHyperlink(parent,
Messages.ThemesPopover_Extract_Current_Theme_label);
extractThemeHyperlink.addHyperlinkListener(new HyperlinkAdapter() {
@Override
public void linkActivated(HyperlinkEvent e) {
IWorkbenchPage page = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow().getActivePage();
if (page == null) {
return;
}
IEditorPart editor = page.getActiveEditor();
if (editor == null) {
return;
}
final IHandlerService handlerService = (IHandlerService) editor
.getSite().getService(IHandlerService.class);
if (handlerService == null) {
return;
}
SafeRunner.run(new SafeRunnable() {
public void run() throws Exception {
handlerService.executeCommand(Extract_Theme_Command_ID,
null);
}
});
}
});
}
private Hyperlink createHyperlink(Composite parent, String message) {
Hyperlink hyperlink = new Hyperlink(parent, SWT.SINGLE);
hyperlink.setBackground(hyperlink.getParent().getBackground());
GridData gridData = new GridData(SWT.LEFT, SWT.CENTER, false, false);
hyperlink.setLayoutData(gridData);
hyperlink.setUnderlined(false);
hyperlink.setText(message);
return hyperlink;
}
private List<IStyle> getViewerInput() {
List<IStyle> list = new ArrayList<IStyle>();
DocumentBuilder documentBuilder = null;
try {
documentBuilder = DocumentBuilderFactory.newInstance()
.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
try {
Bundle bundle = Platform.getBundle(MindMapUI.PLUGIN_ID);
URL url = FileLocator.find(bundle, new Path(THEME_POPOVER_XML),
null);
Document doc = documentBuilder.parse(url.openStream());
IResourceManager rm = MindMapUI.getResourceManager();
Set<IStyle> systemThemeSets = rm.getSystemThemeSheet()
.getStyles(IStyleSheet.MASTER_STYLES);
NodeList nodeList = doc.getElementsByTagName(TAG_THEME);
for (int i = 0; i < nodeList.getLength(); i++) {
Element ele = (Element) nodeList.item(i);
String themeId = ele.getAttribute(ATTR_ID);
Iterator<IStyle> iterSystemTheme = systemThemeSets.iterator();
while (iterSystemTheme.hasNext()) {
IStyle themeStyle = iterSystemTheme.next();
if (themeId.equals(themeStyle.getId())) {
list.add(themeStyle);
break;
}
}
}
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return list;
}
private void setActiveEditor(IGraphicalEditor editor) {
if (editor != activeEditor) {
activeEditor = editor;
updateSelection();
}
}
private void updateSelection() {
if (viewer == null || viewer.getControl().isDisposed())
return;
String themeId = getCurrentThemeId();
IStyle theme = MindMapUI.getResourceManager().getBlankTheme();
if (themeId != null && !theme.getId().equals(themeId)) {
theme = MindMapUI.getResourceManager().getSystemThemeSheet()
.findStyle(themeId);
if (theme == null)
theme = MindMapUI.getResourceManager().getUserThemeSheet()
.findStyle(themeId);
}
updatingSelection = true;
viewer.setSelection(theme == null ? StructuredSelection.EMPTY
: new StructuredSelection(theme));
updatingSelection = false;
}
private void changeTheme(IStyle theme, String apply) {
if (activeEditor == null)
return;
IGraphicalEditorPage page = activeEditor.getActivePageInstance();
if (page == null)
return;
IGraphicalViewer viewer = page.getViewer();
if (viewer == null)
return;
ISheetPart sheetPart = (ISheetPart) viewer.getAdapter(ISheetPart.class);
if (sheetPart == null)
return;
EditDomain domain = page.getEditDomain();
if (domain == null)
return;
domain.handleRequest(new Request(MindMapUI.REQ_MODIFY_THEME)
.setViewer(viewer).setPrimaryTarget(sheetPart)
.setParameter(MindMapUI.PARAM_RESOURCE, theme)
.setParameter(MindMapUI.PARAM_OVERRIDE, apply));
updateSelection();
Control control = viewer.getControl();
if (control != null && !control.isDisposed()) {
control.forceFocus();
}
}
private String getCurrentThemeId() {
if (activeEditor == null)
return null;
IGraphicalEditorPage page = activeEditor.getActivePageInstance();
if (page == null)
return null;
ISheet sheet = (ISheet) page.getAdapter(ISheet.class);
if (sheet == null)
return null;
return sheet.getThemeId();
}
}