/* uDig - User Friendly Desktop Internet GIS client
* http://udig.refractions.net
* (C) 2012, Refractions Research Inc.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* (http://www.eclipse.org/legal/epl-v10.html), and the Refractions BSD
* License v1.0 (http://udig.refractions.net/files/bsd3-v10.html).
*/
package org.locationtech.udig.document.ui;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import net.miginfocom.swt.MigLayout;
import org.locationtech.udig.catalog.document.IDocument;
import org.locationtech.udig.catalog.document.IDocument.ContentType;
import org.locationtech.udig.catalog.document.IDocument.Type;
import org.locationtech.udig.catalog.document.IDocumentSource.DocumentInfo;
import org.locationtech.udig.catalog.document.IHotlinkSource.HotlinkDescriptor;
import org.locationtech.udig.tool.info.internal.Messages;
import org.apache.commons.io.FileUtils;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.IconAndMessageDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.jface.fieldassist.FieldDecoration;
import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.ISelection;
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.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.program.Program;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ListDialog;
/**
* Dialog window to add or edit documents from the {@link DocumentView}.
*
* @author Naz Chan
*/
public class DocumentDialog extends IconAndMessageDialog {
private Composite composite;
private Label headerImg;
private Label headerText;
private Label subHeaderText;
private Label infoLbl;
private Text info;
private ControlDecoration infoDecoration;
private Composite infoBtnComposite;
private Button infoOpenBtn;
private Button infoBrowseBtn;
private Button infoNewBtn;
private Label infoGoActionLbl;
private ComboViewer infoGoAction;
private Button infoGoActionBtn;
private Label attributeLbl;
private Text attribute;
private Text document;
private ComboViewer type;
private Button templateCheckBtn;
private Label labelLbl;
private Text label;
private Text description;
private Properties templateProps;
/**
* Dialog form values.
*/
private Map<String, Object> values;
/**
* Document information (either absolute filepath or url string or action) value.
*/
public static final String V_INFO = "V_INFO"; //$NON-NLS-1$
/**
* Document content type value. Refer to {@link ContentType}.
*/
public static final String V_CONTENT_TYPE = "V_CONTENT_TYPE"; //$NON-NLS-1$
/**
* Document label value.
*/
public static final String V_LABEL = "V_LABEL"; //$NON-NLS-1$
/**
* Document description value.
*/
public static final String V_DESCRIPTION = "V_DESCRIPTION"; //$NON-NLS-1$
/**
* Document attribute value. This is required for {@link Type#HOTLINK} types.
*/
public static final String V_ATTRIBUTE = "V_ATTRIBUTE"; //$NON-NLS-1$
/**
* Document "is template" value. This is required for {@link ContentType#FILE} types.
*/
public static final String V_TEMPLATE = "V_TEMPLATE"; //$NON-NLS-1$
/**
* Document actions value. This is required for {@link Type#HOTLINK} with {@link ContentType#ACTION} types.
*/
public static final String V_ACTIONS = "V_ACTIONS"; //$NON-NLS-1$
/**
* Dialog configuration parameters.
*/
private Map<String, Object> params;
/**
* Dialog mode parameter. Refer to {@link Mode}. This is required.
*/
public static final String P_MODE = "P_MODE"; //$NON-NLS-1$
/**
* Document type parameter. Refer to {@link Type}. This is required.
*/
public static final String P_TYPE = "P_TYPE"; //$NON-NLS-1$
/**
* Document content type allowed options parameter. Refer to {@link ContentType}. This may be
* null and the default content type options (depending on the document type) will be used.
*/
public static final String P_CONTENT_TYPES = "P_CONTENT_TYPES"; //$NON-NLS-1$
/**
* Feature name parameter. A string value used for header display. This may be null for layer level documents.
*/
public static final String P_FEATURE_NAME = "P_FEATURE_NAME"; //$NON-NLS-1$
/**
* Resource name parameter. A string value used for header display. This is required.
*/
public static final String P_RESOURCE_NAME = "P_RESOURCE_NAME"; //$NON-NLS-1$
/**
* Templates parameter. A list of {@link IDocument} used to populate template options. This may
* be null if there are no templates.
*/
public static final String P_TEMPLATES = "P_TEMPLATES"; //$NON-NLS-1$
private boolean hasError = false;
private ContentType typeValue;
/**
* Dialog modes.
*/
public enum Mode {
/**
* Add mode. For adding a new document.
*/
ADD,
/**
* Edit mode. For editing an existing document.
*/
EDIT;
}
private Mode mode;
private Type docType;
public static final String LABEL_FORMAT = "%s%s:"; //$NON-NLS-1$
public static final String MANDATORY = "*"; //$NON-NLS-1$
/**
* Constructor for edit mode with initial values and option to only allow info editing.
*
* @param parentShell
* @param values
* @param isInfoOnly
*/
public DocumentDialog(Shell parentShell, Map<String, Object> values, Map<String, Object> params) {
super(parentShell);
this.values = values;
this.params = params;
}
@Override
protected boolean isResizable() {
return true;
}
public Map<String, Object> getValues() {
return values;
}
public String getInfo() {
return (String) values.get(V_INFO);
}
public ContentType getType() {
return (ContentType) values.get(V_CONTENT_TYPE);
}
public String getLabel() {
return (String) values.get(V_LABEL);
}
public String getDescription() {
return (String) values.get(V_DESCRIPTION);
}
private String getAttribute() {
return (String) values.get(V_ATTRIBUTE);
}
public boolean isTemplate() {
final Object isTemplateObj = values.get(V_TEMPLATE);
if (isTemplateObj != null) {
return (Boolean) isTemplateObj;
}
return false;
}
@SuppressWarnings("unchecked")
private List<HotlinkDescriptor> getActions() {
return (List<HotlinkDescriptor>) values.get(V_ACTIONS);
}
private Type getParamType() {
if (docType == null) {
final Type paramDocType = (Type) params.get(P_TYPE);
if (paramDocType != null) {
docType = paramDocType;
}
}
return docType;
}
@SuppressWarnings("unchecked")
private List<ContentType> getParamContentTypes() {
return (List<ContentType>) params.get(P_CONTENT_TYPES);
}
private boolean isLinked() {
return Type.LINKED == getParamType();
}
private boolean isAttachment() {
return Type.ATTACHMENT == getParamType();
}
private boolean isHotlink() {
return Type.HOTLINK == getParamType();
}
private Mode getParamMode() {
if (mode == null) {
final Mode paramMode = (Mode) params.get(P_MODE);
if (paramMode != null) {
mode = paramMode;
}
}
return mode;
}
private boolean isAddMode() {
return Mode.ADD == getParamMode();
}
private boolean isEditMode() {
return Mode.EDIT == getParamMode();
}
private String getParamFeatureName() {
return (String) params.get(P_FEATURE_NAME);
}
private String getParamResourceName() {
return (String) params.get(P_RESOURCE_NAME);
}
@SuppressWarnings("unchecked")
private List<IDocument> getParamTemplates() {
return (List<IDocument>) params.get(P_TEMPLATES);
}
@Override
protected Image getImage() {
return getInfoImage();
}
@Override
protected void configureShell(Shell shell) {
final int HEIGHT = 380;
final int WIDTH = 460;
final Display display = PlatformUI.getWorkbench().getDisplay();
final Point size = (new Shell(display)).computeSize(-1, -1);
final Rectangle screen = display.getMonitors()[0].getBounds();
final int xPos = (screen.width - size.x) / 2 - WIDTH / 2;
final int yPos = (screen.height - size.y) / 2 - HEIGHT / 2;
shell.setBounds(xPos, yPos, WIDTH, HEIGHT);
super.configureShell(shell);
}
private static final String LABEL_WIDTH = "20%"; //$NON-NLS-1$
private static final String CONTROL_WIDTH = "80%"; //$NON-NLS-1$
private static final String LAYOUT_FORMAT = "[%s, right]8[%s]"; //$NON-NLS-1$
private static final String WIDTH_LAYOUT_FORMAT = "w %s!"; //$NON-NLS-1$
@Override
protected void createButtonsForButtonBar(Composite parent) {
super.createButtonsForButtonBar(parent);
if (isAddMode()) {
final Button okBtn = getButton(IDialogConstants.OK_ID);
if (isAttachment()) {
okBtn.setText(Messages.DocumentDialog_btnAttach);
} else if (isLinked()) {
okBtn.setText(Messages.DocumentDialog_btnLink);
}
}
}
@Override
protected Control createDialogArea(Composite parent) {
composite = new Composite(parent, SWT.NONE);
final String layoutCons = "insets 0, fillx, wrap 2, hidemode 3"; //$NON-NLS-1$
final String columnCons = String.format(LAYOUT_FORMAT, LABEL_WIDTH, CONTROL_WIDTH);
final String rowCons = "[][]15[][][]"; //$NON-NLS-1$
composite.setLayout(new MigLayout(layoutCons, columnCons, rowCons));
composite.setLayoutData(new GridData(GridData.FILL_BOTH));
createHeader();
configHeaderDisplay();
createTypeControls();
createInfoControls();
createInfoBtnControls();
createInfoGoActionControls();
attributeLbl = new Label(composite, SWT.NONE);
attributeLbl.setText(getLabel(Messages.DocumentDialog_attributeLabel));
attributeLbl.setLayoutData(""); //$NON-NLS-1$
attribute = new Text(composite, SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY);
attribute.setLayoutData(String.format(WIDTH_LAYOUT_FORMAT, CONTROL_WIDTH));
final Label documentLbl = new Label(composite, SWT.NONE);
documentLbl.setText(getLabel(Messages.DocumentDialog_documentLabel));
documentLbl.setLayoutData(""); //$NON-NLS-1$
documentLbl.setVisible(false); //Re: Brett's review comment
document = new Text(composite, SWT.SINGLE | SWT.BORDER | SWT.READ_ONLY);
document.setLayoutData(String.format(WIDTH_LAYOUT_FORMAT, CONTROL_WIDTH));
document.setVisible(false); //Re: Brett's review comment
templateCheckBtn = new Button(composite, SWT.CHECK);
templateCheckBtn.setText(Messages.DocumentDialog_templateLabel);
templateCheckBtn.setLayoutData("skip 1"); //$NON-NLS-1$
labelLbl = new Label(composite, SWT.NONE);
labelLbl.setText(getLabel(Messages.DocumentDialog_labelLabel, !isHotlink()));
labelLbl.setLayoutData(""); //$NON-NLS-1$
label = new Text(composite, SWT.SINGLE | SWT.BORDER);
label.setLayoutData(String.format(WIDTH_LAYOUT_FORMAT, CONTROL_WIDTH));
label.addModifyListener(new BasicModifyListener());
final Label descriptionLbl = new Label(composite, SWT.NONE);
descriptionLbl.setText(getLabel(Messages.DocumentDialog_descriptionLabel));
descriptionLbl.setLayoutData(""); //$NON-NLS-1$
description = new Text(composite, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.WRAP);
description.setLayoutData(String.format(WIDTH_LAYOUT_FORMAT, CONTROL_WIDTH) + ", h 60!"); //$NON-NLS-1$
return composite;
}
/**
* Creates the header section to display header image, text and sub-text.
*/
private void createHeader() {
final Image image = getImage();
if (image != null) {
headerImg = new Label(composite, SWT.NULL);
image.setBackground(headerImg.getBackground());
headerImg.setImage(image);
headerImg.setLayoutData("sy 2, top"); //$NON-NLS-1$
}
headerText = new Label(composite, SWT.NONE);
final FontData[] fontData = headerText.getFont().getFontData();
for (int i = 0; i < fontData.length; i++) {
fontData[i].setHeight(14);
};
headerText.setFont(new Font(null, fontData));
headerText.setLayoutData(""); //$NON-NLS-1$
subHeaderText = new Label(composite, SWT.WRAP);
subHeaderText.setLayoutData("wmax 80%"); //$NON-NLS-1$
}
/**
* Creates the info controls.
*/
private void createInfoControls() {
infoLbl = new Label(composite, SWT.NONE);
infoLbl.setText(getLabel(Messages.DocumentDialog_fileLabel));
infoLbl.setLayoutData(""); //$NON-NLS-1$
info = new Text(composite, SWT.SINGLE | SWT.BORDER);
info.setLayoutData(String.format(WIDTH_LAYOUT_FORMAT, CONTROL_WIDTH));
info.addModifyListener(new ValidatingModifyListener());
infoDecoration = new ControlDecoration(info, SWT.TOP | SWT.LEFT);
final FieldDecoration errorFieldIndicator = FieldDecorationRegistry.getDefault()
.getFieldDecoration(FieldDecorationRegistry.DEC_ERROR);
infoDecoration.setImage(errorFieldIndicator.getImage());
infoDecoration.hide();
}
/**
* Creates the info button controls.
*/
private void createInfoBtnControls() {
infoBtnComposite = new Composite(composite, SWT.NONE);
infoBtnComposite.setLayoutData("skip, growx"); //$NON-NLS-1$
infoBtnComposite.setLayout(new MigLayout("insets 0, nogrid, fillx")); //$NON-NLS-1$
infoOpenBtn = new Button(infoBtnComposite, SWT.PUSH);
infoOpenBtn.setText(Messages.DocumentDialog_openBtn);
infoOpenBtn.setLayoutData("sg btnGrp"); //$NON-NLS-1$
infoOpenBtn.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
Program.launch(info.getText());
}
});
infoBrowseBtn = new Button(infoBtnComposite, SWT.PUSH);
infoBrowseBtn.setText(Messages.DocumentDialog_fileBtn);
infoBrowseBtn.setLayoutData("sg btnGrp, gap push"); //$NON-NLS-1$
infoBrowseBtn.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
final File file = openFileDialog();
if (file != null) {
info.setText(file.getAbsolutePath());
refreshBtns();
}
}
});
infoNewBtn = new Button(infoBtnComposite, SWT.PUSH);
infoNewBtn.setText(Messages.DocumentDialog_newBtn);
infoNewBtn.setLayoutData("sg btnGrp"); //$NON-NLS-1$
infoNewBtn.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
createFromTemplate();
}
});
}
private static final String TEMPLATE_PROPS = "templates.properties"; //$NON-NLS-1$
/**
* Loads the template extension properties file.
*
* @return template extension properties
*/
private Properties getTemplateProps() {
if (templateProps == null) {
InputStream inStream = null;
try {
inStream = getClass().getResourceAsStream(TEMPLATE_PROPS);
templateProps = new Properties();
templateProps.load(inStream);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inStream != null) {
try {
inStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
return templateProps;
}
/**
* Creates a new file from a template.
*
* @return new file
*/
private File createFromTemplate() {
final File templateFile = openSelectTemplateDialog();
if (templateFile != null) {
final String filePath = openSaveFileDialog(templateFile);
if (filePath != null) {
return createFileFromTemplate(templateFile, filePath);
}
}
return null;
}
/**
* Opens a list selection dialog to select templates from.
*
* @return template file
*/
private File openSelectTemplateDialog() {
final ListDialog selectDialog = new ListDialog(infoNewBtn.getShell());
selectDialog.setTitle(Messages.DocumentDialog_selectTemplateTitle);
selectDialog.setMessage(Messages.DocumentDialog_selectTemplateMsg);
selectDialog.setLabelProvider(new LabelProvider() {
@Override
public String getText(Object element) {
final IDocument doc = (IDocument) element;
return DocUtils.getLabelAndDescDisplay(DocUtils.getDocStr(doc),
doc.getDescription());
}
});
selectDialog.setContentProvider(new ArrayContentProvider());
final Object[] templates = getParamTemplates().toArray();
selectDialog.setInput(templates);
selectDialog.setInitialElementSelections(Collections.singletonList(templates[0]));
if (Dialog.OK == selectDialog.open()) {
final Object[] results = selectDialog.getResult();
if (results != null && results.length > 0) {
final IDocument doc = (IDocument) results[0];
if (doc != null) {
return (File) doc.getContent();
}
}
}
return null;
}
/**
* Opens an input dialog to enter a filename.
*
* @return filename
*/
private String openSaveFileDialog(File templateFile) {
final FileDialog dialog = new FileDialog(infoNewBtn.getShell(), SWT.SAVE);
dialog.setText(Messages.DocumentDialog_enterFilenameTitle);
dialog.setOverwrite(true);
dialog.setFileName(DocUtils.getFromTemplateFilename(templateFile, getTemplateProps()));
final String filePath = dialog.open();
if (filePath != null) {
return filePath;
}
return null;
}
/**
* Creates a new file with the filename from the template.
*
* @param templateFile
* @param filePath
* @return new file
*/
private File createFileFromTemplate(File templateFile, String filePath) {
File file = null;
try {
file = new File(DocUtils.cleanFromTemplateFilename(filePath, templateFile,
getTemplateProps()));
FileUtils.copyFile(templateFile, file);
info.setText(file.getAbsolutePath());
final boolean doOpen = MessageDialog.openQuestion(infoNewBtn.getShell(),
Messages.DocumentDialog_createFileFromTemplateTitle,
Messages.DocumentDialog_createFileFromTemplateSuccess);
if (doOpen) {
Program.launch(file.getAbsolutePath());
}
} catch (IOException e) {
MessageDialog.openError(infoNewBtn.getShell(),
Messages.DocumentDialog_createFileFromTemplateTitle,
Messages.DocumentDialog_createFileFromTemplateError);
}
return file;
}
/**
* Creates the info (action type) controls.
*/
private void createInfoGoActionControls() {
infoGoActionLbl = new Label(composite, SWT.NONE);
infoGoActionLbl.setText(getLabel(Messages.DocumentDialog_actionLabel));
infoGoActionLbl.setLayoutData(""); //$NON-NLS-1$
infoGoAction = new ComboViewer(composite, SWT.READ_ONLY | SWT.DROP_DOWN);
infoGoAction.getControl().setLayoutData("split 2"); //$NON-NLS-1$
infoGoAction.setLabelProvider(new LabelProvider() {
@Override
public String getText(Object element) {
final HotlinkDescriptor descriptor = (HotlinkDescriptor) element;
return descriptor.getLabel();
}
});
infoGoAction.setContentProvider(ArrayContentProvider.getInstance());
infoGoAction.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
final StructuredSelection selection = (StructuredSelection) event.getSelection();
final HotlinkDescriptor descriptor = (HotlinkDescriptor) selection.getFirstElement();
label.setText(descriptor.getLabel());
final String descriptionStr = descriptor.getDescription();
if (descriptionStr == null) {
description.setText(""); //$NON-NLS-1$
} else {
description.setText(descriptionStr);
}
}
});
final List<HotlinkDescriptor> actions = getActions();
if (actions != null && actions.size() > 0) {
infoGoAction.setInput(actions.toArray());
}
infoGoActionBtn = new Button(composite, SWT.PUSH);
infoGoActionBtn.setText(Messages.DocumentDialog_goBtn);
infoGoActionBtn.setLayoutData(""); //$NON-NLS-1$
infoGoActionBtn.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
final StructuredSelection selection = (StructuredSelection) infoGoAction.getSelection();
final HotlinkDescriptor descriptor = (HotlinkDescriptor) selection.getFirstElement();
final String action = descriptor.getConfig().replace(
DocumentPropertyPage.ACTION_PARAM, info.getText());
Program.launch(action);
}
});
}
/**
* Creates the type controls
*/
private void createTypeControls() {
final Label typeLbl = new Label(composite, SWT.NONE);
typeLbl.setText(getLabel(Messages.DocumentDialog_typeLabel, true));
typeLbl.setLayoutData(""); //$NON-NLS-1$
type = new ComboViewer(composite, SWT.READ_ONLY | SWT.DROP_DOWN);
type.getControl().setLayoutData(""); //$NON-NLS-1$
type.setContentProvider(ArrayContentProvider.getInstance());
type.setLabelProvider(new LabelProvider() {
@Override
public String getText(Object element) {
return DocUtils.toCamelCase(element.toString());
}
});
type.addSelectionChangedListener( new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
final ContentType newTypeValue = getTypeComboValue();
if (typeValue != newTypeValue) {
typeValue = newTypeValue;
if (newTypeValue != null) {
validateInfo();
refreshBtns();
configInfoControls(newTypeValue);
}
}
}
});
List<ContentType> types = getParamContentTypes();
if (types == null) {
types = new ArrayList<ContentType>();
switch (getParamType()) {
case LINKED:
types.add(ContentType.FILE);
types.add(ContentType.WEB);
break;
case ATTACHMENT:
types.add(ContentType.FILE);
break;
case HOTLINK:
types.add(ContentType.FILE);
types.add(ContentType.WEB);
types.add(ContentType.ACTION);
break;
default:
break;
}
}
type.setInput(types.toArray());
}
/**
* Setup before dialog contents creation. Initialisations that will affect creation of contents
* should be set here.
*/
private void beforeCreateContents() {
// Do something
}
@Override
protected Control createContents(Composite parent) {
beforeCreateContents();
final Control control = super.createContents(parent);
afterCreateContents();
return control;
}
/**
* Setup after dialog contents creation. Initialisations that needs the contents should be set
* here. Eg. setting values, enablements, initial validations, etc.
*/
private void afterCreateContents() {
// Set field values here
setValues();
// Set control enablements/visibility
configControlEnablements();
// Refresh buttons
refreshBtns();
}
/**
* Sets the values into the controls.
*/
private void setValues() {
if (isAddMode()) {
final Object[] types = (Object[]) type.getInput();
if (types != null && types.length > 0) {
type.setSelection(new StructuredSelection(types[0]));
}
} else {
type.setSelection(new StructuredSelection(getType()));
setValue(info, getInfo());
setValue(label, getLabel());
setValue(description, getDescription());
setValue(attribute, getAttribute());
templateCheckBtn.setSelection(isTemplate());
final List<HotlinkDescriptor> actions = getActions();
if (actions != null && actions.size() > 0) {
infoGoAction.setSelection(new StructuredSelection(actions.get(0)));
}
}
}
private void setValue(Text text, String value) {
if (value != null) {
text.setText(value);
}
}
/**
* Sets the window, header and sub-header texts.
*/
private void configHeaderDisplay() {
if (isHotlink()) {
setHeaderDisplayHotlink();
} else {
setHeaderDisplayLinkedOrAttachment();
}
}
private void setHeaderDisplayHotlink() {
final String header = String.format(Messages.DocumentDialog_hotlinkHeader,
DocUtils.toCamelCase(getAttribute()));
getShell().setText(header);
headerText.setText(header);
subHeaderText.setText(getDescription());
subHeaderText.setToolTipText(getDescription());
}
private void setHeaderDisplayLinkedOrAttachment() {
String header = ""; //$NON-NLS-1$
String subHeader = ""; //$NON-NLS-1$
String featureName = getParamFeatureName();
String shapefileName = getParamResourceName();
if (isAddMode()) {
header = Messages.DocumentDialog_addAttachHeader;
if (isLinked()) {
header = Messages.DocumentDialog_addLinkHeader;
}
} else {
header = Messages.DocumentDialog_editAttachHeader;
if (isLinked()) {
header = Messages.DocumentDialog_editLinkHeader;
}
}
if (shapefileName != null) {
shapefileName = DocUtils.toCamelCase(shapefileName);
if (featureName != null) {
featureName = DocUtils.toCamelCase(featureName);
String subHeaderFormat = Messages.DocumentDialog_attachSubHeaderFeature;
if (isLinked()) {
subHeaderFormat = Messages.DocumentDialog_linkSubHeaderFeature;
}
subHeader = String.format(subHeaderFormat, featureName, shapefileName);
} else {
String subHeaderFormat = Messages.DocumentDialog_attachSubHeaderShapefile;
if (isLinked()) {
subHeaderFormat = Messages.DocumentDialog_linkSubHeaderShapefile;
}
subHeader = String.format(subHeaderFormat, shapefileName);
}
} else {
subHeader = Messages.DocumentDialog_attachSubHeader;
if (isLinked()) {
subHeader = Messages.DocumentDialog_linkSubHeader;
}
}
getShell().setText(header);
headerText.setText(header);
subHeaderText.setText(subHeader);
subHeaderText.setToolTipText(subHeader);
}
/**
* Sets controls' enablement and visibility settings with respect to the dialog's type and mode.
*/
private void configControlEnablements() {
if (isHotlink()) {
configAttributeControls(true);
configMetadataControls(false);
templateCheckBtn.setVisible(false);
type.getControl().setEnabled(false);
} else {
configAttributeControls(false);
configMetadataControls(true);
templateCheckBtn.setVisible(isAttachment());
boolean isTypeEnabled = false;
if (isLinked() && isAddMode()) {
final Object[] types = (Object[]) type.getInput();
isTypeEnabled = (types != null && types.length > 1);
}
type.getControl().setEnabled(isTypeEnabled);
}
}
@Override
protected void okPressed() {
if (values == null) {
values = new HashMap<String, Object>();
}
values.put(V_LABEL, label.getText());
values.put(V_DESCRIPTION, description.getText());
values.put(V_CONTENT_TYPE, getTypeComboValue());
values.put(V_INFO, info.getText());
values.put(V_TEMPLATE, templateCheckBtn.getSelection());
super.okPressed();
}
@Override
protected void cancelPressed() {
super.cancelPressed();
}
/**
* Configure the visibility and enablement of info controls depending on the type.
*
* @param type
*/
private void configInfoControls(ContentType type) {
switch (type) {
case FILE:
infoLbl.setText(isHotlink() ? getLabel(Messages.DocumentDialog_valueLabel) : getLabel(
Messages.DocumentDialog_fileLabel, true));
configInfoBtnControls(true, true);
configInfoGoActionControls(false);
templateCheckBtn.setVisible(isAttachment());
break;
case WEB:
infoLbl.setText(isHotlink() ? getLabel(Messages.DocumentDialog_valueLabel) : getLabel(
Messages.DocumentDialog_urlLabel, true));
configInfoBtnControls(true, false);
configInfoGoActionControls(false);
templateCheckBtn.setVisible(false);
break;
case ACTION:
infoLbl.setText(isHotlink() ? getLabel(Messages.DocumentDialog_valueLabel) : getLabel(
Messages.DocumentDialog_actionLabel, true));
configInfoBtnControls(false, false);
configInfoGoActionControls(true);
templateCheckBtn.setVisible(false);
break;
default:
break;
}
composite.layout();
}
/**
* Sets the info buttons' enablement and visibility settings.
*
* @param isVisible
* @param isFile
*/
private void configInfoBtnControls(boolean isVisible, boolean isFile) {
infoBtnComposite.setVisible(isVisible);
if (isVisible) {
infoBrowseBtn.setVisible(isFile);
infoNewBtn.setVisible(isFile);
final List<IDocument> templates = getParamTemplates();
final boolean hasTemplates = (templates != null && templates.size() > 0);
infoNewBtn.setEnabled(hasTemplates);
}
}
/**
* Sets the info (action controls) visibility setttings.
*
* @param isVisible
*/
private void configInfoGoActionControls(boolean isVisible) {
infoGoActionLbl.setVisible(isVisible);
infoGoAction.getControl().setVisible(isVisible);
infoGoActionBtn.setVisible(isVisible);
}
/**
* Sets the attribute controls' visbility settings.
*
* @param isVisible
*/
private void configAttributeControls(boolean isVisible) {
attributeLbl.setVisible(isVisible);
attribute.setVisible(isVisible);
}
/**
* Sets the metadata (label and description) controls' enablement settings.
*
* @param isEnabled
*/
private void configMetadataControls(boolean isEnabled) {
label.setEditable(isEnabled);
description.setEditable(isEnabled);
}
/**
* Opens the file selection dialog.
*
* @return selected file
*/
private File openFileDialog() {
final List<File> fileList = openFileDialog(false);
if (fileList != null && fileList.size() > 0) {
return fileList.get(0);
}
return null;
}
/**
* Opens the file selection dialog.
*
* @param isMultiSelect
* @return list of selected files
*/
private List<File> openFileDialog(boolean isMultiSelect) {
final int style = isMultiSelect ? (SWT.OPEN | SWT.MULTI) : SWT.OPEN;
final FileDialog fileDialog = new FileDialog(infoBrowseBtn.getShell(), style);
fileDialog.setText(Messages.docView_openDialogTitle);
final String hasSelection = fileDialog.open();
if (hasSelection != null) {
final String[] filenames = fileDialog.getFileNames();
if (filenames != null && filenames.length > 0) {
final List<File> fileList = new ArrayList<File>();
final String filePath = fileDialog.getFilterPath();
for (int i = 0, n = filenames.length; i < n; i++) {
String filename = filePath;
if (filePath.charAt(filePath.length() - 1) != File.separatorChar) {
filename += File.separatorChar;
}
filename += filenames[i];
fileList.add(new File(filename));
}
return fileList;
}
}
return null;
}
/**
* Refreshes the buttons depending on the field's inputs.
*/
private void refreshBtns() {
if (hasError) {
getButton(IDialogConstants.OK_ID).setEnabled(false);
} else {
getButton(IDialogConstants.OK_ID).setEnabled(!isEmpty());
}
}
/**
* Checks if the required fields are filled up.
*
* @return true if one or more is not filled up, otherwise false
*/
private boolean isEmpty() {
if (isLinked() || isAttachment()) {
if (isEmpty(label)) {
return true;
}
}
if (isEmpty(type)) {
return true;
}
if (isEmpty(info)) {
return true;
}
return false;
}
/**
* Checks if the field is filled up.
*
* @param control
* @return true if it is not filled up, otherwise false
*/
private boolean isEmpty(Object control) {
if (control instanceof Text) {
final Text textCtrl = (Text) control;
final String textCtrlValue = textCtrl.getText().trim();
if (textCtrlValue == null || textCtrlValue.length() == 0) {
return true;
}
} else if (control instanceof ComboViewer) {
final ComboViewer comboCtrl = (ComboViewer) control;
if (getComboValue(comboCtrl) == null) {
return true;
}
}
return false;
}
/**
* Gets the selected value of the combo.
*
* @param combo
* @return selected value
*/
private Object getComboValue(ComboViewer combo) {
final ISelection selection = combo.getSelection();
if( !selection.isEmpty() && selection instanceof StructuredSelection ){
final StructuredSelection structSelection = (StructuredSelection) selection;
return structSelection.getFirstElement();
}
return null;
}
/**
* Gets the selected value of the type field.
*
* @return select value
*/
private ContentType getTypeComboValue() {
return (ContentType) getComboValue(type);
}
/**
* Validate info input with respect to the type.
*
* @return true if input is valid, otherwise false
*/
private void validateInfo() {
infoOpenBtn.setEnabled(false);
infoDecoration.hide();
final String infoValue = info.getText().trim();
if (infoValue != null && infoValue.length() > 0) {
switch (getTypeComboValue()) {
case FILE:
final File file = new File(infoValue);
if (file.exists() && file.isFile()) {
infoOpenBtn.setEnabled(true);
} else {
infoDecoration.setDescriptionText(Messages.DocumentDialog_errValidFile);
infoDecoration.show();
hasError = true;
return;
}
break;
case WEB:
try {
new URL(infoValue);
infoOpenBtn.setEnabled(true);
} catch (MalformedURLException e) {
infoDecoration.setDescriptionText(Messages.DocumentDialog_errValidURL);
infoDecoration.show();
hasError = true;
return;
}
break;
case ACTION:
// Do check here
break;
default:
break;
}
}
hasError = false;
}
/**
* Sets the document control's value.
*/
private void setDocumentValue() {
if (!hasError) {
final String infoValue = info.getText().trim();
if (infoValue != null && infoValue.length() > 0) {
String labelValue = label.getText().trim();
if (labelValue == null || labelValue.length() == 0) {
if (isHotlink()) {
labelValue = attribute.getText();
}
}
document.setText(DocUtils.getDocStr(getTypeComboValue(), infoValue, labelValue));
} else {
document.setText(""); //$NON-NLS-1$
}
}
}
/**
* Modify listener that sets the document text and refreshes buttons' state.
*/
private class BasicModifyListener implements ModifyListener {
@Override
public void modifyText(ModifyEvent e) {
setDocumentValue();
refreshBtns();
}
}
/**
* Modify listener that adds validation to {@link BasicModifyListener}'s functionalities.
*/
private class ValidatingModifyListener extends BasicModifyListener {
@Override
public void modifyText(ModifyEvent e) {
validateInfo();
super.modifyText(e);
}
}
/**
* Gets a standard formatted label for the dialog's form.
*
* @param label
* @return formatted label
*/
private String getLabel(String label) {
return getLabel(label, false);
}
/**
* Gets a standard formatted label for the dialog's form.
*
* @param label
* @param isMandatory
* @return formatted label
*/
private String getLabel(String label, boolean isMandatory) {
return String.format(LABEL_FORMAT, label, (isMandatory ? MANDATORY : "")); //$NON-NLS-1$
}
/**
* Creates a {@link DocumentInfo} from the dialog form values. This is a utility to get values
* after the dialog's Ok button has been clicked.
*
* @return document info
*/
public DocumentInfo getDocInfo() {
return (new DocumentInfo(getLabel(), getDescription(), getInfo(), getType(), isTemplate(),
getParamType()));
}
/**
* Gets a file from the information value of the dialog. This returns null if the value is not a
* valid file or is non existing. This is a utility to get values after the dialog's Ok button
* has been clicked.
*
* @return file
*/
public File getFileInfo() {
final File file = new File(getInfo());
if (file.exists()) {
return file;
}
return null;
}
/**
* Gets a url from the information value of the dialog. This returns null if the value is not a
* valid url. This is a utility to get values after the dialog's Ok button has been clicked.
*
* @return url
*/
public URL getUrlInfo() {
try {
final URL url = new URL(getInfo());
return url;
} catch (MalformedURLException e) {
return null;
}
}
}