]> git.uio.no Git - ifi-stolz-refaktor.git/blame - case-study/jdt-before/ui/org/eclipse/jdt/internal/ui/text/java/hover/AnnotationExpansionControl.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-before / ui / org / eclipse / jdt / internal / ui / text / java / hover / AnnotationExpansionControl.java
CommitLineData
1b2798f6
EK
1/*******************************************************************************
2 * Copyright (c) 2000, 2012 IBM Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * IBM Corporation - initial API and implementation
10 *******************************************************************************/
11package org.eclipse.jdt.internal.ui.text.java.hover;
12
13import java.util.ArrayList;
14import java.util.Iterator;
15import java.util.List;
16
17import org.eclipse.swt.SWT;
18import org.eclipse.swt.custom.StyleRange;
19import org.eclipse.swt.custom.StyledText;
20import org.eclipse.swt.events.DisposeEvent;
21import org.eclipse.swt.events.DisposeListener;
22import org.eclipse.swt.events.FocusListener;
23import org.eclipse.swt.events.MenuEvent;
24import org.eclipse.swt.events.MenuListener;
25import org.eclipse.swt.events.MouseAdapter;
26import org.eclipse.swt.events.MouseEvent;
27import org.eclipse.swt.events.MouseTrackAdapter;
28import org.eclipse.swt.events.MouseTrackListener;
29import org.eclipse.swt.events.PaintEvent;
30import org.eclipse.swt.events.PaintListener;
31import org.eclipse.swt.graphics.Color;
32import org.eclipse.swt.graphics.Cursor;
33import org.eclipse.swt.graphics.Point;
34import org.eclipse.swt.graphics.Rectangle;
35import org.eclipse.swt.layout.GridData;
36import org.eclipse.swt.layout.GridLayout;
37import org.eclipse.swt.widgets.Canvas;
38import org.eclipse.swt.widgets.Composite;
39import org.eclipse.swt.widgets.Control;
40import org.eclipse.swt.widgets.Display;
41import org.eclipse.swt.widgets.Event;
42import org.eclipse.swt.widgets.Layout;
43import org.eclipse.swt.widgets.Listener;
44import org.eclipse.swt.widgets.Menu;
45import org.eclipse.swt.widgets.Shell;
46import org.eclipse.swt.widgets.Widget;
47
48import org.eclipse.jface.viewers.IDoubleClickListener;
49
50import org.eclipse.jface.text.AbstractInformationControlManager;
51import org.eclipse.jface.text.DefaultInformationControl;
52import org.eclipse.jface.text.IInformationControl;
53import org.eclipse.jface.text.IInformationControlCreator;
54import org.eclipse.jface.text.IInformationControlExtension;
55import org.eclipse.jface.text.IInformationControlExtension2;
56import org.eclipse.jface.text.IInformationControlExtension5;
57import org.eclipse.jface.text.IRegion;
58import org.eclipse.jface.text.IViewportListener;
59import org.eclipse.jface.text.Position;
60import org.eclipse.jface.text.Region;
61import org.eclipse.jface.text.TextViewer;
62import org.eclipse.jface.text.source.Annotation;
63import org.eclipse.jface.text.source.IAnnotationAccess;
64import org.eclipse.jface.text.source.IAnnotationAccessExtension;
65import org.eclipse.jface.text.source.IAnnotationModel;
66import org.eclipse.jface.text.source.ISourceViewer;
67import org.eclipse.jface.text.source.IVerticalRulerInfo;
68import org.eclipse.jface.text.source.IVerticalRulerListener;
69import org.eclipse.jface.text.source.VerticalRulerEvent;
70
71
72/**
73 * A control that can display a number of annotations. The control can decide how it layouts the
74 * annotations to present them to the user.
75 * <p>
76 * This class got moved here form Platform Text since it was not used there
77 * and caused discouraged access warnings. It will be moved down again once
78 * annotation roll-over support is provided by Platform Text.
79 * </p>
80 * <p>Each annotation can have its custom context menu and hover.</p>
81 *
82 * @since 3.2
83 */
84public class AnnotationExpansionControl implements IInformationControl, IInformationControlExtension, IInformationControlExtension2, IInformationControlExtension5 {
85
86
87 public interface ICallback {
88 void run(IInformationControlExtension2 control);
89 }
90
91 /**
92 * Input used by the control to display the annotations.
93 * TODO move to top-level class
94 * TODO encapsulate fields
95 *
96 * @since 3.0
97 */
98 public static class AnnotationHoverInput {
99 public Annotation[] fAnnotations;
100 public ISourceViewer fViewer;
101 public IVerticalRulerInfo fRulerInfo;
102 public IVerticalRulerListener fAnnotationListener;
103 public IDoubleClickListener fDoubleClickListener;
104 public ICallback redoAction;
105 public IAnnotationModel model;
106 }
107
108 private final class Item {
109 Annotation fAnnotation;
110 Canvas canvas;
111 StyleRange[] oldStyles;
112
113 public void selected() {
114 Display disp= fShell.getDisplay();
115 canvas.setCursor(getHandCursor(disp));
116 // TODO: shade - for now: set grey background
117 canvas.setBackground(getSelectionColor(disp));
118
119 // highlight the viewer background at its position
120 oldStyles= setViewerBackground(fAnnotation);
121
122 // set the selection
123 fSelection= this;
124
125 if (fHoverManager != null)
126 fHoverManager.showInformation();
127
128 if (fInput.fAnnotationListener != null) {
129 VerticalRulerEvent event= new VerticalRulerEvent(fAnnotation);
130 fInput.fAnnotationListener.annotationSelected(event);
131 }
132
133 }
134
135 public void defaultSelected(MouseEvent e) {
136 if (fInput.fAnnotationListener != null) {
137 Event swtEvent= new Event();
138 swtEvent.type= SWT.MouseDown;
139 swtEvent.display= e.display;
140 swtEvent.widget= e.widget;
141 swtEvent.time= e.time;
142 swtEvent.data= e.data;
143 swtEvent.x= e.x;
144 swtEvent.y= e.y;
145 swtEvent.button= e.button;
146 swtEvent.stateMask= e.stateMask;
147 swtEvent.count= e.count;
148 VerticalRulerEvent event= new VerticalRulerEvent(fAnnotation, swtEvent);
149 fInput.fAnnotationListener.annotationDefaultSelected(event);
150 }
151
152 dispose();
153 }
154
155 public void deselect() {
156 // hide the popup
157// fHoverManager.disposeInformationControl();
158
159 // deselect
160 fSelection= null;
161
162 resetViewerBackground(oldStyles);
163 oldStyles= null;
164
165 Display disp= fShell.getDisplay();
166 canvas.setCursor(null);
167 // TODO: remove shading - for now: set standard background
168 canvas.setBackground(disp.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
169
170 }
171
172 }
173
174 /**
175 * Disposes of an item
176 */
177 private final static class MyDisposeListener implements DisposeListener {
178 /*
179 * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
180 */
181 public void widgetDisposed(DisposeEvent e) {
182 Item item= (Item) ((Widget) e.getSource()).getData();
183 item.deselect();
184 item.canvas= null;
185 item.fAnnotation= null;
186 item.oldStyles= null;
187
188 ((Widget) e.getSource()).setData(null);
189 }
190 }
191
192 /**
193 * Listener on context menu invocation on the items
194 */
195 private final class MyMenuDetectListener implements Listener {
196 /*
197 * @see org.eclipse.swt.widgets.Listener#handleEvent(org.eclipse.swt.widgets.Event)
198 */
199 public void handleEvent(Event event) {
200 if (event.type == SWT.MenuDetect) {
201 // TODO: show per-item menu
202 // for now: show ruler context menu
203 if (fInput != null) {
204 Control ruler= fInput.fRulerInfo.getControl();
205 if (ruler != null && !ruler.isDisposed()) {
206 Menu menu= ruler.getMenu();
207 if (menu != null && !menu.isDisposed()) {
208 menu.setLocation(event.x, event.y);
209 menu.addMenuListener(new MenuListener() {
210
211 public void menuHidden(MenuEvent e) {
212 dispose();
213 }
214
215 public void menuShown(MenuEvent e) {
216 }
217
218 });
219 menu.setVisible(true);
220 }
221 }
222 }
223 }
224 }
225 }
226
227
228 /**
229 * Listener on mouse events on the items.
230 */
231 private final class MyMouseListener extends MouseAdapter {
232 /*
233 * @see org.eclipse.swt.events.MouseListener#mouseDoubleClick(org.eclipse.swt.events.MouseEvent)
234 */
235 @Override
236 public void mouseDoubleClick(MouseEvent e) {
237 Item item= (Item) ((Widget) e.getSource()).getData();
238 if (e.button == 1 && item.fAnnotation == fInput.fAnnotations[0] && fInput.fDoubleClickListener != null) {
239 fInput.fDoubleClickListener.doubleClick(null);
240 // special code for JDT to renew the annotation set.
241 if (fInput.redoAction != null)
242 fInput.redoAction.run(AnnotationExpansionControl.this);
243 }
244// dispose();
245 // TODO special action to invoke double-click action on the vertical ruler
246 // how about
247// Canvas can= (Canvas) e.getSource();
248// Annotation a= (Annotation) can.getData();
249// if (a != null) {
250// a.getDoubleClickAction().run();
251// }
252 }
253
254 /*
255 * Using mouseDown as mouseUp isn't fired on some Platforms, for
256 * details see https://bugs.eclipse.org/bugs/show_bug.cgi?id=165533
257 *
258 * @see org.eclipse.swt.events.MouseListener#mouseDown(org.eclipse.swt.events.MouseEvent)
259 */
260 @Override
261 public void mouseDown(MouseEvent e) {
262 Item item= (Item) ((Widget) e.getSource()).getData();
263 // TODO for now, to make double click work: disable single click on the first item
264 // disable later when the annotationlistener selectively handles input
265 if (item != null && e.button == 1) // && item.fAnnotation != fInput.fAnnotations[0])
266 item.defaultSelected(e);
267 }
268
269 }
270
271 /**
272 * Listener on mouse track events on the items.
273 */
274 private final class MyMouseTrackListener implements MouseTrackListener {
275 /*
276 * @see org.eclipse.swt.events.MouseTrackListener#mouseEnter(org.eclipse.swt.events.MouseEvent)
277 */
278 public void mouseEnter(MouseEvent e) {
279 Item item= (Item) ((Widget) e.getSource()).getData();
280 if (item != null)
281 item.selected();
282 }
283
284 /*
285 * @see org.eclipse.swt.events.MouseTrackListener#mouseExit(org.eclipse.swt.events.MouseEvent)
286 */
287 public void mouseExit(MouseEvent e) {
288
289 Item item= (Item) ((Widget) e.getSource()).getData();
290 if (item != null)
291 item.deselect();
292
293 // if the event lies outside the entire popup, dispose
294 org.eclipse.swt.graphics.Region region= fShell.getRegion();
295 Canvas can= (Canvas) e.getSource();
296 Point p= can.toDisplay(e.x, e.y);
297 if (region == null) {
298 Rectangle bounds= fShell.getBounds();
299// p= fShell.toControl(p);
300 if (!bounds.contains(p))
301 dispose();
302 } else {
303 p= fShell.toControl(p);
304 if (!region.contains(p))
305 dispose();
306 }
307
308
309 }
310
311 /*
312 * @see org.eclipse.swt.events.MouseTrackListener#mouseHover(org.eclipse.swt.events.MouseEvent)
313 */
314 public void mouseHover(MouseEvent e) {
315 if (fHoverManager == null) {
316 fHoverManager= new HoverManager();
317 fHoverManager.takesFocusWhenVisible(false);
318 fHoverManager.install(fComposite);
319 fHoverManager.showInformation();
320 }
321 }
322 }
323
324
325 /**
326 * @since 3.0
327 */
328 public class LinearLayouter {
329
330 private static final int ANNOTATION_SIZE= 14;
331 private static final int BORDER_WIDTH= 2;
332
333 public Layout getLayout(int itemCount) {
334 // simple layout: a row of items
335 GridLayout layout= new GridLayout(itemCount, true);
336 layout.horizontalSpacing= 1;
337 layout.verticalSpacing= 0;
338 layout.marginHeight= 1;
339 layout.marginWidth= 1;
340 return layout;
341 }
342
343 public Object getLayoutData() {
344 GridData gridData= new GridData(ANNOTATION_SIZE + 2 * BORDER_WIDTH, ANNOTATION_SIZE + 2 * BORDER_WIDTH);
345 gridData.horizontalAlignment= GridData.CENTER;
346 gridData.verticalAlignment= GridData.CENTER;
347 return gridData;
348 }
349
350 public int getAnnotationSize() {
351 return ANNOTATION_SIZE;
352 }
353
354 public int getBorderWidth() {
355 return BORDER_WIDTH;
356 }
357
358 /**
359 * Gets the shell region for the given number of items.
360 *
361 * @param itemCount the item count
362 * @return the shell region
363 */
364 public org.eclipse.swt.graphics.Region getShellRegion(int itemCount) {
365 // no special region - set to null for default shell size
366 return null;
367 }
368
369 }
370
371
372 /**
373 * Listener on paint events on the items. Paints the annotation image on the given <code>GC</code>.
374 */
375 private final class MyPaintListener implements PaintListener {
376 /*
377 * @see org.eclipse.swt.events.PaintListener#paintControl(org.eclipse.swt.events.PaintEvent)
378 */
379 public void paintControl(PaintEvent e) {
380 Canvas can= (Canvas) e.getSource();
381 Annotation a= ((Item) can.getData()).fAnnotation;
382 if (a != null) {
383 Rectangle rect= new Rectangle(fLayouter.getBorderWidth(), fLayouter.getBorderWidth(), fLayouter.getAnnotationSize(), fLayouter.getAnnotationSize());
384 if (fAnnotationAccessExtension != null)
385 fAnnotationAccessExtension.paint(a, e.gc, can, rect);
386 }
387 }
388 }
389
390 /**
391 * Our own private hover manager used to shop per-item pop-ups.
392 */
393 private final class HoverManager extends AbstractInformationControlManager {
394
395 /**
396 *
397 */
398 public HoverManager() {
399 super(new IInformationControlCreator() {
400 public IInformationControl createInformationControl(Shell parent) {
401 return new DefaultInformationControl(parent);
402 }
403 });
404
405 setMargins(5, 10);
406 setAnchor(ANCHOR_BOTTOM);
407 setFallbackAnchors(new Anchor[] {ANCHOR_BOTTOM, ANCHOR_LEFT, ANCHOR_RIGHT} );
408 }
409
410 /*
411 * @see org.eclipse.jface.text.AbstractInformationControlManager#computeInformation()
412 */
413 @Override
414 protected void computeInformation() {
415 if (fSelection != null) {
416 Rectangle subjectArea= fSelection.canvas.getBounds();
417 Annotation annotation= fSelection.fAnnotation;
418 String msg;
419 if (annotation != null)
420 msg= annotation.getText();
421 else
422 msg= null;
423
424 setInformation(msg, subjectArea);
425 }
426 }
427
428
429 }
430
431 /** Model data. */
432 protected AnnotationHoverInput fInput;
433 /** The control's shell */
434 private Shell fShell;
435 /** The composite combining all the items. */
436 protected Composite fComposite;
437 /** The currently selected item, or <code>null</code> if none is selected. */
438 private Item fSelection;
439 /** The hover manager for the per-item hovers. */
440 private HoverManager fHoverManager;
441 /** The annotation access extension. */
442 private IAnnotationAccessExtension fAnnotationAccessExtension;
443
444
445 /* listener legion */
446 private final MyPaintListener fPaintListener;
447 private final MyMouseTrackListener fMouseTrackListener;
448 private final MyMouseListener fMouseListener;
449 private final MyMenuDetectListener fMenuDetectListener;
450 private final DisposeListener fDisposeListener;
451 private final IViewportListener fViewportListener;
452
453 private LinearLayouter fLayouter;
454
455 /**
456 * Creates a new control.
457 *
458 * @param parent parent shell
459 * @param shellStyle additional style flags
460 * @param access the annotation access
461 */
462 public AnnotationExpansionControl(Shell parent, int shellStyle, IAnnotationAccess access) {
463 fPaintListener= new MyPaintListener();
464 fMouseTrackListener= new MyMouseTrackListener();
465 fMouseListener= new MyMouseListener();
466 fMenuDetectListener= new MyMenuDetectListener();
467 fDisposeListener= new MyDisposeListener();
468 fViewportListener= new IViewportListener() {
469
470 public void viewportChanged(int verticalOffset) {
471 dispose();
472 }
473
474 };
475 fLayouter= new LinearLayouter();
476
477 if (access instanceof IAnnotationAccessExtension)
478 fAnnotationAccessExtension= (IAnnotationAccessExtension) access;
479
480 fShell= new Shell(parent, shellStyle | SWT.NO_FOCUS | SWT.ON_TOP);
481 Display display= fShell.getDisplay();
482 fShell.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
483 fComposite= new Composite(fShell, SWT.NO_FOCUS | SWT.NO_REDRAW_RESIZE | SWT.NO_TRIM);
484// fComposite= new Composite(fShell, SWT.NO_FOCUS | SWT.NO_REDRAW_RESIZE | SWT.NO_TRIM | SWT.V_SCROLL);
485
486 GridLayout layout= new GridLayout(1, true);
487 layout.marginHeight= 0;
488 layout.marginWidth= 0;
489 fShell.setLayout(layout);
490
491 GridData data= new GridData(GridData.FILL_BOTH);
492 data.heightHint= fLayouter.getAnnotationSize() + 2 * fLayouter.getBorderWidth() + 4;
493 fComposite.setLayoutData(data);
494 fComposite.addMouseTrackListener(new MouseTrackAdapter() {
495
496 @Override
497 public void mouseExit(MouseEvent e) {
498 if (fComposite == null)
499 return;
500 Control[] children= fComposite.getChildren();
501 Rectangle bounds= null;
502 for (int i= 0; i < children.length; i++) {
503 if (bounds == null)
504 bounds= children[i].getBounds();
505 else
506 bounds.add(children[i].getBounds());
507 if (bounds.contains(e.x, e.y))
508 return;
509 }
510
511 // if none of the children contains the event, we leave the popup
512 dispose();
513 }
514
515 });
516
517// fComposite.getVerticalBar().addListener(SWT.Selection, new Listener() {
518//
519// public void handleEvent(Event event) {
520// Rectangle bounds= fShell.getBounds();
521// int x= bounds.x - fLayouter.getAnnotationSize() - fLayouter.getBorderWidth();
522// int y= bounds.y;
523// fShell.setBounds(x, y, bounds.width, bounds.height);
524// }
525//
526// });
527
528 Cursor handCursor= getHandCursor(display);
529 fShell.setCursor(handCursor);
530 fComposite.setCursor(handCursor);
531
532 setInfoSystemColor();
533 }
534
535 private void setInfoSystemColor() {
536 Display display= fShell.getDisplay();
537 setForegroundColor(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
538 setBackgroundColor(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
539 }
540
541 /*
542 * @see org.eclipse.jface.text.IInformationControl#setInformation(java.lang.String)
543 */
544 public void setInformation(String information) {
545 setInput(null);
546 }
547
548
549 /*
550 * @see org.eclipse.jface.text.IInformationControlExtension2#setInput(java.lang.Object)
551 */
552 public void setInput(Object input) {
553 if (fInput != null && fInput.fViewer != null)
554 fInput.fViewer.removeViewportListener(fViewportListener);
555
556 if (input instanceof AnnotationHoverInput)
557 fInput= (AnnotationHoverInput) input;
558 else
559 fInput= null;
560
561 inputChanged(fInput, null);
562 }
563
564 /**
565 * Internal hook method called when the input is
566 * initially set or subsequently changed.
567 *
568 * @param newInput the new input
569 * @param newSelection the new selection
570 */
571 protected void inputChanged(Object newInput, Object newSelection) {
572 refresh();
573 }
574
575 protected void refresh() {
576 adjustItemNumber();
577
578 if (fInput == null)
579 return;
580
581 if (fInput.fAnnotations == null)
582 return;
583
584 if (fInput.fViewer != null)
585 fInput.fViewer.addViewportListener(fViewportListener);
586
587 fShell.setRegion(fLayouter.getShellRegion(fInput.fAnnotations.length));
588
589 Layout layout= fLayouter.getLayout(fInput.fAnnotations.length);
590 fComposite.setLayout(layout);
591
592 Control[] children= fComposite.getChildren();
593 for (int i= 0; i < fInput.fAnnotations.length; i++) {
594 Canvas canvas= (Canvas) children[i];
595 Item item= new Item();
596 item.canvas= canvas;
597 item.fAnnotation= fInput.fAnnotations[i];
598 canvas.setData(item);
599 canvas.redraw();
600 }
601
602 }
603
604 protected void adjustItemNumber() {
605 if (fComposite == null)
606 return;
607
608 Control[] children= fComposite.getChildren();
609 int oldSize= children.length;
610 int newSize= fInput == null ? 0 : fInput.fAnnotations.length;
611
612 Display display= fShell.getDisplay();
613
614 // add missing items
615 for (int i= oldSize; i < newSize; i++) {
616 Canvas canvas= new Canvas(fComposite, SWT.NONE);
617 Object gridData= fLayouter.getLayoutData();
618 canvas.setLayoutData(gridData);
619 canvas.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
620
621 canvas.addPaintListener(fPaintListener);
622
623 canvas.addMouseTrackListener(fMouseTrackListener);
624
625 canvas.addMouseListener(fMouseListener);
626
627 canvas.addListener(SWT.MenuDetect, fMenuDetectListener);
628
629 canvas.addDisposeListener(fDisposeListener);
630 }
631
632 // dispose of exceeding resources
633 for (int i= oldSize; i > newSize; i--) {
634 Item item= (Item) children[i - 1].getData();
635 item.deselect();
636 children[i - 1].dispose();
637 }
638
639 }
640
641 /*
642 * @see IInformationControl#setVisible(boolean)
643 */
644 public void setVisible(boolean visible) {
645 fShell.setVisible(visible);
646 }
647
648 /*
649 * @see IInformationControl#dispose()
650 */
651 public void dispose() {
652 if (fShell != null) {
653 if (!fShell.isDisposed())
654 fShell.dispose();
655 fShell= null;
656 fComposite= null;
657 if (fHoverManager != null)
658 fHoverManager.dispose();
659 fHoverManager= null;
660 fSelection= null;
661 }
662 }
663
664 /*
665 * @see org.eclipse.jface.text.IInformationControlExtension#hasContents()
666 */
667 public boolean hasContents() {
668 return fInput.fAnnotations != null && fInput.fAnnotations.length > 0;
669 }
670
671 /*
672 * @see org.eclipse.jface.text.IInformationControl#setSizeConstraints(int, int)
673 */
674 public void setSizeConstraints(int maxWidth, int maxHeight) {
675 //fMaxWidth= maxWidth;
676 //fMaxHeight= maxHeight;
677 }
678
679 /*
680 * @see org.eclipse.jface.text.IInformationControl#computeSizeHint()
681 */
682 public Point computeSizeHint() {
683 return fShell.computeSize(SWT.DEFAULT, SWT.DEFAULT);
684 }
685
686 /*
687 * @see IInformationControl#setLocation(Point)
688 */
689 public void setLocation(Point location) {
690 fShell.setLocation(location);
691 }
692
693 /*
694 * @see IInformationControl#setSize(int, int)
695 */
696 public void setSize(int width, int height) {
697 fShell.setSize(width, height);
698 }
699
700 /*
701 * @see IInformationControl#addDisposeListener(DisposeListener)
702 */
703 public void addDisposeListener(DisposeListener listener) {
704 fShell.addDisposeListener(listener);
705 }
706
707 /*
708 * @see IInformationControl#removeDisposeListener(DisposeListener)
709 */
710 public void removeDisposeListener(DisposeListener listener) {
711 fShell.removeDisposeListener(listener);
712 }
713
714 /*
715 * @see IInformationControl#setForegroundColor(Color)
716 */
717 public void setForegroundColor(Color foreground) {
718 fComposite.setForeground(foreground);
719 }
720
721 /*
722 * @see IInformationControl#setBackgroundColor(Color)
723 */
724 public void setBackgroundColor(Color background) {
725 fComposite.setBackground(background);
726 }
727
728 /*
729 * @see IInformationControl#isFocusControl()
730 */
731 public boolean isFocusControl() {
732 return fShell.getDisplay().getActiveShell() == fShell;
733 }
734
735 /*
736 * @see IInformationControl#setFocus()
737 */
738 public void setFocus() {
739 fShell.forceFocus();
740 }
741
742 /*
743 * @see IInformationControl#addFocusListener(FocusListener)
744 */
745 public void addFocusListener(FocusListener listener) {
746 fShell.addFocusListener(listener);
747 }
748
749 /*
750 * @see IInformationControl#removeFocusListener(FocusListener)
751 */
752 public void removeFocusListener(FocusListener listener) {
753 fShell.removeFocusListener(listener);
754 }
755
756 private StyleRange[] setViewerBackground(Annotation annotation) {
757 StyledText text= fInput.fViewer.getTextWidget();
758 if (text == null || text.isDisposed())
759 return null;
760
761 Display disp= text.getDisplay();
762
763 Position pos= fInput.model.getPosition(annotation);
764 if (pos == null)
765 return null;
766
767 IRegion region= ((TextViewer)fInput.fViewer).modelRange2WidgetRange(new Region(pos.offset, pos.length));
768 if (region == null)
769 return null;
770
771 StyleRange[] ranges= text.getStyleRanges(region.getOffset(), region.getLength());
772
773 List<StyleRange> undoRanges= new ArrayList<StyleRange>(ranges.length);
774 for (int i= 0; i < ranges.length; i++) {
775 undoRanges.add((StyleRange)ranges[i].clone());
776 }
777
778 int offset= region.getOffset();
779 StyleRange current= undoRanges.size() > 0 ? undoRanges.get(0) : null;
780 int curStart= current != null ? current.start : region.getOffset() + region.getLength();
781 int curEnd= current != null ? current.start + current.length : -1;
782 int index= 0;
783
784 // fill no-style regions
785 while (curEnd < region.getOffset() + region.getLength()) {
786 // add empty range
787 if (curStart > offset) {
788 StyleRange undoRange= new StyleRange(offset, curStart - offset, null, null);
789 undoRanges.add(index, undoRange);
790 index++;
791 }
792
793 // step
794 index++;
795 if (index < undoRanges.size()) {
796 offset= curEnd;
797 current= undoRanges.get(index);
798 curStart= current.start;
799 curEnd= current.start + current.length;
800 } else if (index == undoRanges.size()) {
801 // last one
802 offset= curEnd;
803 current= null;
804 curStart= region.getOffset() + region.getLength();
805 curEnd= -1;
806 } else
807 curEnd= region.getOffset() + region.getLength();
808 }
809
810 // create modified styles (with background)
811 List<StyleRange> shadedRanges= new ArrayList<StyleRange>(undoRanges.size());
812 for (Iterator<StyleRange> it= undoRanges.iterator(); it.hasNext(); ) {
813 StyleRange range= (StyleRange) it.next().clone();
814 shadedRanges.add(range);
815 range.background= getHighlightColor(disp);
816 }
817
818 // set the ranges one by one
819 for (Iterator<StyleRange> iter= shadedRanges.iterator(); iter.hasNext(); ) {
820 text.setStyleRange(iter.next());
821
822 }
823
824 return undoRanges.toArray(undoRanges.toArray(new StyleRange[0]));
825 }
826
827 private void resetViewerBackground(StyleRange[] oldRanges) {
828
829 if (oldRanges == null)
830 return;
831
832 if (fInput == null)
833 return;
834
835 StyledText text= fInput.fViewer.getTextWidget();
836 if (text == null || text.isDisposed())
837 return;
838
839 // set the ranges one by one
840 for (int i= 0; i < oldRanges.length; i++) {
841 text.setStyleRange(oldRanges[i]);
842 }
843 }
844
845 private Color getHighlightColor(Display disp) {
846 return disp.getSystemColor(SWT.COLOR_GRAY);
847 }
848
849 private Color getSelectionColor(Display disp) {
850 return disp.getSystemColor(SWT.COLOR_GRAY);
851 }
852
853 private Cursor getHandCursor(Display disp) {
854 return disp.getSystemCursor(SWT.CURSOR_HAND);
855 }
856
857 /*
858 * @see org.eclipse.jface.text.IInformationControlExtension5#computeSizeConstraints(int, int)
859 * @since 3.4
860 */
861 public Point computeSizeConstraints(int widthInChars, int heightInChars) {
862 return null;
863 }
864
865 /*
866 * @see org.eclipse.jface.text.IInformationControlExtension5#containsControl(org.eclipse.swt.widgets.Control)
867 * @since 3.4
868 */
869 public boolean containsControl(Control control) {
870 do {
871 if (control == fShell)
872 return true;
873 if (control instanceof Shell)
874 return false;
875 control= control.getParent();
876 } while (control != null);
877 return false;
878 }
879
880 /*
881 * @see org.eclipse.jface.text.IInformationControlExtension5#getInformationPresenterControlCreator()
882 * @since 3.4
883 */
884 public IInformationControlCreator getInformationPresenterControlCreator() {
885 return null;
886 }
887
888 /*
889 * @see org.eclipse.jface.text.IInformationControlExtension5#isVisible()
890 */
891 public boolean isVisible() {
892 return fShell != null && !fShell.isDisposed() && fShell.isVisible();
893 }
894
895}