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.xml.text.syntax;
042:
043: import java.awt.event.ActionEvent;
044: import java.awt.Panel;
045: import java.util.*;
046:
047: // prevent ambiguous reference to Utilities
048: import javax.swing.text.Caret;
049: import javax.swing.text.Document;
050: import javax.swing.text.TextAction;
051: import javax.swing.text.JTextComponent;
052: import javax.swing.text.BadLocationException;
053: import javax.swing.*;
054: import org.netbeans.api.lexer.Language;
055: import org.netbeans.api.xml.lexer.XMLTokenId;
056: import org.openide.awt.StatusDisplayer;
057:
058: // we depend on NetBeans editor stuff
059: import org.netbeans.editor.*;
060: import org.netbeans.editor.ext.*;
061: import org.netbeans.modules.editor.*;
062:
063: import org.netbeans.modules.xml.text.completion.NodeSelector;
064: import org.netbeans.modules.xml.text.completion.XMLCompletion;
065:
066: /**
067: * NetBeans editor kit implementation for xml content type.
068: * <p>
069: * It provides syntax coloring, code completion, actions, abbrevirations, ...
070: *
071: * @author Libor Kramolis
072: * @author Petr Kuzel
073: * @author Sandeep
074: */
075: public class XMLKit extends NbEditorKit implements
076: org.openide.util.HelpCtx.Provider {
077:
078: /** Serial Version UID */
079: private static final long serialVersionUID = 5326735092324267367L;
080:
081: /** Default XML Mime Type. */
082: public static final String MIME_TYPE = "text/xml"; // NOI18N
083:
084: // comment action name
085: public static final String xmlCommentAction = "xml-comment";
086:
087: // uncomment action name
088: public static final String xmlUncommentAction = "xml-uncomment";
089:
090: // dump XML sysntax
091: public static final String xmlTestAction = "xml-dump";
092:
093: // hack to be settings browseable //??? more info needed
094: public static Map settings;
095:
096: //temporary - will be removed when lexer is stabilized
097: private static final boolean J2EE_LEXER_COLORING = Boolean
098: .getBoolean("j2ee_lexer_coloring"); //NOI18N
099:
100: public org.openide.util.HelpCtx getHelpCtx() {
101: return new org.openide.util.HelpCtx(XMLKit.class);
102: }
103:
104: /** Create new instance of syntax coloring parser */
105: public Syntax createSyntax(Document doc) {
106: return new XMLDefaultSyntax();
107: // return new JJEditorSyntax(
108: // new XMLSyntaxTokenManager(null).new Bridge(),
109: // new XMLSyntaxTokenMapper(),
110: // XMLTokenContext.contextPath
111: // );
112: }
113:
114: public Document createDefaultDocument() {
115: if (J2EE_LEXER_COLORING) {
116: Document doc = new XMLEditorDocument(this .getClass());
117: Object mimeType = doc.getProperty("mimeType"); //NOI18N
118: if (mimeType == null) {
119: doc.putProperty("mimeType", getContentType()); //NOI18N
120: }
121: doc.putProperty(Language.class, XMLTokenId.language());
122: return doc;
123: } else {
124: return new NbEditorDocument(this .getClass());
125: }
126: }
127:
128: /** Create syntax support */
129: public SyntaxSupport createSyntaxSupport(BaseDocument doc) {
130: return new XMLSyntaxSupport(doc);
131: }
132:
133: public Completion createCompletion(ExtEditorUI extEditorUI) {
134: //return new org.netbeans.modules.xml.text.completion.XMLCompletion(extEditorUI);
135: return null;
136: }
137:
138: public Completion createCompletionForProvider(
139: ExtEditorUI extEditorUI) {
140: return new XMLCompletion(extEditorUI);
141: }
142:
143: public void install(JEditorPane c) {
144: super .install(c);
145: if (Boolean
146: .getBoolean("netbeans.experimental.xml.nodeselectors")) { // NOI18N
147: new NodeSelector(c);
148: }
149: }
150:
151: // hack to be settings browseable //??? more info needed
152: public static void setMap(Map map) {
153: settings = map;
154: }
155:
156: // hack to be settings browseable //??? more info needed
157: public Map getMap() {
158: return settings;
159: }
160:
161: //??? +xml handling
162: public String getContentType() {
163: return MIME_TYPE;
164: }
165:
166: /**
167: * Provide XML related actions.
168: */
169: protected Action[] createActions() {
170: Action[] actions = new Action[] { new XMLCommentAction(),
171: new XMLUncommentAction(), new TestAction(), };
172: return TextAction.augmentList(super .createActions(), actions);
173: }
174:
175: public abstract static class XMLEditorAction extends BaseAction {
176:
177: public XMLEditorAction(String id) {
178: super (id);
179: String desc = org.openide.util.NbBundle.getMessage(
180: XMLKit.class, id); // NOI18N
181: if (desc != null) {
182: putValue(SHORT_DESCRIPTION, desc);
183: }
184: }
185:
186: /**
187: * Uniform way of reporting problem while action executing #15589
188: */
189: protected void problem(String reason) {
190: if (reason != null)
191: StatusDisplayer.getDefault().setStatusText(
192: "Cannot proceed: " + reason);
193: new Panel().getToolkit().beep();
194: }
195: }
196:
197: /**
198: * Comment out editor selection.
199: */
200: public static class XMLCommentAction extends XMLEditorAction {
201:
202: private static final long serialVersionUID = 4004056745446061L;
203:
204: private static final String commentStartString = "<!--"; //NOI18N
205: private static final String commentEndString = "-->"; //NOI18N
206:
207: public XMLCommentAction() {
208: super (xmlCommentAction);
209: }
210:
211: public void actionPerformed(ActionEvent evt,
212: JTextComponent target) {
213: if (target == null)
214: return;
215: if (!target.isEditable() || !target.isEnabled()) {
216: problem(null);
217: return;
218: }
219: Caret caret = target.getCaret();
220: BaseDocument doc = (BaseDocument) target.getDocument();
221: try {
222: if (caret.isSelectionVisible()) {
223: int startPos = Utilities.getRowStart(doc, target
224: .getSelectionStart());
225: int endPos = target.getSelectionEnd();
226: doc.atomicLock();
227: try {
228:
229: if (endPos > 0
230: && Utilities.getRowStart(doc, endPos) == endPos) {
231: endPos--;
232: }
233:
234: int pos = startPos;
235: int lineCnt = Utilities.getRowCount(doc,
236: startPos, endPos);
237:
238: for (; lineCnt > 0; lineCnt--) {
239: doc.insertString(pos, commentStartString,
240: null);
241: doc.insertString(Utilities.getRowEnd(doc,
242: pos), commentEndString, null);
243: pos = Utilities.getRowStart(doc, pos, +1);
244: }
245:
246: } finally {
247: doc.atomicUnlock();
248: }
249: } else { // selection not visible
250: doc.insertString(Utilities.getRowStart(doc, target
251: .getSelectionStart()), commentStartString,
252: null);
253: doc.insertString(Utilities.getRowEnd(doc, target
254: .getSelectionStart()), commentEndString,
255: null);
256: }
257: } catch (BadLocationException e) {
258: problem(null);
259: }
260: }
261:
262: }
263:
264: /**
265: * Uncomment selected text
266: *
267: */
268: public static class XMLUncommentAction extends XMLEditorAction {
269: private static final String commentStartString = "<!--"; //NOI18N
270: private static final String commentEndString = "-->"; //NOI18N
271: private static final char[] commentStart = { '<', '!', '-', '-' };
272: private static final char[] commentEnd = { '-', '-', '>' };
273:
274: static final long serialVersionUID = 40040567454546061L;
275:
276: public XMLUncommentAction() {
277: super (xmlUncommentAction);
278: }
279:
280: public void actionPerformed(ActionEvent evt,
281: JTextComponent target) {
282: if (target == null)
283: return;
284: if (!target.isEditable() || !target.isEnabled()) {
285: problem(null);
286: return;
287: }
288: Caret caret = target.getCaret();
289: BaseDocument doc = (BaseDocument) target.getDocument();
290: try {
291: if (caret.isSelectionVisible()) {
292: int startPos = Utilities.getRowStart(doc, target
293: .getSelectionStart());
294: int endPos = target.getSelectionEnd();
295: doc.atomicLock();
296: try {
297:
298: if (endPos > 0
299: && Utilities.getRowStart(doc, endPos) == endPos) {
300: endPos--;
301: }
302:
303: int pos = startPos;
304: int lineCnt = Utilities.getRowCount(doc,
305: startPos, endPos);
306: char[] startChars, endChars;
307:
308: for (; lineCnt > 0; lineCnt--) {
309: startChars = doc.getChars(pos, 4);
310: endChars = doc.getChars(Utilities
311: .getRowEnd(doc, pos) - 3, 3);
312:
313: if (startChars[0] == commentStart[0]
314: && startChars[1] == commentStart[1]
315: && startChars[2] == commentStart[2]
316: && startChars[3] == commentStart[3]
317: && endChars[0] == commentEnd[0]
318: && endChars[1] == commentEnd[1]
319: && endChars[2] == commentEnd[2]) {
320:
321: doc.remove(pos, 4);
322: doc.remove(Utilities
323: .getRowEnd(doc, pos) - 3, 3);
324: }
325: pos = Utilities.getRowStart(doc, pos, +1);
326: }
327:
328: } finally {
329: doc.atomicUnlock();
330: }
331: } else { // selection not visible
332: char[] startChars = doc.getChars(target
333: .getSelectionStart(), 4);
334: char[] endChars = doc.getChars(Utilities.getRowEnd(
335: doc, target.getSelectionStart()) - 3, 3);
336: if (startChars[0] == commentStart[0]
337: && startChars[1] == commentStart[1]
338: && startChars[2] == commentStart[2]
339: && startChars[3] == commentStart[3]
340: && endChars[0] == commentEnd[0]
341: && endChars[1] == commentEnd[1]
342: && endChars[2] == commentEnd[2]) {
343: doc.remove(target.getSelectionStart(), 4);
344: doc.remove(Utilities.getRowEnd(doc, target
345: .getSelectionStart()) - 3, 3);
346: }
347: }
348: } catch (BadLocationException e) {
349: problem(null);
350: }
351: }
352: }
353:
354: /**
355: * Dump it.
356: */
357: public static class TestAction extends XMLEditorAction {
358:
359: private static final long serialVersionUID = 4004056745446099L;
360:
361: public TestAction() {
362: super (xmlTestAction);
363: }
364:
365: public void actionPerformed(ActionEvent evt,
366: JTextComponent target) {
367: if (target == null)
368: return;
369: if (!target.isEditable() || !target.isEnabled()) {
370: problem(null);
371: return;
372: }
373: Caret caret = target.getCaret();
374: BaseDocument doc = (BaseDocument) target.getDocument();
375: try {
376: doc.dump(System.out);
377: if (target == null)
378: throw new BadLocationException(null, 0); // folish compiler
379: } catch (BadLocationException e) {
380: problem(null);
381: }
382: }
383:
384: }
385:
386: public class XMLEditorDocument extends NbEditorDocument {
387: public XMLEditorDocument(Class kitClass) {
388: super (kitClass);
389: }
390:
391: public boolean addLayer(DrawLayer layer, int visibility) {
392: //filter out the syntax layer adding
393: if (!(layer instanceof DrawLayerFactory.SyntaxLayer)) {
394: return super .addLayer(layer, visibility);
395: } else {
396: return false;
397: }
398: }
399: }
400: }
|