/*
* Copyright (c) 2008 Stiftung Deutsches Elektronen-Synchrotron,
* Member of the Helmholtz Association, (DESY), HAMBURG, GERMANY.
*
* THIS SOFTWARE IS PROVIDED UNDER THIS LICENSE ON AN "../AS IS" BASIS.
* WITHOUT WARRANTY OF ANY KIND, EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED
* TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR PARTICULAR PURPOSE AND
* NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE. SHOULD THE SOFTWARE PROVE DEFECTIVE
* IN ANY RESPECT, THE USER ASSUMES THE COST OF ANY NECESSARY SERVICING, REPAIR OR
* CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE.
* NO USE OF ANY SOFTWARE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
* DESY HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
* OR MODIFICATIONS.
* THE FULL LICENSE SPECIFYING FOR THE SOFTWARE THE REDISTRIBUTION, MODIFICATION,
* USAGE AND OTHER RIGHTS AND OBLIGATIONS IS INCLUDED WITH THE DISTRIBUTION OF THIS
* PROJECT IN THE FILE LICENSE.HTML. IF THE LICENSE IS NOT INCLUDED YOU MAY FIND A COPY
* AT HTTP://WWW.DESY.DE/LEGAL/LICENSE.HTM
*/
package org.csstudio.sds.ui.internal.properties;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import org.csstudio.sds.model.WidgetProperty;
import org.csstudio.sds.ui.SdsUiPlugin;
import org.csstudio.sds.util.TextDnDUtil;
import org.csstudio.sds.util.TooltipResolver;
import org.csstudio.ui.util.CustomMediaFactory;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
/**
* A table cell editor for values of a multiple line String.
*
* @author Kai Meyer
*/
public final class ParamStringCellEditor extends AbstractDialogCellEditor {
/**
* The current String value.
*/
private String _value;
/**
* The names of the properties and their categories.
*/
private Map<String, WidgetProperty> _properties;
/**
* Creates a new string cell editor parented under the given control. The
* cell editor value is a String.
*
* @param parent
* The parent table.
* @param properties
* the names of the properties and their categories
*/
public ParamStringCellEditor(final Composite parent, final Map<String, WidgetProperty> properties) {
super(parent, "Parameterized Text");
_properties = properties;
}
/**
* {@inheritDoc}
*/
@Override
protected void openDialog(final Shell parentShell, final String dialogTitle) {
MultipleLineInputDialog dialog = new MultipleLineInputDialog(parentShell,dialogTitle,"Type in the text", _value);
if (dialog.open()==Window.OK) {
_value = dialog.getText();
}
}
/**
* {@inheritDoc}
*/
@Override
protected boolean shouldFireChanges() {
return _value != null;
}
/**
* {@inheritDoc}
*/
@Override
protected Object doGetValue() {
return _value;
}
/**
* {@inheritDoc}
*/
@Override
protected void doSetFocus() {
// Ignore
}
/**
* {@inheritDoc}
*/
@Override
protected void doSetValue(final Object value) {
Assert.isTrue(value instanceof String);
this._value = (String) value;
}
/**
* This class represents a TextCellEditor, which can handle multiple line text.
*
* @author Kai Meyer
*/
private final class MultipleLineInputDialog extends Dialog {
/**
* The title of the dialog.
*/
private String _title;
/**
* The message to display, or <code>null</code> if none.
*/
private String _message;
/**
* The input value; the empty string by default.
*/
private String _value = "";//$NON-NLS-1$
/**
* Input text widget.
*/
private Text _text;
/**
* The Action to add a new property-tag.
*/
private Action _addAction;
/**
* The menu for the add-action.
*/
private Menu _actionMenu;
/**
* Creates an input dialog with OK and Cancel buttons. Note that the dialog
* will have no visual representation (no widgets) until it is told to open.
* <p>
* Note that the <code>open</code> method blocks for input dialogs.
* </p>
*
* @param parentShell
* the parent shell, or <code>null</code> to create a top-level
* shell
* @param dialogTitle
* the dialog title, or <code>null</code> if none
* @param dialogMessage
* the dialog message, or <code>null</code> if none
* @param initialValue
* the initial input value, or <code>null</code> if none
* (equivalent to the empty string)
*/
public MultipleLineInputDialog(final Shell parentShell, final String dialogTitle,
final String dialogMessage, final String initialValue) {
super(parentShell);
this.setShellStyle(SWT.MODELESS | SWT.CLOSE | SWT.MAX | SWT.TITLE
| SWT.BORDER | SWT.RESIZE);
_title = dialogTitle;
_message = dialogMessage;
if (initialValue == null) {
_value = "";//$NON-NLS-1$
} else {
// _value = TooltipResolver.resolveToValue(initialValue, _properties);
_value = initialValue;
}
}
/**
* {@inheritDoc}
*/
@Override
protected void configureShell(final Shell shell) {
super.configureShell(shell);
if (_title != null) {
shell.setText(_title);
}
}
/**
* {@inheritDoc}
*/
@Override
protected Control createDialogArea(final Composite parent) {
Composite composite = (Composite) super.createDialogArea(parent);
if (_message != null) {
Label label = new Label(composite, SWT.WRAP);
label.setText(_message);
GridData data = new GridData(GridData.GRAB_HORIZONTAL
| GridData.GRAB_VERTICAL | GridData.HORIZONTAL_ALIGN_FILL
| GridData.VERTICAL_ALIGN_CENTER);
data.widthHint = convertHorizontalDLUsToPixels(IDialogConstants.MINIMUM_MESSAGE_AREA_WIDTH);
label.setLayoutData(data);
}
this.createActions();
_actionMenu = this.createMenu(composite);
Composite toolBarComposite = new Composite(composite,SWT.BORDER);
GridLayout gridLayout = new GridLayout(1,false);
gridLayout.marginLeft = 0;
gridLayout.marginRight = 0;
gridLayout.marginBottom = 0;
gridLayout.marginTop = 0;
gridLayout.marginHeight = 0;
gridLayout.marginWidth = 0;
toolBarComposite.setLayout(gridLayout);
GridData gridData = new GridData(SWT.FILL,SWT.FILL,true,true);
toolBarComposite.setLayoutData(gridData);
ToolBarManager toolbarManager = new ToolBarManager(SWT.FLAT);
ToolBar toolBar = toolbarManager.createControl(toolBarComposite);
GridData grid = new GridData();
grid.horizontalAlignment = GridData.FILL;
grid.verticalAlignment = GridData.BEGINNING;
toolBar.setLayoutData(grid);
toolbarManager.add(_addAction);
toolbarManager.update(true);
_text = new Text(toolBarComposite, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
gridData = new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL);
gridData.heightHint = 100;
_text.setLayoutData(gridData);
_text.setText(_value);
_text.setFocus();
_text.addKeyListener(new KeyAdapter() {
/**
* The key code for Return.
*/
private static final int RETURN = 13;
@Override
public void keyPressed(final KeyEvent e) {
if (e.keyCode == SWT.ESC) {
buttonPressed(IDialogConstants.CANCEL_ID);
} else if (e.keyCode==RETURN && e.stateMask==SWT.MOD1) {
buttonPressed(IDialogConstants.OK_ID);
}
}
});
TextDnDUtil.addDnDSupport(_text);
return composite;
}
/**
* Creates the actions.
*/
private void createActions() {
_addAction = new Action("Add") {
@Override
public void run() {
_actionMenu.setVisible(true);
while(!_actionMenu.isDisposed() && _actionMenu.isVisible()){
if(!Display.getCurrent().readAndDispatch()){
Display.getCurrent().sleep();
}
}
_actionMenu.setVisible(false);
}
};
_addAction.setToolTipText("Adds a property tag on the current position of the cursor");
_addAction.setImageDescriptor(CustomMediaFactory.getInstance()
.getImageDescriptorFromPlugin(SdsUiPlugin.PLUGIN_ID,
"icons/add.gif"));
}
/**
* Creates the popup-menu for adding a property-tag.
* @param control The {@link Control} for the menu
* @return The resulting menu
*/
private Menu createMenu(final Control control) {
MenuManager listMenu = new MenuManager();
// get all categories
List<String> categoryNames = new ArrayList<String>();
String[] propertyNames = _properties.keySet().toArray(new String[0]);
Arrays.sort(propertyNames);
for (String propertyName : propertyNames) {
String categoryName = _properties.get(propertyName).getCategory().name();
if (!categoryNames.contains(categoryName)) {
categoryNames.add(categoryName);
}
}
String[] categories = categoryNames.toArray(new String[categoryNames.size()]);
// sort categories
Arrays.sort(categories);
// create submenus for the categories
for (String category : categories) {
MenuManager categoryMenu = new MenuManager(category,category);
listMenu.add(categoryMenu);
}
// fill submenus with entries
for (String key : _properties.keySet()) {
WidgetProperty p = _properties.get(key);
String categoryName = p.getCategory().name();
MenuManager subMenu = (MenuManager) listMenu.find(categoryName);
subMenu.add(new ParamAction(key, p.getDescription()));
}
return listMenu.createContextMenu(control);
}
/**
* {@inheritDoc}
*/
@Override
protected void buttonPressed(final int buttonId) {
if (buttonId == IDialogConstants.OK_ID) {
_value = _text.getText();
} else {
_value = null;
}
super.buttonPressed(buttonId);
}
/**
* Returns the string typed into this dialog.
*
* @return the input string
*/
public String getText() {
return _value;
}
/**
* An {@link Action} which adds a parameter on the current position of the cursor.
* @author Kai Meyer
*
*/
private final class ParamAction extends Action {
/**
* The name of the property.
*/
private String _tooltipVariable;
/**
* Constructor.
* @param tooltipVariable The name of the property
*/
public ParamAction(final String tooltipVariable, String description) {
_tooltipVariable = tooltipVariable;
this.setText("Add '"+description+"'-Tag");
}
/**
* {@inheritDoc}
*/
@Override
public void run() {
String text = _text.getText();
int caretPosition = _text.getCaretPosition();
int textLength = _text.getText().length();
if (caretPosition<textLength) {
String prefix = text.substring(0,caretPosition);
String postfix = text.substring(caretPosition, text.length());
_text.setText(prefix+TooltipResolver.START_SEPARATOR+_tooltipVariable+TooltipResolver.END_SEPARATOR+postfix);
} else {
_text.setText(text+TooltipResolver.START_SEPARATOR+_tooltipVariable+TooltipResolver.END_SEPARATOR);
}
}
}
}
}