package bndtools.wizards.shared; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.util.Arrays; import org.bndtools.api.ILogger; import org.bndtools.api.Logger; import org.bndtools.core.ui.ConfigElementLabelProvider; import org.bndtools.utils.eclipse.CategorisedConfigurationElementComparator; import org.bndtools.utils.eclipse.CategorisedPrioritisedConfigurationElementTreeContentProvider; import org.bndtools.utils.osgi.BundleUtils; import org.bndtools.utils.workspace.FileUtils; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.resource.JFaceResources; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Tree; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.browser.IWebBrowser; import org.eclipse.ui.browser.IWorkbenchBrowserSupport; import org.eclipse.ui.forms.events.HyperlinkAdapter; import org.eclipse.ui.forms.events.HyperlinkEvent; import org.eclipse.ui.forms.widgets.FormText; import org.eclipse.ui.forms.widgets.ScrolledFormText; import org.osgi.framework.Bundle; import bndtools.Plugin; public abstract class AbstractTemplateSelectionWizardPage extends WizardPage { private static final ILogger logger = Logger.getLogger(AbstractTemplateSelectionWizardPage.class); public static final String PROP_ELEMENT = "selectedElement"; protected final PropertyChangeSupport propSupport = new PropertyChangeSupport(this); private Tree tree; private TreeViewer viewer; private ScrolledFormText txtDescription; private IConfigurationElement[] elements; private IConfigurationElement selectedElement = null; private boolean shown = false; protected AbstractTemplateSelectionWizardPage(String pageName) { super(pageName); } @Override public void createControl(Composite parent) { Composite container = new Composite(parent, SWT.NULL); setControl(container); container.setLayout(new GridLayout(1, false)); new Label(container, SWT.NONE).setText("Select Template:"); tree = new Tree(container, SWT.BORDER | SWT.FULL_SELECTION); GridData gd_table = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1); gd_table.heightHint = 100; tree.setLayoutData(gd_table); viewer = new TreeViewer(tree); Label lblNewLabel = new Label(container, SWT.NONE); lblNewLabel.setText("Description:"); Composite cmpDescription = new Composite(container, SWT.BORDER); cmpDescription.setBackground(tree.getBackground()); txtDescription = new ScrolledFormText(cmpDescription, SWT.V_SCROLL | SWT.H_SCROLL, false); FormText formText = new FormText(txtDescription, SWT.NO_FOCUS); txtDescription.setFormText(formText); txtDescription.setBackground(tree.getBackground()); formText.setBackground(tree.getBackground()); formText.setForeground(tree.getForeground()); formText.setFont("fixed", JFaceResources.getTextFont()); formText.setFont("italic", JFaceResources.getFontRegistry().getItalic("")); GridData gd_cmpDescription = new GridData(SWT.FILL, SWT.FILL, true, true); gd_cmpDescription.heightHint = 100; cmpDescription.setLayoutData(gd_cmpDescription); GridLayout layout_cmpDescription = new GridLayout(1, false); cmpDescription.setLayout(layout_cmpDescription); GridData gd_txtDescription = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1); gd_txtDescription.heightHint = 100; txtDescription.setLayoutData(gd_txtDescription); viewer.setContentProvider(new CategorisedPrioritisedConfigurationElementTreeContentProvider(true)); viewer.setLabelProvider(new ConfigElementLabelProvider(parent.getDisplay(), "icons/template.gif")); loadData(); viewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { Object selected = ((IStructuredSelection) viewer.getSelection()).getFirstElement(); if (selected instanceof IConfigurationElement) setSelectionFromConfigElement((IConfigurationElement) selected); else setSelectionFromConfigElement(null); updateUI(); } }); txtDescription.getFormText().addHyperlinkListener(new HyperlinkAdapter() { @Override public void linkActivated(HyperlinkEvent event) { IWorkbenchBrowserSupport browserSupport = PlatformUI.getWorkbench().getBrowserSupport(); try { IWebBrowser externalBrowser = browserSupport.getExternalBrowser(); externalBrowser.openURL(new URL((String) event.getHref())); } catch (PartInitException e) { logger.logError("Error opening external browser.", e); } catch (MalformedURLException e) { // Ignore } } }); updateUI(); } private void updateUI() { if (selectedElement == null) { setPageComplete(false); setMessage("Select a template", IMessageProvider.INFORMATION); } else { setPageComplete(true); setMessage(null); } } protected abstract IConfigurationElement[] loadConfigurationElements(); private void loadData() { elements = loadConfigurationElements(); Arrays.sort(elements, new CategorisedConfigurationElementComparator(true)); viewer.setInput(elements); viewer.expandAll(); } private void setSelectionFromConfigElement(IConfigurationElement element) { showTemplateDescription(element); IConfigurationElement old = this.selectedElement; this.selectedElement = element; propSupport.firePropertyChange(PROP_ELEMENT, old, element); } private void showTemplateDescription(IConfigurationElement element) { String browserText = ""; if (element != null) { browserText = "<form>No description available.</form>"; String name = element.getAttribute("name"); String htmlAttr = element.getAttribute("doc"); if (htmlAttr != null) { String bsn = element.getContributor().getName(); Bundle bundle = BundleUtils.findBundle(Plugin.getDefault().getBundleContext(), bsn, null); if (bundle != null) { URL htmlUrl = bundle.getResource(htmlAttr); if (htmlUrl == null) browserText = String.format("<form>No description for %s.</form>", name); else try { byte[] bytes = FileUtils.readFully(htmlUrl.openStream()); browserText = new String(bytes, "UTF-8"); } catch (IOException e) { logger.logError("Error reading template description document.", e); } } } } txtDescription.setText(browserText); } @Override public void setVisible(boolean visible) { super.setVisible(visible); if (visible && !shown) { shown = true; if (elements.length > 0) { setSelectionFromConfigElement(elements[0]); ISelection selection = new StructuredSelection(elements[0]); viewer.setSelection(selection); } } } @Override public boolean isPageComplete() { return shown && super.isPageComplete(); } public IConfigurationElement getSelectedElement() { return selectedElement; } public void addPropertyChangeListener(PropertyChangeListener listener) { propSupport.addPropertyChangeListener(listener); } public void removePropertyChangeListener(PropertyChangeListener listener) { propSupport.removePropertyChangeListener(listener); } public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { propSupport.addPropertyChangeListener(propertyName, listener); } public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { propSupport.removePropertyChangeListener(propertyName, listener); } }