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