d2760fcc2b855c945597f2ffdacad6f552d63777
[phpeclipse.git] / net.sourceforge.phpeclipse.ui / src / net / sourceforge / phpdt / internal / ui / text / java / hover / SourceViewerInformationControl.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.ui.text.java.hover;
12
13 import net.sourceforge.phpdt.ui.text.PHPSourceViewerConfiguration;
14 //import net.sourceforge.phpeclipse.PHPeclipsePlugin;
15 import net.sourceforge.phpeclipse.phpeditor.JavaSourceViewer;
16 import net.sourceforge.phpeclipse.ui.WebUI;
17
18 import org.eclipse.jface.preference.IPreferenceStore;
19 import org.eclipse.jface.text.Document;
20 import org.eclipse.jface.text.IDocument;
21 import org.eclipse.jface.text.IInformationControl;
22 import org.eclipse.jface.text.IInformationControlExtension;
23 import org.eclipse.jface.text.source.ISourceViewer;
24 import org.eclipse.jface.text.source.SourceViewer;
25 import org.eclipse.swt.SWT;
26 import org.eclipse.swt.custom.StyledText;
27 import org.eclipse.swt.events.DisposeEvent;
28 import org.eclipse.swt.events.DisposeListener;
29 import org.eclipse.swt.events.FocusListener;
30 import org.eclipse.swt.events.KeyEvent;
31 import org.eclipse.swt.events.KeyListener;
32 import org.eclipse.swt.graphics.Color;
33 import org.eclipse.swt.graphics.Font;
34 import org.eclipse.swt.graphics.FontData;
35 import org.eclipse.swt.graphics.Point;
36 import org.eclipse.swt.graphics.Rectangle;
37 import org.eclipse.swt.layout.GridData;
38 import org.eclipse.swt.layout.GridLayout;
39 import org.eclipse.swt.widgets.Composite;
40 import org.eclipse.swt.widgets.Display;
41 import org.eclipse.swt.widgets.Label;
42 import org.eclipse.swt.widgets.Shell;
43
44 /**
45  * Source viewer based implementation of <code>IInformationControl</code>.
46  * Displays information in a source viewer.
47  * 
48  * @since 3.0
49  */
50 public class SourceViewerInformationControl implements IInformationControl,
51                 IInformationControlExtension, DisposeListener {
52
53         /** Border thickness in pixels. */
54         private static final int BORDER = 1;
55
56         /** The control's shell */
57         private Shell fShell;
58
59         /** The control's text widget */
60         private StyledText fText;
61
62         /** The control's source viewer */
63         private SourceViewer fViewer;
64
65         /**
66          * The optional status field.
67          * 
68          * @since 3.0
69          */
70         private Label fStatusField;
71
72         /**
73          * The separator for the optional status field.
74          * 
75          * @since 3.0
76          */
77         private Label fSeparator;
78
79         /**
80          * The font of the optional status text label.
81          * 
82          * @since 3.0
83          */
84         private Font fStatusTextFont;
85
86         /**
87          * Creates a default information control with the given shell as parent. The
88          * given information presenter is used to process the information to be
89          * displayed. The given styles are applied to the created styled text
90          * widget.
91          * 
92          * @param parent
93          *            the parent shell
94          * @param shellStyle
95          *            the additional styles for the shell
96          * @param style
97          *            the additional styles for the styled text widget
98          */
99         public SourceViewerInformationControl(Shell parent, int shellStyle,
100                         int style) {
101                 this(parent, shellStyle, style, null);
102         }
103
104         /**
105          * Creates a default information control with the given shell as parent. The
106          * given information presenter is used to process the information to be
107          * displayed. The given styles are applied to the created styled text
108          * widget.
109          * 
110          * @param parent
111          *            the parent shell
112          * @param shellStyle
113          *            the additional styles for the shell
114          * @param style
115          *            the additional styles for the styled text widget
116          * @param statusFieldText
117          *            the text to be used in the optional status field or
118          *            <code>null</code> if the status field should be hidden
119          * @since 3.0
120          */
121         public SourceViewerInformationControl(Shell parent, int shellStyle,
122                         int style, String statusFieldText) {
123                 GridLayout layout;
124                 GridData gd;
125
126                 fShell = new Shell(parent, SWT.NO_FOCUS | SWT.ON_TOP | shellStyle);
127                 Display display = fShell.getDisplay();
128                 fShell.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
129
130                 Composite composite = fShell;
131                 layout = new GridLayout(1, false);
132                 int border = ((shellStyle & SWT.NO_TRIM) == 0) ? 0 : BORDER;
133                 layout.marginHeight = border;
134                 layout.marginWidth = border;
135                 composite.setLayout(layout);
136                 gd = new GridData(GridData.FILL_HORIZONTAL);
137                 composite.setLayoutData(gd);
138
139                 if (statusFieldText != null) {
140                         composite = new Composite(composite, SWT.NONE);
141                         layout = new GridLayout(1, false);
142                         layout.marginHeight = 0;
143                         layout.marginWidth = 0;
144                         composite.setLayout(layout);
145                         gd = new GridData(GridData.FILL_BOTH);
146                         composite.setLayoutData(gd);
147                         composite.setForeground(display
148                                         .getSystemColor(SWT.COLOR_INFO_FOREGROUND));
149                         composite.setBackground(display
150                                         .getSystemColor(SWT.COLOR_INFO_BACKGROUND));
151                 }
152
153                 // Source viewer
154                 IPreferenceStore store = WebUI.getDefault()
155                                 .getCombinedPreferenceStore();
156                 fViewer = new JavaSourceViewer(composite, null, null, false, style,
157                                 store);
158                 fViewer.configure(new PHPSourceViewerConfiguration(WebUI
159                                 .getDefault().getJavaTextTools().getColorManager(), store,
160                                 null, null));
161                 fViewer.setEditable(false);
162
163                 fText = fViewer.getTextWidget();
164                 gd = new GridData(GridData.BEGINNING | GridData.FILL_BOTH);
165                 fText.setLayoutData(gd);
166                 fText.setForeground(parent.getDisplay().getSystemColor(
167                                 SWT.COLOR_INFO_FOREGROUND));
168                 fText.setBackground(parent.getDisplay().getSystemColor(
169                                 SWT.COLOR_INFO_BACKGROUND));
170
171                 fText.addKeyListener(new KeyListener() {
172
173                         public void keyPressed(KeyEvent e) {
174                                 if (e.character == 0x1B) // ESC
175                                         fShell.dispose();
176                         }
177
178                         public void keyReleased(KeyEvent e) {
179                         }
180                 });
181
182                 // Status field
183                 if (statusFieldText != null) {
184
185                         // Horizontal separator line
186                         fSeparator = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL
187                                         | SWT.LINE_DOT);
188                         fSeparator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
189
190                         // Status field label
191                         fStatusField = new Label(composite, SWT.RIGHT);
192                         fStatusField.setText(statusFieldText);
193                         Font font = fStatusField.getFont();
194                         FontData[] fontDatas = font.getFontData();
195                         for (int i = 0; i < fontDatas.length; i++)
196                                 fontDatas[i].setHeight(fontDatas[i].getHeight() * 9 / 10);
197                         fStatusTextFont = new Font(fStatusField.getDisplay(), fontDatas);
198                         fStatusField.setFont(fStatusTextFont);
199                         GridData gd2 = new GridData(GridData.FILL_VERTICAL
200                                         | GridData.FILL_HORIZONTAL
201                                         | GridData.HORIZONTAL_ALIGN_BEGINNING
202                                         | GridData.VERTICAL_ALIGN_BEGINNING);
203                         fStatusField.setLayoutData(gd2);
204
205                         // Regarding the color see bug 41128
206                         fStatusField.setForeground(display
207                                         .getSystemColor(SWT.COLOR_WIDGET_DARK_SHADOW));
208
209                         fStatusField.setBackground(display
210                                         .getSystemColor(SWT.COLOR_INFO_BACKGROUND));
211                 }
212
213                 addDisposeListener(this);
214         }
215
216         /**
217          * Creates a default information control with the given shell as parent. The
218          * given information presenter is used to process the information to be
219          * displayed. The given styles are applied to the created styled text
220          * widget.
221          * 
222          * @param parent
223          *            the parent shell
224          * @param style
225          *            the additional styles for the styled text widget
226          */
227         public SourceViewerInformationControl(Shell parent, int style) {
228                 this(parent, SWT.NO_TRIM, style);
229         }
230
231         /**
232          * Creates a default information control with the given shell as parent. The
233          * given information presenter is used to process the information to be
234          * displayed. The given styles are applied to the created styled text
235          * widget.
236          * 
237          * @param parent
238          *            the parent shell
239          * @param style
240          *            the additional styles for the styled text widget
241          * @param statusFieldText
242          *            the text to be used in the optional status field or
243          *            <code>null</code> if the status field should be hidden
244          * @since 3.0
245          */
246         public SourceViewerInformationControl(Shell parent, int style,
247                         String statusFieldText) {
248                 this(parent, SWT.NO_TRIM, style, statusFieldText);
249         }
250
251         /**
252          * Creates a default information control with the given shell as parent. No
253          * information presenter is used to process the information to be displayed.
254          * No additional styles are applied to the styled text widget.
255          * 
256          * @param parent
257          *            the parent shell
258          */
259         public SourceViewerInformationControl(Shell parent) {
260                 this(parent, SWT.NONE);
261         }
262
263         /**
264          * Creates a default information control with the given shell as parent. No
265          * information presenter is used to process the information to be displayed.
266          * No additional styles are applied to the styled text widget.
267          * 
268          * @param parent
269          *            the parent shell
270          * @param statusFieldText
271          *            the text to be used in the optional status field or
272          *            <code>null</code> if the status field should be hidden
273          * @since 3.0
274          */
275         public SourceViewerInformationControl(Shell parent, String statusFieldText) {
276                 this(parent, SWT.NONE, statusFieldText);
277         }
278
279         /*
280          * @see org.eclipse.jface.text.IInformationControlExtension2#setInput(java.lang.Object)
281          */
282         public void setInput(Object input) {
283                 if (input instanceof String)
284                         setInformation((String) input);
285                 else
286                         setInformation(null);
287         }
288
289         /*
290          * @see IInformationControl#setInformation(String)
291          */
292         public void setInformation(String content) {
293                 if (content == null) {
294                         fViewer.setInput(null);
295                         return;
296                 }
297
298                 IDocument doc = new Document(content);
299                 WebUI.getDefault().getJavaTextTools()
300                                 .setupJavaDocumentPartitioner(doc);
301
302                 fViewer.setInput(doc);
303         }
304
305         /*
306          * @see IInformationControl#setVisible(boolean)
307          */
308         public void setVisible(boolean visible) {
309                 fShell.setVisible(visible);
310         }
311
312         /**
313          * {@inheritDoc}
314          * 
315          * @since 3.0
316          */
317         public void widgetDisposed(DisposeEvent event) {
318                 if (fStatusTextFont != null && !fStatusTextFont.isDisposed())
319                         fStatusTextFont.dispose();
320
321                 fStatusTextFont = null;
322                 fShell = null;
323                 fText = null;
324         }
325
326         /**
327          * {@inheritDoc}
328          */
329         public final void dispose() {
330                 if (fShell != null && !fShell.isDisposed())
331                         fShell.dispose();
332                 else
333                         widgetDisposed(null);
334         }
335
336         /*
337          * @see IInformationControl#setSize(int, int)
338          */
339         public void setSize(int width, int height) {
340
341                 if (fStatusField != null) {
342                         GridData gd = (GridData) fViewer.getTextWidget().getLayoutData();
343                         Point statusSize = fStatusField.computeSize(SWT.DEFAULT,
344                                         SWT.DEFAULT, true);
345                         Point separatorSize = fSeparator.computeSize(SWT.DEFAULT,
346                                         SWT.DEFAULT, true);
347                         gd.heightHint = height - statusSize.y - separatorSize.y;
348                 }
349                 fShell.setSize(width, height);
350
351                 if (fStatusField != null)
352                         fShell.pack(true);
353         }
354
355         /*
356          * @see IInformationControl#setLocation(Point)
357          */
358         public void setLocation(Point location) {
359                 Rectangle trim = fShell.computeTrim(0, 0, 0, 0);
360                 Point textLocation = fText.getLocation();
361                 location.x += trim.x - textLocation.x;
362                 location.y += trim.y - textLocation.y;
363                 fShell.setLocation(location);
364         }
365
366         /*
367          * @see IInformationControl#setSizeConstraints(int, int)
368          */
369         public void setSizeConstraints(int maxWidth, int maxHeight) {
370                 maxWidth = maxHeight;
371         }
372
373         /*
374          * @see IInformationControl#computeSizeHint()
375          */
376         public Point computeSizeHint() {
377                 return fShell.computeSize(SWT.DEFAULT, SWT.DEFAULT);
378         }
379
380         /*
381          * @see IInformationControl#addDisposeListener(DisposeListener)
382          */
383         public void addDisposeListener(DisposeListener listener) {
384                 fShell.addDisposeListener(listener);
385         }
386
387         /*
388          * @see IInformationControl#removeDisposeListener(DisposeListener)
389          */
390         public void removeDisposeListener(DisposeListener listener) {
391                 fShell.removeDisposeListener(listener);
392         }
393
394         /*
395          * @see IInformationControl#setForegroundColor(Color)
396          */
397         public void setForegroundColor(Color foreground) {
398                 fText.setForeground(foreground);
399         }
400
401         /*
402          * @see IInformationControl#setBackgroundColor(Color)
403          */
404         public void setBackgroundColor(Color background) {
405                 fText.setBackground(background);
406         }
407
408         /*
409          * @see IInformationControl#isFocusControl()
410          */
411         public boolean isFocusControl() {
412                 return fText.isFocusControl();
413         }
414
415         /*
416          * @see IInformationControl#setFocus()
417          */
418         public void setFocus() {
419                 fShell.forceFocus();
420                 fText.setFocus();
421         }
422
423         /*
424          * @see IInformationControl#addFocusListener(FocusListener)
425          */
426         public void addFocusListener(FocusListener listener) {
427                 fText.addFocusListener(listener);
428         }
429
430         /*
431          * @see IInformationControl#removeFocusListener(FocusListener)
432          */
433         public void removeFocusListener(FocusListener listener) {
434                 fText.removeFocusListener(listener);
435         }
436
437         /*
438          * @see IInformationControlExtension#hasContents()
439          */
440         public boolean hasContents() {
441                 return fText.getCharCount() > 0;
442         }
443
444         protected ISourceViewer getViewer() {
445                 return fViewer;
446         }
447 }