source: trunk/org.modelica.mdt.ui/src/org/modelica/mdt/ui/hover/AnnotationExpansionControl.java

Last change on this file was 694, checked in by adrpo, 13 years ago
  • updates to org.modelica.mdt.ui


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