KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > editor > html > HTMLKit


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.editor.html;
21
22 import java.awt.datatransfer.DataFlavor JavaDoc;
23 import java.awt.datatransfer.Transferable JavaDoc;
24 import java.awt.datatransfer.UnsupportedFlavorException JavaDoc;
25 import java.awt.event.ActionEvent JavaDoc;
26 import java.awt.im.InputContext JavaDoc;
27 import java.io.ByteArrayInputStream JavaDoc;
28 import java.io.IOException JavaDoc;
29 import java.io.InputStream JavaDoc;
30 import java.io.Reader JavaDoc;
31 import java.io.StringReader JavaDoc;
32 import java.io.StringWriter JavaDoc;
33 import java.util.logging.Level JavaDoc;
34 import java.util.logging.Logger JavaDoc;
35 import javax.swing.Action JavaDoc;
36 import javax.swing.JComponent JavaDoc;
37 import javax.swing.JEditorPane JavaDoc;
38 import javax.swing.JMenu JavaDoc;
39 import javax.swing.JPasswordField JavaDoc;
40 import javax.swing.TransferHandler JavaDoc;
41 import javax.swing.plaf.UIResource JavaDoc;
42 import javax.swing.text.BadLocationException JavaDoc;
43 import javax.swing.text.Caret JavaDoc;
44 import javax.swing.text.Document JavaDoc;
45 import javax.swing.text.EditorKit JavaDoc;
46 import javax.swing.text.Position JavaDoc;
47 import javax.swing.text.TextAction JavaDoc;
48 import javax.swing.text.JTextComponent JavaDoc;
49 import org.netbeans.api.editor.fold.FoldHierarchy;
50 import org.netbeans.api.editor.fold.FoldUtilities;
51 import org.netbeans.api.lexer.TokenHierarchy;
52 import org.netbeans.editor.*;
53 import org.netbeans.editor.BaseKit.DeleteCharAction;
54 import org.netbeans.editor.ext.*;
55 import org.netbeans.editor.ext.ExtKit.ExtDefaultKeyTypedAction;
56 import org.netbeans.editor.ext.html.*;
57 import org.netbeans.editor.ext.html.HTMLSyntaxSupport;
58 import org.netbeans.editor.ext.html.parser.SyntaxParser;
59 import org.netbeans.modules.editor.NbEditorKit;
60 import org.netbeans.modules.editor.NbEditorKit.GenerateFoldPopupAction;
61 import org.netbeans.modules.html.editor.coloring.EmbeddingUpdater;
62 import org.netbeans.modules.html.editor.folding.HTMLFoldTypes;
63 import org.openide.util.NbBundle;
64
65 /**
66  * Editor kit implementation for HTML content type
67  *
68  * @author Miloslav Metelka
69  * @version 1.00
70  */

