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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 772 jeremybenn
/* JViewport.java --
2
   Copyright (C) 2002, 2004, 2005  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 gnu.classpath.SystemProperties;
42
 
43
import java.awt.Component;
44
import java.awt.Dimension;
45
import java.awt.Graphics;
46
import java.awt.Image;
47
import java.awt.Insets;
48
import java.awt.LayoutManager;
49
import java.awt.Point;
50
import java.awt.Rectangle;
51
import java.awt.Shape;
52
import java.awt.event.ComponentAdapter;
53
import java.awt.event.ComponentEvent;
54
import java.io.Serializable;
55
 
56
import javax.accessibility.Accessible;
57
import javax.accessibility.AccessibleContext;
58
import javax.accessibility.AccessibleRole;
59
import javax.swing.border.Border;
60
import javax.swing.event.ChangeEvent;
61
import javax.swing.event.ChangeListener;
62
import javax.swing.plaf.ViewportUI;
63
 
64
/**
65
 *
66
 * <pre>
67
 *                                                     _
68
 *   +-------------------------------+    ...........Y1 \
69
 *   |  view                         |                .  \
70
 *   |  (this component's child)     |                .   > VY
71
 *   |                               |                .  / = Y2-Y1
72
 *   |         +------------------------------+  ....Y2_/
73
 *   |         | viewport            |        |       .
74
 *   |         | (this component)    |        |       .
75
 *   |         |                     |        |       .
76
 *   |         |                     |        |       .
77
 *   |         |                     |        |       .
78
 *   |         |                     |        |       .
79
 *   |         +------------------------------+  ....Y3
80
 *   |                               |                .
81
 *   |         .                     |        .       .
82
 *   |         .                     |        .       .
83
 *   +---------.---------------------+    ...........Y4
84
 *   .         .                     .        .
85
 *   .         .                     .        .
86
 *   .         .                     .        .
87
 *   X1.......X2.....................X3.......X4
88
 *   \____  ___/
89
 *        \/
90
 *        VX = X2-X1
91
 *</pre>
92
 *
93
 * <p>A viewport is, like all swing components, located at some position in
94
 * the swing component tree; that location is exactly the same as any other
95
 * components: the viewport's "bounds".</p>
96
 *
97
 * <p>But in terms of drawing its child, the viewport thinks of itself as
98
 * covering a particular position <em>of the view's coordinate space</em>.
99
 * For example, the {@link #getViewPosition} method returns
100
 * the position <code>(VX,VY)</code> shown above, which is an position in
101
 * "view space", even though this is <em>implemented</em> by positioning
102
 * the underlying child at position <code>(-VX,-VY)</code></p>
103
 *
104
 */
