001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041: package org.netbeans.modules.editor.gsfret;
042:
043: import java.awt.event.ActionEvent;
044: import java.io.IOException;
045: import java.util.List;
046: import java.util.Set;
047: import javax.swing.Action;
048:
049: import javax.swing.text.BadLocationException;
050: import javax.swing.text.Document;
051: import javax.swing.text.JTextComponent;
052:
053: import org.netbeans.modules.gsf.api.CancellableTask;
054: import org.netbeans.modules.gsf.api.InstantRenamer;
055: import org.netbeans.modules.gsf.api.OffsetRange;
056: import org.netbeans.napi.gsfret.source.CompilationController;
057: import org.netbeans.napi.gsfret.source.Phase;
058: import org.netbeans.napi.gsfret.source.Source;
059: import org.netbeans.napi.gsfret.source.SourceUtils;
060: import org.netbeans.editor.BaseAction;
061: import org.netbeans.editor.BaseDocument;
062: import org.netbeans.editor.Utilities;
063: import org.netbeans.modules.gsf.Language;
064: import org.netbeans.modules.gsf.LanguageRegistry;
065: import org.netbeans.modules.refactoring.api.ui.RefactoringActionsFactory;
066: import org.openide.ErrorManager;
067: import org.openide.cookies.EditorCookie;
068: import org.openide.loaders.DataObject;
069: import org.openide.nodes.Node;
070: import org.openide.util.Lookup;
071: import org.openide.util.NbBundle;
072: import org.openide.util.lookup.AbstractLookup;
073: import org.openide.util.lookup.InstanceContent;
074:
075: /**
076: * This file is originally from Retouche, the Java Support
077: * infrastructure in NetBeans. I have modified the file as little
078: * as possible to make merging Retouche fixes back as simple as
079: * possible.
080: *
081: *
082: * @author Jan Lahoda
083: * @author Tor Norbye
084: */
085: public class InstantRenameAction extends BaseAction {
086: /** Creates a new instance of InstantRenameAction */
087: public InstantRenameAction() {
088: super ("in-place-refactoring", ABBREV_RESET
089: | MAGIC_POSITION_RESET | UNDO_MERGE_RESET);
090: }
091:
092: public void actionPerformed(ActionEvent evt,
093: final JTextComponent target) {
094: try {
095: final int caret = target.getCaretPosition();
096: String ident = Utilities.getIdentifier(Utilities
097: .getDocument(target), caret);
098:
099: if (ident == null) {
100: Utilities.setStatusBoldText(target,
101: "Cannot perform rename here.");
102:
103: return;
104: }
105:
106: if (SourceUtils.isScanInProgress()) {
107: Utilities.setStatusBoldText(target,
108: "Scanning In Progress");
109:
110: return;
111: }
112:
113: DataObject od = (DataObject) target.getDocument()
114: .getProperty(Document.StreamDescriptionProperty);
115: Source js = Source.forFileObject(od.getPrimaryFile());
116: final boolean[] wasResolved = new boolean[1];
117: final String[] message = new String[1];
118: final Set<OffsetRange>[] changePoints = new Set[1];
119:
120: js.runUserActionTask(
121: new CancellableTask<CompilationController>() {
122: public void cancel() {
123: }
124:
125: public void run(CompilationController controller)
126: throws Exception {
127: if (controller.toPhase(Phase.RESOLVED)
128: .compareTo(Phase.RESOLVED) < 0) {
129: return;
130: }
131:
132: Document doc = target.getDocument();
133: BaseDocument baseDoc = (BaseDocument) doc;
134: List<Language> list = LanguageRegistry
135: .getInstance()
136: .getEmbeddedLanguages(baseDoc,
137: caret);
138: Language language = null;
139: for (Language l : list) {
140: if (l.getInstantRenamer() != null) {
141: language = l;
142: break;
143: }
144: }
145:
146: if (language != null) {
147: InstantRenamer renamer = language
148: .getInstantRenamer();
149: assert renamer != null;
150:
151: String[] descRetValue = new String[1];
152:
153: if ((renamer == null)
154: || !renamer.isRenameAllowed(
155: controller, caret,
156: descRetValue)) {
157: wasResolved[0] = false;
158: message[0] = descRetValue[0];
159:
160: return;
161: }
162:
163: wasResolved[0] = true;
164:
165: Set<OffsetRange> regions = renamer
166: .getRenameRegions(controller,
167: caret);
168:
169: if ((regions != null)
170: && (regions.size() > 0)) {
171: changePoints[0] = regions;
172: }
173: }
174: }
175: }, true);
176:
177: if (wasResolved[0]) {
178: if (changePoints[0] != null) {
179: doInstantRename(changePoints[0], target, caret,
180: ident);
181: } else {
182: doFullRename(od.getCookie(EditorCookie.class), od
183: .getNodeDelegate());
184: }
185: } else {
186: if (message[0] == null) {
187: message[0] = NbBundle.getMessage(
188: InstantRenameAction.class,
189: "InstantRenameDenied");
190: }
191:
192: Utilities.setStatusBoldText(target, message[0]);
193: }
194: } catch (BadLocationException e) {
195: ErrorManager.getDefault().notify(e);
196: } catch (IOException ioe) {
197: ErrorManager.getDefault().notify(ioe);
198: }
199: }
200:
201: @Override
202: protected Class getShortDescriptionBundleClass() {
203: return InstantRenameAction.class;
204: }
205:
206: private void doInstantRename(Set<OffsetRange> changePoints,
207: JTextComponent target, int caret, String ident)
208: throws BadLocationException {
209: InstantRenamePerformer.performInstantRename(target,
210: changePoints, caret);
211: }
212:
213: private void doFullRename(EditorCookie ec, Node n) {
214: InstanceContent ic = new InstanceContent();
215: ic.add(ec);
216: ic.add(n);
217:
218: Lookup actionContext = new AbstractLookup(ic);
219:
220: Action a = RefactoringActionsFactory.renameAction()
221: .createContextAwareInstance(actionContext);
222: a.actionPerformed(RefactoringActionsFactory.DEFAULT_EVENT);
223: }
224: }
|