3c2f0eb0b665f5541427d52d7436edc815ea60c2
[deliverable/tracecompass.git] / org.eclipse.linuxtools.tmf.ui / src / org / eclipse / linuxtools / tmf / ui / views / uml2sd / ScrollView.java
1 /**********************************************************************
2 * Copyright (c) 2005, 2013 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
7 *
8 * Contributors:
9 * IBM - Initial API and implementation
10 * Bernd Hufmann - Updated for TMF
11 **********************************************************************/
12
13 package org.eclipse.linuxtools.tmf.ui.views.uml2sd;
14
15 import java.util.Timer;
16 import java.util.TimerTask;
17
18 import org.eclipse.linuxtools.tmf.ui.views.uml2sd.util.Messages;
19 import org.eclipse.swt.SWT;
20 import org.eclipse.swt.events.ControlListener;
21 import org.eclipse.swt.events.FocusEvent;
22 import org.eclipse.swt.events.FocusListener;
23 import org.eclipse.swt.events.KeyEvent;
24 import org.eclipse.swt.events.KeyListener;
25 import org.eclipse.swt.events.MouseEvent;
26 import org.eclipse.swt.events.MouseListener;
27 import org.eclipse.swt.events.MouseMoveListener;
28 import org.eclipse.swt.events.MouseTrackListener;
29 import org.eclipse.swt.events.PaintEvent;
30 import org.eclipse.swt.events.PaintListener;
31 import org.eclipse.swt.events.SelectionEvent;
32 import org.eclipse.swt.events.SelectionListener;
33 import org.eclipse.swt.events.TypedEvent;
34 import org.eclipse.swt.graphics.Color;
35 import org.eclipse.swt.graphics.Cursor;
36 import org.eclipse.swt.graphics.GC;
37 import org.eclipse.swt.graphics.ImageData;
38 import org.eclipse.swt.graphics.PaletteData;
39 import org.eclipse.swt.graphics.Point;
40 import org.eclipse.swt.graphics.RGB;
41 import org.eclipse.swt.graphics.Rectangle;
42 import org.eclipse.swt.widgets.Button;
43 import org.eclipse.swt.widgets.Canvas;
44 import org.eclipse.swt.widgets.Composite;
45 import org.eclipse.swt.widgets.Control;
46 import org.eclipse.swt.widgets.Display;
47 import org.eclipse.swt.widgets.Layout;
48 import org.eclipse.swt.widgets.ScrollBar;
49 import org.eclipse.swt.widgets.Scrollable;
50 import org.eclipse.swt.widgets.Shell;
51
52 /**
53 * ScrollView widget provides a scrolling area with on-demand scroll bars.
54 * Overview scrollable panel can be used (@see setOverviewEnabled()).
55 *
56 * @author Eric Miravete
57 * @version 1.0
58 */
59 public class ScrollView extends Composite {
60
61 // ------------------------------------------------------------------------
62 // Attributes
63 // ------------------------------------------------------------------------
64
65 // Value for scroll bar mode, default is AUTO
66 /**
67 * Scroll bar mode AUTO
68 */
69 public static final int AUTO = 0;
70 /**
71 * Scroll bar mode ALWAYS_ON
72 */
73 public static final int ALWAYS_ON = 1;
74 /**
75 * Scroll bar mode ALWAYS_OFF
76 */
77 public static final int ALWAYS_OFF = 2;
78 /**
79 * Bit mask for visible vertical scroll bar
80 */
81 public static final int VBAR = 0x01;
82 /**
83 * Bit mask for visible horizontal scroll bar
84 */
85 public static final int HBAR = 0x02;
86 /**
87 * Value of the contents height property.
88 */
89 protected int fContentsHeight = 0;
90 /**
91 * Value of the contents width property.
92 */
93 protected int fContentsWidth = 0;
94 /**
95 * Value of the contents x coordinate property
96 */
97 protected int fContentsX = 0;
98 /**
99 * Value of the contents y coordinate property
100 */
101 protected int fContentsY = 0;
102 /**
103 * Scroll bar mode of horizontal scroll bar.
104 */
105 protected int fHorScrollbarMode = AUTO;
106 /**
107 * Scroll bar mode of vertical scroll bar.
108 */
109 protected int fVertScrollbarMode = AUTO;
110 /**
111 * Increment for the horizontal scroll bar.
112 */
113 protected int fHorScrollbarIncrement = 10;
114 /**
115 * Increment for the vertical scroll bar.
116 */
117 protected int fVertScrollbarIncrement = 10;
118 /**
119 * Flag whether auto scroll is enabled or not.
120 */
121 protected boolean fAutoScrollEnabled = true;
122 /**
123 * Value of the auto scroll period.
124 */
125 protected int fAutoScrollPeriod = 75;
126 /**
127 * The local paint listener reference.
128 */
129 protected PaintListener fLocalPaintListener = null;
130 /**
131 * The local mouse move listener reference.
132 */
133 protected MouseMoveListener fLocalMouseMoveListener = null;
134 /**
135 * The local mouse listener reference.
136 */
137 protected MouseListener fLocalMouseListener = null;
138 /**
139 * The local control listener reference.
140 */
141 protected ControlListener fLocalControlListener = null;
142 /**
143 * The local key listener reference.
144 */
145 protected KeyListener fLocalKeyListener = null;
146 // Canvas for vertical/horizontal Scroll Bar only ... because new ScrollBar() does works.
147 /**
148 * Canvas for horizontal scroll bar.
149 */
150 protected Canvas fHorScrollBar;
151 /**
152 * Canvas for vertical scroll bar.
153 */
154 protected Canvas fVertScrollBar;
155 /**
156 * Canvas for the view control.
157 */
158 protected Canvas fViewControl;
159 /**
160 * Control used in the bottom right corner @see setCornerControl() and @see setOverviewEnabled(true)
161 */
162 protected Control fCornerControl;
163 /**
164 * Size of overview widget.
165 */
166 protected int fOverviewSize = 100; // default size for overview
167 /**
168 * Timer for auto_scroll feature
169 */
170 protected AutoScroll fAutoScroll = null;
171 /**
172 * TimerTask for auto_scroll feature !=null when auto scroll is running
173 */
174 protected Timer fAutoScrollTimer = null;
175 /**
176 * where mouse down appear on contents area (x coordinate)
177 */
178 protected int fMouseDownX = -1;
179 /**
180 * where mouse down appear on contents area (y coordinate)
181 */
182 protected int fMousDownY = -1;
183
184
185 // ------------------------------------------------------------------------
186 // Constructors
187 // ------------------------------------------------------------------------
188
189 /**
190 * Create a ScrollView, child of composite c. Both scroll bar have the mode AUTO. Auto scroll feature is enabled
191 * using a delay of 250ms. Overview feature is not enabled by default (use setOverviewEnabled()).
192 *
193 * @param c The parent composite
194 * @param style The SWT style bits @see SWT
195 */
196 public ScrollView(Composite c, int style) {
197 this(c, style, true);
198 }
199
200 /**
201 * Create a ScrollView, child of composite c. Both scroll bar have the mode AUTO. Auto scroll feature is enabled
202 * using a delay of 250ms. Overview feature is not enabled by default (use setOverviewEnabled()).
203 *
204 * @param c The parent composite.
205 * @param style The SWT style bits @see SWT
206 * @param mouseWheel Flag to force scrollView to handles mouse wheel
207 */
208 public ScrollView(Composite c, int style, boolean mouseWheel) {
209 super(c, SWT.NONE); // style&(~(SWT.H_SCROLL|SWT.V_SCROLL)));
210
211 fHorScrollBar = new Canvas(this, SWT.H_SCROLL);
212 if (mouseWheel) {
213 // force scroll bar to get mouse wheel, those scrollbar will be hidden
214 fViewControl = new Canvas(this, style | SWT.H_SCROLL | SWT.V_SCROLL);
215 } else {
216 fViewControl = new Canvas(this, style);
217 }
218 fViewControl.setBackground(getBackground());
219 // hide scroll bar as their are replaced by fHorScrollBar and fVertScrollBar.
220 if (mouseWheel) {
221 fViewControl.getVerticalBar().setVisible(false);
222 fViewControl.getHorizontalBar().setVisible(false);
223 }
224 fVertScrollBar = new Canvas(this, SWT.V_SCROLL);
225 // make fVerScrollBar able to receive mouse wheel
226 // does not help as we can't set a MouseListener on fVerScrollBar.getVerticalBar()
227 // to set focus on viewcontrol_
228 // fVerScrollBar.addKeyListener( new KeyAdapter() {});
229
230 setLayout(new SVLayout());
231
232 fLocalPaintListener = new PaintListener() {
233 @Override
234 public void paintControl(PaintEvent event) {
235 // use clipping, to reduce cost of paint.
236 Rectangle r = event.gc.getClipping();
237 int cx = viewToContentsX(r.x);
238 int cy = viewToContentsY(r.y);
239 drawContents(event.gc, cx, cy, r.width, r.height);
240 }
241 };
242 fViewControl.addPaintListener(fLocalPaintListener);
243
244 fLocalMouseMoveListener = new MouseMoveListener() {
245 @Override
246 public void mouseMove(MouseEvent e) {
247 int ox = e.x, oy = e.y;
248 e.x = viewToContentsX(e.x);
249 e.y = viewToContentsY(e.y);
250 contentsMouseMoveEvent(e);
251 e.x = ox;
252 e.y = oy;
253 }
254 };
255
256 fViewControl.addMouseMoveListener(fLocalMouseMoveListener);
257
258 MouseTrackListener localMouseTrackListener = new MouseTrackListener() {
259 @Override
260 public void mouseEnter(MouseEvent e) {
261 int ox = e.x, oy = e.y;
262 e.x = viewToContentsX(e.x);
263 e.y = viewToContentsY(e.y);
264 contentsMouseEnter(e);
265 e.x = ox;
266 e.y = oy;
267 }
268
269 @Override
270 public void mouseHover(MouseEvent e) {
271 int ox = e.x, oy = e.y;
272 e.x = viewToContentsX(e.x);
273 e.y = viewToContentsY(e.y);
274 contentsMouseHover(e);
275 e.x = ox;
276 e.y = oy;
277 }
278
279 @Override
280 public void mouseExit(MouseEvent e) {
281 int ox = e.x, oy = e.y;
282 e.x = viewToContentsX(e.x);
283 e.y = viewToContentsY(e.y);
284 contentsMouseExit(e);
285 e.x = ox;
286 e.y = oy;
287 }
288
289 };
290
291 fViewControl.addMouseTrackListener(localMouseTrackListener);
292
293 fLocalMouseListener = new MouseListener() {
294 @Override
295 public void mouseDoubleClick(MouseEvent e) {
296 int ox = e.x, oy = e.y;
297 e.x = viewToContentsX(e.x);
298 e.y = viewToContentsY(e.y);
299 contentsMouseDoubleClickEvent(e);
300 e.x = ox;
301 e.y = oy;
302 }
303
304 @Override
305 public void mouseDown(MouseEvent e) {
306 int ox = e.x, oy = e.y;
307 e.x = fMouseDownX = viewToContentsX(e.x);
308 e.y = fMousDownY = viewToContentsY(e.y);
309 contentsMouseDownEvent(e);
310 e.x = ox;
311 e.y = oy;
312 }
313
314 @Override
315 public void mouseUp(MouseEvent e) {
316 int ox = e.x, oy = e.y;
317 e.x = viewToContentsX(e.x);
318 e.y = viewToContentsY(e.y);
319 contentsMouseUpEvent(e);
320 e.x = ox;
321 e.y = oy;
322 // here because class extenting me can catch mouse Up and want to scroll...
323 fMouseDownX = fMousDownY = -1;
324 }
325 };
326 fViewControl.addMouseListener(fLocalMouseListener);
327
328 fLocalKeyListener = new KeyListener() {
329 @Override
330 public void keyPressed(KeyEvent e) {
331 keyPressedEvent(e);
332 }
333
334 @Override
335 public void keyReleased(KeyEvent e) {
336 keyReleasedEvent(e);
337 }
338 };
339
340 fViewControl.addKeyListener(fLocalKeyListener);
341
342 getVerticalBar().addSelectionListener(new SelectionListener() {
343 @Override
344 public void widgetSelected(SelectionEvent e) {
345 setContentsPos(fContentsX, getVerticalBar().getSelection());
346 // need to change "hidden" vertical bar value ?
347 // force focus on fViewControl so we got future mouse wheel's scroll events
348 if (!fViewControl.isFocusControl()) {
349 fViewControl.setFocus();
350 }
351 }
352
353 @Override
354 public void widgetDefaultSelected(SelectionEvent e) {
355 }
356 });
357
358 if (fViewControl.getVerticalBar() != null) {
359 // add fViewControl hidden scrollbar listener to get mouse wheel ...
360 fViewControl.getVerticalBar().addSelectionListener(new SelectionListener() {
361 @Override
362 public void widgetSelected(SelectionEvent e) {
363 ScrollBar b = fViewControl.getVerticalBar();
364 setContentsPos(fContentsX, b.getSelection());
365 // change "real" vertical bar selection too
366 getVerticalBar().setSelection(b.getSelection());
367 }
368
369 @Override
370 public void widgetDefaultSelected(SelectionEvent e) {
371 }
372 });
373 }
374 getHorizontalBar().addSelectionListener(new SelectionListener() {
375 @Override
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();
382 }
383 }
384
385 @Override
386 public void widgetDefaultSelected(SelectionEvent e) {
387 }
388 });
389 if (fViewControl.getHorizontalBar() != null) {
390 fViewControl.getHorizontalBar().addSelectionListener(new SelectionListener() {
391 @Override
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());
397 }
398
399 @Override
400 public void widgetDefaultSelected(SelectionEvent e) {
401 }
402 });
403 }
404 }
405
406 // ------------------------------------------------------------------------
407 // Methods
408 // ------------------------------------------------------------------------
409
410 @Override
411 public boolean setFocus() {
412 return fViewControl.forceFocus();
413 }
414
415 @Override
416 public void setCursor(Cursor cursor) {
417 fViewControl.setCursor(cursor);
418 }
419
420 @Override
421 public void dispose() {
422 if (fAutoScroll != null) {
423 fAutoScroll.cancel();
424 fAutoScroll = null;
425 }
426 if (fViewControl != null) {
427 fViewControl.dispose();
428 }
429 fViewControl = null;
430 if (fVertScrollBar != null) {
431 fVertScrollBar.dispose();
432 }
433 fVertScrollBar = null;
434 if (fHorScrollBar != null) {
435 fHorScrollBar.dispose();
436 }
437 fHorScrollBar = null;
438 if (fCornerControl != null) {
439 Object data = fCornerControl.getData();
440 if (data instanceof Overview) {
441 ((Overview) data).dispose();
442 }
443 fCornerControl.dispose();
444 fCornerControl = null;
445 }
446 super.dispose();
447 }
448
449 @Override
450 public Rectangle getClientArea() {
451 return fViewControl.getClientArea();
452 }
453
454 @Override
455 public void setBackground(Color c) {
456 super.setBackground(c);
457 fViewControl.setBackground(c);
458 }
459
460 @Override
461 public void setToolTipText(String text) {
462 fViewControl.setToolTipText(text);
463 }
464
465 /**
466 * Draw overview area, @see setOverviewEnabled. By default draw a rectangle corresponding to the visible area of
467 * scroll view. You can redefine this method to draw the contents as drawContents does... ...in an other magnify
468 * factor.
469 *
470 * @param gc GC to used to draw.
471 * @param r Rectangle corresponding to the client area of overview.
472 */
473 protected void drawOverview(GC gc, Rectangle r) {
474 int x = (int) (r.width * fContentsX / (float) fContentsWidth);
475 int y = (int) (r.height * fContentsY / (float) fContentsHeight);
476 int vw = getVisibleWidth();
477 int vh = getVisibleHeight();
478 int w = r.width - 1;
479 if (fContentsWidth > vw) {
480 w = (int) (r.width * vw / (float) fContentsWidth);
481 }
482 int h = r.height - 1;
483 if (fContentsHeight > vh) {
484 h = (int) (r.height * vh / (float) fContentsHeight);
485 }
486
487 gc.setForeground(getForeground());
488 // too small rectangle ?
489 if (w < 5 || h < 5) {
490 // use a cross ...
491 gc.drawLine(x, 0, x, r.height);
492 gc.drawLine(0, y, r.width, y);
493 } else {
494 gc.drawRectangle(x, y, w, h);
495 }
496 }
497
498 /**
499 * Remove the local Listener and add the new listener.
500 *
501 * @param nlistener the new listener
502 */
503 public void replaceControlListener(ControlListener nlistener) {
504 if (fLocalControlListener != null) {
505 removeControlListener(fLocalControlListener);
506 fLocalControlListener = null;
507 }
508 addControlListener(nlistener);
509 }
510
511 /**
512 * Remove the local Listener and add the new listener.
513 *
514 * @param nlistener the new listener
515 */
516 public void replaceKeyListener(KeyListener nlistener) {
517 if (fLocalKeyListener != null) {
518 removeKeyListener(fLocalKeyListener);
519 fLocalKeyListener = null;
520 }
521 addKeyListener(nlistener);
522 }
523
524 /**
525 * Remove the local Listener and add the new listener.
526 *
527 * @param nlistener the new listener
528 */
529 public void replaceMouseListener(MouseListener nlistener) {
530 if (fLocalMouseListener != null) {
531 removeMouseListener(fLocalMouseListener);
532 fLocalMouseListener = null;
533 }
534 fViewControl.addMouseListener(nlistener);
535 }
536
537 /**
538 * Remove the local Listener and add the new listener.
539 *
540 * @param nlistener the new listener
541 */
542 public void replaceMouseMoveListener(MouseMoveListener nlistener) {
543 if (fLocalMouseMoveListener != null) {
544 removeMouseMoveListener(fLocalMouseMoveListener);
545 fLocalMouseMoveListener = null;
546 }
547 fViewControl.addMouseMoveListener(nlistener);
548 }
549
550 /**
551 * Remove the local Listener and add the new listener.
552 *
553 * @param nlistener the new listener
554 */
555 public void replacePaintListener(PaintListener nlistener) {
556 if (fLocalPaintListener != null) {
557 removePaintListener(fLocalPaintListener);
558 fLocalPaintListener = null;
559 }
560 fViewControl.addPaintListener(nlistener);
561 }
562
563 /**
564 * Access method for the contentsHeight property.
565 *
566 * @return the current value of the contentsHeight property
567 */
568 public int getContentsHeight() {
569 return fContentsHeight;
570 }
571
572 /**
573 * Access method for the contentsWidth property.
574 *
575 * @return the current value of the contentsWidth property
576 */
577 public int getContentsWidth() {
578 return fContentsWidth;
579 }
580
581 /**
582 * Access method for the contentsX property.
583 *
584 * @return the current value of the contentsX property
585 */
586 public int getContentsX() {
587 return fContentsX;
588 }
589
590 /**
591 * Access method for the contentsY property.
592 *
593 * @return the current value of the contentsY property
594 */
595 public int getContentsY() {
596 return fContentsY;
597 }
598
599 /**
600 * Determines if the dragAutoScroll property is true.
601 *
602 * @return <code>true<code> if the dragAutoScroll property is true
603 */
604 public boolean isDragAutoScroll() {
605 return fAutoScrollEnabled;
606 }
607
608 /**
609 * Sets the value of the dragAutoScroll property.
610 *
611 * @param aDragAutoScroll the new value of the dragAutoScroll property
612 */
613 public void setDragAutoScroll(boolean aDragAutoScroll) {
614 fAutoScrollEnabled = aDragAutoScroll;
615 if (!fAutoScrollEnabled && (fAutoScroll != null)) {
616 fAutoScroll.cancel();
617 fAutoScroll = null;
618 }
619 }
620
621 /**
622 * Change delay (in millisec) used for auto scroll feature.
623 *
624 * @param period new period between to auto scroll
625 */
626 public void setDragAutoScrollPeriod(int period) {
627 fAutoScrollPeriod = Math.max(0, period);
628 }
629
630 /**
631 * Return auto scroll period.
632 *
633 * @return The period
634 */
635 public int getDragAutoScrollPeriod() {
636 return fAutoScrollPeriod;
637 }
638
639 /**
640 * Access method for the hScrollBarMode property.
641 *
642 * @return the current value of the hScrollBarMode property
643 */
644 public int getHScrollBarMode() {
645 return fHorScrollbarMode;
646 }
647
648 /**
649 * Sets the value of the hScrollBarMode property.
650 *
651 * @param aHScrollBarMode the new value of the hScrollBarMode property
652 */
653 public void setHScrollBarMode(int aHScrollBarMode) {
654 fHorScrollbarMode = aHScrollBarMode;
655 }
656
657 /**
658 * Access method for the vScrollBarMode property.
659 *
660 * @return the current value of the vScrollBarMode property
661 */
662 public int getVScrollBarMode() {
663 return fVertScrollbarMode;
664 }
665
666 /**
667 * Sets the value of the vScrollBarMode property.
668 *
669 * @param aVScrollBarMode the new value of the vScrollBarMode property
670 */
671 public void setVScrollBarMode(int aVScrollBarMode) {
672 fVertScrollbarMode = aVScrollBarMode;
673 }
674
675 /**
676 * Return horizontal scroll bar increment, default:1
677 *
678 * @return The increment
679 */
680 public int getHScrollBarIncrement() {
681 return fHorScrollbarIncrement;
682 }
683
684 /**
685 * Return vertical scroll bar increment, default:1
686 *
687 * @return The increment
688 */
689 public int getVScrollBarIncrement() {
690 return fVertScrollbarIncrement;
691 }
692
693 /**
694 * Change horizontal scroll bar increment, minimum:1. Page increment is
695 * always set to visible width.
696 *
697 * @param inc
698 * Increment value to set
699 */
700 public void setHScrollBarIncrement(int inc) {
701 fHorScrollbarIncrement = Math.max(1, inc);
702 }
703
704 /**
705 * Change vertical scroll bar increment, minimum:1. Page increment is always
706 * set to visible height.
707 *
708 * @param inc
709 * Increment value to set
710 */
711 public void setVScrollBarIncrement(int inc) {
712 fVertScrollbarIncrement = Math.max(1, inc);
713 }
714
715 /**
716 * Enable or disable overview feature. Enabling overview, dispose and replace existing corner control by a button.
717 * Clicking in it open overview, move mouse cursor holding button to move scroll view and release button to hide
718 * overview. Tip: hold control and/or shift key while moving mouse when overview is open made fine scroll.
719 *
720 * @param value true to engage overview feature
721 */
722 public void setOverviewEnabled(boolean value) {
723 if (isOverviewEnabled() == value) {
724 return;
725 }
726
727 Control cc = null;
728 if (value) {
729 Button b = new Button(this, SWT.NONE);
730 b.setText("+"); //$NON-NLS-1$
731 Overview ovr = new Overview();
732 ovr.useControl(b);
733 b.setData(ovr);
734 cc = b;
735 b.setToolTipText(Messages.SequenceDiagram_OpenOverviewTooltip);
736 }
737 setCornerControl(cc);
738 }
739
740 /**
741 * Change overview size (at ratio 1:1), default is 100
742 *
743 * @param size
744 * The new size
745 */
746 public void setOverviewSize(int size) {
747 fOverviewSize = Math.abs(size);
748 }
749
750 /**
751 * Returns whether the overview is enabled or not.
752 *
753 * @return true is overview feature is enabled
754 */
755 public boolean isOverviewEnabled() {
756 if (fCornerControl instanceof Button) {
757 Object data = ((Button) fCornerControl).getData();
758 // overview alreay
759 if (data instanceof Overview) {
760 return true;
761 }
762 }
763 return false;
764 }
765
766 /**
767 * Returns the overview size at ratio 1:1.
768 *
769 * @return current overview size at ratio 1:1
770 */
771 public int getOverviewSize() {
772 return fOverviewSize;
773 }
774
775 /**
776 * Returns control used to display view (might not be this object). Use this control to add/remove listener on the
777 * draw area.
778 *
779 * @return control used to display view (might not be this object).
780 */
781 public Control getViewControl() {
782 return fViewControl;
783 }
784
785 /**
786 * Called when the mouse enter the ScrollView area
787 *
788 * @param e
789 * Mouse event
790 */
791 protected void contentsMouseExit(MouseEvent e) {
792 }
793
794 /**
795 * Called when the mouse enter the ScrollView area after and system defined
796 * time
797 *
798 * @param e
799 * Mouse event
800 */
801 protected void contentsMouseHover(MouseEvent e) {
802 }
803
804 /**
805 * Called when the mouse enter the ScrollView area
806 *
807 * @param e
808 * Mouse event
809 */
810 protected void contentsMouseEnter(MouseEvent e) {
811 }
812
813 /**
814 * Called when user double on contents area.
815 *
816 * @param e
817 * Mouse event
818 */
819 protected void contentsMouseDoubleClickEvent(MouseEvent e) {
820 }
821
822 /**
823 * Called when mouse is on contents area and button is pressed.
824 *
825 * @param e
826 * Mouse event
827 */
828 protected void contentsMouseDownEvent(MouseEvent e) {
829 fMouseDownX = e.x;
830 fMousDownY = e.y;
831 }
832
833 /**
834 * TimerTask for auto scroll feature.
835 */
836 protected static class AutoScroll extends TimerTask {
837
838 /** X delta */
839 public int deltaX;
840
841 /** Y delta */
842 public int deltaY;
843
844 /** ScrollView object */
845 public ScrollView scrollView;
846
847 /**
848 * Constructor.
849 *
850 * @param sv
851 * ScrollView object to use
852 * @param dx
853 * X delta
854 * @param dy
855 * Y delta
856 */
857 public AutoScroll(ScrollView sv, int dx, int dy) {
858 scrollView = sv;
859 deltaX = dx;
860 deltaY = dy;
861 }
862
863 @Override
864 public void run() {
865 Display.getDefault().asyncExec(new Runnable() {
866 @Override
867 public void run() {
868 scrollView.scrollBy(deltaX, deltaY);
869 }
870 });
871 }
872 }
873
874 /**
875 * Called when mouse is on contents area and mode.
876 *
877 * @param event
878 * Mouse event
879 */
880 protected void contentsMouseMoveEvent(MouseEvent event) {
881 if ((event.stateMask & SWT.BUTTON_MASK) != 0) {
882 if (!fAutoScrollEnabled) {
883 scrollBy(-(event.x - fMouseDownX), -(event.y - fMousDownY));
884 return;
885 }
886
887 int sx = 0, sy = 0;
888
889 int v_right = getContentsX() + getVisibleWidth();
890 int v_bottom = getContentsY() + getVisibleHeight();
891
892 // auto scroll... ?
893 if (event.x < getContentsX()) {
894 sx = (getContentsX() - event.x);
895 fMouseDownX = getContentsX();
896 } else if (event.x > v_right) {
897 sx = -event.x + v_right;
898 fMouseDownX = v_right;
899 }
900 if (event.y < getContentsY()) {
901 sy = (getContentsY() - event.y);
902 fMousDownY = getContentsY();
903 } else if (event.y > v_bottom) {
904 sy = -event.y + v_bottom;
905 fMousDownY = v_bottom;
906 }
907
908 if (sx != 0 || sy != 0) {
909 // start auto scroll...
910 if (fAutoScroll == null) {
911 if (fAutoScrollTimer == null) {
912 fAutoScrollTimer = new Timer(true);
913 }
914 fAutoScroll = new AutoScroll(this, sx, sy);
915 fAutoScrollTimer.schedule(fAutoScroll, 0, fAutoScrollPeriod);
916 } else {
917 fAutoScroll.deltaX = sx;
918 fAutoScroll.deltaY = sy;
919 }
920 } else {
921 if (fAutoScroll != null) {
922 fAutoScroll.cancel();
923 fAutoScroll = null;
924 }
925
926 scrollBy(-(event.x - fMouseDownX), -(event.y - fMousDownY));
927 }
928 }
929 }
930
931 /**
932 * Called when mouse is on contents area and button is released
933 *
934 * @param event
935 * Mouse event
936 */
937 protected void contentsMouseUpEvent(MouseEvent event) {
938 // reset auto scroll if it's engaged
939 if (fAutoScroll != null) {
940 fAutoScroll.cancel();
941 fAutoScroll = null;
942 }
943 }
944
945 /**
946 * Responsible to draw contents area. At least rectangle clipX must be
947 * redrawn. This rectangle is given in contents coordinates. By default, no
948 * paint is produced.
949 *
950 * @param gc
951 * Graphics context
952 * @param clipx
953 * X clip
954 * @param clipy
955 * Y clip
956 * @param clipw
957 * W clip
958 * @param cliph
959 * H clip
960 */
961 protected void drawContents(GC gc, int clipx, int clipy, int clipw, int cliph) {
962 }
963
964 /**
965 * Change the size of the contents area.
966 *
967 * @param width new width of the area.
968 * @param height new height of the area.
969 */
970 public void resizeContents(int width, int height) {
971 int localWidth = width;
972 int localHeight = height;
973
974 if (localWidth < 0) {
975 localWidth = 0;
976 }
977 if (localHeight < 0) {
978 localHeight = 0;
979 }
980
981 int oldW = fContentsWidth;
982 int oldH = fContentsHeight;
983
984 if (localWidth == oldW && localHeight == oldH) {
985 return;
986 }
987
988 fContentsWidth = localWidth;
989 fContentsHeight = localHeight;
990
991 if (oldW > localWidth) {
992 int s = localWidth;
993 localWidth = oldW;
994 oldW = s;
995 }
996
997 int vis_width = getVisibleWidth();
998 int vis_height = getVisibleHeight();
999 if (oldW < vis_width) {
1000 if (localWidth > vis_width) {
1001 localWidth = vis_width;
1002 }
1003 fViewControl.redraw(getContentsX() + oldW, 0, localWidth - oldW, vis_height, true);
1004 }
1005
1006 if (oldH > localHeight) {
1007 int s = localHeight;
1008 localHeight = oldH;
1009 oldH = s;
1010 }
1011
1012 if (oldH < vis_height) {
1013 if (localHeight > vis_height) {
1014 localHeight = vis_height;
1015 }
1016 fViewControl.redraw(0, getContentsY() + oldH, vis_width, localHeight - oldH, true);
1017 }
1018 if (updateScrollBarVisiblity()) {
1019 layout();
1020 } else {
1021 updateScrollBarsValues();
1022 }
1023 }
1024
1025 // redefined for internal use ..
1026 @Override
1027 public void redraw() {
1028 super.redraw();
1029 // ..need to redraw this already:
1030 fViewControl.redraw();
1031 }
1032
1033 /**
1034 * @param delataX The delta in X
1035 * @param deltaY the delta in Y
1036 */
1037 public void scrollBy(int delataX, int deltaY) {
1038 setContentsPos(getContentsX() + delataX, getContentsY() + deltaY);
1039 }
1040
1041 /**
1042 * Scroll to ensure point(in contents coordinates) is visible.
1043 *
1044 * @param px Point's x position
1045 * @param py Point's y position
1046 */
1047 public void ensureVisible(int px, int py) {
1048 int cx = getContentsX(), cy = getContentsY();
1049 int right = getContentsX() + getVisibleWidth();
1050 int bottom = getContentsY() + getVisibleHeight();
1051 if (px < getContentsX()) {
1052 cx = px;
1053 } else if (px > right) {
1054 cx = px - getVisibleWidth();
1055 }
1056 if (py < getContentsY()) {
1057 cy = py;
1058 } else if (py > bottom) {
1059 cy = py - getVisibleHeight();
1060 }
1061 setContentsPos(cx, cy);
1062 }
1063
1064 /**
1065 * Make rectangle (x,y,w,h, in contents coordinates) visible. if rectangle cannot be completely visible, use
1066 * align flags.
1067 *
1068 * @param xValue x contents coordinates of rectangle.
1069 * @param yValue y contents coordinates of rectangle.
1070 * @param width width of rectangle.
1071 * @param height height of rectangle.
1072 * @param align bit or'ed SWT flag like SWT.LEFT,RIGHT,CENTER,TOP,BOTTOM,VERTICAL used only for bigger rectangle
1073 * than visible area. By default CENTER/VERTICAL
1074 */
1075 public void ensureVisible(int xValue, int yValue, int width, int height, int align) {
1076 ensureVisible(xValue, yValue, width, height, align, false);
1077 }
1078
1079 /**
1080 * Make rectangle (xValue,yValue,width,height, in contents coordinates) visible. if rectangle cannot be completely visible, use
1081 * align flags.
1082 *
1083 * @param xValue x contents coordinates of rectangle.
1084 * @param yValue y contents coordinates of rectangle.
1085 * @param width width of rectangle.
1086 * @param height height of rectangle.
1087 * @param align bit or'ed SWT flag like SWT.LEFT,RIGHT,CENTER,TOP,BOTTOM,VERTICAL used only for bigger rectangle
1088 * than visible area. By default CENTER/VERTICAL
1089 * @param forceAlign force alignment for rectangle smaller than the visible area
1090 */
1091 protected void ensureVisible(int xValue, int yValue, int width, int height, int align, boolean forceAlign) {
1092
1093 int localX = xValue;
1094 int localY = yValue;
1095 int localWidth = width;
1096 int localHeight = height;
1097
1098 if (localWidth < 0) {
1099 localX = localX + localWidth;
1100 localWidth = -localWidth;
1101 }
1102 if (localHeight < 0) {
1103 localY = localY + localHeight;
1104 localHeight = -localHeight;
1105 }
1106 int hbar = getHorizontalBarHeight();
1107 int vbar = getVerticalBarWidth();
1108 int cx = getContentsX();
1109 int cy = getContentsY();
1110 int right = getContentsX() + getVisibleWidth() - vbar;
1111 int bottom = getContentsY() + getVisibleHeight() - hbar;
1112 boolean align_h = false, align_v = false;
1113
1114 if (localX < getContentsX()) {
1115 cx = localX;
1116 } else if (localX + localWidth > right) {
1117 cx = localX - localWidth;
1118 }
1119 if (localY < getContentsY()) {
1120 cy = localY;
1121 } else if (localY + localHeight > bottom) {
1122 cy = localY - localHeight;
1123 }
1124
1125 if (localWidth > getVisibleWidth()) {
1126 align_h = true;
1127 }
1128 if (localHeight > getVisibleHeight()) {
1129 align_v = true;
1130 }
1131 // compute alignment on visible area horizontally
1132 if (align_h || (forceAlign && localX + localWidth > right)) {
1133 // use align flags
1134 if ((align & SWT.LEFT) != 0) {
1135 cx = localX;
1136 } else if ((align & SWT.RIGHT) != 0) {
1137 cx = right - localWidth;
1138 } else { // center
1139 cx = localX + (localWidth - getVisibleWidth()) / 2;
1140 }
1141 }
1142 // compute alignment on visible area vertically
1143 if (align_v || (forceAlign && localY + localHeight > bottom)) {
1144 // use align flags
1145 if ((align & SWT.TOP) != 0) {
1146 cy = localY;
1147 } else if ((align & SWT.BOTTOM) != 0) {
1148 cy = bottom - localHeight;
1149 } else { // center
1150 cy = localY + (localHeight - getVisibleHeight()) / 2;
1151 }
1152 }
1153 setContentsPos(cx, cy);
1154 }
1155
1156 /**
1157 * Returns true if point is visible (expressed in contents coordinates).
1158 *
1159 * @param px Point's x position
1160 * @param py Point's y position
1161 * @return true if point is visible (expressed in contents coordinates)
1162 */
1163 public boolean isVisible(int px, int py) {
1164 if (px < getContentsX()) {
1165 return false;
1166 }
1167 if (py < getContentsY()) {
1168 return false;
1169 }
1170 if (px > (getContentsX() + getVisibleWidth())) {
1171 return false;
1172 }
1173 if (py > (getContentsY() + getVisibleHeight())) {
1174 return false;
1175 }
1176 return true;
1177 }
1178
1179 /**
1180 * Returns true if rectangle if partially visible.
1181 *
1182 * @param xValue x contents coordinates of rectangle.
1183 * @param yValue y contents coordinates of rectangle.
1184 * @param width width of rectangle.
1185 * @param height height of rectangle.
1186 * @return true if rectangle if partially visible.
1187 */
1188 public boolean isVisible(int xValue, int yValue, int width, int height) {
1189 if (xValue + width < getContentsX()) {
1190 return false;
1191 }
1192 if (yValue + height < getContentsY()) {
1193 return false;
1194 }
1195 int vr = getContentsX() + getVisibleWidth();
1196 int vb = getContentsY() + getVisibleHeight();
1197 if (xValue > vr) {
1198 return false;
1199 }
1200 if (yValue > vb) {
1201 return false;
1202 }
1203 return true;
1204 }
1205
1206 /**
1207 * Returns visible part of rectangle, or null if rectangle is not visible.
1208 * Rectangle is expressed in contents coordinates.
1209 *
1210 * @param xValue
1211 * x contents coordinates of rectangle.
1212 * @param yValue
1213 * y contents coordinates of rectangle.
1214 * @param width
1215 * width of rectangle.
1216 * @param height
1217 * height of rectangle.
1218 * @return visible part of rectangle, or null if rectangle is not visible.
1219 */
1220 public Rectangle getVisiblePart(int xValue, int yValue, int width, int height) {
1221 if (xValue + width < getContentsX()) {
1222 return null;
1223 }
1224 if (yValue + height < getContentsY()) {
1225 return null;
1226 }
1227 int vr = getContentsX() + getVisibleWidth();
1228 int vb = getContentsY() + getVisibleHeight();
1229 if (xValue > vr) {
1230 return null;
1231 }
1232 if (yValue > vb) {
1233 return null;
1234 }
1235 int rr = xValue + width, rb = yValue + height;
1236 int nl = Math.max(xValue, getContentsX()), nt = Math.max(yValue, getContentsY()), nr = Math.min(rr, vr), nb = Math.min(rb, vb);
1237 return new Rectangle(nl, nt, nr - nl, nb - nt);
1238 }
1239
1240 /**
1241 * Returns the visible part for given rectangle.
1242 *
1243 * @param rect A rectangle
1244 *
1245 * @return gets visible part of rectangle (or <code>null</code>)
1246 */
1247 public final Rectangle getVisiblePart(Rectangle rect) {
1248 if (rect == null) {
1249 return null;
1250 }
1251 return getVisiblePart(rect.x, rect.y, rect.width, rect.height);
1252 }
1253
1254 /**
1255 * Change top left position of visible area. Check if the given point is inside contents area.
1256 *
1257 * @param xValue x contents coordinates of visible area.
1258 * @param yValue y contents coordinates of visible area.
1259 * @return true if view really moves
1260 */
1261 public boolean setContentsPos(int xValue, int yValue) {
1262 int nx = xValue, ny = yValue;
1263 if (getVisibleWidth() >= getContentsWidth()) {
1264 nx = 0;
1265 } else {
1266 if (xValue < 0) {
1267 nx = 0;
1268 } else if (xValue + getVisibleWidth() > getContentsWidth()) {
1269 nx = getContentsWidth() - getVisibleWidth();
1270 }
1271 }
1272 if (getVisibleHeight() >= getContentsHeight()) {
1273 ny = 0;
1274 } else {
1275 if (yValue <= 0) {
1276 ny = 0;
1277 } else if (yValue + getVisibleHeight() > getContentsHeight()) {
1278 ny = getContentsHeight() - getVisibleHeight();
1279 }
1280 }
1281 // no move
1282 if (nx == fContentsX && ny == fContentsY) {
1283 return false;
1284 }
1285 fContentsX = nx;
1286 fContentsY = ny;
1287 updateScrollBarsValues();
1288 // ? find smallest area to redraw only them ?
1289 fViewControl.redraw();
1290 return true;
1291 }
1292
1293 @Override
1294 public ScrollBar getVerticalBar() {
1295 return fVertScrollBar.getVerticalBar();
1296 }
1297
1298 @Override
1299 public ScrollBar getHorizontalBar() {
1300 return fHorScrollBar.getHorizontalBar();
1301 }
1302
1303 /**
1304 * Compute visibility of vertical/horizontal bar using given width/height and current visibility (i.e. is bar size are already in
1305 * for_xxx)
1306 * @param forWidth width of foreground
1307 * @param forHeight height of foreground
1308 * @param currHorVis The current visibility state of horizontal scroll bar
1309 * @param currVertvis The current visibility state of vertical scroll bar
1310 * @return <code>true</code> if visibility changed else <code>false</code>
1311 */
1312 public int computeBarVisibility(int forWidth, int forHeight, boolean currHorVis, boolean currVertvis) {
1313
1314 int localForWidth = forWidth;
1315 int vis = 0x00;
1316 switch (fVertScrollbarMode) {
1317 case ALWAYS_OFF:
1318 break;
1319 case ALWAYS_ON:
1320 vis |= VBAR;
1321 break;
1322 case AUTO:
1323 if (getContentsHeight() > forHeight) {
1324 vis = VBAR;
1325 // v bar size is already in for_width.
1326 if (!currVertvis) {// (curr_vis&0x01)==0)
1327 localForWidth -= getVerticalBarWidth();
1328 }
1329 }
1330 break;
1331 default:
1332 break;
1333 }
1334
1335 switch (fHorScrollbarMode) {
1336 case ALWAYS_OFF:
1337 break;
1338 case ALWAYS_ON:
1339 vis |= HBAR;
1340 break;
1341 case AUTO:
1342 if (getContentsWidth() > localForWidth) {
1343 vis |= HBAR;
1344 // h bar is not in for_height
1345 if ((!currHorVis) && (getContentsHeight() > (forHeight - getHorizontalBarHeight()))) {// (curr_vis&0x02)==0 )
1346 vis |= VBAR;
1347 }
1348 }
1349 break;
1350 default:
1351 break;
1352 }
1353 return vis;
1354 }
1355
1356 /**
1357 * Setup scroll bars visibility.
1358 *
1359 * @return True if one of visibility changed.
1360 */
1361 protected boolean updateScrollBarVisiblity() {
1362 boolean change = false;
1363
1364 boolean currVertVis = fVertScrollBar.getVisible();
1365 boolean currHorVis = fHorScrollBar.getVisible();
1366 int barNewVis = computeBarVisibility(getVisibleWidth(), getVisibleHeight(), currHorVis, currVertVis);
1367 boolean newVertVis = (barNewVis & VBAR) != 0;
1368 boolean newHorVis = (barNewVis & HBAR) != 0;
1369 if (currVertVis ^ newVertVis) { // vertsb_.getVisible() )
1370 fVertScrollBar.setVisible(newVertVis);
1371 change = true;
1372 }
1373 if (currHorVis ^ newHorVis) {
1374 fHorScrollBar.setVisible(newHorVis);
1375 change = true;
1376 }
1377
1378 // update corner control visibility:
1379 if (fCornerControl != null && change) {
1380 boolean vis = newVertVis || newHorVis;
1381 if (vis ^ fCornerControl.getVisible()) {
1382 fCornerControl.setVisible(vis);
1383 change = true; // but must be already the case
1384 }
1385 }
1386 return change;
1387 }
1388
1389 /**
1390 * Setup scroll bar using contents, visible and scroll bar mode properties.
1391 */
1392 protected void updateScrollBarsValues() {
1393 /* update vertical scrollbar */
1394 ScrollBar b = getVerticalBar();
1395 if (b != null) {
1396 b.setMinimum(0);
1397 b.setMaximum(getContentsHeight());
1398 b.setThumb(getVisibleHeight());
1399 b.setPageIncrement(getVisibleHeight());
1400 b.setIncrement(fVertScrollbarIncrement);
1401 b.setSelection(getContentsY());
1402 }
1403
1404 // update "hidden" vertical bar too
1405 b = fViewControl.getVerticalBar();
1406 if (b != null) {
1407 b.setMinimum(0);
1408 b.setMaximum(getContentsHeight());
1409 b.setThumb(getVisibleHeight());
1410 b.setPageIncrement(getVisibleHeight());
1411 b.setIncrement(fVertScrollbarIncrement);
1412 b.setSelection(getContentsY());
1413 }
1414
1415 /* update horizontal scrollbar */
1416 b = getHorizontalBar();
1417 if (b != null) {
1418 b.setMinimum(0);
1419 b.setMaximum(getContentsWidth());
1420 b.setThumb(getVisibleWidth());
1421 b.setSelection(getContentsX());
1422 b.setPageIncrement(getVisibleWidth());
1423 b.setIncrement(fHorScrollbarIncrement);
1424 }
1425 // update "hidden" horizontal bar too
1426 b = fViewControl.getHorizontalBar();
1427 if (b != null) {
1428 b.setMinimum(0);
1429 b.setMaximum(getContentsWidth());
1430 b.setThumb(getVisibleWidth());
1431 b.setSelection(getContentsX());
1432 b.setPageIncrement(getVisibleWidth());
1433 b.setIncrement(fHorScrollbarIncrement);
1434 }
1435 }
1436
1437 /**
1438 * Change the control used in the bottom right corner (between two scrollbar), if control is null reset previous
1439 * corner control. This control is visible only if at least one scrollbar is visible. Given control will be disposed
1440 * by ScrollView, at dispose() time, at next setCornetControl() call or when calling setOverviewEnabled(). Pay
1441 * attention calling this reset overview feature until setOverviewEnabled(true) if called.
1442 * @param control The control for the overview
1443 */
1444 public void setCornerControl(Control control) {
1445 if (fCornerControl != null) {
1446 fCornerControl.dispose();
1447 }
1448 fCornerControl = control;
1449 if (fCornerControl != null) {
1450 ScrollBar vb = getVerticalBar();
1451 ScrollBar hb = getHorizontalBar();
1452 boolean vis = vb.getVisible() || hb.getVisible();
1453 fCornerControl.setVisible(vis);
1454 }
1455 }
1456
1457 /**
1458 * Transform (x,y) point in widget coordinates to contents coordinates.
1459 *
1460 * @param x The x widget coordinate.
1461 * @param y The y widget coordinate.
1462 * @return org.eclipse.swt.graphics.Point with content coordinates.
1463 */
1464 public final Point viewToContents(int x, int y) {
1465 return new Point(viewToContentsX(x), viewToContentsY(y));
1466 }
1467
1468 /**
1469 * Transform x in widget coordinates to contents coordinates
1470 *
1471 * @param x The y widget coordinate.
1472 * @return the x content coordinate.
1473 */
1474 public int viewToContentsX(int x) {
1475 return fContentsX + x;
1476 }
1477
1478 /**
1479 * Transform y in widget coordinates to contents coordinates
1480 *
1481 * @param y The y widget coordinate.
1482 * @return the y content coordinate.
1483 */
1484 public int viewToContentsY(int y) {
1485 return fContentsY + y;
1486 }
1487
1488 /**
1489 * Transform (x,y) point from contents coordinates, to widget coordinates.
1490 *
1491 * @param x The x content coordinate.
1492 * @param y The y content coordinate.
1493 * @return coordinates widget area as.
1494 */
1495 public final Point contentsToView(int x, int y) {
1496 return new Point(contentsToViewX(x), contentsToViewY(y));
1497 }
1498
1499 /**
1500 * Transform X axis coordinates from contents to widgets.
1501 *
1502 * @param x contents coordinate to transform.
1503 * @return x coordinate in widget area
1504 */
1505 public int contentsToViewX(int x) {
1506 return x - fContentsX;
1507 }
1508
1509 /**
1510 * Transform Y axis coordinates from contents to widgets.
1511 *
1512 * @param y contents coordinate to transform
1513 * @return y coordinate in widget area
1514 */
1515 public int contentsToViewY(int y) {
1516 return y - fContentsY;
1517 }
1518
1519 /**
1520 * Return the visible height of scroll view, might be > contentsHeight
1521 *
1522 * @return the visible height of scroll view, might be > contentsHeight()
1523 */
1524 public int getVisibleHeight() {
1525 return fViewControl.getClientArea().height;
1526 }
1527
1528 /**
1529 * Return int the visible width of scroll view, might be > contentsWidth().
1530 *
1531 * @return int the visible width of scroll view, might be > contentsWidth()
1532 */
1533 public int getVisibleWidth() {
1534 return fViewControl.getClientArea().width;
1535 }
1536
1537 /**
1538 * Add support for arrow key, scroll the ... scroll view. But you can
1539 * redefine this method for your convenience.
1540 *
1541 * @param event
1542 * Keyboard event
1543 */
1544 protected void keyPressedEvent(KeyEvent event) {
1545 switch (event.keyCode) {
1546 case SWT.ARROW_UP:
1547 scrollBy(0, -getVisibleHeight());
1548 break;
1549 case SWT.ARROW_DOWN:
1550 scrollBy(0, +getVisibleHeight());
1551 break;
1552 case SWT.ARROW_LEFT:
1553 scrollBy(-getVisibleWidth(), 0);
1554 break;
1555 case SWT.ARROW_RIGHT:
1556 scrollBy(+getVisibleWidth(), 0);
1557 break;
1558 default:
1559 break;
1560 }
1561 }
1562
1563 /**
1564 * Redefine this method at your convenience
1565 *
1566 * @param event The key event.
1567 */
1568 protected void keyReleasedEvent(KeyEvent event) {
1569 }
1570
1571 /**
1572 * Returns vertical bar width, even if bar isn't visible.
1573 *
1574 * @return vertical bar width, even if bar isn't visible
1575 */
1576 public int getVerticalBarWidth() {
1577 // include vertical bar width and trimming of scrollable used
1578 int bw = fVertScrollBar.computeTrim(0, 0, 0, 0).width;
1579 return bw + 1;
1580 }
1581
1582 /**
1583 * Returns horizontal bar height even if bar isn't visible.
1584 *
1585 * @return horizontal bar height even if bar isn't visible
1586 */
1587 public int getHorizontalBarHeight() {
1588 // include horiz. bar height and trimming of scrollable used
1589 int bh = fHorScrollBar.computeTrim(0, 0, 0, 0).height;
1590 // +1 because win32 H.bar need 1 pixel canvas size to appear ! (strange no ?)
1591 return bh + 1;
1592 }
1593
1594 @Override
1595 public Rectangle computeTrim(int x, int y, int w, int h) {
1596 Rectangle r = new Rectangle(x, y, w, h);
1597 int bar_vis = computeBarVisibility(w, h, false, false);
1598 if ((bar_vis & VBAR) != 0) {
1599 r.width += getVerticalBarWidth();
1600 }
1601 if ((bar_vis & HBAR) != 0) {
1602 r.height += getHorizontalBarHeight();
1603 }
1604 return r;
1605 }
1606
1607 /**
1608 * Internal layout for ScrollView, handle scrollbars, drawzone and corner control
1609 */
1610 protected class SVLayout extends Layout {
1611 /**
1612 * The seek value
1613 */
1614 int seek = 0;
1615 /**
1616 * The do-it-not flag
1617 */
1618 boolean dontLayout = false;
1619
1620 @Override
1621 protected Point computeSize(Composite composite, int wHint, int hHint, boolean flushCache) {
1622 Point p = new Point(250, 250);
1623 if (fContentsWidth < p.x) {
1624 p.x = fContentsWidth;
1625 }
1626 if (fContentsHeight < p.y) {
1627 p.y = fContentsHeight;
1628 }
1629 return p;
1630 }
1631
1632 @Override
1633 protected void layout(Composite composite, boolean flushCache) {
1634 if (dontLayout) {
1635 return;
1636 }
1637 seek++;
1638 if (seek > 10) {
1639 dontLayout = true;
1640 }
1641
1642 Point cs = composite.getSize();
1643 int bar_vis = computeBarVisibility(cs.x, cs.y, false, false);
1644 boolean vb_vis = (bar_vis & VBAR) != 0;
1645 boolean hb_vis = (bar_vis & HBAR) != 0;
1646 fVertScrollBar.setVisible(vb_vis);
1647 fHorScrollBar.setVisible(hb_vis);
1648 int vbw = getVerticalBarWidth();
1649 int hbh = getHorizontalBarHeight();
1650 int wb = vb_vis ? vbw : 0;
1651 int hb = hb_vis ? hbh : 0;
1652 int cww = 0, cwh = 0;
1653
1654 if (fCornerControl != null && (vb_vis || hb_vis)) { // corner_control_.getVisible())
1655 fCornerControl.setVisible(true);
1656 cww = vbw;
1657 cwh = hbh;
1658 if (wb == 0) {
1659 wb = vbw;
1660 }
1661 if (hb == 0) {
1662 hb = hbh;
1663 }
1664 } else if (vb_vis && hb_vis) {
1665 if (fCornerControl != null) {
1666 fCornerControl.setVisible(false);
1667 }
1668 cww = vbw;
1669 cwh = hbh;
1670 }
1671 if (vb_vis || hb_vis) {
1672 updateScrollBarsValues();
1673 }
1674
1675 int vw = cs.x - (vb_vis ? vbw : 0);
1676 int vh = cs.y - (hb_vis ? hbh : 0);
1677 int vbx = cs.x - wb;
1678 int hby = cs.y - hb;
1679
1680 fViewControl.setBounds(0, 0, vw, vh);
1681
1682 if (vb_vis) {
1683 fVertScrollBar.setBounds(vbx, 0, wb, cs.y - cwh);
1684 }
1685 if (hb_vis) {
1686 fHorScrollBar.setBounds(0, hby, cs.x - cww, hb);
1687 }
1688 if (fCornerControl != null && fCornerControl.getVisible()) {
1689 fCornerControl.setBounds(vbx, hby, vbw, hbh);
1690 }
1691 updateScrollBarsValues();
1692
1693 seek--;
1694 if (seek == 0) {
1695 dontLayout = false;
1696 }
1697 }
1698 }
1699
1700 // static must take place here... cursor is created once.
1701 volatile static Cursor fOverviewCursor;
1702
1703 /** Support for click-and-see overview shell on this ScrollView */
1704 protected class Overview {
1705
1706 /**
1707 * factor for X from real and overview sizes, for mouse move speed.
1708 */
1709 protected float fOverviewFactorX;
1710
1711 /**
1712 * factor for Y from real and overview sizes, for mouse move speed.
1713 */
1714 protected float fOverviewFactorY;
1715 /**
1716 * shell use to show overview
1717 */
1718 protected Shell fOverview;
1719 /**
1720 * save mouse X cursor location for disappear();
1721 */
1722 protected int fSaveCursorX;
1723 /**
1724 * save mouse Y cursor location for disappear();
1725 */
1726 protected int fSaveCursorY;
1727
1728 /**
1729 * Apply overview support on a control. Replace existing corner_widget
1730 *
1731 * @param control
1732 * The control to use
1733 */
1734 public void useControl(Control control) {
1735 final Point pos = control.getLocation();
1736 control.addMouseListener(new MouseListener() {
1737 @Override
1738 public void mouseDoubleClick(MouseEvent e) {
1739 }
1740
1741 @Override
1742 public void mouseDown(MouseEvent e) {
1743 overviewAppear(e.x, e.y);
1744 }
1745
1746 @Override
1747 public void mouseUp(MouseEvent e) {
1748 overviewDisappear();
1749 }
1750 });
1751
1752 control.addFocusListener(new FocusListener() {
1753
1754 @Override
1755 public void focusGained(FocusEvent e) {
1756 }
1757
1758 @Override
1759 public void focusLost(FocusEvent e) {
1760 if (overviewing()) {
1761 overviewDisappear(false);
1762 }
1763 }
1764
1765 });
1766 control.addKeyListener(new KeyListener() {
1767
1768 @Override
1769 public void keyPressed(KeyEvent event) {
1770 if (event.keyCode == 32 && !overviewing()) {
1771 overviewAppear(pos.x, pos.y);
1772 } else if (event.keyCode == 32) {
1773 overviewDisappear();
1774 }
1775 if (event.keyCode == SWT.ARROW_DOWN) {
1776 overviewMove(0, 1, event);
1777 }
1778
1779 if (event.keyCode == SWT.ARROW_UP) {
1780 overviewMove(0, -1, event);
1781 }
1782
1783 if (event.keyCode == SWT.ARROW_RIGHT) {
1784 overviewMove(1, 0, event);
1785 }
1786
1787 if (event.keyCode == SWT.ARROW_LEFT) {
1788 overviewMove(-1, 0, event);
1789 }
1790 }
1791
1792 @Override
1793 public void keyReleased(KeyEvent e) {
1794 }
1795 });
1796 control.addMouseMoveListener(new MouseMoveListener() {
1797 private int refReshCount = 0;
1798 @Override
1799 public void mouseMove(MouseEvent event) {
1800 if (overviewing()) {
1801 // Slow down the refresh
1802 if (refReshCount % 4 == 0) {
1803 overviewMove(event);
1804 }
1805 refReshCount++;
1806 }
1807 }
1808 });
1809 }
1810
1811 /**
1812 * Dispose controls of overview
1813 */
1814 public void dispose() {
1815 if (fOverview != null) {
1816 fOverview.dispose();
1817 }
1818 }
1819
1820 /**
1821 * @return true if overview is currently on screen
1822 */
1823 protected boolean overviewing() {
1824 return (fOverview != null && fOverview.isVisible());
1825 }
1826
1827 /**
1828 * Process overview appear
1829 *
1830 * @param mx
1831 * X coordinate
1832 * @param my
1833 * Y coordinate
1834 */
1835 protected void overviewAppear(int mx, int my) {
1836 if (fOverview == null) {
1837 fOverview = new Shell(getShell(), SWT.ON_TOP | SWT.NO_BACKGROUND);
1838 fOverview.addPaintListener(new PaintListener() {
1839 @Override
1840 public void paintControl(PaintEvent e) {
1841 drawOverview(e.gc, fOverview.getClientArea());
1842 }
1843 });
1844 }
1845 // always the same..
1846 // overview.setBackground( viewcontrol_.getBackground() );
1847 fOverview.setForeground(fViewControl.getForeground());
1848
1849 // get location of shell (in screeen coordinates)
1850 Point p = toGlobalCoordinates(fCornerControl, 0, 0);
1851 int x = p.x;
1852 int y = p.y;
1853 int w, h;
1854 w = h = fOverviewSize;
1855 Rectangle scr = getDisplay().getBounds();
1856 Point ccs = fCornerControl.getSize();
1857 try {
1858 if (fContentsWidth > fContentsHeight) {
1859 float ratio = fContentsHeight / (float) fContentsWidth;
1860 h = (int) (w * ratio);
1861 if (h < ccs.y) {
1862 h = ccs.y;
1863 } else if (h >= scr.height / 2) {
1864 h = scr.height / 2;
1865 }
1866 } else {
1867 float ratio = fContentsWidth / (float) fContentsHeight;
1868 w = (int) (h * ratio);
1869 if (w < ccs.x) {
1870 w = ccs.x;
1871 } else if (w >= scr.width / 2) {
1872 w = scr.width / 2;
1873 }
1874 }
1875 fOverviewFactorX = fContentsWidth / (float) w;
1876 fOverviewFactorY = fContentsHeight / (float) h;
1877 }
1878 // no contents size set ?
1879 catch (java.lang.ArithmeticException e) {
1880 }
1881
1882 // try pop-up on button, extending to bottom right,
1883 // if outside screen, extend pop-up to top left
1884 // if( x+w > scr.width ) x = scr.width-w; //x += corner_control_.getSize().x-w;
1885 // if( y+h > scr.height ) y = scr.height-h;//y += corner_control_.getSize().y-h;
1886 if (x <= 0) {
1887 x = 1;
1888 }
1889 if (y <= 0) {
1890 y = 1;
1891 }
1892 x = x - w + ccs.x;
1893 y = y - h + ccs.y;
1894 fOverview.setBounds(x, y, w, h);
1895 fOverview.setVisible(true);
1896 fOverview.redraw();
1897 // mouse cursor disappear, so set invisible mouse cursor ...
1898 if (fOverviewCursor == null) {
1899 RGB rgb[] = { new RGB(0, 0, 0), new RGB(255, 0, 0) };
1900 PaletteData palette = new PaletteData(rgb);
1901 int s = 1;
1902 byte src[] = new byte[s * s];
1903 byte msk[] = new byte[s * s];
1904 for (int i = 0; i < s * s; ++i) {
1905 src[i] = (byte) 0xFF;
1906 }
1907 ImageData i_src = new ImageData(s, s, 1, palette, 1, src);
1908 ImageData i_msk = new ImageData(s, s, 1, palette, 1, msk);
1909 fOverviewCursor = new Cursor(null, i_src, i_msk, 0, 0);
1910 }
1911 fCornerControl.setCursor(fOverviewCursor);
1912 // convert to global coordinates
1913 p = toGlobalCoordinates(fCornerControl, mx, my);
1914 fSaveCursorX = p.x;
1915 fSaveCursorY = p.y;
1916
1917 Rectangle r = fOverview.getClientArea();
1918 int cx = (int) (r.width * fContentsX / (float) fContentsWidth);
1919 int cy = (int) (r.height * fContentsY / (float) fContentsHeight);
1920
1921 // cx,cy to display's global coordinates
1922 p = toGlobalCoordinates(fOverview.getParent(), cx, cy);
1923 }
1924
1925 /**
1926 * Process disappear of overview
1927 */
1928 protected void overviewDisappear() {
1929 overviewDisappear(true);
1930 }
1931
1932 /**
1933 * Process disappear of overview
1934 * @param restoreCursorLoc A flag to restore cursor location
1935 */
1936 protected void overviewDisappear(boolean restoreCursorLoc) {
1937 if (fOverview == null) {
1938 return;
1939 }
1940 fOverview.setVisible(false);
1941 fCornerControl.setCursor(null);
1942 if (restoreCursorLoc) {
1943 getDisplay().setCursorLocation(fSaveCursorX, fSaveCursorY);
1944 }
1945 fOverview.dispose();
1946 fOverview = null;
1947 }
1948
1949 /**
1950 * Process mouse move in overview
1951 * @param event The mouse event
1952 */
1953 protected void overviewMove(MouseEvent event) {
1954 Point p = toGlobalCoordinates(fCornerControl, event.x, event.y);
1955 int dx = p.x - fSaveCursorX;
1956 int dy = p.y - fSaveCursorY;
1957 overviewMove(dx, dy, event);
1958 }
1959
1960 /**
1961 * Process mouse move event when overviewing
1962 *
1963 * @param dx The x coordinates delta
1964 * @param dy The y coordinates delta
1965 * @param event The typed event
1966 */
1967 protected void overviewMove(int dx, int dy, TypedEvent event) {
1968 boolean ctrl = false;
1969 boolean shift = false;
1970
1971 if (event instanceof MouseEvent) {
1972 MouseEvent e = (MouseEvent) event;
1973 getDisplay().setCursorLocation(fSaveCursorX, fSaveCursorY);
1974 ctrl = (e.stateMask & SWT.CONTROL) != 0;
1975 shift = (e.stateMask & SWT.SHIFT) != 0;
1976 } else if (event instanceof KeyEvent) {
1977 KeyEvent e = (KeyEvent) event;
1978 ctrl = (e.stateMask & SWT.CONTROL) != 0;
1979 shift = (e.stateMask & SWT.SHIFT) != 0;
1980 }
1981
1982 int cx = fContentsX;
1983 int cy = fContentsY;
1984 float fx = fOverviewFactorX;
1985 float fy = fOverviewFactorY;
1986
1987 if (ctrl && shift) {
1988 if ((fx * 0.25f > 1) && (fy * 0.25 > 1)) {
1989 fx = fy = 1.0f;
1990 } else {
1991 fx *= 0.1f;
1992 fy *= 0.1f;
1993 }
1994 } else if (ctrl) {
1995 fx *= 0.5f;
1996 fy *= 0.5f;
1997 } else if (shift) {
1998 fx *= 0.5f;
1999 fy *= 0.5f;
2000 }
2001 scrollBy((int) (fx * dx), (int) (fy * dy));
2002 if (cx != fContentsX || cy != fContentsY) {
2003 fOverview.redraw();
2004 fOverview.update(); // draw now !
2005 }
2006 }
2007
2008 /**
2009 * Convert overview coordinates to global coordinates.
2010 *
2011 * @param loc
2012 * the control reference
2013 * @param x
2014 * The x coordinate to convert
2015 * @param y
2016 * The y coordinate to convert
2017 * @return The new converted Point
2018 */
2019 protected Point toGlobalCoordinates(Control loc, int x, int y) {
2020 Point p = new Point(x, y);
2021 for (Control c = loc; c != null; c = c.getParent()) {
2022 // control might have client area with 'decorations'
2023 int trim_x = 0, trim_y = 0;
2024 // other kind of widget with trimming ??
2025 if (c instanceof Scrollable) {
2026 Scrollable s = (Scrollable) c;
2027 Rectangle rr = s.getClientArea();
2028 Rectangle tr = s.computeTrim(rr.x, rr.y, rr.width, rr.height);
2029 trim_x = rr.x - tr.x;
2030 trim_y = rr.y - tr.y;
2031 }
2032 p.x += c.getLocation().x + trim_x;
2033 p.y += c.getLocation().y + trim_y;
2034 }
2035 return p;
2036 }
2037 }
2038 }
This page took 0.103296 seconds and 4 git commands to generate.