OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [javax/] [swing/] [JEditorPane.java] - Blame information for rev 772

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 772 jeremybenn
/* JEditorPane.java --
2
   Copyright (C) 2002, 2004, 2005, 2006,  Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
package javax.swing;
40
 
41
import java.awt.Container;
42
import java.awt.Dimension;
43
import java.io.BufferedInputStream;
44
import java.io.FilterInputStream;
45
import java.io.IOException;
46
import java.io.InputStream;
47
import java.io.InputStreamReader;
48
import java.io.Reader;
49
import java.io.StringReader;
50
import java.net.MalformedURLException;
51
import java.net.URL;
52
import java.net.URLConnection;
53
import java.util.HashMap;
54
 
55
import javax.accessibility.AccessibleContext;
56
import javax.accessibility.AccessibleHyperlink;
57
import javax.accessibility.AccessibleHypertext;
58
import javax.accessibility.AccessibleStateSet;
59
import javax.accessibility.AccessibleText;
60
import javax.swing.event.HyperlinkEvent;
61
import javax.swing.event.HyperlinkListener;
62
import javax.swing.plaf.TextUI;
63
import javax.swing.text.AbstractDocument;
64
import javax.swing.text.BadLocationException;
65
import javax.swing.text.DefaultEditorKit;
66
import javax.swing.text.Document;
67
import javax.swing.text.EditorKit;
68
import javax.swing.text.Element;
69
import javax.swing.text.JTextComponent;
70
import javax.swing.text.View;
71
import javax.swing.text.ViewFactory;
72
import javax.swing.text.WrappedPlainView;
73
import javax.swing.text.html.HTML;
74
import javax.swing.text.html.HTMLDocument;
75
import javax.swing.text.html.HTMLEditorKit;
76
 
77
/**
78
 * A powerful text editor component that can handle different types of
79
 * content.
80
 *
81
 * The JEditorPane text component is driven by an instance of
82
 * {@link EditorKit}. The editor kit is responsible for providing
83
 * a default {@link Document} implementation, a mechanism for loading
84
 * and saving documents of its supported content type and providing
85
 * a set of {@link Action}s for manipulating the content.
86
 *
87
 * By default the following content types are supported:
88
 * <ul>
89
 * <li><code>text/plain</code>: Plain text, handled by
90
 *   {@link javax.swing.text.DefaultEditorKit}.</li>
91
 * <li><code>text/html</code>: HTML 4.0 styled text, handled by
92
 *   {@link javax.swing.text.html.HTMLEditorKit}.</li>
93
 * <li><code>text/rtf</code>: RTF text, handled by
94
 *   {@link javax.swing.text.rtf.RTFEditorKit}.</li>
95
 * </ul>
96
 *
97
 * @author original author unknown
98
 * @author Roman Kennke (roman@kennke.org)
99
 * @author Anthony Balkissoon abalkiss at redhat dot com
100
 */
