1 /*******************************************************************************
2  * Copyright (c) 2000, 2016 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 497575
14  *******************************************************************************/
15 package org.eclipse.swt.examples.controlexample;
16 
17 
18 import static org.eclipse.swt.events.SelectionListener.widgetDefaultSelectedAdapter;
19 import static org.eclipse.swt.events.SelectionListener.widgetSelectedAdapter;
20 
21 import java.lang.reflect.Method;
22 
23 import org.eclipse.swt.SWT;
24 import org.eclipse.swt.events.ArmEvent;
25 import org.eclipse.swt.events.ControlEvent;
26 import org.eclipse.swt.events.DisposeEvent;
27 import org.eclipse.swt.events.FocusEvent;
28 import org.eclipse.swt.events.HelpEvent;
29 import org.eclipse.swt.events.KeyAdapter;
30 import org.eclipse.swt.events.KeyEvent;
31 import org.eclipse.swt.events.MenuEvent;
32 import org.eclipse.swt.events.ModifyEvent;
33 import org.eclipse.swt.events.MouseEvent;
34 import org.eclipse.swt.events.PaintEvent;
35 import org.eclipse.swt.events.SelectionAdapter;
36 import org.eclipse.swt.events.SelectionEvent;
37 import org.eclipse.swt.events.SelectionListener;
38 import org.eclipse.swt.events.ShellEvent;
39 import org.eclipse.swt.events.TraverseEvent;
40 import org.eclipse.swt.events.TreeEvent;
41 import org.eclipse.swt.events.TypedEvent;
42 import org.eclipse.swt.events.VerifyEvent;
43 import org.eclipse.swt.graphics.Color;
44 import org.eclipse.swt.graphics.Font;
45 import org.eclipse.swt.graphics.FontData;
46 import org.eclipse.swt.graphics.GC;
47 import org.eclipse.swt.graphics.Image;
48 import org.eclipse.swt.graphics.Point;
49 import org.eclipse.swt.graphics.RGB;
50 import org.eclipse.swt.graphics.Rectangle;
51 import org.eclipse.swt.layout.GridData;
52 import org.eclipse.swt.layout.GridLayout;
53 import org.eclipse.swt.widgets.Button;
54 import org.eclipse.swt.widgets.ColorDialog;
55 import org.eclipse.swt.widgets.Combo;
56 import org.eclipse.swt.widgets.Composite;
57 import org.eclipse.swt.widgets.Control;
58 import org.eclipse.swt.widgets.Display;
59 import org.eclipse.swt.widgets.Event;
60 import org.eclipse.swt.widgets.FontDialog;
61 import org.eclipse.swt.widgets.Group;
62 import org.eclipse.swt.widgets.Item;
63 import org.eclipse.swt.widgets.Label;
64 import org.eclipse.swt.widgets.Listener;
65 import org.eclipse.swt.widgets.Menu;
66 import org.eclipse.swt.widgets.MenuItem;
67 import org.eclipse.swt.widgets.Shell;
68 import org.eclipse.swt.widgets.TabFolder;
69 import org.eclipse.swt.widgets.Table;
70 import org.eclipse.swt.widgets.TableItem;
71 import org.eclipse.swt.widgets.Text;
72 import org.eclipse.swt.widgets.Widget;
73 
74 /**
75  * <code>Tab</code> is the abstract superclass of every page
76  * in the example's tab folder.  Each page in the tab folder
77  * describes a control.
78  *
79  * A Tab itself is not a control but instead provides a
80  * hierarchy with which to share code that is common to
81  * every page in the folder.
82  *
83  * A typical page in a Tab contains a two column composite.
84  * The left column contains the "Example" group.  The right
85  * column contains "Control" group.  The "Control" group
86  * contains controls that allow the user to interact with
87  * the example control.  The "Control" group typically
88  * contains a "Style", "Other" and "Size" group.  Subclasses
89  * can override these defaults to augment a group or stop
90  * a group from being created.
91  */
92 abstract class Tab {
93 	Shell shell;
94 	Display display;
95 
96 	/* Common control buttons */
97 	Button borderButton, enabledButton, visibleButton, backgroundImageButton, popupMenuButton;
98 	Button preferredButton, tooSmallButton, smallButton, largeButton, rectangleButton, fillHButton, fillVButton;
99 
100 	/* Common groups and composites */
101 	Composite tabFolderPage;
102 	Group exampleGroup, controlGroup, listenersGroup, otherGroup, sizeGroup, styleGroup, colorGroup, backgroundModeGroup;
103 
104 	/* Controlling instance */
105 	final ControlExample instance;
106 
107 	/* Sizing constants for the "Size" group */
108 	static final int TOO_SMALL_SIZE	= 10;
109 	static final int RETANGLE_SIZE_WIDTH	= 140;
110 	static final int RETANGLE_SIZE_HEIGHT	= 30;
111 	static final int SMALL_SIZE		= 50;
112 	static final int LARGE_SIZE		= 100;
113 
114 	/* Right-to-left support */
115 	static final boolean RTL_SUPPORT_ENABLE = "win32".equals(SWT.getPlatform()) || "gtk".equals(SWT.getPlatform());
116 	Group orientationGroup;
117 	Button rtlButton, ltrButton, defaultOrietationButton;
118 	Group directionGroup;
119 	Button rtlDirectionButton, ltrDirectionButton, autoDirectionButton, defaultDirectionButton;
120 
121 	/* Controls and resources for the "Colors & Fonts" group */
122 	static final int IMAGE_SIZE = 12;
123 	static final int FOREGROUND_COLOR = 0;
124 	static final int BACKGROUND_COLOR = 1;
125 	static final int FONT = 2;
126 	Table colorAndFontTable;
127 	ColorDialog colorDialog;
128 	FontDialog fontDialog;
129 	Color foregroundColor, backgroundColor;
130 	Font font;
131 
132 	/* Controls and resources for the "Background Mode" group */
133 	Combo backgroundModeCombo;
134 	Button backgroundModeImageButton, backgroundModeColorButton;
135 
136 	boolean samplePopup = false;
137 
138 	/* Set/Get API controls */
139 	Combo nameCombo;
140 	Label returnTypeLabel;
141 	Button getButton, setButton;
142 	Text setText, getText;
143 	Shell setGetDialog;
144 
145 	/* Event logging variables and controls */
146 	Text eventConsole;
147 	boolean logging = false;
148 	boolean untypedEvents = false;
149 	boolean [] eventsFilter;
150 	int setFieldsMask = 0;
151 	Event setFieldsEvent = new Event ();
152 	boolean ignore = false;
153 
154 	/* Event logging constants */
155 	static final int DOIT	= 0x0100;
156 	static final int DETAIL	= 0x0200;
157 	static final int TEXT	= 0x0400;
158 	static final int X		= 0x0800;
159 	static final int Y		= 0x1000;
160 	static final int WIDTH	= 0x2000;
161 	static final int HEIGHT	= 0x4000;
162 
163 	static final int DETAIL_IME			= 0;
164 	static final int DETAIL_ERASE_ITEM	= 1;
165 	static final int DETAIL_TRAVERSE	= 2;
166 
167 	static class EventInfo {
168 		String name;
169 		int type;
170 		int settableFields;
171 		int setFields;
172 		Event event;
EventInfo(String name, int type, int settableFields, int setFields, Event event)173 		EventInfo (String name, int type, int settableFields, int setFields, Event event) {
174 			this.name = name;
175 			this.type = type;
176 			this.settableFields = settableFields;
177 			this.setFields = setFields;
178 			this.event = event;
179 		}
180 	}
181 
182 	final EventInfo [] EVENT_INFO = {
183 		new EventInfo ("Activate", SWT.Activate, 0, 0, new Event()),
184 		new EventInfo ("Arm", SWT.Arm, 0, 0, new Event()),
185 		new EventInfo ("Close", SWT.Close, DOIT, 0, new Event()),
186 		new EventInfo ("Collapse", SWT.Collapse, 0, 0, new Event()),
187 		new EventInfo ("Deactivate", SWT.Deactivate, 0, 0, new Event()),
188 		new EventInfo ("DefaultSelection", SWT.DefaultSelection, 0, 0, new Event()),
189 		new EventInfo ("Deiconify", SWT.Deiconify, 0, 0, new Event()),
190 		new EventInfo ("Dispose", SWT.Dispose, 0, 0, new Event()),
191 		new EventInfo ("DragDetect", SWT.DragDetect, 0, 0, new Event()),
192 		new EventInfo ("EraseItem", SWT.EraseItem, DETAIL | DETAIL_ERASE_ITEM, 0, new Event()),
193 		new EventInfo ("Expand", SWT.Expand, 0, 0, new Event()),
194 		new EventInfo ("FocusIn", SWT.FocusIn, 0, 0, new Event()),
195 		new EventInfo ("FocusOut", SWT.FocusOut, 0, 0, new Event()),
196 		new EventInfo ("HardKeyDown", SWT.HardKeyDown, 0, 0, new Event()),
197 		new EventInfo ("HardKeyUp", SWT.HardKeyUp, 0, 0, new Event()),
198 		new EventInfo ("Help", SWT.Help, 0, 0, new Event()),
199 		new EventInfo ("Hide", SWT.Hide, 0, 0, new Event()),
200 		new EventInfo ("Iconify", SWT.Iconify, 0, 0, new Event()),
201 		new EventInfo ("KeyDown", SWT.KeyDown, DOIT, 0, new Event()),
202 		new EventInfo ("KeyUp", SWT.KeyUp, DOIT, 0, new Event()),
203 		new EventInfo ("MeasureItem", SWT.MeasureItem, 0, 0, new Event()),
204 		new EventInfo ("MenuDetect", SWT.MenuDetect, X | Y | DOIT, 0, new Event()),
205 		new EventInfo ("Modify", SWT.Modify, 0, 0, new Event()),
206 		new EventInfo ("MouseDoubleClick", SWT.MouseDoubleClick, 0, 0, new Event()),
207 		new EventInfo ("MouseDown", SWT.MouseDown, 0, 0, new Event()),
208 		new EventInfo ("MouseEnter", SWT.MouseEnter, 0, 0, new Event()),
209 		new EventInfo ("MouseExit", SWT.MouseExit, 0, 0, new Event()),
210 		new EventInfo ("MouseHorizontalWheel", SWT.MouseHorizontalWheel, 0, 0, new Event()),
211 		new EventInfo ("MouseHover", SWT.MouseHover, 0, 0, new Event()),
212 		new EventInfo ("MouseMove", SWT.MouseMove, 0, 0, new Event()),
213 		new EventInfo ("MouseUp", SWT.MouseUp, 0, 0, new Event()),
214 		new EventInfo ("MouseVerticalWheel", SWT.MouseVerticalWheel, 0, 0, new Event()),
215 		new EventInfo ("Move", SWT.Move, 0, 0, new Event()),
216 		new EventInfo ("Paint", SWT.Paint, 0, 0, new Event()),
217 		new EventInfo ("PaintItem", SWT.PaintItem, 0, 0, new Event()),
218 		new EventInfo ("Resize", SWT.Resize, 0, 0, new Event()),
219 		new EventInfo ("Selection", SWT.Selection, X | Y | DOIT, 0, new Event()), // sash
220 		new EventInfo ("SetData", SWT.SetData, 0, 0, new Event()),
221 //		new EventInfo ("Settings", SWT.Settings, 0, 0, new Event()),  // note: this event only goes to Display
222 		new EventInfo ("Show", SWT.Show, 0, 0, new Event()),
223 		new EventInfo ("Traverse", SWT.Traverse, DETAIL | DETAIL_TRAVERSE | DOIT, 0, new Event()),
224 		new EventInfo ("Verify", SWT.Verify, TEXT | DOIT, 0, new Event()),
225 		new EventInfo ("ImeComposition", SWT.ImeComposition, DETAIL | DETAIL_IME | TEXT | DOIT, 0, new Event()),
226 	};
227 
228 	static final String [][] DETAIL_CONSTANTS = {
229 		{ // DETAIL_IME = 0
230 			"SWT.COMPOSITION_CHANGED",
231 			"SWT.COMPOSITION_OFFSET",
232 			"SWT.COMPOSITION_SELECTION",
233 		},
234 		{ // DETAIL_ERASE_ITEM = 1
235 			"SWT.SELECTED",
236 			"SWT.FOCUSED",
237 			"SWT.BACKGROUND",
238 			"SWT.FOREGROUND",
239 			"SWT.HOT",
240 		},
241 		{ // DETAIL_TRAVERSE = 2
242 			"SWT.TRAVERSE_NONE",
243 			"SWT.TRAVERSE_ESCAPE",
244 			"SWT.TRAVERSE_RETURN",
245 			"SWT.TRAVERSE_TAB_PREVIOUS",
246 			"SWT.TRAVERSE_TAB_NEXT",
247 			"SWT.TRAVERSE_ARROW_PREVIOUS",
248 			"SWT.TRAVERSE_ARROW_NEXT",
249 			"SWT.TRAVERSE_MNEMONIC",
250 			"SWT.TRAVERSE_PAGE_PREVIOUS",
251 			"SWT.TRAVERSE_PAGE_NEXT",
252 		},
253 	};
254 
255 	static final Object [] DETAIL_VALUES = {
256 		"SWT.COMPOSITION_CHANGED", Integer.valueOf(SWT.COMPOSITION_CHANGED),
257 		"SWT.COMPOSITION_OFFSET", Integer.valueOf(SWT.COMPOSITION_OFFSET),
258 		"SWT.COMPOSITION_SELECTION", Integer.valueOf(SWT.COMPOSITION_SELECTION),
259 		"SWT.SELECTED", Integer.valueOf(SWT.SELECTED),
260 		"SWT.FOCUSED", Integer.valueOf(SWT.FOCUSED),
261 		"SWT.BACKGROUND", Integer.valueOf(SWT.BACKGROUND),
262 		"SWT.FOREGROUND", Integer.valueOf(SWT.FOREGROUND),
263 		"SWT.HOT", Integer.valueOf(SWT.HOT),
264 		"SWT.TRAVERSE_NONE", Integer.valueOf(SWT.TRAVERSE_NONE),
265 		"SWT.TRAVERSE_ESCAPE", Integer.valueOf(SWT.TRAVERSE_ESCAPE),
266 		"SWT.TRAVERSE_RETURN", Integer.valueOf(SWT.TRAVERSE_RETURN),
267 		"SWT.TRAVERSE_TAB_PREVIOUS", Integer.valueOf(SWT.TRAVERSE_TAB_PREVIOUS),
268 		"SWT.TRAVERSE_TAB_NEXT", Integer.valueOf(SWT.TRAVERSE_TAB_NEXT),
269 		"SWT.TRAVERSE_ARROW_PREVIOUS", Integer.valueOf(SWT.TRAVERSE_ARROW_PREVIOUS),
270 		"SWT.TRAVERSE_ARROW_NEXT", Integer.valueOf(SWT.TRAVERSE_ARROW_NEXT),
271 		"SWT.TRAVERSE_MNEMONIC", Integer.valueOf(SWT.TRAVERSE_MNEMONIC),
272 		"SWT.TRAVERSE_PAGE_PREVIOUS", Integer.valueOf(SWT.TRAVERSE_PAGE_PREVIOUS),
273 		"SWT.TRAVERSE_PAGE_NEXT", Integer.valueOf(SWT.TRAVERSE_PAGE_NEXT),
274 	};
275 
276 	/**
277 	 * Creates the Tab within a given instance of ControlExample.
278 	 */
Tab(ControlExample instance)279 	Tab(ControlExample instance) {
280 		this.instance = instance;
281 	}
282 
283 	/**
284 	 * Creates the "Control" group.  The "Control" group
285 	 * is typically the right hand column in the tab.
286 	 */
createControlGroup()287 	void createControlGroup () {
288 
289 		/*
290 		 * Create the "Control" group.  This is the group on the
291 		 * right half of each example tab.  It consists of the
292 		 * "Style" group, the "Other" group and the "Size" group.
293 		 */
294 		controlGroup = new Group (tabFolderPage, SWT.NONE);
295 		controlGroup.setLayout (new GridLayout (2, true));
296 		controlGroup.setLayoutData (new GridData(SWT.FILL, SWT.FILL, false, false));
297 		controlGroup.setText (ControlExample.getResourceString("Parameters"));
298 
299 		/* Create individual groups inside the "Control" group */
300 		createStyleGroup ();
301 		createOtherGroup ();
302 		createSetGetGroup();
303 		createSizeGroup ();
304 		createColorAndFontGroup ();
305 		if (rtlSupport()) {
306 			createOrientationGroup ();
307 			createDirectionGroup ();
308 		}
309 		createBackgroundModeGroup ();
310 
311 		/*
312 		 * For each Button child in the style group, add a selection
313 		 * listener that will recreate the example controls.  If the
314 		 * style group button is a RADIO button, ensure that the radio
315 		 * button is selected before recreating the example controls.
316 		 * When the user selects a RADIO button, the current RADIO
317 		 * button in the group is deselected and the new RADIO button
318 		 * is selected automatically.  The listeners are notified for
319 		 * both these operations but typically only do work when a RADIO
320 		 * button is selected.
321 		 */
322 		SelectionListener selectionListener = widgetSelectedAdapter(event -> {
323 			if ((event.widget.getStyle () & SWT.RADIO) != 0) {
324 				if (!((Button) event.widget).getSelection ()) return;
325 			}
326 			if (!handleTextDirection (event.widget)) {
327 				recreateExampleWidgets ();
328 				if (rtlSupport ()) {
329 					/* Reflect the base direction falls back to the default (i.e. orientation). */
330 					ltrDirectionButton.setSelection (false);
331 					rtlDirectionButton.setSelection (false);
332 					autoDirectionButton.setSelection (false);
333 					defaultDirectionButton.setSelection (true);
334 				}
335 			}
336 		});
337 		Control [] children = styleGroup.getChildren ();
338 		for (Control child : children) {
339 			if (child instanceof Button) {
340 				Button button = (Button) child;
341 				button.addSelectionListener (selectionListener);
342 			} else {
343 				if (child instanceof Composite) {
344 					/* Look down one more level of children in the style group. */
345 					Composite composite = (Composite) child;
346 					Control [] grandchildren = composite.getChildren ();
347 					for (Control grandchild : grandchildren) {
348 						if (grandchild instanceof Button) {
349 							Button button = (Button) grandchild;
350 							button.addSelectionListener (selectionListener);
351 						}
352 					}
353 				}
354 			}
355 		}
356 		if (rtlSupport()) {
357 			rtlButton.addSelectionListener (selectionListener);
358 			ltrButton.addSelectionListener (selectionListener);
359 			defaultOrietationButton.addSelectionListener (selectionListener);
360 			rtlDirectionButton.addSelectionListener (selectionListener);
361 			ltrDirectionButton.addSelectionListener (selectionListener);
362 			autoDirectionButton.addSelectionListener (selectionListener);
363 			defaultDirectionButton.addSelectionListener (selectionListener);
364 		}
365 	}
366 
367 	/**
368 	 * Append the Set/Get API controls to the "Other" group.
369 	 */
createSetGetGroup()370 	void createSetGetGroup() {
371 		/*
372 		 * Create the button to access set/get API functionality.
373 		 */
374 		final String [] methodNames = getMethodNames ();
375 		if (methodNames != null) {
376 			final Button setGetButton = new Button (otherGroup, SWT.PUSH);
377 			setGetButton.setText (ControlExample.getResourceString ("Set_Get"));
378 			setGetButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
379 			setGetButton.addSelectionListener (widgetSelectedAdapter(e -> {
380 				if (getExampleWidgets().length >  0) {
381 					if (setGetDialog == null) {
382 						setGetDialog = createSetGetDialog(methodNames);
383 					}
384 					Point pt = setGetButton.getLocation();
385 					pt = display.map(setGetButton.getParent(), null, pt);
386 					setGetDialog.setLocation(pt.x, pt.y);
387 					setGetDialog.open();
388 				}
389 			}));
390 		}
391 	}
392 
393 	/**
394 	 * Creates the "Control" widget children.
395 	 * Subclasses override this method to augment
396 	 * the standard controls created in the "Style",
397 	 * "Other" and "Size" groups.
398 	 */
createControlWidgets()399 	void createControlWidgets () {
400 	}
401 
402 	/**
403 	 * Creates the "Colors and Fonts" group. This is typically
404 	 * a child of the "Control" group. Subclasses override
405 	 * this method to customize color and font settings.
406 	 */
createColorAndFontGroup()407 	void createColorAndFontGroup () {
408 		/* Create the group. */
409 		colorGroup = new Group(controlGroup, SWT.NONE);
410 		colorGroup.setLayout (new GridLayout (2, true));
411 		colorGroup.setLayoutData (new GridData (SWT.FILL, SWT.FILL, false, false));
412 		colorGroup.setText (ControlExample.getResourceString ("Colors"));
413 		colorAndFontTable = new Table(colorGroup, SWT.BORDER | SWT.V_SCROLL);
414 		colorAndFontTable.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 2, 1));
415 		TableItem item = new TableItem(colorAndFontTable, SWT.None);
416 		item.setText(ControlExample.getResourceString ("Foreground_Color"));
417 		colorAndFontTable.setSelection(0);
418 		item = new TableItem(colorAndFontTable, SWT.None);
419 		item.setText(ControlExample.getResourceString ("Background_Color"));
420 		item = new TableItem(colorAndFontTable, SWT.None);
421 		item.setText(ControlExample.getResourceString ("Font"));
422 		Button changeButton = new Button (colorGroup, SWT.PUSH);
423 		changeButton.setText(ControlExample.getResourceString("Change"));
424 		changeButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
425 		Button defaultsButton = new Button (colorGroup, SWT.PUSH);
426 		defaultsButton.setText(ControlExample.getResourceString("Defaults"));
427 		defaultsButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
428 
429 		/* Add listeners to set/reset colors and fonts. */
430 		colorDialog = new ColorDialog (shell);
431 		fontDialog = new FontDialog (shell);
432 		colorAndFontTable.addSelectionListener(widgetDefaultSelectedAdapter(event -> changeFontOrColor (colorAndFontTable.getSelectionIndex())));
433 		changeButton.addSelectionListener(widgetSelectedAdapter(event -> changeFontOrColor (colorAndFontTable.getSelectionIndex())));
434 		defaultsButton.addSelectionListener(widgetSelectedAdapter(e -> resetColorsAndFonts ()));
435 		shell.addDisposeListener(event -> {
436 			if (foregroundColor != null) foregroundColor.dispose();
437 			if (backgroundColor != null) backgroundColor.dispose();
438 			if (font != null) font.dispose();
439 			foregroundColor = null;
440 			backgroundColor = null;
441 			font = null;
442 			if (colorAndFontTable != null && !colorAndFontTable.isDisposed()) {
443 				TableItem [] items = colorAndFontTable.getItems();
444 				for (TableItem currentItem : items) {
445 					Image image = currentItem.getImage();
446 					if (image != null) image.dispose();
447 				}
448 			}
449 		});
450 	}
451 
changeFontOrColor(int index)452 	void changeFontOrColor(int index) {
453 		switch (index) {
454 			case FOREGROUND_COLOR: {
455 				Color oldColor = foregroundColor;
456 				if (oldColor == null) {
457 					Control [] controls = getExampleControls ();
458 					if (controls.length > 0) oldColor = controls [0].getForeground ();
459 				}
460 				if (oldColor != null) colorDialog.setRGB(oldColor.getRGB()); // seed dialog with current color
461 				RGB rgb = colorDialog.open();
462 				if (rgb == null) return;
463 				oldColor = foregroundColor; // save old foreground color to dispose when done
464 				foregroundColor = new Color (display, rgb);
465 				setExampleWidgetForeground ();
466 				if (oldColor != null) oldColor.dispose ();
467 			}
468 			break;
469 			case BACKGROUND_COLOR: {
470 				Color oldColor = backgroundColor;
471 				if (oldColor == null) {
472 					Control [] controls = getExampleControls ();
473 					if (controls.length > 0) oldColor = controls [0].getBackground (); // seed dialog with current color
474 				}
475 				if (oldColor != null) colorDialog.setRGB(oldColor.getRGB());
476 				RGB rgb = colorDialog.open();
477 				if (rgb == null) return;
478 				oldColor = backgroundColor; // save old background color to dispose when done
479 				backgroundColor = new Color (display, rgb);
480 				setExampleWidgetBackground ();
481 				if (oldColor != null) oldColor.dispose ();
482 			}
483 			break;
484 			case FONT: {
485 				Font oldFont = font;
486 				if (oldFont == null) {
487 					Control [] controls = getExampleControls ();
488 					if (controls.length > 0) oldFont = controls [0].getFont ();
489 				}
490 				if (oldFont != null) fontDialog.setFontList(oldFont.getFontData()); // seed dialog with current font
491 				FontData fontData = fontDialog.open ();
492 				if (fontData == null) return;
493 				oldFont = font; // dispose old font when done
494 				font = new Font (display, fontData);
495 				setExampleWidgetFont ();
496 				setExampleWidgetSize ();
497 				if (oldFont != null) oldFont.dispose ();
498 			}
499 			break;
500 		}
501 	}
502 
503 	/**
504 	 * Creates the "Other" group.  This is typically
505 	 * a child of the "Control" group.
506 	 */
createOtherGroup()507 	void createOtherGroup () {
508 		/* Create the group */
509 		otherGroup = new Group (controlGroup, SWT.NONE);
510 		otherGroup.setLayout (new GridLayout ());
511 		otherGroup.setLayoutData (new GridData (SWT.FILL, SWT.FILL, false, false));
512 		otherGroup.setText (ControlExample.getResourceString("Other"));
513 
514 		/* Create the controls */
515 		enabledButton = new Button(otherGroup, SWT.CHECK);
516 		enabledButton.setText(ControlExample.getResourceString("Enabled"));
517 		visibleButton = new Button(otherGroup, SWT.CHECK);
518 		visibleButton.setText(ControlExample.getResourceString("Visible"));
519 		backgroundImageButton = new Button(otherGroup, SWT.CHECK);
520 		backgroundImageButton.setText(ControlExample.getResourceString("BackgroundImage"));
521 		popupMenuButton = new Button(otherGroup, SWT.CHECK);
522 		popupMenuButton.setText(ControlExample.getResourceString("PopupMenu"));
523 
524 		/* Add the listeners */
525 		enabledButton.addSelectionListener (widgetSelectedAdapter(event -> setExampleWidgetEnabled ()));
526 		visibleButton.addSelectionListener (widgetSelectedAdapter(event -> setExampleWidgetVisibility ()));
527 		backgroundImageButton.addSelectionListener (widgetSelectedAdapter(event -> setExampleWidgetBackgroundImage ()));
528 		popupMenuButton.addSelectionListener (widgetSelectedAdapter(event -> setExampleWidgetPopupMenu ()));
529 
530 		/* Set the default state */
531 		enabledButton.setSelection(true);
532 		visibleButton.setSelection(true);
533 		backgroundImageButton.setSelection(false);
534 		popupMenuButton.setSelection(false);
535 	}
536 
537 	/**
538 	 * Creates the "Background Mode" group.
539 	 */
createBackgroundModeGroup()540 	void createBackgroundModeGroup () {
541 		/* Create the group */
542 		backgroundModeGroup = new Group (controlGroup, SWT.NONE);
543 		backgroundModeGroup.setLayout (new GridLayout ());
544 		backgroundModeGroup.setLayoutData (new GridData (SWT.FILL, SWT.FILL, false, false));
545 		backgroundModeGroup.setText (ControlExample.getResourceString("Background_Mode"));
546 
547 		/* Create the controls */
548 		backgroundModeCombo = new Combo(backgroundModeGroup, SWT.READ_ONLY);
549 		backgroundModeCombo.setItems("SWT.INHERIT_NONE", "SWT.INHERIT_DEFAULT", "SWT.INHERIT_FORCE");
550 		backgroundModeImageButton = new Button(backgroundModeGroup, SWT.CHECK);
551 		backgroundModeImageButton.setText(ControlExample.getResourceString("BackgroundImage"));
552 		backgroundModeColorButton = new Button(backgroundModeGroup, SWT.CHECK);
553 		backgroundModeColorButton.setText(ControlExample.getResourceString("BackgroundColor"));
554 
555 		/* Add the listeners */
556 		backgroundModeCombo.addSelectionListener (widgetSelectedAdapter(event -> setExampleGroupBackgroundMode ()));
557 		backgroundModeImageButton.addSelectionListener (widgetSelectedAdapter(event -> setExampleGroupBackgroundImage ()));
558 		backgroundModeColorButton.addSelectionListener (widgetSelectedAdapter(event -> setExampleGroupBackgroundColor ()));
559 
560 		/* Set the default state */
561 		backgroundModeCombo.setText(backgroundModeCombo.getItem(0));
562 		backgroundModeImageButton.setSelection(false);
563 		backgroundModeColorButton.setSelection(false);
564 	}
565 
createEditEventDialog(Shell parent, int x, int y, final int index)566 	void createEditEventDialog(Shell parent, int x, int y, final int index) {
567 		final Shell dialog = new Shell(parent, SWT.DIALOG_TRIM | SWT.RESIZE | SWT.APPLICATION_MODAL);
568 		dialog.setLayout(new GridLayout());
569 		dialog.setText(ControlExample.getResourceString ("Edit_Event"));
570 		Label label = new Label (dialog, SWT.NONE);
571 		label.setText (ControlExample.getResourceString ("Edit_Event_Fields", EVENT_INFO[index].name));
572 
573 		Group group = new Group (dialog, SWT.NONE);
574 		group.setLayout(new GridLayout(2, false));
575 		group.setLayoutData(new GridData (SWT.FILL, SWT.FILL, true, true));
576 
577 		final int fields = EVENT_INFO[index].settableFields;
578 		final int eventType = EVENT_INFO[index].type;
579 		setFieldsMask = EVENT_INFO[index].setFields;
580 		setFieldsEvent = EVENT_INFO[index].event;
581 
582 		if ((fields & DOIT) != 0) {
583 			new Label (group, SWT.NONE).setText ("doit");
584 			final Combo doitCombo = new Combo (group, SWT.READ_ONLY);
585 			doitCombo.setItems ("", "true", "false");
586 			if ((setFieldsMask & DOIT) != 0) doitCombo.setText(Boolean.toString(setFieldsEvent.doit));
587 			doitCombo.setLayoutData (new GridData (SWT.FILL, SWT.CENTER, true, false));
588 			doitCombo.addSelectionListener(widgetSelectedAdapter(e -> {
589 				String newValue = doitCombo.getText();
590 				if (newValue.length() == 0) {
591 					setFieldsMask &= ~DOIT;
592 				} else {
593 					setFieldsEvent.type = eventType;
594 					setFieldsEvent.doit = newValue.equals("true");
595 					setFieldsMask |= DOIT;
596 				}
597 			}));
598 		}
599 
600 		if ((fields & DETAIL) != 0) {
601 			new Label (group, SWT.NONE).setText ("detail");
602 			int detailType = fields & 0xFF;
603 			final Combo detailCombo = new Combo (group, SWT.READ_ONLY);
604 			detailCombo.setItems (DETAIL_CONSTANTS[detailType]);
605 			detailCombo.add ("", 0);
606 			detailCombo.setVisibleItemCount(detailCombo.getItemCount());
607 			if ((setFieldsMask & DETAIL) != 0) detailCombo.setText (DETAIL_CONSTANTS[detailType][setFieldsEvent.detail]);
608 			detailCombo.setLayoutData (new GridData (SWT.FILL, SWT.CENTER, true, false));
609 			detailCombo.addSelectionListener(widgetSelectedAdapter(e -> {
610 				String newValue = detailCombo.getText();
611 				if (newValue.length() == 0) {
612 					setFieldsMask &= ~DETAIL;
613 				} else {
614 					setFieldsEvent.type = eventType;
615 					for (int i = 0; i < DETAIL_VALUES.length; i += 2) {
616 						if (newValue.equals (DETAIL_VALUES [i])) {
617 							setFieldsEvent.detail = ((Integer) DETAIL_VALUES [i + 1]).intValue();
618 							break;
619 						}
620 					}
621 					setFieldsMask |= DETAIL;
622 				}
623 			}));
624 		}
625 
626 		if ((fields & TEXT) != 0) {
627 			new Label (group, SWT.NONE).setText ("text");
628 			final Text textText = new Text (group, SWT.BORDER);
629 			if ((setFieldsMask & TEXT) != 0) textText.setText(setFieldsEvent.text);
630 			textText.setLayoutData (new GridData (SWT.FILL, SWT.CENTER, true, false));
631 			textText.addModifyListener(e -> {
632 				String newValue = textText.getText();
633 				if (newValue.length() == 0) {
634 					setFieldsMask &= ~TEXT;
635 				} else {
636 					setFieldsEvent.type = eventType;
637 					setFieldsEvent.text = newValue;
638 					setFieldsMask |= TEXT;
639 				}
640 			});
641 		}
642 
643 		if ((fields & X) != 0) {
644 			new Label (group, SWT.NONE).setText ("x");
645 			final Text xText = new Text (group, SWT.BORDER);
646 			if ((setFieldsMask & X) != 0) xText.setText(Integer.toString(setFieldsEvent.x));
647 			xText.setLayoutData (new GridData (SWT.FILL, SWT.CENTER, true, false));
648 			xText.addModifyListener(e -> {
649 				String newValue = xText.getText ();
650 				try {
651 					int newIntValue = Integer.parseInt (newValue);
652 					setFieldsEvent.type = eventType;
653 					setFieldsEvent.x = newIntValue;
654 					setFieldsMask |= X;
655 				} catch (NumberFormatException ex) {
656 					setFieldsMask &= ~X;
657 				}
658 			});
659 		}
660 
661 		if ((fields & Y) != 0) {
662 			new Label (group, SWT.NONE).setText ("y");
663 			final Text yText = new Text (group, SWT.BORDER);
664 			if ((setFieldsMask & Y) != 0) yText.setText(Integer.toString(setFieldsEvent.y));
665 			yText.setLayoutData (new GridData (SWT.FILL, SWT.CENTER, true, false));
666 			yText.addModifyListener(e -> {
667 				String newValue = yText.getText ();
668 				try {
669 					int newIntValue = Integer.parseInt (newValue);
670 					setFieldsEvent.type = eventType;
671 					setFieldsEvent.y = newIntValue;
672 					setFieldsMask |= Y;
673 				} catch (NumberFormatException ex) {
674 					setFieldsMask &= ~Y;
675 				}
676 			});
677 		}
678 
679 		if ((fields & WIDTH) != 0) {
680 			new Label (group, SWT.NONE).setText ("width");
681 			final Text widthText = new Text (group, SWT.BORDER);
682 			if ((setFieldsMask & WIDTH) != 0) widthText.setText(Integer.toString(setFieldsEvent.width));
683 			widthText.setLayoutData (new GridData (SWT.FILL, SWT.CENTER, true, false));
684 			widthText.addModifyListener(e -> {
685 				String newValue = widthText.getText ();
686 				try {
687 					int newIntValue = Integer.parseInt (newValue);
688 					setFieldsEvent.type = eventType;
689 					setFieldsEvent.width = newIntValue;
690 					setFieldsMask |= WIDTH;
691 				} catch (NumberFormatException ex) {
692 					setFieldsMask &= ~WIDTH;
693 				}
694 			});
695 		}
696 
697 		if ((fields & HEIGHT) != 0) {
698 			new Label (group, SWT.NONE).setText ("height");
699 			final Text heightText = new Text (group, SWT.BORDER);
700 			if ((setFieldsMask & HEIGHT) != 0) heightText.setText(Integer.toString(setFieldsEvent.height));
701 			heightText.setLayoutData (new GridData (SWT.FILL, SWT.CENTER, true, false));
702 			heightText.addModifyListener(e -> {
703 				String newValue = heightText.getText ();
704 				try {
705 					int newIntValue = Integer.parseInt (newValue);
706 					setFieldsEvent.type = eventType;
707 					setFieldsEvent.height = newIntValue;
708 					setFieldsMask |= HEIGHT;
709 				} catch (NumberFormatException ex) {
710 					setFieldsMask &= ~HEIGHT;
711 				}
712 			});
713 		}
714 
715 		Button ok = new Button (dialog, SWT.PUSH);
716 		ok.setText (ControlExample.getResourceString("OK"));
717 		GridData data = new GridData (70, SWT.DEFAULT);
718 		data.horizontalAlignment = SWT.RIGHT;
719 		ok.setLayoutData (data);
720 		ok.addSelectionListener (widgetSelectedAdapter(e -> {
721 			EVENT_INFO[index].setFields = setFieldsMask;
722 			EVENT_INFO[index].event = setFieldsEvent;
723 			dialog.dispose();
724 		}));
725 
726 		dialog.setDefaultButton(ok);
727 		dialog.pack();
728 		dialog.setLocation(x, y);
729 		dialog.open();
730 	}
731 
732 	/**
733 	 * Create the event console popup menu.
734 	 */
createEventConsolePopup()735 	void createEventConsolePopup () {
736 		Menu popup = new Menu (shell, SWT.POP_UP);
737 		eventConsole.setMenu (popup);
738 
739 		MenuItem cut = new MenuItem (popup, SWT.PUSH);
740 		cut.setText (ControlExample.getResourceString("MenuItem_Cut"));
741 		cut.addListener (SWT.Selection, event -> eventConsole.cut ());
742 		MenuItem copy = new MenuItem (popup, SWT.PUSH);
743 		copy.setText (ControlExample.getResourceString("MenuItem_Copy"));
744 		copy.addListener (SWT.Selection, event -> eventConsole.copy ());
745 		MenuItem paste = new MenuItem (popup, SWT.PUSH);
746 		paste.setText (ControlExample.getResourceString("MenuItem_Paste"));
747 		paste.addListener (SWT.Selection, event -> eventConsole.paste ());
748 		new MenuItem (popup, SWT.SEPARATOR);
749 		MenuItem selectAll = new MenuItem (popup, SWT.PUSH);
750 		selectAll.setText(ControlExample.getResourceString("MenuItem_SelectAll"));
751 		selectAll.addListener (SWT.Selection, event -> eventConsole.selectAll ());
752 	}
753 
754 	/**
755 	 * Creates the "Example" group.  The "Example" group
756 	 * is typically the left hand column in the tab.
757 	 */
createExampleGroup()758 	void createExampleGroup () {
759 		exampleGroup = new Group (tabFolderPage, SWT.NONE);
760 		exampleGroup.setLayout (new GridLayout ());
761 		exampleGroup.setLayoutData (new GridData (SWT.FILL, SWT.FILL, true, true));
762 	}
763 
764 	/**
765 	 * Creates the "Example" widget children of the "Example" group.
766 	 * Subclasses override this method to create the particular
767 	 * example control.
768 	 */
createExampleWidgets()769 	void createExampleWidgets () {
770 		/* Do nothing */
771 	}
772 
773 	/**
774 	 * Creates and opens the "Listener selection" dialog.
775 	 */
createListenerSelectionDialog()776 	void createListenerSelectionDialog () {
777 		final Shell dialog = new Shell (shell, SWT.DIALOG_TRIM | SWT.RESIZE | SWT.APPLICATION_MODAL);
778 		dialog.setText (ControlExample.getResourceString ("Select_Listeners"));
779 		dialog.setLayout (new GridLayout (2, false));
780 		final Table table = new Table (dialog, SWT.BORDER | SWT.V_SCROLL | SWT.CHECK);
781 		GridData data = new GridData(GridData.FILL_BOTH);
782 		data.verticalSpan = 3;
783 		table.setLayoutData(data);
784 		for (int i = 0; i < EVENT_INFO.length; i++) {
785 			TableItem item = new TableItem (table, SWT.NONE);
786 			item.setText (EVENT_INFO[i].name);
787 			item.setChecked (eventsFilter[i]);
788 		}
789 		final String [] customNames = getCustomEventNames ();
790 		for (int i = 0; i < customNames.length; i++) {
791 			TableItem item = new TableItem (table, SWT.NONE);
792 			item.setText (customNames[i]);
793 			item.setChecked (eventsFilter[EVENT_INFO.length + i]);
794 		}
795 		Button selectAll = new Button (dialog, SWT.PUSH);
796 		selectAll.setText(ControlExample.getResourceString ("Select_All"));
797 		selectAll.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
798 		selectAll.addSelectionListener (widgetSelectedAdapter(e -> {
799 			TableItem [] items = table.getItems();
800 			for (int i = 0; i < EVENT_INFO.length; i++) {
801 				items[i].setChecked(true);
802 			}
803 			for (int i = 0; i < customNames.length; i++) {
804 				items[EVENT_INFO.length + i].setChecked(true);
805 			}
806 		}));
807 		Button deselectAll = new Button (dialog, SWT.PUSH);
808 		deselectAll.setText(ControlExample.getResourceString ("Deselect_All"));
809 		deselectAll.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
810 		deselectAll.addSelectionListener (widgetSelectedAdapter(e -> {
811 			TableItem [] items = table.getItems();
812 			for (int i = 0; i < EVENT_INFO.length; i++) {
813 				items[i].setChecked(false);
814 			}
815 			for (int i = 0; i < customNames.length; i++) {
816 				items[EVENT_INFO.length + i].setChecked(false);
817 			}
818 		}));
819 		final Button editEvent = new Button (dialog, SWT.PUSH);
820 		editEvent.setText (ControlExample.getResourceString ("Edit_Event"));
821 		editEvent.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.VERTICAL_ALIGN_BEGINNING));
822 		editEvent.addSelectionListener (widgetSelectedAdapter(e -> {
823 			Point pt = editEvent.getLocation();
824 			pt = e.display.map(editEvent, null, pt);
825 			int index = table.getSelectionIndex();
826 			if (getExampleWidgets().length > 0 && index != -1) {
827 				createEditEventDialog(dialog, pt.x, pt.y, index);
828 			}
829 		}));
830 		editEvent.setEnabled(false);
831 		table.addSelectionListener(new SelectionAdapter() {
832 			@Override
833 			public void widgetSelected(SelectionEvent e) {
834 				int fields = 0;
835 				int index = table.getSelectionIndex();
836 				if (index != -1 && index < EVENT_INFO.length) {  // TODO: Allow custom widgets to specify event info
837 					fields = (EVENT_INFO[index].settableFields);
838 				}
839 				editEvent.setEnabled(fields != 0);
840 			}
841 			@Override
842 			public void widgetDefaultSelected(SelectionEvent e) {
843 				if (editEvent.getEnabled()) {
844 					Point pt = editEvent.getLocation();
845 					pt = e.display.map(editEvent, null, pt);
846 					int index = table.getSelectionIndex();
847 					if (getExampleWidgets().length > 0 && index != -1 && index < EVENT_INFO.length) {
848 						createEditEventDialog(dialog, pt.x, pt.y, index);
849 					}
850 				}
851 			}
852 		});
853 
854 		new Label(dialog, SWT.NONE); /* Filler */
855 		Button ok = new Button (dialog, SWT.PUSH);
856 		ok.setText(ControlExample.getResourceString ("OK"));
857 		dialog.setDefaultButton(ok);
858 		ok.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
859 		ok.addSelectionListener (widgetSelectedAdapter(e -> {
860 			TableItem [] items = table.getItems();
861 			for (int i = 0; i < EVENT_INFO.length; i++) {
862 				eventsFilter[i] = items[i].getChecked();
863 			}
864 			for (int i = 0; i < customNames.length; i++) {
865 				eventsFilter[EVENT_INFO.length + i] = items[EVENT_INFO.length + i].getChecked();
866 			}
867 			dialog.dispose();
868 		}));
869 		dialog.pack ();
870 		/*
871 		 * If the preferred size of the dialog is too tall for the display,
872 		 * then reduce the height, so that the vertical scrollbar will appear.
873 		 */
874 		Rectangle bounds = dialog.getBounds();
875 		Rectangle trim = dialog.computeTrim(0, 0, 0, 0);
876 		Rectangle clientArea = display.getClientArea();
877 		if (bounds.height > clientArea.height) {
878 			dialog.setSize(bounds.width, clientArea.height - trim.height);
879 		}
880 		dialog.setLocation(bounds.x, clientArea.y);
881 		dialog.open ();
882 		while (! dialog.isDisposed()) {
883 			if (! display.readAndDispatch()) display.sleep();
884 		}
885 	}
886 
887 	/**
888 	 * Creates the "Listeners" group.  The "Listeners" group
889 	 * goes below the "Example" and "Control" groups.
890 	 */
createListenersGroup()891 	void createListenersGroup () {
892 		listenersGroup = new Group (tabFolderPage, SWT.NONE);
893 		listenersGroup.setLayout (new GridLayout (4, false));
894 		listenersGroup.setLayoutData (new GridData (SWT.FILL, SWT.FILL, true, true, 2, 1));
895 		listenersGroup.setText (ControlExample.getResourceString ("Listeners"));
896 
897 		/*
898 		 * Create the button to access the 'Listeners' dialog.
899 		 */
900 		Button listenersButton = new Button (listenersGroup, SWT.PUSH);
901 		listenersButton.setText (ControlExample.getResourceString ("Select_Listeners"));
902 		listenersButton.addSelectionListener (widgetSelectedAdapter(e -> {
903 			createListenerSelectionDialog ();
904 			recreateExampleWidgets ();
905 		}));
906 
907 		/*
908 		 * Create the checkbox to specify whether typed or untyped events are displayed in the log.
909 		 */
910 		final Button untypedEventsCheckbox = new Button (listenersGroup, SWT.CHECK);
911 		untypedEventsCheckbox.setText (ControlExample.getResourceString ("UntypedEvents"));
912 		untypedEventsCheckbox.addSelectionListener (widgetSelectedAdapter(e -> untypedEvents = untypedEventsCheckbox.getSelection ()));
913 
914 		/*
915 		 * Create the checkbox to add/remove listeners to/from the example widgets.
916 		 */
917 		final Button listenCheckbox = new Button (listenersGroup, SWT.CHECK);
918 		listenCheckbox.setText (ControlExample.getResourceString ("Listen"));
919 		listenCheckbox.addSelectionListener (widgetSelectedAdapter(e -> {
920 			logging = listenCheckbox.getSelection ();
921 			recreateExampleWidgets ();
922 		}));
923 
924 		/*
925 		 * Create the button to clear the text.
926 		 */
927 		Button clearButton = new Button (listenersGroup, SWT.PUSH);
928 		clearButton.setText (ControlExample.getResourceString ("Clear"));
929 		clearButton.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
930 		clearButton.addSelectionListener (widgetSelectedAdapter(e -> eventConsole.setText ("")));
931 
932 		/* Initialize the eventsFilter to log all events. */
933 		int customEventCount = getCustomEventNames ().length;
934 		eventsFilter = new boolean [EVENT_INFO.length + customEventCount];
935 		for (int i = 0; i < EVENT_INFO.length + customEventCount; i++) {
936 			eventsFilter [i] = true;
937 		}
938 
939 		/* Create the event console Text. */
940 		eventConsole = new Text (listenersGroup, SWT.BORDER | SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL);
941 		GridData data = new GridData (GridData.FILL_BOTH);
942 		data.horizontalSpan = 4;
943 		data.heightHint = 80;
944 		eventConsole.setLayoutData (data);
945 		createEventConsolePopup ();
946 		eventConsole.addKeyListener (new KeyAdapter () {
947 			@Override
948 			public void keyPressed (KeyEvent e) {
949 				if ((e.keyCode == 'A' || e.keyCode == 'a') && (e.stateMask & SWT.MOD1) != 0) {
950 					eventConsole.selectAll ();
951 					e.doit = false;
952 				}
953 			}
954 		});
955 	}
956 
957 	/**
958 	 * Returns a list of set/get API method names (without the set/get prefix)
959 	 * that can be used to set/get values in the example control(s).
960 	 */
getMethodNames()961 	String[] getMethodNames() {
962 		return null;
963 	}
964 
createSetGetDialog(String[] methodNames)965 	Shell createSetGetDialog(String[] methodNames) {
966 		final Shell dialog = new Shell(shell, SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MODELESS);
967 		dialog.setLayout(new GridLayout(2, false));
968 		dialog.setText(getTabText() + " " + ControlExample.getResourceString ("Set_Get"));
969 		nameCombo = new Combo(dialog, SWT.READ_ONLY);
970 		nameCombo.setItems(methodNames);
971 		nameCombo.setText(methodNames[0]);
972 		nameCombo.setVisibleItemCount(methodNames.length);
973 		nameCombo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
974 		nameCombo.addSelectionListener(widgetSelectedAdapter(e -> resetLabels()));
975 		returnTypeLabel = new Label(dialog, SWT.NONE);
976 		returnTypeLabel.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, false, false));
977 		setButton = new Button(dialog, SWT.PUSH);
978 		setButton.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, false, false));
979 		setButton.addSelectionListener(widgetSelectedAdapter(e -> {
980 			setValue();
981 			setText.selectAll();
982 			setText.setFocus();
983 		}));
984 		setText = new Text(dialog, SWT.SINGLE | SWT.BORDER);
985 		setText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
986 		getButton = new Button(dialog, SWT.PUSH);
987 		getButton.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, false, false));
988 		getButton.addSelectionListener(widgetSelectedAdapter(e -> getValue()));
989 		getText = new Text(dialog, SWT.MULTI | SWT.BORDER | SWT.READ_ONLY | SWT.H_SCROLL | SWT.V_SCROLL);
990 		GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
991 		data.widthHint = 240;
992 		data.heightHint = 200;
993 		getText.setLayoutData(data);
994 		resetLabels();
995 		dialog.setDefaultButton(setButton);
996 		dialog.pack();
997 		dialog.addDisposeListener(e -> setGetDialog = null);
998 		return dialog;
999 	}
1000 
resetLabels()1001 	void resetLabels() {
1002 		String methodRoot = nameCombo.getText();
1003 		returnTypeLabel.setText(parameterInfo(methodRoot));
1004 		setButton.setText(setMethodName(methodRoot));
1005 		getButton.setText("get" + methodRoot);
1006 		setText.setText("");
1007 		getText.setText("");
1008 		getValue();
1009 		setText.setFocus();
1010 	}
1011 
setMethodName(String methodRoot)1012 	String setMethodName(String methodRoot) {
1013 		return "set" + methodRoot;
1014 	}
1015 
parameterInfo(String methodRoot)1016 	String parameterInfo(String methodRoot) {
1017 		String typeName = null;
1018 		Class<?> returnType = getReturnType(methodRoot);
1019 		boolean isArray = returnType.isArray();
1020 		if (isArray) {
1021 			typeName = returnType.getComponentType().getName();
1022 		} else {
1023 			typeName = returnType.getName();
1024 		}
1025 		String typeNameString = typeName;
1026 		int index = typeName.lastIndexOf('.');
1027 		if (index != -1 && index+1 < typeName.length()) typeNameString = typeName.substring(index+1);
1028 		String info = ControlExample.getResourceString("Info_" + typeNameString + (isArray ? "A" : ""));
1029 		if (isArray) {
1030 			typeNameString += "[]";
1031 		}
1032 		return ControlExample.getResourceString("Parameter_Info", new Object[] {typeNameString, info});
1033 	}
1034 
getValue()1035 	void getValue() {
1036 		String methodName = "get" + nameCombo.getText();
1037 		getText.setText("");
1038 		Widget[] widgets = getExampleWidgets();
1039 		for (int i = 0; i < widgets.length; i++) {
1040 			try {
1041 				if (widgets[i] == null) {
1042 					continue;
1043 				}
1044 				Method method = widgets[i].getClass().getMethod(methodName);
1045 				Object result = method.invoke(widgets[i]);
1046 				if (result == null) {
1047 					getText.append("null");
1048 				} else if (result.getClass().isArray()) {
1049 					int length = java.lang.reflect.Array.getLength(result);
1050 					if (length == 0) {
1051 						getText.append(result.getClass().getComponentType() + "[0]");
1052 					}
1053 					for (int j = 0; j < length; j++) {
1054 						getText.append(java.lang.reflect.Array.get(result,j).toString() + "\n");
1055 					}
1056 				} else {
1057 					getText.append(result.toString());
1058 				}
1059 			} catch (Exception e) {
1060 				getText.append(e.toString());
1061 			}
1062 			if (i + 1 < widgets.length) {
1063 				getText.append("\n\n");
1064 			}
1065 		}
1066 	}
1067 
getReturnType(String methodRoot)1068 	Class<?> getReturnType(String methodRoot) {
1069 		Class<?> returnType = null;
1070 		String methodName = "get" + methodRoot;
1071 		Widget[] widgets = getExampleWidgets();
1072 		try {
1073 			Method method = widgets[0].getClass().getMethod(methodName);
1074 			returnType = method.getReturnType();
1075 		} catch (Exception e) {
1076 		}
1077 		return returnType;
1078 	}
1079 
setValue()1080 	void setValue() {
1081 		/* The parameter type must be the same as the get method's return type */
1082 		String methodRoot = nameCombo.getText();
1083 		Class<?> returnType = getReturnType(methodRoot);
1084 		String methodName = setMethodName(methodRoot);
1085 		String value = setText.getText();
1086 		Widget[] widgets = getExampleWidgets();
1087 		for (Widget widget : widgets) {
1088 			try {
1089 				if (widget == null) {
1090 					continue;
1091 				}
1092 				java.lang.reflect.Method method = widget.getClass().getMethod(methodName, returnType);
1093 				String typeName = returnType.getName();
1094 				Object[] parameter = null;
1095 				if (value.equals("null")) {
1096 					parameter = new Object[] {null};
1097 				} else if (typeName.equals("int")) {
1098 					parameter = new Object[] {Integer.valueOf(value)};
1099 				} else if (typeName.equals("long")) {
1100 					parameter = new Object[] {Long.valueOf(value)};
1101 				} else if (typeName.equals("char")) {
1102 					parameter = new Object[] {value.length() == 1 ? Character.valueOf(value.charAt(0)) : Character.valueOf('\0')};
1103 				} else if (typeName.equals("boolean")) {
1104 					parameter = new Object[] {Boolean.valueOf(value)};
1105 				} else if (typeName.equals("java.lang.String")) {
1106 					parameter = new Object[] {value};
1107 				} else if (typeName.equals("org.eclipse.swt.graphics.Point")) {
1108 					String xy[] = split(value, ',');
1109 					parameter = new Object[] {new Point(Integer.parseInt(xy[0]),Integer.parseInt(xy[1]))};
1110 				} else if (typeName.equals("org.eclipse.swt.graphics.Rectangle")) {
1111 					String xywh[] = split(value, ',');
1112 					parameter = new Object[] {new Rectangle(Integer.parseInt(xywh[0]),Integer.parseInt(xywh[1]),Integer.parseInt(xywh[2]),Integer.parseInt(xywh[3]))};
1113 				} else if (typeName.equals("[I")) {
1114 					String strings[] = split(value, ',');
1115 					int[] ints = new int[strings.length];
1116 					for (int j = 0; j < strings.length; j++) {
1117 						ints[j] = Integer.valueOf(strings[j]).intValue();
1118 					}
1119 					parameter = new Object[] {ints};
1120 				} else if (typeName.equals("[C")) {
1121 					String strings[] = split(value, ',');
1122 					char[] chars = new char[strings.length];
1123 					for (int j = 0; j < strings.length; j++) {
1124 						chars[j] = strings[j].charAt(0);
1125 					}
1126 					parameter = new Object[] {chars};
1127 				} else if (typeName.equals("[Ljava.lang.String;")) {
1128 					parameter = new Object[] {split(value, ',')};
1129 				} else {
1130 					parameter = parameterForType(typeName, value, widget);
1131 				}
1132 				method.invoke(widget, parameter);
1133 			} catch (Exception e) {
1134 				Throwable cause = e.getCause();
1135 				String message = e.getMessage();
1136 				getText.setText(e.toString());
1137 				if (cause != null) getText.append(", cause=\n" + cause.toString());
1138 				if (message != null) getText.append(", message=\n" + message);
1139 			}
1140 		}
1141 	}
1142 
parameterForType(String typeName, String value, Widget widget)1143 	Object[] parameterForType(String typeName, String value, Widget widget) {
1144 		return new Object[] {value};
1145 	}
1146 
createOrientationGroup()1147 	void createOrientationGroup () {
1148 		/* Create Orientation group*/
1149 		orientationGroup = new Group (controlGroup, SWT.NONE);
1150 		orientationGroup.setLayout (new GridLayout());
1151 		orientationGroup.setLayoutData (new GridData (SWT.FILL, SWT.FILL, false, false));
1152 		orientationGroup.setText (ControlExample.getResourceString("Orientation"));
1153 		defaultOrietationButton = new Button (orientationGroup, SWT.RADIO);
1154 		defaultOrietationButton.setText (ControlExample.getResourceString("Default"));
1155 		defaultOrietationButton.setSelection (true);
1156 		ltrButton = new Button (orientationGroup, SWT.RADIO);
1157 		ltrButton.setText ("SWT.LEFT_TO_RIGHT");
1158 		rtlButton = new Button (orientationGroup, SWT.RADIO);
1159 		rtlButton.setText ("SWT.RIGHT_TO_LEFT");
1160 	}
1161 
createDirectionGroup()1162 	void createDirectionGroup () {
1163 		/* Create Text Direction group*/
1164 		directionGroup = new Group (controlGroup, SWT.NONE);
1165 		directionGroup.setLayout (new GridLayout());
1166 		directionGroup.setLayoutData (new GridData (SWT.FILL, SWT.FILL, false, false));
1167 		directionGroup.setText (ControlExample.getResourceString("Text_Direction"));
1168 		defaultDirectionButton = new Button (directionGroup, SWT.RADIO);
1169 		defaultDirectionButton.setText (ControlExample.getResourceString("Default"));
1170 		defaultDirectionButton.setSelection (true);
1171 		ltrDirectionButton = new Button (directionGroup, SWT.RADIO);
1172 		ltrDirectionButton.setText ("SWT.LEFT_TO_RIGHT");
1173 		rtlDirectionButton = new Button (directionGroup, SWT.RADIO);
1174 		rtlDirectionButton.setText ("SWT.RIGHT_TO_LEFT");
1175 		autoDirectionButton = new Button (directionGroup, SWT.RADIO);
1176 		autoDirectionButton.setText ("AUTO direction");
1177 	}
1178 
1179 	/**
1180 	 * Creates the "Size" group.  The "Size" group contains
1181 	 * controls that allow the user to change the size of
1182 	 * the example widgets.
1183 	 */
createSizeGroup()1184 	void createSizeGroup () {
1185 		/* Create the group */
1186 		sizeGroup = new Group (controlGroup, SWT.NONE);
1187 		sizeGroup.setLayout (new GridLayout());
1188 		sizeGroup.setLayoutData (new GridData (SWT.FILL, SWT.FILL, false, false));
1189 		sizeGroup.setText (ControlExample.getResourceString("Size"));
1190 
1191 		/* Create the controls */
1192 
1193 		/*
1194 		 * The preferred size of a widget is the size returned
1195 		 * by widget.computeSize (SWT.DEFAULT, SWT.DEFAULT).
1196 		 * This size is defined on a widget by widget basis.
1197 		 * Many widgets will attempt to display their contents.
1198 		 */
1199 		preferredButton = new Button (sizeGroup, SWT.RADIO);
1200 		preferredButton.setText (ControlExample.getResourceString("Preferred"));
1201 		tooSmallButton = new Button (sizeGroup, SWT.RADIO);
1202 		tooSmallButton.setText (TOO_SMALL_SIZE + " X " + TOO_SMALL_SIZE);
1203 		smallButton = new Button(sizeGroup, SWT.RADIO);
1204 		smallButton.setText (SMALL_SIZE + " X " + SMALL_SIZE);
1205 		largeButton = new Button (sizeGroup, SWT.RADIO);
1206 		largeButton.setText (LARGE_SIZE + " X " + LARGE_SIZE);
1207 		rectangleButton = new Button (sizeGroup, SWT.RADIO);
1208 		rectangleButton.setText (RETANGLE_SIZE_WIDTH + " X " + RETANGLE_SIZE_HEIGHT);
1209 		fillHButton = new Button (sizeGroup, SWT.CHECK);
1210 		fillHButton.setText (ControlExample.getResourceString("Fill_X"));
1211 		fillVButton = new Button (sizeGroup, SWT.CHECK);
1212 		fillVButton.setText (ControlExample.getResourceString("Fill_Y"));
1213 
1214 		/* Add the listeners */
1215 		SelectionListener selectionListener = widgetSelectedAdapter(event -> setExampleWidgetSize ());
1216 		preferredButton.addSelectionListener(selectionListener);
1217 		tooSmallButton.addSelectionListener(selectionListener);
1218 		smallButton.addSelectionListener(selectionListener);
1219 		largeButton.addSelectionListener(selectionListener);
1220 		rectangleButton.addSelectionListener(selectionListener);
1221 		fillHButton.addSelectionListener(selectionListener);
1222 		fillVButton.addSelectionListener(selectionListener);
1223 
1224 		/* Set the default state */
1225 		preferredButton.setSelection (true);
1226 	}
1227 
1228 	/**
1229 	 * Creates the "Style" group.  The "Style" group contains
1230 	 * controls that allow the user to change the style of
1231 	 * the example widgets.  Changing a widget "Style" causes
1232 	 * the widget to be destroyed and recreated.
1233 	 */
createStyleGroup()1234 	void createStyleGroup () {
1235 		styleGroup = new Group (controlGroup, SWT.NONE);
1236 		styleGroup.setLayout (new GridLayout ());
1237 		styleGroup.setLayoutData (new GridData (SWT.FILL, SWT.FILL, false, false));
1238 		styleGroup.setText (ControlExample.getResourceString("Styles"));
1239 	}
1240 
1241 	/**
1242 	 * Creates the tab folder page.
1243 	 *
1244 	 * @param tabFolder org.eclipse.swt.widgets.TabFolder
1245 	 * @return the new page for the tab folder
1246 	 */
createTabFolderPage(TabFolder tabFolder)1247 	Composite createTabFolderPage (TabFolder tabFolder) {
1248 		/* Cache the shell and display. */
1249 		shell = tabFolder.getShell ();
1250 		display = shell.getDisplay ();
1251 
1252 		/* Create a two column page. */
1253 		tabFolderPage = new Composite (tabFolder, SWT.NONE);
1254 		tabFolderPage.setLayout (new GridLayout (2, false));
1255 
1256 		/* Create the "Example" and "Control" groups. */
1257 		createExampleGroup ();
1258 		createControlGroup ();
1259 
1260 		/* Create the "Listeners" group under the "Control" group. */
1261 		createListenersGroup ();
1262 
1263 		/* Create and initialize the example and control widgets. */
1264 		createExampleWidgets ();
1265 		hookExampleWidgetListeners ();
1266 		createControlWidgets ();
1267 		setExampleWidgetState ();
1268 
1269 		return tabFolderPage;
1270 	}
1271 
setExampleWidgetPopupMenu()1272 	void setExampleWidgetPopupMenu() {
1273 		Control[] controls = getExampleControls();
1274 		for (final Control control : controls) {
1275 			control.addListener(SWT.MenuDetect, event -> {
1276 				Menu menu = control.getMenu();
1277 				if (menu != null && samplePopup) {
1278 					menu.dispose();
1279 					menu = null;
1280 				}
1281 				if (menu == null && popupMenuButton.getSelection()) {
1282 					menu = new Menu(shell, SWT.POP_UP | (control.getStyle() & (SWT.RIGHT_TO_LEFT | SWT.LEFT_TO_RIGHT)));
1283 					MenuItem item = new MenuItem(menu, SWT.PUSH);
1284 					item.setText("Sample popup menu item");
1285 					specialPopupMenuItems(menu, event);
1286 					control.setMenu(menu);
1287 					samplePopup = true;
1288 				}
1289 			});
1290 		}
1291 	}
1292 
specialPopupMenuItems(final Menu menu, final Event event)1293 	protected void specialPopupMenuItems(final Menu menu, final Event event) {
1294 	}
1295 
1296 	/**
1297 	 * Disposes the "Example" widgets.
1298 	 */
disposeExampleWidgets()1299 	void disposeExampleWidgets () {
1300 		Widget [] widgets = getExampleWidgets ();
1301 		for (Widget widget : widgets) {
1302 			widget.dispose ();
1303 		}
1304 	}
1305 
colorImage(Color color)1306 	Image colorImage (Color color) {
1307 		Image image = new Image (display, IMAGE_SIZE, IMAGE_SIZE);
1308 		GC gc = new GC(image);
1309 		gc.setBackground(color);
1310 		Rectangle bounds = image.getBounds();
1311 		gc.fillRectangle(0, 0, bounds.width, bounds.height);
1312 		gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
1313 		gc.drawRectangle(0, 0, bounds.width - 1, bounds.height - 1);
1314 		gc.dispose();
1315 		return image;
1316 	}
1317 
fontImage(Font font)1318 	Image fontImage (Font font) {
1319 		Image image = new Image (display, IMAGE_SIZE, IMAGE_SIZE);
1320 		GC gc = new GC(image);
1321 		Rectangle bounds = image.getBounds();
1322 		gc.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
1323 		gc.fillRectangle(0, 0, bounds.width, bounds.height);
1324 		gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
1325 		gc.drawRectangle(0, 0, bounds.width - 1, bounds.height - 1);
1326 		FontData data[] = font.getFontData();
1327 		int style = data[0].getStyle();
1328 		switch (style) {
1329 		case SWT.NORMAL:
1330 			gc.drawLine(3, 3, 3, 8);
1331 			gc.drawLine(4, 3, 7, 8);
1332 			gc.drawLine(8, 3, 8, 8);
1333 			break;
1334 		case SWT.BOLD:
1335 			gc.drawLine(3, 2, 3, 9);
1336 			gc.drawLine(4, 2, 4, 9);
1337 			gc.drawLine(5, 2, 7, 2);
1338 			gc.drawLine(5, 3, 8, 3);
1339 			gc.drawLine(5, 5, 7, 5);
1340 			gc.drawLine(5, 6, 7, 6);
1341 			gc.drawLine(5, 8, 8, 8);
1342 			gc.drawLine(5, 9, 7, 9);
1343 			gc.drawLine(7, 4, 8, 4);
1344 			gc.drawLine(7, 7, 8, 7);
1345 			break;
1346 		case SWT.ITALIC:
1347 			gc.drawLine(6, 2, 8, 2);
1348 			gc.drawLine(7, 3, 4, 8);
1349 			gc.drawLine(3, 9, 5, 9);
1350 			break;
1351 		case SWT.BOLD | SWT.ITALIC:
1352 			gc.drawLine(5, 2, 8, 2);
1353 			gc.drawLine(5, 3, 8, 3);
1354 			gc.drawLine(6, 4, 4, 7);
1355 			gc.drawLine(7, 4, 5, 7);
1356 			gc.drawLine(3, 8, 6, 8);
1357 			gc.drawLine(3, 9, 6, 9);
1358 			break;
1359 		}
1360 		gc.dispose();
1361 		return image;
1362 	}
1363 
1364 	/**
1365 	 * Gets the list of custom event names.
1366 	 * Subclasses override this method to allow adding of custom events.
1367 	 *
1368 	 * @return an array containing custom event names
1369 	 * @see hookCustomListener
1370 	 */
getCustomEventNames()1371 	String [] getCustomEventNames () {
1372 		return new String [0];
1373 	}
1374 
1375 	/**
1376 	 * Gets the default style for a widget
1377 	 *
1378 	 * @return the default style bit
1379 	 */
getDefaultStyle()1380 	int getDefaultStyle () {
1381 		if (ltrButton != null && ltrButton.getSelection()) {
1382 			return SWT.LEFT_TO_RIGHT;
1383 		}
1384 		if (rtlButton != null && rtlButton.getSelection()) {
1385 			return SWT.RIGHT_TO_LEFT;
1386 		}
1387 		return SWT.NONE;
1388 	}
1389 
1390 	/**
1391 	 * Gets the "Example" widgets.
1392 	 *
1393 	 * @return an array containing the example widgets
1394 	 */
getExampleWidgets()1395 	Widget [] getExampleWidgets () {
1396 		return new Widget [0];
1397 	}
1398 
1399 	/**
1400 	 * Gets the "Example" controls.
1401 	 * This is the subset of "Example" widgets that are controls.
1402 	 *
1403 	 * @return an array containing the example controls
1404 	 */
getExampleControls()1405 	Control [] getExampleControls () {
1406 		Widget [] widgets = getExampleWidgets ();
1407 		Control [] controls = new Control [0];
1408 		for (Widget widget : widgets) {
1409 			if (widget instanceof Control) {
1410 				Control[] newControls = new Control[controls.length + 1];
1411 				System.arraycopy(controls, 0, newControls, 0, controls.length);
1412 				controls = newControls;
1413 				controls[controls.length - 1] = (Control)widget;
1414 			}
1415 		}
1416 		return controls;
1417 	}
1418 
1419 	/**
1420 	 * Gets the "Example" widget's items, if any.
1421 	 *
1422 	 * @return an array containing the example widget's items
1423 	 */
getExampleWidgetItems()1424 	Item [] getExampleWidgetItems () {
1425 		return new Item [0];
1426 	}
1427 
1428 	/**
1429 	 * Gets the short text for the tab folder item.
1430 	 *
1431 	 * @return the short text for the tab item
1432 	 */
getShortTabText()1433 	String getShortTabText() {
1434 		return getTabText();
1435 	}
1436 
1437 	/**
1438 	 * Gets the text for the tab folder item.
1439 	 *
1440 	 * @return the text for the tab item
1441 	 */
getTabText()1442 	String getTabText () {
1443 		return "";
1444 	}
1445 
1446 	/**
1447 	 * In case one of the buttons that control text direction was selected,
1448 	 * apply the text direction on the controls in the client area.
1449 	 *
1450 	 * @return false iff example widgets must be re-created
1451 	 */
handleTextDirection(Widget widget)1452 	boolean handleTextDirection (Widget widget) {
1453 		if (!rtlSupport ()) {
1454 			return false;
1455 		}
1456 		int textDirection = SWT.NONE;
1457 		if (ltrDirectionButton.equals (widget)) {
1458 			textDirection = SWT.LEFT_TO_RIGHT;
1459 		} else if (rtlDirectionButton.equals (widget)) {
1460 			textDirection = SWT.RIGHT_TO_LEFT;
1461 		} else if (autoDirectionButton.equals (widget)) {
1462 			textDirection = SWT.AUTO_TEXT_DIRECTION;
1463 		} else if (!defaultDirectionButton.equals (widget)) {
1464 			return false;
1465 		}
1466 		Control [] children = getExampleControls ();
1467 		if (children.length > 0) {
1468 			if (SWT.NONE == textDirection) {
1469 				textDirection = children [0].getOrientation ();
1470 			}
1471 			for (Control child : children) {
1472 				child.setTextDirection (textDirection);
1473 			}
1474 		}
1475 		return true;
1476 	}
1477 
1478 	/**
1479 	 * Hooks all listeners to all example controls
1480 	 * and example control items.
1481 	 */
hookExampleWidgetListeners()1482 	void hookExampleWidgetListeners () {
1483 		if (logging) {
1484 			Widget[] widgets = getExampleWidgets ();
1485 			for (Widget widget : widgets) {
1486 				hookListeners (widget);
1487 			}
1488 			Item[] exampleItems = getExampleWidgetItems ();
1489 			for (Item exampleItem : exampleItems) {
1490 				hookListeners (exampleItem);
1491 			}
1492 			String [] customNames = getCustomEventNames ();
1493 			for (int i = 0; i < customNames.length; i++) {
1494 				if (eventsFilter [EVENT_INFO.length + i]) {
1495 					hookCustomListener (customNames[i]);
1496 				}
1497 			}
1498 		}
1499 	}
1500 
1501 	/**
1502 	 * Hooks the custom listener specified by eventName.
1503 	 * Subclasses override this method to add custom listeners.
1504 	 * @see getCustomEventNames
1505 	 */
hookCustomListener(String eventName)1506 	void hookCustomListener (String eventName) {
1507 	}
1508 
1509 	/**
1510 	 * Hooks all listeners to the specified widget.
1511 	 */
hookListeners(Widget widget)1512 	void hookListeners (Widget widget) {
1513 		if (logging) {
1514 			Listener listener = event -> log (event);
1515 			for (int i = 0; i < EVENT_INFO.length; i++) {
1516 				if (eventsFilter [i]) {
1517 					widget.addListener (EVENT_INFO[i].type, listener);
1518 				}
1519 			}
1520 		}
1521 	}
1522 
1523 	/**
1524 	 * Logs an untyped event to the event console.
1525 	 */
log(Event event)1526 	void log(Event event) {
1527 		int i = 0;
1528 		while (i < EVENT_INFO.length) {
1529 			if (EVENT_INFO[i].type == event.type) break;
1530 			i++;
1531 		}
1532 		String toString = EVENT_INFO[i].name + " [" + event.type + "]: ";
1533 		if (!untypedEvents) {
1534 			switch (event.type) {
1535 				case SWT.KeyDown:
1536 				case SWT.KeyUp: toString += new KeyEvent (event).toString (); break;
1537 				case SWT.MouseDown:
1538 				case SWT.MouseUp:
1539 				case SWT.MouseMove:
1540 				case SWT.MouseEnter:
1541 				case SWT.MouseExit:
1542 				case SWT.MouseDoubleClick:
1543 				case SWT.MouseWheel:
1544 				case SWT.MouseHover: toString += new MouseEvent (event).toString (); break;
1545 				case SWT.Paint: toString += new PaintEvent (event).toString (); break;
1546 				case SWT.Move:
1547 				case SWT.Resize: toString += new ControlEvent (event).toString (); break;
1548 				case SWT.Dispose: toString += new DisposeEvent (event).toString (); break;
1549 				case SWT.Selection:
1550 				case SWT.DefaultSelection: toString += new SelectionEvent (event).toString (); break;
1551 				case SWT.FocusIn:
1552 				case SWT.FocusOut: toString += new FocusEvent (event).toString (); break;
1553 				case SWT.Expand:
1554 				case SWT.Collapse: toString += new TreeEvent (event).toString (); break;
1555 				case SWT.Iconify:
1556 				case SWT.Deiconify:
1557 				case SWT.Close:
1558 				case SWT.Activate:
1559 				case SWT.Deactivate: toString += new ShellEvent (event).toString (); break;
1560 				case SWT.Show:
1561 				case SWT.Hide: toString += (event.widget instanceof Menu) ? new MenuEvent (event).toString () : event.toString(); break;
1562 				case SWT.Modify: toString += new ModifyEvent (event).toString (); break;
1563 				case SWT.Verify: toString += new VerifyEvent (event).toString (); break;
1564 				case SWT.Help: toString += new HelpEvent (event).toString (); break;
1565 				case SWT.Arm: toString += new ArmEvent (event).toString (); break;
1566 				case SWT.Traverse: toString += new TraverseEvent (event).toString (); break;
1567 				case SWT.HardKeyDown:
1568 				case SWT.HardKeyUp:
1569 				case SWT.DragDetect:
1570 				case SWT.MenuDetect:
1571 				case SWT.SetData:
1572 				default: toString += event.toString ();
1573 			}
1574 		} else {
1575 			toString += event.toString();
1576 		}
1577 		log (toString);
1578 
1579 		/* Return values for event fields. */
1580 		int mask = EVENT_INFO[i].setFields;
1581 		if (!ignore && mask != 0) {
1582 			Event setFieldsEvent = EVENT_INFO[i].event;
1583 			if ((mask & DOIT) != 0) event.doit = setFieldsEvent.doit;
1584 			if ((mask & DETAIL) != 0) event.detail = setFieldsEvent.detail;
1585 			if ((mask & TEXT) != 0) event.text = setFieldsEvent.text;
1586 			if ((mask & X) != 0) event.x = setFieldsEvent.x;
1587 			if ((mask & Y) != 0) event.y = setFieldsEvent.y;
1588 			if ((mask & WIDTH) != 0) event.width = setFieldsEvent.width;
1589 			if ((mask & HEIGHT) != 0) event.height = setFieldsEvent.height;
1590 			eventConsole.append (ControlExample.getResourceString("Returning"));
1591 			ignore = true;
1592 			log (event);
1593 			ignore = false;
1594 		}
1595 	}
1596 
1597 	/**
1598 	 * Logs a string to the event console.
1599 	 */
log(String string)1600 	void log (String string) {
1601 		if (!eventConsole.isDisposed()) {
1602 			eventConsole.append (string);
1603 			eventConsole.append ("\n");
1604 		}
1605 	}
1606 
1607 	/**
1608 	 * Logs a typed event to the event console.
1609 	 */
log(String eventName, TypedEvent event)1610 	void log (String eventName, TypedEvent event) {
1611 		log (eventName + ": " + event.toString ());
1612 	}
1613 
1614 	/**
1615 	 * Recreates the "Example" widgets.
1616 	 */
recreateExampleWidgets()1617 	void recreateExampleWidgets () {
1618 		disposeExampleWidgets ();
1619 		createExampleWidgets ();
1620 		hookExampleWidgetListeners ();
1621 		setExampleWidgetState ();
1622 	}
1623 
1624 	/**
1625 	 * Sets the foreground color, background color, and font
1626 	 * of the "Example" widgets to their default settings.
1627 	 * Subclasses may extend in order to reset other colors
1628 	 * and fonts to default settings as well.
1629 	 */
resetColorsAndFonts()1630 	void resetColorsAndFonts () {
1631 		Color oldColor = foregroundColor;
1632 		foregroundColor = null;
1633 		setExampleWidgetForeground ();
1634 		if (oldColor != null) oldColor.dispose();
1635 		oldColor = backgroundColor;
1636 		backgroundColor = null;
1637 		setExampleWidgetBackground ();
1638 		if (oldColor != null) oldColor.dispose();
1639 		Font oldFont = font;
1640 		font = null;
1641 		setExampleWidgetFont ();
1642 		setExampleWidgetSize ();
1643 		if (oldFont != null) oldFont.dispose();
1644 	}
1645 
rtlSupport()1646 	boolean rtlSupport() {
1647 		return RTL_SUPPORT_ENABLE;
1648 	}
1649 
1650 	/**
1651 	 * Sets the background color of the "Example" widgets' parent.
1652 	 */
setExampleGroupBackgroundColor()1653 	void setExampleGroupBackgroundColor () {
1654 		if (backgroundModeGroup == null) return;
1655 		exampleGroup.setBackground (backgroundModeColorButton.getSelection () ? display.getSystemColor(SWT.COLOR_BLUE) : null);
1656 	}
1657 	/**
1658 	 * Sets the background image of the "Example" widgets' parent.
1659 	 */
setExampleGroupBackgroundImage()1660 	void setExampleGroupBackgroundImage () {
1661 		if (backgroundModeGroup == null) return;
1662 		exampleGroup.setBackgroundImage (backgroundModeImageButton.getSelection () ? instance.images[ControlExample.ciParentBackground] : null);
1663 	}
1664 
1665 	/**
1666 	 * Sets the background mode of the "Example" widgets' parent.
1667 	 */
setExampleGroupBackgroundMode()1668 	void setExampleGroupBackgroundMode () {
1669 		if (backgroundModeGroup == null) return;
1670 		String modeString = backgroundModeCombo.getText ();
1671 		int mode = SWT.INHERIT_NONE;
1672 		if (modeString.equals("SWT.INHERIT_DEFAULT")) mode = SWT.INHERIT_DEFAULT;
1673 		if (modeString.equals("SWT.INHERIT_FORCE")) mode = SWT.INHERIT_FORCE;
1674 		exampleGroup.setBackgroundMode (mode);
1675 	}
1676 
1677 	/**
1678 	 * Sets the background color of the "Example" widgets.
1679 	 */
setExampleWidgetBackground()1680 	void setExampleWidgetBackground () {
1681 		if (colorAndFontTable == null) return; // user cannot change color/font on this tab
1682 		Control [] controls = getExampleControls ();
1683 		if (!instance.startup) {
1684 			for (Control control : controls) {
1685 				control.setBackground (backgroundColor);
1686 			}
1687 		}
1688 		// Set the background color item's image to match the background color of the example widget(s).
1689 		Color color = backgroundColor;
1690 		if (controls.length == 0) return;
1691 		if (color == null) color = controls [0].getBackground ();
1692 		TableItem item = colorAndFontTable.getItem(BACKGROUND_COLOR);
1693 		Image oldImage = item.getImage();
1694 		if (oldImage != null) oldImage.dispose();
1695 		item.setImage (colorImage (color));
1696 	}
1697 
1698 	/**
1699 	 * Sets the enabled state of the "Example" widgets.
1700 	 */
setExampleWidgetEnabled()1701 	void setExampleWidgetEnabled () {
1702 		Control [] controls = getExampleControls ();
1703 		for (Control control : controls) {
1704 			control.setEnabled (enabledButton.getSelection ());
1705 		}
1706 	}
1707 
1708 	/**
1709 	 * Sets the font of the "Example" widgets.
1710 	 */
setExampleWidgetFont()1711 	void setExampleWidgetFont () {
1712 		if (colorAndFontTable == null) return; // user cannot change color/font on this tab
1713 		Control [] controls = getExampleControls ();
1714 		if (!instance.startup) {
1715 			for (Control control : controls) {
1716 				control.setFont(font);
1717 			}
1718 		}
1719 		/* Set the font item's image and font to match the font of the example widget(s). */
1720 		Font ft = font;
1721 		if (controls.length == 0) return;
1722 		if (ft == null) ft = controls [0].getFont ();
1723 		TableItem item = colorAndFontTable.getItem(FONT);
1724 		Image oldImage = item.getImage();
1725 		if (oldImage != null) oldImage.dispose();
1726 		item.setImage (fontImage (ft));
1727 		item.setFont(ft);
1728 		colorAndFontTable.layout ();
1729 	}
1730 
1731 	/**
1732 	 * Sets the foreground color of the "Example" widgets.
1733 	 */
setExampleWidgetForeground()1734 	void setExampleWidgetForeground () {
1735 		if (colorAndFontTable == null) return; // user cannot change color/font on this tab
1736 		Control [] controls = getExampleControls ();
1737 		if (!instance.startup) {
1738 			for (Control control : controls) {
1739 				control.setForeground (foregroundColor);
1740 			}
1741 		}
1742 		/* Set the foreground color item's image to match the foreground color of the example widget(s). */
1743 		Color color = foregroundColor;
1744 		if (controls.length == 0) return;
1745 		if (color == null) color = controls [0].getForeground ();
1746 		TableItem item = colorAndFontTable.getItem(FOREGROUND_COLOR);
1747 		Image oldImage = item.getImage();
1748 		if (oldImage != null) oldImage.dispose();
1749 		item.setImage (colorImage(color));
1750 	}
1751 
1752 	/**
1753 	 * Sets the size of the "Example" widgets.
1754 	 */
setExampleWidgetSize()1755 	void setExampleWidgetSize () {
1756 		int size = SWT.DEFAULT;
1757 		if (preferredButton == null) return;
1758 		if (preferredButton.getSelection()) size = SWT.DEFAULT;
1759 		if (tooSmallButton.getSelection()) size = TOO_SMALL_SIZE;
1760 		if (smallButton.getSelection()) size = SMALL_SIZE;
1761 		if (largeButton.getSelection()) size = LARGE_SIZE;
1762 		Control [] controls = getExampleControls ();
1763 		for (Control control : controls) {
1764 			GridData gridData = new GridData(size, size);
1765 			if (rectangleButton.getSelection()) {
1766 				gridData = new GridData(RETANGLE_SIZE_WIDTH, RETANGLE_SIZE_HEIGHT);
1767 			}
1768 			gridData.grabExcessHorizontalSpace = fillHButton.getSelection();
1769 			gridData.grabExcessVerticalSpace = fillVButton.getSelection();
1770 			gridData.horizontalAlignment = fillHButton.getSelection() ? SWT.FILL : SWT.LEFT;
1771 			gridData.verticalAlignment = fillVButton.getSelection() ? SWT.FILL : SWT.TOP;
1772 			control.setLayoutData (gridData);
1773 		}
1774 		tabFolderPage.layout (controls);
1775 	}
1776 
1777 	/**
1778 	 * Sets the state of the "Example" widgets.  Subclasses
1779 	 * may extend this method to set "Example" widget state
1780 	 * that is specific to the widget.
1781 	 */
setExampleWidgetState()1782 	void setExampleWidgetState () {
1783 		setExampleWidgetBackground ();
1784 		setExampleWidgetForeground ();
1785 		setExampleWidgetFont ();
1786 		if (!instance.startup) {
1787 			setExampleWidgetEnabled ();
1788 			setExampleWidgetVisibility ();
1789 			setExampleGroupBackgroundMode ();
1790 			setExampleGroupBackgroundColor ();
1791 			setExampleGroupBackgroundImage ();
1792 			setExampleWidgetBackgroundImage ();
1793 			setExampleWidgetPopupMenu ();
1794 			setExampleWidgetSize ();
1795 		}
1796 		//TEMPORARY CODE
1797 //		Control [] controls = getExampleControls ();
1798 //		for (int i=0; i<controls.length; i++) {
1799 //			log ("Control=" + controls [i] + ", border width=" + controls [i].getBorderWidth ());
1800 //		}
1801 	}
1802 
1803 	/**
1804 	 * Sets the visibility of the "Example" widgets.
1805 	 */
setExampleWidgetVisibility()1806 	void setExampleWidgetVisibility () {
1807 		Control [] controls = getExampleControls ();
1808 		for (Control control : controls) {
1809 			control.setVisible (visibleButton.getSelection ());
1810 		}
1811 	}
1812 
1813 	/**
1814 	 * Sets the background image of the "Example" widgets.
1815 	 */
setExampleWidgetBackgroundImage()1816 	void setExampleWidgetBackgroundImage () {
1817 		if (backgroundImageButton != null && backgroundImageButton.isDisposed()) return;
1818 		Control [] controls = getExampleControls ();
1819 		for (Control control : controls) {
1820 			control.setBackgroundImage (backgroundImageButton.getSelection () ? instance.images[ControlExample.ciBackground] : null);
1821 		}
1822 	}
1823 
1824 	/**
1825 	 * Splits the given string around matches of the given character.
1826 	 *
1827 	 * This subset of java.lang.String.split(String regex)
1828 	 * uses only code that can be run on CLDC platforms.
1829 	 */
split(String string, char ch)1830 	String [] split (String string, char ch) {
1831 		String [] result = new String[0];
1832 		int start = 0;
1833 		int length = string.length();
1834 		while (start < length) {
1835 			int end = string.indexOf(ch, start);
1836 			if (end == -1) end = length;
1837 			String substr = string.substring(start, end);
1838 			String [] newResult = new String[result.length + 1];
1839 			System.arraycopy(result, 0, newResult, 0, result.length);
1840 			newResult [result.length] = substr;
1841 			result = newResult;
1842 			start = end + 1;
1843 		}
1844 		return result;
1845 	}
1846 }
1847