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