1 11 package org.eclipse.help.ui.internal; 12 13 import org.eclipse.core.runtime.Platform; 14 import org.eclipse.help.IContext; 15 import org.eclipse.help.IContext2; 16 import org.eclipse.help.IHelpResource; 17 import org.eclipse.help.UAContentFilter; 18 import org.eclipse.help.internal.base.BaseHelpSystem; 19 import org.eclipse.help.internal.base.HelpEvaluationContext; 20 import org.eclipse.help.ui.internal.views.HelpTray; 21 import org.eclipse.osgi.service.environment.Constants; 22 import org.eclipse.swt.SWT; 23 import org.eclipse.swt.accessibility.ACC; 24 import org.eclipse.swt.accessibility.Accessible; 25 import org.eclipse.swt.accessibility.AccessibleAdapter; 26 import org.eclipse.swt.accessibility.AccessibleControlAdapter; 27 import org.eclipse.swt.accessibility.AccessibleControlEvent; 28 import org.eclipse.swt.accessibility.AccessibleEvent; 29 import org.eclipse.swt.custom.BusyIndicator; 30 import org.eclipse.swt.custom.StyledText; 31 import org.eclipse.swt.events.ControlAdapter; 32 import org.eclipse.swt.events.ControlEvent; 33 import org.eclipse.swt.events.TraverseEvent; 34 import org.eclipse.swt.events.TraverseListener; 35 import org.eclipse.swt.graphics.Color; 36 import org.eclipse.swt.graphics.GC; 37 import org.eclipse.swt.graphics.Image; 38 import org.eclipse.swt.graphics.Point; 39 import org.eclipse.swt.graphics.Rectangle; 40 import org.eclipse.swt.layout.GridData; 41 import org.eclipse.swt.layout.GridLayout; 42 import org.eclipse.swt.widgets.Composite; 43 import org.eclipse.swt.widgets.Control; 44 import org.eclipse.swt.widgets.Display; 45 import org.eclipse.swt.widgets.Event; 46 import org.eclipse.swt.widgets.Label; 47 import org.eclipse.swt.widgets.Listener; 48 import org.eclipse.swt.widgets.Shell; 49 import org.eclipse.ui.IWorkbenchWindow; 50 import org.eclipse.ui.PlatformUI; 51 52 55 public class ContextHelpDialog { 56 58 private Color backgroundColour = null; 59 60 private IContext context; 61 62 private Color foregroundColour = null; 63 64 private Color linkColour = null; 65 66 private static HyperlinkHandler linkManager = new HyperlinkHandler(); 67 68 protected Shell parentShell; 69 70 protected Shell shell; 71 72 protected String infopopText; 73 74 77 class LinkListener extends HyperlinkAdapter { 78 IHelpResource topic; 79 80 public LinkListener(IHelpResource topic) { 81 this.topic = topic; 82 } 83 84 public void linkActivated(Control c) { 85 launchLinks(topic); 86 } 87 88 } 89 90 100 ContextHelpDialog(IContext context, int x, int y) { 101 this.context = context; 102 Display display = Display.getCurrent(); 103 if (display == null) { 104 return; 105 } 106 backgroundColour = display.getSystemColor(SWT.COLOR_INFO_BACKGROUND); 107 foregroundColour = display.getSystemColor(SWT.COLOR_INFO_FOREGROUND); 108 linkColour = display.getSystemColor(SWT.COLOR_BLUE); 109 parentShell = display.getActiveShell(); 110 111 if (parentShell != null) { 112 boolean isModal = 0 < (parentShell.getStyle() & (SWT.APPLICATION_MODAL 113 | SWT.PRIMARY_MODAL | SWT.SYSTEM_MODAL)); 114 if (HelpUIPlugin.DEBUG_INFOPOP) { 115 System.out 116 .println("ContextHelpDialog.ContextHelpDialog(): ParentShell: " + parentShell.toString() + " is " + (isModal ? "modal" : "modeless")); } 120 } 121 122 shell = new Shell(parentShell, SWT.NONE); 123 if (HelpUIPlugin.DEBUG_INFOPOP) { 124 System.out 125 .println("ContextHelpDialog.ContextHelpDialog(): Shell is:" + shell.toString()); 127 } 128 PlatformUI.getWorkbench().getHelpSystem().setHelp(shell, IHelpUIConstants.F1_SHELL); 129 130 shell.addListener(SWT.Deactivate, new Listener() { 131 public void handleEvent(Event e) { 132 if (HelpUIPlugin.DEBUG_INFOPOP) { 133 System.out 134 .println("ContextHelpDialog shell deactivate listener: SWT.Deactivate called. "); } 136 close(); 137 } 138 }); 139 140 shell.addTraverseListener(new TraverseListener() { 141 public void keyTraversed(TraverseEvent e) { 142 if (e.detail == SWT.TRAVERSE_ESCAPE) { 143 if (HelpUIPlugin.DEBUG_INFOPOP) { 144 System.out 145 .println("ContextHelpDialog: shell traverse listener: SWT.TRAVERSE_ESCAPE called. "); } 147 e.doit = true; 148 } 149 } 150 }); 151 152 shell.addControlListener(new ControlAdapter() { 153 public void controlMoved(ControlEvent e) { 154 if (HelpUIPlugin.DEBUG_INFOPOP) { 155 System.out 156 .println("ContextHelpDialog: shell control adapter called."); } 158 Rectangle clientArea = shell.getClientArea(); 159 shell.redraw(clientArea.x, clientArea.y, clientArea.width, 160 clientArea.height, true); 161 shell.update(); 162 } 163 }); 164 if (HelpUIPlugin.DEBUG_INFOPOP) { 165 System.out 166 .println("ContextHelpDialog.ContextHelpDialog(): Focus owner is: " + Display.getCurrent().getFocusControl().toString()); 168 } 169 linkManager 170 .setHyperlinkUnderlineMode(HyperlinkHandler.UNDERLINE_ALWAYS); 171 createContents(shell); 172 shell.pack(); 173 int width = shell.getBounds().width; 175 int height = shell.getBounds().height; 176 177 Rectangle screen = display.getClientArea(); 178 x = x >= screen.x ? x : screen.x; 180 y = y >= screen.y ? y : screen.y; 181 x = x + width <= screen.width ? x : screen.width - width; 183 y = y + height <= screen.height ? y : screen.height - height; 184 shell.setLocation(x, y); 185 186 initAccessible(shell); 187 } 188 189 public synchronized void close() { 190 try { 191 if (HelpUIPlugin.DEBUG_INFOPOP) { 192 System.out.println("ContextHelpDialog.close()"); } 194 if (shell != null) { 195 shell.close(); 196 if (!shell.isDisposed()) 197 shell.dispose(); 198 shell = null; 199 } 200 } catch (Throwable ex) { 201 } 202 } 203 204 protected Control createContents(Composite contents) { 205 initAccessible(contents); 206 contents.setBackground(backgroundColour); 207 GridLayout layout = new GridLayout(); 208 layout.marginHeight = 5; 209 layout.marginWidth = 5; 210 contents.setLayout(layout); 211 contents.setLayoutData(new GridData(GridData.FILL_BOTH)); 212 createInfoArea(contents); 214 Control c = createLinksArea(contents); 215 if (c != null) { 216 contents.setTabList(new Control[] { c }); 218 } 219 return contents; 220 } 221 222 private Control createInfoArea(Composite parent) { 223 String styledText; 225 if (context instanceof IContext2) { 226 styledText = ((IContext2) context).getStyledText(); 227 if (styledText == null) { 228 styledText = context.getText(); 229 } 230 } else { 231 styledText = context.getText(); 232 } 233 if (styledText == null) { styledText = Messages.ContextHelpPart_noDescription; 235 } 236 Description text = new Description(parent, SWT.MULTI | SWT.READ_ONLY); 237 text.addTraverseListener(new TraverseListener() { 238 public void keyTraversed(TraverseEvent e) { 239 if (e.detail == SWT.TRAVERSE_ESCAPE) { 240 if (HelpUIPlugin.DEBUG_INFOPOP) { 241 System.out 242 .println("ContextHelpDialog text TraverseListener.handleEvent(): SWT.TRAVERSE_ESCAPE."); } 244 e.doit = true; 245 } 246 } 247 }); 248 249 text.getCaret().setVisible(false); 250 text.setBackground(backgroundColour); 251 text.setForeground(foregroundColour); 252 text.setFont(parent.getFont()); 253 int linkWidth = getLinksWidth(text); 254 StyledLineWrapper content = new StyledLineWrapper(styledText, text, 255 linkWidth + 70); 256 text.setContent(content); 257 text.setStyleRanges(content.getStyles()); 258 259 infopopText = text.getText(); 260 initAccessible(text); 261 262 return text; 263 } 264 265 271 private int getLinksWidth(Description text) { 272 int linkWidth = 0; 273 IHelpResource relatedTopics[] = context.getRelatedTopics(); 274 if (relatedTopics != null) { 275 GC gc = new GC(text); 276 for (int i = 0; i < relatedTopics.length; i++) { 277 linkWidth = Math.max(linkWidth, gc.textExtent(relatedTopics[i] 278 .getLabel()).x); 279 } 280 gc.dispose(); 281 } 282 return linkWidth; 283 } 284 285 private Control createLink(Composite parent, IHelpResource topic) { 286 Label image = new Label(parent, SWT.NONE); 287 image.setImage(getImage()); 288 image.setBackground(backgroundColour); 289 GridData data = new GridData(); 290 data.horizontalAlignment = GridData.HORIZONTAL_ALIGN_BEGINNING; 291 data.verticalAlignment = GridData.VERTICAL_ALIGN_BEGINNING; 292 image.setLayoutData(data); 294 HyperlinkLabel link = new HyperlinkLabel(parent, SWT.NONE); 295 link.setText(topic.getLabel()); 296 link.setBackground(backgroundColour); 297 link.setForeground(linkColour); 298 link.setFont(parent.getFont()); 299 linkManager.registerHyperlink(link, new LinkListener(topic)); 300 return link; 301 } 302 303 private Control createLinksArea(Composite parent) { 304 IHelpResource[] relatedTopics = context.getRelatedTopics(); 305 if (relatedTopics == null) 306 return null; 307 Composite composite = new Composite(parent, SWT.NONE); 309 initAccessible(composite); 310 311 composite.setBackground(backgroundColour); 312 GridLayout layout = new GridLayout(); 313 layout.marginHeight = 2; 314 layout.marginWidth = 0; 315 layout.verticalSpacing = 3; 316 layout.horizontalSpacing = 2; 317 layout.numColumns = 2; 318 composite.setLayout(layout); 319 composite.setFont(parent.getFont()); 320 GridData data = new GridData(GridData.FILL_BOTH 321 | GridData.HORIZONTAL_ALIGN_BEGINNING 322 | GridData.VERTICAL_ALIGN_CENTER); 323 composite.setLayoutData(data); 324 Label label = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL); 326 label.setBackground(backgroundColour); 327 label.setForeground(foregroundColour); 328 data = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING 329 | GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL); 330 data.horizontalSpan = 2; 331 label.setLayoutData(data); 332 for (int i = 0; i < relatedTopics.length; i++) { 334 if (!UAContentFilter.isFiltered(relatedTopics[i], HelpEvaluationContext.getContext())) { 335 createLink(composite, relatedTopics[i]); 336 } 337 } 338 339 IWorkbenchWindow wbWindow = HelpUIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow(); 341 if (DefaultHelpUI.isActiveShell(parentShell, wbWindow) || HelpTray.isAppropriateFor(parentShell)) { 342 label = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL); 344 label.setBackground(backgroundColour); 345 label.setForeground(foregroundColour); 346 data = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING 347 | GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_HORIZONTAL); 348 data.horizontalSpan = 2; 349 label.setLayoutData(data); 350 351 createDynamicHelpLink(composite); 353 } 354 355 return composite; 356 } 357 358 private Control createDynamicHelpLink(Composite parent) { 359 Label image = new Label(parent, SWT.NONE); 360 Image img = HelpUIResources.getImage(IHelpUIConstants.IMAGE_DHELP); 361 image.setImage(img); 362 image.setBackground(backgroundColour); 363 GridData data = new GridData(); 364 data.horizontalAlignment = GridData.HORIZONTAL_ALIGN_BEGINNING; 365 data.verticalAlignment = GridData.VERTICAL_ALIGN_BEGINNING; 366 image.setLayoutData(data); 368 HyperlinkLabel link = new HyperlinkLabel(parent, SWT.NONE); 369 link.setText(Messages.ContextHelpDialog_showInDynamicHelp); 370 link.setBackground(backgroundColour); 371 link.setForeground(linkColour); 372 link.setFont(parent.getFont()); 373 linkManager.registerHyperlink(link, new HyperlinkAdapter() { 374 public void linkActivated(Control label) { 375 openDynamicHelp(); 376 } 377 }); 378 return link; 379 } 380 381 385 protected void launchLinks(IHelpResource selectedTopic) { 386 close(); 387 if (HelpUIPlugin.DEBUG_INFOPOP) { 388 System.out.println("ContextHelpDialog.launchLinks(): closed shell"); } 390 BaseHelpSystem.getHelpDisplay().displayHelp( 391 context, 392 selectedTopic, 393 DefaultHelpUI.isDisplayModal(parentShell) 394 && !Constants.OS_WIN32.equalsIgnoreCase(Platform 395 .getOS())); 396 } 397 398 private void openDynamicHelp() { 399 BusyIndicator.showWhile(shell.getDisplay(), new Runnable () { 400 public void run() { 401 close(); 402 DefaultHelpUI.getInstance().displayContext(context, 0, 0, true); 403 } 404 }); 405 } 406 407 public synchronized void open() { 408 try { 409 shell.open(); 410 if (HelpUIPlugin.DEBUG_INFOPOP) { 411 System.out 412 .println("ContextHelpDialog.open(): Focus owner after open is: " + Display.getCurrent().getFocusControl() 414 .toString()); 415 } 416 } catch (Throwable e) { 417 HelpUIPlugin 418 .logError( 419 "An error occurred when opening context-sensitive help pop-up.", e); 421 } 422 } 423 424 private Image getImage() { 425 return HelpUIResources.getImage(IHelpUIConstants.IMAGE_FILE_F1TOPIC); 426 } 427 428 public boolean isShowing() { 429 return (shell != null && !shell.isDisposed() && shell.isVisible()); 430 } 431 432 private void initAccessible(final Control control) { 433 Accessible accessible = control.getAccessible(); 434 accessible.addAccessibleListener(new AccessibleAdapter() { 435 public void getName(AccessibleEvent e) { 436 e.result = infopopText; 437 } 438 439 public void getHelp(AccessibleEvent e) { 440 e.result = control.getToolTipText(); 441 } 442 }); 443 444 accessible.addAccessibleControlListener(new AccessibleControlAdapter() { 445 public void getChildAtPoint(AccessibleControlEvent e) { 446 Point pt = control.toControl(new Point(e.x, e.y)); 447 e.childID = (control.getBounds().contains(pt)) ? ACC.CHILDID_MULTIPLE 448 : ACC.CHILDID_NONE; 449 } 450 451 public void getLocation(AccessibleControlEvent e) { 452 Rectangle location = control.getBounds(); 453 Point pt = control.toDisplay(new Point(location.x, location.y)); 454 e.x = pt.x; 455 e.y = pt.y; 456 e.width = location.width; 457 e.height = location.height; 458 } 459 460 public void getChildCount(AccessibleControlEvent e) { 461 e.detail = 1; 462 } 463 464 public void getRole(AccessibleControlEvent e) { 465 e.detail = ACC.ROLE_LABEL; 466 } 467 468 public void getState(AccessibleControlEvent e) { 469 e.detail = ACC.STATE_READONLY; 470 } 471 }); 472 } 473 474 public class Description extends StyledText { 475 479 public Description(Composite parent, int style) { 480 super(parent, style); 481 } 482 483 public boolean setFocus() { 484 return false; 485 } 486 487 public boolean isFocusControl() { 488 return false; 489 } 490 } 491 492 } 493 | Popular Tags |