3f3c40a19be87c748f68fe358a1f1e4c80e3e88f
[phpeclipse.git] / net.sourceforge.phpeclipse.ui / src / net / sourceforge / phpdt / internal / ui / text / CustomSourceInformationControl.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;
12
13 import net.sourceforge.phpdt.internal.ui.text.java.hover.SourceViewerInformationControl;
14
15 import org.eclipse.jface.resource.JFaceResources;
16 import org.eclipse.jface.text.Assert;
17 import org.eclipse.jface.text.BadLocationException;
18 import org.eclipse.jface.text.IDocument;
19 import org.eclipse.jface.text.IRegion;
20 import org.eclipse.jface.text.ITextViewerExtension;
21 import org.eclipse.swt.custom.StyledText;
22 import org.eclipse.swt.graphics.Font;
23 import org.eclipse.swt.graphics.GC;
24 import org.eclipse.swt.graphics.Point;
25 import org.eclipse.swt.widgets.Composite;
26 import org.eclipse.swt.widgets.Control;
27 import org.eclipse.swt.widgets.Shell;
28
29 /**
30  * Source viewer used to display quick diff hovers.
31  * 
32  * @since 3.0
33  */
34 public class CustomSourceInformationControl extends
35                 SourceViewerInformationControl {
36
37         /** The font name for the viewer font - the same as the java editor's. */
38         private static final String SYMBOLIC_FONT_NAME = "net.sourceforge.phpdt.ui.editors.textfont"; //$NON-NLS-1$
39
40         /**
41          * The maximum width of the control, set in
42          * <code>setSizeConstraints(int, int)</code>.
43          */
44         int fMaxWidth = Integer.MAX_VALUE;
45
46         /**
47          * The maximum height of the control, set in
48          * <code>setSizeConstraints(int, int)</code>.
49          */
50         int fMaxHeight = Integer.MAX_VALUE;
51
52         /**
53          * The partition type to be used as the starting partition type by the
54          * paritition scanner.
55          */
56         private String fPartition;
57
58         /** The horizontal scroll index. */
59         private int fHorizontalScrollPixel;
60
61         /*
62          * @see org.eclipse.jface.text.IInformationControl#setSizeConstraints(int,
63          *      int)
64          */
65         public void setSizeConstraints(int maxWidth, int maxHeight) {
66                 fMaxWidth = maxWidth;
67                 fMaxHeight = maxHeight;
68         }
69
70         /**
71          * Creates a new information control.
72          * 
73          * @param parent
74          *            the shell that is the parent of this hover / control
75          * @param partition
76          *            the initial partition type to be used for the underlying
77          *            viewer
78          */
79         public CustomSourceInformationControl(Shell parent, String partition) {
80                 super(parent);
81                 setViewerFont();
82                 setStartingPartitionType(partition);
83         }
84
85         /*
86          * @see org.eclipse.jface.text.IInformationControl#computeSizeHint()
87          */
88         public Point computeSizeHint() {
89                 Point size = super.computeSizeHint();
90                 size.x = Math.min(size.x, fMaxWidth);
91                 size.y = Math.min(size.y, fMaxHeight);
92                 return size;
93         }
94
95         /**
96          * Sets the font for this viewer sustaining selection and scroll position.
97          */
98         private void setViewerFont() {
99                 Font font = JFaceResources.getFont(SYMBOLIC_FONT_NAME);
100
101                 if (getViewer().getDocument() != null) {
102
103                         Point selection = getViewer().getSelectedRange();
104                         int topIndex = getViewer().getTopIndex();
105
106                         StyledText styledText = getViewer().getTextWidget();
107                         Control parent = styledText;
108                         if (getViewer() instanceof ITextViewerExtension) {
109                                 ITextViewerExtension extension = (ITextViewerExtension) getViewer();
110                                 parent = extension.getControl();
111                         }
112
113                         parent.setRedraw(false);
114
115                         styledText.setFont(font);
116
117                         getViewer().setSelectedRange(selection.x, selection.y);
118                         getViewer().setTopIndex(topIndex);
119
120                         if (parent instanceof Composite) {
121                                 Composite composite = (Composite) parent;
122                                 composite.layout(true);
123                         }
124
125                         parent.setRedraw(true);
126
127                 } else {
128                         StyledText styledText = getViewer().getTextWidget();
129                         styledText.setFont(font);
130                 }
131         }
132
133         /**
134          * Sets the initial partition for the underlying source viewer.
135          * 
136          * @param partition
137          *            the partition type
138          */
139         public void setStartingPartitionType(String partition) {
140                 if (partition == null)
141                         fPartition = IDocument.DEFAULT_CONTENT_TYPE;
142                 else
143                         fPartition = partition;
144         }
145
146         /*
147          * @see org.eclipse.jface.text.IInformationControl#setInformation(java.lang.String)
148          */
149         public void setInformation(String content) {
150                 super.setInformation(content);
151                 IDocument doc = getViewer().getDocument();
152                 if (doc == null)
153                         return;
154
155                 // ensure that we can scroll enough
156                 ensureScrollable();
157
158                 String start = null;
159                 if (IPHPPartitions.PHP_PHPDOC_COMMENT.equals(fPartition)) {
160                         start = "/**" + doc.getLegalLineDelimiters()[0]; //$NON-NLS-1$
161                 } else if (IPHPPartitions.PHP_MULTILINE_COMMENT.equals(fPartition)) {
162                         start = "/*" + doc.getLegalLineDelimiters()[0]; //$NON-NLS-1$
163                 }
164                 if (start != null) {
165                         try {
166                                 doc.replace(0, 0, start);
167                                 int startLen = start.length();
168                                 getViewer().setDocument(doc, startLen,
169                                                 doc.getLength() - startLen);
170                         } catch (BadLocationException e) {
171                                 // impossible
172                                 Assert.isTrue(false);
173                         }
174                 }
175
176                 getViewer().getTextWidget().setHorizontalPixel(fHorizontalScrollPixel);
177         }
178
179         /**
180          * Ensures that the control can be scrolled at least to
181          * <code>fHorizontalScrollPixel</code> and adjusts <code>fMaxWidth</code>
182          * accordingly.
183          */
184         private void ensureScrollable() {
185                 IDocument doc = getViewer().getDocument();
186                 if (doc == null)
187                         return;
188
189                 StyledText widget = getViewer().getTextWidget();
190                 if (widget == null || widget.isDisposed())
191                         return;
192
193                 int last = doc.getNumberOfLines() - 1;
194                 GC gc = new GC(widget);
195                 gc.setFont(widget.getFont());
196                 int maxWidth = 0;
197                 String content = new String();
198
199                 try {
200                         for (int i = 0; i <= last; i++) {
201                                 IRegion line;
202                                 line = doc.getLineInformation(i);
203                                 content = doc.get(line.getOffset(), line.getLength());
204                                 int width = gc.textExtent(content).x;
205                                 if (width > maxWidth) {
206                                         maxWidth = width;
207                                 }
208                         }
209                 } catch (BadLocationException e) {
210                         return;
211                 } finally {
212                         gc.dispose();
213                 }
214
215                 // limit the size of the window to the maximum width minus scrolling,
216                 // but never more than the configured max size (viewport size).
217                 fMaxWidth = Math.max(0, Math.min(fMaxWidth, maxWidth
218                                 - fHorizontalScrollPixel + 8));
219         }
220
221         /*
222          * @see net.sourceforge.phpdt.internal.ui.text.java.hover.SourceViewerInformationControl#hasContents()
223          */
224         public boolean hasContents() {
225                 return super.hasContents() && fMaxWidth > 0;
226         }
227
228         /**
229          * Sets the horizontal scroll index in pixels.
230          * 
231          * @param scrollIndex
232          *            the new horizontal scroll index
233          */
234         public void setHorizontalScrollPixel(int scrollIndex) {
235                 scrollIndex = Math.max(0, scrollIndex);
236                 fHorizontalScrollPixel = scrollIndex;
237         }
238 }