package org.xmind.cathy.internal.dashboard;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.inject.Inject;
import org.eclipse.core.commands.ParameterizedCommand;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.e4.core.commands.ECommandService;
import org.eclipse.e4.core.commands.EHandlerService;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.di.annotations.Optional;
import org.eclipse.e4.core.di.extensions.EventTopic;
import org.eclipse.e4.ui.di.Focus;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.commands.MCommand;
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.MWindow;
import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
import org.eclipse.e4.ui.model.application.ui.menu.MPopupMenu;
import org.eclipse.e4.ui.services.EMenuService;
import org.eclipse.e4.ui.workbench.UIEvents;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.e4.ui.workbench.modeling.ESelectionService;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.jface.resource.ResourceManager;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IWorkbenchCommandConstants;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.commands.IElementUpdater;
import org.eclipse.ui.internal.handlers.WizardHandler;
import org.eclipse.ui.statushandlers.StatusManager;
import org.osgi.service.event.Event;
import org.xmind.cathy.internal.CathyPlugin;
import org.xmind.cathy.internal.ICathyConstants;
import org.xmind.ui.internal.dashboard.pages.IDashboardContext;
import org.xmind.ui.internal.dashboard.pages.IDashboardPage;
import org.xmind.ui.internal.e4handlers.DisabledHandler;
import org.xmind.ui.tabfolder.MTabFolder;
import org.xmind.ui.tabfolder.MTabItem;
/**
* A view that shows the Dashboard for the Cathy application.
*
* @author Frank Shaka
* @since 3.6.0
*/
public class DashboardPart implements IDashboardContext {
private static final String PERSISTED_STATE_KEY_PREFIX = "org.xmind.cathy.dashboard/"; //$NON-NLS-1$
/**
* A set of identifiers of commands that the Dashboard allows to be enabled.
* All other commands registered in the application will be disabled when
* the Dashboard is showing.
*
* @see #disableUnwantedCommands()
*/
private static final String[] AVAILABLE_COMMAND_IDS = {
"org.xmind.ui.command.showDashboard", //$NON-NLS-1$
"org.xmind.ui.command.toggleDashboard", //$NON-NLS-1$
"org.xmind.ui.command.welcome", //$NON-NLS-1$
"org.xmind.ui.command.openWorkbook", //$NON-NLS-1$
"org.xmind.ui.command.openHomeMap", //$NON-NLS-1$
"org.xmind.ui.command.newWorkbook", //$NON-NLS-1$
"org.xmind.ui.command.newFromTemplate", //$NON-NLS-1$
"org.xmind.ui.command.clearWorkbookHistory", //$NON-NLS-1$
"net.xmind.ui.command.checkForUpdates", //$NON-NLS-1$
"net.xmind.ui.command.subscribeNewsletter", //$NON-NLS-1$
"net.xmind.ui.command.feedback", //$NON-NLS-1$
"net.xmind.ui.command.signIn", //$NON-NLS-1$
"net.xmind.ui.command.signOut", //$NON-NLS-1$
"net.xmind.ui.command.activatePro", //$NON-NLS-1$
"net.xmind.ui.command.goFeaturedMaps", //$NON-NLS-1$
"org.xmind.ui.command.showModelPart", //$NON-NLS-1$
IWorkbenchCommandConstants.FILE_NEW,
IWorkbenchCommandConstants.FILE_IMPORT,
IWorkbenchCommandConstants.FILE_RESTART,
IWorkbenchCommandConstants.FILE_EXIT,
IWorkbenchCommandConstants.WINDOW_CLOSE_PART,
IWorkbenchCommandConstants.WINDOW_PREFERENCES,
IWorkbenchCommandConstants.VIEWS_SHOW_VIEW,
IWorkbenchCommandConstants.WINDOW_RESET_PERSPECTIVE,
IWorkbenchCommandConstants.WINDOW_ACTIVATE_EDITOR,
IWorkbenchCommandConstants.WINDOW_NEXT_EDITOR,
IWorkbenchCommandConstants.WINDOW_NEXT_VIEW,
IWorkbenchCommandConstants.WINDOW_PREVIOUS_EDITOR,
IWorkbenchCommandConstants.WINDOW_PREVIOUS_VIEW,
IWorkbenchCommandConstants.HELP_HELP_CONTENTS,
IWorkbenchCommandConstants.HELP_ABOUT,
IWorkbenchCommandConstants.WINDOW_SHOW_KEY_ASSIST //
};
@Inject
private IEclipseContext context;
@Inject
private MPart partModel;
@Inject
private EHandlerService handlerService;
@Inject
private ECommandService commandService;
@Inject
private ESelectionService selectionService;
@Inject
private EMenuService menuService;
@Inject
private EModelService modelService;
@Inject
private MApplication application;
private MTabFolder tabFolder;
private Set<String> availableCommandIds;
private DashboardContent content;
private ISelectionProvider selectionProvider = null;
private ISelectionChangedListener selectionChangedListener = new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
handleSelectionChanged(event);
}
};
protected IEclipseContext getContext() {
return context;
}
@PostConstruct
public void postConstruct(Composite parent) {
//
context.set(IDashboardContext.class, this);
tabFolder = new MTabFolder(parent);
ResourceManager resourceManager = new LocalResourceManager(
JFaceResources.getResources(), tabFolder);
tabFolder.setStyleProvider(new DashboardStyleProvider(resourceManager));
tabFolder.setBackground(
parent.getDisplay().getSystemColor(SWT.COLOR_TRANSPARENT));
tabFolder.addListener(SWT.Selection, new Listener() {
public void handleEvent(org.eclipse.swt.widgets.Event event) {
handlePageSelected();
}
});
availableCommandIds = new HashSet<String>();
availableCommandIds.addAll(Arrays.asList(AVAILABLE_COMMAND_IDS));
content = new DashboardContent(this, tabFolder);
disableUnwantedCommands();
}
private void handlePageSelected() {
if (tabFolder == null || content == null) {
return;
}
MTabItem item = tabFolder.getSelection();
String pageId = item == null ? null : content.getItemId(item);
partModel.getTransientData()
.put(ICathyConstants.DATA_DASHBOARD_SELECTED_PAGE_ID, pageId);
}
protected void executeCommand(String commandId,
Map<String, Object> parameters) {
if (commandService == null || handlerService == null)
return;
ParameterizedCommand command = commandService.createCommand(commandId,
parameters);
if (command == null)
return;
handlerService.executeHandler(command);
}
public void setSelectionProvider(ISelectionProvider selectionProvider) {
ISelectionProvider oldSelectionProvider = this.selectionProvider;
if (selectionProvider == oldSelectionProvider)
return;
if (oldSelectionProvider != null) {
oldSelectionProvider
.removeSelectionChangedListener(selectionChangedListener);
}
this.selectionProvider = selectionProvider;
if (selectionProvider != null) {
selectionProvider
.addSelectionChangedListener(selectionChangedListener);
}
if (selectionService != null) {
selectionService.setSelection(selectionProvider == null ? null
: selectionProvider.getSelection());
}
}
private void handleSelectionChanged(SelectionChangedEvent event) {
if (selectionService != null) {
selectionService.setSelection(event.getSelection());
}
}
/**
* Disables almost all commands unless explicitly kept enabled, to make sure
* that the user can't trigger commands that may not be appropriate during
* the appearance of the Dashboard.
* <p>
* We activate a {@link DisabledHandler} handler object for each command to
* be disabled. These handlers are registered within the context of this
* view only, so that they do not override real handlers when the Dashboard
* is hidden.
* </p>
*/
private void disableUnwantedCommands() {
if (handlerService == null || application == null)
return;
for (MCommand command : application.getCommands()) {
String commandId = command.getElementId();
if (!availableCommandIds.contains(commandId)) {
handlerService.activateHandler(commandId,
new DisabledHandler(findElementUpdater(commandId)));
}
}
}
/**
* Finds an element updater that knows how to decorate UI elements like the
* real handler of the command.
*
* @param commandId
* the identifier of the command to match
* @return
*/
private IElementUpdater findElementUpdater(String commandId) {
if (IWorkbenchCommandConstants.FILE_EXPORT.equals(commandId)) {
return new WizardHandler.Export();
} else if (IWorkbenchCommandConstants.FILE_IMPORT.equals(commandId)) {
return new WizardHandler.Import();
}
return null;
}
@PreDestroy
public void preDestroy() {
this.content = null;
if (this.tabFolder != null) {
this.tabFolder.dispose();
this.tabFolder = null;
}
}
public void hideDashboard() {
MWindow window = findWindowFor(partModel);
if (window == null) {
CathyPlugin.log("Failed to find window for Dashboard part."); //$NON-NLS-1$
return;
}
if (window.getTags().contains(ICathyConstants.TAG_SHOW_DASHBOARD)) {
window.getTags().remove(ICathyConstants.TAG_SHOW_DASHBOARD);
}
}
private static MWindow findWindowFor(MUIElement element) {
if (element == null)
return null;
if (element instanceof MWindow)
return (MWindow) element;
MPlaceholder placeholder = element.getCurSharedRef();
if (placeholder != null)
return findWindowFor(placeholder);
return findWindowFor(element.getParent());
}
@Inject
@Optional
public void subscribeDashboardTransientData(
@EventTopic(UIEvents.ApplicationElement.TOPIC_TRANSIENTDATA) Event event) {
if (partModel == null
|| partModel != event.getProperty(UIEvents.EventTags.ELEMENT))
return;
Object selectedPageId = partModel.getTransientData()
.get(ICathyConstants.DATA_DASHBOARD_SELECTED_PAGE_ID);
if (selectedPageId == null || !(selectedPageId instanceof String))
return;
if (this.tabFolder == null || content == null)
return;
MTabItem item = content.getItemById((String) selectedPageId);
IDashboardPage dashboardPage = content.getDashboardPage(item);
if (dashboardPage != null) {
Control control = dashboardPage.getControl();
if (control == null || control.isDisposed()) {
dashboardPage.createControl(this.tabFolder.getBody());
item.setControl(dashboardPage.getControl());
}
dashboardPage.setFocus();
this.tabFolder.setSelection(item);
}
}
@Focus
public void setFocus() {
if (tabFolder != null && !tabFolder.isDisposed() && content != null) {
MTabItem item = tabFolder.getSelection();
if (item != null) {
IDashboardPage page = content.getDashboardPage(item);
if (page != null) {
page.setFocus();
return;
} else {
Control control = item.getControl();
if (control != null) {
control.setFocus();
return;
}
}
}
tabFolder.setFocus();
}
}
public <T> T getAdapter(Class<T> adapter) {
if (adapter == MPart.class)
return adapter.cast(partModel);
if (context != null)
return context.get(adapter);
return null;
}
public void registerAvailableCommandId(String commandId) {
availableCommandIds.add(commandId);
}
public boolean registerContextMenu(Object menuParent, final String menuId) {
if (!(menuParent instanceof Control) || menuService == null
|| partModel == null) {
return false;
}
Control parentControl = (Control) menuParent;
MPopupMenu menuModel = null;
for (MMenu item : partModel.getMenus()) {
if (menuId.equals(item.getElementId())
&& item instanceof MPopupMenu) {
menuModel = (MPopupMenu) item;
break;
}
}
if (menuModel == null) {
menuModel = modelService.createModelElement(MPopupMenu.class);
menuModel.setElementId(menuId);
menuModel.getTags().add("menuContribution:popup"); //$NON-NLS-1$
partModel.getMenus().add(menuModel);
}
if (menuModel.getWidget() instanceof Menu) {
Menu menu = (Menu) menuModel.getWidget();
parentControl.setMenu(menu);
return true;
}
return menuService.registerContextMenu(parentControl, menuId);
}
public boolean openEditor(final IEditorInput input, final String editorId) {
final IWorkbenchPage page = context.get(IWorkbenchPage.class);
if (page == null)
return false;
try {
page.openEditor(input, editorId);
return true;
} catch (PartInitException e) {
StatusManager.getManager().handle(new Status(IStatus.ERROR,
CathyPlugin.PLUGIN_ID, e.getMessage(), e),
StatusManager.SHOW);
return false;
}
}
public boolean showView(final String viewId) {
final IWorkbenchPage page = context.get(IWorkbenchPage.class);
if (page == null)
return false;
try {
page.showView(viewId);
return true;
} catch (PartInitException e) {
StatusManager.getManager().handle(new Status(IStatus.ERROR,
CathyPlugin.PLUGIN_ID, e.getMessage(), e),
StatusManager.SHOW);
return false;
}
}
/*
* (non-Javadoc)
* @see
* org.xmind.ui.internal.dashboard.pages.IDashboardContext#getPersistedState
* (java.lang.String)
*/
public String getPersistedState(String key) {
Assert.isLegal(key != null);
return partModel.getPersistedState()
.get(PERSISTED_STATE_KEY_PREFIX + key);
}
/*
* (non-Javadoc)
* @see
* org.xmind.ui.internal.dashboard.pages.IDashboardContext#setPersistedState
* (java.lang.String, java.lang.String)
*/
public void setPersistedState(String key, String value) {
Assert.isLegal(key != null);
if (value == null) {
partModel.getPersistedState()
.remove(PERSISTED_STATE_KEY_PREFIX + key);
} else {
partModel.getPersistedState().put(PERSISTED_STATE_KEY_PREFIX + key,
value);
}
}
/*
* (non-Javadoc)
* @see org.xmind.ui.internal.dashboard.pages.IDashboardContext#
* getContextVariable(java.lang.Class)
*/
public <T> T getContextVariable(Class<T> key) {
return context.get(key);
}
/*
* (non-Javadoc)
* @see org.xmind.ui.internal.dashboard.pages.IDashboardContext#
* getContextVariable(java.lang.String)
*/
public Object getContextVariable(String key) {
return context.get(key);
}
}