71
72 public class HTMLKit extends NbEditorKit implements org.openide.util.HelpCtx.Provider {
73     
74     public org.openide.util.HelpCtx getHelpCtx() {
75         return new org.openide.util.HelpCtx(HTMLKit.class);
76     }
77     
78     private static final Logger JavaDoc LOGGER = Logger.getLogger(HTMLKit.class.getName());
79     
80     static final long serialVersionUID =-1381945567613910297L;
81     
82     public static final String JavaDoc HTML_MIME_TYPE = "text/html"; // NOI18N
83

84     public static final String JavaDoc shiftInsertBreakAction = "shift-insert-break"; // NOI18N
85

86     //comment folds
87
public static final String JavaDoc collapseAllCommentsAction = "collapse-all-comment-folds"; //NOI18N
88

89     public static final String JavaDoc expandAllCommentsAction = "expand-all-comment-folds"; //NOI18N
90

91     private static boolean setupReadersInitialized = false;
92     
93     public HTMLKit(){
94         if (!setupReadersInitialized){
95             NbReaderProvider.setupReaders();
96             setupReadersInitialized = true;
97         }
98     }
99     
100     public String JavaDoc getContentType() {
101         return HTML_MIME_TYPE;
102     }
103     
104     public CompletionJavaDoc createCompletionJavaDoc(ExtEditorUI extEditorUI) {
105         return null;
106     }
107     
108     protected void initDocument(final BaseDocument doc) {
109         TokenHierarchy hi = TokenHierarchy.get(doc);
110         if(hi == null) {
111             LOGGER.log(Level.WARNING, "TokenHierarchy is null for document " + doc);
112             return ;
113         }
114         
115         //listen on the HTML parser and recolor after changes
116
SyntaxParser.get(doc).addSyntaxParserListener(new EmbeddingUpdater(doc));
117     }
118     
119     /** Create new instance of syntax coloring scanner
120      * @param doc document to operate on. It can be null in the cases the syntax
121      * creation is not related to the particular document
122      */

123     public Syntax createSyntax(Document JavaDoc doc) {
124         return new HTMLSyntax();
125     }
126     
127     /** Create syntax support */
128     public SyntaxSupport createSyntaxSupport(BaseDocument doc) {
129         return new HTMLSyntaxSupport(doc);
130     }
131     
132     /** old code completion is disabled. */
133     public Completion createCompletion(ExtEditorUI extEditorUI) {
134         return null;
135     }
136     
137     public Formatter createFormatter() {
138         return new HTMLFormatter(this.getClass());
139     }
140     
141     /** Called after the kit is installed into JEditorPane */
142     public void install(javax.swing.JEditorPane JavaDoc c) {
143         super.install(c);
144         c.setTransferHandler(new HTMLTransferHandler());
145     }
146     
147     protected Action JavaDoc[] createActions() {
148         Action JavaDoc[] HTMLActions = new Action JavaDoc[] {
149             new HTMLDefaultKeyTypedAction(),
150             new HTMLDeleteCharAction(deletePrevCharAction, false),
151             new HTMLDeleteCharAction(deleteNextCharAction, true),
152             new HTMLShiftBreakAction(),
153             // replace MatchBraceAction with HtmlEditor own
154
new MatchBraceAction(ExtKit.matchBraceAction, false),
155             new MatchBraceAction(ExtKit.selectionMatchBraceAction, true),
156             new HTMLGenerateFoldPopupAction(),
157             new CollapseAllCommentsFolds(),
158             new ExpandAllCommentsFolds()
159         };
160         return TextAction.augmentList(super.createActions(), HTMLActions);
161     }
162     
163     public static class HTMLDefaultKeyTypedAction extends ExtDefaultKeyTypedAction {
164         
165         protected void insertString(BaseDocument doc, int dotPos,
166                 Caret JavaDoc caret, String JavaDoc str,
167                 boolean overwrite) throws BadLocationException JavaDoc {
168             super.insertString(doc, dotPos, caret, str, overwrite);
169             HTMLAutoCompletion.charInserted(doc, dotPos, caret, str.charAt(0));
170         }
171         
172     }
173     
174     public static class HTMLDeleteCharAction extends DeleteCharAction {
175         
176         public HTMLDeleteCharAction(String JavaDoc name, boolean nextChar) {
177             super(name, nextChar);
178         }
179         
180         protected void charBackspaced(BaseDocument doc, int dotPos, Caret JavaDoc caret, char ch) throws BadLocationException JavaDoc {
181             super.charBackspaced(doc, dotPos, caret, ch);
182             HTMLAutoCompletion.charDeleted(doc, dotPos, caret, ch);
183         }
184     }
185     
186     
187     public static class HTMLShiftBreakAction extends BaseAction {
188         
189         static final long serialVersionUID =4004043376345356061L;
190         
191         public HTMLShiftBreakAction() {
192             super( shiftInsertBreakAction, ABBREV_RESET
193                     | MAGIC_POSITION_RESET | UNDO_MERGE_RESET);
194         }
195         
196         public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
197             if (target != null) {
198                 Completion completion = ExtUtilities.getCompletion(target);
199                 if (completion != null && completion.isPaneVisible()) {
200                     if (completion.substituteText( true )) {
201                         // completion.setPaneVisible(false);
202
} else {
203                         completion.refresh(false);
204                     }
205                 }
206             }
207         }
208         
209     }
210     
211     /** This is implementation for MatchBraceAction for HTML file.
212      */

