1 /**********************************************************************
2 * Copyright (c) 2005, 2014 IBM Corporation, Ericsson
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
9 * IBM - Initial API and implementation
10 * Bernd Hufmann - Updated for TMF
11 **********************************************************************/
13 package org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
;
15 import java
.util
.Timer
;
16 import java
.util
.TimerTask
;
18 import org
.eclipse
.swt
.SWT
;
19 import org
.eclipse
.swt
.events
.ControlListener
;
20 import org
.eclipse
.swt
.events
.FocusEvent
;
21 import org
.eclipse
.swt
.events
.FocusListener
;
22 import org
.eclipse
.swt
.events
.KeyEvent
;
23 import org
.eclipse
.swt
.events
.KeyListener
;
24 import org
.eclipse
.swt
.events
.MouseEvent
;
25 import org
.eclipse
.swt
.events
.MouseListener
;
26 import org
.eclipse
.swt
.events
.MouseMoveListener
;
27 import org
.eclipse
.swt
.events
.MouseTrackListener
;
28 import org
.eclipse
.swt
.events
.PaintEvent
;
29 import org
.eclipse
.swt
.events
.PaintListener
;
30 import org
.eclipse
.swt
.events
.SelectionEvent
;
31 import org
.eclipse
.swt
.events
.SelectionListener
;
32 import org
.eclipse
.swt
.events
.TypedEvent
;
33 import org
.eclipse
.swt
.graphics
.Color
;
34 import org
.eclipse
.swt
.graphics
.Cursor
;
35 import org
.eclipse
.swt
.graphics
.GC
;
36 import org
.eclipse
.swt
.graphics
.ImageData
;
37 import org
.eclipse
.swt
.graphics
.PaletteData
;
38 import org
.eclipse
.swt
.graphics
.Point
;
39 import org
.eclipse
.swt
.graphics
.RGB
;
40 import org
.eclipse
.swt
.graphics
.Rectangle
;
41 import org
.eclipse
.swt
.widgets
.Button
;
42 import org
.eclipse
.swt
.widgets
.Canvas
;
43 import org
.eclipse
.swt
.widgets
.Composite
;
44 import org
.eclipse
.swt
.widgets
.Control
;
45 import org
.eclipse
.swt
.widgets
.Display
;
46 import org
.eclipse
.swt
.widgets
.Layout
;
47 import org
.eclipse
.swt
.widgets
.ScrollBar
;
48 import org
.eclipse
.swt
.widgets
.Scrollable
;
49 import org
.eclipse
.swt
.widgets
.Shell
;
50 import org
.eclipse
.tracecompass
.tmf
.ui
.views
.uml2sd
.util
.Messages
;
53 * ScrollView widget provides a scrolling area with on-demand scroll bars.
54 * Overview scrollable panel can be used (@see setOverviewEnabled()).
56 * @author Eric Miravete
59 public class ScrollView
extends Composite
{
60 // ------------------------------------------------------------------------
62 // ------------------------------------------------------------------------
65 * Scroll bar mode AUTO
67 public static final int AUTO
= 0;
69 * Scroll bar mode ALWAYS_ON
71 public static final int ALWAYS_ON
= 1;
73 * Scroll bar mode ALWAYS_OFF
75 public static final int ALWAYS_OFF
= 2;
77 * Bit mask for visible vertical scroll bar
79 public static final int VBAR
= 0x01;
81 * Bit mask for visible horizontal scroll bar
83 public static final int HBAR
= 0x02;
85 private static final int DEFAULT_H_SCROLL_INCREMENT
= 10;
86 private static final int DEFAULT_V_SCROLL_INCREMENT
= 10;
87 private static final int DEFAULT_AUTO_SCROLL_PERIOD
= 75;
88 private static final int DEFAULT_OVERVIEW_SIZE
= 100;
90 // ------------------------------------------------------------------------
92 // ------------------------------------------------------------------------
95 * Value of the contents height property.
97 private int fContentsHeight
= 0;
99 * Value of the contents width property.
101 private int fContentsWidth
= 0;
103 * Value of the contents x coordinate property
105 private int fContentsX
= 0;
107 * Value of the contents y coordinate property
109 private int fContentsY
= 0;
111 * Scroll bar mode of horizontal scroll bar.
113 private int fHorScrollbarMode
= AUTO
;
115 * Scroll bar mode of vertical scroll bar.
117 private int fVertScrollbarMode
= AUTO
;
119 * Increment for the horizontal scroll bar.
121 private int fHorScrollbarIncrement
= DEFAULT_H_SCROLL_INCREMENT
;
123 * Increment for the vertical scroll bar.
125 private int fVertScrollbarIncrement
= DEFAULT_V_SCROLL_INCREMENT
;
127 * Flag whether auto scroll is enabled or not.
129 private boolean fAutoScrollEnabled
= true;
131 * Value of the auto scroll period.
133 private int fAutoScrollPeriod
= DEFAULT_AUTO_SCROLL_PERIOD
;
135 * The local paint listener reference.
137 private PaintListener fLocalPaintListener
= null;
139 * The local mouse move listener reference.
141 private MouseMoveListener fLocalMouseMoveListener
= null;
143 * The local mouse listener reference.
145 private MouseListener fLocalMouseListener
= null;
147 * The local control listener reference.
149 private ControlListener fLocalControlListener
= null;
151 * The local key listener reference.
153 private KeyListener fLocalKeyListener
= null;
154 // Canvas for vertical/horizontal Scroll Bar only ... because new ScrollBar() does works.
156 * Canvas for horizontal scroll bar.
158 private Canvas fHorScrollBar
;
160 * Canvas for vertical scroll bar.
162 private Canvas fVertScrollBar
;
164 * Canvas for the view control.
166 private Canvas fViewControl
;
168 * Control used in the bottom right corner @see setCornerControl() and @see setOverviewEnabled(true)
170 private Control fCornerControl
;
172 * Size of overview widget.
174 private int fOverviewSize
= DEFAULT_OVERVIEW_SIZE
; // default size for overview
176 * Timer for auto_scroll feature
178 private AutoScroll fAutoScroll
= null;
180 * TimerTask for auto_scroll feature !=null when auto scroll is running
182 private Timer fAutoScrollTimer
= null;
184 * where mouse down appear on contents area (x coordinate)
186 private int fMouseDownX
= -1;
188 * where mouse down appear on contents area (y coordinate)
190 private int fMousDownY
= -1;
192 // ------------------------------------------------------------------------
194 // ------------------------------------------------------------------------
197 * Create a ScrollView, child of composite c. Both scroll bar have the mode AUTO. Auto scroll feature is enabled
198 * using a delay of 250ms. Overview feature is not enabled by default (use setOverviewEnabled()).
200 * @param c The parent composite
201 * @param style The SWT style bits @see SWT
203 public ScrollView(Composite c
, int style
) {
204 this(c
, style
, true);
208 * Create a ScrollView, child of composite c. Both scroll bar have the mode AUTO. Auto scroll feature is enabled
209 * using a delay of 250ms. Overview feature is not enabled by default (use setOverviewEnabled()).
211 * @param c The parent composite.
212 * @param style The SWT style bits @see SWT
213 * @param mouseWheel Flag to force scrollView to handles mouse wheel
215 public ScrollView(Composite c
, int style
, boolean mouseWheel
) {
218 fHorScrollBar
= new Canvas(this, SWT
.H_SCROLL
);
220 // force scroll bar to get mouse wheel, those scrollbar will be hidden
221 fViewControl
= new Canvas(this, style
| SWT
.H_SCROLL
| SWT
.V_SCROLL
);
223 fViewControl
= new Canvas(this, style
);
225 fViewControl
.setBackground(getBackground());
226 // hide scroll bar as their are replaced by fHorScrollBar and fVertScrollBar.
228 fViewControl
.getVerticalBar().setVisible(false);
229 fViewControl
.getHorizontalBar().setVisible(false);
231 fVertScrollBar
= new Canvas(this, SWT
.V_SCROLL
);
233 setLayout(new SVLayout());
235 fLocalPaintListener
= new PaintListener() {
237 public void paintControl(PaintEvent event
) {
238 // use clipping, to reduce cost of paint.
239 Rectangle r
= event
.gc
.getClipping();
240 int cx
= viewToContentsX(r
.x
);
241 int cy
= viewToContentsY(r
.y
);
242 drawContents(event
.gc
, cx
, cy
, r
.width
, r
.height
);
245 fViewControl
.addPaintListener(fLocalPaintListener
);
247 fLocalMouseMoveListener
= new MouseMoveListener() {
249 public void mouseMove(MouseEvent e
) {
250 int ox
= e
.x
, oy
= e
.y
;
251 e
.x
= viewToContentsX(e
.x
);
252 e
.y
= viewToContentsY(e
.y
);
253 contentsMouseMoveEvent(e
);
259 fViewControl
.addMouseMoveListener(fLocalMouseMoveListener
);
261 MouseTrackListener localMouseTrackListener
= new MouseTrackListener() {
263 public void mouseEnter(MouseEvent e
) {
264 int ox
= e
.x
, oy
= e
.y
;
265 e
.x
= viewToContentsX(e
.x
);
266 e
.y
= viewToContentsY(e
.y
);
267 contentsMouseEnter(e
);
273 public void mouseHover(MouseEvent e
) {
274 int ox
= e
.x
, oy
= e
.y
;
275 e
.x
= viewToContentsX(e
.x
);
276 e
.y
= viewToContentsY(e
.y
);
277 contentsMouseHover(e
);
283 public void mouseExit(MouseEvent e
) {
284 int ox
= e
.x
, oy
= e
.y
;
285 e
.x
= viewToContentsX(e
.x
);
286 e
.y
= viewToContentsY(e
.y
);
287 contentsMouseExit(e
);
294 fViewControl
.addMouseTrackListener(localMouseTrackListener
);
296 fLocalMouseListener
= new MouseListener() {
298 public void mouseDoubleClick(MouseEvent e
) {
299 int ox
= e
.x
, oy
= e
.y
;
300 e
.x
= viewToContentsX(e
.x
);
301 e
.y
= viewToContentsY(e
.y
);
302 contentsMouseDoubleClickEvent(e
);
308 public void mouseDown(MouseEvent e
) {
309 int ox
= e
.x
, oy
= e
.y
;
310 e
.x
= viewToContentsX(e
.x
);
312 e
.y
= viewToContentsY(e
.y
);
314 contentsMouseDownEvent(e
);
320 public void mouseUp(MouseEvent e
) {
321 int ox
= e
.x
, oy
= e
.y
;
322 e
.x
= viewToContentsX(e
.x
);
323 e
.y
= viewToContentsY(e
.y
);
324 contentsMouseUpEvent(e
);
327 // here because class extending me can catch mouse Up and want to scroll...
332 fViewControl
.addMouseListener(fLocalMouseListener
);
334 fLocalKeyListener
= new KeyListener() {
336 public void keyPressed(KeyEvent e
) {
341 public void keyReleased(KeyEvent e
) {
346 fViewControl
.addKeyListener(fLocalKeyListener
);
348 getVerticalBar().addSelectionListener(new SelectionListener() {
350 public void widgetSelected(SelectionEvent e
) {
351 setContentsPos(fContentsX
, getVerticalBar().getSelection());
352 // need to change "hidden" vertical bar value ?
353 // force focus on fViewControl so we got future mouse wheel's scroll events
354 if (!fViewControl
.isFocusControl()) {
355 fViewControl
.setFocus();
360 public void widgetDefaultSelected(SelectionEvent e
) {
364 if (fViewControl
.getVerticalBar() != null) {
365 // add fViewControl hidden scrollbar listener to get mouse wheel ...
366 fViewControl
.getVerticalBar().addSelectionListener(new SelectionListener() {
368 public void widgetSelected(SelectionEvent e
) {
369 ScrollBar b
= fViewControl
.getVerticalBar();
370 setContentsPos(fContentsX
, b
.getSelection());
371 // change "real" vertical bar selection too
372 getVerticalBar().setSelection(b
.getSelection());
376 public void widgetDefaultSelected(SelectionEvent e
) {
380 getHorizontalBar().addSelectionListener(new SelectionListener() {
382 public void widgetSelected(SelectionEvent e
) {
383 setContentsPos(getHorizontalBar().getSelection(), fContentsY
);
384 // need to change "real" horizontal bar too ?
385 // force focus on fViewControl so we got future mouse wheel's scroll events
386 if (!fViewControl
.isFocusControl()) {
387 fViewControl
.setFocus();
392 public void widgetDefaultSelected(SelectionEvent e
) {
395 if (fViewControl
.getHorizontalBar() != null) {
396 fViewControl
.getHorizontalBar().addSelectionListener(new SelectionListener() {
398 public void widgetSelected(SelectionEvent e
) {
399 ScrollBar b
= fViewControl
.getHorizontalBar();
400 setContentsPos(b
.getSelection(), fContentsY
);
401 // change "real" vertical bar selection too
402 getHorizontalBar().setSelection(b
.getSelection());
406 public void widgetDefaultSelected(SelectionEvent e
) {
412 // ------------------------------------------------------------------------
414 // ------------------------------------------------------------------------
417 public boolean setFocus() {
418 return fViewControl
.forceFocus();
422 public void setCursor(Cursor cursor
) {
423 fViewControl
.setCursor(cursor
);
427 public void dispose() {
428 if (fAutoScroll
!= null) {
429 fAutoScroll
.cancel();
432 if (fViewControl
!= null) {
433 fViewControl
.dispose();
436 if (fVertScrollBar
!= null) {
437 fVertScrollBar
.dispose();
439 fVertScrollBar
= null;
440 if (fHorScrollBar
!= null) {
441 fHorScrollBar
.dispose();
443 fHorScrollBar
= null;
444 if (fCornerControl
!= null) {
445 Object data
= fCornerControl
.getData();
446 if (data
instanceof Overview
) {
447 ((Overview
) data
).dispose();
449 fCornerControl
.dispose();
450 fCornerControl
= null;
456 public Rectangle
getClientArea() {
457 Rectangle area
= fViewControl
.getClientArea();
458 /* Clamp the size of the returned area to 1x1 minimum */
459 area
.width
= Math
.max(area
.width
, 1);
460 area
.height
= Math
.max(area
.height
, 1);
465 public void setBackground(Color c
) {
466 super.setBackground(c
);
467 fViewControl
.setBackground(c
);
471 public void setToolTipText(String text
) {
472 fViewControl
.setToolTipText(text
);
476 * Draw overview area, @see setOverviewEnabled. By default draw a rectangle corresponding to the visible area of
477 * scroll view. You can redefine this method to draw the contents as drawContents does... ...in an other magnify
480 * @param gc GC to used to draw.
481 * @param r Rectangle corresponding to the client area of overview.
483 protected void drawOverview(GC gc
, Rectangle r
) {
484 int x
= (int) (r
.width
* fContentsX
/ (float) fContentsWidth
);
485 int y
= (int) (r
.height
* fContentsY
/ (float) fContentsHeight
);
486 int vw
= getVisibleWidth();
487 int vh
= getVisibleHeight();
489 if (fContentsWidth
> vw
) {
490 w
= (int) (r
.width
* vw
/ (float) fContentsWidth
);
492 int h
= r
.height
- 1;
493 if (fContentsHeight
> vh
) {
494 h
= (int) (r
.height
* vh
/ (float) fContentsHeight
);
497 gc
.setForeground(getForeground());
498 // too small rectangle ?
499 if (w
< 5 || h
< 5) {
501 gc
.drawLine(x
, 0, x
, r
.height
);
502 gc
.drawLine(0, y
, r
.width
, y
);
504 gc
.drawRectangle(x
, y
, w
, h
);
509 * Remove the local Listener and add the new listener.
511 * @param nlistener the new listener
513 public void replaceControlListener(ControlListener nlistener
) {
514 if (fLocalControlListener
!= null) {
515 removeControlListener(fLocalControlListener
);
516 fLocalControlListener
= null;
518 addControlListener(nlistener
);
522 * Remove the local Listener and add the new listener.
524 * @param nlistener the new listener
526 public void replaceKeyListener(KeyListener nlistener
) {
527 if (fLocalKeyListener
!= null) {
528 removeKeyListener(fLocalKeyListener
);
529 fLocalKeyListener
= null;
531 addKeyListener(nlistener
);
535 * Remove the local Listener and add the new listener.
537 * @param nlistener the new listener
539 public void replaceMouseListener(MouseListener nlistener
) {
540 if (fLocalMouseListener
!= null) {
541 removeMouseListener(fLocalMouseListener
);
542 fLocalMouseListener
= null;
544 fViewControl
.addMouseListener(nlistener
);
548 * Remove the local Listener and add the new listener.
550 * @param nlistener the new listener
552 public void replaceMouseMoveListener(MouseMoveListener nlistener
) {
553 if (fLocalMouseMoveListener
!= null) {
554 removeMouseMoveListener(fLocalMouseMoveListener
);
555 fLocalMouseMoveListener
= null;
557 fViewControl
.addMouseMoveListener(nlistener
);
561 * Remove the local Listener and add the new listener.
563 * @param nlistener the new listener
565 public void replacePaintListener(PaintListener nlistener
) {
566 if (fLocalPaintListener
!= null) {
567 removePaintListener(fLocalPaintListener
);
568 fLocalPaintListener
= null;
570 fViewControl
.addPaintListener(nlistener
);
574 * Access method for the contentsHeight property.
576 * @return the current value of the contentsHeight property
578 public int getContentsHeight() {
579 return fContentsHeight
;
583 * Access method for the contentsWidth property.
585 * @return the current value of the contentsWidth property
587 public int getContentsWidth() {
588 return fContentsWidth
;
592 * Access method for the contentsX property.
594 * @return the current value of the contentsX property
596 public int getContentsX() {
601 * Access method for the contentsY property.
603 * @return the current value of the contentsY property
605 public int getContentsY() {
610 * Determines if the dragAutoScroll property is true.
612 * @return <code>true<code> if the dragAutoScroll property is true
614 public boolean isDragAutoScroll() {
615 return fAutoScrollEnabled
;
619 * Sets the value of the dragAutoScroll property.
621 * @param aDragAutoScroll the new value of the dragAutoScroll property
623 public void setDragAutoScroll(boolean aDragAutoScroll
) {
624 fAutoScrollEnabled
= aDragAutoScroll
;
625 if (!fAutoScrollEnabled
&& (fAutoScroll
!= null)) {
626 fAutoScroll
.cancel();
632 * Change delay (in millisec) used for auto scroll feature.
634 * @param period new period between to auto scroll
636 public void setDragAutoScrollPeriod(int period
) {
637 fAutoScrollPeriod
= Math
.max(0, period
);
641 * Return auto scroll period.
645 public int getDragAutoScrollPeriod() {
646 return fAutoScrollPeriod
;
650 * Access method for the hScrollBarMode property.
652 * @return the current value of the hScrollBarMode property
654 public int getHScrollBarMode() {
655 return fHorScrollbarMode
;
659 * Sets the value of the hScrollBarMode property.
661 * @param aHScrollBarMode the new value of the hScrollBarMode property
663 public void setHScrollBarMode(int aHScrollBarMode
) {
664 fHorScrollbarMode
= aHScrollBarMode
;
668 * Access method for the vScrollBarMode property.
670 * @return the current value of the vScrollBarMode property
672 public int getVScrollBarMode() {
673 return fVertScrollbarMode
;
677 * Sets the value of the vScrollBarMode property.
679 * @param aVScrollBarMode the new value of the vScrollBarMode property
681 public void setVScrollBarMode(int aVScrollBarMode
) {
682 fVertScrollbarMode
= aVScrollBarMode
;
686 * Return horizontal scroll bar increment, default:1
688 * @return The increment
690 public int getHScrollBarIncrement() {
691 return fHorScrollbarIncrement
;
695 * Return vertical scroll bar increment, default:1
697 * @return The increment
699 public int getVScrollBarIncrement() {
700 return fVertScrollbarIncrement
;
704 * Change horizontal scroll bar increment, minimum:1. Page increment is
705 * always set to visible width.
708 * Increment value to set
710 public void setHScrollBarIncrement(int inc
) {
711 fHorScrollbarIncrement
= Math
.max(1, inc
);
715 * Change vertical scroll bar increment, minimum:1. Page increment is always
716 * set to visible height.
719 * Increment value to set
721 public void setVScrollBarIncrement(int inc
) {
722 fVertScrollbarIncrement
= Math
.max(1, inc
);
726 * Enable or disable overview feature. Enabling overview, dispose and replace existing corner control by a button.
727 * Clicking in it open overview, move mouse cursor holding button to move scroll view and release button to hide
728 * overview. Tip: hold control and/or shift key while moving mouse when overview is open made fine scroll.
730 * @param value true to engage overview feature
732 public void setOverviewEnabled(boolean value
) {
733 if (isOverviewEnabled() == value
) {
739 Button b
= new Button(this, SWT
.NONE
);
740 b
.setText("+"); //$NON-NLS-1$
741 Overview ovr
= new Overview();
745 b
.setToolTipText(Messages
.SequenceDiagram_OpenOverviewTooltip
);
747 setCornerControl(cc
);
751 * Change overview size (at ratio 1:1), default is 100
756 public void setOverviewSize(int size
) {
757 fOverviewSize
= Math
.abs(size
);
761 * Returns whether the overview is enabled or not.
763 * @return true is overview feature is enabled
765 public boolean isOverviewEnabled() {
766 if (fCornerControl
instanceof Button
) {
767 Object data
= ((Button
) fCornerControl
).getData();
769 if (data
instanceof Overview
) {
777 * Returns the overview size at ratio 1:1.
779 * @return current overview size at ratio 1:1
781 public int getOverviewSize() {
782 return fOverviewSize
;
786 * Returns control used to display view (might not be this object). Use this control to add/remove listener on the
789 * @return control used to display view (might not be this object).
791 public Control
getViewControl() {
796 * Called when the mouse enter the ScrollView area
801 protected void contentsMouseExit(MouseEvent e
) {
805 * Called when the mouse enter the ScrollView area after and system defined
811 protected void contentsMouseHover(MouseEvent e
) {
815 * Called when the mouse enter the ScrollView area
820 protected void contentsMouseEnter(MouseEvent e
) {
824 * Called when user double on contents area.
829 protected void contentsMouseDoubleClickEvent(MouseEvent e
) {
833 * Called when mouse is on contents area and button is pressed.
838 protected void contentsMouseDownEvent(MouseEvent e
) {
844 * TimerTask for auto scroll feature.
846 protected static class AutoScroll
extends TimerTask
{
854 /** ScrollView object */
855 private ScrollView scrollView
;
861 * ScrollView object to use
867 public AutoScroll(ScrollView sv
, int dx
, int dy
) {
875 final Display display
= Display
.getDefault();
876 if ((display
== null) || display
.isDisposed()) {
879 display
.asyncExec(new Runnable() {
882 if (!scrollView
.isDisposed()) {
883 scrollView
.scrollBy(deltaX
, deltaY
);
891 * Called when mouse is on contents area and mode.
896 protected void contentsMouseMoveEvent(MouseEvent event
) {
897 if ((event
.stateMask
& SWT
.BUTTON_MASK
) != 0) {
898 if (!fAutoScrollEnabled
) {
899 scrollBy(-(event
.x
- fMouseDownX
), -(event
.y
- fMousDownY
));
905 int vRight
= getContentsX() + getVisibleWidth();
906 int vBottom
= getContentsY() + getVisibleHeight();
909 if (event
.x
< getContentsX()) {
910 sx
= (getContentsX() - event
.x
);
911 fMouseDownX
= getContentsX();
912 } else if (event
.x
> vRight
) {
913 sx
= -event
.x
+ vRight
;
914 fMouseDownX
= vRight
;
916 if (event
.y
< getContentsY()) {
917 sy
= (getContentsY() - event
.y
);
918 fMousDownY
= getContentsY();
919 } else if (event
.y
> vBottom
) {
920 sy
= -event
.y
+ vBottom
;
921 fMousDownY
= vBottom
;
924 if (sx
!= 0 || sy
!= 0) {
925 // start auto scroll...
926 if (fAutoScroll
== null) {
927 if (fAutoScrollTimer
== null) {
928 fAutoScrollTimer
= new Timer(true);
930 fAutoScroll
= new AutoScroll(this, sx
, sy
);
931 fAutoScrollTimer
.schedule(fAutoScroll
, 0, fAutoScrollPeriod
);
933 fAutoScroll
.deltaX
= sx
;
934 fAutoScroll
.deltaY
= sy
;
937 if (fAutoScroll
!= null) {
938 fAutoScroll
.cancel();
942 scrollBy(-(event
.x
- fMouseDownX
), -(event
.y
- fMousDownY
));
948 * Called when mouse is on contents area and button is released
953 protected void contentsMouseUpEvent(MouseEvent event
) {
954 // reset auto scroll if it's engaged
955 if (fAutoScroll
!= null) {
956 fAutoScroll
.cancel();
962 * Responsible to draw contents area. At least rectangle clipX must be
963 * redrawn. This rectangle is given in contents coordinates. By default, no
977 protected void drawContents(GC gc
, int clipx
, int clipy
, int clipw
, int cliph
) {
981 * Change the size of the contents area.
983 * @param width new width of the area.
984 * @param height new height of the area.
986 public void resizeContents(int width
, int height
) {
987 int localWidth
= width
;
988 int localHeight
= height
;
990 if (localWidth
< 0) {
993 if (localHeight
< 0) {
997 int oldW
= fContentsWidth
;
998 int oldH
= fContentsHeight
;
1000 if (localWidth
== oldW
&& localHeight
== oldH
) {
1004 fContentsWidth
= localWidth
;
1005 fContentsHeight
= localHeight
;
1007 if (oldW
> localWidth
) {
1013 int visWidth
= getVisibleWidth();
1014 int visHeight
= getVisibleHeight();
1015 if (oldW
< visWidth
) {
1016 if (localWidth
> visWidth
) {
1017 localWidth
= visWidth
;
1019 fViewControl
.redraw(getContentsX() + oldW
, 0, localWidth
- oldW
, visHeight
, true);
1022 if (oldH
> localHeight
) {
1023 int s
= localHeight
;
1028 if (oldH
< visHeight
) {
1029 if (localHeight
> visHeight
) {
1030 localHeight
= visHeight
;
1032 fViewControl
.redraw(0, getContentsY() + oldH
, visWidth
, localHeight
- oldH
, true);
1034 if (updateScrollBarVisiblity()) {
1037 updateScrollBarsValues();
1041 // redefined for internal use ..
1043 public void redraw() {
1045 // ..need to redraw this already:
1046 fViewControl
.redraw();
1050 * @param delataX The delta in X
1051 * @param deltaY the delta in Y
1053 public void scrollBy(int delataX
, int deltaY
) {
1054 setContentsPos(getContentsX() + delataX
, getContentsY() + deltaY
);
1058 * Scroll to ensure point(in contents coordinates) is visible.
1060 * @param px Point's x position
1061 * @param py Point's y position
1063 public void ensureVisible(int px
, int py
) {
1064 int cx
= getContentsX(), cy
= getContentsY();
1065 int right
= getContentsX() + getVisibleWidth();
1066 int bottom
= getContentsY() + getVisibleHeight();
1067 if (px
< getContentsX()) {
1069 } else if (px
> right
) {
1070 cx
= px
- getVisibleWidth();
1072 if (py
< getContentsY()) {
1074 } else if (py
> bottom
) {
1075 cy
= py
- getVisibleHeight();
1077 setContentsPos(cx
, cy
);
1081 * Make rectangle (x,y,w,h, in contents coordinates) visible. if rectangle cannot be completely visible, use
1084 * @param xValue x contents coordinates of rectangle.
1085 * @param yValue y contents coordinates of rectangle.
1086 * @param width width of rectangle.
1087 * @param height height of rectangle.
1088 * @param align bit or'ed SWT flag like SWT.LEFT,RIGHT,CENTER,TOP,BOTTOM,VERTICAL used only for bigger rectangle
1089 * than visible area. By default CENTER/VERTICAL
1091 public void ensureVisible(int xValue
, int yValue
, int width
, int height
, int align
) {
1092 ensureVisible(xValue
, yValue
, width
, height
, align
, false);
1096 * Make rectangle (xValue,yValue,width,height, in contents coordinates) visible. if rectangle cannot be completely visible, use
1099 * @param xValue x contents coordinates of rectangle.
1100 * @param yValue y contents coordinates of rectangle.
1101 * @param width width of rectangle.
1102 * @param height height of rectangle.
1103 * @param align bit or'ed SWT flag like SWT.LEFT,RIGHT,CENTER,TOP,BOTTOM,VERTICAL used only for bigger rectangle
1104 * than visible area. By default CENTER/VERTICAL
1105 * @param forceAlign force alignment for rectangle smaller than the visible area
1107 protected void ensureVisible(int xValue
, int yValue
, int width
, int height
, int align
, boolean forceAlign
) {
1109 int localX
= xValue
;
1110 int localY
= yValue
;
1111 int localWidth
= width
;
1112 int localHeight
= height
;
1114 if (localWidth
< 0) {
1115 localX
= localX
+ localWidth
;
1116 localWidth
= -localWidth
;
1118 if (localHeight
< 0) {
1119 localY
= localY
+ localHeight
;
1120 localHeight
= -localHeight
;
1122 int hbar
= getHorizontalBarHeight();
1123 int vbar
= getVerticalBarWidth();
1124 int cx
= getContentsX();
1125 int cy
= getContentsY();
1126 int right
= getContentsX() + getVisibleWidth() - vbar
;
1127 int bottom
= getContentsY() + getVisibleHeight() - hbar
;
1128 boolean alignH
= false, alignV
= false;
1130 if (localX
< getContentsX()) {
1132 } else if (localX
+ localWidth
> right
) {
1133 cx
= localX
- localWidth
;
1135 if (localY
< getContentsY()) {
1137 } else if (localY
+ localHeight
> bottom
) {
1138 cy
= localY
- localHeight
;
1141 if (localWidth
> getVisibleWidth()) {
1144 if (localHeight
> getVisibleHeight()) {
1147 // compute alignment on visible area horizontally
1148 if (alignH
|| (forceAlign
&& localX
+ localWidth
> right
)) {
1150 if ((align
& SWT
.LEFT
) != 0) {
1152 } else if ((align
& SWT
.RIGHT
) != 0) {
1153 cx
= right
- localWidth
;
1155 cx
= localX
+ (localWidth
- getVisibleWidth()) / 2;
1158 // compute alignment on visible area vertically
1159 if (alignV
|| (forceAlign
&& localY
+ localHeight
> bottom
)) {
1161 if ((align
& SWT
.TOP
) != 0) {
1163 } else if ((align
& SWT
.BOTTOM
) != 0) {
1164 cy
= bottom
- localHeight
;
1166 cy
= localY
+ (localHeight
- getVisibleHeight()) / 2;
1169 setContentsPos(cx
, cy
);
1173 * Returns true if point is visible (expressed in contents coordinates).
1175 * @param px Point's x position
1176 * @param py Point's y position
1177 * @return true if point is visible (expressed in contents coordinates)
1179 public boolean isVisible(int px
, int py
) {
1180 if (px
< getContentsX()) {
1183 if (py
< getContentsY()) {
1186 if (px
> (getContentsX() + getVisibleWidth())) {
1189 if (py
> (getContentsY() + getVisibleHeight())) {
1196 * Returns true if rectangle if partially visible.
1198 * @param xValue x contents coordinates of rectangle.
1199 * @param yValue y contents coordinates of rectangle.
1200 * @param width width of rectangle.
1201 * @param height height of rectangle.
1202 * @return true if rectangle if partially visible.
1204 public boolean isVisible(int xValue
, int yValue
, int width
, int height
) {
1205 if (xValue
+ width
< getContentsX()) {
1208 if (yValue
+ height
< getContentsY()) {
1211 int vr
= getContentsX() + getVisibleWidth();
1212 int vb
= getContentsY() + getVisibleHeight();
1223 * Returns visible part of rectangle, or null if rectangle is not visible.
1224 * Rectangle is expressed in contents coordinates.
1227 * x contents coordinates of rectangle.
1229 * y contents coordinates of rectangle.
1231 * width of rectangle.
1233 * height of rectangle.
1234 * @return visible part of rectangle, or null if rectangle is not visible.
1236 public Rectangle
getVisiblePart(int xValue
, int yValue
, int width
, int height
) {
1237 if (xValue
+ width
< getContentsX()) {
1240 if (yValue
+ height
< getContentsY()) {
1243 int vr
= getContentsX() + getVisibleWidth();
1244 int vb
= getContentsY() + getVisibleHeight();
1251 int rr
= xValue
+ width
, rb
= yValue
+ height
;
1252 int nl
= Math
.max(xValue
, getContentsX()), nt
= Math
.max(yValue
, getContentsY()), nr
= Math
.min(rr
, vr
), nb
= Math
.min(rb
, vb
);
1253 return new Rectangle(nl
, nt
, nr
- nl
, nb
- nt
);
1257 * Returns the visible part for given rectangle.
1259 * @param rect A rectangle
1261 * @return gets visible part of rectangle (or <code>null</code>)
1263 public final Rectangle
getVisiblePart(Rectangle rect
) {
1267 return getVisiblePart(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
1271 * Change top left position of visible area. Check if the given point is inside contents area.
1273 * @param xValue x contents coordinates of visible area.
1274 * @param yValue y contents coordinates of visible area.
1275 * @return true if view really moves
1277 public boolean setContentsPos(int xValue
, int yValue
) {
1278 int nx
= xValue
, ny
= yValue
;
1279 if (getVisibleWidth() >= getContentsWidth()) {
1284 } else if (xValue
+ getVisibleWidth() > getContentsWidth()) {
1285 nx
= getContentsWidth() - getVisibleWidth();
1288 if (getVisibleHeight() >= getContentsHeight()) {
1293 } else if (yValue
+ getVisibleHeight() > getContentsHeight()) {
1294 ny
= getContentsHeight() - getVisibleHeight();
1298 if (nx
== fContentsX
&& ny
== fContentsY
) {
1303 updateScrollBarsValues();
1304 // ? find smallest area to redraw only them ?
1305 fViewControl
.redraw();
1310 public ScrollBar
getVerticalBar() {
1311 return fVertScrollBar
.getVerticalBar();
1315 public ScrollBar
getHorizontalBar() {
1316 return fHorScrollBar
.getHorizontalBar();
1320 * Compute visibility of vertical/horizontal bar using given width/height and current visibility (i.e. is bar size are already in
1322 * @param forWidth width of foreground
1323 * @param forHeight height of foreground
1324 * @param currHorVis The current visibility state of horizontal scroll bar
1325 * @param currVertvis The current visibility state of vertical scroll bar
1326 * @return <code>true</code> if visibility changed else <code>false</code>
1328 public int computeBarVisibility(int forWidth
, int forHeight
, boolean currHorVis
, boolean currVertvis
) {
1330 int localForWidth
= forWidth
;
1332 switch (fVertScrollbarMode
) {
1339 if (getContentsHeight() > forHeight
) {
1341 // v bar size is already in for_width.
1342 if (!currVertvis
) {// (curr_vis&0x01)==0)
1343 localForWidth
-= getVerticalBarWidth();
1351 switch (fHorScrollbarMode
) {
1358 if (getContentsWidth() > localForWidth
) {
1360 // h bar is not in for_height
1361 if ((!currHorVis
) && (getContentsHeight() > (forHeight
- getHorizontalBarHeight()))) {// (curr_vis&0x02)==0 )
1373 * Setup scroll bars visibility.
1375 * @return True if one of visibility changed.
1377 protected boolean updateScrollBarVisiblity() {
1378 boolean change
= false;
1380 boolean currVertVis
= fVertScrollBar
.getVisible();
1381 boolean currHorVis
= fHorScrollBar
.getVisible();
1382 int barNewVis
= computeBarVisibility(getVisibleWidth(), getVisibleHeight(), currHorVis
, currVertVis
);
1383 boolean newVertVis
= (barNewVis
& VBAR
) != 0;
1384 boolean newHorVis
= (barNewVis
& HBAR
) != 0;
1385 if (currVertVis ^ newVertVis
) { // vertsb_.getVisible() )
1386 fVertScrollBar
.setVisible(newVertVis
);
1389 if (currHorVis ^ newHorVis
) {
1390 fHorScrollBar
.setVisible(newHorVis
);
1394 // update corner control visibility:
1395 if (fCornerControl
!= null && change
) {
1396 boolean vis
= newVertVis
|| newHorVis
;
1397 if (vis ^ fCornerControl
.getVisible()) {
1398 fCornerControl
.setVisible(vis
);
1399 change
= true; // but must be already the case
1406 * Setup scroll bar using contents, visible and scroll bar mode properties.
1408 protected void updateScrollBarsValues() {
1409 /* update vertical scrollbar */
1410 ScrollBar b
= getVerticalBar();
1413 b
.setMaximum(getContentsHeight());
1414 b
.setThumb(getVisibleHeight());
1415 b
.setPageIncrement(getVisibleHeight());
1416 b
.setIncrement(fVertScrollbarIncrement
);
1417 b
.setSelection(getContentsY());
1420 // update "hidden" vertical bar too
1421 b
= fViewControl
.getVerticalBar();
1424 b
.setMaximum(getContentsHeight());
1425 b
.setThumb(getVisibleHeight());
1426 b
.setPageIncrement(getVisibleHeight());
1427 b
.setIncrement(fVertScrollbarIncrement
);
1428 b
.setSelection(getContentsY());
1431 /* update horizontal scrollbar */
1432 b
= getHorizontalBar();
1435 b
.setMaximum(getContentsWidth());
1436 b
.setThumb(getVisibleWidth());
1437 b
.setSelection(getContentsX());
1438 b
.setPageIncrement(getVisibleWidth());
1439 b
.setIncrement(fHorScrollbarIncrement
);
1441 // update "hidden" horizontal bar too
1442 b
= fViewControl
.getHorizontalBar();
1445 b
.setMaximum(getContentsWidth());
1446 b
.setThumb(getVisibleWidth());
1447 b
.setSelection(getContentsX());
1448 b
.setPageIncrement(getVisibleWidth());
1449 b
.setIncrement(fHorScrollbarIncrement
);
1454 * Change the control used in the bottom right corner (between two scrollbar), if control is null reset previous
1455 * corner control. This control is visible only if at least one scrollbar is visible. Given control will be disposed
1456 * by ScrollView, at dispose() time, at next setCornetControl() call or when calling setOverviewEnabled(). Pay
1457 * attention calling this reset overview feature until setOverviewEnabled(true) if called.
1458 * @param control The control for the overview
1460 public void setCornerControl(Control control
) {
1461 if (fCornerControl
!= null) {
1462 fCornerControl
.dispose();
1464 fCornerControl
= control
;
1465 if (fCornerControl
!= null) {
1466 ScrollBar vb
= getVerticalBar();
1467 ScrollBar hb
= getHorizontalBar();
1468 boolean vis
= vb
.getVisible() || hb
.getVisible();
1469 fCornerControl
.setVisible(vis
);
1474 * Transform (x,y) point in widget coordinates to contents coordinates.
1476 * @param x The x widget coordinate.
1477 * @param y The y widget coordinate.
1478 * @return org.eclipse.swt.graphics.Point with content coordinates.
1480 public final Point
viewToContents(int x
, int y
) {
1481 return new Point(viewToContentsX(x
), viewToContentsY(y
));
1485 * Transform x in widget coordinates to contents coordinates
1487 * @param x The y widget coordinate.
1488 * @return the x content coordinate.
1490 public int viewToContentsX(int x
) {
1491 return fContentsX
+ x
;
1495 * Transform y in widget coordinates to contents coordinates
1497 * @param y The y widget coordinate.
1498 * @return the y content coordinate.
1500 public int viewToContentsY(int y
) {
1501 return fContentsY
+ y
;
1505 * Transform (x,y) point from contents coordinates, to widget coordinates.
1507 * @param x The x content coordinate.
1508 * @param y The y content coordinate.
1509 * @return coordinates widget area as.
1511 public final Point
contentsToView(int x
, int y
) {
1512 return new Point(contentsToViewX(x
), contentsToViewY(y
));
1516 * Transform X axis coordinates from contents to widgets.
1518 * @param x contents coordinate to transform.
1519 * @return x coordinate in widget area
1521 public int contentsToViewX(int x
) {
1522 return x
- fContentsX
;
1526 * Transform Y axis coordinates from contents to widgets.
1528 * @param y contents coordinate to transform
1529 * @return y coordinate in widget area
1531 public int contentsToViewY(int y
) {
1532 return y
- fContentsY
;
1536 * Return the visible height of scroll view, might be > contentsHeight
1538 * @return the visible height of scroll view, might be > contentsHeight()
1540 public int getVisibleHeight() {
1541 return fViewControl
.getClientArea().height
;
1545 * Return int the visible width of scroll view, might be > contentsWidth().
1547 * @return int the visible width of scroll view, might be > contentsWidth()
1549 public int getVisibleWidth() {
1550 return fViewControl
.getClientArea().width
;
1554 * Add support for arrow key, scroll the ... scroll view. But you can
1555 * redefine this method for your convenience.
1560 protected void keyPressedEvent(KeyEvent event
) {
1561 switch (event
.keyCode
) {
1563 scrollBy(0, -getVisibleHeight());
1565 case SWT
.ARROW_DOWN
:
1566 scrollBy(0, +getVisibleHeight());
1568 case SWT
.ARROW_LEFT
:
1569 scrollBy(-getVisibleWidth(), 0);
1571 case SWT
.ARROW_RIGHT
:
1572 scrollBy(+getVisibleWidth(), 0);
1580 * Redefine this method at your convenience
1582 * @param event The key event.
1584 protected void keyReleasedEvent(KeyEvent event
) {
1588 * Returns vertical bar width, even if bar isn't visible.
1590 * @return vertical bar width, even if bar isn't visible
1592 public int getVerticalBarWidth() {
1593 // include vertical bar width and trimming of scrollable used
1594 int bw
= fVertScrollBar
.computeTrim(0, 0, 0, 0).width
;
1599 * Returns horizontal bar height even if bar isn't visible.
1601 * @return horizontal bar height even if bar isn't visible
1603 public int getHorizontalBarHeight() {
1604 // include horiz. bar height and trimming of scrollable used
1605 int bh
= fHorScrollBar
.computeTrim(0, 0, 0, 0).height
;
1606 // +1 because win32 H.bar need 1 pixel canvas size to appear ! (strange no ?)
1611 public Rectangle
computeTrim(int x
, int y
, int w
, int h
) {
1612 Rectangle r
= new Rectangle(x
, y
, w
, h
);
1613 int barVis
= computeBarVisibility(w
, h
, false, false);
1614 if ((barVis
& VBAR
) != 0) {
1615 r
.width
+= getVerticalBarWidth();
1617 if ((barVis
& HBAR
) != 0) {
1618 r
.height
+= getHorizontalBarHeight();
1624 * Internal layout for ScrollView, handle scrollbars, drawzone and corner control
1626 protected class SVLayout
extends Layout
{
1628 private static final int DEFAULT_X
= 250;
1629 private static final int DEFAULT_Y
= 250;
1630 private static final int MAX_SEEK
= 10;
1631 private static final int MIN_SEEK
= 0;
1636 private int seek
= 0;
1638 * The do-it-not flag
1640 private boolean dontLayout
= false;
1643 protected Point
computeSize(Composite composite
, int wHint
, int hHint
, boolean flushCache
) {
1644 Point p
= new Point(DEFAULT_X
, DEFAULT_Y
);
1645 if (fContentsWidth
< p
.x
) {
1646 p
.x
= fContentsWidth
;
1648 if (fContentsHeight
< p
.y
) {
1649 p
.y
= fContentsHeight
;
1655 protected void layout(Composite composite
, boolean flushCache
) {
1660 if (seek
> MAX_SEEK
) {
1664 Point cs
= composite
.getSize();
1665 int barVis
= computeBarVisibility(cs
.x
, cs
.y
, false, false);
1666 boolean vbVis
= (barVis
& VBAR
) != 0;
1667 boolean hbVis
= (barVis
& HBAR
) != 0;
1668 fVertScrollBar
.setVisible(vbVis
);
1669 fHorScrollBar
.setVisible(hbVis
);
1670 int vbw
= getVerticalBarWidth();
1671 int hbh
= getHorizontalBarHeight();
1672 int wb
= vbVis ? vbw
: 0;
1673 int hb
= hbVis ? hbh
: 0;
1674 int cww
= 0, cwh
= 0;
1676 if (fCornerControl
!= null && (vbVis
|| hbVis
)) { // corner_control_.getVisible())
1677 fCornerControl
.setVisible(true);
1686 } else if (vbVis
&& hbVis
) {
1687 if (fCornerControl
!= null) {
1688 fCornerControl
.setVisible(false);
1693 if (vbVis
|| hbVis
) {
1694 updateScrollBarsValues();
1697 int vw
= cs
.x
- (vbVis ? vbw
: 0);
1698 int vh
= cs
.y
- (hbVis ? hbh
: 0);
1699 int vbx
= cs
.x
- wb
;
1700 int hby
= cs
.y
- hb
;
1702 fViewControl
.setBounds(0, 0, vw
, vh
);
1705 fVertScrollBar
.setBounds(vbx
, 0, wb
, cs
.y
- cwh
);
1708 fHorScrollBar
.setBounds(0, hby
, cs
.x
- cww
, hb
);
1710 if (fCornerControl
!= null && fCornerControl
.getVisible()) {
1711 fCornerControl
.setBounds(vbx
, hby
, vbw
, hbh
);
1713 updateScrollBarsValues();
1716 if (seek
== MIN_SEEK
) {
1721 boolean isDontLayout() {
1725 void setSontLayout(boolean dontLayout
) {
1726 this.dontLayout
= dontLayout
;
1730 // static must take place here... cursor is created once.
1731 private static volatile Cursor fOverviewCursor
;
1733 /** Support for click-and-see overview shell on this ScrollView */
1734 protected class Overview
{
1736 private static final int REFRESH_FREQ
= 4;
1739 * factor for X from real and overview sizes, for mouse move speed.
1741 private float fOverviewFactorX
;
1744 * factor for Y from real and overview sizes, for mouse move speed.
1746 private float fOverviewFactorY
;
1748 * shell use to show overview
1750 private Shell fOverview
;
1752 * save mouse X cursor location for disappear();
1754 private int fSaveCursorX
;
1756 * save mouse Y cursor location for disappear();
1758 private int fSaveCursorY
;
1761 * Apply overview support on a control. Replace existing corner_widget
1764 * The control to use
1766 public void useControl(Control control
) {
1767 final Point pos
= control
.getLocation();
1768 control
.addMouseListener(new MouseListener() {
1770 public void mouseDoubleClick(MouseEvent e
) {
1774 public void mouseDown(MouseEvent e
) {
1775 overviewAppear(e
.x
, e
.y
);
1779 public void mouseUp(MouseEvent e
) {
1780 overviewDisappear();
1784 control
.addFocusListener(new FocusListener() {
1787 public void focusGained(FocusEvent e
) {
1791 public void focusLost(FocusEvent e
) {
1792 if (overviewing()) {
1793 overviewDisappear(false);
1798 control
.addKeyListener(new KeyListener() {
1801 public void keyPressed(KeyEvent event
) {
1802 if (event
.keyCode
== 32 && !overviewing()) {
1803 overviewAppear(pos
.x
, pos
.y
);
1804 } else if (event
.keyCode
== 32) {
1805 overviewDisappear();
1807 if (event
.keyCode
== SWT
.ARROW_DOWN
) {
1808 overviewMove(0, 1, event
);
1811 if (event
.keyCode
== SWT
.ARROW_UP
) {
1812 overviewMove(0, -1, event
);
1815 if (event
.keyCode
== SWT
.ARROW_RIGHT
) {
1816 overviewMove(1, 0, event
);
1819 if (event
.keyCode
== SWT
.ARROW_LEFT
) {
1820 overviewMove(-1, 0, event
);
1825 public void keyReleased(KeyEvent e
) {
1828 control
.addMouseMoveListener(new MouseMoveListener() {
1829 private int refReshCount
= 0;
1831 public void mouseMove(MouseEvent event
) {
1832 if (overviewing()) {
1833 // Slow down the refresh
1834 if (refReshCount
% REFRESH_FREQ
== 0) {
1835 overviewMove(event
);
1844 * Dispose controls of overview
1846 public void dispose() {
1847 if (fOverview
!= null) {
1848 fOverview
.dispose();
1853 * @return true if overview is currently on screen
1855 protected boolean overviewing() {
1856 return (fOverview
!= null && fOverview
.isVisible());
1860 * Process overview appear
1867 protected void overviewAppear(int mx
, int my
) {
1868 if (fOverview
== null) {
1869 fOverview
= new Shell(getShell(), SWT
.ON_TOP
| SWT
.NO_BACKGROUND
);
1870 fOverview
.addPaintListener(new PaintListener() {
1872 public void paintControl(PaintEvent e
) {
1873 drawOverview(e
.gc
, fOverview
.getClientArea());
1877 // always the same..
1878 fOverview
.setForeground(fViewControl
.getForeground());
1880 // get location of shell (in screeen coordinates)
1881 Point p
= toGlobalCoordinates(fCornerControl
, 0, 0);
1887 Rectangle scr
= getDisplay().getBounds();
1888 Point ccs
= fCornerControl
.getSize();
1890 if (fContentsWidth
> fContentsHeight
) {
1891 float ratio
= fContentsHeight
/ (float) fContentsWidth
;
1892 h
= (int) (w
* ratio
);
1895 } else if (h
>= scr
.height
/ 2) {
1899 float ratio
= fContentsWidth
/ (float) fContentsHeight
;
1900 w
= (int) (h
* ratio
);
1903 } else if (w
>= scr
.width
/ 2) {
1907 fOverviewFactorX
= fContentsWidth
/ (float) w
;
1908 fOverviewFactorY
= fContentsHeight
/ (float) h
;
1910 // no contents size set ?
1911 catch (java
.lang
.ArithmeticException e
) {
1914 // try pop-up on button, extending to bottom right,
1923 fOverview
.setBounds(x
, y
, w
, h
);
1924 fOverview
.setVisible(true);
1926 // mouse cursor disappear, so set invisible mouse cursor ...
1927 if (fOverviewCursor
== null) {
1928 RGB rgb
[] = { new RGB(0, 0, 0), new RGB(255, 0, 0) };
1929 PaletteData palette
= new PaletteData(rgb
);
1931 byte src
[] = new byte[s
* s
];
1932 byte msk
[] = new byte[s
* s
];
1933 for (int i
= 0; i
< s
* s
; ++i
) {
1934 src
[i
] = (byte) 0xFF;
1936 ImageData i_src
= new ImageData(s
, s
, 1, palette
, 1, src
);
1937 ImageData i_msk
= new ImageData(s
, s
, 1, palette
, 1, msk
);
1938 fOverviewCursor
= new Cursor(null, i_src
, i_msk
, 0, 0);
1940 fCornerControl
.setCursor(fOverviewCursor
);
1941 // convert to global coordinates
1942 p
= toGlobalCoordinates(fCornerControl
, mx
, my
);
1946 Rectangle r
= fOverview
.getClientArea();
1947 int cx
= (int) (r
.width
* fContentsX
/ (float) fContentsWidth
);
1948 int cy
= (int) (r
.height
* fContentsY
/ (float) fContentsHeight
);
1950 // cx,cy to display's global coordinates
1951 p
= toGlobalCoordinates(fOverview
.getParent(), cx
, cy
);
1955 * Process disappear of overview
1957 protected void overviewDisappear() {
1958 overviewDisappear(true);
1962 * Process disappear of overview
1963 * @param restoreCursorLoc A flag to restore cursor location
1965 protected void overviewDisappear(boolean restoreCursorLoc
) {
1966 if (fOverview
== null) {
1969 fOverview
.setVisible(false);
1970 fCornerControl
.setCursor(null);
1971 if (restoreCursorLoc
) {
1972 getDisplay().setCursorLocation(fSaveCursorX
, fSaveCursorY
);
1974 fOverview
.dispose();
1979 * Process mouse move in overview
1980 * @param event The mouse event
1982 protected void overviewMove(MouseEvent event
) {
1983 Point p
= toGlobalCoordinates(fCornerControl
, event
.x
, event
.y
);
1984 int dx
= p
.x
- fSaveCursorX
;
1985 int dy
= p
.y
- fSaveCursorY
;
1986 overviewMove(dx
, dy
, event
);
1990 * Process mouse move event when overviewing
1992 * @param dx The x coordinates delta
1993 * @param dy The y coordinates delta
1994 * @param event The typed event
1996 protected void overviewMove(int dx
, int dy
, TypedEvent event
) {
1997 boolean ctrl
= false;
1998 boolean shift
= false;
2000 if (event
instanceof MouseEvent
) {
2001 MouseEvent e
= (MouseEvent
) event
;
2002 getDisplay().setCursorLocation(fSaveCursorX
, fSaveCursorY
);
2003 ctrl
= (e
.stateMask
& SWT
.CONTROL
) != 0;
2004 shift
= (e
.stateMask
& SWT
.SHIFT
) != 0;
2005 } else if (event
instanceof KeyEvent
) {
2006 KeyEvent e
= (KeyEvent
) event
;
2007 ctrl
= (e
.stateMask
& SWT
.CONTROL
) != 0;
2008 shift
= (e
.stateMask
& SWT
.SHIFT
) != 0;
2011 int cx
= fContentsX
;
2012 int cy
= fContentsY
;
2013 float fx
= fOverviewFactorX
;
2014 float fy
= fOverviewFactorY
;
2016 if (ctrl
&& shift
) {
2017 if ((fx
* 0.25f
> 1) && (fy
* 0.25 > 1)) {
2030 scrollBy((int) (fx
* dx
), (int) (fy
* dy
));
2031 if (cx
!= fContentsX
|| cy
!= fContentsY
) {
2033 fOverview
.update(); // draw now !
2038 * Convert overview coordinates to global coordinates.
2041 * the control reference
2043 * The x coordinate to convert
2045 * The y coordinate to convert
2046 * @return The new converted Point
2048 protected Point
toGlobalCoordinates(Control loc
, int x
, int y
) {
2049 Point p
= new Point(x
, y
);
2050 for (Control c
= loc
; c
!= null; c
= c
.getParent()) {
2051 // control might have client area with 'decorations'
2052 int trimX
= 0, trimY
= 0;
2053 // other kind of widget with trimming ??
2054 if (c
instanceof Scrollable
) {
2055 Scrollable s
= (Scrollable
) c
;
2056 Rectangle rr
= s
.getClientArea();
2057 Rectangle tr
= s
.computeTrim(rr
.x
, rr
.y
, rr
.width
, rr
.height
);
2058 trimX
= rr
.x
- tr
.x
;
2059 trimY
= rr
.y
- tr
.y
;
2061 p
.x
+= c
.getLocation().x
+ trimX
;
2062 p
.y
+= c
.getLocation().y
+ trimY
;