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.eclipse.core.runtime.IStatus;
021: import org.eclipse.core.runtime.Status;
022: import org.eclipse.jface.dialogs.ErrorDialog;
023: import org.eclipse.jface.util.Assert;
024: import org.eclipse.jface.viewers.CellEditor;
025: import org.eclipse.jface.viewers.ICellModifier;
026: import org.eclipse.jface.viewers.IContentProvider;
027: import org.eclipse.jface.viewers.ILabelProviderListener;
028: import org.eclipse.jface.viewers.ITableLabelProvider;
029: import org.eclipse.jface.viewers.StructuredSelection;
030: import org.eclipse.jface.viewers.TextCellEditor;
031: import org.eclipse.swt.SWT;
032: import org.eclipse.swt.custom.CCombo;
033: import org.eclipse.swt.events.FocusAdapter;
034: import org.eclipse.swt.events.FocusEvent;
035: import org.eclipse.swt.events.KeyAdapter;
036: import org.eclipse.swt.events.KeyEvent;
037: import org.eclipse.swt.events.KeyListener;
038: import org.eclipse.swt.events.SelectionAdapter;
039: import org.eclipse.swt.events.SelectionEvent;
040: import org.eclipse.swt.events.TraverseEvent;
041: import org.eclipse.swt.events.TraverseListener;
042: import org.eclipse.swt.graphics.GC;
043: import org.eclipse.swt.graphics.Image;
044: import org.eclipse.swt.widgets.Composite;
045: import org.eclipse.swt.widgets.Control;
046: import org.eclipse.swt.widgets.Table;
047: import org.eclipse.swt.widgets.TableColumn;
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 GenericActionOutputsTable extends ActionIOTable {
063:
064: static final String MAPPING_COLUMN_PROP = "MAPPING"; //$NON-NLS-1$
065:
066: static final int MAPPING_COLUMN_IDX = 2;
067:
068: OutputNameCellEditor outputNameCellEditor;
069: OutputTypeCellEditor outputTypeCellEditor;
070: protected OutputMappingCellEditor outputMappingCellEditor;
071:
072: class OutputMappingCellEditor extends TextCellEditor {
073: boolean valueChanged = false;
074: boolean pressedReturn = false;
075:
076: public OutputMappingCellEditor(Composite parent) {
077: super (parent);
078: Text text = (Text) getControl();
079: text.addKeyListener(new KeyListener() {
080:
081: public void keyPressed(KeyEvent e) {
082: e.doit = !Character.isWhitespace(e.character)
083: && (e.character != '-');
084: }
085:
086: public void keyReleased(KeyEvent e) {
087: }
088:
089: });
090: }
091:
092: protected void handleDefaultSelection(SelectionEvent event) {
093: pressedReturn = true;
094: super .handleDefaultSelection(event);
095: }
096:
097: protected void doSetValue(Object value) {
098: if (value instanceof ActionOutput) {
099: ActionOutput actionOutput = (ActionOutput) value;
100: String logicalName = actionOutput.getPublicName();
101: if (logicalName.equals(actionOutput.getName())) {
102: super .doSetValue(""); //$NON-NLS-1$
103: } else {
104: super .doSetValue(logicalName);
105: }
106: } else {
107: super .doSetValue(value);
108: }
109: valueChanged = false;
110: pressedReturn = false;
111: }
112:
113: public void deactivate() {
114: super .deactivate();
115: if (valueChanged) {
116: valueChanged = false;
117: int selectedIndex = getTable().getSelectionIndex();
118: TableItem tableItem = getTable().getItem(selectedIndex);
119: if ((pressedReturn)
120: && (tableItem.getData() instanceof ActionOutput)) {
121: ;
122: editElement(tableItem.getData(), 1);
123: }
124: }
125: }
126: }
127:
128: class OutputNameCellEditor extends TextCellEditor {
129: boolean valueChanged = false;
130: boolean pressedReturn = false;
131:
132: public OutputNameCellEditor(Composite parent) {
133: super (parent);
134: Text text = (Text) getControl();
135: text.addKeyListener(new KeyListener() {
136:
137: public void keyPressed(KeyEvent e) {
138: e.doit = !Character.isWhitespace(e.character)
139: && (e.character != '-');
140: }
141:
142: public void keyReleased(KeyEvent e) {
143: }
144:
145: });
146: }
147:
148: protected void handleDefaultSelection(SelectionEvent event) {
149: pressedReturn = true;
150: super .handleDefaultSelection(event);
151: }
152:
153: protected void doSetValue(Object value) {
154: if (value instanceof ActionOutput) {
155: super .doSetValue(((ActionOutput) value).getName());
156: } else {
157: super .doSetValue(value);
158: }
159: valueChanged = false;
160: pressedReturn = false;
161: }
162:
163: public void deactivate() {
164: super .deactivate();
165: if (valueChanged) {
166: valueChanged = false;
167: int selectedIndex = getTable().getSelectionIndex();
168: TableItem tableItem = getTable().getItem(selectedIndex);
169: if ((pressedReturn)
170: && (tableItem.getData() instanceof ActionOutput)) {
171: ;
172: editElement(tableItem.getData(), 1);
173: }
174: }
175: }
176: }
177:
178: class OutputTypeCellEditor extends CellEditor {
179: boolean valueChanged = false;
180:
181: boolean pressedReturn = false;
182:
183: private String[] items;
184:
185: int selection;
186:
187: CCombo comboBox;
188:
189: private static final int defaultStyle = SWT.NONE;
190:
191: public OutputTypeCellEditor(Composite parent) {
192: super (parent, defaultStyle);
193: setItems(ActionSequenceDocument.IO_TYPES);
194: }
195:
196: public String[] getItems() {
197: return this .items;
198: }
199:
200: public void setItems(String[] items) {
201: Assert.isNotNull(items);
202: this .items = items;
203: populateComboBoxItems();
204: }
205:
206: protected Control createControl(Composite parent) {
207:
208: comboBox = new CCombo(parent, getStyle());
209: comboBox.setFont(parent.getFont());
210:
211: comboBox.addKeyListener(new KeyAdapter() {
212: // hook key pressed - see PR 14201
213: public void keyPressed(KeyEvent e) {
214: keyReleaseOccured(e);
215: }
216: });
217:
218: comboBox.addSelectionListener(new SelectionAdapter() {
219: public void widgetDefaultSelected(SelectionEvent event) {
220: pressedReturn = true;
221: applyEditorValueAndDeactivate();
222: }
223:
224: public void widgetSelected(SelectionEvent event) {
225: selection = comboBox.getSelectionIndex();
226: }
227: });
228:
229: comboBox.addTraverseListener(new TraverseListener() {
230: public void keyTraversed(TraverseEvent e) {
231: if (e.detail == SWT.TRAVERSE_ESCAPE
232: || e.detail == SWT.TRAVERSE_RETURN) {
233: e.doit = false;
234: }
235: }
236: });
237:
238: comboBox.addFocusListener(new FocusAdapter() {
239: public void focusLost(FocusEvent e) {
240: OutputTypeCellEditor.this .focusLost();
241: }
242: });
243: return comboBox;
244: }
245:
246: /* (non-Javadoc)
247: * @see org.eclipse.jface.viewers.CellEditor#doGetValue()
248: */
249: protected Object doGetValue() {
250: Object value = null;
251: CCombo combo = (CCombo) getControl();
252: int selectedIdx = combo.getSelectionIndex();
253: if (selectedIdx >= 0) {
254: value = combo.getItem(selectedIdx);
255: }
256: return value;
257: }
258:
259: protected void doSetFocus() {
260: comboBox.setFocus();
261: }
262:
263: public LayoutData getLayoutData() {
264: LayoutData layoutData = super .getLayoutData();
265: if ((comboBox == null) || comboBox.isDisposed())
266: layoutData.minimumWidth = 60;
267: else {
268: // make the comboBox 10 characters wide
269: GC gc = new GC(comboBox);
270: layoutData.minimumWidth = (gc.getFontMetrics()
271: .getAverageCharWidth() * 10) + 10;
272: gc.dispose();
273: }
274: return layoutData;
275: }
276:
277: protected void doSetValue(Object value) {
278: valueChanged = false;
279: pressedReturn = false;
280: String typeStr = null;
281: if (value instanceof AbstractIOElement) {
282: AbstractIOElement ioElement = (AbstractIOElement) value;
283: typeStr = ioElement.getType();
284: }
285:
286: ((CCombo) getControl()).setText(typeStr != null ? typeStr
287: : ""); //$NON-NLS-1$
288: }
289:
290: private void populateComboBoxItems() {
291: if (comboBox != null && items != null) {
292: comboBox.removeAll();
293: for (int i = 0; i < items.length; i++)
294: comboBox.add(items[i], i);
295:
296: setValueValid(true);
297: selection = 0;
298: }
299: }
300:
301: void applyEditorValueAndDeactivate() {
302: selection = comboBox.getSelectionIndex();
303: Object newValue = doGetValue();
304: markDirty();
305: boolean isValid = isCorrect(newValue);
306: setValueValid(isValid);
307: if (!isValid) {
308: // try to insert the current value into the error message.
309: setErrorMessage(MessageFormat.format(getErrorMessage(),
310: new Object[] { items[selection] }));
311: }
312: fireApplyEditorValue();
313: deactivate();
314: }
315:
316: protected void focusLost() {
317: if (isActivated()) {
318: applyEditorValueAndDeactivate();
319: }
320: }
321:
322: protected void keyReleaseOccured(KeyEvent keyEvent) {
323: if (keyEvent.character == '\u001b') { // Escape character
324: fireCancelEditor();
325: } else if (keyEvent.character == '\t') { // tab key
326: applyEditorValueAndDeactivate();
327: }
328: }
329:
330: public void deactivate() {
331: // TODO Auto-generated method stub
332: super .deactivate();
333: if (valueChanged) {
334: valueChanged = false;
335: int selectedIndex = getTable().getSelectionIndex();
336: TableItem tableItem = getTable().getItem(selectedIndex);
337: if ((pressedReturn)
338: && (tableItem.getData() instanceof ActionOutput)) {
339: ;
340: editElement(tableItem.getData(), 2);
341: }
342: }
343: }
344: }
345:
346: class LabelProvider implements ITableLabelProvider {
347:
348: List listeners = new ArrayList();
349:
350: public LabelProvider() {
351: super ();
352: }
353:
354: public Image getColumnImage(Object element, int columnIndex) {
355: return null;
356: }
357:
358: public String getColumnText(Object element, int columnIndex) {
359: String columnText = ""; //$NON-NLS-1$
360: if (element == ActionUtil.NEW_IO_PLACEHOLDER) {
361: if (columnIndex == NAME_COLUMN_IDX) {
362: columnText = element.toString();
363: }
364: } else if (element instanceof AbstractActionIOElement) {
365: ActionOutput outputElement = (ActionOutput) element;
366: switch (columnIndex) {
367: case NAME_COLUMN_IDX:
368: columnText = outputElement.getName();
369: break;
370: case TYPE_COLUMN_IDX:
371: columnText = outputElement.getType();
372: break;
373: case MAPPING_COLUMN_IDX:
374: columnText = outputElement.getPublicName();
375: if (columnText.equals(outputElement.getName())) {
376: columnText = ""; //$NON-NLS-1$
377: }
378: break;
379: }
380: }
381: return columnText;
382: }
383:
384: public void addListener(ILabelProviderListener listener) {
385: listeners.add(listener);
386: }
387:
388: public void dispose() {
389: }
390:
391: public boolean isLabelProperty(Object element, String property) {
392: return true;
393: }
394:
395: public void removeListener(ILabelProviderListener listener) {
396: listeners.add(listener);
397: }
398:
399: }
400:
401: class OutputModifier implements ICellModifier {
402:
403: public boolean canModify(Object element, String property) {
404: return (element instanceof ActionOutput)
405: || property.equals(NAME_COLUMN_PROP);
406: }
407:
408: public Object getValue(Object tableObject, String property) {
409: Object value = tableObject;
410: if (property.equals(ActionIOTable.NAME_COLUMN_PROP)) {
411: if (tableObject instanceof ActionOutput) {
412: value = ((ActionOutput) tableObject).getName();
413: } else if (tableObject == ActionUtil.NEW_IO_PLACEHOLDER) {
414: value = ""; //$NON-NLS-1$
415: }
416: }
417: return value;
418: }
419:
420: public void modify(Object tableObject, String property,
421: Object value) {
422: if (value != null) {
423: if (property.equals(MAPPING_COLUMN_PROP)) {
424: TableItem tableItem = (TableItem) tableObject;
425: if (tableItem.getData() instanceof AbstractIOElement) {
426: AbstractActionIOElement io = (AbstractActionIOElement) tableItem
427: .getData();
428: value = value.toString();
429: if (!value.equals("")) { //$NON-NLS-1$
430: io.setMapping(value.toString());
431: } else {
432: io.setMapping(null);
433: }
434: refresh(io);
435: }
436: outputMappingCellEditor.valueChanged = true;
437: } else {
438: TableItem tableItem = (TableItem) tableObject;
439: if (property.equals(ActionIOTable.NAME_COLUMN_PROP)) {
440: String name = ((String) value).trim();
441: if (name.length() == 0) {
442: if (tableItem.getData() instanceof AbstractActionIOElement) {
443: ErrorDialog
444: .openError(
445: getTable().getShell(),
446: Messages
447: .getString("GenericActionOutputsTable.OUTPUT_ERROR"), Messages.getString("GenericActionOutputsTable.INVALID_OUTPUT_NAME"), new Status(IStatus.ERROR, Messages.getString("GenericActionInputsTable.DESIGN_STUDIO"), 0, Messages.getString("GenericActionOutputsTable.EMPTY_OUTPUT_NAME"), null)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
448: }
449: } else if (name.split("\\s+").length != 1) { //$NON-NLS-1$
450: ErrorDialog
451: .openError(
452: getTable().getShell(),
453: Messages
454: .getString("GenericActionOutputsTable.OUTPUT_ERROR"), Messages.getString("GenericActionOutputsTable.INVALID_OUTPUT_NAME"), new Status(IStatus.ERROR, Messages.getString("GenericActionInputsTable.DESIGN_STUDIO"), 0, Messages.getString("GenericActionOutputsTable.NO_SPACES_IN_OUTPUT_NAME"), null)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
455: } else {
456: if (tableItem.getData() instanceof AbstractActionIOElement) {
457: AbstractActionIOElement ioElement = (AbstractActionIOElement) tableItem
458: .getData();
459: ioElement.setName(name);
460: refresh(ioElement);
461: } else if ((name.length() > 0)
462: && (tableItem.getData() == ActionUtil.NEW_IO_PLACEHOLDER)) {
463: addNewIOElement(name);
464: refresh();
465: setSelection(new StructuredSelection(
466: getElementAt(getTable()
467: .getItemCount() - 2)));
468: }
469: outputNameCellEditor.valueChanged = true;
470: }
471: } else if (property
472: .equals(ActionIOTable.TYPE_COLUMN_PROP)) {
473: if (tableItem.getData() instanceof AbstractActionIOElement) {
474: AbstractActionIOElement ioElement = (AbstractActionIOElement) tableItem
475: .getData();
476: if (Arrays.asList(
477: ActionSequenceDocument.IO_TYPES)
478: .contains(value)) {
479: ioElement.setType(value.toString());
480: refresh(ioElement);
481: }
482: }
483: outputTypeCellEditor.valueChanged = true;
484: }
485: }
486: }
487: }
488: }
489:
490: /**
491: * Creates an GenericActionOutputsTable
492: * @param parent the parent of this viewer.
493: * @param toolkit the form toolkit.
494: */
495: public GenericActionOutputsTable(Composite parent) {
496: super (parent);
497: }
498:
499: /* (non-Javadoc)
500: * @see org.pentaho.designstudio.editors.actionsequence.pages.actions.ActionIOViewer#createContentProvider()
501: */
502: protected IContentProvider createContentProvider() {
503: return new ActionIOContentProvider(false);
504: }
505:
506: /* (non-Javadoc)
507: * @see org.pentaho.designstudio.editors.actionsequence.pages.actions.ActionIOViewer#createLabelProvider()
508: */
509: protected void createLabelProvider() {
510: setLabelProvider(new LabelProvider());
511: }
512:
513: /* (non-Javadoc)
514: * @see org.pentaho.designstudio.editors.actionsequence.pages.actions.ActionIOViewer#createCellEditors()
515: */
516: protected void createCellEditors() {
517: Table table = getTable();
518: outputMappingCellEditor = new OutputMappingCellEditor(table);
519: outputNameCellEditor = new OutputNameCellEditor(table);
520: outputTypeCellEditor = new OutputTypeCellEditor(table);
521: CellEditor[] editors = new CellEditor[] { outputNameCellEditor,
522: outputTypeCellEditor, outputMappingCellEditor };
523: setCellEditors(editors);
524: setCellModifier(new OutputModifier());
525: setColumnProperties(new String[] { NAME_COLUMN_PROP,
526: TYPE_COLUMN_PROP, MAPPING_COLUMN_PROP });
527:
528: }
529:
530: /* (non-Javadoc)
531: * @see org.pentaho.designstudio.editors.actionsequence.pages.actions.ActionIOViewer#createTableColumns()
532: */
533: protected void createTableColumns() {
534: super .createTableColumns();
535: TableColumn tableColumn = new TableColumn(getTable(), SWT.LEFT);
536: tableColumn.setText(Messages
537: .getString("ActionInputsTable.UI_MAP_TO_HEADER")); //$NON-NLS-1$
538: tableColumn.pack();
539: }
540:
541: protected void addNewIOElement(String variableName) {
542: actionDefinition.addOutputParam(variableName,
543: ActionSequenceDocument.STRING_TYPE);
544: refresh();
545: }
546:
547: }
|