213     public static class MatchBraceAction extends ExtKit.MatchBraceAction {
214         
215         private boolean select; // whether the text between matched blocks should be selected
216

217         public MatchBraceAction(String JavaDoc name, boolean select) {
218             super(name, select);
219             this.select = select;
220         }
221         
222         public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
223             if (target != null) {
224                 try {
225                     Caret JavaDoc caret = target.getCaret();
226                     BaseDocument doc = Utilities.getDocument(target);
227                     int dotPos = caret.getDot();
228                     ExtSyntaxSupport sup = (ExtSyntaxSupport)doc.getSyntaxSupport();
229                     
230                     //TODO: check whether we are in HTML text
231
if (dotPos > 0) {
232                         int[] matchBlk = sup.findMatchingBlock(dotPos - 1, false);
233                         if (matchBlk != null) {
234                             if (select) {
235                                 caret.moveDot(matchBlk[1]);
236                             } else {
237                                 caret.setDot(matchBlk[1]);
238                             }
239                         }
240                         
241                     } else{ // If this is not token from HTML Syntax -> call the original action from editor.
242
super.actionPerformed(evt, target);
243                     }
244                     
245                 } catch (BadLocationException JavaDoc e) {
246                     target.getToolkit().beep();
247                 }
248             }
249         }
250     }
251     
252     public static class HTMLGenerateFoldPopupAction extends GenerateFoldPopupAction {
253         
254         protected void addAdditionalItems(JTextComponent JavaDoc target, JMenu JavaDoc menu){
255             addAction(target, menu, collapseAllCommentsAction);
256             addAction(target, menu, expandAllCommentsAction);
257         }
258     }
259     
260     public static class ExpandAllCommentsFolds extends BaseAction{
261         public ExpandAllCommentsFolds(){
262             super(expandAllCommentsAction);
263             putValue(SHORT_DESCRIPTION, NbBundle.getBundle(HTMLKit.class).getString("expand-all-comment-folds"));
264             putValue(BaseAction.POPUP_MENU_TEXT, NbBundle.getBundle(HTMLKit.class).getString("popup-expand-all-comment-folds"));
265         }
266         
267         public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
268             FoldHierarchy hierarchy = FoldHierarchy.get(target);
269             // Hierarchy locking done in the utility method
270
FoldUtilities.expand(hierarchy, HTMLFoldTypes.COMMENT);
271         }
272     }
273     
274     public static class CollapseAllCommentsFolds extends BaseAction{
275         public CollapseAllCommentsFolds(){
276             super(collapseAllCommentsAction);
277             putValue(SHORT_DESCRIPTION, NbBundle.getBundle(HTMLKit.class).getString("collapse-all-comment-folds")); //NOI18N
278
putValue(BaseAction.POPUP_MENU_TEXT, NbBundle.getBundle(HTMLKit.class).getString("popup-collapse-all-comment-folds")); //NOI18N
279
}
280         
281         public void actionPerformed(ActionEvent JavaDoc evt, JTextComponent JavaDoc target) {
282             FoldHierarchy hierarchy = FoldHierarchy.get(target);
283             // Hierarchy locking done in the utility method
284
FoldUtilities.collapse(hierarchy, HTMLFoldTypes.COMMENT);
285         }
286     }
287     
288     
289     
290     
291     
292     /* !!!!!!!!!!!!!!!!!!!!!
293      *
294      * Inner classes bellow were taken from BasicTextUI and rewritten in the place marked
295      * with [REWRITE_PLACE]. This needs to be done to fix the issue #43309
296      *
297      * !!!!!!!!!!!!!!!!!!!!!
298      */

