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