View Javadoc
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 }