001: /*******************************************************************************
002: * Copyright (c) 2006, 2007 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.pde.internal.ui.editor.cheatsheet.simple.details;
011:
012: import java.util.Iterator;
013: import java.util.Map;
014:
015: import org.eclipse.core.commands.ParameterizedCommand;
016: import org.eclipse.core.commands.SerializationException;
017: import org.eclipse.core.commands.common.NotDefinedException;
018: import org.eclipse.core.expressions.IEvaluationContext;
019: import org.eclipse.jface.fieldassist.ControlDecoration;
020: import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
021: import org.eclipse.jface.window.Window;
022: import org.eclipse.pde.internal.core.icheatsheet.simple.ISimpleCSCommand;
023: import org.eclipse.pde.internal.core.icheatsheet.simple.ISimpleCSConstants;
024: import org.eclipse.pde.internal.core.icheatsheet.simple.ISimpleCSItem;
025: import org.eclipse.pde.internal.core.icheatsheet.simple.ISimpleCSRun;
026: import org.eclipse.pde.internal.core.icheatsheet.simple.ISimpleCSRunContainerObject;
027: import org.eclipse.pde.internal.core.util.PDETextHelper;
028: import org.eclipse.pde.internal.ui.PDEPlugin;
029: import org.eclipse.pde.internal.ui.PDEUIMessages;
030: import org.eclipse.pde.internal.ui.commands.CommandComposerDialog;
031: import org.eclipse.pde.internal.ui.commands.CommandComposerPart;
032: import org.eclipse.pde.internal.ui.editor.FormLayoutFactory;
033: import org.eclipse.pde.internal.ui.editor.cheatsheet.CSAbstractSubDetails;
034: import org.eclipse.pde.internal.ui.editor.cheatsheet.ICSMaster;
035: import org.eclipse.pde.internal.ui.editor.cheatsheet.simple.SimpleCSInputContext;
036: import org.eclipse.swt.SWT;
037: import org.eclipse.swt.events.SelectionAdapter;
038: import org.eclipse.swt.events.SelectionEvent;
039: import org.eclipse.swt.graphics.Color;
040: import org.eclipse.swt.layout.GridData;
041: import org.eclipse.swt.widgets.Button;
042: import org.eclipse.swt.widgets.Composite;
043: import org.eclipse.swt.widgets.Label;
044: import org.eclipse.swt.widgets.Table;
045: import org.eclipse.swt.widgets.TableColumn;
046: import org.eclipse.swt.widgets.TableItem;
047: import org.eclipse.ui.IWorkbench;
048: import org.eclipse.ui.PlatformUI;
049: import org.eclipse.ui.commands.ICommandService;
050: import org.eclipse.ui.forms.IFormColors;
051: import org.eclipse.ui.forms.widgets.ExpandableComposite;
052: import org.eclipse.ui.forms.widgets.FormToolkit;
053: import org.eclipse.ui.forms.widgets.Section;
054: import org.eclipse.ui.handlers.IHandlerService;
055: import org.eclipse.ui.internal.handlers.HandlerService;
056:
057: /**
058: * SimpleCSCommandDetailsSection
059: *
060: */
061: public class SimpleCSCommandDetails extends CSAbstractSubDetails {
062:
063: private ISimpleCSRun fRun;
064:
065: private Table fCommandTable;
066:
067: private SimpleCSCommandComboPart fCommandCombo;
068:
069: private ControlDecoration fCommandInfoDecoration;
070:
071: private Button fCommandBrowse;
072:
073: private Button fCommandOptional;
074:
075: private static final String F_NO_COMMAND = PDEUIMessages.SimpleCSCommandDetails_6;
076:
077: private static final int F_COMMAND_INSERTION_INDEX = 1;
078:
079: /**
080: * @param section
081: */
082: public SimpleCSCommandDetails(ICSMaster section) {
083: super (section, SimpleCSInputContext.CONTEXT_ID);
084: fRun = null;
085:
086: fCommandTable = null;
087: fCommandCombo = null;
088: fCommandInfoDecoration = null;
089: fCommandBrowse = null;
090: fCommandOptional = null;
091: }
092:
093: /* (non-Javadoc)
094: * @see org.eclipse.pde.internal.ui.editor.cheatsheet.CSAbstractDetails#setData(java.lang.Object)
095: */
096: public void setData(ISimpleCSRun object) {
097: // Set data
098: fRun = object;
099: }
100:
101: /* (non-Javadoc)
102: * @see org.eclipse.pde.internal.ui.editor.cheatsheet.simple.details.ISimpleCSDetails#createDetails(org.eclipse.swt.widgets.Composite)
103: */
104: public void createDetails(Composite parent) {
105:
106: int columnSpan = 3;
107: Section commandSection = null;
108: FormToolkit toolkit = getToolkit();
109: Color foreground = toolkit.getColors().getColor(
110: IFormColors.TITLE);
111: GridData data = null;
112: Label label = null;
113:
114: // Create command section
115: commandSection = toolkit.createSection(parent,
116: Section.DESCRIPTION | ExpandableComposite.TITLE_BAR);
117: commandSection.clientVerticalSpacing = FormLayoutFactory.SECTION_HEADER_VERTICAL_SPACING;
118: commandSection.setText(PDEUIMessages.SimpleCSItemDetails_5);
119: commandSection
120: .setDescription(PDEUIMessages.SimpleCSItemDetails_6);
121: commandSection.setLayout(FormLayoutFactory
122: .createClearGridLayout(false, 1));
123: data = new GridData(GridData.FILL_HORIZONTAL);
124: commandSection.setLayoutData(data);
125:
126: // Create container for command section
127: Composite commandSectionClient = toolkit
128: .createComposite(commandSection);
129: commandSectionClient.setLayout(FormLayoutFactory
130: .createSectionClientGridLayout(false, columnSpan));
131:
132: // Element: command
133: // Label
134: label = toolkit.createLabel(commandSectionClient,
135: PDEUIMessages.SimpleCSItemDetails_7, SWT.WRAP);
136: label.setForeground(foreground);
137: // Combo box
138: fCommandCombo = new SimpleCSCommandComboPart();
139: fCommandCombo.createControl(commandSectionClient, toolkit,
140: SWT.READ_ONLY);
141: data = new GridData(GridData.FILL_HORIZONTAL);
142: data.horizontalIndent = FormLayoutFactory.CONTROL_HORIZONTAL_INDENT;
143: fCommandCombo.getControl().setLayoutData(data);
144: // Insertion index is 0 for no command combo box entry
145: // Always keep this entry as the first entry
146: fCommandCombo.add(F_NO_COMMAND);
147: fCommandCombo.setText(F_NO_COMMAND);
148: fCommandCombo.populate();
149: // Always insert new command keys obtained from other combo boxes in
150: // the position after the no command entry
151: fCommandCombo.setNewCommandKeyIndex(F_COMMAND_INSERTION_INDEX);
152: // Limit the combo box to the 11 most recent entries (includes no
153: // command entry)
154: fCommandCombo.setComboEntryLimit(11);
155:
156: createCommandInfoDecoration();
157: // Button
158: fCommandBrowse = toolkit.createButton(commandSectionClient,
159: PDEUIMessages.GeneralInfoSection_browse, SWT.PUSH);
160:
161: // Element: command
162: // Label for parameters
163: label = toolkit.createLabel(commandSectionClient,
164: PDEUIMessages.SimpleCSItemDetails_8, SWT.WRAP);
165: label.setForeground(foreground);
166: data = new GridData(GridData.FILL_HORIZONTAL);
167: data.horizontalSpan = columnSpan;
168: label.setLayoutData(data);
169:
170: fCommandTable = toolkit.createTable(commandSectionClient,
171: SWT.SINGLE | SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL
172: | SWT.FULL_SELECTION);
173: data = new GridData(GridData.FILL_HORIZONTAL);
174: data.heightHint = 25;
175: data.horizontalSpan = columnSpan;
176: fCommandTable.setLayoutData(data);
177: //fCommandTable.setHeaderVisible(true);
178: fCommandTable.setLinesVisible(true);
179: //fCommandTable.setForeground(foreground);
180: TableColumn tableColumn1 = new TableColumn(fCommandTable,
181: SWT.LEFT);
182: tableColumn1.setText(PDEUIMessages.SimpleCSItemDetails_9);
183: TableColumn tableColumn2 = new TableColumn(fCommandTable,
184: SWT.LEFT);
185: tableColumn2.setText(PDEUIMessages.SimpleCSItemDetails_10);
186:
187: // Attribute: required
188: fCommandOptional = getToolkit()
189: .createButton(
190: commandSectionClient,
191: PDEUIMessages.SimpleCSCommandDetails_UICheckBoxOptionalCommand,
192: SWT.CHECK);
193: data = new GridData(GridData.FILL_HORIZONTAL);
194: data.horizontalSpan = columnSpan;
195: fCommandOptional.setLayoutData(data);
196: fCommandOptional.setForeground(foreground);
197:
198: // Bind widgets
199: toolkit.paintBordersFor(commandSectionClient);
200: commandSection.setClient(commandSectionClient);
201: // Mark as a details part to enable cut, copy, paste, etc.
202: markDetailsPart(commandSection);
203: }
204:
205: /**
206: * @param label
207: */
208: private void createCommandInfoDecoration() {
209: // Command info decoration
210: int bits = SWT.TOP | SWT.LEFT;
211: fCommandInfoDecoration = new ControlDecoration(fCommandCombo
212: .getControl(), bits);
213: fCommandInfoDecoration.setMarginWidth(1);
214: fCommandInfoDecoration
215: .setDescriptionText(PDEUIMessages.SimpleCSCommandDetails_msgFieldDisabledCommand);
216: updateCommandInfoDecoration(false);
217: fCommandInfoDecoration.setImage(FieldDecorationRegistry
218: .getDefault().getFieldDecoration(
219: FieldDecorationRegistry.DEC_INFORMATION)
220: .getImage());
221: }
222:
223: /* (non-Javadoc)
224: * @see org.eclipse.pde.internal.ui.editor.cheatsheet.simple.details.ISimpleCSDetails#hookListeners()
225: */
226: public void hookListeners() {
227:
228: // Element: command
229: fCommandCombo.addSelectionListener(new SelectionAdapter() {
230: public void widgetSelected(SelectionEvent e) {
231: // Ensure data object is defined
232: if (fRun == null) {
233: return;
234: }
235: String selection = fCommandCombo.getSelection();
236: if (selection.equals(F_NO_COMMAND) == false) {
237: // Get the associated serialization stored as data against the
238: // command name
239: String serialization = fCommandCombo
240: .getValue(selection);
241: if (PDETextHelper.isDefined(serialization)) {
242: // Create the new command in the model
243: createCommandInModel(serialization);
244:
245: ParameterizedCommand result = getParameterizedCommand(serialization);
246: if (result != null) {
247: updateCommandTable(result.getParameterMap());
248: }
249: }
250: } else {
251: // The empty entry was selected
252: // Delete the existing command
253: fRun.setExecutable(null);
254: fCommandTable.clearAll();
255: }
256: // Update the master section buttons
257: getMasterSection().updateButtons();
258: // Update the optional command checkbox
259: updateUICommandOptional();
260: }
261: });
262:
263: fCommandBrowse.addSelectionListener(new SelectionAdapter() {
264: public void widgetSelected(SelectionEvent e) {
265: // Ensure data object is defined
266: if (fRun == null) {
267: return;
268: }
269: // Open the command composer dialog using the input from the
270: // currently selected command
271: CommandComposerDialog dialog = new CommandComposerDialog(
272: fCommandBrowse.getShell(),
273: CommandComposerPart.F_CHEATSHEET_FILTER,
274: getParameterizedCommand(fRun),
275: getSnapshotContext());
276: // Check result of dialog
277: if (dialog.open() == Window.OK) {
278: // Command composer exited successfully
279: // Update accordingly
280: updateCommandCombo(dialog.getCommand(), true);
281: // Update the master section buttons
282: getMasterSection().updateButtons();
283: // Update the optional command checkbox
284: updateUICommandOptional();
285: }
286: }
287: });
288:
289: // Attribute: required
290: fCommandOptional.addSelectionListener(new SelectionAdapter() {
291: public void widgetSelected(SelectionEvent e) {
292: // Ensure data object is defined
293: if (fRun == null) {
294: return;
295: }
296: // Get the command
297: ISimpleCSCommand commandObject = getCommandObject(fRun);
298: // Ensure the command is defined
299: if (commandObject == null) {
300: return;
301: }
302: // Set required value in model
303: boolean isRequired = (fCommandOptional.getSelection() == false);
304: commandObject.setRequired(isRequired);
305: }
306: });
307: }
308:
309: /* (non-Javadoc)
310: * @see org.eclipse.pde.internal.ui.editor.cheatsheet.simple.details.ISimpleCSDetails#updateFields()
311: */
312: public void updateFields() {
313: // Ensure data object is defined
314: if (fRun == null) {
315: return;
316: }
317: // i.e. Action: class
318: ParameterizedCommand command = getParameterizedCommand(fRun);
319: if (command == null) {
320: // Since, this page is static the command combo and command table
321: // must be reset
322: clearCommandUI();
323: } else {
324: updateCommandCombo(command, false);
325: }
326: // Update the optional command checkbox
327: updateUICommandOptional();
328: // Update command UI enablement
329: updateCommandEnablement();
330: }
331:
332: /**
333: *
334: */
335: private void updateUICommandOptional() {
336: // Attribute: required
337: ISimpleCSCommand commandObject = getCommandObject(fRun);
338: if (commandObject == null) {
339: fCommandOptional.setSelection(false);
340: fCommandOptional.setEnabled(false);
341: } else {
342: boolean isOptional = (commandObject.getRequired() == false);
343: fCommandOptional.setSelection(isOptional);
344: fCommandOptional.setEnabled(isEditableElement());
345: }
346: }
347:
348: /**
349: * @param runObject
350: * @return
351: */
352: private ISimpleCSCommand getCommandObject(ISimpleCSRun runObject) {
353: // Ensure the run object is defined
354: if (runObject == null) {
355: return null;
356: }
357: // Get the executable
358: ISimpleCSRunContainerObject executable = runObject
359: .getExecutable();
360: // Ensure executable is defined
361: if (executable == null) {
362: return null;
363: } else if (executable.getType() != ISimpleCSConstants.TYPE_COMMAND) {
364: // Not a command
365: return null;
366: }
367: return (ISimpleCSCommand) executable;
368: }
369:
370: /**
371: *
372: */
373: private void clearCommandUI() {
374: // Clear the command combo
375: fCommandCombo.setText(F_NO_COMMAND);
376: // Clear the command table
377: fCommandTable.clearAll();
378: }
379:
380: /**
381: *
382: */
383: private void updateCommandEnablement() {
384: // Ensure data object is defined
385: if (fRun == null) {
386: return;
387: }
388: boolean editable = isEditableElement();
389:
390: if (fRun.getType() == ISimpleCSConstants.TYPE_ITEM) {
391: ISimpleCSItem item = (ISimpleCSItem) fRun;
392: // Preserve cheat sheet validity
393: // Semantic Rule: Cannot have a subitem and any of the following
394: // together: perform-when, command, action
395: if (item.hasSubItems()) {
396: editable = false;
397: updateCommandInfoDecoration(true);
398: } else {
399: updateCommandInfoDecoration(false);
400: }
401: }
402:
403: fCommandCombo.setEnabled(editable);
404: fCommandTable.setEnabled(true);
405: fCommandBrowse.setEnabled(editable);
406: }
407:
408: /**
409: * @param serialization
410: */
411: private void createCommandInModel(String serialization) {
412: // Ensure data object is defined
413: if (fRun == null) {
414: return;
415: }
416: ISimpleCSCommand command = fRun.getModel().getFactory()
417: .createSimpleCSCommand(fRun);
418: command.setSerialization(serialization);
419: command.setRequired(false);
420: fRun.setExecutable(command);
421: }
422:
423: /**
424: * @param result
425: * @param createInModel
426: */
427: private void updateCommandCombo(ParameterizedCommand result,
428: boolean createInModel) {
429:
430: if (result == null) {
431: return;
432: }
433: // Get serialization
434: String serialization = result.serialize();
435: // Get presentable command name
436: String commandName = null;
437: try {
438: commandName = result.getCommand().getName();
439: } catch (NotDefinedException e) {
440: // Ignore, name will be undefined
441: }
442: // Get command ID
443: String commandId = result.getId();
444:
445: if (PDETextHelper.isDefined(serialization)
446: && PDETextHelper.isDefined(commandId)) {
447: if (createInModel) {
448: // Create the new command in the model
449: createCommandInModel(serialization);
450: }
451: // Determine the presentable name to use in the combo box and the
452: // key to store the serialization data against in the widget
453: String nameToUse = null;
454: if (PDETextHelper.isDefined(commandName)) {
455: nameToUse = commandName;
456: } else {
457: nameToUse = commandId;
458: }
459: // Add new selection to the combo box if it is not already there
460: // Associate the serialization with the command name
461: // in the widget to retrieve for later use
462: fCommandCombo.putValue(nameToUse, serialization,
463: F_COMMAND_INSERTION_INDEX);
464: // Select it
465: fCommandCombo.setText(nameToUse);
466: // Update the command table parameters
467: updateCommandTable(result.getParameterMap());
468: } else {
469: // No serialization, something bad happened
470: fCommandCombo.setText(F_NO_COMMAND);
471: }
472:
473: }
474:
475: /**
476: * @param serialization
477: * @return
478: */
479: private ParameterizedCommand getParameterizedCommand(
480: String serialization) {
481: if (PDETextHelper.isDefined(serialization)) {
482: ICommandService service = getCommandService();
483: if (service != null) {
484: try {
485: return service.deserialize(serialization);
486: } catch (NotDefinedException e) {
487: PDEPlugin
488: .logException(
489: e,
490: PDEUIMessages.SimpleCSCommandDetails_DFErrorTitle,
491: PDEUIMessages.SimpleCSCommandDetails_DFErrorBody
492: + serialization);
493: } catch (SerializationException e) {
494: PDEPlugin
495: .logException(
496: e,
497: PDEUIMessages.SimpleCSCommandDetails_DFErrorTitle,
498: PDEUIMessages.SimpleCSCommandDetails_DFErrorBody
499: + serialization);
500: }
501: }
502: }
503: return null;
504: }
505:
506: /**
507: * @param run
508: * @return
509: */
510: private ParameterizedCommand getParameterizedCommand(
511: ISimpleCSRun run) {
512: if (run == null) {
513: return null;
514: }
515: ISimpleCSRunContainerObject object = run.getExecutable();
516: if ((object != null)
517: && (object.getType() == ISimpleCSConstants.TYPE_COMMAND)) {
518: ISimpleCSCommand command = (ISimpleCSCommand) object;
519: return getParameterizedCommand(command.getSerialization());
520: }
521: return null;
522: }
523:
524: /**
525: * @param parameters
526: */
527: private void updateCommandTable(Map parameters) {
528: // Clear the table contents
529: fCommandTable.clearAll();
530:
531: if ((parameters != null) && (parameters.isEmpty() == false)) {
532: // Iterate over the keys in the map
533: Iterator it = parameters.keySet().iterator();
534: int rowCount = 0;
535: while (it.hasNext()) {
536: // Track number of keys / rows processed
537: TableItem item = null;
538: // Determine if there is an existing row already at that index
539: if (rowCount < fCommandTable.getItemCount()) {
540: // There is, reuse it
541: item = fCommandTable.getItem(rowCount);
542: } else {
543: // There isn't, create a new one
544: item = new TableItem(fCommandTable, SWT.NONE);
545: }
546: // Get key
547: Object key = it.next();
548: if (key instanceof String) {
549: String keyString = (String) key;
550: // If present, remove the fully qualified ID from the
551: // paramater key
552: // i.e. "org.eclipse.ui.perspective" becomes just
553: // "perspective"
554: int dotIndex = keyString.lastIndexOf('.');
555: if ((dotIndex != -1)
556: && (dotIndex != (keyString.length() - 1))) {
557: keyString = keyString.substring(dotIndex + 1);
558: }
559: // Set parameter key in first column
560: item.setText(0, keyString);
561: }
562: Object value = parameters.get(key);
563: if (value instanceof String) {
564: // Set parameter value in second column
565: item.setText(1, (String) value);
566: }
567: rowCount++;
568: }
569: // Pack the columns with the new data
570: for (int i = 0; i < fCommandTable.getColumnCount(); i++) {
571: TableColumn tableColumn = fCommandTable.getColumn(i);
572: tableColumn.pack();
573: }
574: }
575: }
576:
577: /**
578: * @return
579: */
580: private static ICommandService getCommandService() {
581: IWorkbench workbench = PlatformUI.getWorkbench();
582: return (ICommandService) workbench
583: .getAdapter(ICommandService.class);
584: }
585:
586: /**
587: * @return
588: */
589: private static IHandlerService getGlobalHandlerService() {
590: return (IHandlerService) PlatformUI.getWorkbench().getService(
591: IHandlerService.class);
592: }
593:
594: /**
595: * @return
596: */
597: private static IEvaluationContext getSnapshotContext() {
598: IHandlerService service = getGlobalHandlerService();
599: // TODO: MP: SimpleCS: Get rid of internal class use when context snapshots are made API
600: if (service instanceof HandlerService) {
601: return ((HandlerService) service).getContextSnapshot();
602: }
603: return null;
604: }
605:
606: /**
607: *
608: */
609: private void updateCommandInfoDecoration(boolean showDecoration) {
610: if (showDecoration) {
611: fCommandInfoDecoration.show();
612: } else {
613: fCommandInfoDecoration.hide();
614: }
615: fCommandInfoDecoration.setShowHover(showDecoration);
616: }
617:
618: /* (non-Javadoc)
619: * @see org.eclipse.ui.forms.AbstractFormPart#commit(boolean)
620: */
621: public void commit(boolean onSave) {
622: super .commit(onSave);
623: // NO-OP
624: // No form entries
625: }
626: }
|