package org.xmind.cathy.internal.dashboard;
import java.util.Arrays;
import java.util.List;
import javax.inject.Inject;
import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.core.di.extensions.EventTopic;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.ui.MElementContainer;
import org.eclipse.e4.ui.model.application.ui.MUIElement;
import org.eclipse.e4.ui.model.application.ui.advanced.MPlaceholder;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
import org.eclipse.e4.ui.model.application.ui.basic.MStackElement;
import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
import org.eclipse.e4.ui.model.application.ui.menu.MHandledItem;
import org.eclipse.e4.ui.workbench.Selector;
import org.eclipse.e4.ui.workbench.UIEvents;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.e4.ui.workbench.modeling.EPartService;
import org.osgi.service.event.Event;
import org.xmind.cathy.internal.HandledItemMatcher;
import org.xmind.cathy.internal.ICathyConstants;
import org.xmind.cathy.internal.WorkbenchMessages;
public class DashboardAutomationAddon {
@Inject
private EModelService modelService;
@Inject
private MApplication application;
private Selector itemMatcher = new HandledItemMatcher(
ICathyConstants.COMMAND_TOGGLE_DASHBOARD);
/**
* @param modelService
* the modelService to set
*/
public void setModelService(EModelService modelService) {
this.modelService = modelService;
}
/**
* @param application
* the application to set
*/
public void setApplication(MApplication application) {
this.application = application;
}
public void showDashboard(MWindow window) {
if (doShowDashboard(window)) {
updateDashboardToolItems(window);
}
//hide right parts.
hideVisiblePart(window, "org.xmind.ui.stack.right"); //$NON-NLS-1$
}
@Inject
@Optional
public void updateDashboardVisibilityWhenWindowTagsChanged(
@EventTopic(UIEvents.ApplicationElement.TOPIC_TAGS) Event event) {
Object element = event.getProperty(UIEvents.EventTags.ELEMENT);
if (!(element instanceof MWindow) || !ICathyConstants.ID_MAIN_WINDOW
.equals(((MWindow) element).getElementId()))
return;
MWindow window = (MWindow) element;
if (UIEvents.EventTypes.ADD
.equals(event.getProperty(UIEvents.EventTags.TYPE))
&& ICathyConstants.TAG_SHOW_DASHBOARD.equals(
event.getProperty(UIEvents.EventTags.NEW_VALUE))) {
if (!doShowDashboard(window)) {
window.getTags().remove(ICathyConstants.TAG_SHOW_DASHBOARD);
return;
}
} else if (UIEvents.EventTypes.REMOVE
.equals(event.getProperty(UIEvents.EventTags.TYPE))
&& ICathyConstants.TAG_SHOW_DASHBOARD.equals(
event.getProperty(UIEvents.EventTags.OLD_VALUE))) {
if (!doHideDashboard(window)) {
window.getTags().add(ICathyConstants.TAG_SHOW_DASHBOARD);
return;
}
}
updateDashboardToolItems(window);
}
private boolean doShowDashboard(MWindow window) {
MPart dashboardPart = findReferencedDashboardPartIn(window, true);
if (dashboardPart == null)
return false;
EPartService partService = window.getContext().get(EPartService.class);
if (partService == null)
return false;
partService.activate(dashboardPart, true);
return partService.getActivePart() == dashboardPart;
}
private boolean doHideDashboard(MWindow window) {
MPart dashboardPart = findReferencedDashboardPartIn(window, false);
if (dashboardPart == null)
return true;
EPartService partService = window.getContext().get(EPartService.class);
if (partService == null)
return false;
partService.hidePart(dashboardPart);
return partService.getActivePart() != dashboardPart;
}
@Inject
@Optional
public void updateWindowTagsWhenDashboardVisibilityChanged(
@EventTopic(UIEvents.ElementContainer.TOPIC_SELECTEDELEMENT) Event event) {
Object element = event.getProperty(UIEvents.EventTags.ELEMENT);
if (!(element instanceof MElementContainer))
return;
MElementContainer container = (MElementContainer) element;
final MWindow window = modelService.getTopLevelWindowFor(container);
if (window == null || !ICathyConstants.ID_MAIN_WINDOW
.equals(window.getElementId()))
return;
MPart activePart = findSelectedElementIn(window, MPart.class);
if (activePart != null && ICathyConstants.ID_DASHBOARD_PART
.equals(activePart.getElementId())) {
/*
* The Dashboard is shown, we must ensure that the
* CathyShowDashboard tag is added to window.
*/
if (!window.getTags()
.contains(ICathyConstants.TAG_SHOW_DASHBOARD)) {
window.getTags().add(ICathyConstants.TAG_SHOW_DASHBOARD);
}
} else {
/*
* The Dashboard is about to be hidden, we must ensure that the
* CathyShowDashboard tag is removed from the window.
*/
if (window.getTags().contains(ICathyConstants.TAG_SHOW_DASHBOARD)) {
window.getTags().remove(ICathyConstants.TAG_SHOW_DASHBOARD);
}
}
}
@Inject
@Optional
public void showDashboardWhenAllEditorsAreRemoved(
@EventTopic(UIEvents.ElementContainer.TOPIC_CHILDREN) Event event) {
if (!UIEvents.isREMOVE(event))
return;
Object element = event.getProperty(UIEvents.EventTags.ELEMENT);
if (!(element instanceof MElementContainer))
return;
boolean partRemoved = false;
for (Object removed : UIEvents.asIterable(event,
UIEvents.EventTags.OLD_VALUE)) {
if (removed instanceof MPart) {
partRemoved = true;
break;
}
}
if (!partRemoved)
return;
MWindow window = modelService
.getTopLevelWindowFor((MUIElement) element);
if (window == null || !ICathyConstants.ID_MAIN_WINDOW
.equals(window.getElementId()))
return;
List<MPart> editors = modelService.findElements(window, null,
MPart.class, Arrays.asList(ICathyConstants.TAG_EDITOR));
if (!editors.isEmpty())
return;
//hide right parts.
hideVisiblePart(window, "org.xmind.ui.stack.right"); //$NON-NLS-1$
if (!window.getTags().contains(ICathyConstants.TAG_SHOW_DASHBOARD)) {
window.getTags().add(ICathyConstants.TAG_SHOW_DASHBOARD);
}
}
private MPart findReferencedDashboardPartIn(MWindow window,
boolean createIfMissing) {
MPart dashboardPart = null;
/*
* Find Dashboard instance in window model tree.
*/
List<MPart> dashboardParts = modelService.findElements(window,
ICathyConstants.ID_DASHBOARD_PART, MPart.class, null);
if (!dashboardParts.isEmpty()) {
dashboardPart = dashboardParts.get(0);
} else {
/*
* Find Dashboard instance in shared elements.
*/
for (MUIElement p : window.getChildren()) {
if (p instanceof MPart && ICathyConstants.ID_DASHBOARD_PART
.equals(p.getElementId())) {
dashboardPart = (MPart) p;
break;
}
}
}
if (dashboardPart == null && createIfMissing) {
/*
* Create Dashboard part from snippet.
*/
MUIElement part = modelService.cloneSnippet(application,
ICathyConstants.ID_DASHBOARD_PART, window);
if (part != null && part instanceof MPart
&& ICathyConstants.ID_DASHBOARD_PART
.equals(part.getElementId())) {
dashboardPart = (MPart) part;
window.getChildren().add(dashboardPart);
}
}
return dashboardPart;
}
private <T extends MUIElement> T findSelectedElementIn(MUIElement root,
Class<T> type) {
if (type.isInstance(root))
return type.cast(root);
if (root instanceof MPlaceholder)
return findSelectedElementIn(((MPlaceholder) root).getRef(), type);
if (root instanceof MElementContainer)
return findSelectedElementIn(
((MElementContainer) root).getSelectedElement(), type);
return null;
}
private void updateDashboardToolItems(MWindow window) {
String tooltip;
boolean selected;
if (window.getTags().contains(ICathyConstants.TAG_SHOW_DASHBOARD)) {
tooltip = WorkbenchMessages.DashboardHideHome_tooltip;
selected = true;
} else {
tooltip = WorkbenchMessages.DashboardShowHome_tooltip;
selected = false;
}
List<MHandledItem> items = modelService.findElements(window,
MHandledItem.class, EModelService.ANYWHERE, itemMatcher);
for (MHandledItem item : items) {
item.setTooltip(tooltip);
item.setSelected(selected);
}
}
private static final String hideVisiblePart(MWindow window,
String partStackId) {
if (window == null || partStackId == null) {
return null;
}
EModelService modelService = window.getContext()
.get(EModelService.class);
EPartService partService = window.getContext().get(EPartService.class);
List<MPartStack> partStacks = modelService.findElements(window,
partStackId, MPartStack.class, null);
if (partStacks.isEmpty()) {
return null;
}
MPartStack partStack = partStacks.get(0);
MPart visiblePart = null;
MStackElement selectedElement = partStack.getSelectedElement();
if (selectedElement instanceof MPlaceholder) {
MPlaceholder placeholder = (MPlaceholder) selectedElement;
visiblePart = partService.findPart(placeholder.getElementId());
} else if (selectedElement instanceof MPart) {
visiblePart = (MPart) selectedElement;
}
if (visiblePart != null) {
visiblePart.setVisible(false);
partService.hidePart(visiblePart);
return visiblePart.getElementId();
}
return null;
}
}