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