Source Code Cross Referenced for TextTransferHandler.java in  » IDE-Netbeans » visualweb.api.designer » org » netbeans » modules » visualweb » extension » openide » text » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » IDE Netbeans » visualweb.api.designer » org.netbeans.modules.visualweb.extension.openide.text 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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-2007 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:
042:        package org.netbeans.modules.visualweb.extension.openide.text;
043:
044:        import java.awt.*;
045:        import java.awt.event.*;
046:        import java.awt.font.*;
047:        import java.awt.datatransfer.*;
048:        import java.awt.dnd.*;
049:        import java.beans.*;
050:        import java.io.*;
051:        import java.net.*;
052:        import java.util.ArrayList;
053:        import java.util.Arrays;
054:        import java.util.List;
055:        import javax.swing.*;
056:        import javax.swing.plaf.*;
057:        import javax.swing.text.*;
058:        import javax.swing.event.*;
059:        import javax.swing.border.Border;
060:        import javax.swing.plaf.UIResource;
061:        import javax.swing.Timer;
062:
063:        import org.openide.ErrorManager;
064:        import org.openide.windows.TopComponent;
065:
066:        // XXX Copied from previously located openide/src/../text/ dir, this is not a NB code.
067:
068:        /* A transfer handler for the editor component. This seems necessary because
069:         * the NetBeans editor doesn't inherit from the Swing plaf.basic package,
070:         * so it's missing a bunch of drag & drop behavior.
071:         * <p>
072:         * This code is basically a merged version of text-related code in
073:         * javax.swing.plaf.basic: BasicTextUI, BasicTransferable, ...
074:         * I had to copy it since it has package protected access in
075:         * javax.swing.plaf.basic.
076:         * <p>
077:         * <b>There is one important difference</b>. In order to allow the DESTINATION
078:         * to decide if the transferable should be moved or copied (e.g. if the
079:         * destination is the same document, move, if it's the clipboard palette,
080:         * copy), there's a global flag that can be set which basically turns off
081:         * moving when a drag is in progress. Yup, this is a bit of a hack, but
082:         * I couldn't find a better way. With Swing, the copy-vs-move decision is
083:         * made when the drag is -started-, and at that point we don't know yet
084:         * where you're going to drop. The docs for TransferHandler exportAsDrag says:
085:         *  <blockquote> action - the transfer action initially requested; this should
086:         *  be a value of either <code>COPY</code> or <code>MOVE</code>;
087:         *  the value may be changed during the course of the drag operation
088:         *  </blockquote>.
089:         * However, it does not say HOW you can change the action, and from looking
090:         * at the code, I suspect it cannot be done, since the action is passed
091:         * to a gesture listener that has private access.
092:         * <p>
093:         * @author Tor Norbye
094:         */
095:
096:        public class TextTransferHandler extends TransferHandler implements 
097:                UIResource {
098:
099:            /** Flag which is only defined during a drag & drop operation.
100:             * Clients (typically drop zones) can set it to true to indicate
101:             * that the data being dragged should be copied, not moved.
102:             * For example, the clipboard viewer sets this when it handles
103:             * the import. That way, the exportDone method knows not to remove
104:             * the text being placed on the clipboard from the document, since
105:             * text dragging (without modified keys) defaults to moving, not
106:             * copying. And we don't want to disallow copying in getSourceActions,
107:             * since dragging text from one place in the document to another
108:             * SHOULD be moved, not copied. */
109:            public static boolean dontRemove = false;
110:
111:            private JTextComponent exportComp;
112:            private boolean shouldRemove;
113:            private int p0;
114:            private int p1;
115:
116:            /**
117:             * Try to find a flavor that can be used to import a Transferable.
118:             * The set of usable flavors are tried in the following order:
119:             * <ol>
120:             *     <li>First, an attempt is made to find a flavor matching the content type
121:             *         of the EditorKit for the component.
122:             *     <li>Second, an attempt to find a text/plain flavor is made.
123:             *     <li>Third, an attempt to find a flavor representing a String reference
124:             *         in the same VM is made.
125:             *     <li>Lastly, DataFlavor.stringFlavor is searched for.
126:             * </ol>
127:             */
128:            protected DataFlavor getImportFlavor(DataFlavor[] flavors,
129:                    JTextComponent c) {
130:                DataFlavor plainFlavor = null;
131:                DataFlavor refFlavor = null;
132:                DataFlavor stringFlavor = null;
133:                if (c instanceof  JEditorPane) {
134:                    for (int i = 0; i < flavors.length; i++) {
135:                        String mime = flavors[i].getMimeType();
136:                        if (mime.startsWith(((JEditorPane) c).getEditorKit()
137:                                .getContentType())) {
138:                            return flavors[i];
139:                        } else if (plainFlavor == null
140:                                && mime.startsWith("text/plain")) {
141:                            plainFlavor = flavors[i];
142:                        } else if (refFlavor == null
143:                                && mime
144:                                        .startsWith("application/x-java-jvm-local-objectref")
145:                                && flavors[i].getRepresentationClass() == java.lang.String.class) {
146:                            refFlavor = flavors[i];
147:                        } else if (stringFlavor == null
148:                                && flavors[i].equals(DataFlavor.stringFlavor)) {
149:                            stringFlavor = flavors[i];
150:                        }
151:                    }
152:                    if (plainFlavor != null) {
153:                        return plainFlavor;
154:                    } else if (refFlavor != null) {
155:                        return refFlavor;
156:                    } else if (stringFlavor != null) {
157:                        return stringFlavor;
158:                    }
159:                    return null;
160:                }
161:
162:                for (int i = 0; i < flavors.length; i++) {
163:                    String mime = flavors[i].getMimeType();
164:                    if (mime.startsWith("text/plain")) {
165:                        return flavors[i];
166:                    } else if (refFlavor == null
167:                            && mime
168:                                    .startsWith("application/x-java-jvm-local-objectref")
169:                            && flavors[i].getRepresentationClass() == java.lang.String.class) {
170:                        refFlavor = flavors[i];
171:                    } else if (stringFlavor == null
172:                            && flavors[i].equals(DataFlavor.stringFlavor)) {
173:                        stringFlavor = flavors[i];
174:                    }
175:                }
176:                if (refFlavor != null) {
177:                    return refFlavor;
178:                } else if (stringFlavor != null) {
179:                    return stringFlavor;
180:                }
181:                return null;
182:            }
183:
184:            /**
185:             * Import the given stream data into the text component.
186:             */
187:            protected void handleReaderImport(Reader in, JTextComponent c,
188:                    boolean useRead) throws BadLocationException, IOException {
189:                if (useRead) {
190:                    int startPosition = c.getSelectionStart();
191:                    int endPosition = c.getSelectionEnd();
192:                    int length = endPosition - startPosition;
193:                    EditorKit kit = c.getUI().getEditorKit(c);
194:                    Document doc = c.getDocument();
195:                    if (length > 0) {
196:                        doc.remove(startPosition, length);
197:                    }
198:                    kit.read(in, doc, startPosition);
199:                } else {
200:                    char[] buff = new char[1024];
201:                    int nch;
202:                    boolean lastWasCR = false;
203:                    int last;
204:                    StringBuffer sbuff = null;
205:
206:                    // Read in a block at a time, mapping \r\n to \n, as well as single
207:                    // \r to \n.
208:                    while ((nch = in.read(buff, 0, buff.length)) != -1) {
209:                        if (sbuff == null) {
210:                            sbuff = new StringBuffer(nch);
211:                        }
212:                        last = 0;
213:                        for (int counter = 0; counter < nch; counter++) {
214:                            switch (buff[counter]) {
215:                            case '\r':
216:                                if (lastWasCR) {
217:                                    if (counter == 0) {
218:                                        sbuff.append('\n');
219:                                    } else {
220:                                        buff[counter - 1] = '\n';
221:                                    }
222:                                } else {
223:                                    lastWasCR = true;
224:                                }
225:                                break;
226:                            case '\n':
227:                                if (lastWasCR) {
228:                                    if (counter > (last + 1)) {
229:                                        sbuff.append(buff, last, counter - last
230:                                                - 1);
231:                                    }
232:                                    // else nothing to do, can skip \r, next write will
233:                                    // write \n
234:                                    lastWasCR = false;
235:                                    last = counter;
236:                                }
237:                                break;
238:                            default:
239:                                if (lastWasCR) {
240:                                    if (counter == 0) {
241:                                        sbuff.append('\n');
242:                                    } else {
243:                                        buff[counter - 1] = '\n';
244:                                    }
245:                                    lastWasCR = false;
246:                                }
247:                                break;
248:                            }
249:                        }
250:                        if (last < nch) {
251:                            if (lastWasCR) {
252:                                if (last < (nch - 1)) {
253:                                    sbuff.append(buff, last, nch - last - 1);
254:                                }
255:                            } else {
256:                                sbuff.append(buff, last, nch - last);
257:                            }
258:                        }
259:                    }
260:                    if (lastWasCR) {
261:                        sbuff.append('\n');
262:                    }
263:                    c.replaceSelection(sbuff != null ? sbuff.toString() : "");
264:                }
265:            }
266:
267:            // --- TransferHandler methods ------------------------------------
268:
269:            /**
270:             * This is the type of transfer actions supported by the source.  Some models are 
271:             * not mutable, so a transfer operation of COPY only should
272:             * be advertised in that case.
273:             * 
274:             * @param c  The component holding the data to be transfered.  This
275:             *  argument is provided to enable sharing of TransferHandlers by
276:             *  multiple components.
277:             * @return  This is implemented to return NONE if the component is a JPasswordField
278:             *  since exporting data via user gestures is not allowed.  If the text component is
279:             *  editable, COPY_OR_MOVE is returned, otherwise just COPY is allowed.
280:             */
281:            public int getSourceActions(JComponent c) {
282:                int actions = NONE;
283:                if (!(c instanceof  JPasswordField)) {
284:                    if (((JTextComponent) c).isEditable()) {
285:                        actions = COPY_OR_MOVE;
286:                    } else {
287:                        actions = COPY;
288:                    }
289:                }
290:                return actions;
291:            }
292:
293:            /**
294:             * Create a Transferable to use as the source for a data transfer.
295:             *
296:             * @param comp  The component holding the data to be transfered.  This
297:             *  argument is provided to enable sharing of TransferHandlers by
298:             *  multiple components.
299:             * @return  The representation of the data to be transfered. 
300:             *  
301:             */
302:            protected Transferable createTransferable(JComponent comp) {
303:                exportComp = (JTextComponent) comp;
304:                shouldRemove = true;
305:                dontRemove = false;
306:                p0 = exportComp.getSelectionStart();
307:                p1 = exportComp.getSelectionEnd();
308:                return (p0 != p1) ? (new TextTransferable(exportComp, p0, p1))
309:                        : null;
310:            }
311:
312:            /**
313:             * This method is called after data has been exported.  This
314:             * method should remove the data that was transfered if the action
315:             * was MOVE.
316:             *
317:             * @param source The component that was the source of the data.
318:             * @param data   The data that was transferred or possibly null
319:             *               if the action is <code>NONE</code>.
320:             * @param action The actual action that was performed.  
321:             */
322:            protected void exportDone(JComponent source, Transferable data,
323:                    int action) {
324:                // only remove the text if shouldRemove has not been set to
325:                // false by importData and only if the action is a move
326:                if (shouldRemove && action == MOVE) {
327:                    TextTransferable t = (TextTransferable) data;
328:                    if (!dontRemove) {
329:                        t.removeText();
330:                    }
331:                }
332:
333:                exportComp = null;
334:            }
335:
336:            /**
337:             * This method causes a transfer to a component from a clipboard or a 
338:             * DND drop operation.  The Transferable represents the data to be
339:             * imported into the component.  
340:             *
341:             * @param comp  The component to receive the transfer.  This
342:             *  argument is provided to enable sharing of TransferHandlers by
343:             *  multiple components.
344:             * @param t     The data to import
345:             * @return  true if the data was inserted into the component, false otherwise.
346:             */
347:            public boolean importData(JComponent comp, Transferable t) {
348:                JTextComponent c = (JTextComponent) comp;
349:
350:                // if we are importing to the same component that we exported from
351:                // then don't actually do anything if the drop location is inside
352:                // the drag location and set shouldRemove to false so that exportDone
353:                // knows not to remove any data
354:                if (c == exportComp && c.getCaretPosition() >= p0
355:                        && c.getCaretPosition() <= p1) {
356:                    shouldRemove = false;
357:                    return true;
358:                }
359:
360:                boolean imported = false;
361:                DataFlavor importFlavor = getImportFlavor(t
362:                        .getTransferDataFlavors(), c);
363:                if (importFlavor != null) {
364:                    try {
365:                        boolean useRead = false;
366:                        if (comp instanceof  JEditorPane) {
367:                            JEditorPane ep = (JEditorPane) comp;
368:                            if (!ep.getContentType().startsWith("text/plain")
369:                                    && importFlavor.getMimeType().startsWith(
370:                                            ep.getContentType())) {
371:                                useRead = true;
372:
373:                            }
374:
375:                            // XXX The hack, in order to call the callback (which in this case is 
376:                            // expected to show the dialog letting user to deal with parametrized code clip at the drop time),
377:                            // masked into special flavor.
378:                            if (t
379:                                    .isDataFlavorSupported(CodeClipTransferData.CODE_CLIP_DATA_FLAVOR)) {
380:                                try {
381:                                    Runnable r = (Runnable) t
382:                                            .getTransferData(CodeClipTransferData.CODE_CLIP_DATA_FLAVOR);
383:                                    if (r != null) {
384:                                        r.run();
385:                                    }
386:                                } catch (IOException ioe) {
387:                                    ErrorManager.getDefault().notify(
388:                                            ErrorManager.INFORMATIONAL, ioe);
389:                                } catch (UnsupportedFlavorException ufe) {
390:                                    ErrorManager.getDefault().notify(
391:                                            ErrorManager.INFORMATIONAL, ufe);
392:                                }
393:                            }
394:                        }
395:                        Reader r = importFlavor.getReaderForText(t);
396:                        handleReaderImport(r, c, useRead);
397:                        imported = true;
398:
399:                        // #4946925 Trying to put the activation to the drop target.
400:                        TopComponent tc = (TopComponent) SwingUtilities
401:                                .getAncestorOfClass(TopComponent.class, c);
402:                        if (tc != null) {
403:                            tc.requestActive();
404:                        }
405:                    } catch (UnsupportedFlavorException ufe) {
406:                        ErrorManager.getDefault().notify(
407:                                ErrorManager.INFORMATIONAL, ufe);
408:                    } catch (BadLocationException ble) {
409:                        ErrorManager.getDefault().notify(
410:                                ErrorManager.INFORMATIONAL, ble);
411:                    } catch (IOException ioe) {
412:                        ErrorManager.getDefault().notify(
413:                                ErrorManager.INFORMATIONAL, ioe);
414:                    }
415:                }
416:                return imported;
417:            }
418:
419:            /**
420:             * This method indicates if a component would accept an import of the given
421:             * set of data flavors prior to actually attempting to import it. 
422:             *
423:             * @param comp  The component to receive the transfer.  This
424:             *  argument is provided to enable sharing of TransferHandlers by
425:             *  multiple components.
426:             * @param flavors  The data formats available
427:             * @return  true if the data can be inserted into the component, false otherwise.
428:             */
429:            public boolean canImport(JComponent comp, DataFlavor[] flavors) {
430:                JTextComponent c = (JTextComponent) comp;
431:                if (!(c.isEditable() && c.isEnabled())) {
432:                    return false;
433:                }
434:                return (getImportFlavor(flavors, c) != null);
435:            }
436:
437:            /**
438:             * A possible implementation of the Transferable interface
439:             * for text components.  For a JEditorPane with a rich set
440:             * of EditorKit implementations, conversions could be made
441:             * giving a wider set of formats.  This is implemented to
442:             * offer up only the active content type and text/plain
443:             * (if that is not the active format) since that can be
444:             * extracted from other formats.
445:             */
446:            static class TextTransferable implements  Transferable, UIResource {
447:
448:                // begin copied from BasicTransferable
449:                protected String plainData = null;
450:                protected String htmlData = null;
451:
452:                private static DataFlavor[] htmlFlavors;
453:                private static DataFlavor[] stringFlavors;
454:                private static DataFlavor[] plainFlavors;
455:
456:                static {
457:                    try {
458:                        htmlFlavors = new DataFlavor[3];
459:                        htmlFlavors[0] = new DataFlavor(
460:                                "text/html;class=java.lang.String");
461:                        htmlFlavors[1] = new DataFlavor(
462:                                "text/html;class=java.io.Reader");
463:                        htmlFlavors[2] = new DataFlavor(
464:                                "text/html;charset=unicode;class=java.io.InputStream");
465:
466:                        plainFlavors = new DataFlavor[3];
467:                        plainFlavors[0] = new DataFlavor(
468:                                "text/plain;class=java.lang.String");
469:                        plainFlavors[1] = new DataFlavor(
470:                                "text/plain;class=java.io.Reader");
471:                        plainFlavors[2] = new DataFlavor(
472:                                "text/plain;charset=unicode;class=java.io.InputStream");
473:
474:                        stringFlavors = new DataFlavor[2];
475:                        stringFlavors[0] = new DataFlavor(
476:                                DataFlavor.javaJVMLocalObjectMimeType
477:                                        + ";class=java.lang.String");
478:                        stringFlavors[1] = DataFlavor.stringFlavor;
479:
480:                    } catch (ClassNotFoundException cle) {
481:                        System.err
482:                                .println("error initializing javax.swing.plaf.basic.BasicTranserable");
483:                    }
484:                }
485:
486:                /**
487:                 * Returns an array of DataFlavor objects indicating the flavors the data 
488:                 * can be provided in.  The array should be ordered according to preference
489:                 * for providing the data (from most richly descriptive to least descriptive).
490:                 * @return an array of data flavors in which this data can be transferred
491:                 */
492:                public DataFlavor[] getTransferDataFlavors() {
493:                    DataFlavor[] richerFlavors = getRicherFlavors();
494:                    int nRicher = (richerFlavors != null) ? richerFlavors.length
495:                            : 0;
496:                    int nHTML = (isHTMLSupported()) ? htmlFlavors.length : 0;
497:                    int nPlain = (isPlainSupported()) ? plainFlavors.length : 0;
498:                    int nString = (isPlainSupported()) ? stringFlavors.length
499:                            : 0;
500:                    int nFlavors = nRicher + nHTML + nPlain + nString;
501:                    DataFlavor[] flavors = new DataFlavor[nFlavors];
502:
503:                    // fill in the array
504:                    int nDone = 0;
505:                    if (nRicher > 0) {
506:                        System.arraycopy(richerFlavors, 0, flavors, nDone,
507:                                nRicher);
508:                        nDone += nRicher;
509:                    }
510:                    if (nHTML > 0) {
511:                        System.arraycopy(htmlFlavors, 0, flavors, nDone, nHTML);
512:                        nDone += nHTML;
513:                    }
514:                    if (nPlain > 0) {
515:                        System.arraycopy(plainFlavors, 0, flavors, nDone,
516:                                nPlain);
517:                        nDone += nPlain;
518:                    }
519:                    if (nString > 0) {
520:                        System.arraycopy(stringFlavors, 0, flavors, nDone,
521:                                nString);
522:                        nDone += nString;
523:                    }
524:                    return flavors;
525:                }
526:
527:                /**
528:                 * Returns whether or not the specified data flavor is supported for
529:                 * this object.
530:                 * @param flavor the requested flavor for the data
531:                 * @return boolean indicating whether or not the data flavor is supported
532:                 */
533:                public boolean isDataFlavorSupported(DataFlavor flavor) {
534:                    DataFlavor[] flavors = getTransferDataFlavors();
535:                    for (int i = 0; i < flavors.length; i++) {
536:                        if (flavors[i].equals(flavor)) {
537:                            return true;
538:                        }
539:                    }
540:                    return false;
541:                }
542:
543:                /**
544:                 * Returns an object which represents the data to be transferred.  The class 
545:                 * of the object returned is defined by the representation class of the flavor.
546:                 *
547:                 * @param flavor the requested flavor for the data
548:                 * @see DataFlavor#getRepresentationClass
549:                 * @exception IOException                if the data is no longer available
550:                 *              in the requested flavor.
551:                 * @exception UnsupportedFlavorException if the requested data flavor is
552:                 *              not supported.
553:                 */
554:                public Object getTransferData(DataFlavor flavor)
555:                        throws UnsupportedFlavorException, IOException {
556:                    DataFlavor[] richerFlavors = getRicherFlavors();
557:                    if (isRicherFlavor(flavor)) {
558:                        return getRicherData(flavor);
559:                    } else if (isHTMLFlavor(flavor)) {
560:                        String data = getHTMLData();
561:                        data = (data == null) ? "" : data;
562:                        if (String.class
563:                                .equals(flavor.getRepresentationClass())) {
564:                            return data;
565:                        } else if (Reader.class.equals(flavor
566:                                .getRepresentationClass())) {
567:                            return new StringReader(data);
568:                        } else if (InputStream.class.equals(flavor
569:                                .getRepresentationClass())) {
570:                            return new StringBufferInputStream(data);
571:                        }
572:                        // fall through to unsupported
573:                    } else if (isPlainFlavor(flavor)) {
574:                        String data = getPlainData();
575:                        data = (data == null) ? "" : data;
576:                        if (String.class
577:                                .equals(flavor.getRepresentationClass())) {
578:                            return data;
579:                        } else if (Reader.class.equals(flavor
580:                                .getRepresentationClass())) {
581:                            return new StringReader(data);
582:                        } else if (InputStream.class.equals(flavor
583:                                .getRepresentationClass())) {
584:                            return new StringBufferInputStream(data);
585:                        }
586:                        // fall through to unsupported
587:
588:                    } else if (isStringFlavor(flavor)) {
589:                        String data = getPlainData();
590:                        data = (data == null) ? "" : data;
591:                        return data;
592:                    }
593:                    throw new UnsupportedFlavorException(flavor);
594:                }
595:
596:                // --- richer subclass flavors ----------------------------------------------
597:
598:                protected boolean isRicherFlavor(DataFlavor flavor) {
599:                    DataFlavor[] richerFlavors = getRicherFlavors();
600:                    int nFlavors = (richerFlavors != null) ? richerFlavors.length
601:                            : 0;
602:                    for (int i = 0; i < nFlavors; i++) {
603:                        if (richerFlavors[i].equals(flavor)) {
604:                            return true;
605:                        }
606:                    }
607:                    return false;
608:                }
609:
610:                // --- html flavors ----------------------------------------------------------
611:
612:                /**
613:                 * Returns whether or not the specified data flavor is an HTML flavor that
614:                 * is supported.
615:                 * @param flavor the requested flavor for the data
616:                 * @return boolean indicating whether or not the data flavor is supported
617:                 */
618:                protected boolean isHTMLFlavor(DataFlavor flavor) {
619:                    DataFlavor[] flavors = htmlFlavors;
620:                    for (int i = 0; i < flavors.length; i++) {
621:                        if (flavors[i].equals(flavor)) {
622:                            return true;
623:                        }
624:                    }
625:                    return false;
626:                }
627:
628:                /**
629:                 * Should the HTML flavors be offered?  If so, the method
630:                 * getHTMLData should be implemented to provide something reasonable.
631:                 */
632:                protected boolean isHTMLSupported() {
633:                    return htmlData != null;
634:                }
635:
636:                /**
637:                 * Fetch the data in a text/html format
638:                 */
639:                protected String getHTMLData() {
640:                    return htmlData;
641:                }
642:
643:                // --- plain text flavors ----------------------------------------------------
644:
645:                /**
646:                 * Returns whether or not the specified data flavor is an plain flavor that
647:                 * is supported.
648:                 * @param flavor the requested flavor for the data
649:                 * @return boolean indicating whether or not the data flavor is supported
650:                 */
651:                protected boolean isPlainFlavor(DataFlavor flavor) {
652:                    DataFlavor[] flavors = plainFlavors;
653:                    for (int i = 0; i < flavors.length; i++) {
654:                        if (flavors[i].equals(flavor)) {
655:                            return true;
656:                        }
657:                    }
658:                    return false;
659:                }
660:
661:                /**
662:                 * Should the plain text flavors be offered?  If so, the method
663:                 * getPlainData should be implemented to provide something reasonable.
664:                 */
665:                protected boolean isPlainSupported() {
666:                    return plainData != null;
667:                }
668:
669:                /**
670:                 * Fetch the data in a text/plain format.
671:                 */
672:                protected String getPlainData() {
673:                    return plainData;
674:                }
675:
676:                // --- string flavorss --------------------------------------------------------
677:
678:                /**
679:                 * Returns whether or not the specified data flavor is a String flavor that
680:                 * is supported.
681:                 * @param flavor the requested flavor for the data
682:                 * @return boolean indicating whether or not the data flavor is supported
683:                 */
684:                protected boolean isStringFlavor(DataFlavor flavor) {
685:                    DataFlavor[] flavors = stringFlavors;
686:                    for (int i = 0; i < flavors.length; i++) {
687:                        if (flavors[i].equals(flavor)) {
688:                            return true;
689:                        }
690:                    }
691:                    return false;
692:                }
693:
694:                // end copied from BasicTransferable
695:
696:                TextTransferable(JTextComponent c, int start, int end) {
697:                    this .c = c;
698:
699:                    Document doc = c.getDocument();
700:
701:                    try {
702:                        p0 = doc.createPosition(start);
703:                        p1 = doc.createPosition(end);
704:
705:                        plainData = c.getSelectedText();
706:
707:                        if (c instanceof  JEditorPane) {
708:                            JEditorPane ep = (JEditorPane) c;
709:
710:                            mimeType = ep.getContentType();
711:
712:                            if (mimeType.startsWith("text/plain")) {
713:                                return;
714:                            }
715:
716:                            StringWriter sw = new StringWriter(p1.getOffset()
717:                                    - p0.getOffset());
718:                            ep.getEditorKit().write(sw, doc, p0.getOffset(),
719:                                    p1.getOffset() - p0.getOffset());
720:
721:                            if (mimeType.startsWith("text/html")) {
722:                                htmlData = sw.toString();
723:                            } else {
724:                                richText = sw.toString();
725:                            }
726:                        }
727:                    } catch (BadLocationException ble) {
728:                    } catch (IOException ioe) {
729:                    }
730:                }
731:
732:                void removeText() {
733:                    if ((p0 != null) && (p1 != null)
734:                            && (p0.getOffset() != p1.getOffset())) {
735:                        try {
736:                            Document doc = c.getDocument();
737:                            doc.remove(p0.getOffset(), p1.getOffset()
738:                                    - p0.getOffset());
739:                        } catch (BadLocationException e) {
740:                        }
741:                    }
742:                }
743:
744:                // ---- EditorKit other than plain or HTML text -----------------------
745:
746:                /** 
747:                 * If the EditorKit is not for text/plain or text/html, that format
748:                 * is supported through the "richer flavors" part of BasicTransferable.
749:                 */
750:                protected DataFlavor[] getRicherFlavors() {
751:                    if (richText == null) {
752:                        return null;
753:                    }
754:
755:                    try {
756:                        DataFlavor[] flavors = new DataFlavor[3];
757:                        flavors[0] = new DataFlavor(mimeType
758:                                + ";class=java.lang.String");
759:                        flavors[1] = new DataFlavor(mimeType
760:                                + ";class=java.io.Reader");
761:                        flavors[2] = new DataFlavor(mimeType
762:                                + ";class=java.io.InputStream;charset=unicode");
763:                        return flavors;
764:                    } catch (ClassNotFoundException cle) {
765:                        // fall through to unsupported (should not happen)
766:                    }
767:
768:                    return null;
769:                }
770:
771:                /**
772:                 * The only richer format supported is the file list flavor
773:                 */
774:                protected Object getRicherData(DataFlavor flavor)
775:                        throws UnsupportedFlavorException {
776:                    if (richText == null) {
777:                        return null;
778:                    }
779:
780:                    if (String.class.equals(flavor.getRepresentationClass())) {
781:                        return richText;
782:                    } else if (Reader.class.equals(flavor
783:                            .getRepresentationClass())) {
784:                        return new StringReader(richText);
785:                    } else if (InputStream.class.equals(flavor
786:                            .getRepresentationClass())) {
787:                        return new StringBufferInputStream(richText);
788:                    }
789:                    throw new UnsupportedFlavorException(flavor);
790:                }
791:
792:                Position p0;
793:                Position p1;
794:                String mimeType;
795:                String richText;
796:                JTextComponent c;
797:            }
798:
799:            // XXX Hack to enable poping up a dialog when DnD of code clip.
800:            public static class CodeClipTransferData extends StringSelection {
801:
802:                // XXX Fake DataFlavor.. for cheating to retrieve the callback.
803:                private static final DataFlavor CODE_CLIP_DATA_FLAVOR = new DataFlavor(
804:                        CodeClipTransferData.class, CodeClipTransferData.class
805:                                .getName()); // TEMP
806:
807:                // XXX Callback to provide the popup.
808:                private Runnable callback;
809:                // XXX We need to manipulate the data in this class (the superclass is private).
810:                private String data;
811:
812:                public CodeClipTransferData(String data) {
813:                    super (data); // Just fake.
814:                    this .data = data;
815:                }
816:
817:                public void setCallback(Runnable callback) {
818:                    this .callback = callback;
819:                }
820:
821:                public void resetData(String data) {
822:                    this .data = data;
823:                }
824:
825:                // XXX Overriden to manipulate with our data field.
826:                public DataFlavor[] getTransferDataFlavors() {
827:                    DataFlavor[] dfs = super .getTransferDataFlavors();
828:                    List flavors = new ArrayList(Arrays.asList(dfs));
829:                    flavors.add(CODE_CLIP_DATA_FLAVOR);
830:                    return (DataFlavor[]) flavors.toArray(new DataFlavor[0]);
831:                }
832:
833:                // XXX Overriden to manipulate with our data field.
834:                public boolean isDataFlavorSupported(DataFlavor flavor) {
835:                    if (flavor == CODE_CLIP_DATA_FLAVOR) {
836:                        return true;
837:                    }
838:
839:                    return super .isDataFlavorSupported(flavor);
840:                }
841:
842:                // XXX Overriden to manipulate with our data field and provide the hacking callback.
843:                public Object getTransferData(DataFlavor flavor)
844:                        throws UnsupportedFlavorException, IOException {
845:                    if (flavor == CODE_CLIP_DATA_FLAVOR) {
846:                        return callback;
847:                    }
848:
849:                    // JCK Test StringSelection0007: if 'flavor' is null, throw NPE
850:                    if (flavor.equals(DataFlavor.stringFlavor)) {
851:                        return (Object) data;
852:                    } else if (flavor.equals(DataFlavor.plainTextFlavor)) { // deprecated
853:                        return new StringReader(data);
854:                    } else {
855:                        throw new UnsupportedFlavorException(flavor);
856:                    }
857:                }
858:
859:            }
860:        }
w_ww___._j__a__va__2__s_.___c___o___m | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.