]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms.ui/src/org/argeo/cms/ui/eclipse/forms/FormUtil.java
Improve documentation.
[lgpl/argeo-commons.git] / org.argeo.cms.ui / src / org / argeo / cms / ui / eclipse / forms / FormUtil.java
1 package org.argeo.cms.ui.eclipse.forms;
2
3 import org.eclipse.swt.SWT;
4 import org.eclipse.swt.custom.ScrolledComposite;
5 import org.eclipse.swt.events.MouseEvent;
6 //import org.eclipse.swt.graphics.Device;
7 import org.eclipse.swt.graphics.FontMetrics;
8 import org.eclipse.swt.graphics.GC;
9 //import org.eclipse.swt.graphics.Image;
10 //import org.eclipse.swt.graphics.ImageData;
11 import org.eclipse.swt.graphics.Point;
12 import org.eclipse.swt.graphics.Rectangle;
13 import org.eclipse.swt.layout.GridData;
14 import org.eclipse.swt.widgets.Combo;
15 import org.eclipse.swt.widgets.Composite;
16 import org.eclipse.swt.widgets.Control;
17 import org.eclipse.swt.widgets.Label;
18 import org.eclipse.swt.widgets.Layout;
19 //import org.eclipse.swt.widgets.ScrollBar;
20 import org.eclipse.swt.widgets.Text;
21 //import org.eclipse.ui.forms.widgets.ColumnLayout;
22 //import org.eclipse.ui.forms.widgets.Form;
23 //import org.eclipse.ui.forms.widgets.FormText;
24 //import org.eclipse.ui.forms.widgets.FormToolkit;
25 //import org.eclipse.ui.forms.widgets.ILayoutExtension;
26 //
27 //import com.ibm.icu.text.BreakIterator;
28
29 public class FormUtil {
30 public static final String PLUGIN_ID = "org.eclipse.ui.forms"; //$NON-NLS-1$
31
32 static final int H_SCROLL_INCREMENT = 5;
33
34 static final int V_SCROLL_INCREMENT = 64;
35
36 public static final String DEBUG = PLUGIN_ID + "/debug"; //$NON-NLS-1$
37
38 public static final String DEBUG_TEXT = DEBUG + "/text"; //$NON-NLS-1$
39 public static final String DEBUG_TEXTSIZE = DEBUG + "/textsize"; //$NON-NLS-1$
40
41 public static final String DEBUG_FOCUS = DEBUG + "/focus"; //$NON-NLS-1$
42
43 public static final String FOCUS_SCROLLING = "focusScrolling"; //$NON-NLS-1$
44
45 public static final String IGNORE_BODY = "__ignore_body__"; //$NON-NLS-1$
46
47 public static Text createText(Composite parent, String label,
48 FormToolkit factory) {
49 return createText(parent, label, factory, 1);
50 }
51
52 public static Text createText(Composite parent, String label,
53 FormToolkit factory, int span) {
54 factory.createLabel(parent, label);
55 Text text = factory.createText(parent, ""); //$NON-NLS-1$
56 int hfill = span == 1 ? GridData.FILL_HORIZONTAL
57 : GridData.HORIZONTAL_ALIGN_FILL;
58 GridData gd = new GridData(hfill | GridData.VERTICAL_ALIGN_CENTER);
59 gd.horizontalSpan = span;
60 text.setLayoutData(gd);
61 return text;
62 }
63
64 public static Text createText(Composite parent, String label,
65 FormToolkit factory, int span, int style) {
66 Label l = factory.createLabel(parent, label);
67 if ((style & SWT.MULTI) != 0) {
68 GridData gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
69 l.setLayoutData(gd);
70 }
71 Text text = factory.createText(parent, "", style); //$NON-NLS-1$
72 int hfill = span == 1 ? GridData.FILL_HORIZONTAL
73 : GridData.HORIZONTAL_ALIGN_FILL;
74 GridData gd = new GridData(hfill | GridData.VERTICAL_ALIGN_CENTER);
75 gd.horizontalSpan = span;
76 text.setLayoutData(gd);
77 return text;
78 }
79
80 public static Text createText(Composite parent, FormToolkit factory,
81 int span) {
82 Text text = factory.createText(parent, ""); //$NON-NLS-1$
83 int hfill = span == 1 ? GridData.FILL_HORIZONTAL
84 : GridData.HORIZONTAL_ALIGN_FILL;
85 GridData gd = new GridData(hfill | GridData.VERTICAL_ALIGN_CENTER);
86 gd.horizontalSpan = span;
87 text.setLayoutData(gd);
88 return text;
89 }
90
91 public static int computeMinimumWidth(GC gc, String text) {
92 // BreakIterator wb = BreakIterator.getWordInstance();
93 // wb.setText(text);
94 // int last = 0;
95 //
96 // int width = 0;
97 //
98 // for (int loc = wb.first(); loc != BreakIterator.DONE; loc = wb.next()) {
99 // String word = text.substring(last, loc);
100 // Point extent = gc.textExtent(word);
101 // width = Math.max(width, extent.x);
102 // last = loc;
103 // }
104 // String lastWord = text.substring(last);
105 // Point extent = gc.textExtent(lastWord);
106 // width = Math.max(width, extent.x);
107 // return width;
108 return 0;
109 }
110
111 public static Point computeWrapSize(GC gc, String text, int wHint) {
112 // BreakIterator wb = BreakIterator.getWordInstance();
113 // wb.setText(text);
114 FontMetrics fm = gc.getFontMetrics();
115 int lineHeight = fm.getHeight();
116
117 int saved = 0;
118 int last = 0;
119 int height = lineHeight;
120 int maxWidth = 0;
121 // for (int loc = wb.first(); loc != BreakIterator.DONE; loc = wb.next()) {
122 // String word = text.substring(saved, loc);
123 // Point extent = gc.textExtent(word);
124 // if (extent.x > wHint) {
125 // // overflow
126 // saved = last;
127 // height += extent.y;
128 // // switch to current word so maxWidth will accommodate very long single words
129 // word = text.substring(last, loc);
130 // extent = gc.textExtent(word);
131 // }
132 // maxWidth = Math.max(maxWidth, extent.x);
133 // last = loc;
134 // }
135 /*
136 * Correct the height attribute in case it was calculated wrong due to wHint being less than maxWidth.
137 * The recursive call proved to be the only thing that worked in all cases. Some attempts can be made
138 * to estimate the height, but the algorithm needs to be run again to be sure.
139 */
140 if (maxWidth > wHint)
141 return computeWrapSize(gc, text, maxWidth);
142 return new Point(maxWidth, height);
143 }
144
145 // RAP [rh] paintWrapText unnecessary
146 // public static void paintWrapText(GC gc, String text, Rectangle bounds) {
147 // paintWrapText(gc, text, bounds, false);
148 // }
149
150 // RAP [rh] paintWrapText unnecessary
151 // public static void paintWrapText(GC gc, String text, Rectangle bounds,
152 // boolean underline) {
153 // BreakIterator wb = BreakIterator.getWordInstance();
154 // wb.setText(text);
155 // FontMetrics fm = gc.getFontMetrics();
156 // int lineHeight = fm.getHeight();
157 // int descent = fm.getDescent();
158 //
159 // int saved = 0;
160 // int last = 0;
161 // int y = bounds.y;
162 // int width = bounds.width;
163 //
164 // for (int loc = wb.first(); loc != BreakIterator.DONE; loc = wb.next()) {
165 // String line = text.substring(saved, loc);
166 // Point extent = gc.textExtent(line);
167 //
168 // if (extent.x > width) {
169 // // overflow
170 // String prevLine = text.substring(saved, last);
171 // gc.drawText(prevLine, bounds.x, y, true);
172 // if (underline) {
173 // Point prevExtent = gc.textExtent(prevLine);
174 // int lineY = y + lineHeight - descent + 1;
175 // gc
176 // .drawLine(bounds.x, lineY, bounds.x + prevExtent.x,
177 // lineY);
178 // }
179 //
180 // saved = last;
181 // y += lineHeight;
182 // }
183 // last = loc;
184 // }
185 // // paint the last line
186 // String lastLine = text.substring(saved, last);
187 // gc.drawText(lastLine, bounds.x, y, true);
188 // if (underline) {
189 // int lineY = y + lineHeight - descent + 1;
190 // Point lastExtent = gc.textExtent(lastLine);
191 // gc.drawLine(bounds.x, lineY, bounds.x + lastExtent.x, lineY);
192 // }
193 // }
194
195 public static ScrolledComposite getScrolledComposite(Control c) {
196 Composite parent = c.getParent();
197
198 while (parent != null) {
199 if (parent instanceof ScrolledComposite) {
200 return (ScrolledComposite) parent;
201 }
202 parent = parent.getParent();
203 }
204 return null;
205 }
206
207 public static void ensureVisible(Control c) {
208 ScrolledComposite scomp = getScrolledComposite(c);
209 if (scomp != null) {
210 Object data = scomp.getData(FOCUS_SCROLLING);
211 if (data == null || !data.equals(Boolean.FALSE))
212 FormUtil.ensureVisible(scomp, c);
213 }
214 }
215
216 public static void ensureVisible(ScrolledComposite scomp, Control control) {
217 // if the control is a FormText we do not need to scroll since it will
218 // ensure visibility of its segments as necessary
219 // if (control instanceof FormText)
220 // return;
221 Point controlSize = control.getSize();
222 Point controlOrigin = getControlLocation(scomp, control);
223 ensureVisible(scomp, controlOrigin, controlSize);
224 }
225
226 public static void ensureVisible(ScrolledComposite scomp,
227 Point controlOrigin, Point controlSize) {
228 Rectangle area = scomp.getClientArea();
229 Point scompOrigin = scomp.getOrigin();
230
231 int x = scompOrigin.x;
232 int y = scompOrigin.y;
233
234 // horizontal right, but only if the control is smaller
235 // than the client area
236 if (controlSize.x < area.width
237 && (controlOrigin.x + controlSize.x > scompOrigin.x
238 + area.width)) {
239 x = controlOrigin.x + controlSize.x - area.width;
240 }
241 // horizontal left - make sure the left edge of
242 // the control is showing
243 if (controlOrigin.x < x) {
244 if (controlSize.x < area.width)
245 x = controlOrigin.x + controlSize.x - area.width;
246 else
247 x = controlOrigin.x;
248 }
249 // vertical bottom
250 if (controlSize.y < area.height
251 && (controlOrigin.y + controlSize.y > scompOrigin.y
252 + area.height)) {
253 y = controlOrigin.y + controlSize.y - area.height;
254 }
255 // vertical top - make sure the top of
256 // the control is showing
257 if (controlOrigin.y < y) {
258 if (controlSize.y < area.height)
259 y = controlOrigin.y + controlSize.y - area.height;
260 else
261 y = controlOrigin.y;
262 }
263
264 if (scompOrigin.x != x || scompOrigin.y != y) {
265 // scroll to reveal
266 scomp.setOrigin(x, y);
267 }
268 }
269
270 public static void ensureVisible(ScrolledComposite scomp, Control control,
271 MouseEvent e) {
272 Point controlOrigin = getControlLocation(scomp, control);
273 int rX = controlOrigin.x + e.x;
274 int rY = controlOrigin.y + e.y;
275 Rectangle area = scomp.getClientArea();
276 Point scompOrigin = scomp.getOrigin();
277
278 int x = scompOrigin.x;
279 int y = scompOrigin.y;
280 // System.out.println("Ensure: area="+area+", origin="+scompOrigin+",
281 // cloc="+controlOrigin+", csize="+controlSize+", x="+x+", y="+y);
282
283 // horizontal right
284 if (rX > scompOrigin.x + area.width) {
285 x = rX - area.width;
286 }
287 // horizontal left
288 else if (rX < x) {
289 x = rX;
290 }
291 // vertical bottom
292 if (rY > scompOrigin.y + area.height) {
293 y = rY - area.height;
294 }
295 // vertical top
296 else if (rY < y) {
297 y = rY;
298 }
299
300 if (scompOrigin.x != x || scompOrigin.y != y) {
301 // scroll to reveal
302 scomp.setOrigin(x, y);
303 }
304 }
305
306 public static Point getControlLocation(ScrolledComposite scomp,
307 Control control) {
308 int x = 0;
309 int y = 0;
310 Control content = scomp.getContent();
311 Control currentControl = control;
312 for (;;) {
313 if (currentControl == content)
314 break;
315 Point location = currentControl.getLocation();
316 // if (location.x > 0)
317 // x += location.x;
318 // if (location.y > 0)
319 // y += location.y;
320 x += location.x;
321 y += location.y;
322 currentControl = currentControl.getParent();
323 }
324 return new Point(x, y);
325 }
326
327 static void scrollVertical(ScrolledComposite scomp, boolean up) {
328 scroll(scomp, 0, up ? -V_SCROLL_INCREMENT : V_SCROLL_INCREMENT);
329 }
330
331 static void scrollHorizontal(ScrolledComposite scomp, boolean left) {
332 scroll(scomp, left ? -H_SCROLL_INCREMENT : H_SCROLL_INCREMENT, 0);
333 }
334
335 static void scrollPage(ScrolledComposite scomp, boolean up) {
336 Rectangle clientArea = scomp.getClientArea();
337 int increment = up ? -clientArea.height : clientArea.height;
338 scroll(scomp, 0, increment);
339 }
340
341 static void scroll(ScrolledComposite scomp, int xoffset, int yoffset) {
342 Point origin = scomp.getOrigin();
343 Point contentSize = scomp.getContent().getSize();
344 int xorigin = origin.x + xoffset;
345 int yorigin = origin.y + yoffset;
346 xorigin = Math.max(xorigin, 0);
347 xorigin = Math.min(xorigin, contentSize.x - 1);
348 yorigin = Math.max(yorigin, 0);
349 yorigin = Math.min(yorigin, contentSize.y - 1);
350 scomp.setOrigin(xorigin, yorigin);
351 }
352
353 // RAP [rh] FormUtil#updatePageIncrement: empty implementation
354 public static void updatePageIncrement(ScrolledComposite scomp) {
355 // ScrollBar vbar = scomp.getVerticalBar();
356 // if (vbar != null) {
357 // Rectangle clientArea = scomp.getClientArea();
358 // int increment = clientArea.height - 5;
359 // vbar.setPageIncrement(increment);
360 // }
361 // ScrollBar hbar = scomp.getHorizontalBar();
362 // if (hbar != null) {
363 // Rectangle clientArea = scomp.getClientArea();
364 // int increment = clientArea.width - 5;
365 // hbar.setPageIncrement(increment);
366 // }
367 }
368
369 public static void processKey(int keyCode, Control c) {
370 if (c.isDisposed()) {
371 return;
372 }
373 ScrolledComposite scomp = FormUtil.getScrolledComposite(c);
374 if (scomp != null) {
375 if (c instanceof Combo)
376 return;
377 switch (keyCode) {
378 case SWT.ARROW_DOWN:
379 if (scomp.getData("novarrows") == null) //$NON-NLS-1$
380 FormUtil.scrollVertical(scomp, false);
381 break;
382 case SWT.ARROW_UP:
383 if (scomp.getData("novarrows") == null) //$NON-NLS-1$
384 FormUtil.scrollVertical(scomp, true);
385 break;
386 case SWT.ARROW_LEFT:
387 FormUtil.scrollHorizontal(scomp, true);
388 break;
389 case SWT.ARROW_RIGHT:
390 FormUtil.scrollHorizontal(scomp, false);
391 break;
392 case SWT.PAGE_UP:
393 FormUtil.scrollPage(scomp, true);
394 break;
395 case SWT.PAGE_DOWN:
396 FormUtil.scrollPage(scomp, false);
397 break;
398 }
399 }
400 }
401
402 public static boolean isWrapControl(Control c) {
403 if ((c.getStyle() & SWT.WRAP) != 0)
404 return true;
405 if (c instanceof Composite) {
406 return false;
407 // return ((Composite) c).getLayout() instanceof ILayoutExtension;
408 }
409 return false;
410 }
411
412 public static int getWidthHint(int wHint, Control c) {
413 boolean wrap = isWrapControl(c);
414 return wrap ? wHint : SWT.DEFAULT;
415 }
416
417 public static int getHeightHint(int hHint, Control c) {
418 if (c instanceof Composite) {
419 Layout layout = ((Composite) c).getLayout();
420 // if (layout instanceof ColumnLayout)
421 // return hHint;
422 }
423 return SWT.DEFAULT;
424 }
425
426 public static int computeMinimumWidth(Control c, boolean changed) {
427 if (c instanceof Composite) {
428 Layout layout = ((Composite) c).getLayout();
429 // if (layout instanceof ILayoutExtension)
430 // return ((ILayoutExtension) layout).computeMinimumWidth(
431 // (Composite) c, changed);
432 }
433 return c.computeSize(FormUtil.getWidthHint(5, c), SWT.DEFAULT, changed).x;
434 }
435
436 public static int computeMaximumWidth(Control c, boolean changed) {
437 if (c instanceof Composite) {
438 Layout layout = ((Composite) c).getLayout();
439 // if (layout instanceof ILayoutExtension)
440 // return ((ILayoutExtension) layout).computeMaximumWidth(
441 // (Composite) c, changed);
442 }
443 return c.computeSize(SWT.DEFAULT, SWT.DEFAULT, changed).x;
444 }
445
446 // public static Form getForm(Control c) {
447 // Composite parent = c.getParent();
448 // while (parent != null) {
449 // if (parent instanceof Form) {
450 // return (Form) parent;
451 // }
452 // parent = parent.getParent();
453 // }
454 // return null;
455 // }
456
457 // RAP [rh] FormUtil#createAlphaMashImage unnecessary
458 // public static Image createAlphaMashImage(Device device, Image srcImage) {
459 // Rectangle bounds = srcImage.getBounds();
460 // int alpha = 0;
461 // int calpha = 0;
462 // ImageData data = srcImage.getImageData();
463 // // Create a new image with alpha values alternating
464 // // between fully transparent (0) and fully opaque (255).
465 // // This image will show the background through the
466 // // transparent pixels.
467 // for (int i = 0; i < bounds.height; i++) {
468 // // scan line
469 // alpha = calpha;
470 // for (int j = 0; j < bounds.width; j++) {
471 // // column
472 // data.setAlpha(j, i, alpha);
473 // alpha = alpha == 255 ? 0 : 255;
474 // }
475 // calpha = calpha == 255 ? 0 : 255;
476 // }
477 // return new Image(device, data);
478 // }
479
480 public static boolean mnemonicMatch(String text, char key) {
481 char mnemonic = findMnemonic(text);
482 if (mnemonic == '\0')
483 return false;
484 return Character.toUpperCase(key) == Character.toUpperCase(mnemonic);
485 }
486
487 private static char findMnemonic(String string) {
488 int index = 0;
489 int length = string.length();
490 do {
491 while (index < length && string.charAt(index) != '&')
492 index++;
493 if (++index >= length)
494 return '\0';
495 if (string.charAt(index) != '&')
496 return string.charAt(index);
497 index++;
498 } while (index < length);
499 return '\0';
500 }
501
502 public static void setFocusScrollingEnabled(Control c, boolean enabled) {
503 ScrolledComposite scomp = null;
504
505 if (c instanceof ScrolledComposite)
506 scomp = (ScrolledComposite)c;
507 else
508 scomp = getScrolledComposite(c);
509 if (scomp!=null)
510 scomp.setData(FormUtil.FOCUS_SCROLLING, enabled?null:Boolean.FALSE);
511 }
512
513 // RAP [rh] FormUtil#setAntialias unnecessary
514 // public static void setAntialias(GC gc, int style) {
515 // if (!gc.getAdvanced()) {
516 // gc.setAdvanced(true);
517 // if (!gc.getAdvanced())
518 // return;
519 // }
520 // gc.setAntialias(style);
521 // }
522 }