1 /**********************************************************************
2 * Copyright (c) 2005, 2008 IBM Corporation and others.
3 * Copyright (c) 2011, 2012 Ericsson.
5 * All rights reserved. This program and the accompanying materials
6 * are made available under the terms of the Eclipse Public License v1.0
7 * which accompanies this distribution, and is available at
8 * http://www.eclipse.org/legal/epl-v10.html
11 * IBM - Initial API and implementation
12 * Bernd Hufmann - Updated for TMF
13 **********************************************************************/
14 package org
.eclipse
.linuxtools
.tmf
.ui
.views
.uml2sd
;
16 import java
.util
.Timer
;
17 import java
.util
.TimerTask
;
19 import org
.eclipse
.linuxtools
.tmf
.ui
.views
.uml2sd
.util
.SDMessages
;
20 import org
.eclipse
.swt
.SWT
;
21 import org
.eclipse
.swt
.events
.ControlListener
;
22 import org
.eclipse
.swt
.events
.FocusEvent
;
23 import org
.eclipse
.swt
.events
.FocusListener
;
24 import org
.eclipse
.swt
.events
.KeyEvent
;
25 import org
.eclipse
.swt
.events
.KeyListener
;
26 import org
.eclipse
.swt
.events
.MouseEvent
;
27 import org
.eclipse
.swt
.events
.MouseListener
;
28 import org
.eclipse
.swt
.events
.MouseMoveListener
;
29 import org
.eclipse
.swt
.events
.MouseTrackListener
;
30 import org
.eclipse
.swt
.events
.PaintEvent
;
31 import org
.eclipse
.swt
.events
.PaintListener
;
32 import org
.eclipse
.swt
.events
.SelectionEvent
;
33 import org
.eclipse
.swt
.events
.SelectionListener
;
34 import org
.eclipse
.swt
.events
.TypedEvent
;
35 import org
.eclipse
.swt
.graphics
.Color
;
36 import org
.eclipse
.swt
.graphics
.Cursor
;
37 import org
.eclipse
.swt
.graphics
.GC
;
38 import org
.eclipse
.swt
.graphics
.ImageData
;
39 import org
.eclipse
.swt
.graphics
.PaletteData
;
40 import org
.eclipse
.swt
.graphics
.Point
;
41 import org
.eclipse
.swt
.graphics
.RGB
;
42 import org
.eclipse
.swt
.graphics
.Rectangle
;
43 import org
.eclipse
.swt
.widgets
.Button
;
44 import org
.eclipse
.swt
.widgets
.Canvas
;
45 import org
.eclipse
.swt
.widgets
.Composite
;
46 import org
.eclipse
.swt
.widgets
.Control
;
47 import org
.eclipse
.swt
.widgets
.Display
;
48 import org
.eclipse
.swt
.widgets
.Layout
;
49 import org
.eclipse
.swt
.widgets
.ScrollBar
;
50 import org
.eclipse
.swt
.widgets
.Scrollable
;
51 import org
.eclipse
.swt
.widgets
.Shell
;
54 * ScrollView widget provides a scrolling area with on-demand scroll bars.
55 * Overview scrollable panel can be used (@see setOverviewEnabled()).
57 * @author Eric Miravete
60 public class ScrollView
extends Composite
{
62 // ------------------------------------------------------------------------
64 // ------------------------------------------------------------------------
66 // Value for scroll bar mode, default is AUTO
68 * Scroll bar mode AUTO
70 public static final int AUTO
= 0;
72 * Scroll bar mode ALWAYS_ON
74 public static final int ALWAYS_ON
= 1;
76 * Scroll bar mode ALWAYS_OFF
78 public static final int ALWAYS_OFF
= 2;
80 * Bit mask for visible vertical scroll bar
82 public static final int VBAR
= 0x01;
84 * Bit mask for visible horizontal scroll bar
86 public static final int HBAR
= 0x02;
88 * Value of the contents height property.
90 protected int fContentsHeight
= 0;
92 * Value of the contents width property.
94 protected int fContentsWidth
= 0;
96 * Value of the contents x coordinate property
98 protected int fContentsX
= 0;
100 * Value of the contents y coordinate property
102 protected int fContentsY
= 0;
104 * Scroll bar mode of horizontal scroll bar.
106 protected int fHorScrollbarMode
= AUTO
;
108 * Scroll bar mode of vertical scroll bar.
110 protected int fVertScrollbarMode
= AUTO
;
112 * Increment for the horizontal scroll bar.
114 protected int fHorScrollbarIncrement
= 10;
116 * Increment for the vertical scroll bar.
118 protected int fVertScrollbarIncrement
= 10;
120 * Flag whether auto scroll is enabled or not.
122 protected boolean fAutoScrollEnabled
= true;
124 * Value of the auto scroll period.
126 protected int fAutoScrollPeriod
= 75;
128 * The local paint listener reference.
130 protected PaintListener fLocalPaintListener
= null;
132 * The local mouse move listener reference.
134 protected MouseMoveListener fLocalMouseMoveListener
= null;
136 * The local mouse listener reference.
138 protected MouseListener fLocalMouseListener
= null;
140 * The local control listener reference.
142 protected ControlListener fLocalControlListener
= null;
144 * The local key listener reference.
146 protected KeyListener fLocalKeyListener
= null;
147 // Canvas for vertical/horizontal Scroll Bar only ... because new ScrollBar() does works.
149 * Canvas for horizontal scroll bar.
151 protected Canvas fHorScrollBar
;
153 * Canvas for vertical scroll bar.
155 protected Canvas fVertScrollBar
;
157 * Canvas for the view control.
159 protected Canvas fViewControl
;
161 * Control used in the bottom right corner @see setCornerControl() and @see setOverviewEnabled(true)
163 protected Control fCornerControl
;
165 * Size of overview widget.
167 protected int fOverviewSize
= 100; // default size for overview
169 * Timer for auto_scroll feature
171 protected AutoScroll fAutoScroll
= null;
173 * TimerTask for auto_scroll feature !=null when auto scroll is running
175 protected Timer fAutoScrollTimer
= null;
177 * where mouse down appear on contents area (x coordinate)
179 protected int fMouseDownX
= -1;
181 * where mouse down appear on contents area (y coordinate)
183 protected int fMousDownY
= -1;
186 // ------------------------------------------------------------------------
188 // ------------------------------------------------------------------------
191 * Create a ScrollView, child of composite c. Both scroll bar have the mode AUTO. Auto scroll feature is enabled
192 * using a delay of 250ms. Overview feature is not enabled by default (use setOverviewEnabled()).
194 * @param c The parent composite
195 * @param style The SWT style bits @see SWT
197 public ScrollView(Composite c
, int style
) {
198 this(c
, style
, true);
202 * Create a ScrollView, child of composite c. Both scroll bar have the mode AUTO. Auto scroll feature is enabled
203 * using a delay of 250ms. Overview feature is not enabled by default (use setOverviewEnabled()).
205 * @param c The parent composite.
206 * @param style The SWT style bits @see SWT
207 * @param mouseWheel Flag to force scrollView to handles mouse wheel
209 public ScrollView(Composite c
, int style
, boolean mouseWheel
) {
210 super(c
, SWT
.NONE
); // style&(~(SWT.H_SCROLL|SWT.V_SCROLL)));
212 fHorScrollBar
= new Canvas(this, SWT
.H_SCROLL
);
214 // force scroll bar to get mouse wheel, those scrollbar will be hidden
215 fViewControl
= new Canvas(this, style
| SWT
.H_SCROLL
| SWT
.V_SCROLL
);
217 fViewControl
= new Canvas(this, style
);
219 fViewControl
.setBackground(getBackground());
220 // hide scroll bar as their are replaced by fHorScrollBar and fVertScrollBar.
222 fViewControl
.getVerticalBar().setVisible(false);
223 fViewControl
.getHorizontalBar().setVisible(false);
225 fVertScrollBar
= new Canvas(this, SWT
.V_SCROLL
);
226 // make fVerScrollBar able to receive mouse wheel
227 // does not help as we can't set a MouseListener on fVerScrollBar.getVerticalBar()
228 // to set focus on viewcontrol_
229 // fVerScrollBar.addKeyListener( new KeyAdapter() {});
231 setLayout(new SVLayout());
233 fLocalPaintListener
= new PaintListener() {
235 public void paintControl(PaintEvent event
) {
236 // use clipping, to reduce cost of paint.
237 Rectangle r
= event
.gc
.getClipping();
238 int cx
= viewToContentsX(r
.x
);
239 int cy
= viewToContentsY(r
.y
);
240 drawContents(event
.gc
, cx
, cy
, r
.width
, r
.height
);
243 fViewControl
.addPaintListener(fLocalPaintListener
);
245 fLocalMouseMoveListener
= new MouseMoveListener() {
247 public void mouseMove(MouseEvent e
) {
248 int ox
= e
.x
, oy
= e
.y
;
249 e
.x
= viewToContentsX(e
.x
);
250 e
.y
= viewToContentsY(e
.y
);
251 contentsMouseMoveEvent(e
);
257 fViewControl
.addMouseMoveListener(fLocalMouseMoveListener
);
259 MouseTrackListener localMouseTrackListener
= new MouseTrackListener() {
261 public void mouseEnter(MouseEvent e
) {
262 int ox
= e
.x
, oy
= e
.y
;
263 e
.x
= viewToContentsX(e
.x
);
264 e
.y
= viewToContentsY(e
.y
);
265 contentsMouseEnter(e
);
271 public void mouseHover(MouseEvent e
) {
272 int ox
= e
.x
, oy
= e
.y
;
273 e
.x
= viewToContentsX(e
.x
);
274 e
.y
= viewToContentsY(e
.y
);
275 contentsMouseHover(e
);
281 public void mouseExit(MouseEvent e
) {
282 int ox
= e
.x
, oy
= e
.y
;
283 e
.x
= viewToContentsX(e
.x
);
284 e
.y
= viewToContentsY(e
.y
);
285 contentsMouseExit(e
);
292 fViewControl
.addMouseTrackListener(localMouseTrackListener
);
294 fLocalMouseListener
= new MouseListener() {
296 public void mouseDoubleClick(MouseEvent e
) {
297 int ox
= e
.x
, oy
= e
.y
;
298 e
.x
= viewToContentsX(e
.x
);
299 e
.y
= viewToContentsY(e
.y
);
300 contentsMouseDoubleClickEvent(e
);
306 public void mouseDown(MouseEvent e
) {
307 int ox
= e
.x
, oy
= e
.y
;
308 e
.x
= fMouseDownX
= viewToContentsX(e
.x
);
309 e
.y
= fMousDownY
= viewToContentsY(e
.y
);
310 contentsMouseDownEvent(e
);
316 public void mouseUp(MouseEvent e
) {
317 int ox
= e
.x
, oy
= e
.y
;
318 e
.x
= viewToContentsX(e
.x
);
319 e
.y
= viewToContentsY(e
.y
);
320 contentsMouseUpEvent(e
);
323 // here because class extenting me can catch mouse Up and want to scroll...
324 fMouseDownX
= fMousDownY
= -1;
327 fViewControl
.addMouseListener(fLocalMouseListener
);
329 fLocalKeyListener
= new KeyListener() {
331 public void keyPressed(KeyEvent e
) {
336 public void keyReleased(KeyEvent e
) {
341 fViewControl
.addKeyListener(fLocalKeyListener
);
343 getVerticalBar().addSelectionListener(new SelectionListener() {
345 public void widgetSelected(SelectionEvent e
) {
346 setContentsPos(fContentsX
, getVerticalBar().getSelection());
347 // need to change "hidden" vertical bar value ?
348 // force focus on fViewControl so we got future mouse wheel's scroll events
349 if (!fViewControl
.isFocusControl()) {
350 fViewControl
.setFocus();
355 public void widgetDefaultSelected(SelectionEvent e
) {
359 if (fViewControl
.getVerticalBar() != null)
360 // add fViewControl hidden scrollbar listener to get mouse wheel ...
361 fViewControl
.getVerticalBar().addSelectionListener(new SelectionListener() {
363 public void widgetSelected(SelectionEvent e
) {
364 ScrollBar b
= fViewControl
.getVerticalBar();
365 setContentsPos(fContentsX
, b
.getSelection());
366 // change "real" vertical bar selection too
367 getVerticalBar().setSelection(b
.getSelection());
371 public void widgetDefaultSelected(SelectionEvent e
) {
374 getHorizontalBar().addSelectionListener(new SelectionListener() {
376 public void widgetSelected(SelectionEvent e
) {
377 setContentsPos(getHorizontalBar().getSelection(), fContentsY
);
378 // need to change "real" horizontal bar too ?
379 // force focus on fViewControl so we got future mouse wheel's scroll events
380 if (!fViewControl
.isFocusControl()) {
381 fViewControl
.setFocus();
386 public void widgetDefaultSelected(SelectionEvent e
) {
389 if (fViewControl
.getHorizontalBar() != null)
390 fViewControl
.getHorizontalBar().addSelectionListener(new SelectionListener() {
392 public void widgetSelected(SelectionEvent e
) {
393 ScrollBar b
= fViewControl
.getHorizontalBar();
394 setContentsPos(b
.getSelection(), fContentsY
);
395 // change "real" vertical bar selection too
396 getHorizontalBar().setSelection(b
.getSelection());
400 public void widgetDefaultSelected(SelectionEvent e
) {
405 // ------------------------------------------------------------------------
407 // ------------------------------------------------------------------------
411 * @see org.eclipse.swt.widgets.Composite#setFocus()
414 public boolean setFocus() {
415 return fViewControl
.forceFocus();
420 * @see org.eclipse.swt.widgets.Control#setCursor(org.eclipse.swt.graphics.Cursor)
423 public void setCursor(Cursor cursor
) {
424 fViewControl
.setCursor(cursor
);
428 * Dispose controls used in scroll view
431 * @see org.eclipse.swt.widgets.Widget#dispose()
434 public void dispose() {
435 if (fAutoScroll
!= null) {
436 fAutoScroll
.cancel();
439 if (fViewControl
!= null) {
440 fViewControl
.dispose();
443 if (fVertScrollBar
!= null) {
444 fVertScrollBar
.dispose();
446 fVertScrollBar
= null;
447 if (fHorScrollBar
!= null) {
448 fHorScrollBar
.dispose();
450 fHorScrollBar
= null;
451 if (fCornerControl
!= null) {
452 Object data
= fCornerControl
.getData();
453 if (data
instanceof Overview
) {
454 ((Overview
) data
).dispose();
456 fCornerControl
.dispose();
457 fCornerControl
= null;
464 * @see org.eclipse.swt.widgets.Composite#getClientArea()
467 public Rectangle
getClientArea() {
468 return fViewControl
.getClientArea();
473 * @see org.eclipse.swt.widgets.Control#setBackground(org.eclipse.swt.graphics.Color)
476 public void setBackground(Color c
) {
477 super.setBackground(c
);
478 fViewControl
.setBackground(c
);
483 * @see org.eclipse.swt.widgets.Control#setToolTipText(java.lang.String)
486 public void setToolTipText(String text
) {
487 fViewControl
.setToolTipText(text
);
491 * Draw overview area, @see setOverviewEnabled. By default draw a rectangle corresponding to the visible area of
492 * scroll view. You can redefine this method to draw the contents as drawContents does... ...in an other magnify
495 * @param gc GC to used to draw.
496 * @param r Rectangle corresponding to the client area of overview.
498 protected void drawOverview(GC gc
, Rectangle r
) {
499 int x
= (int) (r
.width
* fContentsX
/ (float) fContentsWidth
);
500 int y
= (int) (r
.height
* fContentsY
/ (float) fContentsHeight
);
501 int vw
= getVisibleWidth();
502 int vh
= getVisibleHeight();
504 if (fContentsWidth
> vw
) {
505 w
= (int) (r
.width
* vw
/ (float) fContentsWidth
);
507 int h
= r
.height
- 1;
508 if (fContentsHeight
> vh
) {
509 h
= (int) (r
.height
* vh
/ (float) fContentsHeight
);
512 gc
.setForeground(getForeground());
513 // too small rectangle ?
514 if (w
< 5 || h
< 5) {
516 gc
.drawLine(x
, 0, x
, r
.height
);
517 gc
.drawLine(0, y
, r
.width
, y
);
519 gc
.drawRectangle(x
, y
, w
, h
);
524 * Remove the local Listener and add the new listener.
526 * @param nlistener the new listener
528 public void replaceControlListener(ControlListener nlistener
) {
529 if (fLocalControlListener
!= null) {
530 removeControlListener(fLocalControlListener
);
531 fLocalControlListener
= null;
533 addControlListener(nlistener
);
537 * Remove the local Listener and add the new listener.
539 * @param nlistener the new listener
541 public void replaceKeyListener(KeyListener nlistener
) {
542 if (fLocalKeyListener
!= null) {
543 removeKeyListener(fLocalKeyListener
);
544 fLocalKeyListener
= null;
546 addKeyListener(nlistener
);
550 * Remove the local Listener and add the new listener.
552 * @param nlistener the new listener
554 public void replaceMouseListener(MouseListener nlistener
) {
555 if (fLocalMouseListener
!= null) {
556 removeMouseListener(fLocalMouseListener
);
557 fLocalMouseListener
= null;
559 fViewControl
.addMouseListener(nlistener
);
563 * Remove the local Listener and add the new listener.
565 * @param nlistener the new listener
567 public void replaceMouseMoveListener(MouseMoveListener nlistener
) {
568 if (fLocalMouseMoveListener
!= null) {
569 removeMouseMoveListener(fLocalMouseMoveListener
);
570 fLocalMouseMoveListener
= null;
572 fViewControl
.addMouseMoveListener(nlistener
);
576 * Remove the local Listener and add the new listener.
578 * @param nlistener the new listener
580 public void replacePaintListener(PaintListener nlistener
) {
581 if (fLocalPaintListener
!= null) {
582 removePaintListener(fLocalPaintListener
);
583 fLocalPaintListener
= null;
585 fViewControl
.addPaintListener(nlistener
);
589 * Access method for the contentsHeight property.
591 * @return the current value of the contentsHeight property
593 public int getContentsHeight() {
594 return fContentsHeight
;
598 * Access method for the contentsWidth property.
600 * @return the current value of the contentsWidth property
602 public int getContentsWidth() {
603 return fContentsWidth
;
607 * Access method for the contentsX property.
609 * @return the current value of the contentsX property
611 public int getContentsX() {
616 * Access method for the contentsY property.
618 * @return the current value of the contentsY property
620 public int getContentsY() {
625 * Determines if the dragAutoScroll property is true.
627 * @return <code>true<code> if the dragAutoScroll property is true
629 public boolean getDragAutoScroll() {
630 return fAutoScrollEnabled
;
634 * Sets the value of the dragAutoScroll property.
636 * @param aDragAutoScroll the new value of the dragAutoScroll property
638 public void setDragAutoScroll(boolean aDragAutoScroll
) {
639 fAutoScrollEnabled
= aDragAutoScroll
;
640 if (!fAutoScrollEnabled
&& (fAutoScroll
!= null)) {
641 fAutoScroll
.cancel();
647 * Change delay (in millisec) used for auto scroll feature.
649 * @param period new period between to auto scroll
651 public void setDragAutoScrollPeriod(int period
) {
652 fAutoScrollPeriod
= Math
.max(0, period
);
656 * Return auto scroll period.
658 public int getDragAutoScrollPeriod() {
659 return fAutoScrollPeriod
;
663 * Access method for the hScrollBarMode property.
665 * @return the current value of the hScrollBarMode property
667 public int getHScrollBarMode() {
668 return fHorScrollbarMode
;
672 * Sets the value of the hScrollBarMode property.
674 * @param aHScrollBarMode the new value of the hScrollBarMode property
676 public void setHScrollBarMode(int aHScrollBarMode
) {
677 fHorScrollbarMode
= aHScrollBarMode
;
681 * Access method for the vScrollBarMode property.
683 * @return the current value of the vScrollBarMode property
685 public int getVScrollBarMode() {
686 return fVertScrollbarMode
;
690 * Sets the value of the vScrollBarMode property.
692 * @param aVScrollBarMode the new value of the vScrollBarMode property
694 public void setVScrollBarMode(int aVScrollBarMode
) {
695 fVertScrollbarMode
= aVScrollBarMode
;
699 * Return horizontal scroll bar increment, default:1
701 public int getHScrollBarIncrement() {
702 return fHorScrollbarIncrement
;
706 * Return vertical scroll bar increment, default:1
708 public int getVScrollBarIncrement() {
709 return fVertScrollbarIncrement
;
713 * Change horizontal scroll bar increment, minimum:1. Page increment is always set to visible width.
715 public void setHScrollBarIncrement(int inc
) {
716 fHorScrollbarIncrement
= Math
.max(1, inc
);
720 * Change vertical scroll bar increment, minimum:1. Page increment is always set to visible height.
722 public void setVScrollBarIncrement(int inc
) {
723 fVertScrollbarIncrement
= Math
.max(1, inc
);
727 * Enable or disable overview feature. Enabling overview, dispose and replace existing corner control by a button.
728 * Clicking in it open overview, move mouse cursor holding button to move scroll view and release button to hide
729 * overview. Tip: hold control and/or shift key while moving mouse when overview is open made fine scroll.
731 * @param value true to engage overview feature
733 public void setOverviewEnabled(boolean value
) {
734 if (getOverviewEnabled() == value
) {
740 Button b
= new Button(this, SWT
.NONE
);
741 b
.setText("+"); //$NON-NLS-1$
742 Overview ovr
= new Overview();
746 b
.setToolTipText(SDMessages
._78
);
748 setCornerControl(cc
);
752 * Change overview size (at ratio 1:1), default is 100
754 public void setOverviewSize(int size
) {
755 fOverviewSize
= Math
.abs(size
);
759 * Returns whether the overview is enabled or not.
761 * @return true is overview feature is enabled
763 public boolean getOverviewEnabled() {
764 if (fCornerControl
instanceof Button
) {
765 Object data
= ((Button
) fCornerControl
).getData();
767 if (data
instanceof Overview
) {
775 * Returns the overview size at ratio 1:1.
777 * @return current overview size at ratio 1:1
779 public int getOverviewSize() {
780 return fOverviewSize
;
784 * Returns control used to display view (might not be this object). Use this control to add/remove listener on the
787 * @return control used to display view (might not be this object).
789 public Control
getViewControl() {
794 * Called when the mouse enter the ScrollView area
798 protected void contentsMouseExit(MouseEvent e
) {
802 * Called when the mouse enter the ScrollView area after and system defined time
806 protected void contentsMouseHover(MouseEvent e
) {
810 * Called when the mouse enter the ScrollView area
814 protected void contentsMouseEnter(MouseEvent e
) {
818 * Called when user double on contents area.
822 protected void contentsMouseDoubleClickEvent(MouseEvent e
) {
826 * Called when mouse is on contents area and button is pressed.
830 protected void contentsMouseDownEvent(MouseEvent e
) {
836 * TimerTask for auto scroll feature.
838 protected static class AutoScroll
extends TimerTask
{
841 public ScrollView scrollView
;
843 public AutoScroll(ScrollView sv
, int dx
, int dy
) {
851 Display
.getDefault().asyncExec(new Runnable() {
854 scrollView
.scrollBy(deltaX
, deltaY
);
861 * Called when mouse is on contents area and mode.
865 protected void contentsMouseMoveEvent(MouseEvent event
) {
866 if ((event
.stateMask
& SWT
.BUTTON_MASK
) != 0) {
867 if (!fAutoScrollEnabled
) {
868 scrollBy(-(event
.x
- fMouseDownX
), -(event
.y
- fMousDownY
));
874 int v_right
= getContentsX() + getVisibleWidth();
875 int v_bottom
= getContentsY() + getVisibleHeight();
878 if (event
.x
< getContentsX()) {
879 sx
= (getContentsX() - event
.x
);
880 fMouseDownX
= getContentsX();
881 } else if (event
.x
> v_right
) {
882 sx
= -event
.x
+ v_right
;
883 fMouseDownX
= v_right
;
885 if (event
.y
< getContentsY()) {
886 sy
= (getContentsY() - event
.y
);
887 fMousDownY
= getContentsY();
888 } else if (event
.y
> v_bottom
) {
889 sy
= -event
.y
+ v_bottom
;
890 fMousDownY
= v_bottom
;
893 if (sx
!= 0 || sy
!= 0) {
894 // start auto scroll...
895 if (fAutoScroll
== null) {
896 if (fAutoScrollTimer
== null) {
897 fAutoScrollTimer
= new Timer(true);
899 fAutoScroll
= new AutoScroll(this, sx
, sy
);
900 fAutoScrollTimer
.schedule(fAutoScroll
, 0, fAutoScrollPeriod
);
902 fAutoScroll
.deltaX
= sx
;
903 fAutoScroll
.deltaY
= sy
;
906 if (fAutoScroll
!= null) {
907 fAutoScroll
.cancel();
911 scrollBy(-(event
.x
- fMouseDownX
), -(event
.y
- fMousDownY
));
917 * Called when mouse is on contents area and button is released
921 protected void contentsMouseUpEvent(MouseEvent event
) {
922 // reset auto scroll if it's engaged
923 if (fAutoScroll
!= null) {
924 fAutoScroll
.cancel();
930 * Responsible to draw contents area. At least rectangle clipX must be redrawn. This rectangle is given in contents
931 * coordinates. By default, no paint is produced.
939 protected void drawContents(GC gc
, int clipx
, int clipy
, int clipw
, int cliph
) {
943 * Change the size of the contents area.
945 * @param width new width of the area.
946 * @param height new height of the area.
948 public void resizeContents(int width
, int height
) {
949 // System.out.println("SV--resizeContents("+_w+","+_h+" ) {");
950 int localWidth
= width
;
951 int localHeight
= height
;
953 if (localWidth
< 0) {
956 if (localHeight
< 0) {
960 int oldW
= fContentsWidth
;
961 int oldH
= fContentsHeight
;
963 if (localWidth
== oldW
&& localHeight
== oldH
) {
967 // System.out.println("RESIZE-CONTENTS("+_w+","+_h+")");
968 fContentsWidth
= localWidth
;
969 fContentsHeight
= localHeight
;
971 if (oldW
> localWidth
) {
977 int vis_width
= getVisibleWidth();
978 int vis_height
= getVisibleHeight();
979 if (oldW
< vis_width
) {
980 if (localWidth
> vis_width
) {
981 localWidth
= vis_width
;
983 fViewControl
.redraw(getContentsX() + oldW
, 0, localWidth
- oldW
, vis_height
, true);
986 if (oldH
> localHeight
) {
992 if (oldH
< vis_height
) {
993 if (localHeight
> vis_height
) {
994 localHeight
= vis_height
;
996 fViewControl
.redraw(0, getContentsY() + oldH
, vis_width
, localHeight
- oldH
, true);
998 if (updateScrollBarVisiblity()) {
1001 updateScrollBarsValues();
1003 // System.out.println("SV--resizeContents() }");
1006 // redefined for internal use ..
1008 public void redraw() {
1010 // ..need to redraw this already:
1011 fViewControl
.redraw();
1015 * @param delataX The delta in X
1016 * @param deltaY the delta in Y
1018 public void scrollBy(int delataX
, int deltaY
) {
1019 setContentsPos(getContentsX() + delataX
, getContentsY() + deltaY
);
1023 * Scroll to ensure point(in contents coordinates) is visible.
1025 * @param px Point's x position
1026 * @param py Point's y position
1028 public void ensureVisible(int px
, int py
) {
1029 int cx
= getContentsX(), cy
= getContentsY();
1030 int right
= getContentsX() + getVisibleWidth();
1031 int bottom
= getContentsY() + getVisibleHeight();
1032 if (px
< getContentsX()) {
1034 } else if (px
> right
) {
1035 cx
= px
- getVisibleWidth();
1037 if (py
< getContentsY()) {
1039 } else if (py
> bottom
) {
1040 cy
= py
- getVisibleHeight();
1042 setContentsPos(cx
, cy
);
1046 * Make rectangle (x,y,w,h, in contents coordinates) visible. if rectangle cannot be completely visible, use
1049 * @param xValue x contents coordinates of rectangle.
1050 * @param yValue y contents coordinates of rectangle.
1051 * @param width width of rectangle.
1052 * @param height height of rectangle.
1053 * @param align bit or'ed SWT flag like SWT.LEFT,RIGHT,CENTER,TOP,BOTTOM,VERTICAL used only for bigger rectangle
1054 * than visible area. By default CENTER/VERTICAL
1056 public void ensureVisible(int xValue
, int yValue
, int width
, int height
, int align
) {
1057 ensureVisible(xValue
, yValue
, width
, height
, align
, false);
1061 * Make rectangle (xValue,yValue,width,height, in contents coordinates) visible. if rectangle cannot be completely visible, use
1064 * @param xValue x contents coordinates of rectangle.
1065 * @param yValue y contents coordinates of rectangle.
1066 * @param width width of rectangle.
1067 * @param height height of rectangle.
1068 * @param align bit or'ed SWT flag like SWT.LEFT,RIGHT,CENTER,TOP,BOTTOM,VERTICAL used only for bigger rectangle
1069 * than visible area. By default CENTER/VERTICAL
1070 * @param forceAlign force alignment for rectangle smaller than the visible area
1072 protected void ensureVisible(int xValue
, int yValue
, int width
, int height
, int align
, boolean forceAlign
) {
1074 int localWidth
= width
;
1075 int localHeight
= height
;
1077 if (localWidth
< 0) {
1078 xValue
= xValue
+ localWidth
;
1079 localWidth
= -localWidth
;
1081 if (localHeight
< 0) {
1082 yValue
= yValue
+ localHeight
;
1083 localHeight
= -localHeight
;
1085 int hbar
= getHorizontalBarHeight();
1086 int vbar
= getVerticalBarWidth();
1087 int cx
= getContentsX(), cy
= getContentsY();
1088 int right
= getContentsX() + getVisibleWidth() - vbar
;
1089 int bottom
= getContentsY() + getVisibleHeight() - hbar
;
1090 boolean align_h
= false, align_v
= false;
1092 if (xValue
< getContentsX()) {
1094 } else if (xValue
+ localWidth
> right
) {
1095 cx
= xValue
- localWidth
;
1097 if (yValue
< getContentsY()) {
1099 } else if (yValue
+ localHeight
> bottom
) {
1100 cy
= yValue
- localHeight
;
1103 if (localWidth
> getVisibleWidth()) {
1106 if (localHeight
> getVisibleHeight()) {
1109 // compute alignment on visible area horizontally
1110 if (align_h
|| (forceAlign
&& xValue
+ localWidth
> right
)) {
1112 if ((align
& SWT
.LEFT
) != 0) {
1114 } else if ((align
& SWT
.RIGHT
) != 0) {
1115 cx
= right
- localWidth
;
1117 cx
= xValue
+ (localWidth
- getVisibleWidth()) / 2;
1120 // compute alignment on visible area vertically
1121 if (align_v
|| (forceAlign
&& yValue
+ localHeight
> bottom
)) {
1123 if ((align
& SWT
.TOP
) != 0) {
1125 } else if ((align
& SWT
.BOTTOM
) != 0) {
1126 cy
= bottom
- localHeight
;
1128 cy
= yValue
+ (localHeight
- getVisibleHeight()) / 2;
1131 setContentsPos(cx
, cy
);
1135 * Returns true if point is visible (expressed in contents coordinates).
1137 * @param px Point's x position
1138 * @param py Point's y position
1139 * @return true if point is visible (expressed in contents coordinates)
1141 public boolean isVisible(int px
, int py
) {
1142 if (px
< getContentsX()) {
1145 if (py
< getContentsY()) {
1148 if (px
> (getContentsX() + getVisibleWidth())) {
1151 if (py
> (getContentsY() + getVisibleHeight())) {
1158 * Returns true if rectangle if partially visible.
1160 * @param xValue x contents coordinates of rectangle.
1161 * @param yValue y contents coordinates of rectangle.
1162 * @param width width of rectangle.
1163 * @param height height of rectangle.
1164 * @return true if rectangle if partially visible.
1166 public boolean isVisible(int xValue
, int yValue
, int width
, int height
) {
1167 if (xValue
+ width
< getContentsX()) {
1170 if (yValue
+ height
< getContentsY()) {
1173 int vr
= getContentsX() + getVisibleWidth();
1174 int vb
= getContentsY() + getVisibleHeight();
1185 * Returns visible part of rectangle, or null if rectangle is not visible. Rectangle is expressed in contents
1188 * @param xValue x contents coordinates of rectangle.
1189 * @param yValue y contents coordinates of rectangle.
1190 * @param width width of rectangle.
1191 * @param height height of rectangle.
1192 * @return visible part of rectangle, or null if rectangle is not visible.
1194 public Rectangle
getVisiblePart(int xValue
, int yYalue
, int width
, int height
) {
1195 if (xValue
+ width
< getContentsX()) {
1198 if (yYalue
+ height
< getContentsY()) {
1201 int vr
= getContentsX() + getVisibleWidth();
1202 int vb
= getContentsY() + getVisibleHeight();
1209 int rr
= xValue
+ width
, rb
= yYalue
+ height
;
1210 int nl
= Math
.max(xValue
, getContentsX()), nt
= Math
.max(yYalue
, getContentsY()), nr
= Math
.min(rr
, vr
), nb
= Math
.min(rb
, vb
);
1211 return new Rectangle(nl
, nt
, nr
- nl
, nb
- nt
);
1215 * Returns the visible part for given rectangle.
1217 * @param rect A rectangle
1219 * @return gets visible part of rectangle (or <code>null</code>)
1221 public final Rectangle
getVisiblePart(Rectangle rect
) {
1225 return getVisiblePart(rect
.x
, rect
.y
, rect
.width
, rect
.height
);
1229 * Change top left position of visible area. Check if the given point is inside contents area.
1231 * @param xValue x contents coordinates of visible area.
1232 * @param yValue y contents coordinates of visible area.
1233 * @return true if view really moves
1235 public boolean setContentsPos(int xValue
, int yValue
) {
1236 int nx
= xValue
, ny
= yValue
;
1237 if (getVisibleWidth() >= getContentsWidth()) {
1242 } else if (xValue
+ getVisibleWidth() > getContentsWidth()) {
1243 nx
= getContentsWidth() - getVisibleWidth();
1246 if (getVisibleHeight() >= getContentsHeight()) {
1251 } else if (yValue
+ getVisibleHeight() > getContentsHeight()) {
1252 ny
= getContentsHeight() - getVisibleHeight();
1256 if (nx
== fContentsX
&& ny
== fContentsY
) {
1261 updateScrollBarsValues();
1262 // ? find smallest area to redraw only them ?
1263 fViewControl
.redraw();
1267 // redefined to return our vertical bar
1270 * @see org.eclipse.swt.widgets.Scrollable#getVerticalBar()
1273 public ScrollBar
getVerticalBar() {
1274 return fVertScrollBar
.getVerticalBar();
1277 // redefined to return out horizontal bar
1280 * @see org.eclipse.swt.widgets.Scrollable#getHorizontalBar()
1283 public ScrollBar
getHorizontalBar() {
1284 return fHorScrollBar
.getHorizontalBar();
1288 * Compute visibility of vertical/horizontal bar using given width/height and current visibility (i.e. is bar size are already in
1290 * @param forWidth width of foreground
1291 * @param forHeight height of foreground
1292 * @param currHorVis The current visibility state of horizontal scroll bar
1293 * @param currVertvis The current visibility state of vertical scroll bar
1294 * @return <code>true</code> if visibility changed else <code>false</code>
1296 public int computeBarVisibility(int forWidth
, int forHeight
, boolean currHorVis
, boolean currVertvis
) {
1298 int localForWidth
= forWidth
;
1300 switch (fVertScrollbarMode
) {
1307 if (getContentsHeight() > forHeight
) {
1309 // v bar size is already in for_width.
1310 if (!currVertvis
) {// (curr_vis&0x01)==0)
1311 localForWidth
-= getVerticalBarWidth();
1317 switch (fHorScrollbarMode
) {
1324 if (getContentsWidth() > localForWidth
) {
1326 // h bar is not in for_height
1327 if ((!currHorVis
) && (getContentsHeight() > (forHeight
- getHorizontalBarHeight()))) {// (curr_vis&0x02)==0 )
1337 * setup scroll bars visibility, return true if one of visibility changed.
1339 protected boolean updateScrollBarVisiblity() {
1340 boolean change
= false;
1342 boolean currVertVis
= fVertScrollBar
.getVisible();
1343 boolean currHorVis
= fHorScrollBar
.getVisible();
1344 int barNewVis
= computeBarVisibility(getVisibleWidth(), getVisibleHeight(), currHorVis
, currVertVis
);
1345 boolean newVertVis
= (barNewVis
& VBAR
) != 0;
1346 boolean newHorVis
= (barNewVis
& HBAR
) != 0;
1347 // System.out.println("SV--updateScrollBarVis old, h:"+curr_h_vis+" v:"+curr_v_vis+" new="+bar_new_vis);
1348 if (currVertVis ^ newVertVis
) { // vertsb_.getVisible() )
1349 fVertScrollBar
.setVisible(newVertVis
);
1352 if (currHorVis ^ newHorVis
) {
1353 fHorScrollBar
.setVisible(newHorVis
);
1357 // update corner control visibility:
1358 if (fCornerControl
!= null && change
) {
1359 boolean vis
= newVertVis
|| newHorVis
;
1360 if (vis ^ fCornerControl
.getVisible()) {
1361 fCornerControl
.setVisible(vis
);
1362 change
= true; // but must be already the case
1369 * Setup scroll bar using contents, visible and scroll bar mode properties.
1371 protected void updateScrollBarsValues() {
1372 // System.out.println("UPDATE-SCROLL-BAR-VALUES");
1373 /* update vertical scrollbar */
1374 ScrollBar b
= getVerticalBar();
1377 b
.setMaximum(getContentsHeight());
1378 b
.setThumb(getVisibleHeight());
1379 b
.setPageIncrement(getVisibleHeight());
1380 b
.setIncrement(fVertScrollbarIncrement
);
1381 b
.setSelection(getContentsY());
1384 // update "hidden" vertical bar too
1385 b
= fViewControl
.getVerticalBar();
1388 b
.setMaximum(getContentsHeight());
1389 b
.setThumb(getVisibleHeight());
1390 b
.setPageIncrement(getVisibleHeight());
1391 b
.setIncrement(fVertScrollbarIncrement
);
1392 b
.setSelection(getContentsY());
1395 /* update horizontal scrollbar */
1396 b
= getHorizontalBar();
1399 b
.setMaximum(getContentsWidth());
1400 b
.setThumb(getVisibleWidth());
1401 b
.setSelection(getContentsX());
1402 b
.setPageIncrement(getVisibleWidth());
1403 b
.setIncrement(fHorScrollbarIncrement
);
1405 // update "hidden" horizontal bar too
1406 b
= fViewControl
.getHorizontalBar();
1409 b
.setMaximum(getContentsWidth());
1410 b
.setThumb(getVisibleWidth());
1411 b
.setSelection(getContentsX());
1412 b
.setPageIncrement(getVisibleWidth());
1413 b
.setIncrement(fHorScrollbarIncrement
);
1418 * Change the control used in the bottom right corner (between two scrollbar), if control is null reset previous
1419 * corner control. This control is visible only if at least one scrollbar is visible. Given control will be disposed
1420 * by ScrollView, at dispose() time, at next setCornetControl() call or when calling setOverviewEnabled(). Pay
1421 * attention calling this reset overview feature until setOverviewEnabled(true) if called.
1422 * @param control The control for the overview
1424 public void setCornerControl(Control control
) {
1425 if (fCornerControl
!= null) {
1426 fCornerControl
.dispose();
1428 fCornerControl
= control
;
1429 if (fCornerControl
!= null) {
1430 ScrollBar vb
= getVerticalBar();
1431 ScrollBar hb
= getHorizontalBar();
1432 boolean vis
= vb
.getVisible() || hb
.getVisible();
1433 fCornerControl
.setVisible(vis
);
1438 * Transform (x,y) point in widget coordinates to contents coordinates.
1440 * @param x The x widget coordinate.
1441 * @param y The y widget coordinate.
1442 * @return org.eclipse.swt.graphics.Point with content coordinates.
1444 public final Point
viewToContents(int x
, int y
) {
1445 return new Point(viewToContentsX(x
), viewToContentsY(y
));
1449 * Transform x in widget coordinates to contents coordinates
1451 * @param x The y widget coordinate.
1452 * @return the x content coordinate.
1454 public int viewToContentsX(int x
) {
1455 return fContentsX
+ x
;
1459 * Transform y in widget coordinates to contents coordinates
1461 * @param y The y widget coordinate.
1462 * @return the y content coordinate.
1464 public int viewToContentsY(int y
) {
1465 return fContentsY
+ y
;
1469 * Transform (x,y) point from contents coordinates, to widget coordinates.
1471 * @param x The x content coordinate.
1472 * @param y The y content coordinate.
1473 * @return coordinates widget area as.
1475 public final Point
contentsToView(int x
, int y
) {
1476 return new Point(contentsToViewX(x
), contentsToViewY(y
));
1480 * Transform X axis coordinates from contents to widgets.
1482 * @param x contents coordinate to transform.
1483 * @return x coordinate in widget area
1485 public int contentsToViewX(int x
) {
1486 return x
- fContentsX
;
1490 * Transform Y axis coordinates from contents to widgets.
1492 * @param y contents coordinate to transform
1493 * @return y coordinate in widget area
1495 public int contentsToViewY(int y
) {
1496 return y
- fContentsY
;
1500 * Return the visible height of scroll view, might be > contentsHeight
1502 * @return the visible height of scroll view, might be > contentsHeight()
1504 public int getVisibleHeight() {
1505 Rectangle r
= fViewControl
.getClientArea();
1510 * Return int the visible width of scroll view, might be > contentsWidth().
1512 * @return int the visible width of scroll view, might be > contentsWidth()
1514 public int getVisibleWidth() {
1515 Rectangle r
= fViewControl
.getClientArea();
1520 * Add support for arrow key, scroll the ... scroll view. But you can redefine this method for your convenience.
1522 protected void keyPressedEvent(KeyEvent event
) {
1523 switch (event
.keyCode
) {
1525 scrollBy(0, -getVisibleHeight());
1527 case SWT
.ARROW_DOWN
:
1528 scrollBy(0, +getVisibleHeight());
1530 case SWT
.ARROW_LEFT
:
1531 scrollBy(-getVisibleWidth(), 0);
1533 case SWT
.ARROW_RIGHT
:
1534 scrollBy(+getVisibleWidth(), 0);
1540 * Redefine this method at your convenience
1541 * @param event The key event.
1543 protected void keyReleasedEvent(KeyEvent event
) {
1547 * Called when ScrollView view is resized.
1549 protected void viewResized() {
1550 // System.out.println("SV--viewResizeEvent()");
1551 // scroll contents x,y if visible area bigger than contents...
1552 if (!setContentsPos(getContentsX(), getContentsY())) {
1553 // if no scroll done, scroll bar must be updated.
1555 * if( ocx==getContentsX() && ocy==getContentsY() ) { updateScrollBars(); }
1561 * Returns vertical bar width, even if bar isn't visible.
1563 * @return vertical bar width, even if bar isn't visible
1565 public int getVerticalBarWidth() {
1566 // include vertical bar width and trimming of scrollable used
1567 int bw
= fVertScrollBar
.computeTrim(0, 0, 0, 0).width
;
1572 * Returns horizontal bar height even if bar isn't visible.
1574 * @return horizontal bar height even if bar isn't visible
1576 public int getHorizontalBarHeight() {
1577 // include horiz. bar height and trimming of scrollable used
1578 int bh
= fHorScrollBar
.computeTrim(0, 0, 0, 0).height
;
1579 // +1 because win32 H.bar need 1 pixel canvas size to appear ! (strange no ?)
1585 * @see org.eclipse.swt.widgets.Scrollable#computeTrim(int, int, int, int)
1588 public Rectangle
computeTrim(int x
, int y
, int w
, int h
) {
1589 Rectangle r
= new Rectangle(x
, y
, w
, h
);
1590 int bar_vis
= computeBarVisibility(w
, h
, false, false);
1591 if ((bar_vis
& VBAR
) != 0) {
1592 r
.width
+= getVerticalBarWidth();
1594 if ((bar_vis
& HBAR
) != 0) {
1595 r
.height
+= getHorizontalBarHeight();
1601 * Internal layout for ScrollView, handle scrollbars, drawzone and corner control
1603 protected class SVLayout
extends Layout
{
1609 * The do-it-not flag
1611 boolean dontLayout
= false;
1615 * @see org.eclipse.swt.widgets.Layout#computeSize(org.eclipse.swt.widgets.Composite, int, int, boolean)
1618 protected Point
computeSize(Composite composite
, int wHint
, int hHint
, boolean flushCache
) {
1619 Point p
= new Point(250, 250);
1620 if (fContentsWidth
< p
.x
) {
1621 p
.x
= fContentsWidth
;
1623 if (fContentsHeight
< p
.y
) {
1624 p
.y
= fContentsHeight
;
1631 * @see org.eclipse.swt.widgets.Layout#layout(org.eclipse.swt.widgets.Composite, boolean)
1634 protected void layout(Composite composite
, boolean flushCache
) {
1643 // System.out.println(">>> SV.layout() {");
1644 Point cs
= composite
.getSize();
1645 int bar_vis
= computeBarVisibility(cs
.x
, cs
.y
, false, false);
1646 boolean vb_vis
= (bar_vis
& VBAR
) != 0;
1647 boolean hb_vis
= (bar_vis
& HBAR
) != 0;
1648 fVertScrollBar
.setVisible(vb_vis
);
1649 fHorScrollBar
.setVisible(hb_vis
);
1650 int vbw
= getVerticalBarWidth();
1651 int hbh
= getHorizontalBarHeight();
1652 int wb
= vb_vis ? vbw
: 0;
1653 int hb
= hb_vis ? hbh
: 0;
1654 int cww
= 0, cwh
= 0;
1655 // System.out.println("SV-LAYOUT H.vis="+hb_vis+" V.vis="+vb_vis);
1657 if (fCornerControl
!= null && (vb_vis
|| hb_vis
)) { // corner_control_.getVisible())
1658 fCornerControl
.setVisible(true);
1665 } else if (vb_vis
&& hb_vis
) {
1666 if (fCornerControl
!= null) {
1667 fCornerControl
.setVisible(false);
1672 if (vb_vis
|| hb_vis
) {
1673 updateScrollBarsValues();
1676 int vw
= cs
.x
- (vb_vis ? vbw
: 0);
1677 int vh
= cs
.y
- (hb_vis ? hbh
: 0);
1678 int vbx
= cs
.x
- wb
;
1679 int hby
= cs
.y
- hb
;
1680 Rectangle rc
= fViewControl
.getClientArea();
1681 int old_width
= rc
.width
;
1682 int old_height
= rc
.height
;
1683 // provoque pas un viewResize ???
1684 fViewControl
.setBounds(0, 0, vw
, vh
);
1685 boolean do_view_resize
= false;
1686 rc
= fViewControl
.getClientArea();
1687 if (old_width
!= rc
.width
|| old_height
!= rc
.height
) {
1688 // area size change, so visibleWidth()/Height() change too
1689 // so scrollbars visibility ma change too..
1690 // so need an other layout !
1692 * if( updateScrollBarVisiblity() ) { layout( composite, flushCache);
1693 * System.out.println("<<< SV.layout() } (recursive)"); return ; }
1695 do_view_resize
= true;
1698 fVertScrollBar
.setBounds(vbx
, 0, wb
, cs
.y
- cwh
);
1701 fHorScrollBar
.setBounds(0, hby
, cs
.x
- cww
, hb
);
1703 if (fCornerControl
!= null && fCornerControl
.getVisible()) {
1704 fCornerControl
.setBounds(vbx
, hby
, vbw
, hbh
);
1706 updateScrollBarsValues();
1707 if (do_view_resize
) {
1708 // System.out.println(" -layout do_view_resize old="+old_width+"x"+old_height+" new="+viewcontrol_.getClientArea());
1711 // System.out.println("<<< SV.layout() }");
1719 // static must take place here... cursor is created once.
1720 static Cursor fOverviewCursor
;
1722 /** Support for click-and-see overview shell on this ScrollView */
1723 protected class Overview
{
1726 * factor for X from real and overview sizes, for mouse move speed.
1728 protected float fOverviewFactorX
;
1731 * factor for Y from real and overview sizes, for mouse move speed.
1733 protected float fOverviewFactorY
;
1735 * shell use to show overview
1737 protected Shell fOverview
;
1739 * save mouse X cursor location for disappear();
1741 protected int fSaveCursorX
;
1743 * save mouse Y cursor location for disappear();
1745 protected int fSaveCursorY
;
1748 * apply overview support on a control. Replace existing corner_widget
1750 public void useControl(Control control
) {
1751 final Point pos
= control
.getLocation();
1752 control
.addMouseListener(new MouseListener() {
1754 public void mouseDoubleClick(MouseEvent e
) {
1758 public void mouseDown(MouseEvent e
) {
1759 overviewAppear(e
.x
, e
.y
);
1763 public void mouseUp(MouseEvent e
) {
1764 overviewDisappear();
1768 control
.addFocusListener(new FocusListener() {
1771 public void focusGained(FocusEvent e
) {
1775 public void focusLost(FocusEvent e
) {
1777 overviewDisappear(false);
1781 control
.addKeyListener(new KeyListener() {
1784 public void keyPressed(KeyEvent event
) {
1785 if (event
.keyCode
== 32 && !overviewing()) {
1786 overviewAppear(pos
.x
, pos
.y
);
1787 } else if (event
.keyCode
== 32) {
1788 overviewDisappear();
1790 if (event
.keyCode
== SWT
.ARROW_DOWN
) {
1791 overviewMove(0, 1, event
);
1794 if (event
.keyCode
== SWT
.ARROW_UP
) {
1795 overviewMove(0, -1, event
);
1798 if (event
.keyCode
== SWT
.ARROW_RIGHT
) {
1799 overviewMove(1, 0, event
);
1802 if (event
.keyCode
== SWT
.ARROW_LEFT
) {
1803 overviewMove(-1, 0, event
);
1808 public void keyReleased(KeyEvent e
) {
1811 control
.addMouseMoveListener(new MouseMoveListener() {
1812 private int refReshCount
= 0;
1814 public void mouseMove(MouseEvent event
) {
1815 if (overviewing()) {
1816 // Slow down the refresh
1817 if (refReshCount
% 4 == 0) {
1818 overviewMove(event
);
1827 * Dispose controls of overview
1829 public void dispose() {
1830 if (fOverview
!= null) {
1831 fOverview
.dispose();
1836 * @return true if overview is currently on screen
1838 protected boolean overviewing() {
1839 return (fOverview
!= null && fOverview
.isVisible());
1843 * Process overview appear
1845 protected void overviewAppear(int mx
, int my
) {
1846 if (fOverview
== null) {
1847 fOverview
= new Shell(getShell(), SWT
.ON_TOP
| SWT
.NO_BACKGROUND
);
1848 fOverview
.addPaintListener(new PaintListener() {
1850 public void paintControl(PaintEvent e
) {
1851 drawOverview(e
.gc
, fOverview
.getClientArea());
1855 // always the same..
1856 // overview.setBackground( viewcontrol_.getBackground() );
1857 fOverview
.setForeground(fViewControl
.getForeground());
1859 // get location of shell (in screeen coordinates)
1860 Point p
= toGlobalCoordinates(fCornerControl
, 0, 0);
1864 w
= h
= fOverviewSize
;
1865 Rectangle scr
= getDisplay().getBounds();
1866 Point ccs
= fCornerControl
.getSize();
1868 if (fContentsWidth
> fContentsHeight
) {
1869 float ratio
= fContentsHeight
/ (float) fContentsWidth
;
1870 h
= (int) (w
* ratio
);
1873 } else if (h
>= scr
.height
/ 2) {
1877 float ratio
= fContentsWidth
/ (float) fContentsHeight
;
1878 w
= (int) (h
* ratio
);
1881 } else if (w
>= scr
.width
/ 2) {
1885 fOverviewFactorX
= fContentsWidth
/ (float) w
;
1886 fOverviewFactorY
= fContentsHeight
/ (float) h
;
1888 // no contents size set ?
1889 catch (java
.lang
.ArithmeticException e
) {
1892 // try pop-up on button, extending to bottom right,
1893 // if outside screen, extend pop-up to top left
1894 // if( x+w > scr.width ) x = scr.width-w; //x += corner_control_.getSize().x-w;
1895 // if( y+h > scr.height ) y = scr.height-h;//y += corner_control_.getSize().y-h;
1904 fOverview
.setBounds(x
, y
, w
, h
);
1905 fOverview
.setVisible(true);
1907 // mouse cursor disappear, so set invisible mouse cursor ...
1908 if (fOverviewCursor
== null) {
1909 RGB rgb
[] = { new RGB(0, 0, 0), new RGB(255, 0, 0) };
1910 PaletteData palette
= new PaletteData(rgb
);
1912 byte src
[] = new byte[s
* s
];
1913 byte msk
[] = new byte[s
* s
];
1914 for (int i
= 0; i
< s
* s
; ++i
)
1915 src
[i
] = (byte) 0xFF;
1916 ImageData i_src
= new ImageData(s
, s
, 1, palette
, 1, src
);
1917 ImageData i_msk
= new ImageData(s
, s
, 1, palette
, 1, msk
);
1918 fOverviewCursor
= new Cursor(null, i_src
, i_msk
, 0, 0);
1920 fCornerControl
.setCursor(fOverviewCursor
);
1921 // convert to global coordinates
1922 p
= toGlobalCoordinates(fCornerControl
, mx
, my
);
1926 Rectangle r
= fOverview
.getClientArea();
1927 int cx
= (int) (r
.width
* fContentsX
/ (float) fContentsWidth
);
1928 int cy
= (int) (r
.height
* fContentsY
/ (float) fContentsHeight
);
1930 // cx,cy to display's global coordinates
1931 p
= toGlobalCoordinates(fOverview
.getParent(), cx
, cy
);
1938 * Process disappear of overview
1940 protected void overviewDisappear() {
1941 overviewDisappear(true);
1945 * Process disappear of overview
1946 * @param restoreCursorLoc A flag to restore cursor location
1948 protected void overviewDisappear(boolean restoreCursorLoc
) {
1949 if (fOverview
== null)
1951 fOverview
.setVisible(false);
1952 fCornerControl
.setCursor(null);
1953 if (restoreCursorLoc
) {
1954 getDisplay().setCursorLocation(fSaveCursorX
, fSaveCursorY
);
1956 fOverview
.dispose();
1961 * Process mouse move in overview
1962 * @param event The mouse event
1964 protected void overviewMove(MouseEvent event
) {
1965 Point p
= toGlobalCoordinates(fCornerControl
, event
.x
, event
.y
);
1966 int dx
= p
.x
- fSaveCursorX
;
1967 int dy
= p
.y
- fSaveCursorY
;
1968 overviewMove(dx
, dy
, event
);
1972 * Process mouse move event when overviewing
1974 * @param dx The x coordinates delta
1975 * @param dy The y coordinates delta
1976 * @param event The typed event
1978 protected void overviewMove(int dx
, int dy
, TypedEvent event
) {
1979 boolean ctrl
= false;
1980 boolean shift
= false;
1982 if (event
instanceof MouseEvent
) {
1983 MouseEvent e
= (MouseEvent
) event
;
1984 getDisplay().setCursorLocation(fSaveCursorX
, fSaveCursorY
);
1985 ctrl
= (e
.stateMask
& SWT
.CONTROL
) != 0;
1986 shift
= (e
.stateMask
& SWT
.SHIFT
) != 0;
1987 } else if (event
instanceof KeyEvent
) {
1988 KeyEvent e
= (KeyEvent
) event
;
1989 ctrl
= (e
.stateMask
& SWT
.CONTROL
) != 0;
1990 shift
= (e
.stateMask
& SWT
.SHIFT
) != 0;
1993 int cx
= fContentsX
;
1994 int cy
= fContentsY
;
1995 float fx
= fOverviewFactorX
;
1996 float fy
= fOverviewFactorY
;
1998 if (ctrl
&& shift
) {
1999 if ((fx
* 0.25f
> 1) && (fy
* 0.25 > 1)) {
2012 scrollBy((int) (fx
* dx
), (int) (fy
* dy
));
2013 if (cx
!= fContentsX
|| cy
!= fContentsY
) {
2015 fOverview
.update(); // draw now !
2020 * Convert overview coordinates to global coordinates.
2022 * @param loc the control reference
2023 * @param x The x coordinate to convert
2024 * @param y The y coordinate to convert
2027 protected Point
toGlobalCoordinates(Control loc
, int x
, int y
) {
2028 Point p
= new Point(x
, y
);
2029 for (Control c
= loc
; c
!= null; c
= c
.getParent()) {
2030 // control might have client area with 'decorations'
2031 int trim_x
= 0, trim_y
= 0;
2032 // other kind of widget with trimming ??
2033 if (c
instanceof Scrollable
) {
2034 Scrollable s
= (Scrollable
) c
;
2035 Rectangle rr
= s
.getClientArea();
2036 Rectangle tr
= s
.computeTrim(rr
.x
, rr
.y
, rr
.width
, rr
.height
);
2037 trim_x
= rr
.x
- tr
.x
;
2038 trim_y
= rr
.y
- tr
.y
;
2040 p
.x
+= c
.getLocation().x
+ trim_x
;
2041 p
.y
+= c
.getLocation().y
+ trim_y
;