001: /*******************************************************************************
002: * Copyright (c) 2005, 2006 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.ui.internal.navigator;
011:
012: import org.eclipse.jface.action.Action;
013: import org.eclipse.jface.action.IAction;
014: import org.eclipse.jface.util.IPropertyChangeListener;
015: import org.eclipse.jface.util.PropertyChangeEvent;
016: import org.eclipse.swt.SWT;
017: import org.eclipse.swt.events.KeyAdapter;
018: import org.eclipse.swt.events.KeyEvent;
019: import org.eclipse.swt.events.MouseAdapter;
020: import org.eclipse.swt.events.MouseEvent;
021: import org.eclipse.swt.widgets.Event;
022: import org.eclipse.swt.widgets.Listener;
023: import org.eclipse.swt.widgets.Text;
024: import org.eclipse.ui.IActionBars;
025: import org.eclipse.ui.PlatformUI;
026: import org.eclipse.ui.actions.ActionFactory;
027:
028: /**
029: * Handles the redirection of the global Cut, Copy, Paste, and
030: * Select All actions to either the current inline text control
031: * or the part's supplied action handler.
032: * <p>
033: * This class may be instantiated; it is not intended to be subclassed.
034: * </p><p>
035: * Example usage:
036: * <pre>
037: * textActionHandler = new TextActionHandler(this.getViewSite().getActionBars());
038: * textActionHandler.addText((Text)textCellEditor1.getControl());
039: * textActionHandler.addText((Text)textCellEditor2.getControl());
040: * textActionHandler.setSelectAllAction(selectAllAction);
041: * </pre>
042: * </p>
043: */
044: public class TextActionHandler {
045: private DeleteActionHandler textDeleteAction = new DeleteActionHandler();
046:
047: private CutActionHandler textCutAction = new CutActionHandler();
048:
049: private CopyActionHandler textCopyAction = new CopyActionHandler();
050:
051: private PasteActionHandler textPasteAction = new PasteActionHandler();
052:
053: private SelectAllActionHandler textSelectAllAction = new SelectAllActionHandler();
054:
055: private IAction deleteAction;
056:
057: private IAction cutAction;
058:
059: private IAction copyAction;
060:
061: private IAction pasteAction;
062:
063: private IAction selectAllAction;
064:
065: private IPropertyChangeListener deleteActionListener = new PropertyChangeListener(
066: textDeleteAction);
067:
068: private IPropertyChangeListener cutActionListener = new PropertyChangeListener(
069: textCutAction);
070:
071: private IPropertyChangeListener copyActionListener = new PropertyChangeListener(
072: textCopyAction);
073:
074: private IPropertyChangeListener pasteActionListener = new PropertyChangeListener(
075: textPasteAction);
076:
077: private IPropertyChangeListener selectAllActionListener = new PropertyChangeListener(
078: textSelectAllAction);
079:
080: private Listener textControlListener = new TextControlListener();
081:
082: private Text activeTextControl;
083:
084: private MouseAdapter mouseAdapter = new MouseAdapter() {
085: public void mouseUp(MouseEvent e) {
086: updateActionsEnableState();
087: }
088: };
089:
090: private KeyAdapter keyAdapter = new KeyAdapter() {
091: public void keyReleased(KeyEvent e) {
092: updateActionsEnableState();
093: }
094: };
095:
096: private class TextControlListener implements Listener {
097: public void handleEvent(Event event) {
098: switch (event.type) {
099: case SWT.Activate:
100: activeTextControl = (Text) event.widget;
101: updateActionsEnableState();
102: break;
103: case SWT.Deactivate:
104: activeTextControl = null;
105: updateActionsEnableState();
106: break;
107: default:
108: break;
109: }
110: }
111: }
112:
113: private class PropertyChangeListener implements
114: IPropertyChangeListener {
115: private IAction actionHandler;
116:
117: protected PropertyChangeListener(IAction actionHandler) {
118: super ();
119: this .actionHandler = actionHandler;
120: }
121:
122: public void propertyChange(PropertyChangeEvent event) {
123: if (activeTextControl != null) {
124: return;
125: }
126: if (event.getProperty().equals(IAction.ENABLED)) {
127: Boolean bool = (Boolean) event.getNewValue();
128: actionHandler.setEnabled(bool.booleanValue());
129: }
130: }
131: }
132:
133: private class DeleteActionHandler extends Action {
134: protected DeleteActionHandler() {
135: super (CommonNavigatorMessages.Delete);
136: setId("TextDeleteActionHandler");//$NON-NLS-1$
137: setEnabled(false);
138: PlatformUI.getWorkbench().getHelpSystem().setHelp(this ,
139: INavigatorHelpContextIds.TEXT_DELETE_ACTION);
140: }
141:
142: public void runWithEvent(Event event) {
143: if (activeTextControl != null
144: && !activeTextControl.isDisposed()) {
145: activeTextControl.clearSelection();
146: return;
147: }
148: if (deleteAction != null) {
149: deleteAction.runWithEvent(event);
150: return;
151: }
152: }
153:
154: /**
155: * Update state.
156: */
157: public void updateEnabledState() {
158: if (activeTextControl != null
159: && !activeTextControl.isDisposed()) {
160: setEnabled(activeTextControl.getSelectionCount() > 0
161: || activeTextControl.getCaretPosition() < activeTextControl
162: .getCharCount());
163: return;
164: }
165: if (deleteAction != null) {
166: setEnabled(deleteAction.isEnabled());
167: return;
168: }
169: setEnabled(false);
170: }
171: }
172:
173: private class CutActionHandler extends Action {
174: protected CutActionHandler() {
175: super (CommonNavigatorMessages.Cut);
176: setId("TextCutActionHandler");//$NON-NLS-1$
177: setEnabled(false);
178: PlatformUI.getWorkbench().getHelpSystem().setHelp(this ,
179: INavigatorHelpContextIds.TEXT_CUT_ACTION);
180: }
181:
182: public void runWithEvent(Event event) {
183: if (activeTextControl != null
184: && !activeTextControl.isDisposed()) {
185: activeTextControl.cut();
186: return;
187: }
188: if (cutAction != null) {
189: cutAction.runWithEvent(event);
190: return;
191: }
192: }
193:
194: /**
195: * Update state.
196: */
197: public void updateEnabledState() {
198: if (activeTextControl != null
199: && !activeTextControl.isDisposed()) {
200: setEnabled(activeTextControl.getSelectionCount() > 0);
201: return;
202: }
203: if (cutAction != null) {
204: setEnabled(cutAction.isEnabled());
205: return;
206: }
207: setEnabled(false);
208: }
209: }
210:
211: private class CopyActionHandler extends Action {
212: protected CopyActionHandler() {
213: super (CommonNavigatorMessages.Copy);
214: setId("TextCopyActionHandler");//$NON-NLS-1$
215: setEnabled(false);
216: PlatformUI.getWorkbench().getHelpSystem().setHelp(this ,
217: INavigatorHelpContextIds.TEXT_COPY_ACTION);
218: }
219:
220: public void runWithEvent(Event event) {
221: if (activeTextControl != null
222: && !activeTextControl.isDisposed()) {
223: activeTextControl.copy();
224: return;
225: }
226: if (copyAction != null) {
227: copyAction.runWithEvent(event);
228: return;
229: }
230: }
231:
232: /**
233: * Update the state.
234: */
235: public void updateEnabledState() {
236: if (activeTextControl != null
237: && !activeTextControl.isDisposed()) {
238: setEnabled(activeTextControl.getSelectionCount() > 0);
239: return;
240: }
241: if (copyAction != null) {
242: setEnabled(copyAction.isEnabled());
243: return;
244: }
245: setEnabled(false);
246: }
247: }
248:
249: private class PasteActionHandler extends Action {
250: protected PasteActionHandler() {
251: super (CommonNavigatorMessages.Paste);
252: setId("TextPasteActionHandler");//$NON-NLS-1$
253: setEnabled(false);
254: PlatformUI.getWorkbench().getHelpSystem().setHelp(this ,
255: INavigatorHelpContextIds.TEXT_PASTE_ACTION);
256: }
257:
258: public void runWithEvent(Event event) {
259: if (activeTextControl != null
260: && !activeTextControl.isDisposed()) {
261: activeTextControl.paste();
262: return;
263: }
264: if (pasteAction != null) {
265: pasteAction.runWithEvent(event);
266: return;
267: }
268: }
269:
270: /**
271: * Update the state
272: */
273: public void updateEnabledState() {
274: if (activeTextControl != null
275: && !activeTextControl.isDisposed()) {
276: setEnabled(true);
277: return;
278: }
279: if (pasteAction != null) {
280: setEnabled(pasteAction.isEnabled());
281: return;
282: }
283: setEnabled(false);
284: }
285: }
286:
287: private class SelectAllActionHandler extends Action {
288: protected SelectAllActionHandler() {
289: super (CommonNavigatorMessages.TextAction_selectAll);
290: setId("TextSelectAllActionHandler");//$NON-NLS-1$
291: setEnabled(false);
292: PlatformUI.getWorkbench().getHelpSystem().setHelp(this ,
293: INavigatorHelpContextIds.TEXT_SELECT_ALL_ACTION);
294: }
295:
296: public void runWithEvent(Event event) {
297: if (activeTextControl != null
298: && !activeTextControl.isDisposed()) {
299: activeTextControl.selectAll();
300: return;
301: }
302: if (selectAllAction != null) {
303: selectAllAction.runWithEvent(event);
304: return;
305: }
306: }
307:
308: /**
309: * Update the state.
310: */
311: public void updateEnabledState() {
312: if (activeTextControl != null
313: && !activeTextControl.isDisposed()) {
314: setEnabled(true);
315: return;
316: }
317: if (selectAllAction != null) {
318: setEnabled(selectAllAction.isEnabled());
319: return;
320: }
321: setEnabled(false);
322: }
323: }
324:
325: /**
326: * Creates a <code>Text</code> control action handler
327: * for the global Cut, Copy, Paste, Delete, and Select All
328: * of the action bar.
329: *
330: * @param actionBar the action bar to register global
331: * action handlers for Cut, Copy, Paste, Delete,
332: * and Select All
333: */
334: public TextActionHandler(IActionBars actionBar) {
335: super ();
336: actionBar.setGlobalActionHandler(ActionFactory.CUT.getId(),
337: textCutAction);
338: actionBar.setGlobalActionHandler(ActionFactory.COPY.getId(),
339: textCopyAction);
340: actionBar.setGlobalActionHandler(ActionFactory.PASTE.getId(),
341: textPasteAction);
342: actionBar.setGlobalActionHandler(ActionFactory.SELECT_ALL
343: .getId(), textSelectAllAction);
344: actionBar.setGlobalActionHandler(ActionFactory.DELETE.getId(),
345: textDeleteAction);
346: }
347:
348: /**
349: * Add a <code>Text</code> control to the handler
350: * so that the Cut, Copy, Paste, Delete, and Select All
351: * actions are redirected to it when active.
352: *
353: * @param textControl the inline <code>Text</code> control
354: */
355: public void addText(Text textControl) {
356: if (textControl == null) {
357: return;
358: }
359:
360: activeTextControl = textControl;
361: textControl.addListener(SWT.Activate, textControlListener);
362: textControl.addListener(SWT.Deactivate, textControlListener);
363:
364: // We really want a selection listener but it is not supported so we
365: // use a key listener and a mouse listener to know when selection changes
366: // may have occured
367: textControl.addKeyListener(keyAdapter);
368: textControl.addMouseListener(mouseAdapter);
369:
370: }
371:
372: /**
373: * Dispose of this action handler
374: */
375: public void dispose() {
376: setCutAction(null);
377: setCopyAction(null);
378: setPasteAction(null);
379: setSelectAllAction(null);
380: setDeleteAction(null);
381: }
382:
383: /**
384: * Removes a <code>Text</code> control from the handler
385: * so that the Cut, Copy, Paste, Delete, and Select All
386: * actions are no longer redirected to it when active.
387: *
388: * @param textControl the inline <code>Text</code> control
389: */
390: public void removeText(Text textControl) {
391: if (textControl == null) {
392: return;
393: }
394:
395: textControl.removeListener(SWT.Activate, textControlListener);
396: textControl.removeListener(SWT.Deactivate, textControlListener);
397:
398: textControl.removeMouseListener(mouseAdapter);
399: textControl.removeKeyListener(keyAdapter);
400:
401: activeTextControl = null;
402: updateActionsEnableState();
403: }
404:
405: /**
406: * Set the default <code>IAction</code> handler for the Copy
407: * action. This <code>IAction</code> is run only if no active
408: * inline text control.
409: *
410: * @param action the <code>IAction</code> to run for the
411: * Copy action, or <code>null</code> if not interested.
412: */
413: public void setCopyAction(IAction action) {
414: if (copyAction == action) {
415: return;
416: }
417:
418: if (copyAction != null) {
419: copyAction.removePropertyChangeListener(copyActionListener);
420: }
421:
422: copyAction = action;
423:
424: if (copyAction != null) {
425: copyAction.addPropertyChangeListener(copyActionListener);
426: }
427:
428: textCopyAction.updateEnabledState();
429: }
430:
431: /**
432: * Set the default <code>IAction</code> handler for the Cut
433: * action. This <code>IAction</code> is run only if no active
434: * inline text control.
435: *
436: * @param action the <code>IAction</code> to run for the
437: * Cut action, or <code>null</code> if not interested.
438: */
439: public void setCutAction(IAction action) {
440: if (cutAction == action) {
441: return;
442: }
443:
444: if (cutAction != null) {
445: cutAction.removePropertyChangeListener(cutActionListener);
446: }
447:
448: cutAction = action;
449:
450: if (cutAction != null) {
451: cutAction.addPropertyChangeListener(cutActionListener);
452: }
453:
454: textCutAction.updateEnabledState();
455: }
456:
457: /**
458: * Set the default <code>IAction</code> handler for the Paste
459: * action. This <code>IAction</code> is run only if no active
460: * inline text control.
461: *
462: * @param action the <code>IAction</code> to run for the
463: * Paste action, or <code>null</code> if not interested.
464: */
465: public void setPasteAction(IAction action) {
466: if (pasteAction == action) {
467: return;
468: }
469:
470: if (pasteAction != null) {
471: pasteAction
472: .removePropertyChangeListener(pasteActionListener);
473: }
474:
475: pasteAction = action;
476:
477: if (pasteAction != null) {
478: pasteAction.addPropertyChangeListener(pasteActionListener);
479: }
480:
481: textPasteAction.updateEnabledState();
482: }
483:
484: /**
485: * Set the default <code>IAction</code> handler for the Select All
486: * action. This <code>IAction</code> is run only if no active
487: * inline text control.
488: *
489: * @param action the <code>IAction</code> to run for the
490: * Select All action, or <code>null</code> if not interested.
491: */
492: public void setSelectAllAction(IAction action) {
493: if (selectAllAction == action) {
494: return;
495: }
496:
497: if (selectAllAction != null) {
498: selectAllAction
499: .removePropertyChangeListener(selectAllActionListener);
500: }
501:
502: selectAllAction = action;
503:
504: if (selectAllAction != null) {
505: selectAllAction
506: .addPropertyChangeListener(selectAllActionListener);
507: }
508:
509: textSelectAllAction.updateEnabledState();
510: }
511:
512: /**
513: * Set the default <code>IAction</code> handler for the Delete
514: * action. This <code>IAction</code> is run only if no active
515: * inline text control.
516: *
517: * @param action the <code>IAction</code> to run for the
518: * Delete action, or <code>null</code> if not interested.
519: */
520: public void setDeleteAction(IAction action) {
521: if (deleteAction == action) {
522: return;
523: }
524:
525: if (deleteAction != null) {
526: deleteAction
527: .removePropertyChangeListener(deleteActionListener);
528: }
529:
530: deleteAction = action;
531:
532: if (deleteAction != null) {
533: deleteAction
534: .addPropertyChangeListener(deleteActionListener);
535: }
536:
537: textDeleteAction.updateEnabledState();
538: }
539:
540: /**
541: * Update the enable state of the Cut, Copy,
542: * Paste, Delete, and Select All action handlers
543: */
544: private void updateActionsEnableState() {
545: textCutAction.updateEnabledState();
546: textCopyAction.updateEnabledState();
547: textPasteAction.updateEnabledState();
548: textSelectAllAction.updateEnabledState();
549: textDeleteAction.updateEnabledState();
550: }
551: }
|