105
public class JViewport extends JComponent implements Accessible
106
{
107
  /**
108
   * Provides accessibility support for <code>JViewport</code>.
109
   *
110
   * @author Roman Kennke (roman@kennke.org)
111
   */
112
  protected class AccessibleJViewport extends AccessibleJComponent
113
  {
114
    /**
115
     * Creates a new instance of <code>AccessibleJViewport</code>.
116
     */
117
    protected AccessibleJViewport()
118
    {
119
      // Nothing to do here.
120
    }
121
 
122
    /**
123
     * Returns the accessible role of <code>JViewport</code>, which is
124
     * {@link AccessibleRole#VIEWPORT}.
125
     *
126
     * @return the accessible role of <code>JViewport</code>
127
     */
128
    public AccessibleRole getAccessibleRole()
129
    {
130
      return AccessibleRole.VIEWPORT;
131
    }
132
  }
133
 
134
  /**
135
   * A {@link java.awt.event.ComponentListener} that listens for
136
   * changes of the view's size. This triggers a revalidate() call on the
137
   * viewport.
138
   */
139
  protected class ViewListener extends ComponentAdapter implements Serializable
140
  {
141
    private static final long serialVersionUID = -2812489404285958070L;
142
 
143
    /**
144
     * Creates a new instance of ViewListener.
145
     */
146
    protected ViewListener()
147
    {
148
      // Nothing to do here.
149
    }
150
 
151
    /**
152
     * Receives notification when a component (in this case: the view
153
     * component) changes it's size. This simply triggers a revalidate() on the
154
     * viewport.
155
     *
156
     * @param ev the ComponentEvent describing the change
157
     */
158
    public void componentResized(ComponentEvent ev)
159
    {
160
      // Fire state change, because resizing the view means changing the
161
      // extentSize.
162
      fireStateChanged();
163
      revalidate();
164
    }
165
  }
166
 
167
  public static final int SIMPLE_SCROLL_MODE = 0;
168
  public static final int BLIT_SCROLL_MODE = 1;
169
  public static final int BACKINGSTORE_SCROLL_MODE = 2;
170
 
171
  private static final long serialVersionUID = -6925142919680527970L;
172
 
173
  /**
174
   * The default scrollmode to be used by all JViewports as determined by
175
   * the system property gnu.javax.swing.JViewport.scrollMode.
176
   */
177
  private static final int defaultScrollMode;
178
 
179
  protected boolean scrollUnderway;
180
  protected boolean isViewSizeSet;
181
 
182
  /**
183
   * This flag indicates whether we use a backing store for drawing.
184
   *
185
   * @deprecated since JDK 1.3
186
   */
187
  protected boolean backingStore;
188
 
189
  /**
190
   * The backingstore image used for the backingstore and blit scroll methods.
191
   */
192
  protected Image backingStoreImage;
193
 
194
  /**
195
   * The position at which the view has been drawn the last time. This is used
196
   * to determine the bittable area.
197
   */
198
  protected Point lastPaintPosition;
199
 
200
  ChangeEvent changeEvent = new ChangeEvent(this);
201
 
202
  int scrollMode;
203
 
204
  /**
205
   * The ViewListener instance.
206
   */
207
  ViewListener viewListener;
208
 
209
  /**
210
   * Stores the location from where to blit. This is a cached Point object used
211
   * in blitting calculations.
212
   */
213
  Point cachedBlitFrom;
214
 
215
  /**
216
   * Stores the location where to blit to. This is a cached Point object used
217
   * in blitting calculations.
218
   */
219
  Point cachedBlitTo;
220
 
221
  /**
222
   * Stores the width of the blitted area. This is a cached Dimension object
223
   * used in blitting calculations.
224
   */
225
  Dimension cachedBlitSize;
226
 
227
  /**
228
   * Stores the bounds of the area that needs to be repainted. This is a cached
229
   * Rectangle object used in blitting calculations.
230
   */
231
  Rectangle cachedBlitPaint;
232
 
233
  boolean damaged = true;
234
 
235
  /**
236
   * A flag indicating if the size of the viewport has changed since the
237
   * last repaint. This is used in double buffered painting to check if we
238
   * need a new double buffer, or can reuse the old one.
239
   */
240
  boolean sizeChanged = true;
241
 
242
  /**
243
   * Indicates if this JViewport is the paint root or not. If it is not, then
244
   * we may not assume that the offscreen buffer still has the right content
245
   * because parent components may have cleared the background already.
246
   */
247
  private boolean isPaintRoot = false;
248
 
249
  /**
250
   * Initializes the default setting for the scrollMode property.
251
   */
252
  static
253
  {
254
    String scrollModeProp =
255
      SystemProperties.getProperty("gnu.swing.scrollmode", "BACKINGSTORE");
256
    if (scrollModeProp.equalsIgnoreCase("simple"))
257
      defaultScrollMode = SIMPLE_SCROLL_MODE;
258
    else if (scrollModeProp.equalsIgnoreCase("backingstore"))
259
      defaultScrollMode = BACKINGSTORE_SCROLL_MODE;
260
    else
261
      defaultScrollMode = BLIT_SCROLL_MODE;
262
  }
263
 
264
  public JViewport()
265
  {
266
    setOpaque(true);
267
    setScrollMode(defaultScrollMode);
268
    updateUI();
269
    setLayout(createLayoutManager());
270
    lastPaintPosition = new Point();
271
    cachedBlitFrom = new Point();
272
    cachedBlitTo = new Point();
273
    cachedBlitSize = new Dimension();
274
    cachedBlitPaint = new Rectangle();
275
  }
276
 
277
  public Dimension getExtentSize()
278
  {
279
    return getSize();
280
  }
281
 
282
  public Dimension toViewCoordinates(Dimension size)
283
  {
284
    return size;
285
  }
286
 
287
  public Point toViewCoordinates(Point p)
288
  {
289
    Point pos = getViewPosition();
290
    return new Point(p.x + pos.x,
291
                     p.y + pos.y);
292
  }
293
 
294
  public void setExtentSize(Dimension newSize)
295
  {
296
    Dimension oldExtent = getExtentSize();
297
    if (! newSize.equals(oldExtent))
298
      {
299
        setSize(newSize);
300
        fireStateChanged();
301
      }
302
  }
303
 
304
  /**
305
   * Returns the viewSize when set, or the preferred size of the set
306
   * Component view.  If no viewSize and no Component view is set an
307
   * empty Dimension is returned.
308
   */
309
  public Dimension getViewSize()
310
  {
311
    Dimension size;
312
    Component view = getView();
313
    if (view != null)
314
      {
315
        if (isViewSizeSet)
316
          size = view.getSize();
317
        else
318
          size = view.getPreferredSize();
319
      }
320
    else
321
      size = new Dimension(0, 0);
322
    return size;
323
  }
324
 
325
 
326
  public void setViewSize(Dimension newSize)
327
  {
328
    Component view = getView();
329
    if (view != null)
330
      {
331
        if (! newSize.equals(view.getSize()))
332
          {
333
            scrollUnderway = false;
334
            view.setSize(newSize);
335
            isViewSizeSet = true;
336
            fireStateChanged();
337
          }
338
      }
339
  }
340
 
341
  /**
342
   * Get the viewport's position in view space. Despite confusing name,
343
   * this really does return the viewport's (0,0) position in view space,
344
   * not the view's position.
345
   */
346
 
347
  public Point getViewPosition()
348
  {
349
    Component view = getView();
350
    if (view == null)
351
      return new Point(0,0);
352
    else
353
      {
354
        Point p = view.getLocation();
355
        p.x = -p.x;
356
        p.y = -p.y;
357
        return p;
358
      }
359
  }
360
 
361
  public void setViewPosition(Point p)
362
  {
363
    Component view = getView();
364
    if (view != null && ! p.equals(getViewPosition()))
365
      {
366
        scrollUnderway = true;
367
        view.setLocation(-p.x, -p.y);
368
        fireStateChanged();
369
      }
370
  }
371
 
372
  public Rectangle getViewRect()
373
  {
374
    return new Rectangle(getViewPosition(), getExtentSize());
375
  }
376
 
377
  /**
378
   * @deprecated 1.4
379
   */
380
  public boolean isBackingStoreEnabled()
381
  {
382
    return scrollMode == BACKINGSTORE_SCROLL_MODE;
383
  }
384
 
385
  /**
386
   * @deprecated 1.4
387
   */
388
  public void setBackingStoreEnabled(boolean b)
389
  {
390
    if (b && scrollMode != BACKINGSTORE_SCROLL_MODE)
391
      {
392
        scrollMode = BACKINGSTORE_SCROLL_MODE;
393
        fireStateChanged();
394
      }
395
  }
396
 
397
  public void setScrollMode(int mode)
398
  {
399
    scrollMode = mode;
400
    fireStateChanged();
401
  }
402
 
403
  public int getScrollMode()
404
  {
405
    return scrollMode;
406
  }
407
 
408
  public Component getView()
409
  {
410
    if (getComponentCount() == 0)
411
      return null;
412
 
413
    return getComponents()[0];
414
  }
415
 
416
  public void setView(Component v)
417
  {
418
    Component currView = getView();
419
    if (viewListener != null && currView != null)
420
      currView.removeComponentListener(viewListener);
421
 
422
    if (v != null)
423
      {
424
        if (viewListener == null)
425
          viewListener = createViewListener();
426
        v.addComponentListener(viewListener);
427
        add(v);
428
        fireStateChanged();
429
      }
430
    revalidate();
431
    repaint();
432
  }
433
 
434
  public void reshape(int x, int y, int w, int h)
435
  {
436
    if (w != getWidth() || h != getHeight())
437
      sizeChanged = true;
438
    super.reshape(x, y, w, h);
439
    if (sizeChanged)
440
      {
441
        damaged = true;
442
        fireStateChanged();
443
      }
444
  }
445
 
446
  public final Insets getInsets()
447
  {
448
    return new Insets(0, 0, 0, 0);
449
  }
450
 
451
  public final Insets getInsets(Insets insets)
452
  {
453
    if (insets == null)
454
      return getInsets();
455
    insets.top = 0;
456
    insets.bottom = 0;
457
    insets.left = 0;
458
    insets.right = 0;
459
    return insets;
460
  }
461
 
462
 
463
  /**
464
   * Overridden to return <code>false</code>, so the JViewport's paint method
465
   * gets called instead of directly calling the children. This is necessary
466
   * in order to get a useful clipping and translation on the children.
467
   *
468
   * @return <code>false</code>
469
   */
470
  public boolean isOptimizedDrawingEnabled()
471
  {
472
    return false;
473
  }
474
 
475
  public void paint(Graphics g)
476
  {
477
    Component view = getView();
478
 
479
    if (view == null)
480
      return;
481
 
482
    Rectangle viewBounds = view.getBounds();
483
    Rectangle portBounds = getBounds();
484
 
485
    if (viewBounds.width == 0
486
        || viewBounds.height == 0
487
        || portBounds.width == 0
488
        || portBounds.height == 0)
489
      return;
490
 
491
    switch (getScrollMode())
492
      {
493
 
494
      case JViewport.BACKINGSTORE_SCROLL_MODE:
495
        paintBackingStore(g);
496
        break;
497
      case JViewport.BLIT_SCROLL_MODE:
498
        paintBlit(g);
499
        break;
500
      case JViewport.SIMPLE_SCROLL_MODE:
501
      default:
502
        paintSimple(g);
503
        break;
504
      }
505
    damaged = false;
506
  }
507
 
508
  public void addChangeListener(ChangeListener listener)
509
  {
510
    listenerList.add(ChangeListener.class, listener);
511
  }
512
 
513
  public void removeChangeListener(ChangeListener listener)
514
  {
515
    listenerList.remove(ChangeListener.class, listener);
516
  }
517
 
518
  public ChangeListener[] getChangeListeners()
519
  {
520
    return (ChangeListener[]) getListeners(ChangeListener.class);
521
  }
522
 
523
  /**
524
   * This method returns the String ID of the UI class of  Separator.
525
   *
526
   * @return The UI class' String ID.
527
   */
528
  public String getUIClassID()
529
  {
530
    return "ViewportUI";
531
  }
532
 
533
  /**
534
   * This method resets the UI used to the Look and Feel defaults..
535
   */
536
  public void updateUI()
537
  {
538
    setUI((ViewportUI) UIManager.getUI(this));
539
  }
540
 
541
  /**
542
   * This method returns the viewport's UI delegate.
543
   *
544
   * @return The viewport's UI delegate.
545
   */
546
  public ViewportUI getUI()
547
  {
548
    return (ViewportUI) ui;
549
  }
550
 
551
  /**
552
   * This method sets the viewport's UI delegate.
553
   *
554
   * @param ui The viewport's UI delegate.
555
   */
556
  public void setUI(ViewportUI ui)
557
  {
558
    super.setUI(ui);
559
  }
560
 
561
  public final void setBorder(Border border)
562
  {
563
    if (border != null)
564
      throw new IllegalArgumentException();
565
  }
566
 
567
  /**
568
   * Scrolls the view so that contentRect becomes visible.
569
   *
570
   * @param contentRect the rectangle to make visible within the view
571
   */
572
  public void scrollRectToVisible(Rectangle contentRect)
573
  {
574
    Component view = getView();
575
    if (view == null)
576
      return;
577
 
578
    Point pos = getViewPosition();
579
    // We get the contentRect in the viewport coordinates. But we want to
580
    // calculate with view coordinates.
581
    int contentX = contentRect.x + pos.x;
582
    int contentY = contentRect.y + pos.y;
583
    Rectangle viewBounds = getView().getBounds();
584
    Rectangle portBounds = getBounds();
585
 
586
    if (isShowing())
587
      getView().validate();
588
 
589
    // If the bottom boundary of contentRect is below the port
590
    // boundaries, scroll up as necessary.
591
    if (contentY + contentRect.height + viewBounds.y > portBounds.height)
592
      pos.y = contentY + contentRect.height - portBounds.height;
593
    // If contentY is above the port boundaries, scroll down to
594
    // contentY.
595
    if (contentY + viewBounds.y < 0)
596
      pos.y = contentY;
597
    // If the right boundary of contentRect is right from the port
598
    // boundaries, scroll left as necessary.
599
    if (contentX + contentRect.width + viewBounds.x > portBounds.width)
600
      pos.x = contentX + contentRect.width - portBounds.width;
601
    // If contentX is left from the port boundaries, scroll right to
602
    // contentRect.x.
603
    if (contentX + viewBounds.x < 0)
604
      pos.x = contentX;
605
    setViewPosition(pos);
606
  }
607
 
608
  /**
609
   * Returns the accessible context for this <code>JViewport</code>. This
610
   * will be an instance of {@link AccessibleJViewport}.
611
   *
612
   * @return the accessible context for this <code>JViewport</code>
613
   */
614
  public AccessibleContext getAccessibleContext()
615
  {
616
    if (accessibleContext == null)
617
      accessibleContext = new AccessibleJViewport();
618
    return accessibleContext;
619
  }
620
 
621
  /**
622
   * Forward repaint to parent to make sure only one paint is performed by the
623
   * RepaintManager.
624
   *
625
   * @param tm number of milliseconds to defer the repaint request
626
   * @param x the X coordinate of the upper left corner of the dirty area
627
   * @param y the Y coordinate of the upper left corner of the dirty area
628
   * @param w the width of the dirty area
629
   * @param h the height of the dirty area
630
   */
631
  public void repaint(long tm, int x, int y, int w, int h)
632
  {
633
    Component parent = getParent();
634
    if (parent != null)
635
      parent.repaint(tm, x + getX(), y + getY(), w, h);
636
    else
637
      super.repaint(tm, x, y, w, h);
638
  }
639
 
640
  protected void addImpl(Component comp, Object constraints, int index)
641
  {
642
    if (getComponentCount() > 0)
643
      remove(getComponents()[0]);
644
 
645
    super.addImpl(comp, constraints, index);
646
  }
647
 
648
  protected void fireStateChanged()
649
  {
650
    ChangeListener[] listeners = getChangeListeners();
651
    for (int i = 0; i < listeners.length; ++i)
652
      listeners[i].stateChanged(changeEvent);
653
  }
654
 
655
  /**
656
   * Creates a {@link ViewListener} that is supposed to listen for
657
   * size changes on the view component.
658
   *
659
   * @return a ViewListener instance
660
   */
661
  protected ViewListener createViewListener()
662
  {
663
    return new ViewListener();
664
  }
665
 
666
  /**
667
   * Creates the LayoutManager that is used for this viewport. Override
668
   * this method if you want to use a custom LayoutManager.
669
   *
670
   * @return a LayoutManager to use for this viewport
671
   */
672
  protected LayoutManager createLayoutManager()
673
  {
674
    return new ViewportLayout();
675
  }
676
 
677
  /**
678
   * Computes the parameters for the blitting scroll method. <code>dx</code>
679
   * and <code>dy</code> specifiy the X and Y offset by which the viewport
680
   * is scrolled. All other arguments are output parameters and are filled by
681
   * this method.
682
   *
683
   * <code>blitFrom</code> holds the position of the blit rectangle in the
684
   * viewport rectangle before scrolling, <code>blitTo</code> where the blitArea
685
   * is copied to.
686
   *
687
   * <code>blitSize</code> holds the size of the blit area and
688
   * <code>blitPaint</code> is the area of the view that needs to be painted.
689
   *
690
   * This method returns <code>true</code> if blitting is possible and
691
   * <code>false</code> if the viewport has to be repainted completetly without
692
   * blitting.
693
   *
694
   * @param dx the horizontal delta
695
   * @param dy the vertical delta
696
   * @param blitFrom the position from where to blit; set by this method
697
   * @param blitTo the position where to blit area is copied to; set by this
698
   *        method
699
   * @param blitSize the size of the blitted area; set by this method
700
   * @param blitPaint the area that needs repainting; set by this method
701
   *
702
   * @return <code>true</code> if blitting is possible,
703
   *         <code>false</code> otherwise
704
   */
705
  protected boolean computeBlit(int dx, int dy, Point blitFrom, Point blitTo,
706
                                Dimension blitSize, Rectangle blitPaint)
707
  {
708
    if ((dx != 0 && dy != 0) || (dy == 0 && dy == 0) || damaged)
709
      // We cannot blit if the viewport is scrolled in both directions at
710
      // once. Also, we do not want to blit if the viewport is not scrolled at
711
      // all, because that probably means the view component repaints itself
712
      // and the buffer needs updating.
713
      return false;
714
 
715
    Rectangle portBounds = SwingUtilities.calculateInnerArea(this, getBounds());
716
 
717
    // Compute the blitFrom and blitTo parameters.
718
    blitFrom.x = portBounds.x;
719
    blitFrom.y = portBounds.y;
720
    blitTo.x = portBounds.x;
721
    blitTo.y = portBounds.y;
722
 
723
    if (dy > 0)
724
      {
725
        blitFrom.y = portBounds.y + dy;
726
      }
727
    else if (dy < 0)
728
      {
729
        blitTo.y = portBounds.y - dy;
730
      }
731
    else if (dx > 0)
732
      {
733
        blitFrom.x = portBounds.x + dx;
734
      }
735
    else if (dx < 0)
736
      {
737
        blitTo.x = portBounds.x - dx;
738
      }
739
 
740
    // Compute size of the blit area.
741
    if (dx != 0)
742
      {
743
        blitSize.width = portBounds.width - Math.abs(dx);
744
        blitSize.height = portBounds.height;
745
      }
746
    else if (dy != 0)
747
      {
748
        blitSize.width = portBounds.width;
749
        blitSize.height = portBounds.height - Math.abs(dy);
750
      }
751
 
752
    // Compute the blitPaint parameter.
753
    blitPaint.setBounds(portBounds);
754
    if (dy > 0)
755
      {
756
        blitPaint.y = portBounds.y + portBounds.height - dy;
757
        blitPaint.height = dy;
758
      }
759
    else if (dy < 0)
760
      {
761
        blitPaint.height = -dy;
762
      }
763
    if (dx > 0)
764
      {
765
        blitPaint.x = portBounds.x + portBounds.width - dx;
766
        blitPaint.width = dx;
767
      }
768
    else if (dx < 0)
769
      {
770
        blitPaint.width = -dx;
771
      }
772
 
773
    return true;
774
  }
775
 
776
  /**
777
   * Paints the viewport in case we have a scrollmode of
778
   * {@link #SIMPLE_SCROLL_MODE}.
779
   *
780
   * This simply paints the view directly on the surface of the viewport.
781
   *
782
   * @param g the graphics context to use
783
   */
784
  void paintSimple(Graphics g)
785
  {
786
    // We need to call this to properly clear the background.
787
    paintComponent(g);
788
 
789
    Point pos = getViewPosition();
790
    Component view = getView();
791
    Shape oldClip = g.getClip();
792
    g.clipRect(0, 0, getWidth(), getHeight());
793
    boolean translated = false;
794
    try
795
      {
796
        g.translate(-pos.x, -pos.y);
797
        translated = true;
798
        view.paint(g);
799
      }
800
    finally
801
      {
802
        if (translated)
803
          g.translate (pos.x, pos.y);
804
        g.setClip(oldClip);
805
      }
806
  }
807
 
808
  /**
809
   * Paints the viewport in case we have a scroll mode of
810
   * {@link #BACKINGSTORE_SCROLL_MODE}.
811
   *
812
   * This method uses a backing store image to paint the view to, which is then
813
   * subsequently painted on the screen. This should make scrolling more
814
   * smooth.
815
   *
816
   * @param g the graphics context to use
817
   */
818
  void paintBackingStore(Graphics g)
819
  {
820
    // If we have no backing store image yet or the size of the component has
821
    // changed, we need to rebuild the backing store.
822
    if (backingStoreImage == null || sizeChanged)
823
      {
824
        backingStoreImage = createImage(getWidth(), getHeight());
825
        sizeChanged = false;
826
        Graphics g2 = backingStoreImage.getGraphics();
827
        paintSimple(g2);
828
        g2.dispose();
829
      }
830
    // Otherwise we can perform the blitting on the backing store image:
831
    // First we move the part that remains visible after scrolling, then
832
    // we only need to paint the bit that becomes newly visible.
833
    else
834
      {
835
        Graphics g2 = backingStoreImage.getGraphics();
836
        Point viewPosition = getViewPosition();
837
        int dx = viewPosition.x - lastPaintPosition.x;
838
        int dy = viewPosition.y - lastPaintPosition.y;
839
        boolean canBlit = computeBlit(dx, dy, cachedBlitFrom, cachedBlitTo,
840
                                      cachedBlitSize, cachedBlitPaint);
841
        if (canBlit && isPaintRoot)
842
          {
843
            // Copy the part that remains visible during scrolling.
844
            if (cachedBlitSize.width > 0 && cachedBlitSize.height > 0)
845
              {
846
                g2.copyArea(cachedBlitFrom.x, cachedBlitFrom.y,
847
                            cachedBlitSize.width, cachedBlitSize.height,
848
                            cachedBlitTo.x - cachedBlitFrom.x,
849
                            cachedBlitTo.y - cachedBlitFrom.y);
850
              }
851
            // Now paint the part that becomes newly visible.
852
            g2.setClip(cachedBlitPaint.x, cachedBlitPaint.y,
853
                       cachedBlitPaint.width, cachedBlitPaint.height);
854
            paintSimple(g2);
855
          }
856
        // If blitting is not possible for some reason, fall back to repainting
857
        // everything.
858
        else
859
          {
860
            // If the image has not been scrolled at all, only the changed
861
            // clip must be updated in the buffer.
862
            if (dx == 0 && dy == 0)
863
              g2.setClip(g.getClip());
864
 
865
            paintSimple(g2);
866
          }
867
        g2.dispose();
868
      }
869
    // Actually draw the backingstore image to the graphics context.
870
    g.drawImage(backingStoreImage, 0, 0, this);
871
    // Update the lastPaintPosition so that we know what is already drawn when
872
    // we paint the next time.
873
    lastPaintPosition.setLocation(getViewPosition());
874
  }
875
 
876
  /**
877
   * Paints the viewport in case we have a scrollmode of
878
   * {@link #BLIT_SCROLL_MODE}.
879
   *
880
   * This paints the viewport using a backingstore and a blitting algorithm.
881
   * Only the newly exposed area of the view is painted from the view painting
882
   * methods, the remainder is copied from the backing store.
883
   *
884
   * @param g the graphics context to use
885
   */
886
  void paintBlit(Graphics g)
887
  {
888
    // First we move the part that remains visible after scrolling, then
889
    // we only need to paint the bit that becomes newly visible.
890
    Point viewPosition = getViewPosition();
891
    int dx = viewPosition.x - lastPaintPosition.x;
892
    int dy = viewPosition.y - lastPaintPosition.y;
893
    boolean canBlit = computeBlit(dx, dy, cachedBlitFrom, cachedBlitTo,
894
                                  cachedBlitSize, cachedBlitPaint);
895
    if (canBlit && isPaintRoot)
896
      {
897
        // Copy the part that remains visible during scrolling.
898
        if (cachedBlitSize.width > 0 && cachedBlitSize.width > 0)
899
          {
900
            g.copyArea(cachedBlitFrom.x, cachedBlitFrom.y,
901
                       cachedBlitSize.width, cachedBlitSize.height,
902
                       cachedBlitTo.x - cachedBlitFrom.x,
903
                       cachedBlitTo.y - cachedBlitFrom.y);
904
          }
905
        // Now paint the part that becomes newly visible.
906
        Shape oldClip = g.getClip();
907
        g.clipRect(cachedBlitPaint.x, cachedBlitPaint.y,
908
                  cachedBlitPaint.width, cachedBlitPaint.height);
909
        try
910
          {
911
            paintSimple(g);
912
          }
913
        finally
914
          {
915
            g.setClip(oldClip);
916
          }
917
      }
918
    // If blitting is not possible for some reason, fall back to repainting
919
    // everything.
920
    else
921
      paintSimple(g);
922
    lastPaintPosition.setLocation(getViewPosition());
923
  }
924
 
925
  /**
926
   * Overridden from JComponent to set the {@link #isPaintRoot} flag.
927
   *
928
   * @param x the rectangle to paint, X coordinate
929
   * @param y the rectangle to paint, Y coordinate
930
   * @param w the rectangle to paint, width
931
   * @param h the rectangle to paint, height
932
   */
933
  void paintImmediately2(int x, int y, int w, int h)
934
  {
935
    isPaintRoot = true;
936
    super.paintImmediately2(x, y, w, h);
937
    isPaintRoot = false;
938
  }
939
 
940
  /**
941
   * Returns true when the JViewport is using a backbuffer, so that we
942
   * can update our backbuffer correctly.
943
   */
944
  boolean isPaintRoot()
945
  {
946
    return scrollMode == BACKINGSTORE_SCROLL_MODE;
947
  }
948
}

powered by: WebSVN 2.1.0

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