1 /*******************************************************************************
2  * Copyright (c) 2002, 2020 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  *     Asma Smaoui - CEA LIST - https://bugs.eclipse.org/bugs/show_bug.cgi?id=517379
14  *     George Suaridze <suag@1c.ru> (1C-Soft LLC) - Bug 559885
15  *******************************************************************************/
16 package org.eclipse.ui.internal.cheatsheets.views;
17 
18 import java.util.ArrayList;
19 import java.util.Iterator;
20 
21 import org.eclipse.help.HelpSystem;
22 import org.eclipse.help.IContext;
23 import org.eclipse.jface.action.Action;
24 import org.eclipse.swt.SWT;
25 import org.eclipse.swt.events.FocusEvent;
26 import org.eclipse.swt.events.FocusListener;
27 import org.eclipse.swt.events.SelectionAdapter;
28 import org.eclipse.swt.events.SelectionEvent;
29 import org.eclipse.swt.graphics.Color;
30 import org.eclipse.swt.graphics.Font;
31 import org.eclipse.swt.graphics.FontData;
32 import org.eclipse.swt.graphics.Image;
33 import org.eclipse.swt.graphics.Point;
34 import org.eclipse.swt.layout.GridData;
35 import org.eclipse.swt.layout.GridLayout;
36 import org.eclipse.swt.widgets.Composite;
37 import org.eclipse.swt.widgets.Control;
38 import org.eclipse.swt.widgets.Label;
39 import org.eclipse.swt.widgets.Widget;
40 import org.eclipse.ui.PlatformUI;
41 import org.eclipse.ui.cheatsheets.AbstractItemExtensionElement;
42 import org.eclipse.ui.forms.events.ExpansionAdapter;
43 import org.eclipse.ui.forms.events.ExpansionEvent;
44 import org.eclipse.ui.forms.events.HyperlinkAdapter;
45 import org.eclipse.ui.forms.events.HyperlinkEvent;
46 import org.eclipse.ui.forms.widgets.ExpandableComposite;
47 import org.eclipse.ui.forms.widgets.FormText;
48 import org.eclipse.ui.forms.widgets.FormToolkit;
49 import org.eclipse.ui.forms.widgets.ImageHyperlink;
50 import org.eclipse.ui.forms.widgets.TableWrapData;
51 import org.eclipse.ui.forms.widgets.TableWrapLayout;
52 import org.eclipse.ui.internal.cheatsheets.CheatSheetPlugin;
53 import org.eclipse.ui.internal.cheatsheets.CheatSheetStopWatch;
54 import org.eclipse.ui.internal.cheatsheets.ICheatSheetResource;
55 import org.eclipse.ui.internal.cheatsheets.Messages;
56 import org.eclipse.ui.internal.cheatsheets.data.IParserTags;
57 import org.eclipse.ui.internal.cheatsheets.data.Item;
58 import org.eclipse.ui.internal.cheatsheets.views.CheatSheetHyperlinkActionFactory.CheatSheetHyperlinkAction;
59 
60 public abstract class ViewItem {
61 
62 	public final static byte VIEWITEM_ADVANCE = 0;
63 	public final static byte VIEWITEM_DONOT_ADVANCE = 1;
64 	private Composite bodyComp;
65 
66 	protected FormText bodyText;
67 	protected FormText completionText;
68 //	protected Label bodyText;
69 	protected Composite bodyWrapperComposite;
70 	protected Composite buttonComposite;
71 	protected Composite completionComposite;
72 
73 	private boolean buttonExpanded = true;
74 	private boolean completionMessageExpanded = false;
75 	private Label checkDoneLabel;
76 	private boolean completed = false;
77 
78 	protected Item item;
79 
80 	// Colors
81 	protected Color itemColor;
82 
83 	private boolean isSkipped = false;
84 	private ExpandableComposite mainItemComposite;
85 
86 	private Composite parent;
87 	protected CheatSheetViewer viewer;
88 	protected CheatSheetPage page;
89 	private Composite titleComposite;
90 	private boolean bold = true;
91 	private Font boldFont;
92 	private Font regularFont;
93 	private boolean initialized = false;
94 	protected ArrayList<SubItemCompositeHolder> listOfSubItemCompositeHolders;
95 
96 	/**
97 	 * Constructor for ViewItem.
98 	 */
ViewItem(CheatSheetPage page, Item item, Color itemColor, CheatSheetViewer viewer)99 	public ViewItem(CheatSheetPage page, Item item, Color itemColor, CheatSheetViewer viewer) {
100 		super();
101 		this.page = page;
102 		this.parent = page.getForm().getBody();
103 		this.item = item;
104 		this.itemColor = itemColor;
105 		this.viewer = viewer;
106 		addItem();
107 	}
108 
109 	//Adds the item to the main composite.
addItem()110 	private void addItem() {
111 		CheatSheetStopWatch.startStopWatch("ViewItem.addItem()"); //$NON-NLS-1$
112 		CheatSheetStopWatch.printLapTime("ViewItem.addItem()", "Time in addItem() after getBannerBackground: "); //$NON-NLS-1$ //$NON-NLS-2$
113 
114 		//		Set up the main composite for the item.******************************************
115 		checkDoneLabel = page.getToolkit().createLabel(parent, " "); //$NON-NLS-1$
116 		CheatSheetStopWatch.printLapTime("ViewItem.addItem()", "Time in addItem() after create checkDoneLabel: "); //$NON-NLS-1$ //$NON-NLS-2$
117 
118 		mainItemComposite = page.getToolkit().createSection(parent, ExpandableComposite.TWISTIE|ExpandableComposite.COMPACT);
119 		mainItemComposite.setBackground(itemColor);
120 		mainItemComposite.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB));
121 		String title = item.getTitle();
122 		if (title != null) {
123 			mainItemComposite.setText(ViewUtilities.escapeForLabel(title));
124 		}
125 		CheatSheetStopWatch.printLapTime("ViewItem.addItem()", "Time in addItem() after create mainItemComposite: "); //$NON-NLS-1$ //$NON-NLS-2$
126 
127 
128 		mainItemComposite.addExpansionListener(new ExpansionAdapter() {
129 			@Override
130 			public void expansionStateChanged(ExpansionEvent e) {
131 				page.getForm().reflow(true);
132 			}
133 		});
134 		CheatSheetStopWatch.printLapTime("ViewItem.addItem()", "Time in addItem() after addExpansionListener: "); //$NON-NLS-1$ //$NON-NLS-2$
135 
136 		// handle item extensions here
137 		// check number of extensions for this item and adjust layout accordingly
138 		int number = 0;
139 		ArrayList<AbstractItemExtensionElement[]> itemExts = item.getItemExtensions();
140 
141 		if((itemExts != null && itemExts.size() > 0) || item.getContextId() != null || item.getHref() != null) {
142 			// Set up the title composite for the item.
143 			titleComposite = page.getToolkit().createComposite(mainItemComposite);
144 			titleComposite.setBackground(itemColor);
145 		}
146 
147 		if(itemExts != null) {
148 			for (int g = 0; g < itemExts.size(); g++) {
149 				AbstractItemExtensionElement[] eea = itemExts.get(g);
150 				number += eea.length;
151 				for (int x = 0; x < eea.length; x++) {
152 					eea[x].createControl(titleComposite);
153 				}
154 			}
155 		}
156 		CheatSheetStopWatch.printLapTime("ViewItem.addItem()", "Time in addItem() after create item extensions: "); //$NON-NLS-1$ //$NON-NLS-2$
157 
158 		// don't add the help icon unless there is a context id or help link
159 		if(item.getContextId() != null || item.getHref() != null) {
160 			// adjust the layout count
161 			number++;
162 			ImageHyperlink helpButton = createButton(titleComposite, CheatSheetPlugin.getPlugin().getImage(ICheatSheetResource.CHEATSHEET_ITEM_HELP), this, itemColor, Messages.HELP_BUTTON_TOOLTIP);
163 			helpButton.addHyperlinkListener(new HyperlinkAdapter() {
164 				@Override
165 				public void linkActivated(HyperlinkEvent e) {
166 					// If we have a context id, handle this first and ignore an hrefs
167 					if(item.getContextId() != null) {
168 						openInfopop(e.widget);
169 					} else {
170 						// We only have an href, so let's open it in the help system
171 						openHelpTopic();
172 					}
173 				}
174 			});
175 		}
176 		CheatSheetStopWatch.printLapTime("ViewItem.addItem()", "Time in addItem() after create help button: "); //$NON-NLS-1$ //$NON-NLS-2$
177 
178 		if(number > 0) {
179 			mainItemComposite.setTextClient(titleComposite);
180 			GridLayout layout = new GridLayout(number, false);
181 			GridData data = new GridData(GridData.FILL_BOTH);
182 
183 			titleComposite.setLayout(layout);
184 			titleComposite.setLayoutData(data);
185 			layout.marginWidth = 0;
186 			layout.marginHeight = 0;
187 			layout.verticalSpacing = 0;
188 		}
189 		CheatSheetStopWatch.printLapTime("ViewItem.addItem()", "Time in addItem() after setTextClient: "); //$NON-NLS-1$ //$NON-NLS-2$
190 
191 		//Body wrapper here.   this composite will be hidden and shown as appropriate.
192 		bodyWrapperComposite = page.getToolkit().createComposite(mainItemComposite);
193 		mainItemComposite.setClient(bodyWrapperComposite);
194 		TableWrapLayout wrapperLayout = new TableWrapLayout();
195 		bodyWrapperComposite.setLayout(wrapperLayout);
196 		bodyWrapperComposite.setBackground(itemColor);
197 		CheatSheetStopWatch.printLapTime("ViewItem.addItem()", "Time in addItem() after create bodyWrapperComposite: "); //$NON-NLS-1$ //$NON-NLS-2$
198 
199 		bodyText = page.getToolkit().createFormText(bodyWrapperComposite, false);
200 		bodyText.addSelectionListener(new SelectionAdapter() {
201 			@Override
202 			public void widgetSelected(SelectionEvent e) {
203 				Action copyAction = viewer.getCopyAction();
204 				if (copyAction != null) {
205 					copyAction.setEnabled(bodyText.canCopy());
206 				}
207 			}
208 		});
209 		bodyText.addFocusListener(new FocusListener() {
210 			@Override
211 			public void focusGained(FocusEvent e) {
212 				Action copyAction = viewer.getCopyAction();
213 				if (copyAction != null) {
214 					copyAction.setEnabled(bodyText.canCopy());
215 				}
216 			}
217 			@Override
218 			public void focusLost(FocusEvent e) {
219 				Action copyAction = viewer.getCopyAction();
220 				if (copyAction != null) {
221 					copyAction.setEnabled(false);
222 				}
223 			}
224 		});
225 
226 		bodyText.addHyperlinkListener(new HyperlinkAdapter() {
227 			@Override
228 			public void linkActivated(HyperlinkEvent event) {
229 				String url = (String) event.getHref();
230 				CheatSheetHyperlinkActionFactory actionFactory = new CheatSheetHyperlinkActionFactory();
231 				CheatSheetHyperlinkAction cheatSheetHyperlink = actionFactory.create(url);
232 				cheatSheetHyperlink.execute();
233 			}
234 		});
235 
236 //		bodyText = toolkit.createLabel(bodyWrapperComposite, item.getDescription(), SWT.WRAP);
237 		bodyText.setText(item.getDescription(), item.getDescription().startsWith(IParserTags.FORM_START_TAG), false);
238 
239 		//Set up the body text portion here.
240 		bodyText.setBackground(itemColor);
241 		bodyText.setLayoutData(new TableWrapData(TableWrapData.FILL_GRAB));
242 		CheatSheetStopWatch.printLapTime("ViewItem.addItem()", "Time in addItem() after create FormText: "); //$NON-NLS-1$ //$NON-NLS-2$
243 
244 		//Handle the sub-steps and regular buttons here.
245 		//First Check to see if there is sub steps.  If there is, don't create the button comp,
246 		//As it will be handled by the CoreItemWithSubs.
247 		//If there is no sub steps, create a button composite and Pass it to CoreItem using the handleButtons.
248 
249 		if(!item.isDynamic()) {
250 			handleButtons();
251 		}
252 		CheatSheetStopWatch.printLapTime("ViewItem.addItem()", "Time in addItem() after handleButtons(): "); //$NON-NLS-1$ //$NON-NLS-2$
253 
254 		setButtonsVisible(false);
255 		setCollapsed();
256 		CheatSheetStopWatch.printLapTime("ViewItem.addItem()", "Time in addItem() after setting buttons and item collapsed: "); //$NON-NLS-1$ //$NON-NLS-2$
257 
258 		boldFont = mainItemComposite.getFont();
259 		FontData[] fontDatas = boldFont.getFontData();
260 		for (int i = 0; i < fontDatas.length; i++) {
261 			fontDatas[i].setStyle(fontDatas[i].getStyle() ^ SWT.BOLD);
262 		}
263 		regularFont = new Font(mainItemComposite.getDisplay(), fontDatas);
264 		CheatSheetStopWatch.printLapTime("ViewItem.addItem()", "Time in addItem() after font initlization: "); //$NON-NLS-1$ //$NON-NLS-2$
265 
266 		setBold(false);
267 		CheatSheetStopWatch.printLapTime("ViewItem.addItem()", "Time in addItem() after setBold: "); //$NON-NLS-1$ //$NON-NLS-2$
268 	}
269 
createButtonWithText(Composite parent, Image image, ViewItem item, Color color, String linkText)270 	protected ImageHyperlink createButtonWithText(Composite parent, Image image, ViewItem item, Color color, String linkText) {
271 		ImageHyperlink button = page.getToolkit().createImageHyperlink(parent, SWT.NULL);
272 		button.setImage(image);
273 		button.setData(item);
274 		button.setBackground(color);
275 		button.setText(linkText);
276 		button.setToolTipText(linkText);
277 		return button;
278 	}
279 
createButton(Composite parent, Image image, ViewItem item, Color color, String toolTipText)280 	protected ImageHyperlink createButton(Composite parent, Image image, ViewItem item, Color color, String toolTipText) {
281 		ImageHyperlink button = new ImageHyperlink(parent, SWT.NULL);
282 		page.getToolkit().adapt(button, true, true);
283 		button.setImage(image);
284 		button.setData(item);
285 		button.setBackground(color);
286 		button.setToolTipText(toolTipText);
287 //		button.setFAccessibleDescription(bodyText.getText());
288 //		button.setFAccessibleName(button.getToolTipText());
289 
290 		return button;
291 	}
292 
dispose()293 	public void dispose() {
294 		if (checkDoneLabel != null)
295 			checkDoneLabel.dispose();
296 		if (bodyText != null)
297 			bodyText.dispose();
298 		if (buttonComposite != null)
299 			buttonComposite.dispose();
300 		if (completionComposite != null)
301 			completionComposite.dispose();
302 		if (bodyComp != null)
303 			bodyComp.dispose();
304 		if (bodyWrapperComposite != null)
305 			bodyWrapperComposite.dispose();
306 		if (mainItemComposite != null)
307 			mainItemComposite.dispose();
308 		if (titleComposite != null)
309 			titleComposite.dispose();
310 		if (regularFont != null)
311 			regularFont.dispose();
312 
313 		ArrayList<AbstractItemExtensionElement[]> itemExts = item.getItemExtensions();
314 		if (itemExts != null) {
315 			for (int g = 0; g < itemExts.size(); g++) {
316 				AbstractItemExtensionElement[] eea = itemExts.get(g);
317 				for (int x = 0; x < eea.length; x++) {
318 					eea[x].dispose();
319 				}
320 			}
321 		}
322 	}
323 
324 	/**
325 	 * @return
326 	 */
327 	/*package*/
getCompleteImage()328 	Image getCompleteImage() {
329 		return CheatSheetPlugin.getPlugin().getImage(ICheatSheetResource.CHEATSHEET_ITEM_COMPLETE);
330 	}
331 
332 	/**
333 	 * @return
334 	 */
getItem()335 	public Item getItem() {
336 		return item;
337 	}
338 
339 	/**
340 	 * Returns the mainItemComposite.
341 	 * @return Composite
342 	 */
343 	/*package*/
getMainItemComposite()344 	Composite getMainItemComposite() {
345 		return mainItemComposite;
346 	}
347 
348 	/**
349 	 * @return
350 	 */
351 	/*package*/
getSkipImage()352 	Image getSkipImage() {
353 		return CheatSheetPlugin.getPlugin().getImage(ICheatSheetResource.CHEATSHEET_ITEM_SKIP);
354 	}
355 
356 	//Adds the buttons to the buttonComposite.
357 	/*package*/
handleButtons()358 	abstract void handleButtons();
359 
360 	/*package*/
isBold()361 	boolean isBold() {
362 		return bold;
363 	}
364 
365 	/**
366 	 * Returns the completed.
367 	 * @return boolean
368 	 */
isCompleted()369 	public boolean isCompleted() {
370 		return completed;
371 	}
372 
isExpanded()373 	public boolean isExpanded() {
374 		return mainItemComposite.isExpanded();
375 	}
376 
isCompletionMessageExpanded()377 	public boolean isCompletionMessageExpanded() {
378 		return completionMessageExpanded;
379 	}
380 
381 	/**
382 	 * Returns whether or not cheat sheet viewer containing this item is in
383 	 * a modal dialog.
384 	 *
385 	 * @return whether the cheat sheet viewer is in a modal dialog
386 	 */
isInDialogMode()387 	public boolean isInDialogMode() {
388 		return viewer.isInDialogMode();
389 	}
390 
391 	/*package*/
isSkipped()392 	boolean isSkipped() {
393 		return isSkipped;
394 	}
395 
396 	/**
397 	 * Open a help topic
398 	 */
openHelpTopic()399 	private void openHelpTopic() {
400 		if (item == null || item.getHref() == null) {
401 			return;
402 		}
403 
404 		PlatformUI.getWorkbench().getHelpSystem().displayHelpResource(item.getHref());
405 	}
406 
407 	/**
408 	 * Open an infopop
409 	 */
openInfopop(Widget widget)410 	private void openInfopop(Widget widget) {
411 		if (item == null || item.getContextId() == null) {
412 			return;
413 		}
414 
415 		IContext context = HelpSystem.getContext(item.getContextId());
416 
417 		if (context != null) {
418 			// determine a location in the upper right corner of the widget
419 			Point point = widget.getDisplay().getCursorLocation();
420 			point = new Point(point.x + 15, point.y);
421 			// display the help
422 			PlatformUI.getWorkbench().getHelpSystem().displayContext(context, point.x, point.y);
423 		}
424 	}
425 
setAsCurrentActiveItem()426 	public void setAsCurrentActiveItem() {
427 		setColorAsCurrent(true);
428 		setButtonsVisible(true);
429 		setBold(true);
430 		setExpanded();
431 		setFocus();
432 	}
433 
setFocus()434 	protected void setFocus() {
435 		mainItemComposite.setFocus();
436 		FormToolkit.ensureVisible(getMainItemComposite());
437 	}
438 
439 	/*package*/
setAsNormalCollapsed()440 	void setAsNormalCollapsed() {
441 		setBold(false);
442 		setColorAsCurrent(false);
443 		if (mainItemComposite.isExpanded())
444 			setCollapsed();
445 	}
446 
447 	/*package*/
setAsNormalNonCollapsed()448 	void setAsNormalNonCollapsed() {
449 		setColorAsCurrent(false);
450 		setBold(false);
451 	}
452 
setBodyColor(Color color)453 	private void setBodyColor(Color color) {
454 		mainItemComposite.setBackground(color);
455 		setBackgroundColor(bodyWrapperComposite, color);
456 		setBackgroundColor(buttonComposite, color);
457 		setBackgroundColor(completionComposite, color);
458 	}
459 
460 	/*
461 	 * Set the background color of this composite and its children.
462 	 * If the composite is null do nothing.
463 	 */
setBackgroundColor(Composite composite, Color color)464 	protected void setBackgroundColor(Composite composite, Color color) {
465 		if (composite != null) {
466 			composite.setBackground(color);
467 			Control[] children = composite.getChildren();
468 			for (Control element : children) {
469 				element.setBackground(color);
470 			}
471 		}
472 	}
473 
474 	/*package*/
setBold(boolean value)475 	void setBold(boolean value) {
476 		if(value) {
477 			mainItemComposite.setFont(boldFont);
478 			if(initialized)
479 				mainItemComposite.layout();
480 		} else {
481 			mainItemComposite.setFont(regularFont);
482 			if(initialized)
483 				mainItemComposite.layout();
484 		}
485 		bold = value;
486 	}
487 
488 	//collapse or expand the item
489 	/*package*/
setButtonsVisible(boolean isVisible)490 	void setButtonsVisible(boolean isVisible) {
491 		if (buttonExpanded != isVisible) {
492 			if (listOfSubItemCompositeHolders != null) {
493 				for (Iterator<SubItemCompositeHolder> iter = listOfSubItemCompositeHolders.iterator(); iter
494 						.hasNext();) {
495 					iter.next().setButtonsVisible(isVisible);
496 				}
497 			} else if (buttonComposite != null) {
498 				buttonComposite.setVisible(isVisible);
499 			}
500 		}
501 
502 		if(isVisible && initialized) {
503 			FormToolkit.ensureVisible(getMainItemComposite());
504 		}
505 		buttonExpanded = isVisible;
506 	}
507 
setCompletionMessageExpanded(boolean isFinalItem)508 	protected void setCompletionMessageExpanded(boolean isFinalItem) {
509 		if (hasCompletionMessage()) {
510 			if (completionComposite == null) {
511 				createCompletionComposite(isFinalItem);
512 			}
513 			if (!completionMessageExpanded) {
514 				completionComposite.setVisible(true);
515 				completionMessageExpanded = true;
516 			}
517 		}
518 	}
519 
createCompletionComposite(boolean isFinalItem)520 	abstract void createCompletionComposite(boolean isFinalItem);
521 
setCompletionMessageCollapsed()522 	protected void setCompletionMessageCollapsed() {
523 		if (completionComposite != null) {
524 			if (completionMessageExpanded) {
525 				completionComposite.dispose();
526 				completionComposite = null;
527 				page.getForm().reflow(true);
528 			}
529 		}
530 		completionMessageExpanded = false;
531 	}
532 
533 	//collapses the item
534 	/*package*/
setCollapsed()535 	void setCollapsed() {
536 		if (mainItemComposite.isExpanded()) {
537 			mainItemComposite.setExpanded(false);
538 			if(initialized) {
539 				page.getForm().reflow(true);
540 				FormToolkit.ensureVisible(getMainItemComposite());
541 			}
542 		}
543 	}
544 
setColorAsCurrent(boolean active)545 	private void setColorAsCurrent(boolean active) {
546 		if (active) {
547 			setTitleColor(page.getActiveColor());
548 			setBodyColor(page.getActiveColor());
549 		} else {
550 			setTitleColor(itemColor);
551 			setBodyColor(itemColor);
552 		}
553 	}
554 
555 	//marks the item as complete.
setComplete()556 	public void setComplete() {
557 		completed = true;
558 		checkDoneLabel.setImage(getCompleteImage());
559 
560 		if(initialized) {
561 			checkDoneLabel.getParent().layout();
562 		}
563 	}
564 
565 	//expands the item
setExpanded()566 	public void setExpanded() {
567 		if (!mainItemComposite.isExpanded()) {
568 			mainItemComposite.setExpanded(true);
569 			if(initialized) {
570 				page.getForm().reflow(true);
571 				FormToolkit.ensureVisible(getMainItemComposite());
572 			}
573 		}
574 	}
575 
576 	/*package*/
setIncomplete()577 	void setIncomplete() {
578 		checkDoneLabel.setImage(null);
579 		completed = false;
580 		setStartImage();
581 	}
582 
583 	/**
584 	 * Sets the itemColor.
585 	 * @param itemColor The itemColor to set
586 	 */
587 	/*package*/
setItemColor(Color itemColor)588 	void setItemColor(Color itemColor) {
589 		this.itemColor = itemColor;
590 	}
591 
592 	/*package*/
setOriginalColor()593 	void setOriginalColor() {
594 		setTitleColor(itemColor);
595 		setBodyColor(itemColor);
596 		setBold(false);
597 	}
598 
599 	/*package*/
setRestartImage()600 	abstract void setRestartImage();
601 
602 	/*package*/
setSkipped()603 	void setSkipped() {
604 		isSkipped = true;
605 		checkDoneLabel.setImage(getSkipImage());
606 
607 		if(initialized) {
608 			checkDoneLabel.getParent().layout();
609 		}
610 	}
611 	/*package*/
setStartImage()612 	abstract void setStartImage();
613 
setTitleColor(Color bg)614 	private void setTitleColor(Color bg) {
615 		if(titleComposite != null) {
616 			titleComposite.setBackground(bg);
617 
618 			Control[] titlechildren = titleComposite.getChildren();
619 			for (Control element : titlechildren) {
620 				element.setBackground(bg);
621 			}
622 		}
623 	}
624 
initialized()625 	public void initialized() {
626 		initialized = true;
627 	}
628 
canCopy()629 	public boolean canCopy() {
630 		return (bodyText!=null && !bodyText.isDisposed())?bodyText.canCopy():false;
631 	}
copy()632 	public void copy() {
633 		if (bodyText!=null && !bodyText.isDisposed())
634 			bodyText.copy();
635 	}
636 
hasCompletionMessage()637 	abstract boolean hasCompletionMessage();
638 
639 }
640