Lines 1-564
Link Here
|
1 |
/******************************************************************************* |
1 |
/******************************************************************************* |
2 |
* Copyright (c) 2006 IBM Corporation and others. |
2 |
* Copyright (c) 2006 IBM Corporation and others. |
3 |
* All rights reserved. This program and the accompanying materials |
3 |
* All rights reserved. This program and the accompanying materials |
4 |
* are made available under the terms of the Eclipse Public License v1.0 |
4 |
* are made available under the terms of the Eclipse Public License v1.0 |
5 |
* which accompanies this distribution, and is available at |
5 |
* which accompanies this distribution, and is available at |
6 |
* http://www.eclipse.org/legal/epl-v10.html |
6 |
* http://www.eclipse.org/legal/epl-v10.html |
7 |
* |
7 |
* |
8 |
* Contributors: |
8 |
* Contributors: |
9 |
* IBM Corporation - initial API and implementation |
9 |
* IBM Corporation - initial API and implementation |
10 |
*******************************************************************************/ |
10 |
*******************************************************************************/ |
11 |
|
11 |
|
12 |
package org.eclipse.pde.internal.ui.editor.contentassist.display; |
12 |
package org.eclipse.pde.internal.ui.editor.contentassist.display; |
13 |
|
13 |
|
14 |
import java.io.IOException; |
14 |
import java.io.IOException; |
15 |
import java.io.StringReader; |
15 |
import java.io.StringReader; |
16 |
import java.util.Iterator; |
16 |
import java.util.Iterator; |
17 |
import org.eclipse.core.runtime.ListenerList; |
17 |
import org.eclipse.core.runtime.ListenerList; |
18 |
import org.eclipse.jface.text.*; |
18 |
import org.eclipse.jface.text.*; |
19 |
import org.eclipse.pde.internal.ui.PDEPlugin; |
19 |
import org.eclipse.pde.internal.ui.PDEPlugin; |
20 |
import org.eclipse.pde.internal.ui.editor.text.HTMLPrinter; |
20 |
import org.eclipse.pde.internal.ui.editor.text.HTMLPrinter; |
21 |
import org.eclipse.swt.SWT; |
21 |
import org.eclipse.swt.SWT; |
22 |
import org.eclipse.swt.SWTError; |
22 |
import org.eclipse.swt.SWTError; |
23 |
import org.eclipse.swt.browser.*; |
23 |
import org.eclipse.swt.browser.*; |
24 |
import org.eclipse.swt.custom.StyleRange; |
24 |
import org.eclipse.swt.custom.StyleRange; |
25 |
import org.eclipse.swt.events.*; |
25 |
import org.eclipse.swt.events.*; |
26 |
import org.eclipse.swt.graphics.*; |
26 |
import org.eclipse.swt.graphics.*; |
27 |
import org.eclipse.swt.layout.GridData; |
27 |
import org.eclipse.swt.layout.GridData; |
28 |
import org.eclipse.swt.layout.GridLayout; |
28 |
import org.eclipse.swt.layout.GridLayout; |
29 |
import org.eclipse.swt.widgets.*; |
29 |
import org.eclipse.swt.widgets.*; |
30 |
|
30 |
|
31 |
/** |
31 |
/** |
32 |
* Displays textual information in a {@link org.eclipse.swt.browser.Browser} |
32 |
* Displays textual information in a {@link org.eclipse.swt.browser.Browser} |
33 |
* widget. |
33 |
* widget. |
34 |
* |
34 |
* |
35 |
* <p> |
35 |
* <p> |
36 |
* This class may be instantiated; it is not intended to be subclassed. |
36 |
* This class may be instantiated; it is not intended to be subclassed. |
37 |
* </p> |
37 |
* </p> |
38 |
* <p> |
38 |
* <p> |
39 |
* Current problems: |
39 |
* Current problems: |
40 |
* - the size computation is too small |
40 |
* - the size computation is too small |
41 |
* - focusLost event is not sent (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=84532) |
41 |
* - focusLost event is not sent (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=84532) |
42 |
* </p> |
42 |
* </p> |
43 |
* |
43 |
* |
44 |
* @since 3.1 |
44 |
* @since 3.1 |
45 |
*/ |
45 |
*/ |
46 |
public class BrowserInformationControl implements IInformationControl, IInformationControlExtension, IInformationControlExtension3, DisposeListener { |
46 |
public class BrowserInformationControl implements IInformationControl, IInformationControlExtension, IInformationControlExtension3, DisposeListener { |
47 |
|
47 |
|
48 |
/** |
48 |
/** |
49 |
* Tells whether the SWT Browser widget and hence this information |
49 |
* Tells whether the SWT Browser widget and hence this information |
50 |
* control is available. |
50 |
* control is available. |
51 |
* |
51 |
* |
52 |
* @param parent the parent component used for checking or <code>null</code> if none |
52 |
* @param parent the parent component used for checking or <code>null</code> if none |
53 |
* @return <code>true</code> if this control is available |
53 |
* @return <code>true</code> if this control is available |
54 |
*/ |
54 |
*/ |
55 |
public static boolean isAvailable(Composite parent) { |
55 |
public static boolean isAvailable(Composite parent) { |
56 |
if (!fgAvailabilityChecked) { |
56 |
if (!fgAvailabilityChecked) { |
57 |
try { |
57 |
try { |
58 |
if (parent == null) |
58 |
if (parent == null) |
59 |
parent = PDEPlugin.getActiveWorkbenchShell(); |
59 |
parent = PDEPlugin.getActiveWorkbenchShell(); |
60 |
if (parent == null) |
60 |
if (parent == null) |
61 |
return false; // don't store this value - try again later |
61 |
return false; // don't store this value - try again later |
62 |
|
62 |
|
63 |
Browser browser = new Browser(parent, SWT.NONE); |
63 |
Browser browser = new Browser(parent, SWT.NONE); |
64 |
browser.dispose(); |
64 |
browser.dispose(); |
65 |
fgIsAvailable = true; |
65 |
fgIsAvailable = true; |
66 |
} catch (SWTError er) { |
66 |
} catch (SWTError er) { |
67 |
fgIsAvailable = false; |
67 |
fgIsAvailable = false; |
68 |
} finally { |
68 |
} finally { |
69 |
fgAvailabilityChecked = true; |
69 |
fgAvailabilityChecked = true; |
70 |
} |
70 |
} |
71 |
} |
71 |
} |
72 |
|
72 |
|
73 |
return fgIsAvailable; |
73 |
return fgIsAvailable; |
74 |
} |
74 |
} |
75 |
|
75 |
|
76 |
/** Border thickness in pixels. */ |
76 |
/** Border thickness in pixels. */ |
77 |
private static final int BORDER = 1; |
77 |
private static final int BORDER = 1; |
78 |
|
78 |
|
79 |
/** |
79 |
/** |
80 |
* Minimal size constraints. |
80 |
* Minimal size constraints. |
81 |
* @since 3.2 |
81 |
* @since 3.2 |
82 |
*/ |
82 |
*/ |
83 |
private static final int MIN_WIDTH = 80; |
83 |
private static final int MIN_WIDTH = 80; |
84 |
private static final int MIN_HEIGHT = 80; |
84 |
private static final int MIN_HEIGHT = 80; |
85 |
|
85 |
|
86 |
/** |
86 |
/** |
87 |
* Availability checking cache. |
87 |
* Availability checking cache. |
88 |
*/ |
88 |
*/ |
89 |
private static boolean fgIsAvailable = false; |
89 |
private static boolean fgIsAvailable = false; |
90 |
private static boolean fgAvailabilityChecked = false; |
90 |
private static boolean fgAvailabilityChecked = false; |
91 |
|
91 |
|
92 |
/** The control's shell */ |
92 |
/** The control's shell */ |
93 |
private Shell fShell; |
93 |
private Shell fShell; |
94 |
/** The control's browser widget */ |
94 |
/** The control's browser widget */ |
95 |
private Browser fBrowser; |
95 |
private Browser fBrowser; |
96 |
/** Tells whether the browser has content */ |
96 |
/** Tells whether the browser has content */ |
97 |
private boolean fBrowserHasContent; |
97 |
private boolean fBrowserHasContent; |
98 |
/** The control width constraint */ |
98 |
/** The control width constraint */ |
99 |
private int fMaxWidth = -1; |
99 |
private int fMaxWidth = -1; |
100 |
/** The control height constraint */ |
100 |
/** The control height constraint */ |
101 |
private int fMaxHeight = -1; |
101 |
private int fMaxHeight = -1; |
102 |
private Font fStatusTextFont; |
102 |
private Font fStatusTextFont; |
103 |
private Label fStatusTextField; |
103 |
private Label fStatusTextField; |
104 |
private String fStatusFieldText; |
104 |
private String fStatusFieldText; |
105 |
private boolean fHideScrollBars; |
105 |
private boolean fHideScrollBars; |
106 |
private Listener fDeactivateListener; |
106 |
private Listener fDeactivateListener; |
107 |
private ListenerList fFocusListeners = new ListenerList(); |
107 |
private ListenerList fFocusListeners = new ListenerList(); |
108 |
private Label fSeparator; |
108 |
private Label fSeparator; |
109 |
private String fInputText; |
109 |
private String fInputText; |
110 |
private TextLayout fTextLayout; |
110 |
private TextLayout fTextLayout; |
111 |
|
111 |
|
112 |
private TextStyle fBoldStyle; |
112 |
private TextStyle fBoldStyle; |
113 |
|
113 |
|
114 |
/** |
114 |
/** |
115 |
* Creates a default information control with the given shell as parent. The given |
115 |
* Creates a default information control with the given shell as parent. The given |
116 |
* information presenter is used to process the information to be displayed. The given |
116 |
* information presenter is used to process the information to be displayed. The given |
117 |
* styles are applied to the created styled text widget. |
117 |
* styles are applied to the created styled text widget. |
118 |
* |
118 |
* |
119 |
* @param parent the parent shell |
119 |
* @param parent the parent shell |
120 |
* @param shellStyle the additional styles for the shell |
120 |
* @param shellStyle the additional styles for the shell |
121 |
* @param style the additional styles for the styled text widget |
121 |
* @param style the additional styles for the styled text widget |
122 |
*/ |
122 |
*/ |
123 |
public BrowserInformationControl(Shell parent, int shellStyle, int style) { |
123 |
public BrowserInformationControl(Shell parent, int shellStyle, int style) { |
124 |
this(parent, shellStyle, style, null); |
124 |
this(parent, shellStyle, style, null); |
125 |
} |
125 |
} |
126 |
|
126 |
|
127 |
/** |
127 |
/** |
128 |
* Creates a default information control with the given shell as parent. The given |
128 |
* Creates a default information control with the given shell as parent. The given |
129 |
* information presenter is used to process the information to be displayed. The given |
129 |
* information presenter is used to process the information to be displayed. The given |
130 |
* styles are applied to the created styled text widget. |
130 |
* styles are applied to the created styled text widget. |
131 |
* |
131 |
* |
132 |
* @param parent the parent shell |
132 |
* @param parent the parent shell |
133 |
* @param shellStyle the additional styles for the shell |
133 |
* @param shellStyle the additional styles for the shell |
134 |
* @param style the additional styles for the styled text widget |
134 |
* @param style the additional styles for the styled text widget |
135 |
* @param statusFieldText the text to be used in the optional status field |
135 |
* @param statusFieldText the text to be used in the optional status field |
136 |
* or <code>null</code> if the status field should be hidden |
136 |
* or <code>null</code> if the status field should be hidden |
137 |
*/ |
137 |
*/ |
138 |
public BrowserInformationControl(Shell parent, int shellStyle, int style, String statusFieldText) { |
138 |
public BrowserInformationControl(Shell parent, int shellStyle, int style, String statusFieldText) { |
139 |
fStatusFieldText = statusFieldText; |
139 |
fStatusFieldText = statusFieldText; |
140 |
|
140 |
|
141 |
fShell = new Shell(parent, SWT.NO_FOCUS | SWT.ON_TOP | shellStyle); |
141 |
fShell = new Shell(parent, SWT.NO_FOCUS | SWT.ON_TOP | shellStyle); |
142 |
Display display = fShell.getDisplay(); |
142 |
Display display = fShell.getDisplay(); |
143 |
fShell.setBackground(display.getSystemColor(SWT.COLOR_BLACK)); |
143 |
fShell.setBackground(display.getSystemColor(SWT.COLOR_BLACK)); |
144 |
fTextLayout = new TextLayout(display); |
144 |
fTextLayout = new TextLayout(display); |
145 |
|
145 |
|
146 |
Composite composite = fShell; |
146 |
Composite composite = fShell; |
147 |
GridLayout layout = new GridLayout(1, false); |
147 |
GridLayout layout = new GridLayout(1, false); |
148 |
int border = ((shellStyle & SWT.NO_TRIM) == 0) ? 0 : BORDER; |
148 |
int border = ((shellStyle & SWT.NO_TRIM) == 0) ? 0 : BORDER; |
149 |
layout.marginHeight = border; |
149 |
layout.marginHeight = border; |
150 |
layout.marginWidth = border; |
150 |
layout.marginWidth = border; |
151 |
composite.setLayout(layout); |
151 |
composite.setLayout(layout); |
152 |
|
152 |
|
153 |
if (statusFieldText != null) { |
153 |
if (statusFieldText != null) { |
154 |
composite = new Composite(composite, SWT.NONE); |
154 |
composite = new Composite(composite, SWT.NONE); |
155 |
layout = new GridLayout(1, false); |
155 |
layout = new GridLayout(1, false); |
156 |
layout.marginHeight = 0; |
156 |
layout.marginHeight = 0; |
157 |
layout.marginWidth = 0; |
157 |
layout.marginWidth = 0; |
158 |
layout.verticalSpacing = 1; |
158 |
layout.verticalSpacing = 1; |
159 |
layout.horizontalSpacing = 1; |
159 |
layout.horizontalSpacing = 1; |
160 |
composite.setLayout(layout); |
160 |
composite.setLayout(layout); |
161 |
|
161 |
|
162 |
GridData gd = new GridData(GridData.FILL_BOTH); |
162 |
GridData gd = new GridData(GridData.FILL_BOTH); |
163 |
composite.setLayoutData(gd); |
163 |
composite.setLayoutData(gd); |
164 |
|
164 |
|
165 |
composite.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND)); |
165 |
composite.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND)); |
166 |
composite.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); |
166 |
composite.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); |
167 |
} |
167 |
} |
168 |
|
168 |
|
169 |
// Browser field |
169 |
// Browser field |
170 |
fBrowser = new Browser(composite, SWT.NONE); |
170 |
fBrowser = new Browser(composite, SWT.NONE); |
171 |
|
171 |
|
172 |
// Disable javascript for security reasons, see bug 265808 |
172 |
// Disable javascript for security reasons, see bug 265808 |
173 |
fBrowser.setJavascriptEnabled(false); |
173 |
fBrowser.setJavascriptEnabled(false); |
174 |
|
174 |
|
175 |
fHideScrollBars = (style & SWT.V_SCROLL) == 0 && (style & SWT.H_SCROLL) == 0; |
175 |
fHideScrollBars = (style & SWT.V_SCROLL) == 0 && (style & SWT.H_SCROLL) == 0; |
176 |
|
176 |
|
177 |
GridData gd = new GridData(GridData.BEGINNING | GridData.FILL_BOTH); |
177 |
GridData gd = new GridData(GridData.BEGINNING | GridData.FILL_BOTH); |
178 |
fBrowser.setLayoutData(gd); |
178 |
fBrowser.setLayoutData(gd); |
179 |
|
179 |
|
180 |
fBrowser.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND)); |
180 |
fBrowser.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND)); |
181 |
fBrowser.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); |
181 |
fBrowser.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); |
182 |
fBrowser.addKeyListener(new KeyListener() { |
182 |
fBrowser.addKeyListener(new KeyListener() { |
183 |
|
183 |
|
184 |
public void keyPressed(KeyEvent e) { |
184 |
public void keyPressed(KeyEvent e) { |
185 |
if (e.character == 0x1B) // ESC |
185 |
if (e.character == 0x1B) // ESC |
186 |
fShell.dispose(); |
186 |
fShell.dispose(); |
187 |
} |
187 |
} |
188 |
|
188 |
|
189 |
public void keyReleased(KeyEvent e) { |
189 |
public void keyReleased(KeyEvent e) { |
190 |
} |
190 |
} |
191 |
}); |
191 |
}); |
192 |
/* |
192 |
/* |
193 |
* XXX revisit when the Browser support is better |
193 |
* XXX revisit when the Browser support is better |
194 |
* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=107629. Choosing a link to a |
194 |
* See https://bugs.eclipse.org/bugs/show_bug.cgi?id=107629. Choosing a link to a |
195 |
* non-available target will show an error dialog behind the ON_TOP shell that seemingly |
195 |
* non-available target will show an error dialog behind the ON_TOP shell that seemingly |
196 |
* blocks the workbench. Disable links completely for now. |
196 |
* blocks the workbench. Disable links completely for now. |
197 |
*/ |
197 |
*/ |
198 |
fBrowser.addLocationListener(new LocationAdapter() { |
198 |
fBrowser.addLocationListener(new LocationAdapter() { |
199 |
/* |
199 |
/* |
200 |
* @see org.eclipse.swt.browser.LocationAdapter#changing(org.eclipse.swt.browser.LocationEvent) |
200 |
* @see org.eclipse.swt.browser.LocationAdapter#changing(org.eclipse.swt.browser.LocationEvent) |
201 |
*/ |
201 |
*/ |
202 |
public void changing(LocationEvent event) { |
202 |
public void changing(LocationEvent event) { |
203 |
String location = event.location; |
203 |
String location = event.location; |
204 |
if (!"about:blank".equals(location)) //$NON-NLS-1$ |
204 |
if (!"about:blank".equals(location)) //$NON-NLS-1$ |
205 |
event.doit = false; |
205 |
event.doit = false; |
206 |
} |
206 |
} |
207 |
}); |
207 |
}); |
208 |
|
208 |
|
209 |
// Replace browser's built-in context menu with none |
209 |
// Replace browser's built-in context menu with none |
210 |
fBrowser.setMenu(new Menu(fShell, SWT.NONE)); |
210 |
fBrowser.setMenu(new Menu(fShell, SWT.NONE)); |
211 |
|
211 |
|
212 |
// Status field |
212 |
// Status field |
213 |
if (statusFieldText != null) { |
213 |
if (statusFieldText != null) { |
214 |
|
214 |
|
215 |
fSeparator = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL | SWT.LINE_DOT); |
215 |
fSeparator = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL | SWT.LINE_DOT); |
216 |
fSeparator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
216 |
fSeparator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); |
217 |
|
217 |
|
218 |
// Status field label |
218 |
// Status field label |
219 |
fStatusTextField = new Label(composite, SWT.RIGHT); |
219 |
fStatusTextField = new Label(composite, SWT.RIGHT); |
220 |
fStatusTextField.setText(statusFieldText); |
220 |
fStatusTextField.setText(statusFieldText); |
221 |
Font font = fStatusTextField.getFont(); |
221 |
Font font = fStatusTextField.getFont(); |
222 |
FontData[] fontDatas = font.getFontData(); |
222 |
FontData[] fontDatas = font.getFontData(); |
223 |
for (int i = 0; i < fontDatas.length; i++) |
223 |
for (int i = 0; i < fontDatas.length; i++) |
224 |
fontDatas[i].setHeight(fontDatas[i].getHeight() * 9 / 10); |
224 |
fontDatas[i].setHeight(fontDatas[i].getHeight() * 9 / 10); |
225 |
fStatusTextFont = new Font(fStatusTextField.getDisplay(), fontDatas); |
225 |
fStatusTextFont = new Font(fStatusTextField.getDisplay(), fontDatas); |
226 |
fStatusTextField.setFont(fStatusTextFont); |
226 |
fStatusTextField.setFont(fStatusTextFont); |
227 |
gd = new GridData(GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.VERTICAL_ALIGN_BEGINNING); |
227 |
gd = new GridData(GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.VERTICAL_ALIGN_BEGINNING); |
228 |
fStatusTextField.setLayoutData(gd); |
228 |
fStatusTextField.setLayoutData(gd); |
229 |
|
229 |
|
230 |
fStatusTextField.setForeground(display.getSystemColor(SWT.COLOR_WIDGET_DARK_SHADOW)); |
230 |
fStatusTextField.setForeground(display.getSystemColor(SWT.COLOR_WIDGET_DARK_SHADOW)); |
231 |
|
231 |
|
232 |
fStatusTextField.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); |
232 |
fStatusTextField.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND)); |
233 |
} |
233 |
} |
234 |
|
234 |
|
235 |
addDisposeListener(this); |
235 |
addDisposeListener(this); |
236 |
createTextLayout(); |
236 |
createTextLayout(); |
237 |
} |
237 |
} |
238 |
|
238 |
|
239 |
/** |
239 |
/** |
240 |
* Creates a default information control with the given shell as parent. The given |
240 |
* Creates a default information control with the given shell as parent. The given |
241 |
* information presenter is used to process the information to be displayed. The given |
241 |
* information presenter is used to process the information to be displayed. The given |
242 |
* styles are applied to the created styled text widget. |
242 |
* styles are applied to the created styled text widget. |
243 |
* |
243 |
* |
244 |
* @param parent the parent shell |
244 |
* @param parent the parent shell |
245 |
* @param style the additional styles for the browser widget |
245 |
* @param style the additional styles for the browser widget |
246 |
*/ |
246 |
*/ |
247 |
public BrowserInformationControl(Shell parent, int style) { |
247 |
public BrowserInformationControl(Shell parent, int style) { |
248 |
this(parent, SWT.TOOL | SWT.NO_TRIM, style); |
248 |
this(parent, SWT.TOOL | SWT.NO_TRIM, style); |
249 |
} |
249 |
} |
250 |
|
250 |
|
251 |
/** |
251 |
/** |
252 |
* Creates a default information control with the given shell as parent. |
252 |
* Creates a default information control with the given shell as parent. |
253 |
* No information presenter is used to process the information |
253 |
* No information presenter is used to process the information |
254 |
* to be displayed. No additional styles are applied to the styled text widget. |
254 |
* to be displayed. No additional styles are applied to the styled text widget. |
255 |
* |
255 |
* |
256 |
* @param parent the parent shell |
256 |
* @param parent the parent shell |
257 |
*/ |
257 |
*/ |
258 |
public BrowserInformationControl(Shell parent) { |
258 |
public BrowserInformationControl(Shell parent) { |
259 |
this(parent, SWT.NONE); |
259 |
this(parent, SWT.NONE); |
260 |
} |
260 |
} |
261 |
|
261 |
|
262 |
/* |
262 |
/* |
263 |
* @see IInformationControl#setInformation(String) |
263 |
* @see IInformationControl#setInformation(String) |
264 |
*/ |
264 |
*/ |
265 |
public void setInformation(String content) { |
265 |
public void setInformation(String content) { |
266 |
fBrowserHasContent = content != null && content.length() > 0; |
266 |
fBrowserHasContent = content != null && content.length() > 0; |
267 |
|
267 |
|
268 |
if (!fBrowserHasContent) |
268 |
if (!fBrowserHasContent) |
269 |
content = "<html><body ></html>"; //$NON-NLS-1$ |
269 |
content = "<html><body ></html>"; //$NON-NLS-1$ |
270 |
|
270 |
|
271 |
fInputText = content; |
271 |
fInputText = content; |
272 |
|
272 |
|
273 |
int shellStyle = fShell.getStyle(); |
273 |
int shellStyle = fShell.getStyle(); |
274 |
boolean RTL = (shellStyle & SWT.RIGHT_TO_LEFT) != 0; |
274 |
boolean RTL = (shellStyle & SWT.RIGHT_TO_LEFT) != 0; |
275 |
|
275 |
|
276 |
String[] styles = null; |
276 |
String[] styles = null; |
277 |
if (RTL && !fHideScrollBars) |
277 |
if (RTL && !fHideScrollBars) |
278 |
styles = new String[] {"direction:rtl;", "word-wrap:break-word;"}; //$NON-NLS-1$ //$NON-NLS-2$ |
278 |
styles = new String[] {"direction:rtl;", "word-wrap:break-word;"}; //$NON-NLS-1$ //$NON-NLS-2$ |
279 |
else if (RTL && fHideScrollBars) |
279 |
else if (RTL && fHideScrollBars) |
280 |
styles = new String[] {"direction:rtl;", "overflow:hidden;", "word-wrap:break-word;"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
280 |
styles = new String[] {"direction:rtl;", "overflow:hidden;", "word-wrap:break-word;"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ |
281 |
else if (fHideScrollBars && true) |
281 |
else if (fHideScrollBars && true) |
282 |
styles = new String[] {"overflow:hidden;", "word-wrap: break-word;"}; //$NON-NLS-1$ //$NON-NLS-2$ |
282 |
styles = new String[] {"overflow:hidden;", "word-wrap: break-word;"}; //$NON-NLS-1$ //$NON-NLS-2$ |
283 |
|
283 |
|
284 |
if (styles != null) { |
284 |
if (styles != null) { |
285 |
StringBuffer buffer = new StringBuffer(content); |
285 |
StringBuffer buffer = new StringBuffer(content); |
286 |
HTMLPrinter.insertStyles(buffer, styles); |
286 |
HTMLPrinter.insertStyles(buffer, styles); |
287 |
content = buffer.toString(); |
287 |
content = buffer.toString(); |
288 |
} |
288 |
} |
289 |
|
289 |
|
290 |
fBrowser.setText(content); |
290 |
fBrowser.setText(content); |
291 |
|
291 |
|
292 |
} |
292 |
} |
293 |
|
293 |
|
294 |
/* |
294 |
/* |
295 |
* @see org.eclipse.jdt.internal.ui.text.IInformationControlExtension4#setStatusText(java.lang.String) |
295 |
* @see org.eclipse.jdt.internal.ui.text.IInformationControlExtension4#setStatusText(java.lang.String) |
296 |
* @since 3.2 |
296 |
* @since 3.2 |
297 |
*/ |
297 |
*/ |
298 |
public void setStatusText(String statusFieldText) { |
298 |
public void setStatusText(String statusFieldText) { |
299 |
fStatusFieldText = statusFieldText; |
299 |
fStatusFieldText = statusFieldText; |
300 |
} |
300 |
} |
301 |
|
301 |
|
302 |
/* |
302 |
/* |
303 |
* @see IInformationControl#setVisible(boolean) |
303 |
* @see IInformationControl#setVisible(boolean) |
304 |
*/ |
304 |
*/ |
305 |
public void setVisible(boolean visible) { |
305 |
public void setVisible(boolean visible) { |
306 |
if (fShell.isVisible() == visible) |
306 |
if (fShell.isVisible() == visible) |
307 |
return; |
307 |
return; |
308 |
|
308 |
|
309 |
if (visible) { |
309 |
if (visible) { |
310 |
if (fStatusTextField != null) { |
310 |
if (fStatusTextField != null) { |
311 |
boolean state = fStatusFieldText != null; |
311 |
boolean state = fStatusFieldText != null; |
312 |
if (state) |
312 |
if (state) |
313 |
fStatusTextField.setText(fStatusFieldText); |
313 |
fStatusTextField.setText(fStatusFieldText); |
314 |
fStatusTextField.setVisible(state); |
314 |
fStatusTextField.setVisible(state); |
315 |
fSeparator.setVisible(state); |
315 |
fSeparator.setVisible(state); |
316 |
} |
316 |
} |
317 |
} |
317 |
} |
318 |
|
318 |
|
319 |
fShell.setVisible(visible); |
319 |
fShell.setVisible(visible); |
320 |
if (!visible) |
320 |
if (!visible) |
321 |
setInformation(""); //$NON-NLS-1$ |
321 |
setInformation(""); //$NON-NLS-1$ |
322 |
} |
322 |
} |
323 |
|
323 |
|
324 |
/** |
324 |
/** |
325 |
* Creates and initializes the text layout used |
325 |
* Creates and initializes the text layout used |
326 |
* to compute the size hint. |
326 |
* to compute the size hint. |
327 |
* |
327 |
* |
328 |
* @since 3.2 |
328 |
* @since 3.2 |
329 |
*/ |
329 |
*/ |
330 |
private void createTextLayout() { |
330 |
private void createTextLayout() { |
331 |
fTextLayout = new TextLayout(fBrowser.getDisplay()); |
331 |
fTextLayout = new TextLayout(fBrowser.getDisplay()); |
332 |
|
332 |
|
333 |
// Initialize fonts |
333 |
// Initialize fonts |
334 |
Font font = fBrowser.getFont(); |
334 |
Font font = fBrowser.getFont(); |
335 |
fTextLayout.setFont(font); |
335 |
fTextLayout.setFont(font); |
336 |
fTextLayout.setWidth(-1); |
336 |
fTextLayout.setWidth(-1); |
337 |
FontData[] fontData = font.getFontData(); |
337 |
FontData[] fontData = font.getFontData(); |
338 |
for (int i = 0; i < fontData.length; i++) |
338 |
for (int i = 0; i < fontData.length; i++) |
339 |
fontData[i].setStyle(SWT.BOLD); |
339 |
fontData[i].setStyle(SWT.BOLD); |
340 |
font = new Font(fShell.getDisplay(), fontData); |
340 |
font = new Font(fShell.getDisplay(), fontData); |
341 |
fBoldStyle = new TextStyle(font, null, null); |
341 |
fBoldStyle = new TextStyle(font, null, null); |
342 |
|
342 |
|
343 |
// Compute and set tab width |
343 |
// Compute and set tab width |
344 |
fTextLayout.setText(" "); //$NON-NLS-1$ |
344 |
fTextLayout.setText(" "); //$NON-NLS-1$ |
345 |
int tabWidth = fTextLayout.getBounds().width; |
345 |
int tabWidth = fTextLayout.getBounds().width; |
346 |
fTextLayout.setTabs(new int[] {tabWidth}); |
346 |
fTextLayout.setTabs(new int[] {tabWidth}); |
347 |
|
347 |
|
348 |
fTextLayout.setText(""); //$NON-NLS-1$ |
348 |
fTextLayout.setText(""); //$NON-NLS-1$ |
349 |
} |
349 |
} |
350 |
|
350 |
|
351 |
/* |
351 |
/* |
352 |
* @see IInformationControl#dispose() |
352 |
* @see IInformationControl#dispose() |
353 |
*/ |
353 |
*/ |
354 |
public void dispose() { |
354 |
public void dispose() { |
355 |
fTextLayout.dispose(); |
355 |
fTextLayout.dispose(); |
356 |
fTextLayout = null; |
356 |
fTextLayout = null; |
357 |
fBoldStyle.font.dispose(); |
357 |
fBoldStyle.font.dispose(); |
358 |
fBoldStyle = null; |
358 |
fBoldStyle = null; |
359 |
if (fShell != null && !fShell.isDisposed()) |
359 |
if (fShell != null && !fShell.isDisposed()) |
360 |
fShell.dispose(); |
360 |
fShell.dispose(); |
361 |
else |
361 |
else |
362 |
widgetDisposed(null); |
362 |
widgetDisposed(null); |
363 |
} |
363 |
} |
364 |
|
364 |
|
365 |
/* |
365 |
/* |
366 |
* @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent) |
366 |
* @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent) |
367 |
*/ |
367 |
*/ |
368 |
public void widgetDisposed(DisposeEvent event) { |
368 |
public void widgetDisposed(DisposeEvent event) { |
369 |
if (fStatusTextFont != null && !fStatusTextFont.isDisposed()) |
369 |
if (fStatusTextFont != null && !fStatusTextFont.isDisposed()) |
370 |
fStatusTextFont.dispose(); |
370 |
fStatusTextFont.dispose(); |
371 |
|
371 |
|
372 |
fShell = null; |
372 |
fShell = null; |
373 |
fBrowser = null; |
373 |
fBrowser = null; |
374 |
fStatusTextFont = null; |
374 |
fStatusTextFont = null; |
375 |
} |
375 |
} |
376 |
|
376 |
|
377 |
/* |
377 |
/* |
378 |
* @see IInformationControl#setSize(int, int) |
378 |
* @see IInformationControl#setSize(int, int) |
379 |
*/ |
379 |
*/ |
380 |
public void setSize(int width, int height) { |
380 |
public void setSize(int width, int height) { |
381 |
fShell.setSize(Math.min(width, fMaxWidth), Math.min(height, fMaxHeight)); |
381 |
fShell.setSize(Math.min(width, fMaxWidth), Math.min(height, fMaxHeight)); |
382 |
} |
382 |
} |
383 |
|
383 |
|
384 |
/* |
384 |
/* |
385 |
* @see IInformationControl#setLocation(Point) |
385 |
* @see IInformationControl#setLocation(Point) |
386 |
*/ |
386 |
*/ |
387 |
public void setLocation(Point location) { |
387 |
public void setLocation(Point location) { |
388 |
fShell.setLocation(location); |
388 |
fShell.setLocation(location); |
389 |
} |
389 |
} |
390 |
|
390 |
|
391 |
/* |
391 |
/* |
392 |
* @see IInformationControl#setSizeConstraints(int, int) |
392 |
* @see IInformationControl#setSizeConstraints(int, int) |
393 |
*/ |
393 |
*/ |
394 |
public void setSizeConstraints(int maxWidth, int maxHeight) { |
394 |
public void setSizeConstraints(int maxWidth, int maxHeight) { |
395 |
fMaxWidth = maxWidth; |
395 |
fMaxWidth = maxWidth; |
396 |
fMaxHeight = maxHeight; |
396 |
fMaxHeight = maxHeight; |
397 |
} |
397 |
} |
398 |
|
398 |
|
399 |
/* |
399 |
/* |
400 |
* @see IInformationControl#computeSizeHint() |
400 |
* @see IInformationControl#computeSizeHint() |
401 |
*/ |
401 |
*/ |
402 |
public Point computeSizeHint() { |
402 |
public Point computeSizeHint() { |
403 |
TextPresentation presentation = new TextPresentation(); |
403 |
TextPresentation presentation = new TextPresentation(); |
404 |
HTML2TextReader reader = new HTML2TextReader(new StringReader(fInputText), presentation); |
404 |
HTML2TextReader reader = new HTML2TextReader(new StringReader(fInputText), presentation); |
405 |
String text; |
405 |
String text; |
406 |
try { |
406 |
try { |
407 |
text = reader.getString(); |
407 |
text = reader.getString(); |
408 |
} catch (IOException e) { |
408 |
} catch (IOException e) { |
409 |
text = ""; //$NON-NLS-1$ |
409 |
text = ""; //$NON-NLS-1$ |
410 |
} |
410 |
} |
411 |
|
411 |
|
412 |
fTextLayout.setText(text); |
412 |
fTextLayout.setText(text); |
413 |
Iterator iter = presentation.getAllStyleRangeIterator(); |
413 |
Iterator iter = presentation.getAllStyleRangeIterator(); |
414 |
while (iter.hasNext()) { |
414 |
while (iter.hasNext()) { |
415 |
StyleRange sr = (StyleRange) iter.next(); |
415 |
StyleRange sr = (StyleRange) iter.next(); |
416 |
if (sr.fontStyle == SWT.BOLD) |
416 |
if (sr.fontStyle == SWT.BOLD) |
417 |
fTextLayout.setStyle(fBoldStyle, sr.start, sr.start + sr.length - 1); |
417 |
fTextLayout.setStyle(fBoldStyle, sr.start, sr.start + sr.length - 1); |
418 |
} |
418 |
} |
419 |
Rectangle bounds = fTextLayout.getBounds(); |
419 |
Rectangle bounds = fTextLayout.getBounds(); |
420 |
int width = bounds.width; |
420 |
int width = bounds.width; |
421 |
int height = bounds.height; |
421 |
int height = bounds.height; |
422 |
|
422 |
|
423 |
width += 15; |
423 |
width += 15; |
424 |
height += 25; |
424 |
height += 25; |
425 |
|
425 |
|
426 |
if (fStatusFieldText != null && fSeparator != null) { |
426 |
if (fStatusFieldText != null && fSeparator != null) { |
427 |
fTextLayout.setText(fStatusFieldText); |
427 |
fTextLayout.setText(fStatusFieldText); |
428 |
Rectangle statusBounds = fTextLayout.getBounds(); |
428 |
Rectangle statusBounds = fTextLayout.getBounds(); |
429 |
Rectangle separatorBounds = fSeparator.getBounds(); |
429 |
Rectangle separatorBounds = fSeparator.getBounds(); |
430 |
width = Math.max(width, statusBounds.width); |
430 |
width = Math.max(width, statusBounds.width); |
431 |
height = height + statusBounds.height + separatorBounds.height; |
431 |
height = height + statusBounds.height + separatorBounds.height; |
432 |
} |
432 |
} |
433 |
|
433 |
|
434 |
// Apply size constraints |
434 |
// Apply size constraints |
435 |
if (fMaxWidth != SWT.DEFAULT) |
435 |
if (fMaxWidth != SWT.DEFAULT) |
436 |
width = Math.min(fMaxWidth, width); |
436 |
width = Math.min(fMaxWidth, width); |
437 |
if (fMaxHeight != SWT.DEFAULT) |
437 |
if (fMaxHeight != SWT.DEFAULT) |
438 |
height = Math.min(fMaxHeight, height); |
438 |
height = Math.min(fMaxHeight, height); |
439 |
|
439 |
|
440 |
// Ensure minimal size |
440 |
// Ensure minimal size |
441 |
width = Math.max(MIN_WIDTH, width); |
441 |
width = Math.max(MIN_WIDTH, width); |
442 |
height = Math.max(MIN_HEIGHT, height); |
442 |
height = Math.max(MIN_HEIGHT, height); |
443 |
|
443 |
|
444 |
return new Point(width, height); |
444 |
return new Point(width, height); |
445 |
} |
445 |
} |
446 |
|
446 |
|
447 |
/* |
447 |
/* |
448 |
* @see org.eclipse.jface.text.IInformationControlExtension3#computeTrim() |
448 |
* @see org.eclipse.jface.text.IInformationControlExtension3#computeTrim() |
449 |
*/ |
449 |
*/ |
450 |
public Rectangle computeTrim() { |
450 |
public Rectangle computeTrim() { |
451 |
return fShell.computeTrim(0, 0, 0, 0); |
451 |
return fShell.computeTrim(0, 0, 0, 0); |
452 |
} |
452 |
} |
453 |
|
453 |
|
454 |
/* |
454 |
/* |
455 |
* @see org.eclipse.jface.text.IInformationControlExtension3#getBounds() |
455 |
* @see org.eclipse.jface.text.IInformationControlExtension3#getBounds() |
456 |
*/ |
456 |
*/ |
457 |
public Rectangle getBounds() { |
457 |
public Rectangle getBounds() { |
458 |
return fShell.getBounds(); |
458 |
return fShell.getBounds(); |
459 |
} |
459 |
} |
460 |
|
460 |
|
461 |
/* |
461 |
/* |
462 |
* @see org.eclipse.jface.text.IInformationControlExtension3#restoresLocation() |
462 |
* @see org.eclipse.jface.text.IInformationControlExtension3#restoresLocation() |
463 |
*/ |
463 |
*/ |
464 |
public boolean restoresLocation() { |
464 |
public boolean restoresLocation() { |
465 |
return false; |
465 |
return false; |
466 |
} |
466 |
} |
467 |
|
467 |
|
468 |
/* |
468 |
/* |
469 |
* @see org.eclipse.jface.text.IInformationControlExtension3#restoresSize() |
469 |
* @see org.eclipse.jface.text.IInformationControlExtension3#restoresSize() |
470 |
*/ |
470 |
*/ |
471 |
public boolean restoresSize() { |
471 |
public boolean restoresSize() { |
472 |
return false; |
472 |
return false; |
473 |
} |
473 |
} |
474 |
|
474 |
|
475 |
/* |
475 |
/* |
476 |
* @see IInformationControl#addDisposeListener(DisposeListener) |
476 |
* @see IInformationControl#addDisposeListener(DisposeListener) |
477 |
*/ |
477 |
*/ |
478 |
public void addDisposeListener(DisposeListener listener) { |
478 |
public void addDisposeListener(DisposeListener listener) { |
479 |
fShell.addDisposeListener(listener); |
479 |
fShell.addDisposeListener(listener); |
480 |
} |
480 |
} |
481 |
|
481 |
|
482 |
/* |
482 |
/* |
483 |
* @see IInformationControl#removeDisposeListener(DisposeListener) |
483 |
* @see IInformationControl#removeDisposeListener(DisposeListener) |
484 |
*/ |
484 |
*/ |
485 |
public void removeDisposeListener(DisposeListener listener) { |
485 |
public void removeDisposeListener(DisposeListener listener) { |
486 |
fShell.removeDisposeListener(listener); |
486 |
fShell.removeDisposeListener(listener); |
487 |
} |
487 |
} |
488 |
|
488 |
|
489 |
/* |
489 |
/* |
490 |
* @see IInformationControl#setForegroundColor(Color) |
490 |
* @see IInformationControl#setForegroundColor(Color) |
491 |
*/ |
491 |
*/ |
492 |
public void setForegroundColor(Color foreground) { |
492 |
public void setForegroundColor(Color foreground) { |
493 |
fBrowser.setForeground(foreground); |
493 |
fBrowser.setForeground(foreground); |
494 |
} |
494 |
} |
495 |
|
495 |
|
496 |
/* |
496 |
/* |
497 |
* @see IInformationControl#setBackgroundColor(Color) |
497 |
* @see IInformationControl#setBackgroundColor(Color) |
498 |
*/ |
498 |
*/ |
499 |
public void setBackgroundColor(Color background) { |
499 |
public void setBackgroundColor(Color background) { |
500 |
fBrowser.setBackground(background); |
500 |
fBrowser.setBackground(background); |
501 |
} |
501 |
} |
502 |
|
502 |
|
503 |
/* |
503 |
/* |
504 |
* @see IInformationControl#isFocusControl() |
504 |
* @see IInformationControl#isFocusControl() |
505 |
*/ |
505 |
*/ |
506 |
public boolean isFocusControl() { |
506 |
public boolean isFocusControl() { |
507 |
return fBrowser.isFocusControl(); |
507 |
return fBrowser.isFocusControl(); |
508 |
} |
508 |
} |
509 |
|
509 |
|
510 |
/* |
510 |
/* |
511 |
* @see IInformationControl#setFocus() |
511 |
* @see IInformationControl#setFocus() |
512 |
*/ |
512 |
*/ |
513 |
public void setFocus() { |
513 |
public void setFocus() { |
514 |
fShell.forceFocus(); |
514 |
fShell.forceFocus(); |
515 |
fBrowser.setFocus(); |
515 |
fBrowser.setFocus(); |
516 |
} |
516 |
} |
517 |
|
517 |
|
518 |
/* |
518 |
/* |
519 |
* @see IInformationControl#addFocusListener(FocusListener) |
519 |
* @see IInformationControl#addFocusListener(FocusListener) |
520 |
*/ |
520 |
*/ |
521 |
public void addFocusListener(final FocusListener listener) { |
521 |
public void addFocusListener(final FocusListener listener) { |
522 |
fBrowser.addFocusListener(listener); |
522 |
fBrowser.addFocusListener(listener); |
523 |
|
523 |
|
524 |
/* |
524 |
/* |
525 |
* FIXME: This is a workaround for bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=84532 |
525 |
* FIXME: This is a workaround for bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=84532 |
526 |
* (Browser widget does not send focusLost event) |
526 |
* (Browser widget does not send focusLost event) |
527 |
*/ |
527 |
*/ |
528 |
if (fFocusListeners.isEmpty()) { |
528 |
if (fFocusListeners.isEmpty()) { |
529 |
fDeactivateListener = new Listener() { |
529 |
fDeactivateListener = new Listener() { |
530 |
public void handleEvent(Event event) { |
530 |
public void handleEvent(Event event) { |
531 |
Object[] listeners = fFocusListeners.getListeners(); |
531 |
Object[] listeners = fFocusListeners.getListeners(); |
532 |
for (int i = 0; i < listeners.length; i++) |
532 |
for (int i = 0; i < listeners.length; i++) |
533 |
((FocusListener) listeners[i]).focusLost(new FocusEvent(event)); |
533 |
((FocusListener) listeners[i]).focusLost(new FocusEvent(event)); |
534 |
} |
534 |
} |
535 |
}; |
535 |
}; |
536 |
fBrowser.getShell().addListener(SWT.Deactivate, fDeactivateListener); |
536 |
fBrowser.getShell().addListener(SWT.Deactivate, fDeactivateListener); |
537 |
} |
537 |
} |
538 |
fFocusListeners.add(listener); |
538 |
fFocusListeners.add(listener); |
539 |
} |
539 |
} |
540 |
|
540 |
|
541 |
/* |
541 |
/* |
542 |
* @see IInformationControl#removeFocusListener(FocusListener) |
542 |
* @see IInformationControl#removeFocusListener(FocusListener) |
543 |
*/ |
543 |
*/ |
544 |
public void removeFocusListener(FocusListener listener) { |
544 |
public void removeFocusListener(FocusListener listener) { |
545 |
fBrowser.removeFocusListener(listener); |
545 |
fBrowser.removeFocusListener(listener); |
546 |
|
546 |
|
547 |
/* |
547 |
/* |
548 |
* FIXME: This is a workaround for bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=84532 |
548 |
* FIXME: This is a workaround for bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=84532 |
549 |
* (Browser widget does not send focusLost event) |
549 |
* (Browser widget does not send focusLost event) |
550 |
*/ |
550 |
*/ |
551 |
fFocusListeners.remove(listener); |
551 |
fFocusListeners.remove(listener); |
552 |
if (fFocusListeners.isEmpty()) { |
552 |
if (fFocusListeners.isEmpty()) { |
553 |
fBrowser.getShell().removeListener(SWT.Deactivate, fDeactivateListener); |
553 |
fBrowser.getShell().removeListener(SWT.Deactivate, fDeactivateListener); |
554 |
fDeactivateListener = null; |
554 |
fDeactivateListener = null; |
555 |
} |
555 |
} |
556 |
} |
556 |
} |
557 |
|
557 |
|
558 |
/* |
558 |
/* |
559 |
* @see IInformationControlExtension#hasContents() |
559 |
* @see IInformationControlExtension#hasContents() |
560 |
*/ |
560 |
*/ |
561 |
public boolean hasContents() { |
561 |
public boolean hasContents() { |
562 |
return fBrowserHasContent; |
562 |
return fBrowserHasContent; |
563 |
} |
563 |
} |
564 |
} |
564 |
} |