package org.xmind.ui.internal.popover;
import static org.xmind.ui.mindmap.MindMapUI.REQ_ADD_MARKER;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.SafeRunner;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.jface.util.SafeRunnable;
import org.eclipse.swt.SWT;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DragSourceListener;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseTrackAdapter;
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.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.forms.IFormColors;
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.forms.widgets.ScrolledForm;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.handlers.IHandlerService;
import org.xmind.core.event.ICoreEventSource;
import org.xmind.core.internal.MarkerGroup;
import org.xmind.core.marker.IMarker;
import org.xmind.core.marker.IMarkerGroup;
import org.xmind.core.marker.IMarkerSheet;
import org.xmind.gef.EditDomain;
import org.xmind.gef.Request;
import org.xmind.gef.ui.editor.IGraphicalEditor;
import org.xmind.gef.ui.editor.IGraphicalEditorPage;
import org.xmind.ui.forms.WidgetFactory;
import org.xmind.ui.internal.MindMapMessages;
import org.xmind.ui.internal.MindMapUIPlugin;
import org.xmind.ui.internal.dnd.MindMapElementTransfer;
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.mindmap.MindMapUI;
import org.xmind.ui.resources.ColorUtils;
import org.xmind.ui.util.MarkerImageDescriptor;
public class MarkerPopoverMenuToolItem extends PopoverMenuToolItem {
private static class MarkerSheetPart {
private List<IMarkerSheet> sheets;
private Composite composite;
private ArrayList<MarkerGroupPart> groupParts = new ArrayList<MarkerGroupPart>();
private List<Section> groupSections = new ArrayList<Section>();
private Map<IMarkerGroup, MarkerGroupPart> groupToPart = new HashMap<IMarkerGroup, MarkerGroupPart>();
private Map<IMarkerGroup, Section> groupToSection = new HashMap<IMarkerGroup, Section>();
public MarkerSheetPart(List<IMarkerSheet> sheets) {
this.sheets = sheets;
}
public Control createControl(Composite parent) {
if (composite == null) {
composite = createComposite(parent);
refresh(false);
composite.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
dispose();
}
});
}
return composite;
}
private Composite createComposite(Composite parent) {
Composite composite = new Composite(parent, SWT.WRAP);
composite.setBackground(composite.getParent().getBackground());
GridLayout layout = new GridLayout(1, true);
layout.marginHeight = 0;
layout.marginWidth = 0;
layout.verticalSpacing = 3;
composite.setLayout(layout);
return composite;
}
public void refresh(boolean reflow) {
if (composite == null || composite.isDisposed()) {
return;
}
composite.setRedraw(false);
List<IMarkerGroup> newGroups = new ArrayList<IMarkerGroup>();
if (!RecentMarkerGroup.instance.isEmpty())
newGroups.add(RecentMarkerGroup.instance);
for (IMarkerSheet sheet : sheets) {
List<IMarkerGroup> markerGroups = sheet.getMarkerGroups();
for (IMarkerGroup markerGroup : markerGroups)
if (!markerGroup.isEmpty())
newGroups.add(markerGroup);
}
int i;
for (i = 0; i < newGroups.size(); i++) {
IMarkerGroup group = newGroups.get(i);
if (i < groupParts.size()) {
MarkerGroupPart part = groupParts.get(i);
IMarkerGroup g = part.getMarkerGroup();
if (group.equals(g)) {
continue;
}
}
MarkerGroupPart part = groupToPart.get(group);
if (part == null) {
if (!newGroups.get(i).isHidden()) {
part = createChild(group);
addChild(part, i);
}
}
}
Object[] toTrim = groupParts.toArray();
for (; i < toTrim.length; i++) {
removeChild((MarkerGroupPart) toTrim[i]);
}
composite.setRedraw(true);
}
private MarkerGroupPart createChild(IMarkerGroup group) {
MarkerGroupPart part = new MarkerGroupPart(group, false);
groupToPart.put(group, part);
return part;
}
private void addChild(MarkerGroupPart part, int index) {
index = index < groupParts.size() ? index : groupParts.size();
groupParts.add(index, part);
Control c = part.createControl(composite);
groupSections.add(index, part.section);
groupToSection.put(part.group, part.section);
c.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
}
private void removeChild(MarkerGroupPart part) {
groupParts.remove(part);
groupToPart.remove(part.getMarkerGroup());
groupSections.remove(part.section);
groupToSection.remove(part.getMarkerGroup());
part.section.dispose();
part.dispose();
}
public void dispose() {
if (composite != null) {
composite.dispose();
composite = null;
}
for (Object o : groupParts.toArray()) {
MarkerGroupPart groupPart = (MarkerGroupPart) o;
groupToPart.remove(groupPart.getMarkerGroup());
groupToSection.remove(groupPart.getMarkerGroup());
groupPart.dispose();
}
groupParts.clear();
groupSections.clear();
}
}
private static class MarkerGroupPart {
private IMarkerGroup group;
private boolean hasTitle;
private Control control;
private Section section;
private ToolBarManager toolbar;
public MarkerGroupPart(IMarkerGroup group, boolean hasTitle) {
this.group = group;
this.hasTitle = hasTitle;
}
public IMarkerGroup getMarkerGroup() {
return group;
}
public Control createControl(final Composite parent) {
if (control == null) {
WidgetFactory factory = new WidgetFactory(parent.getDisplay());
section = createSection(parent, group.getName(), factory);
if (toolbar == null) {
toolbar = new ToolBarManager(
SWT.RIGHT | SWT.FLAT | SWT.WRAP);
}
Composite c = factory.createComposite(section, SWT.WRAP);
GridLayout layout = new GridLayout(1, true);
layout.marginHeight = 0;
layout.marginWidth = 0;
layout.verticalSpacing = 0;
c.setLayout(layout);
if (hasTitle) {
factory.createLabel(c, group.getName());
}
final ToolBar tb = toolbar.createControl(c);
tb.setBackground(
tb.getDisplay().getSystemColor(SWT.COLOR_WHITE));
GridData data = new GridData(SWT.FILL, SWT.FILL, true, false);
tb.setLayoutData(data);
addDragSource(tb);
control = section;
section.setClient(c);
refresh(false);
control.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
dispose();
}
});
}
return control;
}
private Section createSection(Composite parent, String title,
WidgetFactory factory) {
Section section = factory.createSection(parent, SWT.None);
section.setText(title);
return section;
}
private void addDragSource(final ToolBar toolbar) {
final DragSource dragSource = new DragSource(toolbar,
DND.DROP_COPY);
dragSource.setTransfer(
new Transfer[] { MindMapElementTransfer.getInstance() });
dragSource.addDragListener(new DragSourceListener() {
ToolItem sourceItem;
public void dragStart(DragSourceEvent event) {
sourceItem = toolbar.getItem(new Point(event.x, event.y));
if (sourceItem == null)
event.doit = false;
else {
event.image = sourceItem.getImage();
}
}
public void dragSetData(DragSourceEvent event) {
if (sourceItem == null)
return;
int index = toolbar.indexOf(sourceItem);
IMarker marker = group.getMarkers().get(index);
event.data = new Object[] { marker };
}
public void dragFinished(DragSourceEvent event) {
}
});
toolbar.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
dragSource.dispose();
}
});
}
public void refresh(boolean reflow) {
if (toolbar == null || control == null || control.isDisposed())
return;
section.setText(group.getName());
toolbar.removeAll();
for (int index = 0; index < group.getMarkers().size(); index++) {
IMarker marker = group.getMarkers().get(index);
if (!group.isHidden() && !marker.isHidden()) {
toolbar.add(new MarkerAction(marker));
}
}
toolbar.update(false);
}
public void dispose() {
if (toolbar != null) {
toolbar.dispose();
toolbar = null;
}
if (control != null) {
control.dispose();
control = null;
}
}
}
private static class RecentMarkerGroup extends MarkerGroup {
public static final RecentMarkerGroup instance = new RecentMarkerGroup();
private static final int CAPACITY = 7;
private List<IMarker> markers = new ArrayList<IMarker>(CAPACITY);
private RecentMarkerGroup() {
}
public void addMarker(IMarker marker) {
if (markers.contains(marker))
return;
while (markers.size() >= CAPACITY) {
markers.remove(markers.size() - 1);
}
markers.add(0, marker);
}
public <T> T getAdapter(Class<T> adapter) {
if (adapter == ICoreEventSource.class)
return adapter.cast(this);
return super.getAdapter(adapter);
}
public List<IMarker> getMarkers() {
return markers;
}
/*
* (non-Javadoc)
* @see org.xmind.core.marker.IMarkerGroup#isEmpty()
*/
@Override
public boolean isEmpty() {
return markers.isEmpty();
}
public String getName() {
return MindMapMessages.RecentUsed;
}
public void setSingleton(boolean singleton) {
}
public IMarkerSheet getOwnedSheet() {
return null;
}
public IMarkerSheet getParent() {
return null;
}
public boolean isSingleton() {
return false;
}
public boolean isHidden() {
return false;
}
public void setHidden(boolean hidden) {
}
public void removeMarker(IMarker marker) {
if (!markers.contains(marker))
return;
markers.remove(marker);
}
public void setName(String name) {
}
public String getId() {
return "org.xmind.ui.RecentMarkerGroup"; //$NON-NLS-1$
}
public int hashCode() {
return super.hashCode();
}
}
private static class MarkerAction extends Action {
private static final int ICON_WIDTH = 24;
private static final int ICON_HEIGHT = 24;
private IMarker marker;
public MarkerAction(IMarker marker) {
super();
this.marker = marker;
setImageDescriptor(MarkerImageDescriptor.createFromMarker(marker,
ICON_WIDTH, ICON_HEIGHT, false));
setToolTipText(marker.getName());
}
public void run() {
MindMapUIPlugin.getDefault().getUsageDataCollector()
.increase("InsertMarkerCount"); //$NON-NLS-1$
RecentMarkerGroup.instance.addMarker(marker);
IWorkbenchPage page = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow().getActivePage();
if (page != null) {
IEditorPart editor = page.getActiveEditor();
if (editor != null && editor instanceof IGraphicalEditor) {
IGraphicalEditorPage gp = ((IGraphicalEditor) editor)
.getActivePageInstance();
if (gp != null) {
EditDomain domain = gp.getEditDomain();
if (domain != null) {
Request req = new Request(REQ_ADD_MARKER)
.setViewer(gp.getViewer()).setDomain(domain)
.setParameter(MindMapUI.PARAM_MARKER_ID,
marker.getId());
domain.handleRequest(req);
}
// IViewer viewer = gp.getViewer();
// if (viewer != null) {
// Control control = viewer.getControl();
// if (control != null && !control.isDisposed()) {
// control.setFocus();
// }
// }
}
}
}
}
}
private static final int POPOVER_WIDTH = 255;
private static final int POPOVER_HEIGHT = 380;
@Override
protected Control createContents(Composite parent) {
Composite composite = (Composite) super.createContents(parent);
Composite composite2 = new Composite(composite, SWT.WRAP);
composite2.setBackground(composite2.getParent().getBackground());
GridData gridData = new GridData(GridData.FILL_BOTH);
gridData.widthHint = POPOVER_WIDTH;
gridData.heightHint = POPOVER_HEIGHT;
composite2.setLayoutData(gridData);
GridLayout layout = new GridLayout();
layout.marginWidth = 0;
layout.marginHeight = 0;
layout.verticalSpacing = 2;
composite2.setLayout(layout);
createMarkersContainer(composite2);
createSeperator(composite2);
createHyperlinks(composite2);
return composite;
}
private ScrolledForm createForm(Composite parent) {
final WidgetFactory factory = new WidgetFactory(parent.getDisplay());
final ScrolledForm form = new ScrolledForm(parent,
SWT.V_SCROLL | factory.getOrientation());
form.setExpandHorizontal(true);
form.setExpandVertical(true);
form.setBackground(factory.getColors().getBackground());
form.setForeground(factory.getColors().getColor(IFormColors.TITLE));
form.setFont(JFaceResources.getHeaderFont());
form.setMinWidth(1);
form.setAlwaysShowScrollBars(true);
form.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
form.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
if (factory != null) {
factory.dispose();
}
}
});
return form;
}
private void createMarkersContainer(Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
composite.setBackground(composite.getParent().getBackground());
GridData gridData = new GridData(GridData.FILL_BOTH);
composite.setLayoutData(gridData);
GridLayout layout = new GridLayout(1, true);
layout.marginTop = 1;
layout.marginHeight = 3;
layout.marginWidth = 3;
layout.verticalSpacing = 7;
composite.setLayout(layout);
final ScrolledForm form = createForm(composite);
final Composite formBody = form.getBody();
final GridLayout layout2 = new GridLayout(1, true);
layout2.marginLeft = 12;
layout2.marginWidth = 0;
formBody.setLayout(layout2);
formBody.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
createMarkersControl(formBody);
form.addListener(SWT.Resize, new Listener() {
public void handleEvent(Event event) {
int width = form.getClientArea().width;
width -= layout2.marginLeft + layout2.marginRight
+ layout2.marginWidth * 2;
Control[] controls = formBody.getChildren();
for (int i = 0; i < controls.length; i++) {
Control c = controls[i];
((GridData) c.getLayoutData()).widthHint = width;
}
form.reflow(true);
}
});
form.reflow(true);
}
private void createMarkersControl(Composite parent) {
List<IMarkerSheet> sheets = new ArrayList<IMarkerSheet>();
if (MindMapUI.getResourceManager().getSystemMarkerSheet() != null)
sheets.add(MindMapUI.getResourceManager().getSystemMarkerSheet());
if (MindMapUI.getResourceManager().getUserMarkerSheet() != null)
sheets.add(MindMapUI.getResourceManager().getUserMarkerSheet());
MarkerSheetPart markerPart = new MarkerSheetPart(sheets);
Control control = markerPart.createControl(parent);
GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
control.setLayoutData(gridData);
}
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.marginHeight = 0;
layout.marginWidth = 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(layout);
}
private void createHyperlinks(Composite parent) {
Composite composite = new Composite(parent, SWT.NONE);
composite.setBackground(composite.getParent().getBackground());
GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
composite.setLayoutData(gridData);
GridLayout layout = new GridLayout();
layout.marginHeight = 5;
layout.marginWidth = 0;
layout.marginBottom = 2;
layout.verticalSpacing = 2;
composite.setLayout(layout);
createManageMarkersHyperlink(composite);
createImportMarkersHyperlink(composite);
createExportMarkersHyperlink(composite);
}
private void createManageMarkersHyperlink(Composite parent) {
Hyperlink manageMarkersHyperlink = createHyperlink(parent,
Messages.MarkersPopover_ManageMarkers_label);
manageMarkersHyperlink.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_MARKER, null);
}
});
}
private void createImportMarkersHyperlink(Composite parent) {
Hyperlink importManagerHyperlink = createHyperlink(parent,
Messages.MarkersPopover_ImportMarkers_label);
importManagerHyperlink.addHyperlinkListener(new HyperlinkAdapter() {
@Override
public void linkActivated(HyperlinkEvent e) {
handleShellDeactived();
IWorkbenchWindow window = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow();
final IHandlerService handlerService = window
.getService(IHandlerService.class);
SafeRunner.run(new SafeRunnable() {
@Override
public void run() throws Exception {
handlerService.executeCommand(
"org.xmind.ui.command.marker.import", null); //$NON-NLS-1$
}
});
}
});
}
private void createExportMarkersHyperlink(Composite parent) {
Hyperlink link = createHyperlink(parent,
Messages.MarkersPopover_ExportMarkers_label);
link.addHyperlinkListener(new HyperlinkAdapter() {
@Override
public void linkActivated(HyperlinkEvent e) {
handleShellDeactived();
IWorkbenchWindow window = PlatformUI.getWorkbench()
.getActiveWorkbenchWindow();
final IHandlerService handlerService = window
.getService(IHandlerService.class);
SafeRunner.run(new SafeRunnable() {
@Override
public void run() throws Exception {
handlerService.executeCommand(
"org.xmind.ui.command.marker.export", null); //$NON-NLS-1$
}
});
}
});
}
private Hyperlink createHyperlink(final Composite parent, String message) {
final Composite padding = new Composite(parent, SWT.NONE);
GridLayout layout = new GridLayout(1, false);
layout.marginWidth = 15;
layout.marginHeight = 0;
padding.setBackground(parent.getBackground());
padding.setLayout(layout);
GridData gridData = new GridData(SWT.FILL, SWT.CENTER, true, false);
padding.setLayoutData(gridData);
final Hyperlink hyperlink = new Hyperlink(padding, SWT.SINGLE);
hyperlink.setBackground(hyperlink.getParent().getBackground());
hyperlink.setLayoutData(gridData);
hyperlink.setUnderlined(false);
hyperlink.setText(message);
hyperlink.addMouseTrackListener(new MouseTrackAdapter() {
@Override
public void mouseExit(MouseEvent e) {
padding.setBackground(new LocalResourceManager(
JFaceResources.getResources(), parent)
.createColor(ColorUtils.toRGB("#FFFFFF"))); //$NON-NLS-1$
hyperlink.setBackground(new LocalResourceManager(
JFaceResources.getResources(), parent)
.createColor(ColorUtils.toRGB("#FFFFFF"))); //$NON-NLS-1$
hyperlink.setForeground(new LocalResourceManager(
JFaceResources.getResources(), parent)
.createColor(ColorUtils.toRGB("#000000"))); //$NON-NLS-1$
}
@Override
public void mouseEnter(MouseEvent e) {
padding.setBackground(new LocalResourceManager(
JFaceResources.getResources(), parent)
.createColor(ColorUtils.toRGB("#0070D8"))); //$NON-NLS-1$
hyperlink.setBackground(new LocalResourceManager(
JFaceResources.getResources(), parent)
.createColor(ColorUtils.toRGB("#0070D8"))); //$NON-NLS-1$
hyperlink.setForeground(new LocalResourceManager(
JFaceResources.getResources(), parent)
.createColor(ColorUtils.toRGB("#FFFFFF"))); //$NON-NLS-1$
}
});
return hyperlink;
}
}