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