Applying pteague's patch (re #685)
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / ui / text / HTMLTextPresenter.java
1 package net.sourceforge.phpdt.internal.ui.text;
2
3 /*
4  * (c) Copyright IBM Corp. 2000, 2001.
5  * All Rights Reserved.
6  */
7
8 import java.io.IOException;
9 import java.io.Reader;
10 import java.io.StringReader;
11 import java.util.Iterator;
12
13 import net.sourceforge.phpdt.internal.ui.PHPUIMessages;
14 import net.sourceforge.phpeclipse.PHPeclipsePlugin;
15
16 import org.eclipse.jface.text.DefaultInformationControl;
17 import org.eclipse.jface.text.Region;
18 import org.eclipse.jface.text.TextPresentation;
19 import org.eclipse.swt.custom.StyleRange;
20 import org.eclipse.swt.graphics.GC;
21 import org.eclipse.swt.widgets.Display;
22
23 public class HTMLTextPresenter implements
24                 DefaultInformationControl.IInformationPresenter {
25
26         private static final String LINE_DELIM = System.getProperty(
27                         "line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
28
29         private int fCounter;
30
31         private boolean fEnforceUpperLineLimit;
32
33         public HTMLTextPresenter(boolean enforceUpperLineLimit) {
34                 super();
35                 fEnforceUpperLineLimit = enforceUpperLineLimit;
36         }
37
38         public HTMLTextPresenter() {
39                 this(true);
40         }
41
42         protected Reader createReader(String hoverInfo,
43                         TextPresentation presentation) {
44                 return new HTML2TextReader(new StringReader(hoverInfo), presentation);
45         }
46
47         protected void adaptTextPresentation(TextPresentation presentation,
48                         int offset, int insertLength) {
49
50                 int yoursStart = offset;
51                 int yoursEnd = offset + insertLength - 1;
52                 yoursEnd = Math.max(yoursStart, yoursEnd);
53
54                 Iterator e = presentation.getAllStyleRangeIterator();
55                 while (e.hasNext()) {
56
57                         StyleRange range = (StyleRange) e.next();
58
59                         int myStart = range.start;
60                         int myEnd = range.start + range.length - 1;
61                         myEnd = Math.max(myStart, myEnd);
62
63                         if (myEnd < yoursStart)
64                                 continue;
65
66                         if (myStart < yoursStart)
67                                 range.length += insertLength;
68                         else
69                                 range.start += insertLength;
70                 }
71         }
72
73         private void append(StringBuffer buffer, String string,
74                         TextPresentation presentation) {
75
76                 int length = string.length();
77                 buffer.append(string);
78
79                 if (presentation != null)
80                         adaptTextPresentation(presentation, fCounter, length);
81
82                 fCounter += length;
83         }
84
85         private String getIndent(String line) {
86                 int length = line.length();
87
88                 int i = 0;
89                 while (i < length && Character.isWhitespace(line.charAt(i)))
90                         ++i;
91
92                 return (i == length ? line : line.substring(0, i)) + " "; //$NON-NLS-1$
93         }
94
95         /*
96          * @see IHoverInformationPresenter#updatePresentation(Display display,
97          *      String, TextPresentation, int, int)
98          */
99         public String updatePresentation(Display display, String hoverInfo,
100                         TextPresentation presentation, int maxWidth, int maxHeight) {
101
102                 if (hoverInfo == null)
103                         return null;
104
105                 GC gc = new GC(display);
106                 try {
107
108                         StringBuffer buffer = new StringBuffer();
109                         int maxNumberOfLines = Math.round(maxHeight
110                                         / gc.getFontMetrics().getHeight());
111
112                         fCounter = 0;
113                         LineBreakingReader reader = new LineBreakingReader(createReader(
114                                         hoverInfo, presentation), gc, maxWidth);
115
116                         boolean lastLineFormatted = false;
117                         String lastLineIndent = null;
118
119                         String line = reader.readLine();
120                         boolean lineFormatted = reader.isFormattedLine();
121                         boolean firstLineProcessed = false;
122
123                         while (line != null) {
124
125                                 if (fEnforceUpperLineLimit && maxNumberOfLines <= 0)
126                                         break;
127
128                                 if (firstLineProcessed) {
129                                         if (!lastLineFormatted)
130                                                 append(buffer, LINE_DELIM, null);
131                                         else {
132                                                 append(buffer, LINE_DELIM, presentation);
133                                                 if (lastLineIndent != null)
134                                                         append(buffer, lastLineIndent, presentation);
135                                         }
136                                 }
137
138                                 append(buffer, line, null);
139                                 firstLineProcessed = true;
140
141                                 lastLineFormatted = lineFormatted;
142                                 if (!lineFormatted)
143                                         lastLineIndent = null;
144                                 else if (lastLineIndent == null)
145                                         lastLineIndent = getIndent(line);
146
147                                 line = reader.readLine();
148                                 lineFormatted = reader.isFormattedLine();
149
150                                 maxNumberOfLines--;
151                         }
152
153                         if (line != null) {
154                                 append(buffer, LINE_DELIM, lineFormatted ? presentation : null);
155                                 append(buffer, PHPUIMessages
156                                                 .getString("HTMLTextPresenter.ellipsis"), presentation); //$NON-NLS-1$
157                         }
158
159                         return trim(buffer, presentation);
160
161                 } catch (IOException e) {
162
163                         PHPeclipsePlugin.log(e);
164                         return null;
165
166                 } finally {
167                         gc.dispose();
168                 }
169         }
170
171         private String trim(StringBuffer buffer, TextPresentation presentation) {
172
173                 int length = buffer.length();
174
175                 int end = length - 1;
176                 while (end >= 0 && Character.isWhitespace(buffer.charAt(end)))
177                         --end;
178
179                 if (end == -1)
180                         return ""; //$NON-NLS-1$
181
182                 if (end < length - 1)
183                         buffer.delete(end + 1, length);
184                 else
185                         end = length;
186
187                 int start = 0;
188                 while (start < end && Character.isWhitespace(buffer.charAt(start)))
189                         ++start;
190
191                 buffer.delete(0, start);
192                 presentation.setResultWindow(new Region(start, buffer.length()));
193                 return buffer.toString();
194         }
195 }