/* * Carrot2 project. * * Copyright (C) 2002-2016, Dawid Weiss, Stanisław Osiński. * All rights reserved. * * Refer to the full license file "carrot2.LICENSE" * in the root folder of the repository checkout or at: * http://www.carrot2.org/carrot2.LICENSE */ package org.carrot2.workbench.editors.impl; import java.net.MalformedURLException; import java.net.URL; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; import java.util.Map; import org.apache.commons.lang.ObjectUtils; import org.carrot2.shaded.guava.common.collect.Lists; import org.carrot2.util.attribute.constraint.ResourceNameFilter; import org.carrot2.util.attribute.constraint.ResourceNameFilters; import org.carrot2.util.resource.FileResource; import org.carrot2.util.resource.IResource; import org.carrot2.util.resource.URLResource; import org.carrot2.util.resource.URLResourceWithParams; import org.carrot2.workbench.core.helpers.DisposeBin; import org.carrot2.workbench.core.helpers.GUIFactory; import org.carrot2.workbench.editors.AttributeEditorAdapter; import org.carrot2.workbench.editors.AttributeEditorInfo; import org.carrot2.workbench.editors.AttributeEvent; import org.eclipse.jface.dialogs.IDialogConstants; import org.eclipse.jface.dialogs.IInputValidator; import org.eclipse.jface.dialogs.InputDialog; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; 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.FileDialog; import org.eclipse.swt.widgets.Text; /** * Editor for attributes that are of {@link IResource} type. */ public class ResourceEditor extends AttributeEditorAdapter { /* * Disposal of resources. */ private DisposeBin disposeBin = new DisposeBin(); /** * Resource information string. */ private Text resourceInfo; /** * The actual resource (most recent valid value or <code>null</code>). */ private IResource resource = null; /** * Resource name filters. */ private ResourceNameFilter [] filters; /* * Validator for URIs. */ private final static IInputValidator validatorURI = new IInputValidator() { public String isValid(String text) { try { URL validURI = new URL(text); if (validURI.getProtocol() == null) { throw new MalformedURLException("Empty scheme."); } } catch (MalformedURLException e) { return "Not a valid URL"; } return null; } }; /* * */ @Override protected AttributeEditorInfo init(Map<String,Object> defaultValues) { if (descriptor.getAnnotation(ResourceNameFilters.class) != null) { filters = descriptor.getAnnotation(ResourceNameFilters.class).filters(); } return new AttributeEditorInfo(1, false); } /* * */ @Override public void createEditor(Composite parent, int gridColumns) { final Composite holder = new Composite(parent, SWT.NONE); holder.setLayoutData(GUIFactory.editorGridData().grab(true, false).span( gridColumns, 1).create()); GridLayout gl = GUIFactory.zeroMarginGridLayout(); gl.numColumns = 4; gl.horizontalSpacing = 3; holder.setLayout(gl); createTextBox(holder); createFileButton(holder); createUrlButton(holder); createClearButton(holder); } /* * */ private void createTextBox(Composite holder) { this.resourceInfo = new Text(holder, SWT.READ_ONLY | SWT.NO_FOCUS | SWT.BORDER | SWT.SINGLE); final GridData gd = GridDataFactory.fillDefaults().grab(true, false).hint(100, SWT.DEFAULT).align(SWT.FILL, SWT.CENTER).create(); resourceInfo.setLayoutData(gd); } /* * */ private void createClearButton(Composite holder) { final Image image = EditorsPlugin.getImageDescriptor("icons/clear.png").createImage(); disposeBin.add(image); final Button button = new Button(holder, SWT.PUSH | SWT.CENTER); button.setImage(image); button.setLayoutData(GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER) .create()); button.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { setValue(null); } }); } /* * */ private void createFileButton(Composite holder) { final Image image = EditorsPlugin.getImageDescriptor("icons/open_folder.png") .createImage(); disposeBin.add(image); final Button button = new Button(holder, SWT.PUSH | SWT.CENTER); button.setImage(image); button.setLayoutData(GridDataFactory.fillDefaults().align(SWT.CENTER, SWT.CENTER) .create()); button.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { openFileResourceDialog(); } }); } /* * */ private void openFileResourceDialog() { final FileDialog dialog = new FileDialog(this.resourceInfo.getShell()); java.util.List<String> patterns = Lists.newArrayList(); java.util.List<String> names = Lists.newArrayList(); if (filters != null) { for (ResourceNameFilter f : filters) { patterns.add(f.pattern()); names.add(f.description()); } } else { // Backwards compatibility. patterns.addAll(Arrays.asList("*.xml;*.XML", "*.*")); names.addAll(Arrays.asList("XML files", "All")); } dialog.setFilterExtensions(patterns.toArray(new String [patterns.size()])); dialog.setFilterNames(names.toArray(new String [names.size()])); if (this.resource != null && resource instanceof FileResource) { dialog.setFileName(((FileResource) resource).getPath().toString()); } else { // In case we can't restore last file, refer to global last key. dialog.setFileName(EditorsPlugin.getDefault().getPreferenceStore().getString( EditorsPluginConstants.PREF_LAST_SELECTED_FILE)); } final String path = dialog.open(); if (path != null) { Path p = Paths.get(path); EditorsPlugin.getDefault().getPreferenceStore().setValue( EditorsPluginConstants.PREF_LAST_SELECTED_FILE, p.toAbsolutePath().toString()); setValue(new FileResource(p)); } } /* * */ private void createUrlButton(Composite holder) { final Image image = EditorsPlugin.getImageDescriptor("icons/open_url.png") .createImage(); disposeBin.add(image); final Button button = new Button(holder, SWT.PUSH | SWT.CENTER); button.setImage(image); button.setLayoutData(GridDataFactory.fillDefaults().create()); button.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { openURLResourceDialog(); } }); } /* * */ private void openURLResourceDialog() { String previous = ""; if (resource != null && resource instanceof URLResource) { previous = ((URLResource) resource).getUrl().toExternalForm(); } if (resource != null && resource instanceof URLResourceWithParams) { previous = ((URLResourceWithParams) resource).getUrl().toExternalForm(); } final InputDialog dialog = new InputDialog(resourceInfo.getShell(), "Enter resource URL", "Enter resource URL", previous, validatorURI); if (dialog.open() == IDialogConstants.OK_ID) { try { setValue(new URLResourceWithParams(new URL(dialog.getValue()))); } catch (MalformedURLException e) { // Simply skip, shouldn't happen. } } } /* * */ @Override public void setValue(Object newValue) { if (ObjectUtils.equals(newValue, resource)) { return; } if (newValue != null && !(newValue instanceof IResource)) { return; } this.resource = (IResource) newValue; this.resourceInfo.setText(resource == null ? "" : resource.toString()); fireAttributeChanged(new AttributeEvent(this)); } /* * */ @Override public Object getValue() { return resource; } /* * */ @Override public void dispose() { disposeBin.dispose(); } }