101
public class JEditorPane extends JTextComponent
102
{
103
  /**
104
   * Provides accessibility support for <code>JEditorPane</code>.
105
   *
106
   * @author Roman Kennke (kennke@aicas.com)
107
   */
108
  protected class AccessibleJEditorPane extends AccessibleJTextComponent
109
  {
110
 
111
    /**
112
     * Creates a new <code>AccessibleJEditorPane</code> object.
113
     */
114
    protected AccessibleJEditorPane()
115
    {
116
      super();
117
    }
118
 
119
    /**
120
     * Returns a description of this <code>AccessibleJEditorPane</code>. If
121
     * this property is not set, then this returns the content-type of the
122
     * editor pane.
123
     *
124
     * @return a description of this AccessibleJEditorPane
125
     */
126
    public String getAccessibleDescription()
127
    {
128
      String descr = super.getAccessibleDescription();
129
      if (descr == null)
130
        return getContentType();
131
      else
132
        return descr;
133
    }
134
 
135
    /**
136
     * Returns the accessible state of this <code>AccessibleJEditorPane</code>.
137
     *
138
     * @return  the accessible state of this <code>AccessibleJEditorPane</code>
139
     */
140
    public AccessibleStateSet getAccessibleStateSet()
141
    {
142
      AccessibleStateSet state = super.getAccessibleStateSet();
143
      // TODO: Figure out what state must be added here to the super's state.
144
      return state;
145
    }
146
  }
147
 
148
  /**
149
   * Provides accessibility support for <code>JEditorPane</code>s, when the
150
   * editor kit is an instance of {@link HTMLEditorKit}.
151
   *
152
   * @author Roman Kennke (kennke@aicas.com)
153
   */
154
  protected class AccessibleJEditorPaneHTML extends AccessibleJEditorPane
155
  {
156
    /**
157
     * Returns the accessible text of the <code>JEditorPane</code>. This will
158
     * be an instance of
159
     * {@link JEditorPaneAccessibleHypertextSupport}.
160
     *
161
     * @return the accessible text of the <code>JEditorPane</code>
162
     */
163
    public AccessibleText getAccessibleText()
164
    {
165
      return new JEditorPaneAccessibleHypertextSupport();
166
    }
167
  }
168
 
169
  /**
170
   * This is the accessible text that is returned by
171
   * {@link AccessibleJEditorPaneHTML#getAccessibleText()}.
172
   *
173
   * @author Roman Kennke (kennke@aicas.com)
174
   */
175
  protected class JEditorPaneAccessibleHypertextSupport
176
    extends AccessibleJEditorPane implements AccessibleHypertext
177
  {
178
 
179
    /**
180
     * Creates a new JEditorPaneAccessibleHypertextSupport object.
181
     */
182
    public JEditorPaneAccessibleHypertextSupport()
183
    {
184
      super();
185
    }
186
 
187
    /**
188
     * The accessible representation of a HTML link.
189
     *
190
     * @author Roman Kennke (kennke@aicas.com)
191
     */
192
    public class HTMLLink extends AccessibleHyperlink
193
    {
194
 
195
      /**
196
       * The element in the document that represents the link.
197
       */
198
      Element element;
199
 
200
      /**
201
       * Creates a new <code>HTMLLink</code>.
202
       *
203
       * @param el the link element
204
       */
205
      public HTMLLink(Element el)
206
      {
207
        this.element = el;
208
      }
209
 
210
      /**
211
       * Returns <code>true</code> if this <code>HTMLLink</code> is still
212
       * valid. A <code>HTMLLink</code> can become invalid when the document
213
       * changes.
214
       *
215
       * @return <code>true</code> if this <code>HTMLLink</code> is still
216
       *         valid
217
       */
218
      public boolean isValid()
219
      {
220
        // I test here if the element at our element's start offset is the
221
        // same as the element in the document at this offset. If this is true,
222
        // I consider the link valid, if not, then this link no longer
223
        // represented by this HTMLLink and therefor invalid.
224
        HTMLDocument doc = (HTMLDocument) getDocument();
225
        return doc.getCharacterElement(element.getStartOffset()) == element;
226
      }
227
 
228
      /**
229
       * Returns the number of AccessibleActions in this link object. In
230
       * general, link have 1 AccessibleAction associated with them. There are
231
       * special cases where links can have multiple actions associated, like
232
       * in image maps.
233
       *
234
       * @return the number of AccessibleActions in this link object
235
       */
236
      public int getAccessibleActionCount()
237
      {
238
        // TODO: Implement the special cases.
239
        return 1;
240
      }
241
 
242
      /**
243
       * Performs the specified action on the link object. This ususally means
244
       * activating the link.
245
       *
246
       * @return <code>true</code> if the action has been performed
247
       *         successfully, <code>false</code> otherwise
248
       */
249
      public boolean doAccessibleAction(int i)
250
      {
251
        String href = (String) element.getAttributes().getAttribute("href");
252
        HTMLDocument doc = (HTMLDocument) getDocument();
253
        try
254
          {
255
            URL url = new URL(doc.getBase(), href);
256
            setPage(url);
257
            String desc = doc.getText(element.getStartOffset(),
258
                            element.getEndOffset() - element.getStartOffset());
259
            HyperlinkEvent ev =
260
              new HyperlinkEvent(JEditorPane.this,
261
                                 HyperlinkEvent.EventType.ACTIVATED, url, desc,
262
                                 element);
263
            fireHyperlinkUpdate(ev);
264
            return true;
265
          }
266
        catch (Exception ex)
267
          {
268
            return false;
269
          }
270
      }
271
 
272
      /**
273
       * Returns the description of the action at action index <code>i</code>.
274
       * This method returns the text within the element associated with this
275
       * link.
276
       *
277
       * @param i the action index
278
       *
279
       * @return the description of the action at action index <code>i</code>
280
       */
281
      public String getAccessibleActionDescription(int i)
282
      {
283
        HTMLDocument doc = (HTMLDocument) getDocument();
284
        try
285
          {
286
            return doc.getText(element.getStartOffset(),
287
                            element.getEndOffset() - element.getStartOffset());
288
          }
289
        catch (BadLocationException ex)
290
          {
291
            throw (AssertionError)
292
            new AssertionError("BadLocationException must not be thrown "
293
                               + "here.")
294
              .initCause(ex);
295
          }
296
      }
297
 
298
      /**
299
       * Returns an {@link URL} object, that represents the action at action
300
       * index <code>i</code>.
301
       *
302
       * @param i the action index
303
       *
304
       * @return an {@link URL} object, that represents the action at action
305
       *         index <code>i</code>
306
       */
307
      public Object getAccessibleActionObject(int i)
308
      {
309
        String href = (String) element.getAttributes().getAttribute("href");
310
        HTMLDocument doc = (HTMLDocument) getDocument();
311
        try
312
          {
313
            URL url = new URL(doc.getBase(), href);
314
            return url;
315
          }
316
        catch (MalformedURLException ex)
317
          {
318
            return null;
319
          }
320
      }
321
 
322
      /**
323
       * Returns an object that represents the link anchor. For examples, if
324
       * the link encloses a string, then a <code>String</code> object is
325
       * returned, if the link encloses an &lt;img&gt; tag, then an
326
       * <code>ImageIcon</code> object is returned.
327
       *
328
       * @return an object that represents the link anchor
329
       */
330
      public Object getAccessibleActionAnchor(int i)
331
      {
332
        // TODO: This is only the String case. Implement all cases.
333
        return getAccessibleActionDescription(i);
334
      }
335
 
336
      /**
337
       * Returns the start index of the hyperlink element.
338
       *
339
       * @return the start index of the hyperlink element
340
       */
341
      public int getStartIndex()
342
      {
343
        return element.getStartOffset();
344
      }
345
 
346
      /**
347
       * Returns the end index of the hyperlink element.
348
       *
349
       * @return the end index of the hyperlink element
350
       */
351
      public int getEndIndex()
352
      {
353
        return element.getEndOffset();
354
      }
355
 
356
    }
357
 
358
    /**
359
     * Returns the number of hyperlinks in the document.
360
     *
361
     * @return the number of hyperlinks in the document
362
     */
363
    public int getLinkCount()
364
    {
365
      HTMLDocument doc = (HTMLDocument) getDocument();
366
      HTMLDocument.Iterator linkIter = doc.getIterator(HTML.Tag.A);
367
      int count = 0;
368
      while (linkIter.isValid())
369
        {
370
          count++;
371
          linkIter.next();
372
        }
373
      return count;
374
    }
375
 
376
    /**
377
     * Returns the <code>i</code>-th hyperlink in the document or
378
     * <code>null</code> if there is no hyperlink with the specified index.
379
     *
380
     * @param i the index of the hyperlink to return
381
     *
382
     * @return the <code>i</code>-th hyperlink in the document or
383
     *         <code>null</code> if there is no hyperlink with the specified
384
     *         index
385
     */
386
    public AccessibleHyperlink getLink(int i)
387
    {
388
      HTMLDocument doc = (HTMLDocument) getDocument();
389
      HTMLDocument.Iterator linkIter = doc.getIterator(HTML.Tag.A);
390
      int count = 0;
391
      while (linkIter.isValid())
392
        {
393
          count++;
394
          if (count == i)
395
            break;
396
          linkIter.next();
397
        }
398
      if (linkIter.isValid())
399
        {
400
          int offset = linkIter.getStartOffset();
401
          // TODO: I fetch the element for the link via getCharacterElement().
402
          // I am not sure that this is correct, maybe we must use
403
          // getParagraphElement()?
404
          Element el = doc.getCharacterElement(offset);
405
          HTMLLink link = new HTMLLink(el);
406
          return link;
407
        }
408
      else
409
        return null;
410
    }
411
 
412
    /**
413
     * Returns the index of the link element at the character position
414
     * <code>c</code> within the document, or <code>-1</code> if there is no
415
     * link at the specified position.
416
     *
417
     * @param c the character index from which to fetch the link index
418
     *
419
     * @return the index of the link element at the character position
420
     *         <code>c</code> within the document, or <code>-1</code> if there
421
     *         is no link at the specified position
422
     */
423
    public int getLinkIndex(int c)
424
    {
425
      HTMLDocument doc = (HTMLDocument) getDocument();
426
      HTMLDocument.Iterator linkIter = doc.getIterator(HTML.Tag.A);
427
      int count = 0;
428
      while (linkIter.isValid())
429
        {
430
          if (linkIter.getStartOffset() <= c && linkIter.getEndOffset() > c)
431
            break;
432
          count++;
433
          linkIter.next();
434
        }
435
      if (linkIter.isValid())
436
        return count;
437
      else
438
        return -1;
439
    }
440
 
441
    /**
442
     * Returns the link text of the link at index <code>i</code>, or
443
     * <code>null</code>, if there is no link at the specified position.
444
     *
445
     * @param i the index of the link
446
     *
447
     * @return  the link text of the link at index <code>i</code>, or
448
     *          <code>null</code>, if there is no link at the specified
449
     *          position
450
     */
451
    public String getLinkText(int i)
452
    {
453
      HTMLDocument doc = (HTMLDocument) getDocument();
454
      HTMLDocument.Iterator linkIter = doc.getIterator(HTML.Tag.A);
455
      int count = 0;
456
      while (linkIter.isValid())
457
        {
458
          count++;
459
          if (count == i)
460
            break;
461
          linkIter.next();
462
        }
463
      if (linkIter.isValid())
464
        {
465
          int offset = linkIter.getStartOffset();
466
          // TODO: I fetch the element for the link via getCharacterElement().
467
          // I am not sure that this is correct, maybe we must use
468
          // getParagraphElement()?
469
          Element el = doc.getCharacterElement(offset);
470
          try
471
            {
472
              String text = doc.getText(el.getStartOffset(),
473
                                      el.getEndOffset() - el.getStartOffset());
474
              return text;
475
            }
476
          catch (BadLocationException ex)
477
            {
478
              throw (AssertionError)
479
                new AssertionError("BadLocationException must not be thrown "
480
                                   + "here.")
481
                  .initCause(ex);
482
            }
483
        }
484
      else
485
        return null;
486
    }
487
  }
488
 
489
  /**
490
   * Used to store a mapping for content-type to editor kit class.
491
   */
492
  private static class EditorKitMapping
493
  {
494
    /**
495
     * The classname of the editor kit.
496
     */
497
    String className;
498
 
499
    /**
500
     * The classloader with which the kit is to be loaded.
501
     */
502
    ClassLoader classLoader;
503
 
504
    /**
505
     * Creates a new EditorKitMapping object.
506
     *
507
     * @param cn the classname
508
     * @param cl the classloader
509
     */
510
    EditorKitMapping(String cn, ClassLoader cl)
511
    {
512
      className = cn;
513
      classLoader = cl;
514
    }
515
  }
516
 
517
  /**
518
   * An EditorKit used for plain text. This is the default editor kit for
519
   * JEditorPanes.
520
   *
521
   * @author Roman Kennke (kennke@aicas.com)
522
   */
523
  private static class PlainEditorKit extends DefaultEditorKit
524
  {
525
 
526
    /**
527
     * Returns a ViewFactory that supplies WrappedPlainViews.
528
     */
529
    public ViewFactory getViewFactory()
530
    {
531
      return new ViewFactory()
532
      {
533
        public View create(Element el)
534
        {
535
          return new WrappedPlainView(el);
536
        }
537
      };
538
    }
539
  }
540
 
541
  /**
542
   * A special stream that can be cancelled.
543
   */
544
  private class PageStream
545
    extends FilterInputStream
546
  {
547
    /**
548
     * True when the stream has been cancelled, false otherwise.
549
     */
550
    private boolean cancelled;
551
 
552
    protected PageStream(InputStream in)
553
    {
554
      super(in);
555
      cancelled = false;
556
    }
557
 
558
    private void checkCancelled()
559
      throws IOException
560
    {
561
      if (cancelled)
562
        throw new IOException("Stream has been cancelled");
563
    }
564
 
565
    void cancel()
566
    {
567
      cancelled = true;
568
    }
569
 
570
    public int read()
571
      throws IOException
572
    {
573
      checkCancelled();
574
      return super.read();
575
    }
576
 
577
    public int read(byte[] b, int off, int len)
578
      throws IOException
579
    {
580
      checkCancelled();
581
      return super.read(b, off, len);
582
    }
583
 
584
    public long skip(long n)
585
      throws IOException
586
    {
587
      checkCancelled();
588
      return super.skip(n);
589
    }
590
 
591
    public int available()
592
      throws IOException
593
    {
594
      checkCancelled();
595
      return super.available();
596
    }
597
 
598
    public void reset()
599
      throws IOException
600
    {
601
      checkCancelled();
602
      super.reset();
603
    }
604
  }
605
 
606
  /**
607
   * The thread that loads documents asynchronously.
608
   */
609
  private class PageLoader
610
    implements Runnable
611
  {
612
    private Document doc;
613
    private PageStream in;
614
    private URL old;
615
    URL page;
616
    PageLoader(Document doc, InputStream in, URL old, URL page)
617
    {
618
      this.doc = doc;
619
      this.in = new PageStream(in);
620
      this.old = old;
621
      this.page = page;
622
    }
623
 
624
    public void run()
625
    {
626
      try
627
        {
628
          read(in, doc);
629
        }
630
      catch (IOException ex)
631
        {
632
          UIManager.getLookAndFeel().provideErrorFeedback(JEditorPane.this);
633
        }
634
      finally
635
        {
636
          if (SwingUtilities.isEventDispatchThread())
637
            firePropertyChange("page", old, page);
638
          else
639
            {
640
              SwingUtilities.invokeLater(new Runnable()
641
              {
642
                public void run()
643
                {
644
                  firePropertyChange("page", old, page);
645
                }
646
              });
647
            }
648
         }
649
     }
650
 
651
     void cancel()
652
     {
653
       in.cancel();
654
     }
655
  }
656
 
657
  private static final long serialVersionUID = 3140472492599046285L;
658
 
659
  private EditorKit editorKit;
660
 
661
  boolean focus_root;
662
 
663
  /**
664
   * Maps content-types to editor kit instances.
665
   */
666
  static HashMap editorKits;
667
 
668
  // A mapping between content types and registered EditorKit types
669
  static HashMap registerMap;
670
 
671
  static
672
  {
673
    registerMap = new HashMap();
674
    editorKits = new HashMap();
675
    registerEditorKitForContentType("application/rtf",
676
                                    "javax.swing.text.rtf.RTFEditorKit");
677
    registerEditorKitForContentType("text/plain",
678
                                    "javax.swing.JEditorPane$PlainEditorKit");
679
    registerEditorKitForContentType("text/html",
680
                                    "javax.swing.text.html.HTMLEditorKit");
681
    registerEditorKitForContentType("text/rtf",
682
                                    "javax.swing.text.rtf.RTFEditorKit");
683
 
684
  }
685
 
686
  // A mapping between content types and used EditorKits
687
  HashMap editorMap;
688
 
689
  /**
690
   * The currently loading stream, if any.
691
   */
692
  private PageLoader loader;
693
 
694
  public JEditorPane()
695
  {
696
    init();
697
    setEditorKit(createDefaultEditorKit());
698
  }
699
 
700
  public JEditorPane(String url) throws IOException
701
  {
702
    this(new URL(url));
703
  }
704
 
705
  public JEditorPane(String type, String text)
706
  {
707
    init();
708
    setEditorKit(createEditorKitForContentType(type));
709
    setText(text);
710
  }
711
 
712
  public JEditorPane(URL url) throws IOException
713
  {
714
    init();
715
    setEditorKit(createEditorKitForContentType("text/html"));
716
    setPage(url);
717
  }
718
 
719
  /**
720
   * Called by the constructors to set up the default bindings for content
721
   * types and EditorKits.
722
   */
723
  void init()
724
  {
725
    editorMap = new HashMap();
726
  }
727
 
728
  protected EditorKit createDefaultEditorKit()
729
  {
730
    return new PlainEditorKit();
731
  }
732
 
733
  /**
734
   * Creates and returns an EditorKit that is appropriate for the given
735
   * content type.  This is created using the default recognized types
736
   * plus any EditorKit types that have been registered.
737
   *
738
   * @see #registerEditorKitForContentType(String, String)
739
   * @see #registerEditorKitForContentType(String, String, ClassLoader)
740
   * @param type the content type
741
   * @return an EditorKit for use with the given content type
742
   */
743
  public static EditorKit createEditorKitForContentType(String type)
744
  {
745
    // Try cached instance.
746
    EditorKit e = (EditorKit) editorKits.get(type);
747
    if (e == null)
748
      {
749
        EditorKitMapping m = (EditorKitMapping) registerMap.get(type);
750
        if (m != null)
751
          {
752
            String className = m.className;
753
            ClassLoader loader = m.classLoader;
754
            try
755
              {
756
                e = (EditorKit) loader.loadClass(className).newInstance();
757
              }
758
            catch (Exception e2)
759
              {
760
                // The reference implementation returns null when class is not
761
                // loadable or instantiatable.
762
              }
763
          }
764
        // Cache this for later retrieval.
765
        if (e != null)
766
          editorKits.put(type, e);
767
      }
768
    return e;
769
  }
770
 
771
  /**
772
   * Sends a given <code>HyperlinkEvent</code> to all registered listeners.
773
   *
774
   * @param event the event to send
775
   */
776
  public void fireHyperlinkUpdate(HyperlinkEvent event)
777
  {
778
    HyperlinkListener[] listeners = getHyperlinkListeners();
779
 
780
    for (int index = 0; index < listeners.length; ++index)
781
       listeners[index].hyperlinkUpdate(event);
782
  }
783
 
784
  /**
785
   * Returns the accessible context associated with this editor pane.
786
   *
787
   * @return the accessible context associated with this editor pane
788
   */
789
  public AccessibleContext getAccessibleContext()
790
  {
791
    if (accessibleContext == null)
792
      {
793
        if (getEditorKit() instanceof HTMLEditorKit)
794
          accessibleContext = new AccessibleJEditorPaneHTML();
795
        else
796
          accessibleContext = new AccessibleJEditorPane();
797
      }
798
    return accessibleContext;
799
  }
800
 
801
  public final String getContentType()
802
  {
803
    return getEditorKit().getContentType();
804
  }
805
 
806
  /**
807
   * Returns the EditorKit. If there is no EditorKit set this method
808
   * calls createDefaultEditorKit() and setEditorKit() first.
809
   */
810
  public EditorKit getEditorKit()
811
  {
812
    if (editorKit == null)
813
      setEditorKit(createDefaultEditorKit());
814
    return editorKit;
815
  }
816
 
817
  /**
818
   * Returns the class name of the EditorKit associated with the given
819
   * content type.
820
   *
821
   * @since 1.3
822
   * @param type the content type
823
   * @return the class name of the EditorKit associated with this content type
824
   */
825
  public static String getEditorKitClassNameForContentType(String type)
826
  {
827
    EditorKitMapping m = (EditorKitMapping) registerMap.get(type);
828
    String kitName = m != null ? m.className : null;
829
    return kitName;
830
  }
831
 
832
  /**
833
   * Returns the EditorKit to use for the given content type.  If an
834
   * EditorKit has been explicitly set via
835
   * <code>setEditorKitForContentType</code>
836
   * then it will be returned.  Otherwise an attempt will be made to create
837
   * an EditorKit from the default recognzied content types or any
838
   * EditorKits that have been registered.  If none can be created, a
839
   * PlainEditorKit is created.
840
   *
841
   * @see #registerEditorKitForContentType(String, String)
842
   * @see #registerEditorKitForContentType(String, String, ClassLoader)
843
   * @param type the content type
844
   * @return an appropriate EditorKit for the given content type
845
   */
846
  public EditorKit getEditorKitForContentType(String type)
847
  {
848
    // First check if an EditorKit has been explicitly set.
849
    EditorKit e = (EditorKit) editorMap.get(type);
850
    // Then check to see if we can create one.
851
    if (e == null)
852
      {
853
        e = createEditorKitForContentType(type);
854
        if (e != null)
855
          setEditorKitForContentType(type, e);
856
      }
857
    // Otherwise default to PlainEditorKit.
858
    if (e == null)
859
      e = createDefaultEditorKit();
860
    return e;
861
  }
862
 
863
  /**
864
   * Returns the preferred size for the JEditorPane. This is implemented to
865
   * return the super's preferred size, unless one of
866
   * {@link #getScrollableTracksViewportHeight()} or
867
   * {@link #getScrollableTracksViewportWidth()} returns <code>true</code>,
868
   * in which case the preferred width and/or height is replaced by the UI's
869
   * minimum size.
870
   *
871
   * @return the preferred size for the JEditorPane
872
   */
873
  public Dimension getPreferredSize()
874
  {
875
    Dimension pref = super.getPreferredSize();
876
    Container parent = getParent();
877
    if (parent instanceof JViewport)
878
      {
879
        JViewport vp = (JViewport) getParent();
880
        TextUI ui = getUI();
881
        Dimension min = null;
882
        if (! getScrollableTracksViewportWidth())
883
          {
884
            min = ui.getMinimumSize(this);
885
            int vpWidth = vp.getWidth();
886
            if (vpWidth != 0 && vpWidth < min.width)
887
              pref.width = min.width;
888
          }
889
        if (! getScrollableTracksViewportHeight())
890
          {
891
            if (min == null)
892
              min = ui.getMinimumSize(this);
893
            int vpHeight = vp.getHeight();
894
            if (vpHeight != 0 && vpHeight < min.height)
895
              pref.height = min.height;
896
          }
897
      }
898
    return pref;
899
  }
900
 
901
  /**
902
   * Returns <code>true</code> when a Viewport should force the height of
903
   * this component to match the viewport height. This is implemented to return
904
   * <code>true</code> when  the parent is an instance of JViewport and
905
   * the viewport height > the UI's minimum height.
906
   *
907
   * @return <code>true</code> when a Viewport should force the height of
908
   *         this component to match the viewport height
909
   */
910
  public boolean getScrollableTracksViewportHeight()
911
  {
912
    // Tests show that this returns true when the parent is a JViewport
913
    // and has a height > minimum UI height.
914
    Container parent = getParent();
915
    int height = parent.getHeight();
916
    TextUI ui = getUI();
917
    return parent instanceof JViewport
918
           && height >= ui.getMinimumSize(this).height
919
           && height <= ui.getMaximumSize(this).height;
920
  }
921
 
922
  /**
923
   * Returns <code>true</code> when a Viewport should force the width of
924
   * this component to match the viewport width. This is implemented to return
925
   * <code>true</code> when  the parent is an instance of JViewport and
926
   * the viewport width > the UI's minimum width.
927
   *
928
   * @return <code>true</code> when a Viewport should force the width of
929
   *         this component to match the viewport width
930
   */
931
  public boolean getScrollableTracksViewportWidth()
932
  {
933
    // Tests show that this returns true when the parent is a JViewport
934
    // and has a width > minimum UI width.
935
    Container parent = getParent();
936
    return parent != null && parent instanceof JViewport
937
           && parent.getWidth() > getUI().getMinimumSize(this).width;
938
  }
939
 
940
  public URL getPage()
941
  {
942
    return loader != null ? loader.page : null;
943
  }
944
 
945
  protected InputStream getStream(URL page)
946
    throws IOException
947
  {
948
    URLConnection conn = page.openConnection();
949
    // Try to detect the content type of the stream data.
950
    String type = conn.getContentType();
951
    if (type != null)
952
      setContentType(type);
953
    InputStream stream = conn.getInputStream();
954
    return new BufferedInputStream(stream);
955
  }
956
 
957
  public String getText()
958
  {
959
    return super.getText();
960
  }
961
 
962
  public String getUIClassID()
963
  {
964
    return "EditorPaneUI";
965
  }
966
 
967
  public boolean isFocusCycleRoot()
968
  {
969
    return focus_root;
970
  }
971
 
972
  protected String paramString()
973
  {
974
    return "JEditorPane";
975
  }
976
 
977
  /**
978
   * This method initializes from a stream.
979
   */
980
  public void read(InputStream in, Object desc) throws IOException
981
  {
982
    EditorKit kit = getEditorKit();
983
    if (kit instanceof HTMLEditorKit && desc instanceof HTMLDocument)
984
      {
985
        HTMLDocument doc = (HTMLDocument) desc;
986
        setDocument(doc);
987
        try
988
          {
989
            InputStreamReader reader = new InputStreamReader(in);
990
            kit.read(reader, doc, 0);
991
          }
992
        catch (BadLocationException ex)
993
          {
994
            assert false : "BadLocationException must not be thrown here.";
995
          }
996
      }
997
    else
998
      {
999
        Reader inRead = new InputStreamReader(in);
1000
        super.read(inRead, desc);
1001
      }
1002
  }
1003
 
1004
  /**
1005
   * Establishes a binding between type and classname.  This enables
1006
   * us to create an EditorKit later for the given content type.
1007
   *
1008
   * @param type the content type
1009
   * @param classname the name of the class that is associated with this
1010
   * content type
1011
   */
1012
  public static void registerEditorKitForContentType(String type,
1013
                                                     String classname)
1014
  {
1015
    registerEditorKitForContentType(type, classname,
1016
                               Thread.currentThread().getContextClassLoader());
1017
  }
1018
 
1019
  /**
1020
   * Establishes the default bindings of type to classname.
1021
   */
1022
  public static void registerEditorKitForContentType(String type,
1023
                                                     String classname,
1024
                                                     ClassLoader loader)
1025
  {
1026
    registerMap.put(type, new EditorKitMapping(classname, loader));
1027
  }
1028
 
1029
  /**
1030
   * Replaces the currently selected content with new content represented
1031
   * by the given string.
1032
   */
1033
  public void replaceSelection(String content)
1034
  {
1035
    // TODO: Implement this properly.
1036
    super.replaceSelection(content);
1037
  }
1038
 
1039
  /**
1040
   * Scrolls the view to the given reference location (that is, the value
1041
   * returned by the UL.getRef method for the URL being displayed).
1042
   */
1043
  public void scrollToReference(String reference)
1044
  {
1045
    // TODO: Implement this properly.
1046
  }
1047
 
1048
  public final void setContentType(String type)
1049
  {
1050
    // Strip off content type parameters.
1051
    int paramIndex = type.indexOf(';');
1052
    if (paramIndex > -1)
1053
      {
1054
        // TODO: Handle character encoding.
1055
        type = type.substring(0, paramIndex).trim();
1056
      }
1057
    if (editorKit != null
1058
        && editorKit.getContentType().equals(type))
1059
      return;
1060
 
1061
    EditorKit kit = getEditorKitForContentType(type);
1062
 
1063
    if (kit != null)
1064
      setEditorKit(kit);
1065
  }
1066
 
1067
  public void setEditorKit(EditorKit newValue)
1068
  {
1069
    if (editorKit == newValue)
1070
      return;
1071
 
1072
    if (editorKit != null)
1073
      editorKit.deinstall(this);
1074
 
1075
    EditorKit oldValue = editorKit;
1076
    editorKit = newValue;
1077
 
1078
    if (editorKit != null)
1079
      {
1080
        editorKit.install(this);
1081
        setDocument(editorKit.createDefaultDocument());
1082
      }
1083
 
1084
    firePropertyChange("editorKit", oldValue, newValue);
1085
    invalidate();
1086
    repaint();
1087
    // Reset the accessibleContext since this depends on the editorKit.
1088
    accessibleContext = null;
1089
  }
1090
 
1091
  /**
1092
   * Explicitly sets an EditorKit to be used for the given content type.
1093
   * @param type the content type
1094
   * @param k the EditorKit to use for the given content type
1095
   */
1096
  public void setEditorKitForContentType(String type, EditorKit k)
1097
  {
1098
    editorMap.put(type, k);
1099
  }
1100
 
1101
  /**
1102
   * Sets the current URL being displayed.
1103
   */
1104
  public void setPage(String url) throws IOException
1105
  {
1106
    setPage(new URL(url));
1107
  }
1108
 
1109
  /**
1110
   * Sets the current URL being displayed.
1111
   */
1112
  public void setPage(URL page) throws IOException
1113
  {
1114
    if (page == null)
1115
      throw new IOException("invalid url");
1116
 
1117
    URL old = getPage();
1118
    // Only reload if the URL doesn't point to the same file.
1119
    // This is not the same as equals because there might be different
1120
    // URLs on the same file with different anchors.
1121
    if (old == null || ! old.sameFile(page))
1122
      {
1123
        InputStream in = getStream(page);
1124
        if (editorKit != null)
1125
          {
1126
            Document doc = editorKit.createDefaultDocument();
1127
            doc.putProperty(Document.StreamDescriptionProperty, page);
1128
 
1129
            if (loader != null)
1130
              loader.cancel();
1131
            loader = new PageLoader(doc, in, old, page);
1132
 
1133
            int prio = -1;
1134
            if (doc instanceof AbstractDocument)
1135
              {
1136
                AbstractDocument aDoc = (AbstractDocument) doc;
1137
                prio = aDoc.getAsynchronousLoadPriority();
1138
              }
1139
            if (prio >= 0)
1140
              {
1141
                // Load asynchronously.
1142
                setDocument(doc);
1143
                Thread loadThread = new Thread(loader,
1144
                                               "JEditorPane.PageLoader");
1145
                loadThread.setDaemon(true);
1146
                loadThread.setPriority(prio);
1147
                loadThread.start();
1148
              }
1149
            else
1150
              {
1151
                // Load synchronously.
1152
                loader.run();
1153
                setDocument(doc);
1154
              }
1155
          }
1156
      }
1157
  }
1158
 
1159
  /**
1160
   * Sets the text of the JEditorPane.  The argument <code>t</code>
1161
   * is expected to be in the format of the current EditorKit.  This removes
1162
   * the content of the current document and uses the EditorKit to read in the
1163
   * new text.  This allows the EditorKit to handle the String rather than just
1164
   * inserting in plain text.
1165
   *
1166
   * @param t the text to display in this JEditorPane
1167
   */
1168
  public void setText(String t)
1169
  {
1170
    try
1171
    {
1172
      // Remove the current content.
1173
      Document doc = getDocument();
1174
      doc.remove(0, doc.getLength());
1175
      if (t == null || t.equals(""))
1176
        return;
1177
 
1178
      // Let the EditorKit read the text into the Document.
1179
      getEditorKit().read(new StringReader(t), doc, 0);
1180
    }
1181
    catch (BadLocationException ble)
1182
    {
1183
      // TODO: Don't know what to do here.
1184
    }
1185
    catch (IOException ioe)
1186
    {
1187
      // TODO: Don't know what to do here.
1188
    }
1189
  }
1190
 
1191
  /**
1192
   * Add a <code>HyperlinkListener</code> object to this editor pane.
1193
   *
1194
   * @param listener the listener to add
1195
   */
1196
  public void addHyperlinkListener(HyperlinkListener listener)
1197
  {
1198
    listenerList.add(HyperlinkListener.class, listener);
1199
  }
1200
 
1201
  /**
1202
   * Removes a <code>HyperlinkListener</code> object to this editor pane.
1203
   *
1204
   * @param listener the listener to remove
1205
   */
1206
  public void removeHyperlinkListener(HyperlinkListener listener)
1207
  {
1208
    listenerList.remove(HyperlinkListener.class, listener);
1209
  }
1210
 
1211
  /**
1212
   * Returns all added <code>HyperlinkListener</code> objects.
1213
   *
1214
   * @return array of listeners
1215
   *
1216
   * @since 1.4
1217
   */
1218
  public HyperlinkListener[] getHyperlinkListeners()
1219
  {
1220
    return (HyperlinkListener[]) getListeners(HyperlinkListener.class);
1221
  }
1222
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.