299     static class HTMLTransferHandler extends TransferHandler JavaDoc implements UIResource JavaDoc {
300         
301         private JTextComponent JavaDoc exportComp;
302         private boolean shouldRemove;
303         private int p0;
304         private int p1;
305         
306         /**
307          * Try to find a flavor that can be used to import a Transferable.
308          * The set of usable flavors are tried in the following order:
309          * <ol>
310          * <li>First, an attempt is made to find a flavor matching the content type
311          * of the EditorKit for the component.
312          * <li>Second, an attempt to find a text/plain flavor is made.
313          * <li>Third, an attempt to find a flavor representing a String reference
314          * in the same VM is made.
315          * <li>Lastly, DataFlavor.stringFlavor is searched for.
316          * </ol>
317          */

318         protected DataFlavor JavaDoc getImportFlavor(DataFlavor JavaDoc[] flavors, JTextComponent JavaDoc c) {
319             DataFlavor JavaDoc plainFlavor = null;
320             DataFlavor JavaDoc refFlavor = null;
321             DataFlavor JavaDoc stringFlavor = null;
322             
323             if (c instanceof JEditorPane JavaDoc) {
324                 for (int i = 0; i < flavors.length; i++) {
325                     String JavaDoc mime = flavors[i].getMimeType();
326                     if (mime.startsWith(((JEditorPane JavaDoc)c).getEditorKit().getContentType())) {
327                         //return flavors[i]; [REWRITE_PLACE]
328
} else if (plainFlavor == null && mime.startsWith("text/plain")) { //NOI18N
329
plainFlavor = flavors[i];
330                     } else if (refFlavor == null && mime.startsWith("application/x-java-jvm-local-objectref") //NOI18N
331
&& flavors[i].getRepresentationClass() == java.lang.String JavaDoc.class) {
332                         refFlavor = flavors[i];
333                     } else if (stringFlavor == null && flavors[i].equals(DataFlavor.stringFlavor)) {
334                         stringFlavor = flavors[i];
335                     }
336                 }
337                 if (plainFlavor != null) {
338                     return plainFlavor;
339                 } else if (refFlavor != null) {
340                     return refFlavor;
341                 } else if (stringFlavor != null) {
342                     return stringFlavor;
343                 }
344                 return null;
345             }
346             
347             
348             for (int i = 0; i < flavors.length; i++) {
349                 String JavaDoc mime = flavors[i].getMimeType();
350                 if (mime.startsWith("text/plain")) { //NOI18N
351
return flavors[i];
352                 } else if (refFlavor == null && mime.startsWith("application/x-java-jvm-local-objectref") //NOI18N
353
&& flavors[i].getRepresentationClass() == java.lang.String JavaDoc.class) {
354                     refFlavor = flavors[i];
355                 } else if (stringFlavor == null && flavors[i].equals(DataFlavor.stringFlavor)) {
356                     stringFlavor = flavors[i];
357                 }
358             }
359             if (refFlavor != null) {
360                 return refFlavor;
361             } else if (stringFlavor != null) {
362                 return stringFlavor;
363             }
364             return null;
365         }
366         
367         /**
368          * Import the given stream data into the text component.
369          */

370         protected void handleReaderImport(Reader JavaDoc in, JTextComponent JavaDoc c, boolean useRead)
371                 throws BadLocationException JavaDoc, IOException JavaDoc {
372             if (useRead) {
373                 int startPosition = c.getSelectionStart();
374                 int endPosition = c.getSelectionEnd();
375                 int length = endPosition - startPosition;
376                 EditorKit JavaDoc kit = c.getUI().getEditorKit(c);
377                 Document JavaDoc doc = c.getDocument();
378                 if (length > 0) {
379                     doc.remove(startPosition, length);
380                 }
381                 kit.read(in, doc, startPosition);
382             } else {
383                 char[] buff = new char[1024];
384                 int nch;
385                 boolean lastWasCR = false;
386                 int last;
387                 StringBuffer JavaDoc sbuff = null;
388                 
389                 // Read in a block at a time, mapping \r\n to \n, as well as single
390
// \r to \n.
391
while ((nch = in.read(buff, 0, buff.length)) != -1) {
392                     if (sbuff == null) {
393                         sbuff = new StringBuffer JavaDoc(nch);
394                     }
395                     last = 0;
396                     for(int counter = 0; counter < nch; counter++) {
397                         switch(buff[counter]) {
398                             case '\r':
399                                 if (lastWasCR) {
400                                     if (counter == 0) {
401                                         sbuff.append('\n');
402                                     } else {
403                                         buff[counter - 1] = '\n';
404                                     }
405                                 } else {
406                                     lastWasCR = true;
407                                 }
408                                 break;
409                             case '\n':
410                                 if (lastWasCR) {
411                                     if (counter > (last + 1)) {
412                                         sbuff.append(buff, last, counter - last - 1);
413                                     }
414                                     // else nothing to do, can skip \r, next write will
415
// write \n
416
lastWasCR = false;
417                                     last = counter;
418                                 }
419                                 break;
420                             default:
421                                 if (lastWasCR) {
422                                     if (counter == 0) {
423                                         sbuff.append('\n');
424                                     } else {
425                                         buff[counter - 1] = '\n';
426                                     }
427                                     lastWasCR = false;
428                                 }
429                                 break;
430                         }
431                     }
432                     if (last < nch) {
433                         if (lastWasCR) {
434                             if (last < (nch - 1)) {
435                                 sbuff.append(buff, last, nch - last - 1);
436                             }
437                         } else {
438                             sbuff.append(buff, last, nch - last);
439                         }
440                     }
441                 }
442                 if (lastWasCR) {
443                     sbuff.append('\n');
444                 }
445                 c.replaceSelection(sbuff != null ? sbuff.toString() : ""); //NOI18N
446
}
447         }
448         
449         // --- TransferHandler methods ------------------------------------
450

451         /**
452          * This is the type of transfer actions supported by the source. Some models are
453          * not mutable, so a transfer operation of COPY only should
454          * be advertised in that case.
455          *
456          * @param c The component holding the data to be transfered. This
457          * argument is provided to enable sharing of TransferHandlers by
458          * multiple components.
459          * @return This is implemented to return NONE if the component is a JPasswordField
460          * since exporting data via user gestures is not allowed. If the text component is
461          * editable, COPY_OR_MOVE is returned, otherwise just COPY is allowed.
462          */

463         public int getSourceActions(JComponent JavaDoc c) {
464             int actions = NONE;
465             if (! (c instanceof JPasswordField JavaDoc)) {
466                 if (((JTextComponent JavaDoc)c).isEditable()) {
467                     actions = COPY_OR_MOVE;
468                 } else {
469                     actions = COPY;
470                 }
471             }
472             return actions;
473         }
474         
475         /**
476          * Create a Transferable to use as the source for a data transfer.
477          *
478          * @param comp The component holding the data to be transfered. This
479          * argument is provided to enable sharing of TransferHandlers by
480          * multiple components.
481          * @return The representation of the data to be transfered.
482          *
483          */

484         protected Transferable JavaDoc createTransferable(JComponent JavaDoc comp) {
485             exportComp = (JTextComponent JavaDoc)comp;
486             shouldRemove = true;
487             p0 = exportComp.getSelectionStart();
488             p1 = exportComp.getSelectionEnd();
489             return (p0 != p1) ? (new HTMLTransferable(exportComp, p0, p1)) : null;
490         }
491         
492         /**
493          * This method is called after data has been exported. This method should remove
494          * the data that was transfered if the action was MOVE.
495          *
496          * @param source The component that was the source of the data.
497          * @param data The data that was transferred or possibly null
498          * if the action is <code>NONE</code>.
499          * @param action The actual action that was performed.
500          */

501         protected void exportDone(JComponent JavaDoc source, Transferable JavaDoc data, int action) {
502             // only remove the text if shouldRemove has not been set to
503
// false by importData and only if the action is a move
504
if (shouldRemove && action == MOVE) {
505                 HTMLTransferable t = (HTMLTransferable)data;
506                 t.removeText();
507             }
508             
509             exportComp = null;
510         }
511         
512         /**
513          * This method causes a transfer to a component from a clipboard or a
514          * DND drop operation. The Transferable represents the data to be
515          * imported into the component.
516          *
517          * @param comp The component to receive the transfer. This
518          * argument is provided to enable sharing of TransferHandlers by
519          * multiple components.
520          * @param t The data to import
521          * @return true if the data was inserted into the component, false otherwise.
522          */

523         public boolean importData(JComponent JavaDoc comp, Transferable JavaDoc t) {
524             JTextComponent JavaDoc c = (JTextComponent JavaDoc)comp;
525             
526             // if we are importing to the same component that we exported from
527
// then don't actually do anything if the drop location is inside
528
// the drag location and set shouldRemove to false so that exportDone
529
// knows not to remove any data
530
if (c == exportComp && c.getCaretPosition() >= p0 && c.getCaretPosition() <= p1) {
531                 shouldRemove = false;
532                 return true;
533             }
534             
535             boolean imported = false;
536             DataFlavor JavaDoc importFlavor = getImportFlavor(t.getTransferDataFlavors(), c);
537             if (importFlavor != null) {
538                 try {
539                     boolean useRead = false;
540                     if (comp instanceof JEditorPane JavaDoc) {
541                         JEditorPane JavaDoc ep = (JEditorPane JavaDoc)comp;
542                         if (!ep.getContentType().startsWith("text/plain") && //NOI18N
543
importFlavor.getMimeType().startsWith(ep.getContentType())) {
544                             useRead = true;
545                         }
546                     }
547                     InputContext JavaDoc ic = c.getInputContext();
548                     if (ic != null) {
549                         ic.endComposition();
550                     }
551                     Reader JavaDoc r = importFlavor.getReaderForText(t);
552                     handleReaderImport(r, c, useRead);
553                     imported = true;
554                 } catch (UnsupportedFlavorException JavaDoc ufe) {
555                     //just ignore
556
} catch (BadLocationException JavaDoc ble) {
557                     //just ignore
558
} catch (IOException JavaDoc ioe) {
559                     //just ignore
560
}
561             }
562             return imported;
563         }
564         
565         /**
566          * This method indicates if a component would accept an import of the given
567          * set of data flavors prior to actually attempting to import it.
568          *
569          * @param comp The component to receive the transfer. This
570          * argument is provided to enable sharing of TransferHandlers by
571          * multiple components.
572          * @param flavors The data formats available
573          * @return true if the data can be inserted into the component, false otherwise.
574          */

575         public boolean canImport(JComponent JavaDoc comp, DataFlavor JavaDoc[] flavors) {
576             JTextComponent JavaDoc c = (JTextComponent JavaDoc)comp;
577             if (!(c.isEditable() && c.isEnabled())) {
578                 return false;
579             }
580             return (getImportFlavor(flavors, c) != null);
581         }
582         
583         /**
584          * A possible implementation of the Transferable interface
585          * for text components. For a JEditorPane with a rich set
586          * of EditorKit implementations, conversions could be made
587          * giving a wider set of formats. This is implemented to
588          * offer up only the active content type and text/plain
589          * (if that is not the active format) since that can be
590          * extracted from other formats.
591          */

592         static class HTMLTransferable extends BasicTransferable {
593             
594             HTMLTransferable(JTextComponent JavaDoc c, int start, int end) {
595                 super(null, null);
596                 
597                 this.c = c;
598                 
599                 Document JavaDoc doc = c.getDocument();
600                 
601                 try {
602                     p0 = doc.createPosition(start);
603                     p1 = doc.createPosition(end);
604                     
605                     plainData = c.getSelectedText();
606                     
607                     if (c instanceof JEditorPane JavaDoc) {
608                         JEditorPane JavaDoc ep = (JEditorPane JavaDoc)c;
609                         
610                         mimeType = ep.getContentType();
611                         
612                         if (mimeType.startsWith("text/plain")) { //NOI18N
613
return;
614                         }
615                         
616                         StringWriter JavaDoc sw = new StringWriter JavaDoc(p1.getOffset() - p0.getOffset());
617                         ep.getEditorKit().write(sw, doc, p0.getOffset(), p1.getOffset() - p0.getOffset());
618                         
619                         if (mimeType.startsWith("text/html")) { //NOI18N
620
htmlData = sw.toString();
621                         } else {
622                             richText = sw.toString();
623                         }
624                     }
625                 } catch (BadLocationException JavaDoc ble) {
626                 } catch (IOException JavaDoc ioe) {
627                 }
628             }
629             
630             void removeText() {
631                 if ((p0 != null) && (p1 != null) && (p0.getOffset() != p1.getOffset())) {
632                     try {
633                         Document JavaDoc doc = c.getDocument();
634                         doc.remove(p0.getOffset(), p1.getOffset() - p0.getOffset());
635                     } catch (BadLocationException JavaDoc e) {
636                     }
637                 }
638             }
639             
640             // ---- EditorKit other than plain or HTML text -----------------------
641

642             /**
643              * If the EditorKit is not for text/plain or text/html, that format
644              * is supported through the "richer flavors" part of BasicTransferable.
645              */

646             protected DataFlavor JavaDoc[] getRicherFlavors() {
647                 if (richText == null) {
648                     return null;
649                 }
650                 
651                 try {
652                     DataFlavor JavaDoc[] flavors = new DataFlavor JavaDoc[3];
653                     flavors[0] = new DataFlavor JavaDoc(mimeType + ";class=java.lang.String"); //NOI18N
654
flavors[1] = new DataFlavor JavaDoc(mimeType + ";class=java.io.Reader"); //NOI18N
655
flavors[2] = new DataFlavor JavaDoc(mimeType + ";class=java.io.InputStream;charset=unicode"); //NOI18N
656
return flavors;
657                 } catch (ClassNotFoundException JavaDoc cle) {
658                     // fall through to unsupported (should not happen)
659
}
660                 
661                 return null;
662             }
663             
664             /**
665              * The only richer format supported is the file list flavor
666              */

667             protected Object JavaDoc getRicherData(DataFlavor JavaDoc flavor) throws UnsupportedFlavorException JavaDoc {
668                 if (richText == null) {
669                     return null;
670                 }
671                 
672                 if (String JavaDoc.class.equals(flavor.getRepresentationClass())) {
673                     return richText;
674                 } else if (Reader JavaDoc.class.equals(flavor.getRepresentationClass())) {
675                     return new StringReader JavaDoc(richText);
676                 } else if (InputStream JavaDoc.class.equals(flavor.getRepresentationClass())) {
677                     return new ByteArrayInputStream JavaDoc(richText.getBytes());
678                 }
679                 throw new UnsupportedFlavorException JavaDoc(flavor);
680             }
681             
682             Position JavaDoc p0;
683             Position JavaDoc p1;
684             String JavaDoc mimeType;
685             String JavaDoc richText;
686             JTextComponent JavaDoc c;
687         }
688         
689     }
690     
691     private static class BasicTransferable implements Transferable JavaDoc, UIResource JavaDoc {
692         
693         protected String JavaDoc plainData;
694         protected String JavaDoc htmlData;
695         
696         private static DataFlavor JavaDoc[] htmlFlavors;
697         private static DataFlavor JavaDoc[] stringFlavors;
698         private static DataFlavor JavaDoc[] plainFlavors;
699         
700         static {
701             try {
702                 htmlFlavors = new DataFlavor JavaDoc[3];
703                 htmlFlavors[0] = new DataFlavor JavaDoc("text/html;class=java.lang.String"); //NOI18N
704
htmlFlavors[1] = new DataFlavor JavaDoc("text/html;class=java.io.Reader"); //NOI18N
705
htmlFlavors[2] = new DataFlavor JavaDoc("text/html;charset=unicode;class=java.io.InputStream"); //NOI18N
706

707                 plainFlavors = new DataFlavor JavaDoc[3];
708                 plainFlavors[0] = new DataFlavor JavaDoc("text/plain;class=java.lang.String"); //NOI18N
709
plainFlavors[1] = new DataFlavor JavaDoc("text/plain;class=java.io.Reader"); //NOI18N
710
plainFlavors[2] = new DataFlavor JavaDoc("text/plain;charset=unicode;class=java.io.InputStream"); //NOI18N
711

712                 stringFlavors = new DataFlavor JavaDoc[2];
713                 stringFlavors[0] = new DataFlavor JavaDoc(DataFlavor.javaJVMLocalObjectMimeType+";class=java.lang.String"); //NOI18N
714
stringFlavors[1] = DataFlavor.stringFlavor;
715                 
716             } catch (ClassNotFoundException JavaDoc cle) {
717                 System.err.println("error initializing javax.swing.plaf.basic.BasicTranserable"); ////NOI18N
718
}
719         }
720         
721         public BasicTransferable(String JavaDoc plainData, String JavaDoc htmlData) {
722             this.plainData = plainData;
723             this.htmlData = htmlData;
724         }
725         
726         
727         /**
728          * Returns an array of DataFlavor objects indicating the flavors the data
729          * can be provided in. The array should be ordered according to preference
730          * for providing the data (from most richly descriptive to least descriptive).
731          * @return an array of data flavors in which this data can be transferred
732          */

733         public DataFlavor JavaDoc[] getTransferDataFlavors() {
734             DataFlavor JavaDoc[] richerFlavors = getRicherFlavors();
735             int nRicher = (richerFlavors != null) ? richerFlavors.length : 0;
736             int nHTML = (isHTMLSupported()) ? htmlFlavors.length : 0;
737             int nPlain = (isPlainSupported()) ? plainFlavors.length: 0;
738             int nString = (isPlainSupported()) ? stringFlavors.length : 0;
739             int nFlavors = nRicher + nHTML + nPlain + nString;
740             DataFlavor JavaDoc[] flavors = new DataFlavor JavaDoc[nFlavors];
741             
742             // fill in the array
743
int nDone = 0;
744             if (nRicher > 0) {
745                 System.arraycopy(richerFlavors, 0, flavors, nDone, nRicher);
746                 nDone += nRicher;
747             }
748             if (nHTML > 0) {
749                 System.arraycopy(htmlFlavors, 0, flavors, nDone, nHTML);
750                 nDone += nHTML;
751             }
752             if (nPlain > 0) {
753                 System.arraycopy(plainFlavors, 0, flavors, nDone, nPlain);
754                 nDone += nPlain;
755             }
756             if (nString > 0) {
757                 System.arraycopy(stringFlavors, 0, flavors, nDone, nString);
758                 nDone += nString;
759             }
760             return flavors;
761         }
762         
763         /**
764          * Returns whether or not the specified data flavor is supported for
765          * this object.
766          * @param flavor the requested flavor for the data
767          * @return boolean indicating whether or not the data flavor is supported
768          */

769         public boolean isDataFlavorSupported(DataFlavor JavaDoc flavor) {
770             DataFlavor JavaDoc[] flavors = getTransferDataFlavors();
771             for (int i = 0; i < flavors.length; i++) {
772                 if (flavors[i].equals(flavor)) {
773                     return true;
774                 }
775             }
776             return false;
777         }
778         
779         /**
780          * Returns an object which represents the data to be transferred. The class
781          * of the object returned is defined by the representation class of the flavor.
782          *
783          * @param flavor the requested flavor for the data
784          * @see DataFlavor#getRepresentationClass
785          * @exception IOException if the data is no longer available
786          * in the requested flavor.
787          * @exception UnsupportedFlavorException if the requested data flavor is
788          * not supported.
789          */

790         public Object JavaDoc getTransferData(DataFlavor JavaDoc flavor) throws UnsupportedFlavorException JavaDoc, IOException JavaDoc {
791             DataFlavor JavaDoc[] richerFlavors = getRicherFlavors();
792             if (isRicherFlavor(flavor)) {
793                 return getRicherData(flavor);
794             } else if (isHTMLFlavor(flavor)) {
795                 String JavaDoc data = getHTMLData();
796                 data = (data == null) ? "" : data; //NOI18N
797
if (String JavaDoc.class.equals(flavor.getRepresentationClass())) {
798                     return data;
799                 } else if (Reader JavaDoc.class.equals(flavor.getRepresentationClass())) {
800                     return new StringReader JavaDoc(data);
801                 } else if (InputStream JavaDoc.class.equals(flavor.getRepresentationClass())) {
802                     return new ByteArrayInputStream JavaDoc(data.getBytes());
803                 }
804                 // fall through to unsupported
805
} else if (isPlainFlavor(flavor)) {
806                 String JavaDoc data = getPlainData();
807                 data = (data == null) ? "" : data;
808                 if (String JavaDoc.class.equals(flavor.getRepresentationClass())) {
809                     return data;
810                 } else if (Reader JavaDoc.class.equals(flavor.getRepresentationClass())) {
811                     return new StringReader JavaDoc(data);
812                 } else if (InputStream JavaDoc.class.equals(flavor.getRepresentationClass())) {
813                     return new ByteArrayInputStream JavaDoc(data.getBytes());
814                 }
815                 // fall through to unsupported
816

817             } else if (isStringFlavor(flavor)) {
818                 String JavaDoc data = getPlainData();
819                 data = (data == null) ? "" : data; //NOI18N
820
return data;
821             }
822             throw new UnsupportedFlavorException JavaDoc(flavor);
823         }
824         
825         // --- richer subclass flavors ----------------------------------------------
826

827         protected boolean isRicherFlavor(DataFlavor JavaDoc flavor) {
828             DataFlavor JavaDoc[] richerFlavors = getRicherFlavors();
829             int nFlavors = (richerFlavors != null) ? richerFlavors.length : 0;
830             for (int i = 0; i < nFlavors; i++) {
831                 if (richerFlavors[i].equals(flavor)) {
832                     return true;
833                 }
834             }
835             return false;
836         }
837         
838         /**
839          * Some subclasses will have flavors that are more descriptive than HTML
840          * or plain text. If this method returns a non-null value, it will be
841          * placed at the start of the array of supported flavors.
842          */

843         protected DataFlavor JavaDoc[] getRicherFlavors() {
844             return null;
845         }
846         
847         protected Object JavaDoc getRicherData(DataFlavor JavaDoc flavor) throws UnsupportedFlavorException JavaDoc {
848             return null;
849         }
850         
851         // --- html flavors ----------------------------------------------------------
852

853         /**
854          * Returns whether or not the specified data flavor is an HTML flavor that
855          * is supported.
856          * @param flavor the requested flavor for the data
857          * @return boolean indicating whether or not the data flavor is supported
858          */

859         protected boolean isHTMLFlavor(DataFlavor JavaDoc flavor) {
860             DataFlavor JavaDoc[] flavors = htmlFlavors;
861             for (int i = 0; i < flavors.length; i++) {
862                 if (flavors[i].equals(flavor)) {
863                     return true;
864                 }
865             }
866             return false;
867         }
868         
869         /**
870          * Should the HTML flavors be offered? If so, the method
871          * getHTMLData should be implemented to provide something reasonable.
872          */

873         protected boolean isHTMLSupported() {
874             return htmlData != null;
875         }
876         
877         /**
878          * Fetch the data in a text/html format
879          */

880         protected String JavaDoc getHTMLData() {
881             return htmlData;
882         }
883         
884         // --- plain text flavors ----------------------------------------------------
885

886         /**
887          * Returns whether or not the specified data flavor is an plain flavor that
888          * is supported.
889          * @param flavor the requested flavor for the data
890          * @return boolean indicating whether or not the data flavor is supported
891          */

892         protected boolean isPlainFlavor(DataFlavor JavaDoc flavor) {
893             DataFlavor JavaDoc[] flavors = plainFlavors;
894             for (int i = 0; i < flavors.length; i++) {
895                 if (flavors[i].equals(flavor)) {
896                     return true;
897                 }
898             }
899             return false;
900         }
901         
902         /**
903          * Should the plain text flavors be offered? If so, the method
904          * getPlainData should be implemented to provide something reasonable.
905          */

906         protected boolean isPlainSupported() {
907             return plainData != null;
908         }
909         
910         /**
911          * Fetch the data in a text/plain format.
912          */

913         protected String JavaDoc getPlainData() {
914             return plainData;
915         }
916         
917         // --- string flavorss --------------------------------------------------------
918

919         /**
920          * Returns whether or not the specified data flavor is a String flavor that
921          * is supported.
922          * @param flavor the requested flavor for the data
923          * @return boolean indicating whether or not the data flavor is supported
924          */

925         protected boolean isStringFlavor(DataFlavor JavaDoc flavor) {
926             DataFlavor JavaDoc[] flavors = stringFlavors;
927             for (int i = 0; i < flavors.length; i++) {
928                 if (flavors[i].equals(flavor)) {
929                     return true;
930                 }
931             }
932             return false;
933         }
934         
935         
936     }
937     
938     // END of fix of issue #43309
939

940     
941 }
942
943
Popular Tags