1 11 12 package org.eclipse.jface.internal.text.link.contentassist; 13 14 15 import java.util.Stack ; 16 17 import org.eclipse.jface.text.ITextViewer; 18 import org.eclipse.jface.text.TextPresentation; 19 import org.eclipse.jface.text.contentassist.IContextInformation; 20 import org.eclipse.jface.text.contentassist.IContextInformationExtension; 21 import org.eclipse.jface.text.contentassist.IContextInformationPresenter; 22 import org.eclipse.jface.text.contentassist.IContextInformationValidator; 23 import org.eclipse.swt.SWT; 24 import org.eclipse.swt.custom.BusyIndicator; 25 import org.eclipse.swt.custom.StyledText; 26 import org.eclipse.swt.events.KeyEvent; 27 import org.eclipse.swt.events.SelectionEvent; 28 import org.eclipse.swt.events.SelectionListener; 29 import org.eclipse.swt.events.VerifyEvent; 30 import org.eclipse.swt.graphics.Color; 31 import org.eclipse.swt.graphics.Point; 32 import org.eclipse.swt.layout.GridData; 33 import org.eclipse.swt.layout.GridLayout; 34 import org.eclipse.swt.widgets.Control; 35 import org.eclipse.swt.widgets.Display; 36 import org.eclipse.swt.widgets.Shell; 37 import org.eclipse.swt.widgets.Table; 38 import org.eclipse.swt.widgets.TableItem; 39 40 41 56 class ContextInformationPopup2 implements IContentAssistListener2 { 57 58 59 60 64 static class ContextFrame { 65 public int fBeginOffset; 66 public int fOffset; 67 public int fVisibleOffset; 68 public IContextInformation fInformation; 69 public IContextInformationValidator fValidator; 70 public IContextInformationPresenter fPresenter; 71 } 72 73 private ITextViewer fViewer; 74 private ContentAssistant2 fContentAssistant; 75 76 private PopupCloser2 fPopupCloser= new PopupCloser2(); 77 private Shell fContextSelectorShell; 78 private Table fContextSelectorTable; 79 private IContextInformation[] fContextSelectorInput; 80 private String fLineDelimiter= null; 81 82 private Shell fContextInfoPopup; 83 private StyledText fContextInfoText; 84 private TextPresentation fTextPresentation; 85 86 private Stack fContextFrameStack= new Stack (); 87 88 89 95 public ContextInformationPopup2(ContentAssistant2 contentAssistant, ITextViewer viewer) { 96 fContentAssistant= contentAssistant; 97 fViewer= viewer; 98 } 99 100 106 public String showContextProposals(final boolean autoActivated) { 107 final StyledText styledText= fViewer.getTextWidget(); 108 BusyIndicator.showWhile(styledText.getDisplay(), new Runnable () { 109 public void run() { 110 111 int position= fViewer.getSelectedRange().x; 112 113 IContextInformation[] contexts= computeContextInformation(position); 114 int count = (contexts == null ? 0 : contexts.length); 115 if (count == 1) { 116 117 internalShowContextInfo(contexts[0], position); 119 120 } else if (count > 0) { 121 123 if (fLineDelimiter == null) 124 fLineDelimiter= styledText.getLineDelimiter(); 125 126 createContextSelector(); 127 setContexts(contexts); 128 displayContextSelector(); 129 hideContextInfoPopup(); 130 131 } else if (!autoActivated) { 132 styledText.getDisplay().beep(); 133 } 134 } 135 }); 136 137 return getErrorMessage(); 138 } 139 140 147 public void showContextInformation(final IContextInformation info, final int position) { 148 Control control= fViewer.getTextWidget(); 149 BusyIndicator.showWhile(control.getDisplay(), new Runnable () { 150 public void run() { 151 internalShowContextInfo(info, position); 152 hideContextSelector(); 153 } 154 }); 155 } 156 157 164 165 private void internalShowContextInfo(IContextInformation information, int offset) { 166 167 IContextInformationValidator validator= fContentAssistant.getContextInformationValidator(fViewer, offset); 168 169 if (validator != null) { 170 ContextFrame current= new ContextFrame(); 171 current.fInformation= information; 172 current.fBeginOffset= (information instanceof IContextInformationExtension) ? ((IContextInformationExtension) information).getContextInformationPosition() : offset; 173 if (current.fBeginOffset == -1) current.fBeginOffset= offset; 174 current.fOffset= offset; 175 current.fVisibleOffset= fViewer.getTextWidget().getSelectionRange().x - (offset - current.fBeginOffset); 176 current.fValidator= validator; 177 current.fPresenter= fContentAssistant.getContextInformationPresenter(fViewer, offset); 178 179 fContextFrameStack.push(current); 180 181 internalShowContextFrame(current, fContextFrameStack.size() == 1); 182 } 183 } 184 185 192 private void internalShowContextFrame(ContextFrame frame, boolean initial) { 193 194 frame.fValidator.install(frame.fInformation, fViewer, frame.fOffset); 195 196 if (frame.fPresenter != null) { 197 if (fTextPresentation == null) 198 fTextPresentation= new TextPresentation(); 199 frame.fPresenter.install(frame.fInformation, fViewer, frame.fBeginOffset); 200 frame.fPresenter.updatePresentation(frame.fOffset, fTextPresentation); 201 } 202 203 createContextInfoPopup(); 204 205 fContextInfoText.setText(frame.fInformation.getInformationDisplayString()); 206 if (fTextPresentation != null) 207 TextPresentation.applyTextPresentation(fTextPresentation, fContextInfoText); 208 resize(); 209 210 if (initial) { 211 if (fContentAssistant.addContentAssistListener(this, ContentAssistant2.CONTEXT_INFO_POPUP)) { 212 fContentAssistant.addToLayout(this, fContextInfoPopup, ContentAssistant2.LayoutManager.LAYOUT_CONTEXT_INFO_POPUP, frame.fVisibleOffset); 213 fContextInfoPopup.setVisible(true); 214 } 215 } else { 216 fContentAssistant.layout(ContentAssistant2.LayoutManager.LAYOUT_CONTEXT_INFO_POPUP, frame.fVisibleOffset); 217 } 218 } 219 220 227 private IContextInformation[] computeContextInformation(int position) { 228 return fContentAssistant.computeContextInformation(fViewer, position); 229 } 230 231 236 private String getErrorMessage() { 237 return fContentAssistant.getErrorMessage(); 238 } 239 240 243 private void createContextInfoPopup() { 244 if (Helper2.okToUse(fContextInfoPopup)) 245 return; 246 247 Control control= fViewer.getTextWidget(); 248 Display display= control.getDisplay(); 249 250 fContextInfoPopup= new Shell(control.getShell(), SWT.NO_TRIM | SWT.ON_TOP); 251 fContextInfoPopup.setBackground(display.getSystemColor(SWT.COLOR_BLACK)); 252 253 fContextInfoText= new StyledText(fContextInfoPopup, SWT.MULTI | SWT.READ_ONLY); 254 255 Color c= fContentAssistant.getContextInformationPopupBackground(); 256 if (c == null) 257 c= display.getSystemColor(SWT.COLOR_INFO_BACKGROUND); 258 fContextInfoText.setBackground(c); 259 260 c= fContentAssistant.getContextInformationPopupForeground(); 261 if (c == null) 262 c= display.getSystemColor(SWT.COLOR_INFO_FOREGROUND); 263 fContextInfoText.setForeground(c); 264 } 265 266 270 private void resize() { 271 Point size= fContextInfoText.computeSize(SWT.DEFAULT, SWT.DEFAULT, true); 272 size.x += 3; 273 fContextInfoText.setSize(size); 274 fContextInfoText.setLocation(1,1); 275 size.x += 2; 276 size.y += 2; 277 fContextInfoPopup.setSize(size); 278 } 279 280 283 private void hideContextInfoPopup() { 284 285 if (Helper2.okToUse(fContextInfoPopup)) { 286 287 int size= fContextFrameStack.size(); 288 if (size > 0) { 289 fContextFrameStack.pop(); 290 -- size; 291 } 292 293 if (size > 0) { 294 ContextFrame current= (ContextFrame) fContextFrameStack.peek(); 295 internalShowContextFrame(current, false); 296 } else { 297 298 fContentAssistant.removeContentAssistListener(this, ContentAssistant2.CONTEXT_INFO_POPUP); 299 300 fContextInfoPopup.setVisible(false); 301 fContextInfoPopup.dispose(); 302 fContextInfoPopup= null; 303 304 if (fTextPresentation != null) { 305 fTextPresentation.clear(); 306 fTextPresentation= null; 307 } 308 } 309 } 310 311 if (fContextInfoPopup == null) 312 fContentAssistant.contextInformationClosed(); 313 } 314 315 319 private void createContextSelector() { 320 if (Helper2.okToUse(fContextSelectorShell)) 321 return; 322 323 Control control= fViewer.getTextWidget(); 324 fContextSelectorShell= new Shell(control.getShell(), SWT.NO_TRIM | SWT.ON_TOP); 325 GridLayout layout= new GridLayout(); 326 layout.marginWidth= 0; 327 layout.marginHeight= 0; 328 fContextSelectorShell.setLayout(layout); 329 fContextSelectorShell.setBackground(control.getDisplay().getSystemColor(SWT.COLOR_BLACK)); 330 331 332 fContextSelectorTable= new Table(fContextSelectorShell, SWT.H_SCROLL | SWT.V_SCROLL); 333 fContextSelectorTable.setLocation(1, 1); 334 GridData gd= new GridData(GridData.FILL_BOTH); 335 gd.heightHint= fContextSelectorTable.getItemHeight() * 10; 336 gd.widthHint= 300; 337 fContextSelectorTable.setLayoutData(gd); 338 339 fContextSelectorShell.pack(true); 340 341 Color c= fContentAssistant.getContextSelectorBackground(); 342 if (c == null) 343 c= control.getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND); 344 fContextSelectorTable.setBackground(c); 345 346 c= fContentAssistant.getContextSelectorForeground(); 347 if (c == null) 348 c= control.getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND); 349 fContextSelectorTable.setForeground(c); 350 351 fContextSelectorTable.addSelectionListener(new SelectionListener() { 352 public void widgetSelected(SelectionEvent e) { 353 } 354 355 public void widgetDefaultSelected(SelectionEvent e) { 356 insertSelectedContext(); 357 hideContextSelector(); 358 } 359 }); 360 361 fPopupCloser.install(fContentAssistant, fContextSelectorTable); 362 363 fContextSelectorTable.setHeaderVisible(false); 364 fContentAssistant.addToLayout(this, fContextSelectorShell, ContentAssistant2.LayoutManager.LAYOUT_CONTEXT_SELECTOR, fContentAssistant.getSelectionOffset()); 365 } 366 367 371 private void insertSelectedContext() { 372 int i= fContextSelectorTable.getSelectionIndex(); 373 374 if (i < 0 || i >= fContextSelectorInput.length) 375 return; 376 377 int position= fViewer.getSelectedRange().x; 378 internalShowContextInfo(fContextSelectorInput[i], position); 379 } 380 381 386 private void setContexts(IContextInformation[] contexts) { 387 if (Helper2.okToUse(fContextSelectorTable)) { 388 389 fContextSelectorInput= contexts; 390 391 fContextSelectorTable.setRedraw(false); 392 fContextSelectorTable.removeAll(); 393 394 TableItem item; 395 IContextInformation t; 396 for (int i= 0; i < contexts.length; i++) { 397 t= contexts[i]; 398 item= new TableItem(fContextSelectorTable, SWT.NULL); 399 if (t.getImage() != null) 400 item.setImage(t.getImage()); 401 item.setText(t.getContextDisplayString()); 402 } 403 404 fContextSelectorTable.select(0); 405 fContextSelectorTable.setRedraw(true); 406 } 407 } 408 409 412 private void displayContextSelector() { 413 if (fContentAssistant.addContentAssistListener(this, ContentAssistant2.CONTEXT_SELECTOR)) 414 fContextSelectorShell.setVisible(true); 415 } 416 417 420 private void hideContextSelector() { 421 if (Helper2.okToUse(fContextSelectorShell)) { 422 fContentAssistant.removeContentAssistListener(this, ContentAssistant2.CONTEXT_SELECTOR); 423 424 fPopupCloser.uninstall(); 425 fContextSelectorShell.setVisible(false); 426 fContextSelectorShell.dispose(); 427 fContextSelectorShell= null; 428 } 429 430 if (!Helper2.okToUse(fContextInfoPopup)) 431 fContentAssistant.contextInformationClosed(); 432 } 433 434 439 public boolean hasFocus() { 440 if (Helper2.okToUse(fContextSelectorShell)) 441 return (fContextSelectorShell.isFocusControl() || fContextSelectorTable.isFocusControl()); 442 443 return false; 444 } 445 446 449 public void hide() { 450 hideContextSelector(); 451 hideContextInfoPopup(); 452 } 453 454 460 public boolean isActive() { 461 return (Helper2.okToUse(fContextInfoPopup) || Helper2.okToUse(fContextSelectorShell)); 462 } 463 464 467 public boolean verifyKey(VerifyEvent e) { 468 if (Helper2.okToUse(fContextSelectorShell)) 469 return contextSelectorKeyPressed(e); 470 if (Helper2.okToUse(fContextInfoPopup)) 471 return contextInfoPopupKeyPressed(e); 472 return true; 473 } 474 475 481 private boolean contextSelectorKeyPressed(VerifyEvent e) { 482 483 char key= e.character; 484 if (key == 0) { 485 486 int change; 487 int visibleRows= (fContextSelectorTable.getSize().y / fContextSelectorTable.getItemHeight()) - 1; 488 int selection= fContextSelectorTable.getSelectionIndex(); 489 490 switch (e.keyCode) { 491 492 case SWT.ARROW_UP: 493 change= (fContextSelectorTable.getSelectionIndex() > 0 ? -1 : 0); 494 break; 495 496 case SWT.ARROW_DOWN: 497 change= (fContextSelectorTable.getSelectionIndex() < fContextSelectorTable.getItemCount() - 1 ? 1 : 0); 498 break; 499 500 case SWT.PAGE_DOWN : 501 change= visibleRows; 502 if (selection + change >= fContextSelectorTable.getItemCount()) 503 change= fContextSelectorTable.getItemCount() - selection; 504 break; 505 506 case SWT.PAGE_UP : 507 change= -visibleRows; 508 if (selection + change < 0) 509 change= -selection; 510 break; 511 512 case SWT.HOME : 513 change= -selection; 514 break; 515 516 case SWT.END : 517 change= fContextSelectorTable.getItemCount() - selection; 518 break; 519 520 default: 521 if (e.keyCode != SWT.MOD1 && e.keyCode != SWT.MOD2 && e.keyCode != SWT.MOD3 && e.keyCode != SWT.MOD4) 522 hideContextSelector(); 523 return true; 524 } 525 526 fContextSelectorTable.setSelection(selection + change); 527 fContextSelectorTable.showSelection(); 528 e.doit= false; 529 return false; 530 531 } else if ('\t' == key) { 532 e.doit= false; 534 fContextSelectorShell.setFocus(); 535 return false; 536 } else if (key == 0x1B) { 537 hideContextSelector(); 539 } 540 541 return true; 542 } 543 544 550 private boolean contextInfoPopupKeyPressed(KeyEvent e) { 551 552 char key= e.character; 553 if (key == 0) { 554 555 switch (e.keyCode) { 556 557 case SWT.ARROW_LEFT: 558 case SWT.ARROW_RIGHT: 559 validateContextInformation(); 560 break; 561 default: 562 if (e.keyCode != SWT.MOD1 && e.keyCode != SWT.MOD2 && e.keyCode != SWT.MOD3 && e.keyCode != SWT.MOD4) 563 hideContextInfoPopup(); 564 break; 565 } 566 567 } else if (key == 0x1B) { 568 hideContextInfoPopup(); 570 } else { 571 validateContextInformation(); 572 } 573 return true; 574 } 575 576 579 public void processEvent(VerifyEvent event) { 580 if (Helper2.okToUse(fContextSelectorShell)) 581 contextSelectorProcessEvent(event); 582 if (Helper2.okToUse(fContextInfoPopup)) 583 contextInfoPopupProcessEvent(event); 584 } 585 586 591 private void contextSelectorProcessEvent(VerifyEvent e) { 592 593 if (e.start == e.end && e.text != null && e.text.equals(fLineDelimiter)) { 594 e.doit= false; 595 insertSelectedContext(); 596 } 597 598 hideContextSelector(); 599 } 600 601 606 private void contextInfoPopupProcessEvent(VerifyEvent e) { 607 if (e.start != e.end && (e.text == null || e.text.length() == 0)) 608 validateContextInformation(); 609 } 610 611 614 private void validateContextInformation() { 615 621 fContextInfoPopup.getDisplay().asyncExec(new Runnable () { 622 623 private ContextFrame fFrame= (ContextFrame) fContextFrameStack.peek(); 624 625 public void run() { 626 if (Helper2.okToUse(fContextInfoPopup) && fFrame == fContextFrameStack.peek()) { 627 int offset= fViewer.getSelectedRange().x; 628 if (fFrame.fValidator == null || !fFrame.fValidator.isContextInformationValid(offset)) { 629 hideContextInfoPopup(); 630 } else if (fFrame.fPresenter != null && fFrame.fPresenter.updatePresentation(offset, fTextPresentation)) { 631 TextPresentation.applyTextPresentation(fTextPresentation, fContextInfoText); 632 resize(); 633 } 634 } 635 } 636 }); 637 } 638 } 639 | Popular Tags |