| /*=============================================================================# |
| # Copyright (c) 2007, 2018 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.internal.redocs.tex.r.ui.processing; |
| |
| import java.util.List; |
| |
| import org.eclipse.core.databinding.DataBindingContext; |
| import org.eclipse.core.databinding.UpdateValueStrategy; |
| import org.eclipse.core.databinding.observable.ChangeEvent; |
| import org.eclipse.core.databinding.observable.Diffs; |
| import org.eclipse.core.databinding.observable.Realm; |
| import org.eclipse.core.databinding.observable.value.AbstractObservableValue; |
| import org.eclipse.core.databinding.observable.value.IObservableValue; |
| import org.eclipse.core.databinding.observable.value.WritableValue; |
| import org.eclipse.core.databinding.validation.IValidator; |
| import org.eclipse.core.databinding.validation.ValidationStatus; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.debug.core.DebugPlugin; |
| import org.eclipse.debug.core.ILaunchConfiguration; |
| import org.eclipse.debug.core.ILaunchConfigurationListener; |
| import org.eclipse.debug.core.ILaunchConfigurationType; |
| import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy; |
| import org.eclipse.debug.core.ILaunchManager; |
| import org.eclipse.debug.ui.EnvironmentTab; |
| import org.eclipse.debug.ui.ILaunchConfigurationTab; |
| import org.eclipse.jface.text.DocumentEvent; |
| import org.eclipse.jface.text.IDocumentListener; |
| import org.eclipse.jface.viewers.ArrayContentProvider; |
| import org.eclipse.jface.viewers.ISelectionChangedListener; |
| import org.eclipse.jface.viewers.LabelProvider; |
| import org.eclipse.jface.viewers.SelectionChangedEvent; |
| import org.eclipse.jface.viewers.StructuredSelection; |
| import org.eclipse.jface.viewers.TableViewer; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.events.SelectionAdapter; |
| import org.eclipse.swt.events.SelectionEvent; |
| import org.eclipse.swt.events.SelectionListener; |
| import org.eclipse.swt.graphics.Image; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Button; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Display; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.texlipse.Texlipse; |
| import org.eclipse.texlipse.viewer.TexLaunchConfigurationDelegate; |
| import org.eclipse.texlipse.viewer.TexLaunchConfigurationTab; |
| import org.eclipse.texlipse.viewer.ViewerConfiguration; |
| import org.eclipse.ui.statushandlers.StatusManager; |
| |
| import org.eclipse.statet.ecommons.debug.ui.config.LaunchConfigTabWithDbc; |
| import org.eclipse.statet.ecommons.ui.util.LayoutUtil; |
| import org.eclipse.statet.ecommons.ui.util.UIAccess; |
| |
| import org.eclipse.statet.docmlet.base.ui.DocBaseUIResources; |
| import org.eclipse.statet.redocs.tex.r.ui.TexRweaveUI; |
| |
| |
| public class PreviewTab extends LaunchConfigTabWithDbc { |
| |
| |
| public static final String NS= "org.eclipse.statet.r.debug/DocPreview/"; //$NON-NLS-1$ |
| public static final String ATTR_VIEWER_CODE= NS + "Viewer.code"; //$NON-NLS-1$ |
| |
| |
| private class SelectionObservable extends AbstractObservableValue implements SelectionListener, ISelectionChangedListener, IDocumentListener, IValidator { |
| |
| private String encodedValue; |
| private IStatus currentStatus; |
| |
| |
| public SelectionObservable() { |
| this.currentStatus= ValidationStatus.ok(); |
| } |
| |
| |
| @Override |
| public Object getValueType() { |
| return String.class; |
| } |
| |
| @Override |
| protected void doSetValue(final Object value) { |
| if (value instanceof String) { |
| final String s= (String) value; |
| this.encodedValue= s; |
| if (s.startsWith(TexRweaveLaunchDelegate.PREVIEW_IDE)) { |
| updateEnablement(TexRweaveLaunchDelegate.PREVIEW_IDE); |
| this.currentStatus= ValidationStatus.ok(); |
| return; |
| } |
| else if (s.startsWith(TexRweaveLaunchDelegate.PREVIEW_SPECIAL)) { |
| updateEnablement(TexRweaveLaunchDelegate.PREVIEW_SPECIAL); |
| |
| final String[] split= s.split(":", 2); //$NON-NLS-1$ |
| if (split.length == 2 && split[1].length() > 0) { |
| final List<ViewerConfiguration> configs= PreviewTab.this.availablePreviewConfigs; |
| for (final ViewerConfiguration config : configs) { |
| if (config.getName().equals(split[1])) { |
| PreviewTab.this.launchConfigTable.setSelection(new StructuredSelection(config)); |
| this.currentStatus= ValidationStatus.ok(); |
| return; |
| } |
| } |
| } |
| PreviewTab.this.launchConfigTable.setSelection(new StructuredSelection()); |
| this.currentStatus= ValidationStatus.warning(Messages.PreviewTab_LaunchConfig_error_NoConfigSelected_message); |
| return; |
| } |
| } |
| |
| this.currentStatus= ValidationStatus.ok(); |
| updateEnablement(null); |
| } |
| |
| @Override |
| protected Object doGetValue() { |
| return this.encodedValue; |
| } |
| |
| @Override |
| public void widgetDefaultSelected(final SelectionEvent e) { |
| } |
| |
| @Override |
| public void widgetSelected(final SelectionEvent e) { |
| if (!isInitializing()) { |
| updateValue(); |
| } |
| } |
| |
| @Override |
| public void selectionChanged(final SelectionChangedEvent event) { |
| if (!isInitializing()) { |
| updateValue(); |
| } |
| } |
| |
| @Override |
| public void documentAboutToBeChanged(final DocumentEvent event) { |
| } |
| |
| @Override |
| public void documentChanged(final DocumentEvent event) { |
| if (!isInitializing()) { |
| updateValue(); |
| } |
| } |
| |
| private void updateValue() { |
| String value; |
| if (PreviewTab.this.systemSelectControl.getSelection()) { |
| value= TexRweaveLaunchDelegate.PREVIEW_IDE; |
| this.currentStatus= ValidationStatus.ok(); |
| updateEnablement(TexRweaveLaunchDelegate.PREVIEW_IDE); |
| } |
| else if (PreviewTab.this.launchConfigSelectControl.getSelection()) { |
| final Object selectedLaunch= ((StructuredSelection) PreviewTab.this.launchConfigTable.getSelection()).getFirstElement(); |
| value= TexRweaveLaunchDelegate.PREVIEW_SPECIAL; |
| if (selectedLaunch instanceof ViewerConfiguration) { |
| value += ':'+((ViewerConfiguration) selectedLaunch).getName(); |
| this.currentStatus= ValidationStatus.ok(); |
| } |
| else { |
| this.currentStatus= ValidationStatus.warning(Messages.PreviewTab_LaunchConfig_error_NoConfigSelected_message); |
| } |
| updateEnablement(TexRweaveLaunchDelegate.PREVIEW_SPECIAL); |
| } |
| else { |
| value= ""; //$NON-NLS-1$ |
| this.currentStatus= ValidationStatus.ok(); |
| updateEnablement(null); |
| } |
| if (!value.equals(this.encodedValue)) { |
| final String oldValue= this.encodedValue; |
| this.encodedValue= value; |
| fireValueChange(Diffs.createValueDiff(oldValue, value)); |
| } |
| } |
| |
| @Override |
| public IStatus validate(final Object value) { |
| return this.currentStatus; |
| } |
| |
| public void updateEnablement(final String selection) { |
| PreviewTab.this.disableSelectControl.setSelection(selection == null); |
| PreviewTab.this.systemSelectControl.setSelection(selection == TexRweaveLaunchDelegate.PREVIEW_IDE); |
| PreviewTab.this.launchConfigSelectControl.setSelection(selection == TexRweaveLaunchDelegate.PREVIEW_SPECIAL); |
| |
| PreviewTab.this.launchConfigTable.getControl().setEnabled(selection == TexRweaveLaunchDelegate.PREVIEW_SPECIAL); |
| PreviewTab.this.launchConfigNewButton.setEnabled(selection == TexRweaveLaunchDelegate.PREVIEW_SPECIAL); |
| } |
| |
| } |
| |
| |
| private List<ViewerConfiguration> availablePreviewConfigs; |
| private final IObservableValue<String> selectionValue; |
| |
| private ILaunchConfigurationListener launchConfigurationListener; |
| private Button disableSelectControl; |
| private Button systemSelectControl; |
| private Button launchConfigSelectControl; |
| private TableViewer launchConfigTable; |
| private Button launchConfigNewButton; |
| |
| private String outputFormat; |
| private TexTab texTab; |
| private SelectionObservable selectionObservable; |
| |
| |
| public PreviewTab() { |
| final Realm realm= getRealm(); |
| this.selectionValue= new WritableValue<>(realm, null, String.class); |
| } |
| |
| @Override |
| public String getName() { |
| return Messages.Processing_PreviewTab_label; |
| } |
| |
| @Override |
| public Image getImage() { |
| return DocBaseUIResources.INSTANCE.getImage(DocBaseUIResources.TOOL_PREVIEW_IMAGE_ID); |
| } |
| |
| |
| @Override |
| public void createControl(final Composite parent) { |
| final Composite mainComposite= new Composite(parent, SWT.NONE); |
| setControl(mainComposite); |
| mainComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); |
| mainComposite.setLayout(new GridLayout()); |
| |
| final Label label= new Label(mainComposite, SWT.NONE); |
| label.setText(Messages.PreviewTab_label); |
| label.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false)); |
| |
| LayoutUtil.addSmallFiller(mainComposite, false); |
| |
| Composite composite; |
| composite= new Composite(mainComposite, SWT.NONE); |
| composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); |
| createOptions(composite); |
| |
| this.launchConfigurationListener= new ILaunchConfigurationListener() { |
| @Override |
| public void launchConfigurationAdded(final ILaunchConfiguration configuration) { |
| updateAvailableConfigs(); |
| } |
| @Override |
| public void launchConfigurationChanged(final ILaunchConfiguration configuration) { |
| updateAvailableConfigs(); |
| } |
| @Override |
| public void launchConfigurationRemoved(final ILaunchConfiguration configuration) { |
| updateAvailableConfigs(); |
| } |
| }; |
| DebugPlugin.getDefault().getLaunchManager().addLaunchConfigurationListener(this.launchConfigurationListener); |
| |
| initBindings(); |
| } |
| |
| private void createOptions(final Composite group) { |
| GridData gd; |
| group.setLayout(LayoutUtil.createCompositeGrid(2)); |
| |
| this.disableSelectControl= new Button(group, SWT.RADIO); |
| this.disableSelectControl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1)); |
| this.disableSelectControl.setText(Messages.PreviewTab_Disable_label); |
| |
| LayoutUtil.addSmallFiller(group, false); |
| |
| this.systemSelectControl= new Button(group, SWT.RADIO); |
| this.systemSelectControl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1)); |
| this.systemSelectControl.setText(Messages.PreviewTab_SystemEditor_label); |
| |
| LayoutUtil.addSmallFiller(group, false); |
| |
| this.launchConfigSelectControl= new Button(group, SWT.RADIO); |
| this.launchConfigSelectControl.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1)); |
| this.launchConfigSelectControl.setText(Messages.PreviewTab_LaunchConfig_label); |
| |
| this.launchConfigTable= new TableViewer(group, SWT.SINGLE | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.FULL_SELECTION); |
| gd= new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1); |
| gd.horizontalIndent= LayoutUtil.defaultIndent(); |
| gd.heightHint= LayoutUtil.hintHeight(this.launchConfigTable.getTable(), 5); |
| this.launchConfigTable.getControl().setLayoutData(gd); |
| this.launchConfigTable.setLabelProvider(new LabelProvider() { |
| @Override |
| public String getText(final Object element) { |
| if (element instanceof ViewerConfiguration) { |
| return ((ViewerConfiguration) element).getName(); |
| } |
| return super.getText(element); |
| } |
| }); |
| this.launchConfigTable.setContentProvider(new ArrayContentProvider()); |
| this.launchConfigTable.setInput(new Object()); |
| |
| this.launchConfigNewButton= new Button(group, SWT.PUSH); |
| this.launchConfigNewButton.setText(Messages.PreviewTab_LaunchConfig_NewConfig_label); |
| gd= new GridData(SWT.FILL, SWT.TOP, false, false); |
| gd.widthHint= LayoutUtil.hintWidth(this.launchConfigNewButton); |
| this.launchConfigNewButton.setLayoutData(gd); |
| this.launchConfigNewButton.addSelectionListener(new SelectionAdapter() { |
| @Override |
| public void widgetSelected(final SelectionEvent e) { |
| createNewPreviewLaunchConfig(); |
| } |
| |
| }); |
| } |
| |
| |
| private final Runnable fUpdateConfigsRunnable= new Runnable() { |
| @Override |
| public void run() { |
| PreviewTab.this.fUpdateConfigsScheduled= false; |
| if (PreviewTab.this.texTab == null) { |
| final ILaunchConfigurationTab[] tabs= getLaunchConfigurationDialog().getTabs(); |
| for (int i= 0; i < tabs.length; i++) { |
| if (tabs[i] instanceof TexTab) { |
| PreviewTab.this.texTab= (TexTab) tabs[i]; |
| } |
| } |
| if (PreviewTab.this.texTab == null) { |
| return; |
| } |
| if (!PreviewTab.this.texTab.addOutputFormatListener( |
| (final ChangeEvent event) -> updateAvailableConfigs() )) { |
| PreviewTab.this.texTab= null; |
| return; |
| } |
| } |
| PreviewTab.this.outputFormat= PreviewTab.this.texTab.getOutputFormat(); |
| PreviewTab.this.availablePreviewConfigs= Texlipse.getViewerManager().getAvailableConfigurations(PreviewTab.this.outputFormat); |
| if (UIAccess.isOkToUse(PreviewTab.this.launchConfigTable)) { |
| PreviewTab.this.launchConfigTable.setInput(PreviewTab.this.availablePreviewConfigs); |
| if (PreviewTab.this.selectionObservable != null) { |
| PreviewTab.this.selectionObservable.updateValue(); |
| } |
| } |
| } |
| }; |
| private volatile boolean fUpdateConfigsScheduled; |
| |
| private void updateAvailableConfigs() { |
| final Display display= UIAccess.getDisplay(); |
| if (display.getThread() == Thread.currentThread()) { |
| this.fUpdateConfigsRunnable.run(); |
| } |
| else if (!this.fUpdateConfigsScheduled) { |
| this.fUpdateConfigsScheduled= true; |
| display.asyncExec(this.fUpdateConfigsRunnable); |
| } |
| } |
| |
| private void createNewPreviewLaunchConfig() { |
| try { |
| final ILaunchManager launchManager= DebugPlugin.getDefault().getLaunchManager(); |
| final ILaunchConfigurationType type= launchManager.getLaunchConfigurationType(TexLaunchConfigurationDelegate.CONFIGURATION_ID); |
| final String name= getLaunchConfigurationDialog().generateName(NLS.bind(Messages.PreviewTab_LaunchConfig_NewConfig_seed, this.outputFormat.toUpperCase())); |
| final ILaunchConfigurationWorkingCopy config= type.newInstance(null, name); |
| new EnvironmentTab().setDefaults(config); |
| new TexLaunchConfigurationTab().setDefaults(config); |
| |
| this.selectionValue.setValue(TexRweaveLaunchDelegate.PREVIEW_SPECIAL+':'+name); |
| setDirty(true); |
| |
| config.doSave(); |
| } |
| catch (final CoreException e) { |
| StatusManager.getManager().handle(new Status(IStatus.ERROR, TexRweaveUI.BUNDLE_ID, 0, |
| Messages.PreviewTab_LaunchConfig_NewConfig_error_Creating_message, e), StatusManager.LOG | StatusManager.SHOW); |
| } |
| } |
| |
| @Override |
| protected void addBindings(final DataBindingContext dbc, final Realm realm) { |
| this.selectionObservable= new SelectionObservable(); |
| this.disableSelectControl.addSelectionListener(this.selectionObservable); |
| this.systemSelectControl.addSelectionListener(this.selectionObservable); |
| this.launchConfigSelectControl.addSelectionListener(this.selectionObservable); |
| this.launchConfigTable.addSelectionChangedListener(this.selectionObservable); |
| this.selectionValue.setValue("init"); //$NON-NLS-1$ |
| |
| dbc.bindValue(this.selectionObservable, this.selectionValue, new UpdateValueStrategy().setAfterGetValidator(this.selectionObservable), null); |
| } |
| |
| |
| @Override |
| public void setDefaults(final ILaunchConfigurationWorkingCopy configuration) { |
| configuration.setAttribute(ATTR_VIEWER_CODE, TexRweaveLaunchDelegate.PREVIEW_IDE); |
| } |
| |
| @Override |
| protected void doInitialize(final ILaunchConfiguration configuration) { |
| updateAvailableConfigs(); |
| |
| String value= null; |
| try { |
| value= configuration.getAttribute(ATTR_VIEWER_CODE, ""); //$NON-NLS-1$ |
| } catch (final CoreException e) { |
| logReadingError(e); |
| } |
| final Object firstConfig= this.launchConfigTable.getElementAt(0); |
| this.launchConfigTable.setSelection((firstConfig != null) ? new StructuredSelection(firstConfig) : new StructuredSelection()); |
| this.selectionValue.setValue(value); |
| } |
| |
| @Override |
| protected void doSave(final ILaunchConfigurationWorkingCopy configuration) { |
| configuration.setAttribute(ATTR_VIEWER_CODE, this.selectionValue.getValue()); |
| } |
| |
| @Override |
| public void dispose() { |
| if (this.launchConfigurationListener != null) { |
| DebugPlugin.getDefault().getLaunchManager().removeLaunchConfigurationListener(this.launchConfigurationListener); |
| this.launchConfigurationListener= null; |
| } |
| super.dispose(); |
| } |
| |
| } |