misc changes
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / phpeditor / ToggleCommentAction.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11
12 package net.sourceforge.phpeclipse.phpeditor;
13
14 import java.util.ResourceBundle;
15
16 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
17
18 import org.eclipse.jface.dialogs.MessageDialog;
19 import org.eclipse.jface.text.BadLocationException;
20 import org.eclipse.jface.text.IDocument;
21 import org.eclipse.jface.text.ITextOperationTarget;
22 import org.eclipse.jface.text.ITextSelection;
23 import org.eclipse.jface.viewers.ISelection;
24 import org.eclipse.swt.custom.BusyIndicator;
25 import org.eclipse.swt.widgets.Display;
26 import org.eclipse.swt.widgets.Shell;
27 import org.eclipse.ui.texteditor.ITextEditor;
28 import org.eclipse.ui.texteditor.ResourceAction;
29 import org.eclipse.ui.texteditor.TextEditorAction;
30
31
32
33 /**
34  * An action which toggles the single line comment prefixes on the selected lines.
35  * 
36  * @since 3.0
37  */
38 public final class ToggleCommentAction extends TextEditorAction {
39         
40         /** The text operation target */
41         private ITextOperationTarget fOperationTarget;
42         /** The comment prefixes */
43         private String[] fCommentPrefixes;
44         
45         /**
46          * Creates and initializes the action for the given text editor. The action
47          * configures its visual representation from the given resource bundle.
48          *
49          * @param bundle the resource bundle
50          * @param prefix a prefix to be prepended to the various resource keys
51          *   (described in <code>ResourceAction</code> constructor), or 
52          *   <code>null</code> if none
53          * @param editor the text editor
54          * @see ResourceAction#ResourceAction
55          */
56         public ToggleCommentAction(ResourceBundle bundle, String prefix, ITextEditor editor, String[] commentPrefixes) {
57                 super(bundle, prefix, editor);
58                 fCommentPrefixes= commentPrefixes;
59         }
60         
61         /**
62          * Implementation of the <code>IAction</code> prototype. Checks if the selected
63          * lines are all commented or not and uncomment/comments them respectively.
64          */
65         public void run() {
66                 if (fOperationTarget == null)
67                         return;
68                         
69                 ITextEditor editor= getTextEditor();
70                 if (!(editor instanceof PHPEditor))
71                         return;
72
73                 if (!validateEditorInputState())
74                         return;
75                 
76                 final int operationCode;
77                 if (isSelectionCommented(editor.getSelectionProvider().getSelection()))
78                         operationCode= ITextOperationTarget.STRIP_PREFIX;
79                 else
80                         operationCode= ITextOperationTarget.PREFIX;
81                 
82                 Shell shell= editor.getSite().getShell();
83                 if (!fOperationTarget.canDoOperation(operationCode)) {
84                         if (shell != null)
85                                 MessageDialog.openError(shell, PHPEditorMessages.getString("ToggleComment.error.title"), PHPEditorMessages.getString("ToggleComment.error.message")); //$NON-NLS-1$ //$NON-NLS-2$
86                         return;
87                 }
88                 
89                 Display display= null;
90                 if (shell != null && !shell.isDisposed()) 
91                         display= shell.getDisplay();
92         
93                 BusyIndicator.showWhile(display, new Runnable() {
94                         public void run() {
95                                 fOperationTarget.doOperation(operationCode);
96                         }
97                 });
98         }
99         
100         /**
101          * Is the given selection single-line commented?
102          *
103          * @param selection Selection to check
104          * @return <code>true</code> iff all selected lines are single-line commented
105          */
106         private boolean isSelectionCommented(ISelection selection) {
107                 if (!(selection instanceof ITextSelection))
108                         return false;
109                         
110                 ITextSelection ts= (ITextSelection) selection;
111                 if (ts.getStartLine() < 0 || ts.getEndLine() < 0)
112                         return false;
113                 
114                 IDocument document= getTextEditor().getDocumentProvider().getDocument(getTextEditor().getEditorInput());
115                 OUTER: for (int i= ts.getStartLine(); i <= ts.getEndLine(); i++) {
116                         for (int j= 0; j < fCommentPrefixes.length; j++) {
117                                 try {
118                                         if (fCommentPrefixes[j].length() == 0)
119                                                 continue;
120                                         String s= document.get(document.getLineOffset(i), document.getLineLength(i));
121                                         int index= s.indexOf(fCommentPrefixes[j]);
122                                         if (index >= 0 && s.substring(0, index).trim().length() == 0)
123                                                 continue OUTER;
124                                 } catch (BadLocationException e) {
125                                         // should not happen
126                                         PHPeclipsePlugin.log(e);
127                                 }
128                         }
129                         return false;
130                 }
131                 return true;
132         }
133
134         /**
135          * Implementation of the <code>IUpdate</code> prototype method discovers
136          * the operation through the current editor's
137          * <code>ITextOperationTarget</code> adapter, and sets the enabled state
138          * accordingly.
139          */
140         public void update() {
141                 super.update();
142                 
143                 if (!canModifyEditor()) {
144                         setEnabled(false);
145                         return;
146                 }
147                 
148                 ITextEditor editor= getTextEditor();
149                 if (fOperationTarget == null && editor != null)
150                         fOperationTarget= (ITextOperationTarget) editor.getAdapter(ITextOperationTarget.class);
151                         
152                 boolean isEnabled= (fOperationTarget != null && fOperationTarget.canDoOperation(ITextOperationTarget.PREFIX) && fOperationTarget.canDoOperation(ITextOperationTarget.STRIP_PREFIX));
153                 setEnabled(isEnabled);
154         }
155         
156         /*
157          * @see TextEditorAction#setEditor(ITextEditor)
158          */
159         public void setEditor(ITextEditor editor) {
160                 super.setEditor(editor);
161                 fOperationTarget= null;
162         }
163 }