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