/** * Copyright (c) 2016 committers of YAKINDU and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * Contributors: * committers of YAKINDU - initial API and implementation * */ package org.yakindu.sct.examples.wizard.pages; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.util.List; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Platform; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.ArrayContentProvider; import org.eclipse.jface.viewers.DelegatingStyledCellLabelProvider; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerFilter; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.browser.Browser; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.program.Program; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.yakindu.sct.examples.wizard.ExampleActivator; import org.yakindu.sct.examples.wizard.preferences.ExamplesPreferenceConstants; import org.yakindu.sct.examples.wizard.service.ExampleData; import org.yakindu.sct.examples.wizard.service.ExampleWizardConstants; import org.yakindu.sct.examples.wizard.service.IExampleService; import com.google.common.base.Predicate; import com.google.common.collect.Iterables; import com.google.inject.Inject; /** * * @author t00manysecretss * @author andreas muelder - Replace Image Gallery with Browser widget * */ public class SelectExamplePage extends WizardPage implements ExampleWizardConstants, ISelectionChangedListener, SelectionListener, IPropertyChangeListener { private static final String PRO_BUNDLE = "com.yakindu.sct.domain.c"; private static final String PRO_UPDATE_SITE = "https://info.itemis.com/yakindu/statecharts/pro/"; @Inject private IExampleService exampleService; private TableViewer viewer; private ExampleData selection; private Browser browser; private MessageArea messageArea; /** ID of example to be installed */ private String exampleIdToInstall; public SelectExamplePage() { super(SELECT_PAGE_TITLE); setTitle(SELECT_PAGE_TITLE); setDescription(SELECT_PAGE_DESCRIPTION); setPageComplete(false); ExampleActivator.getDefault().getPreferenceStore().addPropertyChangeListener(this); } @Override public void dispose() { ExampleActivator.getDefault().getPreferenceStore().removePropertyChangeListener(this); super.dispose(); } public void createControl(Composite parent) { Composite root = new Composite(parent, SWT.NONE); root.setLayout(new GridLayout(1, true)); createUpdateGroup(root); SashForm container = new SashForm(root, SWT.NONE); GridDataFactory.fillDefaults().grab(true, true).applyTo(container); GridLayout layout = new GridLayout(2, false); container.setLayout(layout); createTreeViewer(container); createDetailsPane(container); container.setWeights(new int[] { 1, 2 }); setControl(container); } private void createUpdateGroup(Composite root) { messageArea = new MessageArea(root); GridDataFactory.fillDefaults().grab(true, false).applyTo(messageArea); messageArea.addSelectionListener(this); messageArea.hide(); } @Override public void setVisible(boolean visible) { super.setVisible(visible); if (visible) { initAsync(); } else { viewer.setInput(null); browser.setUrl("about:blank"); } } private boolean revealExamplesAutomatically() { return (exampleIdToInstall != null) && (!exampleService.exists() || !exampleService.isUpToDate(null)); } private void initAsync() { try { getWizard().getContainer().run(true, false, new IRunnableWithProgress() { @Override public void run(final IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { init(monitor); } }); if (revealExamplesAutomatically()) { Display.getCurrent().asyncExec(new Runnable() { @Override public void run() { messageArea.button.setEnabled(false); revealExamples(); } }); } } catch (InvocationTargetException | InterruptedException e) { e.printStackTrace(); } } private void init(final IProgressMonitor monitor) { if (!exampleService.exists()) { Display.getDefault().syncExec(new Runnable() { @Override public void run() { messageArea.showDownload(); messageArea.getParent().layout(true); } }); } else if (!exampleService.isUpToDate(monitor)) { Display.getDefault().syncExec(new Runnable() { @Override public void run() { setInput(monitor); messageArea.showUpdate(); messageArea.getParent().layout(true); } }); } else { Display.getDefault().syncExec(new Runnable() { @Override public void run() { setInput(monitor); } }); } } protected void setInput(final IProgressMonitor monitor) { final List<ExampleData> input = exampleService.getExamples(new NullProgressMonitor()); messageArea.hide(); viewer.setInput(input); // explicit layouting required for Unix systems viewer.getControl().getParent().getParent().layout(true); filterAndSelectExampleToInstall(viewer, input); } protected void filterAndSelectExampleToInstall(TableViewer viewer, List<ExampleData> input) { final ExampleData exampleToInstall = Iterables.find(input, new Predicate<ExampleData>() { @Override public boolean apply(ExampleData input) { if (exampleIdToInstall != null) { return exampleIdToInstall.equals(input.getId()); } return true; } }); if (exampleToInstall != null) { viewer.addFilter(new ViewerFilter() { @Override public boolean select(Viewer viewer, Object parentElement, Object element) { if (exampleIdToInstall == null) { return true; } if (element instanceof ExampleData) { return exampleIdToInstall.equals(((ExampleData) element).getId()); } if (element instanceof ExampleContentProvider.Category) { return ((ExampleContentProvider.Category) element).getChildren().contains(exampleToInstall); } return true; } }); viewer.setSelection(new StructuredSelection(exampleToInstall), true); } } protected void createTreeViewer(Composite container) { viewer = new TableViewer(container, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL | SWT.SINGLE); GridDataFactory.fillDefaults().grab(true, true).applyTo(viewer.getControl()); viewer.setContentProvider(new ArrayContentProvider()); viewer.setLabelProvider(new DelegatingStyledCellLabelProvider(new ExampleLabelProvider())); viewer.addSelectionChangedListener(this); } protected void updateSelection(ExampleData data) { selection = data; setDetailPaneContent(data); setPageComplete(true); setErrorMessage(null); checkInstalledPlugins(data); viewer.refresh(); } private void checkInstalledPlugins(ExampleData data) { if (data.isProfessional() && Platform.getBundle(PRO_BUNDLE) == null) { messageArea.showProInstall(); } else { messageArea.hide(); } messageArea.getParent().layout(true); this.getControl().update(); } protected void setDetailPaneContent(ExampleData exampleData) { String url = exampleData.getProjectDir().getAbsolutePath() + File.separator + "index.html"; browser.setUrl(url); } protected void createDetailsPane(Composite parent) { final Composite composite = new Composite(parent, SWT.BORDER); composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); composite.setLayout(new FillLayout()); browser = new Browser(composite, SWT.NONE); } public ExampleData getSelection() { return selection; } @Override public void selectionChanged(SelectionChangedEvent event) { Object firstElement = ((StructuredSelection) event.getSelection()).getFirstElement(); if (firstElement instanceof ExampleData) updateSelection((ExampleData) firstElement); } @Override public void widgetSelected(SelectionEvent e) { switch (messageArea.getState()) { case DOWNLOAD: case UPDATE: revealExamples(); break; case INSTALL: Program.launch(PRO_UPDATE_SITE); break; default: break; } } protected void revealExamples() { try { getWizard().getContainer().run(true, true, new IRunnableWithProgress() { @Override public void run(final IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { final IStatus status = exampleService.fetchAllExamples(monitor); Display.getDefault().asyncExec(new Runnable() { @Override public void run() { if (status.isOK()) { SelectExamplePage.this.setInput(monitor); } else { messageArea.showError(); } } }); } }); } catch (InvocationTargetException | InterruptedException e1) { e1.printStackTrace(); } } @Override public void widgetDefaultSelected(SelectionEvent e) { widgetSelected(e); } @Override public void propertyChange(PropertyChangeEvent event) { if (ExamplesPreferenceConstants.STORAGE_LOCATION.equals(event.getProperty())) { initAsync(); } } public void setInstallExampleId(String exampleId) { this.exampleIdToInstall = exampleId; } }