package org.xmind.cathy.internal.dashboard; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; import javax.xml.parsers.DocumentBuilderFactory; import org.eclipse.core.runtime.Platform; import org.eclipse.e4.core.contexts.ContextInjectionFactory; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.swt.SWT; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.osgi.framework.Bundle; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xmind.cathy.internal.CathyPlugin; import org.xmind.ui.internal.dashboard.pages.IDashboardPage; import org.xmind.ui.tabfolder.MTabFolder; import org.xmind.ui.tabfolder.MTabItem; public class DashboardContent { private static final String CONTENT_URI = "platform:/plugin/org.xmind.cathy/dashboard/dashboard.xml"; //$NON-NLS-1$ private static final String NLS_PATH_BASE = "dashboard/dashboard"; //$NON-NLS-1$ private static final String TAG_DASHBOARD = "dashboard"; //$NON-NLS-1$ private static final String TAG_PAGE = "page"; //$NON-NLS-1$ private static final String TAG_SPACE = "space"; //$NON-NLS-1$ private static final String TAG_COMMAND = "command"; //$NON-NLS-1$ private static final String TAG_PARAMETER = "parameter"; //$NON-NLS-1$ private static final String TAG_ITEM = "item"; //$NON-NLS-1$ private static final String ATTR_ID = "id"; //$NON-NLS-1$ private static final String ATTR_LABEL = "label"; //$NON-NLS-1$ private static final String ATTR_ICON_URI = "iconURI"; //$NON-NLS-1$ private static final String ATTR_CONTRIBUTION_URI = "contributionURI"; //$NON-NLS-1$ private static final String ATTR_COMMAND_ID = "commandId"; //$NON-NLS-1$ private static final String ATTR_NAME = "name"; //$NON-NLS-1$ private static final String ATTR_VALUE = "value"; //$NON-NLS-1$ private static final String ATTR_WIDTH = "width"; //$NON-NLS-1$ private static final String VAL_FILL = "fill"; //$NON-NLS-1$ private static final String DATA_ID = "org.xmind.ui.dashboard.itemId"; //$NON-NLS-1$ private static final String DATA_PARAMETERS = "org.xmind.ui.dashboard.commandParameters"; //$NON-NLS-1$ private static final String STATE_SELECTED_PAGE_ID = "selectedPageId"; //$NON-NLS-1$ private final DashboardPart part; private final MTabFolder tabFolder; private Properties nlsProperties = new Properties(); public DashboardContent(final DashboardPart part, final MTabFolder tabFolder) { this.part = part; this.tabFolder = tabFolder; loadFromDefaultLocation(); tabFolder.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { Object page = event.item.getData(); if (page instanceof IDashboardPage) { handlePageSelected((IDashboardPage) page); } } }); tabFolder.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { MTabItem item = tabFolder.getSelection(); String pageId = (String) item.getData(DATA_ID); if (pageId != null) { part.setPersistedState(STATE_SELECTED_PAGE_ID, pageId); } } }); } private void loadFromDefaultLocation() { // load NLS properties nlsProperties = CathyPlugin.getDefault() .loadNLSProperties(NLS_PATH_BASE); // load content xml try { URL docURL = new URL(CONTENT_URI); loadFromURL(docURL); } catch (Exception e) { CathyPlugin.log(e, "Failed to load dashboard content from " + CONTENT_URI); //$NON-NLS-1$ } // set primary selection MTabItem primarySelection = findPrimarySelection(); tabFolder.setSelection(primarySelection); IDashboardPage page = getDashboardPage(primarySelection); if (page != null) { if (page.getControl() == null || page.getControl().isDisposed()) { page.createControl(this.tabFolder.getBody()); primarySelection.setControl(page.getControl()); } handlePageSelected(page); } } private void loadFromURL(URL docURL) throws Exception { InputStream docStream = docURL.openStream(); try { Document doc = DocumentBuilderFactory.newInstance() .newDocumentBuilder().parse(docStream); Element rootElement = doc.getDocumentElement(); if (rootElement == null || !TAG_DASHBOARD.equals(rootElement.getNodeName())) throw new IllegalArgumentException( "No 'dashboard' element in " + CONTENT_URI); //$NON-NLS-1$ readElement(rootElement, tabFolder); } finally { docStream.close(); } } private void readElement(Element element, Object parent) throws Exception { String tagName = element.getTagName(); Object item = parent; if (parent instanceof MTabFolder) { if (TAG_PAGE.equals(tagName)) { item = readPage(element, (MTabFolder) parent); } else if (TAG_COMMAND.equals(tagName)) { item = readCommand(element, (MTabFolder) parent); } else if (TAG_SPACE.equals(tagName)) { item = readSeparator(element, (MTabFolder) parent); } else if (TAG_ITEM.equals(tagName)) { item = readSimpleItem(element, (MTabFolder) parent); } } else if (parent instanceof MTabItem) { if (TAG_PARAMETER.equals(tagName)) { readCommandParameter(element, (MTabItem) parent); } } readChildren(element.getChildNodes(), item); } private void readChildren(NodeList children, Object parent) throws Exception { int length = children.getLength(); for (int i = 0; i < length; i++) { Node childNode = children.item(i); if (childNode.getNodeType() == Node.ELEMENT_NODE) { readElement((Element) childNode, parent); } } } private MTabItem readPage(Element element, MTabFolder tabFolder) throws Exception { String id = element.getAttribute(ATTR_ID); if (id == null || "".equals(id)) //$NON-NLS-1$ throw new IllegalArgumentException("No id for page."); //$NON-NLS-1$ String contributionURI = element.getAttribute(ATTR_CONTRIBUTION_URI); if (contributionURI == null || !contributionURI.startsWith("bundleclass://")) //$NON-NLS-1$ throw new IllegalArgumentException( "Invalid contributionURI: " + contributionURI); //$NON-NLS-1$ String[] contributionPaths = contributionURI.substring(14).split("/"); //$NON-NLS-1$ if (contributionPaths.length != 2) throw new IllegalArgumentException( "Invalid contributionURI: " + contributionURI); //$NON-NLS-1$ String bundleId = contributionPaths[0]; String className = contributionPaths[1]; Class<?> cls; try { Bundle bundle = Platform.getBundle(bundleId); if (bundle == null) throw new ClassNotFoundException(); cls = bundle.loadClass(className); } catch (ClassNotFoundException e) { // ignore errors caused contribution not found return null; } Object contribution = ContextInjectionFactory.make(cls, part.getContext()); if (!(contribution instanceof IDashboardPage)) throw new IllegalArgumentException( "Invalid contribution type: " + contribution); //$NON-NLS-1$ final IDashboardPage page = (IDashboardPage) contribution; page.setContext(part); String label = readLabel(element); page.setTitle(label); ImageDescriptor icon = readIcon(element); page.setImageDescriptor(icon); // add side-bar tab MTabItem item = new MTabItem(tabFolder, SWT.RADIO); item.setText(page.getTitle()); item.setImage(page.getImage()); // page.createControl(this.tabFolder.getBody()); // item.setControl(page.getControl()); item.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { Control pageControl = page.getControl(); if (pageControl != null) { pageControl.dispose(); } page.dispose(); } }); item.setData(page); item.setData(DATA_ID, id); return item; } private MTabItem readCommand(Element element, MTabFolder tabFolder) throws Exception { String id = element.getAttribute(ATTR_ID); if (id == null || "".equals(id)) //$NON-NLS-1$ throw new IllegalArgumentException("No id for command."); //$NON-NLS-1$ final String commandId = element.getAttribute(ATTR_COMMAND_ID); if (commandId == null || "".equals(commandId)) //$NON-NLS-1$ throw new IllegalArgumentException( "No command id found for command"); //$NON-NLS-1$ String label = readLabel(element); ImageDescriptor icon = readIcon(element); MTabItem item = new MTabItem(tabFolder, SWT.PUSH); item.setText(label); final Image iconImage = icon == null ? null : icon.createImage(); item.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { iconImage.dispose(); } }); item.setImage(iconImage); item.setData(DATA_ID, id); item.setData(DATA_PARAMETERS, new Properties()); item.addListener(SWT.Selection, new Listener() { public void handleEvent(Event event) { Map<String, Object> parameters = new HashMap<String, Object>(); Properties commandParameters = (Properties) event.widget .getData(DATA_PARAMETERS); if (commandParameters != null) { for (Entry<Object, Object> en : commandParameters .entrySet()) { parameters.put((String) en.getKey(), en.getValue()); } } part.executeCommand(commandId, parameters); } }); return item; } private MTabItem readSimpleItem(Element element, MTabFolder tabFolder) throws Exception { String id = element.getAttribute(ATTR_ID); if (id == null || "".equals(id)) //$NON-NLS-1$ throw new IllegalArgumentException("No id for page."); //$NON-NLS-1$ String label = readLabel(element); ImageDescriptor icon = readIcon(element); MTabItem item = new MTabItem(tabFolder, SWT.SIMPLE); item.setText(label); final Image iconImage = icon.createImage(); item.addDisposeListener(new DisposeListener() { public void widgetDisposed(DisposeEvent e) { iconImage.dispose(); } }); item.setImage(iconImage); item.setData(DATA_ID, id); return item; } private MTabItem readSeparator(Element element, MTabFolder tabFolder) throws Exception { String id = element.getAttribute(ATTR_ID); if (id == null || "".equals(id)) //$NON-NLS-1$ throw new IllegalArgumentException("No id for page."); //$NON-NLS-1$ MTabItem item = new MTabItem(tabFolder, SWT.SEPARATOR); item.setData(DATA_ID, id); String width = element.getAttribute(ATTR_WIDTH); if (VAL_FILL.equals(width)) { item.setWidth(SWT.SEPARATOR_FILL); } else if (width != null && !"".equals(width)) { //$NON-NLS-1$ try { int widthValue = Integer.parseInt(width, 10); item.setWidth(widthValue); } catch (NumberFormatException e) { } } return item; } private void readCommandParameter(Element element, MTabItem item) { String name = element.getAttribute(ATTR_NAME); String value = element.getAttribute(ATTR_VALUE); if (name == null || "".equals(name) //$NON-NLS-1$ || value == null || "".equals(value)) //$NON-NLS-1$ return; Properties parameters = (Properties) item.getData(DATA_PARAMETERS); if (parameters == null) return; parameters.put(name, value); } private ImageDescriptor readIcon(Element element) throws MalformedURLException { String iconURI = element.getAttribute(ATTR_ICON_URI); ImageDescriptor icon = (iconURI == null || "".equals(iconURI)) //$NON-NLS-1$ ? null : ImageDescriptor.createFromURL(new URL(iconURI)); return icon; } private String readLabel(Element element) { String label = element.getAttribute(ATTR_LABEL); if (label.startsWith("%")) { //$NON-NLS-1$ String nativeLabel = nlsProperties.getProperty(label.substring(1)); if (nativeLabel != null) { label = nativeLabel; } } return label; } private MTabItem findPrimarySelection() { String lastPageId = part.getPersistedState(STATE_SELECTED_PAGE_ID); if (lastPageId != null) { MTabItem item = getItemById(lastPageId); if (item != null) return item; } int itemCount = tabFolder.getItemCount(); for (int i = 0; i < itemCount; i++) { MTabItem item = tabFolder.getItem(i); if ((item.getStyle() & SWT.RADIO) != 0) { return item; } } return null; } public MTabItem getItemById(String pageId) { if (pageId == null) return null; int itemCount = tabFolder.getItemCount(); for (int i = 0; i < itemCount; i++) { MTabItem item = tabFolder.getItem(i); if (pageId.equals(item.getData(DATA_ID))) return item; } return null; } public String getItemId(MTabItem item) { return (String) item.getData(DATA_ID); } public IDashboardPage getDashboardPage(MTabItem item) { Object data = item.getData(); return data instanceof IDashboardPage ? (IDashboardPage) data : null; } protected void handlePageSelected(final IDashboardPage page) { ISelectionProvider selectionProvider = CathyPlugin.getAdapter(page, ISelectionProvider.class); part.setSelectionProvider(selectionProvider); } }