001: /*
002: * Copyright 2006 Pentaho Corporation. All rights reserved.
003: * This software was developed by Pentaho Corporation and is provided under the terms
004: * of the Mozilla Public License, Version 1.1, or any later version. You may not use
005: * this file except in compliance with the license. If you need a copy of the license,
006: * please go to http://www.mozilla.org/MPL/MPL-1.1.txt. The Original Code is the Pentaho
007: * BI Platform. The Initial Developer is Pentaho Corporation.
008: *
009: * Software distributed under the Mozilla Public License is distributed on an "AS IS"
010: * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. Please refer to
011: * the license for the specific language governing your rights and limitations.
012: */
013: package org.pentaho.designstudio.controls;
014:
015: import java.text.MessageFormat;
016: import java.util.ArrayList;
017: import java.util.Arrays;
018: import java.util.List;
019:
020: import org.dom4j.Element;
021: import org.eclipse.core.runtime.IStatus;
022: import org.eclipse.core.runtime.Status;
023: import org.eclipse.jface.dialogs.ErrorDialog;
024: import org.eclipse.jface.util.Assert;
025: import org.eclipse.jface.viewers.CellEditor;
026: import org.eclipse.jface.viewers.ICellModifier;
027: import org.eclipse.jface.viewers.IContentProvider;
028: import org.eclipse.jface.viewers.ILabelProviderListener;
029: import org.eclipse.jface.viewers.ITableLabelProvider;
030: import org.eclipse.jface.viewers.StructuredSelection;
031: import org.eclipse.jface.viewers.TextCellEditor;
032: import org.eclipse.swt.SWT;
033: import org.eclipse.swt.custom.CCombo;
034: import org.eclipse.swt.events.FocusAdapter;
035: import org.eclipse.swt.events.FocusEvent;
036: import org.eclipse.swt.events.KeyAdapter;
037: import org.eclipse.swt.events.KeyEvent;
038: import org.eclipse.swt.events.KeyListener;
039: import org.eclipse.swt.events.SelectionAdapter;
040: import org.eclipse.swt.events.SelectionEvent;
041: import org.eclipse.swt.events.TraverseEvent;
042: import org.eclipse.swt.events.TraverseListener;
043: import org.eclipse.swt.graphics.GC;
044: import org.eclipse.swt.graphics.Image;
045: import org.eclipse.swt.widgets.Composite;
046: import org.eclipse.swt.widgets.Control;
047: import org.eclipse.swt.widgets.Table;
048: import org.eclipse.swt.widgets.TableItem;
049: import org.eclipse.swt.widgets.Text;
050: import org.pentaho.actionsequence.dom.AbstractActionIOElement;
051: import org.pentaho.actionsequence.dom.AbstractIOElement;
052: import org.pentaho.actionsequence.dom.ActionOutput;
053: import org.pentaho.actionsequence.dom.ActionSequenceDocument;
054: import org.pentaho.designstudio.messages.Messages;
055:
056: /**
057: * Table viewer used for viewing and modifying the outputs of an action
058: * definition element.
059: *
060: * @author Angelo Rodriguez
061: */
062: public class ActionOutputsTable extends ActionIOTable {
063:
064: class OutputModifier implements ICellModifier {
065:
066: /* (non-Javadoc)
067: * @see org.eclipse.jface.viewers.ICellModifier#canModify(java.lang.Object, java.lang.String)
068: */
069: public boolean canModify(Object element, String property) {
070: return property.equals(ActionIOTable.TYPE_COLUMN_PROP)
071: || property.equals(ActionIOTable.NAME_COLUMN_PROP);
072: }
073:
074: /* (non-Javadoc)
075: * @see org.eclipse.jface.viewers.ICellModifier#getValue(java.lang.Object, java.lang.String)
076: */
077: public Object getValue(Object tableObject, String property) {
078: Object value = tableObject;
079: if (property.equals(ActionIOTable.NAME_COLUMN_PROP)) {
080: if (tableObject instanceof Element) {
081: value = ((Element) tableObject).getName();
082: } else if (tableObject == ActionUtil.NEW_IO_PLACEHOLDER) {
083: value = ""; //$NON-NLS-1$
084: }
085: }
086: return value;
087: }
088:
089: public void modify(Object tableObject, String property,
090: Object value) {
091: if (value != null) {
092: TableItem tableItem = (TableItem) tableObject;
093: if (property.equals(ActionIOTable.NAME_COLUMN_PROP)) {
094: String name = ((String) value).trim();
095: if (name.length() == 0) {
096: if (tableItem.getData() instanceof AbstractActionIOElement) {
097: ErrorDialog
098: .openError(
099: getTable().getShell(),
100: Messages
101: .getString("ActionOutputsTable.OUTPUT_ERROR"), Messages.getString("ActionOutputsTable.INVALID_OUTPUT_NAME"), new Status(IStatus.ERROR, Messages.getString("ActionOutputsTable.DESIGN_STUDIO"), 0, Messages.getString("ActionOutputsTable.EMPTY_NAME"), null)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
102: }
103: } else if (name.split("\\s+").length != 1) { //$NON-NLS-1$
104: ErrorDialog
105: .openError(
106: getTable().getShell(),
107: Messages
108: .getString("ActionOutputsTable.OUTPUT_ERROR"), Messages.getString("ActionOutputsTable.INVALID_OUTPUT_NAME"), new Status(IStatus.ERROR, Messages.getString("ActionOutputsTable.DESIGN_STUDIO"), 0, Messages.getString("ActionOutputsTable.NO_SPACES_IN_OUTPUT_NAME"), null)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
109: } else {
110: if (tableItem.getData() instanceof AbstractActionIOElement) {
111: AbstractActionIOElement ioElement = (AbstractActionIOElement) tableItem
112: .getData();
113: ioElement.setName(name);
114: refresh(ioElement);
115: } else if ((name.length() > 0)
116: && (tableItem.getData() == ActionUtil.NEW_IO_PLACEHOLDER)) {
117: addNewIOElement(name);
118: refresh();
119: setSelection(new StructuredSelection(
120: getElementAt(getTable()
121: .getItemCount() - 2)));
122: }
123: outputNameCellEditor.valueChanged = true;
124: }
125: } else if (property
126: .equals(ActionIOTable.TYPE_COLUMN_PROP)) {
127: if (tableItem.getData() instanceof AbstractActionIOElement) {
128: AbstractActionIOElement ioElement = (AbstractActionIOElement) tableItem
129: .getData();
130: if (Arrays.asList(
131: ActionSequenceDocument.IO_TYPES)
132: .contains(value)) {
133: ioElement.setType(value.toString());
134: refresh(ioElement);
135: }
136: }
137: outputTypeCellEditor.valueChanged = true;
138: }
139: }
140: }
141: }
142:
143: class OutputNameCellEditor extends TextCellEditor {
144: boolean valueChanged = false;
145: boolean pressedReturn = false;
146:
147: public OutputNameCellEditor(Composite parent) {
148: super (parent);
149: Text text = (Text) getControl();
150: text.addKeyListener(new KeyListener() {
151:
152: public void keyPressed(KeyEvent e) {
153: e.doit = !Character.isWhitespace(e.character)
154: && (e.character != '-');
155: }
156:
157: public void keyReleased(KeyEvent e) {
158: }
159:
160: });
161: }
162:
163: protected void handleDefaultSelection(SelectionEvent event) {
164: pressedReturn = true;
165: super .handleDefaultSelection(event);
166: }
167:
168: protected void doSetValue(Object value) {
169: if (value instanceof ActionOutput) {
170: super .doSetValue(((ActionOutput) value).getName());
171: } else {
172: super .doSetValue(value);
173: }
174: valueChanged = false;
175: pressedReturn = false;
176: }
177:
178: public void deactivate() {
179: super .deactivate();
180: if (valueChanged) {
181: valueChanged = false;
182: int selectedIndex = getTable().getSelectionIndex();
183: TableItem tableItem = getTable().getItem(selectedIndex);
184: if ((pressedReturn)
185: && (tableItem.getData() instanceof ActionOutput)) {
186: ;
187: editElement(tableItem.getData(), 1);
188: }
189: }
190: }
191: }
192:
193: public class OutputTypeCellEditor extends CellEditor {
194: boolean valueChanged = false;
195:
196: boolean pressedReturn = false;
197:
198: private String[] items;
199:
200: int selection;
201:
202: CCombo comboBox;
203:
204: private static final int defaultStyle = SWT.NONE;
205:
206: public OutputTypeCellEditor(Composite parent) {
207: super (parent, defaultStyle);
208: setItems(ActionSequenceDocument.IO_TYPES);
209: }
210:
211: public String[] getItems() {
212: return this .items;
213: }
214:
215: public void setItems(String[] items) {
216: Assert.isNotNull(items);
217: this .items = items;
218: populateComboBoxItems();
219: }
220:
221: protected Control createControl(Composite parent) {
222:
223: comboBox = new CCombo(parent, getStyle());
224: comboBox.setFont(parent.getFont());
225:
226: comboBox.addKeyListener(new KeyAdapter() {
227: // hook key pressed - see PR 14201
228: public void keyPressed(KeyEvent e) {
229: keyReleaseOccured(e);
230: }
231: });
232:
233: comboBox.addSelectionListener(new SelectionAdapter() {
234: public void widgetDefaultSelected(SelectionEvent event) {
235: pressedReturn = true;
236: applyEditorValueAndDeactivate();
237: }
238:
239: public void widgetSelected(SelectionEvent event) {
240: selection = comboBox.getSelectionIndex();
241: }
242: });
243:
244: comboBox.addTraverseListener(new TraverseListener() {
245: public void keyTraversed(TraverseEvent e) {
246: if (e.detail == SWT.TRAVERSE_ESCAPE
247: || e.detail == SWT.TRAVERSE_RETURN) {
248: e.doit = false;
249: }
250: }
251: });
252:
253: comboBox.addFocusListener(new FocusAdapter() {
254: public void focusLost(FocusEvent e) {
255: OutputTypeCellEditor.this .focusLost();
256: }
257: });
258: return comboBox;
259: }
260:
261: /* (non-Javadoc)
262: * @see org.eclipse.jface.viewers.CellEditor#doGetValue()
263: */
264: protected Object doGetValue() {
265: Object value = null;
266: CCombo combo = (CCombo) getControl();
267: int selectedIdx = combo.getSelectionIndex();
268: if (selectedIdx >= 0) {
269: value = combo.getItem(selectedIdx);
270: }
271: return value;
272: }
273:
274: protected void doSetFocus() {
275: comboBox.setFocus();
276: }
277:
278: public LayoutData getLayoutData() {
279: LayoutData layoutData = super .getLayoutData();
280: if ((comboBox == null) || comboBox.isDisposed())
281: layoutData.minimumWidth = 60;
282: else {
283: // make the comboBox 10 characters wide
284: GC gc = new GC(comboBox);
285: layoutData.minimumWidth = (gc.getFontMetrics()
286: .getAverageCharWidth() * 10) + 10;
287: gc.dispose();
288: }
289: return layoutData;
290: }
291:
292: protected void doSetValue(Object value) {
293: valueChanged = false;
294: pressedReturn = false;
295: String typeStr = null;
296: if (value instanceof AbstractIOElement) {
297: AbstractIOElement ioElement = (AbstractIOElement) value;
298: typeStr = ioElement.getType();
299: }
300:
301: ((CCombo) getControl()).setText(typeStr != null ? typeStr
302: : ""); //$NON-NLS-1$
303: }
304:
305: private void populateComboBoxItems() {
306: if (comboBox != null && items != null) {
307: comboBox.removeAll();
308: for (int i = 0; i < items.length; i++)
309: comboBox.add(items[i], i);
310:
311: setValueValid(true);
312: selection = 0;
313: }
314: }
315:
316: void applyEditorValueAndDeactivate() {
317: selection = comboBox.getSelectionIndex();
318: Object newValue = doGetValue();
319: markDirty();
320: boolean isValid = isCorrect(newValue);
321: setValueValid(isValid);
322: if (!isValid) {
323: // try to insert the current value into the error message.
324: setErrorMessage(MessageFormat.format(getErrorMessage(),
325: new Object[] { items[selection] }));
326: }
327: fireApplyEditorValue();
328: deactivate();
329: }
330:
331: protected void focusLost() {
332: if (isActivated()) {
333: applyEditorValueAndDeactivate();
334: }
335: }
336:
337: protected void keyReleaseOccured(KeyEvent keyEvent) {
338: if (keyEvent.character == '\u001b') { // Escape character
339: fireCancelEditor();
340: } else if (keyEvent.character == '\t') { // tab key
341: applyEditorValueAndDeactivate();
342: }
343: }
344:
345: public void deactivate() {
346: // TODO Auto-generated method stub
347: super .deactivate();
348: if (valueChanged) {
349: valueChanged = false;
350: int selectedIndex = getTable().getSelectionIndex();
351: TableItem tableItem = getTable().getItem(selectedIndex);
352: if ((pressedReturn)
353: && (tableItem.getData() instanceof ActionOutput)) {
354: ;
355: editElement(getTable().getItem(selectedIndex + 1)
356: .getData(), 0);
357: }
358: }
359: }
360: }
361:
362: public class LabelProvider implements ITableLabelProvider {
363:
364: List listeners = new ArrayList();
365:
366: public LabelProvider() {
367: super ();
368: }
369:
370: public Image getColumnImage(Object element, int columnIndex) {
371: return null;
372: }
373:
374: public String getColumnText(Object element, int columnIndex) {
375: String columnText = ""; //$NON-NLS-1$
376: if (element == ActionUtil.NEW_IO_PLACEHOLDER) {
377: if (columnIndex == NAME_COLUMN_IDX) {
378: columnText = element.toString();
379: }
380: } else if (element instanceof AbstractIOElement) {
381: AbstractIOElement inputElement = (AbstractIOElement) element;
382: switch (columnIndex) {
383: case NAME_COLUMN_IDX:
384: columnText = inputElement.getName();
385: break;
386: case TYPE_COLUMN_IDX:
387: columnText = inputElement.getType();
388: break;
389: }
390: }
391: return columnText;
392: }
393:
394: public void addListener(ILabelProviderListener listener) {
395: listeners.add(listener);
396: }
397:
398: public void dispose() {
399: }
400:
401: public boolean isLabelProperty(Object element, String property) {
402: return true;
403: }
404:
405: public void removeListener(ILabelProviderListener listener) {
406: listeners.add(listener);
407: }
408:
409: }
410:
411: OutputNameCellEditor outputNameCellEditor;
412: OutputTypeCellEditor outputTypeCellEditor;
413:
414: /**
415: * Creates an ActionOutputsViewer
416: * @param parent the parent of this viewer.
417: * @param toolkit the form toolkit.
418: * @param ioInfo a description of the inputs allowed within the action definition.
419: */
420: public ActionOutputsTable(Composite parent) {
421: super (parent);
422: }
423:
424: /* (non-Javadoc)
425: * @see org.pentaho.designstudio.editors.actionsequence.pages.actions.ActionIOViewer#createContentProvider()
426: */
427: protected IContentProvider createContentProvider() {
428: return new ActionIOContentProvider(false);
429: }
430:
431: /* (non-Javadoc)
432: * @see org.pentaho.designstudio.editors.actionsequence.pages.actions.ActionIOViewer#createLabelProvider()
433: */
434: protected void createLabelProvider() {
435: setLabelProvider(new LabelProvider());
436: }
437:
438: protected void addNewIOElement(String variableName) {
439: actionDefinition.addOutputParam(variableName,
440: ActionSequenceDocument.STRING_TYPE);
441: }
442:
443: /* (non-Javadoc)
444: * @see org.pentaho.designstudio.editors.actionsequence.pages.actions.ActionIOViewer#createCellEditors()
445: */
446: protected void createCellEditors() {
447: Table table = getTable();
448:
449: outputNameCellEditor = new OutputNameCellEditor(table);
450: outputTypeCellEditor = new OutputTypeCellEditor(table);
451:
452: CellEditor[] editors = new CellEditor[] { outputNameCellEditor,
453: outputTypeCellEditor };
454: setCellEditors(editors);
455: setCellModifier(new OutputModifier());
456: setColumnProperties(new String[] { NAME_COLUMN_PROP,
457: TYPE_COLUMN_PROP });
458: }
459:
460: }
|