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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 772 jeremybenn
package javax.swing.text.html;
2
 
3
import gnu.javax.swing.text.html.ImageViewIconFactory;
4
import gnu.javax.swing.text.html.css.Length;
5
 
6
import java.awt.Graphics;
7
import java.awt.Image;
8
import java.awt.MediaTracker;
9
import java.awt.Rectangle;
10
import java.awt.Shape;
11
import java.awt.Toolkit;
12
import java.awt.image.ImageObserver;
13
import java.net.MalformedURLException;
14
import java.net.URL;
15
 
16
import javax.swing.Icon;
17
import javax.swing.SwingUtilities;
18
import javax.swing.text.AbstractDocument;
19
import javax.swing.text.AttributeSet;
20
import javax.swing.text.BadLocationException;
21
import javax.swing.text.Document;
22
import javax.swing.text.Element;
23
import javax.swing.text.View;
24
import javax.swing.text.Position.Bias;
25
import javax.swing.text.html.HTML.Attribute;
26
 
27
/**
28
 * A view, representing a single image, represented by the HTML IMG tag.
29
 *
30
 * @author Audrius Meskauskas (AudriusA@Bioinformatics.org)
31
 */
32
public class ImageView extends View
33
{
34
  /**
35
   * Tracks image loading state and performs the necessary layout updates.
36
   */
37
  class Observer
38
    implements ImageObserver
39
  {
40
 
41
    public boolean imageUpdate(Image image, int flags, int x, int y, int width, int height)
42
    {
43
      boolean widthChanged = false;
44
      if ((flags & ImageObserver.WIDTH) != 0 && spans[X_AXIS] == null)
45
        widthChanged = true;
46
      boolean heightChanged = false;
47
      if ((flags & ImageObserver.HEIGHT) != 0 && spans[Y_AXIS] == null)
48
        heightChanged = true;
49
      if (widthChanged || heightChanged)
50
        safePreferenceChanged(ImageView.this, widthChanged, heightChanged);
51
      boolean ret = (flags & ALLBITS) != 0;
52
      return ret;
53
    }
54
 
55
  }
56
 
57
  /**
58
   * True if the image loads synchronuosly (on demand). By default, the image
59
   * loads asynchronuosly.
60
   */
61
  boolean loadOnDemand;
62
 
63
  /**
64
   * The image icon, wrapping the image,
65
   */
66
  Image image;
67
 
68
  /**
69
   * The image state.
70
   */
71
  byte imageState = MediaTracker.LOADING;
72
 
73
  /**
74
   * True when the image needs re-loading, false otherwise.
75
   */
76
  private boolean reloadImage;
77
 
78
  /**
79
   * True when the image properties need re-loading, false otherwise.
80
   */
81
  private boolean reloadProperties;
82
 
83
  /**
84
   * True when the width is set as CSS/HTML attribute.
85
   */
86
  private boolean haveWidth;
87
 
88
  /**
89
   * True when the height is set as CSS/HTML attribute.
90
   */
91
  private boolean haveHeight;
92
 
93
  /**
94
   * True when the image is currently loading.
95
   */
96
  private boolean loading;
97
 
98
  /**
99
   * The current width of the image.
100
   */
101
  private int width;
102
 
103
  /**
104
   * The current height of the image.
105
   */
106
  private int height;
107
 
108
  /**
109
   * Our ImageObserver for tracking the loading state.
110
   */
111
  private ImageObserver observer;
112
 
113
  /**
114
   * The CSS width and height.
115
   *
116
   * Package private to avoid synthetic accessor methods.
117
   */
118
  Length[] spans;
119
 
120
  /**
121
   * The cached attributes.
122
   */
123
  private AttributeSet attributes;
124
 
125
  /**
126
   * Creates the image view that represents the given element.
127
   *
128
   * @param element the element, represented by this image view.
129
   */
130
  public ImageView(Element element)
131
  {
132
    super(element);
133
    spans = new Length[2];
134
    observer = new Observer();
135
    reloadProperties = true;
136
    reloadImage = true;
137
    loadOnDemand = false;
138
  }
139
 
140
  /**
141
   * Load or reload the image. This method initiates the image reloading. After
142
   * the image is ready, the repaint event will be scheduled. The current image,
143
   * if it already exists, will be discarded.
144
   */
145
  private void reloadImage()
146
  {
147
    loading = true;
148
    reloadImage = false;
149
    haveWidth = false;
150
    haveHeight = false;
151
    image = null;
152
    width = 0;
153
    height = 0;
154
    try
155
      {
156
        loadImage();
157
        updateSize();
158
      }
159
    finally
160
      {
161
        loading = false;
162
      }
163
  }
164
 
165
  /**
166
   * Get the image alignment. This method works handling standart alignment
167
   * attributes in the HTML IMG tag (align = top bottom middle left right).
168
   * Depending from the parameter, either horizontal or vertical alingment
169
   * information is returned.
170
   *
171
   * @param axis -
172
   *          either X_AXIS or Y_AXIS
173
   */
174
  public float getAlignment(int axis)
175
  {
176
    AttributeSet attrs = getAttributes();
177
    Object al = attrs.getAttribute(Attribute.ALIGN);
178
 
179
    // Default is top left aligned.
180
    if (al == null)
181
      return 0.0f;
182
 
183
    String align = al.toString();
184
 
185
    if (axis == View.X_AXIS)
186
      {
187
        if (align.equals("middle"))
188
          return 0.5f;
189
        else if (align.equals("left"))
190
          return 0.0f;
191
        else if (align.equals("right"))
192
          return 1.0f;
193
        else
194
          return 0.0f;
195
      }
196
    else if (axis == View.Y_AXIS)
197
      {
198
        if (align.equals("middle"))
199
          return 0.5f;
200
        else if (align.equals("top"))
201
          return 0.0f;
202
        else if (align.equals("bottom"))
203
          return 1.0f;
204
        else
205
          return 0.0f;
206
      }
207
    else
208
      throw new IllegalArgumentException("axis " + axis);
209
  }
210
 
211
  /**
212
   * Get the text that should be shown as the image replacement and also as the
213
   * image tool tip text. The method returns the value of the attribute, having
214
   * the name {@link Attribute#ALT}. If there is no such attribute, the image
215
   * name from the url is returned. If the URL is not available, the empty
216
   * string is returned.
217
   */
218
  public String getAltText()
219
  {
220
    Object rt = getAttributes().getAttribute(Attribute.ALT);
221
    if (rt != null)
222
      return rt.toString();
223
    else
224
      {
225
        URL u = getImageURL();
226
        if (u == null)
227
          return "";
228
        else
229
          return u.getFile();
230
      }
231
  }
232
 
233
  /**
234
   * Returns the combination of the document and the style sheet attributes.
235
   */
236
  public AttributeSet getAttributes()
237
  {
238
    if (attributes == null)
239
      attributes = getStyleSheet().getViewAttributes(this);
240
    return attributes;
241
  }
242
 
243
  /**
244
   * Get the image to render. May return null if the image is not yet loaded.
245
   */
246
  public Image getImage()
247
  {
248
    updateState();
249
    return image;
250
  }
251
 
252
  /**
253
   * Get the URL location of the image to render. If this method returns null,
254
   * the "no image" icon is rendered instead. By defaul, url must be present as
255
   * the "src" property of the IMG tag. If it is missing, null is returned and
256
   * the "no image" icon is rendered.
257
   *
258
   * @return the URL location of the image to render.
259
   */
260
  public URL getImageURL()
261
  {
262
    Element el = getElement();
263
    String src = (String) el.getAttributes().getAttribute(Attribute.SRC);
264
    URL url = null;
265
    if (src != null)
266
      {
267
        URL base = ((HTMLDocument) getDocument()).getBase();
268
        try
269
          {
270
            url = new URL(base, src);
271
          }
272
        catch (MalformedURLException ex)
273
          {
274
            // Return null.
275
          }
276
      }
277
    return url;
278
  }
279
 
280
  /**
281
   * Get the icon that should be displayed while the image is loading and hence
282
   * not yet available.
283
   *
284
   * @return an icon, showing a non broken sheet of paper with image.
285
   */
286
  public Icon getLoadingImageIcon()
287
  {
288
    return ImageViewIconFactory.getLoadingImageIcon();
289
  }
290
 
291
  /**
292
   * Get the image loading strategy.
293
   *
294
   * @return false (default) if the image is loaded when the view is
295
   *         constructed, true if the image is only loaded on demand when
296
   *         rendering.
297
   */
298
  public boolean getLoadsSynchronously()
299
  {
300
    return loadOnDemand;
301
  }
302
 
303
  /**
304
   * Get the icon that should be displayed when the image is not available.
305
   *
306
   * @return an icon, showing a broken sheet of paper with image.
307
   */
308
  public Icon getNoImageIcon()
309
  {
310
    return ImageViewIconFactory.getNoImageIcon();
311
  }
312
 
313
  /**
314
   * Get the preferred span of the image along the axis. The image size is first
315
   * requested to the attributes {@link Attribute#WIDTH} and
316
   * {@link Attribute#HEIGHT}. If they are missing, and the image is already
317
   * loaded, the image size is returned. If there are no attributes, and the
318
   * image is not loaded, zero is returned.
319
   *
320
   * @param axis -
321
   *          either X_AXIS or Y_AXIS
322
   * @return either width of height of the image, depending on the axis.
323
   */
324
  public float getPreferredSpan(int axis)
325
  {
326
    Image image = getImage();
327
 
328
    if (axis == View.X_AXIS)
329
      {
330
        if (spans[axis] != null)
331
          return spans[axis].getValue();
332
        else if (image != null)
333
          return image.getWidth(getContainer());
334
        else
335
          return getNoImageIcon().getIconWidth();
336
      }
337
    else if (axis == View.Y_AXIS)
338
      {
339
        if (spans[axis] != null)
340
          return spans[axis].getValue();
341
        else if (image != null)
342
          return image.getHeight(getContainer());
343
        else
344
          return getNoImageIcon().getIconHeight();
345
      }
346
    else
347
      throw new IllegalArgumentException("axis " + axis);
348
  }
349
 
350
  /**
351
   * Get the associated style sheet from the document.
352
   *
353
   * @return the associated style sheet.
354
   */
355
  protected StyleSheet getStyleSheet()
356
  {
357
    HTMLDocument doc = (HTMLDocument) getDocument();
358
    return doc.getStyleSheet();
359
  }
360
 
361
  /**
362
   * Get the tool tip text. This is overridden to return the value of the
363
   * {@link #getAltText()}. The parameters are ignored.
364
   *
365
   * @return that is returned by getAltText().
366
   */
367
  public String getToolTipText(float x, float y, Shape shape)
368
  {
369
    return getAltText();
370
  }
371
 
372
  /**
373
   * Paints the image or one of the two image state icons. The image is resized
374
   * to the shape bounds. If there is no image available, the alternative text
375
   * is displayed besides the image state icon.
376
   *
377
   * @param g
378
   *          the Graphics, used for painting.
379
   * @param bounds
380
   *          the bounds of the region where the image or replacing icon must be
381
   *          painted.
382
   */
383
  public void paint(Graphics g, Shape bounds)
384
  {
385
    updateState();
386
    Rectangle r = bounds instanceof Rectangle ? (Rectangle) bounds
387
                                              : bounds.getBounds();
388
    Image image = getImage();
389
    if (image != null)
390
      {
391
        g.drawImage(image, r.x, r.y, r.width, r.height, observer);
392
      }
393
    else
394
      {
395
        Icon icon = getNoImageIcon();
396
        if (icon != null)
397
          icon.paintIcon(getContainer(), g, r.x, r.y);
398
      }
399
  }
400
 
401
  /**
402
   * Set if the image should be loaded only when needed (synchronuosly). By
403
   * default, the image loads asynchronuosly. If the image is not yet ready, the
404
   * icon, returned by the {@link #getLoadingImageIcon()}, is displayed.
405
   */
406
  public void setLoadsSynchronously(boolean load_on_demand)
407
  {
408
    loadOnDemand = load_on_demand;
409
  }
410
 
411
  /**
412
   * Update all cached properties from the attribute set, returned by the
413
   * {@link #getAttributes}.
414
   */
415
  protected void setPropertiesFromAttributes()
416
  {
417
    AttributeSet atts = getAttributes();
418
    StyleSheet ss = getStyleSheet();
419
    float emBase = ss.getEMBase(atts);
420
    float exBase = ss.getEXBase(atts);
421
    spans[X_AXIS] = (Length) atts.getAttribute(CSS.Attribute.WIDTH);
422
    if (spans[X_AXIS] != null)
423
      {
424
        spans[X_AXIS].setFontBases(emBase, exBase);
425
      }
426
    spans[Y_AXIS] = (Length) atts.getAttribute(CSS.Attribute.HEIGHT);
427
    if (spans[Y_AXIS] != null)
428
      {
429
        spans[Y_AXIS].setFontBases(emBase, exBase);
430
      }
431
  }
432
 
433
  /**
434
   * Maps the picture co-ordinates into the image position in the model. As the
435
   * image is not divideable, this is currently implemented always to return the
436
   * start offset.
437
   */
438
  public int viewToModel(float x, float y, Shape shape, Bias[] bias)
439
  {
440
    return getStartOffset();
441
  }
442
 
443
  /**
444
   * This is currently implemented always to return the area of the image view,
445
   * as the image is not divideable by character positions.
446
   *
447
   * @param pos character position
448
   * @param area of the image view
449
   * @param bias bias
450
   *
451
   * @return the shape, where the given character position should be mapped.
452
   */
453
  public Shape modelToView(int pos, Shape area, Bias bias)
454
      throws BadLocationException
455
  {
456
    return area;
457
  }
458
 
459
  /**
460
   * Starts loading the image asynchronuosly. If the image must be loaded
461
   * synchronuosly instead, the {@link #setLoadsSynchronously} must be
462
   * called before calling this method. The passed parameters are not used.
463
   */
464
  public void setSize(float width, float height)
465
  {
466
    updateState();
467
    // TODO: Implement this when we have an alt view for the alt=... attribute.
468
  }
469
 
470
  /**
471
   * This makes sure that the image and properties have been loaded.
472
   */
473
  private void updateState()
474
  {
475
    if (reloadImage)
476
      reloadImage();
477
    if (reloadProperties)
478
      setPropertiesFromAttributes();
479
  }
480
 
481
  /**
482
   * Actually loads the image.
483
   */
484
  private void loadImage()
485
  {
486
    URL src = getImageURL();
487
    Image newImage = null;
488
    if (src != null)
489
      {
490
        // Call getImage(URL) to allow the toolkit caching of that image URL.
491
        Toolkit tk = Toolkit.getDefaultToolkit();
492
        newImage = tk.getImage(src);
493
        tk.prepareImage(newImage, -1, -1, observer);
494
        if (newImage != null && getLoadsSynchronously())
495
          {
496
            // Load image synchronously.
497
            MediaTracker tracker = new MediaTracker(getContainer());
498
            tracker.addImage(newImage, 0);
499
            try
500
              {
501
                tracker.waitForID(0);
502
              }
503
            catch (InterruptedException ex)
504
              {
505
                Thread.interrupted();
506
              }
507
 
508
          }
509
      }
510
    image = newImage;
511
  }
512
 
513
  /**
514
   * Updates the size parameters of the image.
515
   */
516
  private void updateSize()
517
  {
518
    int newW = 0;
519
    int newH = 0;
520
    Image newIm = getImage();
521
    if (newIm != null)
522
      {
523
        // Fetch width.
524
        Length l = spans[X_AXIS];
525
        if (l != null)
526
          {
527
            newW = (int) l.getValue();
528
            haveWidth = true;
529
          }
530
        else
531
          {
532
            newW = newIm.getWidth(observer);
533
          }
534
        // Fetch height.
535
        l = spans[Y_AXIS];
536
        if (l != null)
537
          {
538
            newH = (int) l.getValue();
539
            haveHeight = true;
540
          }
541
        else
542
          {
543
            newW = newIm.getWidth(observer);
544
          }
545
        // Go and trigger loading.
546
        Toolkit tk = Toolkit.getDefaultToolkit();
547
        if (haveWidth || haveHeight)
548
          tk.prepareImage(newIm, width, height, observer);
549
        else
550
          tk.prepareImage(newIm, -1, -1, observer);
551
      }
552
  }
553
 
554
  /**
555
   * Calls preferenceChanged from the event dispatch thread and within
556
   * a read lock to protect us from threading issues.
557
   *
558
   * @param v the view
559
   * @param width true when the width changed
560
   * @param height true when the height changed
561
   */
562
  void safePreferenceChanged(final View v, final boolean width,
563
                             final boolean height)
564
  {
565
    if (SwingUtilities.isEventDispatchThread())
566
      {
567
        Document doc = getDocument();
568
        if (doc instanceof AbstractDocument)
569
          ((AbstractDocument) doc).readLock();
570
        try
571
          {
572
            preferenceChanged(v, width, height);
573
          }
574
        finally
575
          {
576
            if (doc instanceof AbstractDocument)
577
              ((AbstractDocument) doc).readUnlock();
578
          }
579
      }
580
    else
581
      {
582
        SwingUtilities.invokeLater(new Runnable()
583
        {
584
          public void run()
585
          {
586
            safePreferenceChanged(v, width, height);
587
          }
588
        });
589
      }
590
  }
591
}

powered by: WebSVN 2.1.0

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