package org.xmind.cathy.internal.dashboard; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Properties; import javax.xml.parsers.DocumentBuilderFactory; import org.eclipse.core.runtime.Assert; import org.eclipse.core.runtime.FileLocator; import org.eclipse.draw2d.geometry.Dimension; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.Viewer; import org.eclipse.swt.graphics.Image; 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.gallery.GalleryViewer; import org.xmind.ui.viewers.ImageCachedLabelProvider; public class StructureListContentProvider implements IStructuredContentProvider { public static final String CONTENT_URI = "platform:/plugin/org.xmind.cathy/dashboard/new/structures.xml"; //$NON-NLS-1$ public static final String NLS_PATH_BASE = "dashboard/new/structures"; //$NON-NLS-1$ private static final String TAG_STRUCTURE_LIST = "structure-list"; //$NON-NLS-1$ private static final String TAG_STRUCTURE = "structure"; //$NON-NLS-1$ private static final String ATTR_ID = "id"; //$NON-NLS-1$ private static final String ATTR_NAME = "name"; //$NON-NLS-1$ private static final String ATTR_ICON = "icon"; //$NON-NLS-1$ private static final String ATTR_VALUE = "value"; //$NON-NLS-1$ private static final String ATTR_ICON_HEIGHT = "icon-height"; //$NON-NLS-1$ private static final String ATTR_ICON_WIDTH = "icon-width"; //$NON-NLS-1$ public static final class ContentSource { public final String contentURI; public final String nlsPathBase; public ContentSource(String contentURI, String nlsPathBase) { this.contentURI = contentURI; this.nlsPathBase = nlsPathBase; } @Override public boolean equals(Object obj) { if (obj == this) return true; if (obj == null || !(obj instanceof ContentSource)) return false; ContentSource that = (ContentSource) obj; return (this.contentURI == that.contentURI || (this.contentURI != null && this.contentURI.equals(that.contentURI))) && (this.nlsPathBase == that.nlsPathBase || (this.nlsPathBase != null && this.nlsPathBase .equals(that.nlsPathBase))); } @Override public int hashCode() { int x = 37; if (contentURI != null) { x = x ^ contentURI.hashCode(); } if (nlsPathBase != null) { x = x ^ nlsPathBase.hashCode(); } return x; } } static class StructureDescriptor { private String id; private String value; private String name; private ImageDescriptor icon; public StructureDescriptor(String id, String value, String name, ImageDescriptor icon) { super(); Assert.isNotNull(id); Assert.isNotNull(value); this.id = id; this.value = value; this.name = name; this.icon = icon; } public int hashCode() { return id.hashCode(); } public String getId() { return id; } public String getName() { return this.name; } public String getValue() { return this.value; } public ImageDescriptor getIcon() { return this.icon; } public boolean equals(Object obj) { if (obj == this) return true; if (obj == null || !(obj instanceof StructureDescriptor)) return false; StructureDescriptor that = (StructureDescriptor) obj; return this.id.equals(that.id); } } static class StructureListLabelProvider extends ImageCachedLabelProvider { @Override public String getText(Object element) { if (element instanceof StructureDescriptor) return ((StructureDescriptor) element).getName(); return super.getText(element); } @Override protected Image createImage(Object element) { if (element instanceof StructureDescriptor) { ImageDescriptor icon = ((StructureDescriptor) element) .getIcon(); if (icon != null) return icon.createImage(); } return null; } } private ContentSource source = null; private List<StructureDescriptor> structureDescriptors = new ArrayList<StructureListContentProvider.StructureDescriptor>(); private Dimension iconSizeHints = new Dimension(); public void dispose() { structureDescriptors.clear(); source = null; } public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { ContentSource newSource = toContentSource(newInput); if (newSource == source || (newSource != null && newSource.equals(source))) return; source = newSource; structureDescriptors.clear(); iconSizeHints = new Dimension(); if (source != null) { readTemplatesFromSource(source); } if (viewer instanceof GalleryViewer) { ((GalleryViewer) viewer).getProperties() .set(GalleryViewer.FrameContentSize, iconSizeHints); } } private ContentSource toContentSource(Object input) { ContentSource newSource; if (input instanceof ContentSource) { newSource = (ContentSource) input; } else if (input instanceof String) { newSource = new ContentSource((String) input, null); } else { newSource = null; } return newSource; } public Object[] getElements(Object inputElement) { ContentSource inputSource = toContentSource(inputElement); if (inputSource == source || (inputSource != null && inputSource.equals(source))) { return structureDescriptors.toArray(); } return new Object[0]; } private void readTemplatesFromSource(ContentSource source) { Properties nlsProperties; if (source.nlsPathBase != null) { nlsProperties = CathyPlugin.getDefault() .loadNLSProperties(source.nlsPathBase); } else { nlsProperties = new Properties(); } if (source.contentURI != null) { try { URL contentURL = new URL(source.contentURI); URL locatedURL = FileLocator.find(contentURL); if (locatedURL != null) contentURL = locatedURL; InputStream contentStream = contentURL.openStream(); try { Document doc = DocumentBuilderFactory.newInstance() .newDocumentBuilder().parse(contentStream); readElement(doc.getDocumentElement(), nlsProperties); } finally { contentStream.close(); } } catch (Exception e) { CathyPlugin.log(e, "Failed to load content for structure list from: " //$NON-NLS-1$ + source.contentURI); } } } private void readElement(Element element, Properties nlsProperties) { String tagName = element.getTagName(); if (TAG_STRUCTURE.equals(tagName)) { readTemplate(element, nlsProperties); } else if (TAG_STRUCTURE_LIST.equals(tagName)) { readGlobalAttributes(element); } readChildren(element.getChildNodes(), nlsProperties); } private void readChildren(NodeList children, Properties nlsProperties) { int length = children.getLength(); for (int i = 0; i < length; i++) { Node node = children.item(i); if (node != null && node.getNodeType() == Node.ELEMENT_NODE) { readElement((Element) node, nlsProperties); } } } private void readTemplate(Element element, Properties nlsProperties) { String id = element.getAttribute(ATTR_ID); String name = element.getAttribute(ATTR_NAME); String iconURI = element.getAttribute(ATTR_ICON); String structureClass = element.getAttribute(ATTR_VALUE); if (id == null || "".equals(id)) //$NON-NLS-1$ throw new IllegalArgumentException("Missing 'id' attribute"); //$NON-NLS-1$ if (name == null) { name = ""; //$NON-NLS-1$ } else if (name.startsWith("%")) { //$NON-NLS-1$ String nativeName = nlsProperties.getProperty(name.substring(1)); if (nativeName != null) { name = nativeName; } } ImageDescriptor icon; if (iconURI == null) { icon = null; } else { try { icon = ImageDescriptor.createFromURL(new URL(iconURI)); } catch (MalformedURLException e) { CathyPlugin.log(e, "Invalid icon URI: '" + iconURI + "'"); //$NON-NLS-1$ //$NON-NLS-2$ icon = null; } } StructureDescriptor structureDescriptor = new StructureDescriptor(id, structureClass, name, icon); structureDescriptors.add(structureDescriptor); } private void readGlobalAttributes(Element element) { String iconWidth = element.getAttribute(ATTR_ICON_WIDTH); String iconHeight = element.getAttribute(ATTR_ICON_HEIGHT); if (iconWidth != null && iconHeight != null) { try { int width = Integer.parseInt(iconWidth, 10); int height = Integer.parseInt(iconHeight, 10); iconSizeHints.width = width; iconSizeHints.height = height; } catch (NumberFormatException e) { } } } public static final ContentSource getDefaultInput() { return new ContentSource(CONTENT_URI, NLS_PATH_BASE); } }