Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.
View | Details | Raw Unified | Return to bug 158331
Collapse All | Expand All

(-)src/org/eclipse/pde/internal/ui/editor/contentassist/TypeCompletionProposal.java (-6 / +5 lines)
Lines 13-22 Link Here
13
13
14
import org.eclipse.core.runtime.Assert;
14
import org.eclipse.core.runtime.Assert;
15
import org.eclipse.core.runtime.IProgressMonitor;
15
import org.eclipse.core.runtime.IProgressMonitor;
16
import org.eclipse.jface.internal.text.html.BrowserInformationControl;
17
import org.eclipse.jface.resource.JFaceResources;
16
import org.eclipse.jface.text.*;
18
import org.eclipse.jface.text.*;
17
import org.eclipse.jface.text.contentassist.*;
19
import org.eclipse.jface.text.contentassist.*;
18
import org.eclipse.pde.internal.ui.editor.contentassist.display.BrowserInformationControl;
19
import org.eclipse.swt.SWT;
20
import org.eclipse.swt.graphics.Image;
20
import org.eclipse.swt.graphics.Image;
21
import org.eclipse.swt.graphics.Point;
21
import org.eclipse.swt.graphics.Point;
22
import org.eclipse.swt.widgets.Shell;
22
import org.eclipse.swt.widgets.Shell;
Lines 112-120 Link Here
112
	}
112
	}
113
113
114
	public IInformationControlCreator getInformationControlCreator() {
114
	public IInformationControlCreator getInformationControlCreator() {
115
		if (!BrowserInformationControl.isAvailable(null))
116
			return null;
117
118
		if (fCreator == null) {
115
		if (fCreator == null) {
119
			fCreator = new AbstractReusableInformationControlCreator() {
116
			fCreator = new AbstractReusableInformationControlCreator() {
120
117
Lines 122-128 Link Here
122
				 * @see org.eclipse.jdt.internal.ui.text.java.hover.AbstractReusableInformationControlCreator#doCreateInformationControl(org.eclipse.swt.widgets.Shell)
119
				 * @see org.eclipse.jdt.internal.ui.text.java.hover.AbstractReusableInformationControlCreator#doCreateInformationControl(org.eclipse.swt.widgets.Shell)
123
				 */
120
				 */
124
				public IInformationControl doCreateInformationControl(Shell parent) {
121
				public IInformationControl doCreateInformationControl(Shell parent) {
125
					return new BrowserInformationControl(parent, SWT.NO_TRIM | SWT.TOOL, SWT.NONE, null);
122
					if (BrowserInformationControl.isAvailable(parent))
123
						return new BrowserInformationControl(parent, JFaceResources.DIALOG_FONT, false);
124
					return new DefaultInformationControl(parent, false);
126
				}
125
				}
127
			};
126
			};
128
		}
127
		}
(-)src/org/eclipse/pde/internal/ui/editor/contentassist/XMLCompletionProposal.java (-7 / +6 lines)
Lines 16-21 Link Here
16
import java.util.Stack;
16
import java.util.Stack;
17
import org.eclipse.core.runtime.CoreException;
17
import org.eclipse.core.runtime.CoreException;
18
import org.eclipse.core.runtime.IProgressMonitor;
18
import org.eclipse.core.runtime.IProgressMonitor;
19
import org.eclipse.jface.internal.text.html.BrowserInformationControl;
20
import org.eclipse.jface.internal.text.html.HTMLPrinter;
21
import org.eclipse.jface.resource.JFaceResources;
19
import org.eclipse.jface.text.*;
22
import org.eclipse.jface.text.*;
20
import org.eclipse.jface.text.contentassist.*;
23
import org.eclipse.jface.text.contentassist.*;
21
import org.eclipse.pde.core.IBaseModel;
24
import org.eclipse.pde.core.IBaseModel;
Lines 26-36 Link Here
26
import org.eclipse.pde.internal.ui.PDEPlugin;
29
import org.eclipse.pde.internal.ui.PDEPlugin;
27
import org.eclipse.pde.internal.ui.PDEUIMessages;
30
import org.eclipse.pde.internal.ui.PDEUIMessages;
28
import org.eclipse.pde.internal.ui.editor.PDESourcePage;
31
import org.eclipse.pde.internal.ui.editor.PDESourcePage;
29
import org.eclipse.pde.internal.ui.editor.contentassist.display.BrowserInformationControl;
30
import org.eclipse.pde.internal.ui.editor.text.HTMLPrinter;
31
import org.eclipse.pde.internal.ui.editor.text.XMLUtil;
32
import org.eclipse.pde.internal.ui.editor.text.XMLUtil;
32
import org.eclipse.pde.internal.ui.util.TextUtil;
33
import org.eclipse.pde.internal.ui.util.TextUtil;
33
import org.eclipse.swt.SWT;
34
import org.eclipse.swt.graphics.Image;
34
import org.eclipse.swt.graphics.Image;
35
import org.eclipse.swt.graphics.Point;
35
import org.eclipse.swt.graphics.Point;
36
import org.eclipse.swt.widgets.Shell;
36
import org.eclipse.swt.widgets.Shell;
Lines 518-530 Link Here
518
	}
518
	}
519
519
520
	public IInformationControlCreator getInformationControlCreator() {
520
	public IInformationControlCreator getInformationControlCreator() {
521
		if (!BrowserInformationControl.isAvailable(null))
522
			return null;
523
524
		if (fCreator == null) {
521
		if (fCreator == null) {
525
			fCreator = new AbstractReusableInformationControlCreator() {
522
			fCreator = new AbstractReusableInformationControlCreator() {
526
				public IInformationControl doCreateInformationControl(Shell parent) {
523
				public IInformationControl doCreateInformationControl(Shell parent) {
527
					return new BrowserInformationControl(parent, SWT.NO_TRIM | SWT.TOOL, SWT.NONE);
524
					if (BrowserInformationControl.isAvailable(parent))
525
						return new BrowserInformationControl(parent, JFaceResources.DIALOG_FONT, false);
526
					return new DefaultInformationControl(parent, false);
528
				}
527
				}
529
			};
528
			};
530
		}
529
		}
(-)src/org/eclipse/pde/internal/ui/editor/contentassist/display/BrowserInformationControl.java (-560 lines)
Removed Link Here
1
/*******************************************************************************
2
 *  Copyright (c) 2006, 2010 IBM Corporation and others.
3
 *  All rights reserved. This program and the accompanying materials
4
 *  are made available under the terms of the Eclipse Public License v1.0
5
 *  which accompanies this distribution, and is available at
6
 *  http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 *  Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.pde.internal.ui.editor.contentassist.display;
12
13
import java.io.IOException;
14
import java.io.StringReader;
15
import java.util.Iterator;
16
import org.eclipse.core.runtime.ListenerList;
17
import org.eclipse.jface.text.*;
18
import org.eclipse.pde.internal.ui.PDEPlugin;
19
import org.eclipse.pde.internal.ui.editor.text.HTMLPrinter;
20
import org.eclipse.swt.SWT;
21
import org.eclipse.swt.SWTError;
22
import org.eclipse.swt.browser.*;
23
import org.eclipse.swt.custom.StyleRange;
24
import org.eclipse.swt.events.*;
25
import org.eclipse.swt.graphics.*;
26
import org.eclipse.swt.layout.GridData;
27
import org.eclipse.swt.layout.GridLayout;
28
import org.eclipse.swt.widgets.*;
29
30
/**
31
 * Displays textual information in a {@link org.eclipse.swt.browser.Browser}
32
 * widget.
33
 *
34
 * <p>
35
 * This class may be instantiated; it is not intended to be subclassed.
36
 * </p>
37
 * <p>
38
 * Current problems:
39
 * - the size computation is too small
40
 * - focusLost event is not sent (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=84532)
41
 * </p>
42
 *
43
 * @since 3.1
44
 */
45
public class BrowserInformationControl implements IInformationControl, IInformationControlExtension, IInformationControlExtension3, DisposeListener {
46
47
	/**
48
	 * Tells whether the SWT Browser widget and hence this information
49
	 * control is available.
50
	 *
51
	 * @param parent the parent component used for checking or <code>null</code> if none
52
	 * @return <code>true</code> if this control is available
53
	 */
54
	public static boolean isAvailable(Composite parent) {
55
		if (!fgAvailabilityChecked) {
56
			try {
57
				if (parent == null)
58
					parent = PDEPlugin.getActiveWorkbenchShell();
59
				if (parent == null)
60
					return false; // don't store this value - try again later
61
62
				Browser browser = new Browser(parent, SWT.NONE);
63
				browser.dispose();
64
				fgIsAvailable = true;
65
			} catch (SWTError er) {
66
				fgIsAvailable = false;
67
			} finally {
68
				fgAvailabilityChecked = true;
69
			}
70
		}
71
72
		return fgIsAvailable;
73
	}
74
75
	/** Border thickness in pixels. */
76
	private static final int BORDER = 1;
77
78
	/**
79
	 * Minimal size constraints.
80
	 * @since 3.2
81
	 */
82
	private static final int MIN_WIDTH = 80;
83
	private static final int MIN_HEIGHT = 80;
84
85
	/**
86
	 * Availability checking cache.
87
	 */
88
	private static boolean fgIsAvailable = false;
89
	private static boolean fgAvailabilityChecked = false;
90
91
	/** The control's shell */
92
	private Shell fShell;
93
	/** The control's browser widget */
94
	private Browser fBrowser;
95
	/** Tells whether the browser has content */
96
	private boolean fBrowserHasContent;
97
	/** The control width constraint */
98
	private int fMaxWidth = -1;
99
	/** The control height constraint */
100
	private int fMaxHeight = -1;
101
	private Font fStatusTextFont;
102
	private Label fStatusTextField;
103
	private String fStatusFieldText;
104
	private boolean fHideScrollBars;
105
	private Listener fDeactivateListener;
106
	private ListenerList fFocusListeners = new ListenerList();
107
	private Label fSeparator;
108
	private String fInputText;
109
	private TextLayout fTextLayout;
110
111
	private TextStyle fBoldStyle;
112
113
	/**
114
	 * Creates a default information control with the given shell as parent. The given
115
	 * information presenter is used to process the information to be displayed. The given
116
	 * styles are applied to the created styled text widget.
117
	 *
118
	 * @param parent the parent shell
119
	 * @param shellStyle the additional styles for the shell
120
	 * @param style the additional styles for the styled text widget
121
	 */
122
	public BrowserInformationControl(Shell parent, int shellStyle, int style) {
123
		this(parent, shellStyle, style, null);
124
	}
125
126
	/**
127
	 * Creates a default information control with the given shell as parent. The given
128
	 * information presenter is used to process the information to be displayed. The given
129
	 * styles are applied to the created styled text widget.
130
	 *
131
	 * @param parent the parent shell
132
	 * @param shellStyle the additional styles for the shell
133
	 * @param style the additional styles for the styled text widget
134
	 * @param statusFieldText the text to be used in the optional status field
135
	 *                         or <code>null</code> if the status field should be hidden
136
	 */
137
	public BrowserInformationControl(Shell parent, int shellStyle, int style, String statusFieldText) {
138
		fStatusFieldText = statusFieldText;
139
140
		fShell = new Shell(parent, SWT.NO_FOCUS | SWT.ON_TOP | shellStyle);
141
		Display display = fShell.getDisplay();
142
		fShell.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
143
144
		Composite composite = fShell;
145
		GridLayout layout = new GridLayout(1, false);
146
		int border = ((shellStyle & SWT.NO_TRIM) == 0) ? 0 : BORDER;
147
		layout.marginHeight = border;
148
		layout.marginWidth = border;
149
		composite.setLayout(layout);
150
151
		if (statusFieldText != null) {
152
			composite = new Composite(composite, SWT.NONE);
153
			layout = new GridLayout(1, false);
154
			layout.marginHeight = 0;
155
			layout.marginWidth = 0;
156
			layout.verticalSpacing = 1;
157
			layout.horizontalSpacing = 1;
158
			composite.setLayout(layout);
159
160
			GridData gd = new GridData(GridData.FILL_BOTH);
161
			composite.setLayoutData(gd);
162
163
			composite.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
164
			composite.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
165
		}
166
167
		// Browser field
168
		fBrowser = new Browser(composite, SWT.NONE);
169
170
		// Disable javascript for security reasons, see bug 265808
171
		fBrowser.setJavascriptEnabled(false);
172
173
		fHideScrollBars = (style & SWT.V_SCROLL) == 0 && (style & SWT.H_SCROLL) == 0;
174
175
		GridData gd = new GridData(GridData.BEGINNING | GridData.FILL_BOTH);
176
		fBrowser.setLayoutData(gd);
177
178
		fBrowser.setForeground(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
179
		fBrowser.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
180
181
		/*
182
		 * XXX revisit when the Browser support is better 
183
		 * See https://bugs.eclipse.org/bugs/show_bug.cgi?id=107629. Choosing a link to a
184
		 * non-available target will show an error dialog behind the ON_TOP shell that seemingly
185
		 * blocks the workbench. Disable links completely for now.
186
		 */
187
		fBrowser.addLocationListener(new LocationAdapter() {
188
			/*
189
			 * @see org.eclipse.swt.browser.LocationAdapter#changing(org.eclipse.swt.browser.LocationEvent)
190
			 */
191
			public void changing(LocationEvent event) {
192
				String location = event.location;
193
				if (!"about:blank".equals(location)) //$NON-NLS-1$
194
					event.doit = false;
195
			}
196
		});
197
198
		// Replace browser's built-in context menu with none
199
		fBrowser.setMenu(new Menu(fShell, SWT.NONE));
200
201
		// Status field
202
		if (statusFieldText != null) {
203
204
			fSeparator = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL | SWT.LINE_DOT);
205
			fSeparator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
206
207
			// Status field label
208
			fStatusTextField = new Label(composite, SWT.RIGHT);
209
			fStatusTextField.setText(statusFieldText);
210
			Font font = fStatusTextField.getFont();
211
			FontData[] fontDatas = font.getFontData();
212
			for (int i = 0; i < fontDatas.length; i++)
213
				fontDatas[i].setHeight(fontDatas[i].getHeight() * 9 / 10);
214
			fStatusTextFont = new Font(fStatusTextField.getDisplay(), fontDatas);
215
			fStatusTextField.setFont(fStatusTextFont);
216
			gd = new GridData(GridData.FILL_HORIZONTAL | GridData.HORIZONTAL_ALIGN_BEGINNING | GridData.VERTICAL_ALIGN_BEGINNING);
217
			fStatusTextField.setLayoutData(gd);
218
219
			fStatusTextField.setForeground(display.getSystemColor(SWT.COLOR_WIDGET_DARK_SHADOW));
220
221
			fStatusTextField.setBackground(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
222
		}
223
224
		addDisposeListener(this);
225
		createTextLayout();
226
	}
227
228
	/**
229
	 * Creates a default information control with the given shell as parent. The given
230
	 * information presenter is used to process the information to be displayed. The given
231
	 * styles are applied to the created styled text widget.
232
	 *
233
	 * @param parent the parent shell
234
	 * @param style the additional styles for the browser widget
235
	 */
236
	public BrowserInformationControl(Shell parent, int style) {
237
		this(parent, SWT.TOOL | SWT.NO_TRIM, style);
238
	}
239
240
	/**
241
	 * Creates a default information control with the given shell as parent.
242
	 * No information presenter is used to process the information
243
	 * to be displayed. No additional styles are applied to the styled text widget.
244
	 *
245
	 * @param parent the parent shell
246
	 */
247
	public BrowserInformationControl(Shell parent) {
248
		this(parent, SWT.NONE);
249
	}
250
251
	/*
252
	 * @see IInformationControl#setInformation(String)
253
	 */
254
	public void setInformation(String content) {
255
		fBrowserHasContent = content != null && content.length() > 0;
256
257
		if (!fBrowserHasContent)
258
			content = "<html><body ></html>"; //$NON-NLS-1$
259
260
		fInputText = content;
261
262
		int shellStyle = fShell.getStyle();
263
		boolean RTL = (shellStyle & SWT.RIGHT_TO_LEFT) != 0;
264
265
		String[] styles = null;
266
		if (RTL && !fHideScrollBars)
267
			styles = new String[] {"direction:rtl;", "word-wrap:break-word;"}; //$NON-NLS-1$ //$NON-NLS-2$
268
		else if (RTL && fHideScrollBars)
269
			styles = new String[] {"direction:rtl;", "overflow:hidden;", "word-wrap:break-word;"}; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
270
		else if (fHideScrollBars && true)
271
			styles = new String[] {"overflow:hidden;", "word-wrap: break-word;"}; //$NON-NLS-1$ //$NON-NLS-2$
272
273
		if (styles != null) {
274
			StringBuffer buffer = new StringBuffer(content);
275
			HTMLPrinter.insertStyles(buffer, styles);
276
			content = buffer.toString();
277
		}
278
279
		fBrowser.setText(content);
280
281
	}
282
283
	/*
284
	 * @see org.eclipse.jdt.internal.ui.text.IInformationControlExtension4#setStatusText(java.lang.String)
285
	 * @since 3.2
286
	 */
287
	public void setStatusText(String statusFieldText) {
288
		fStatusFieldText = statusFieldText;
289
	}
290
291
	/*
292
	 * @see IInformationControl#setVisible(boolean)
293
	 */
294
	public void setVisible(boolean visible) {
295
		if (fShell.isVisible() == visible)
296
			return;
297
298
		if (visible) {
299
			if (fStatusTextField != null) {
300
				boolean state = fStatusFieldText != null;
301
				if (state)
302
					fStatusTextField.setText(fStatusFieldText);
303
				fStatusTextField.setVisible(state);
304
				fSeparator.setVisible(state);
305
			}
306
		}
307
308
		fShell.setVisible(visible);
309
		if (!visible)
310
			setInformation(""); //$NON-NLS-1$
311
	}
312
313
	/**
314
	 * Creates and initializes the text layout used
315
	 * to compute the size hint.
316
	 * 
317
	 * @since 3.2
318
	 */
319
	private void createTextLayout() {
320
		fTextLayout = new TextLayout(fBrowser.getDisplay());
321
322
		// Initialize fonts
323
		Font font = fBrowser.getFont();
324
		fTextLayout.setFont(font);
325
		fTextLayout.setWidth(-1);
326
		FontData[] fontData = font.getFontData();
327
		for (int i = 0; i < fontData.length; i++)
328
			fontData[i].setStyle(SWT.BOLD);
329
		font = new Font(fShell.getDisplay(), fontData);
330
		fBoldStyle = new TextStyle(font, null, null);
331
332
		// Compute and set tab width
333
		fTextLayout.setText("    "); //$NON-NLS-1$
334
		int tabWidth = fTextLayout.getBounds().width;
335
		fTextLayout.setTabs(new int[] {tabWidth});
336
337
		fTextLayout.setText(""); //$NON-NLS-1$
338
	}
339
340
	/*
341
	 * @see IInformationControl#dispose()
342
	 */
343
	public void dispose() {
344
		if (fTextLayout != null) {
345
			fTextLayout.dispose();
346
			fTextLayout = null;
347
		}
348
		fBoldStyle.font.dispose();
349
		fBoldStyle = null;
350
		if (fShell != null && !fShell.isDisposed())
351
			fShell.dispose();
352
		else
353
			widgetDisposed(null);
354
	}
355
356
	/*
357
	 * @see org.eclipse.swt.events.DisposeListener#widgetDisposed(org.eclipse.swt.events.DisposeEvent)
358
	 */
359
	public void widgetDisposed(DisposeEvent event) {
360
		if (fTextLayout != null) {
361
			fTextLayout.dispose();
362
			fTextLayout = null;
363
		}
364
365
		if (fStatusTextFont != null && !fStatusTextFont.isDisposed())
366
			fStatusTextFont.dispose();
367
368
		fShell = null;
369
		fBrowser = null;
370
		fStatusTextFont = null;
371
	}
372
373
	/*
374
	 * @see IInformationControl#setSize(int, int)
375
	 */
376
	public void setSize(int width, int height) {
377
		fShell.setSize(Math.min(width, fMaxWidth), Math.min(height, fMaxHeight));
378
	}
379
380
	/*
381
	 * @see IInformationControl#setLocation(Point)
382
	 */
383
	public void setLocation(Point location) {
384
		fShell.setLocation(location);
385
	}
386
387
	/*
388
	 * @see IInformationControl#setSizeConstraints(int, int)
389
	 */
390
	public void setSizeConstraints(int maxWidth, int maxHeight) {
391
		fMaxWidth = maxWidth;
392
		fMaxHeight = maxHeight;
393
	}
394
395
	/*
396
	 * @see IInformationControl#computeSizeHint()
397
	 */
398
	public Point computeSizeHint() {
399
		TextPresentation presentation = new TextPresentation();
400
		HTML2TextReader reader = new HTML2TextReader(new StringReader(fInputText), presentation);
401
		String text;
402
		try {
403
			text = reader.getString();
404
		} catch (IOException e) {
405
			text = ""; //$NON-NLS-1$
406
		}
407
408
		fTextLayout.setText(text);
409
		Iterator iter = presentation.getAllStyleRangeIterator();
410
		while (iter.hasNext()) {
411
			StyleRange sr = (StyleRange) iter.next();
412
			if (sr.fontStyle == SWT.BOLD)
413
				fTextLayout.setStyle(fBoldStyle, sr.start, sr.start + sr.length - 1);
414
		}
415
		Rectangle bounds = fTextLayout.getBounds();
416
		int width = bounds.width;
417
		int height = bounds.height;
418
419
		width += 15;
420
		height += 25;
421
422
		if (fStatusFieldText != null && fSeparator != null) {
423
			fTextLayout.setText(fStatusFieldText);
424
			Rectangle statusBounds = fTextLayout.getBounds();
425
			Rectangle separatorBounds = fSeparator.getBounds();
426
			width = Math.max(width, statusBounds.width);
427
			height = height + statusBounds.height + separatorBounds.height;
428
		}
429
430
		// Apply size constraints
431
		if (fMaxWidth != SWT.DEFAULT)
432
			width = Math.min(fMaxWidth, width);
433
		if (fMaxHeight != SWT.DEFAULT)
434
			height = Math.min(fMaxHeight, height);
435
436
		// Ensure minimal size
437
		width = Math.max(MIN_WIDTH, width);
438
		height = Math.max(MIN_HEIGHT, height);
439
440
		return new Point(width, height);
441
	}
442
443
	/*
444
	 * @see org.eclipse.jface.text.IInformationControlExtension3#computeTrim()
445
	 */
446
	public Rectangle computeTrim() {
447
		return fShell.computeTrim(0, 0, 0, 0);
448
	}
449
450
	/*
451
	 * @see org.eclipse.jface.text.IInformationControlExtension3#getBounds()
452
	 */
453
	public Rectangle getBounds() {
454
		return fShell.getBounds();
455
	}
456
457
	/*
458
	 * @see org.eclipse.jface.text.IInformationControlExtension3#restoresLocation()
459
	 */
460
	public boolean restoresLocation() {
461
		return false;
462
	}
463
464
	/*
465
	 * @see org.eclipse.jface.text.IInformationControlExtension3#restoresSize()
466
	 */
467
	public boolean restoresSize() {
468
		return false;
469
	}
470
471
	/*
472
	 * @see IInformationControl#addDisposeListener(DisposeListener)
473
	 */
474
	public void addDisposeListener(DisposeListener listener) {
475
		fShell.addDisposeListener(listener);
476
	}
477
478
	/*
479
	 * @see IInformationControl#removeDisposeListener(DisposeListener)
480
	 */
481
	public void removeDisposeListener(DisposeListener listener) {
482
		fShell.removeDisposeListener(listener);
483
	}
484
485
	/*
486
	 * @see IInformationControl#setForegroundColor(Color)
487
	 */
488
	public void setForegroundColor(Color foreground) {
489
		fBrowser.setForeground(foreground);
490
	}
491
492
	/*
493
	 * @see IInformationControl#setBackgroundColor(Color)
494
	 */
495
	public void setBackgroundColor(Color background) {
496
		fBrowser.setBackground(background);
497
	}
498
499
	/*
500
	 * @see IInformationControl#isFocusControl()
501
	 */
502
	public boolean isFocusControl() {
503
		return fBrowser.isFocusControl();
504
	}
505
506
	/*
507
	 * @see IInformationControl#setFocus()
508
	 */
509
	public void setFocus() {
510
		fShell.forceFocus();
511
		fBrowser.setFocus();
512
	}
513
514
	/*
515
	 * @see IInformationControl#addFocusListener(FocusListener)
516
	 */
517
	public void addFocusListener(final FocusListener listener) {
518
		fBrowser.addFocusListener(listener);
519
520
		/*
521
		 * FIXME:	This is a workaround for bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=84532
522
		 * 			(Browser widget does not send focusLost event)
523
		 */
524
		if (fFocusListeners.isEmpty()) {
525
			fDeactivateListener = new Listener() {
526
				public void handleEvent(Event event) {
527
					Object[] listeners = fFocusListeners.getListeners();
528
					for (int i = 0; i < listeners.length; i++)
529
						((FocusListener) listeners[i]).focusLost(new FocusEvent(event));
530
				}
531
			};
532
			fBrowser.getShell().addListener(SWT.Deactivate, fDeactivateListener);
533
		}
534
		fFocusListeners.add(listener);
535
	}
536
537
	/*
538
	 * @see IInformationControl#removeFocusListener(FocusListener)
539
	 */
540
	public void removeFocusListener(FocusListener listener) {
541
		fBrowser.removeFocusListener(listener);
542
543
		/*
544
		 * FIXME:	This is a workaround for bug https://bugs.eclipse.org/bugs/show_bug.cgi?id=84532
545
		 * 			(Browser widget does not send focusLost event)
546
		 */
547
		fFocusListeners.remove(listener);
548
		if (fFocusListeners.isEmpty()) {
549
			fBrowser.getShell().removeListener(SWT.Deactivate, fDeactivateListener);
550
			fDeactivateListener = null;
551
		}
552
	}
553
554
	/*
555
	 * @see IInformationControlExtension#hasContents()
556
	 */
557
	public boolean hasContents() {
558
		return fBrowserHasContent;
559
	}
560
}
(-)src/org/eclipse/pde/internal/ui/editor/contentassist/display/HTML2TextReader.java (-312 lines)
Removed Link Here
1
/*******************************************************************************
2
 *  Copyright (c) 2006, 2008 IBM Corporation and others.
3
 *  All rights reserved. This program and the accompanying materials
4
 *  are made available under the terms of the Eclipse Public License v1.0
5
 *  which accompanies this distribution, and is available at
6
 *  http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 *  Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.pde.internal.ui.editor.contentassist.display;
12
13
import java.io.*;
14
import java.util.*;
15
import org.eclipse.jface.text.TextPresentation;
16
import org.eclipse.swt.SWT;
17
import org.eclipse.swt.custom.StyleRange;
18
19
/**
20
 * Reads the text contents from a reader of HTML contents and translates
21
 * the tags or cut them out.
22
 */
23
public class HTML2TextReader extends SubstitutionTextReader {
24
25
	private static final String EMPTY_STRING = ""; //$NON-NLS-1$
26
	private static final Map fgEntityLookup;
27
	private static final Set fgTags;
28
29
	static {
30
31
		fgTags = new HashSet();
32
		fgTags.add("b"); //$NON-NLS-1$
33
		fgTags.add("br"); //$NON-NLS-1$
34
		fgTags.add("br/"); //$NON-NLS-1$
35
		fgTags.add("div"); //$NON-NLS-1$
36
		fgTags.add("h1"); //$NON-NLS-1$
37
		fgTags.add("h2"); //$NON-NLS-1$
38
		fgTags.add("h3"); //$NON-NLS-1$
39
		fgTags.add("h4"); //$NON-NLS-1$
40
		fgTags.add("h5"); //$NON-NLS-1$
41
		fgTags.add("p"); //$NON-NLS-1$
42
		fgTags.add("dl"); //$NON-NLS-1$
43
		fgTags.add("dt"); //$NON-NLS-1$
44
		fgTags.add("dd"); //$NON-NLS-1$
45
		fgTags.add("li"); //$NON-NLS-1$
46
		fgTags.add("ul"); //$NON-NLS-1$
47
		fgTags.add("pre"); //$NON-NLS-1$
48
		fgTags.add("head"); //$NON-NLS-1$
49
50
		fgEntityLookup = new HashMap(7);
51
		fgEntityLookup.put("lt", "<"); //$NON-NLS-1$ //$NON-NLS-2$
52
		fgEntityLookup.put("gt", ">"); //$NON-NLS-1$ //$NON-NLS-2$
53
		fgEntityLookup.put("nbsp", " "); //$NON-NLS-1$ //$NON-NLS-2$
54
		fgEntityLookup.put("amp", "&"); //$NON-NLS-1$ //$NON-NLS-2$
55
		fgEntityLookup.put("circ", "^"); //$NON-NLS-1$ //$NON-NLS-2$
56
		fgEntityLookup.put("tilde", "~"); //$NON-NLS-2$ //$NON-NLS-1$
57
		fgEntityLookup.put("quot", "\""); //$NON-NLS-1$ //$NON-NLS-2$
58
	}
59
60
	private int fCounter = 0;
61
	private TextPresentation fTextPresentation;
62
	private int fBold = 0;
63
	private int fStartOffset = -1;
64
	private boolean fInParagraph = false;
65
	private boolean fIsPreformattedText = false;
66
	private boolean fIgnore = false;
67
68
	/**
69
	 * Transforms the HTML text from the reader to formatted text.
70
	 *
71
	 * @param reader the reader
72
	 * @param presentation If not <code>null</code>, formattings will be applied to
73
	 * the presentation.
74
	*/
75
	public HTML2TextReader(Reader reader, TextPresentation presentation) {
76
		super(new PushbackReader(reader));
77
		fTextPresentation = presentation;
78
	}
79
80
	public int read() throws IOException {
81
		int c = super.read();
82
		if (c != -1)
83
			++fCounter;
84
		return c;
85
	}
86
87
	protected void startBold() {
88
		if (fBold == 0)
89
			fStartOffset = fCounter;
90
		++fBold;
91
	}
92
93
	protected void startPreformattedText() {
94
		fIsPreformattedText = true;
95
		setSkipWhitespace(false);
96
	}
97
98
	protected void stopPreformattedText() {
99
		fIsPreformattedText = false;
100
		setSkipWhitespace(true);
101
	}
102
103
	protected void stopBold() {
104
		--fBold;
105
		if (fBold == 0) {
106
			if (fTextPresentation != null) {
107
				fTextPresentation.addStyleRange(new StyleRange(fStartOffset, fCounter - fStartOffset, null, null, SWT.BOLD));
108
			}
109
			fStartOffset = -1;
110
		}
111
	}
112
113
	/*
114
	 * @see org.eclipse.jdt.internal.ui.text.SubstitutionTextReader#computeSubstitution(int)
115
	 */
116
	protected String computeSubstitution(int c) throws IOException {
117
118
		if (c == '<')
119
			return processHTMLTag();
120
		else if (fIgnore)
121
			return EMPTY_STRING;
122
		else if (c == '&')
123
			return processEntity();
124
		else if (fIsPreformattedText)
125
			return processPreformattedText(c);
126
127
		return null;
128
	}
129
130
	private String html2Text(String html) {
131
132
		if (html == null || html.length() == 0)
133
			return EMPTY_STRING;
134
135
		html = html.toLowerCase();
136
137
		String tag = html;
138
		if ('/' == tag.charAt(0))
139
			tag = tag.substring(1);
140
141
		if (!fgTags.contains(tag))
142
			return EMPTY_STRING;
143
144
		if ("pre".equals(html)) { //$NON-NLS-1$
145
			startPreformattedText();
146
			return EMPTY_STRING;
147
		}
148
149
		if ("/pre".equals(html)) { //$NON-NLS-1$
150
			stopPreformattedText();
151
			return EMPTY_STRING;
152
		}
153
154
		if (fIsPreformattedText)
155
			return EMPTY_STRING;
156
157
		if ("b".equals(html)) { //$NON-NLS-1$
158
			startBold();
159
			return EMPTY_STRING;
160
		}
161
162
		if ((html.length() > 1 && html.charAt(0) == 'h' && Character.isDigit(html.charAt(1))) || "dt".equals(html)) { //$NON-NLS-1$
163
			startBold();
164
			return EMPTY_STRING;
165
		}
166
167
		if ("dl".equals(html)) //$NON-NLS-1$
168
			return LINE_DELIM;
169
170
		if ("dd".equals(html)) //$NON-NLS-1$
171
			return "\t"; //$NON-NLS-1$
172
173
		if ("li".equals(html)) //$NON-NLS-1$
174
			// FIXME: this hard-coded prefix does not work for RTL languages, see https://bugs.eclipse.org/bugs/show_bug.cgi?id=91682
175
			return LINE_DELIM + "\t- "; //$NON-NLS-1$
176
177
		if ("/b".equals(html)) { //$NON-NLS-1$
178
			stopBold();
179
			return EMPTY_STRING;
180
		}
181
182
		if ("p".equals(html)) { //$NON-NLS-1$
183
			fInParagraph = true;
184
			return LINE_DELIM;
185
		}
186
187
		if ("br".equals(html) || "br/".equals(html) || "div".equals(html)) //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
188
			return LINE_DELIM;
189
190
		if ("/p".equals(html)) { //$NON-NLS-1$
191
			boolean inParagraph = fInParagraph;
192
			fInParagraph = false;
193
			return inParagraph ? EMPTY_STRING : LINE_DELIM;
194
		}
195
196
		if ((html.startsWith("/h") && html.length() > 2 && Character.isDigit(html.charAt(2))) || "/dt".equals(html)) { //$NON-NLS-1$ //$NON-NLS-2$
197
			stopBold();
198
			return LINE_DELIM;
199
		}
200
201
		if ("/dd".equals(html)) //$NON-NLS-1$
202
			return LINE_DELIM;
203
204
		if ("head".equals(html)) { //$NON-NLS-1$
205
			fIgnore = true;
206
			return EMPTY_STRING;
207
		}
208
209
		if ("/head".equals(html)) { //$NON-NLS-1$
210
			fIgnore = false;
211
			return EMPTY_STRING;
212
		}
213
214
		return EMPTY_STRING;
215
	}
216
217
	/*
218
	 * A '<' has been read. Process a html tag
219
	 */
220
	private String processHTMLTag() throws IOException {
221
222
		StringBuffer buf = new StringBuffer();
223
		int ch;
224
		do {
225
226
			ch = nextChar();
227
228
			while (ch != -1 && ch != '>') {
229
				buf.append(Character.toLowerCase((char) ch));
230
				ch = nextChar();
231
				if (ch == '"') {
232
					buf.append(Character.toLowerCase((char) ch));
233
					ch = nextChar();
234
					while (ch != -1 && ch != '"') {
235
						buf.append(Character.toLowerCase((char) ch));
236
						ch = nextChar();
237
					}
238
				}
239
				if (ch == '<') {
240
					unread(ch);
241
					return '<' + buf.toString();
242
				}
243
			}
244
245
			if (ch == -1)
246
				return null;
247
248
			int tagLen = buf.length();
249
			// needs special treatment for comments
250
			if ((tagLen >= 3 && "!--".equals(buf.substring(0, 3))) //$NON-NLS-1$
251
					&& !(tagLen >= 5 && "--".equals(buf.substring(tagLen - 2)))) { //$NON-NLS-1$
252
				// unfinished comment
253
				buf.append(ch);
254
			} else {
255
				break;
256
			}
257
		} while (true);
258
259
		return html2Text(buf.toString());
260
	}
261
262
	private String processPreformattedText(int c) {
263
		if (c == '\r' || c == '\n')
264
			fCounter++;
265
		return null;
266
	}
267
268
	private void unread(int ch) throws IOException {
269
		((PushbackReader) getReader()).unread(ch);
270
	}
271
272
	protected String entity2Text(String symbol) {
273
		if (symbol.length() > 1 && symbol.charAt(0) == '#') {
274
			int ch;
275
			try {
276
				if (symbol.charAt(1) == 'x') {
277
					ch = Integer.parseInt(symbol.substring(2), 16);
278
				} else {
279
					ch = Integer.parseInt(symbol.substring(1), 10);
280
				}
281
				return EMPTY_STRING + (char) ch;
282
			} catch (NumberFormatException e) {
283
			}
284
		} else {
285
			String str = (String) fgEntityLookup.get(symbol);
286
			if (str != null) {
287
				return str;
288
			}
289
		}
290
		return "&" + symbol; // not found //$NON-NLS-1$
291
	}
292
293
	/*
294
	 * A '&' has been read. Process a entity
295
	 */
296
	private String processEntity() throws IOException {
297
		StringBuffer buf = new StringBuffer();
298
		int ch = nextChar();
299
		while (Character.isLetterOrDigit((char) ch) || ch == '#') {
300
			buf.append((char) ch);
301
			ch = nextChar();
302
		}
303
304
		if (ch == ';')
305
			return entity2Text(buf.toString());
306
307
		buf.insert(0, '&');
308
		if (ch != -1)
309
			buf.append((char) ch);
310
		return buf.toString();
311
	}
312
}
(-)src/org/eclipse/pde/internal/ui/editor/contentassist/display/JavaDocCommentReader.java (-2 / +10 lines)
Lines 1-5 Link Here
1
/*******************************************************************************
1
/*******************************************************************************
2
 *  Copyright (c) 2006, 2008 IBM Corporation and others.
2
 *  Copyright (c) 2006, 2010 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
Lines 12-28 Link Here
12
12
13
import org.eclipse.jdt.core.IBuffer;
13
import org.eclipse.jdt.core.IBuffer;
14
import org.eclipse.jdt.core.formatter.IndentManipulation;
14
import org.eclipse.jdt.core.formatter.IndentManipulation;
15
import org.eclipse.jface.internal.text.html.SingleCharReader;
15
16
16
/**
17
/**
17
 * Reads a java doc comment from a java doc comment. Skips star-character
18
 * Reads a java doc comment from a java doc comment. Skips star-character
18
 * on begin of line
19
 * on begin of line.
20
 * <p>
21
 * XXX: copied from <code>org.eclipse.jdt.ui</code>.
22
 * </p>
19
 */
23
 */
20
public class JavaDocCommentReader extends SingleCharReader {
24
public class JavaDocCommentReader extends SingleCharReader {
21
25
22
	private IBuffer fBuffer;
26
	private IBuffer fBuffer;
23
27
24
	private int fCurrPos;
28
	private int fCurrPos;
29
25
	private int fStartPos;
30
	private int fStartPos;
31
26
	private int fEndPos;
32
	private int fEndPos;
27
33
28
	private boolean fWasNewLine;
34
	private boolean fWasNewLine;
Lines 81-86 Link Here
81
87
82
	/**
88
	/**
83
	 * Returns the offset of the last read character in the passed buffer.
89
	 * Returns the offset of the last read character in the passed buffer.
90
	 * 
91
	 * @return the offset
84
	 */
92
	 */
85
	public int getOffset() {
93
	public int getOffset() {
86
		return fCurrPos;
94
		return fCurrPos;
(-)src/org/eclipse/pde/internal/ui/editor/contentassist/display/SingleCharReader.java (-60 lines)
Removed Link Here
1
/*******************************************************************************
2
 *  Copyright (c) 2006, 2008 IBM Corporation and others.
3
 *  All rights reserved. This program and the accompanying materials
4
 *  are made available under the terms of the Eclipse Public License v1.0
5
 *  which accompanies this distribution, and is available at
6
 *  http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 *  Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.pde.internal.ui.editor.contentassist.display;
12
13
import java.io.IOException;
14
import java.io.Reader;
15
16
abstract class SingleCharReader extends Reader {
17
18
	/**
19
	 * @see Reader#read()
20
	 */
21
	public abstract int read() throws IOException;
22
23
	/**
24
	 * @see Reader#read(char[],int,int)
25
	 */
26
	public int read(char cbuf[], int off, int len) throws IOException {
27
		int end = off + len;
28
		for (int i = off; i < end; i++) {
29
			int ch = read();
30
			if (ch == -1) {
31
				if (i == off)
32
					return -1;
33
				return i - off;
34
			}
35
			cbuf[i] = (char) ch;
36
		}
37
		return len;
38
	}
39
40
	/**
41
	 * @see Reader#ready()
42
	 */
43
	public boolean ready() throws IOException {
44
		return true;
45
	}
46
47
	/**
48
	 * Returns the readable content as string.
49
	 * @return the readable content as string
50
	 * @exception IOException in case reading fails
51
	 */
52
	public String getString() throws IOException {
53
		StringBuffer buf = new StringBuffer();
54
		int ch;
55
		while ((ch = read()) != -1) {
56
			buf.append((char) ch);
57
		}
58
		return buf.toString();
59
	}
60
}
(-)src/org/eclipse/pde/internal/ui/editor/contentassist/display/SubstitutionTextReader.java (-156 lines)
Removed Link Here
1
/*******************************************************************************
2
 *  Copyright (c) 2006, 2008 IBM Corporation and others.
3
 *  All rights reserved. This program and the accompanying materials
4
 *  are made available under the terms of the Eclipse Public License v1.0
5
 *  which accompanies this distribution, and is available at
6
 *  http://www.eclipse.org/legal/epl-v10.html
7
 * 
8
 *  Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
12
package org.eclipse.pde.internal.ui.editor.contentassist.display;
13
14
import java.io.IOException;
15
import java.io.Reader;
16
17
/**
18
 * Reads the text contents from a reader and computes for each character
19
 * a potential substitution. The substitution may eat more characters than
20
 * only the one passed into the computation routine.
21
 */
22
abstract class SubstitutionTextReader extends SingleCharReader {
23
24
	protected static final String LINE_DELIM = System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
25
26
	private Reader fReader;
27
	private boolean fWasWhiteSpace;
28
	private int fCharAfterWhiteSpace;
29
30
	/**
31
	 * Tells whether white space characters are skipped.
32
	 */
33
	private boolean fSkipWhiteSpace = true;
34
35
	private boolean fReadFromBuffer;
36
	private StringBuffer fBuffer;
37
	private int fIndex;
38
39
	protected SubstitutionTextReader(Reader reader) {
40
		fReader = reader;
41
		fBuffer = new StringBuffer();
42
		fIndex = 0;
43
		fReadFromBuffer = false;
44
		fCharAfterWhiteSpace = -1;
45
		fWasWhiteSpace = true;
46
	}
47
48
	/**
49
	 * Computes the substitution for the given character and if necessary
50
	 * subsequent characters. Implementation should use <code>nextChar</code>
51
	 * to read subsequent characters.
52
	 *
53
	 * @param c the character to be substituted
54
	 * @return the substitution for <code>c</code>
55
	 * @throws IOException in case computing the substitution fails
56
	 */
57
	protected abstract String computeSubstitution(int c) throws IOException;
58
59
	/**
60
	 * Returns the internal reader.
61
	 *
62
	 * @return the internal reader
63
	 */
64
	protected Reader getReader() {
65
		return fReader;
66
	}
67
68
	/**
69
	 * Returns the next character.
70
	 * @return the next character
71
	 * @throws IOException in case reading the character fails
72
	 */
73
	protected int nextChar() throws IOException {
74
		fReadFromBuffer = (fBuffer.length() > 0);
75
		if (fReadFromBuffer) {
76
			char ch = fBuffer.charAt(fIndex++);
77
			if (fIndex >= fBuffer.length()) {
78
				fBuffer.setLength(0);
79
				fIndex = 0;
80
			}
81
			return ch;
82
		}
83
84
		int ch = fCharAfterWhiteSpace;
85
		if (ch == -1) {
86
			ch = fReader.read();
87
		}
88
		if (fSkipWhiteSpace && Character.isWhitespace((char) ch)) {
89
			do {
90
				ch = fReader.read();
91
			} while (Character.isWhitespace((char) ch));
92
			if (ch != -1) {
93
				fCharAfterWhiteSpace = ch;
94
				return ' ';
95
			}
96
		} else {
97
			fCharAfterWhiteSpace = -1;
98
		}
99
		return ch;
100
	}
101
102
	/**
103
	 * @see Reader#read()
104
	 */
105
	public int read() throws IOException {
106
		int c;
107
		do {
108
109
			c = nextChar();
110
			while (!fReadFromBuffer) {
111
				String s = computeSubstitution(c);
112
				if (s == null)
113
					break;
114
				if (s.length() > 0)
115
					fBuffer.insert(0, s);
116
				c = nextChar();
117
			}
118
119
		} while (fSkipWhiteSpace && fWasWhiteSpace && (c == ' '));
120
		fWasWhiteSpace = (c == ' ' || c == '\r' || c == '\n');
121
		return c;
122
	}
123
124
	/**
125
	 * @see Reader#ready()
126
	 */
127
	public boolean ready() throws IOException {
128
		return fReader.ready();
129
	}
130
131
	/**
132
	 * @see Reader#close()
133
	 */
134
	public void close() throws IOException {
135
		fReader.close();
136
	}
137
138
	/**
139
	 * @see Reader#reset()
140
	 */
141
	public void reset() throws IOException {
142
		fReader.reset();
143
		fWasWhiteSpace = true;
144
		fCharAfterWhiteSpace = -1;
145
		fBuffer.setLength(0);
146
		fIndex = 0;
147
	}
148
149
	protected final void setSkipWhitespace(boolean state) {
150
		fSkipWhiteSpace = state;
151
	}
152
153
	protected final boolean isSkippingWhitespace() {
154
		return fSkipWhiteSpace;
155
	}
156
}
(-)src/org/eclipse/pde/internal/ui/editor/text/HTMLPrinter.java (-291 lines)
Removed Link Here
1
/*******************************************************************************
2
 * Copyright (c) 2000, 2009 IBM Corporation and others.
3
 * All rights reserved. This program and the accompanying materials
4
 * are made available under the terms of the Eclipse Public License v1.0
5
 * which accompanies this distribution, and is available at
6
 * http://www.eclipse.org/legal/epl-v10.html
7
 *
8
 * Contributors:
9
 *     IBM Corporation - initial API and implementation
10
 *******************************************************************************/
11
package org.eclipse.pde.internal.ui.editor.text;
12
13
import java.io.IOException;
14
import java.io.Reader;
15
import java.net.URL;
16
import org.eclipse.swt.SWT;
17
import org.eclipse.swt.SWTError;
18
import org.eclipse.swt.graphics.FontData;
19
import org.eclipse.swt.graphics.RGB;
20
import org.eclipse.swt.widgets.Display;
21
22
/**
23
 * Provides a set of convenience methods for creating HTML pages.
24
 * <p>
25
 * Moved into this package from <code>org.eclipse.jface.internal.text.revisions</code>.</p>
26
 */
27
public class HTMLPrinter {
28
29
	private static RGB BG_COLOR_RGB = new RGB(255, 255, 225); // RGB value of info bg color on WindowsXP
30
	private static RGB FG_COLOR_RGB = new RGB(0, 0, 0); // RGB value of info fg color on WindowsXP
31
32
	private static final String UNIT; // See: https://bugs.eclipse.org/bugs/show_bug.cgi?id=155993
33
	static {
34
		String platform = SWT.getPlatform();
35
		UNIT = "carbon".equals(platform) || "cocoa".equals(platform) ? "px" : "pt"; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
36
	}
37
38
	static {
39
		final Display display = Display.getDefault();
40
		if (display != null && !display.isDisposed()) {
41
			try {
42
				display.asyncExec(new Runnable() {
43
					/*
44
					 * @see java.lang.Runnable#run()
45
					 */
46
					public void run() {
47
						BG_COLOR_RGB = display.getSystemColor(SWT.COLOR_INFO_BACKGROUND).getRGB();
48
						FG_COLOR_RGB = display.getSystemColor(SWT.COLOR_INFO_FOREGROUND).getRGB();
49
					}
50
				});
51
			} catch (SWTError err) {
52
				// see: https://bugs.eclipse.org/bugs/show_bug.cgi?id=45294
53
				if (err.code != SWT.ERROR_DEVICE_DISPOSED)
54
					throw err;
55
			}
56
		}
57
	}
58
59
	private HTMLPrinter() {
60
	}
61
62
	private static String replace(String text, char c, String s) {
63
64
		int previous = 0;
65
		int current = text.indexOf(c, previous);
66
67
		if (current == -1)
68
			return text;
69
70
		StringBuffer buffer = new StringBuffer();
71
		while (current > -1) {
72
			buffer.append(text.substring(previous, current));
73
			buffer.append(s);
74
			previous = current + 1;
75
			current = text.indexOf(c, previous);
76
		}
77
		buffer.append(text.substring(previous));
78
79
		return buffer.toString();
80
	}
81
82
	public static String convertToHTMLContent(String content) {
83
		content = replace(content, '&', "&amp;"); //$NON-NLS-1$
84
		content = replace(content, '"', "&quot;"); //$NON-NLS-1$
85
		content = replace(content, '<', "&lt;"); //$NON-NLS-1$
86
		return replace(content, '>', "&gt;"); //$NON-NLS-1$
87
	}
88
89
	public static String read(Reader rd) {
90
91
		StringBuffer buffer = new StringBuffer();
92
		char[] readBuffer = new char[2048];
93
94
		try {
95
			int n = rd.read(readBuffer);
96
			while (n > 0) {
97
				buffer.append(readBuffer, 0, n);
98
				n = rd.read(readBuffer);
99
			}
100
			return buffer.toString();
101
		} catch (IOException x) {
102
		}
103
104
		return null;
105
	}
106
107
	public static void insertPageProlog(StringBuffer buffer, int position, RGB fgRGB, RGB bgRGB, String styleSheet) {
108
		if (fgRGB == null)
109
			fgRGB = FG_COLOR_RGB;
110
		if (bgRGB == null)
111
			bgRGB = BG_COLOR_RGB;
112
113
		StringBuffer pageProlog = new StringBuffer(300);
114
115
		pageProlog.append("<html>"); //$NON-NLS-1$
116
117
		appendStyleSheetURL(pageProlog, styleSheet);
118
119
		appendColors(pageProlog, fgRGB, bgRGB);
120
121
		buffer.insert(position, pageProlog.toString());
122
	}
123
124
	private static void appendColors(StringBuffer pageProlog, RGB fgRGB, RGB bgRGB) {
125
		pageProlog.append("<body text=\""); //$NON-NLS-1$
126
		appendColor(pageProlog, fgRGB);
127
		pageProlog.append("\" bgcolor=\""); //$NON-NLS-1$
128
		appendColor(pageProlog, bgRGB);
129
		pageProlog.append("\">"); //$NON-NLS-1$
130
	}
131
132
	private static void appendColor(StringBuffer buffer, RGB rgb) {
133
		buffer.append('#');
134
		appendAsHexString(buffer, rgb.red);
135
		appendAsHexString(buffer, rgb.green);
136
		appendAsHexString(buffer, rgb.blue);
137
	}
138
139
	private static void appendAsHexString(StringBuffer buffer, int intValue) {
140
		String hexValue = Integer.toHexString(intValue);
141
		if (hexValue.length() == 1)
142
			buffer.append('0');
143
		buffer.append(hexValue);
144
	}
145
146
	public static void insertStyles(StringBuffer buffer, String[] styles) {
147
		if (styles == null || styles.length == 0)
148
			return;
149
150
		StringBuffer styleBuf = new StringBuffer(10 * styles.length);
151
		for (int i = 0; i < styles.length; i++) {
152
			styleBuf.append(" style=\""); //$NON-NLS-1$
153
			styleBuf.append(styles[i]);
154
			styleBuf.append('"');
155
		}
156
157
		// Find insertion index
158
		// a) within existing body tag with trailing space
159
		int index = buffer.indexOf("<body "); //$NON-NLS-1$
160
		if (index != -1) {
161
			buffer.insert(index + 5, styleBuf.toString());
162
			return;
163
		}
164
165
		// b) within existing body tag without attributes
166
		index = buffer.indexOf("<body>"); //$NON-NLS-1$
167
		if (index != -1) {
168
			buffer.insert(index + 5, ' ');
169
			buffer.insert(index + 6, styleBuf.toString());
170
			return;
171
		}
172
	}
173
174
	private static void appendStyleSheetURL(StringBuffer buffer, String styleSheet) {
175
		if (styleSheet == null)
176
			return;
177
178
		buffer.append("<head><style CHARSET=\"ISO-8859-1\" TYPE=\"text/css\">"); //$NON-NLS-1$
179
		buffer.append(styleSheet);
180
		buffer.append("</style></head>"); //$NON-NLS-1$
181
	}
182
183
	private static void appendStyleSheetURL(StringBuffer buffer, URL styleSheetURL) {
184
		if (styleSheetURL == null)
185
			return;
186
187
		buffer.append("<head>"); //$NON-NLS-1$
188
189
		buffer.append("<LINK REL=\"stylesheet\" HREF= \""); //$NON-NLS-1$
190
		buffer.append(styleSheetURL);
191
		buffer.append("\" CHARSET=\"ISO-8859-1\" TYPE=\"text/css\">"); //$NON-NLS-1$
192
193
		buffer.append("</head>"); //$NON-NLS-1$
194
	}
195
196
	public static void insertPageProlog(StringBuffer buffer, int position) {
197
		StringBuffer pageProlog = new StringBuffer(60);
198
		pageProlog.append("<html>"); //$NON-NLS-1$
199
		appendColors(pageProlog, FG_COLOR_RGB, BG_COLOR_RGB);
200
		buffer.insert(position, pageProlog.toString());
201
	}
202
203
	public static void insertPageProlog(StringBuffer buffer, int position, URL styleSheetURL) {
204
		StringBuffer pageProlog = new StringBuffer(300);
205
		pageProlog.append("<html>"); //$NON-NLS-1$
206
		appendStyleSheetURL(pageProlog, styleSheetURL);
207
		appendColors(pageProlog, FG_COLOR_RGB, BG_COLOR_RGB);
208
		buffer.insert(position, pageProlog.toString());
209
	}
210
211
	public static void insertPageProlog(StringBuffer buffer, int position, String styleSheet) {
212
		insertPageProlog(buffer, position, null, null, styleSheet);
213
	}
214
215
	public static void addPageProlog(StringBuffer buffer) {
216
		insertPageProlog(buffer, buffer.length());
217
	}
218
219
	public static void addPageEpilog(StringBuffer buffer) {
220
		buffer.append("</font></body></html>"); //$NON-NLS-1$
221
	}
222
223
	public static void startBulletList(StringBuffer buffer) {
224
		buffer.append("<ul>"); //$NON-NLS-1$
225
	}
226
227
	public static void endBulletList(StringBuffer buffer) {
228
		buffer.append("</ul>"); //$NON-NLS-1$
229
	}
230
231
	public static void addBullet(StringBuffer buffer, String bullet) {
232
		if (bullet != null) {
233
			buffer.append("<li>"); //$NON-NLS-1$
234
			buffer.append(bullet);
235
			buffer.append("</li>"); //$NON-NLS-1$
236
		}
237
	}
238
239
	public static void addSmallHeader(StringBuffer buffer, String header) {
240
		if (header != null) {
241
			buffer.append("<h5>"); //$NON-NLS-1$
242
			buffer.append(header);
243
			buffer.append("</h5>"); //$NON-NLS-1$
244
		}
245
	}
246
247
	public static void addParagraph(StringBuffer buffer, String paragraph) {
248
		if (paragraph != null) {
249
			buffer.append("<p>"); //$NON-NLS-1$
250
			buffer.append(paragraph);
251
		}
252
	}
253
254
	public static void addParagraph(StringBuffer buffer, Reader paragraphReader) {
255
		if (paragraphReader != null)
256
			addParagraph(buffer, read(paragraphReader));
257
	}
258
259
	/**
260
	 * Replaces the following style attributes of the font definition of the <code>html</code>
261
	 * element:
262
	 * <ul>
263
	 * <li>font-size</li>
264
	 * <li>font-weight</li>
265
	 * <li>font-style</li>
266
	 * <li>font-family</li>
267
	 * </ul>
268
	 * The font's name is used as font family, a <code>sans-serif</code> default font family is
269
	 * appended for the case that the given font name is not available.
270
	 * <p>
271
	 * If the listed font attributes are not contained in the passed style list, nothing happens.
272
	 * </p>
273
	 *
274
	 * @param styles CSS style definitions
275
	 * @param fontData the font information to use
276
	 * @return the modified style definitions
277
	 * @since 3.3
278
	 */
279
	public static String convertTopLevelFont(String styles, FontData fontData) {
280
		boolean bold = (fontData.getStyle() & SWT.BOLD) != 0;
281
		boolean italic = (fontData.getStyle() & SWT.ITALIC) != 0;
282
		String size = Integer.toString(fontData.getHeight()) + UNIT;
283
		String family = "'" + fontData.getName() + "',sans-serif"; //$NON-NLS-1$ //$NON-NLS-2$
284
285
		styles = styles.replaceFirst("(html\\s*\\{.*(?:\\s|;)font-size:\\s*)\\d+pt(\\;?.*\\})", "$1" + size + "$2"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
286
		styles = styles.replaceFirst("(html\\s*\\{.*(?:\\s|;)font-weight:\\s*)\\w+(\\;?.*\\})", "$1" + (bold ? "bold" : "normal") + "$2"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
287
		styles = styles.replaceFirst("(html\\s*\\{.*(?:\\s|;)font-style:\\s*)\\w+(\\;?.*\\})", "$1" + (italic ? "italic" : "normal") + "$2"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
288
		styles = styles.replaceFirst("(html\\s*\\{.*(?:\\s|;)font-family:\\s*).+?(;.*\\})", "$1" + family + "$2"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
289
		return styles;
290
	}
291
}
(-)src/org/eclipse/pde/internal/ui/util/PDEJavaHelperUI.java (-1 / +1 lines)
Lines 22-27 Link Here
22
import org.eclipse.jdt.core.search.SearchEngine;
22
import org.eclipse.jdt.core.search.SearchEngine;
23
import org.eclipse.jdt.ui.JavaUI;
23
import org.eclipse.jdt.ui.JavaUI;
24
import org.eclipse.jface.fieldassist.*;
24
import org.eclipse.jface.fieldassist.*;
25
import org.eclipse.jface.internal.text.html.HTMLPrinter;
25
import org.eclipse.jface.viewers.ILabelProvider;
26
import org.eclipse.jface.viewers.ILabelProvider;
26
import org.eclipse.jface.window.Window;
27
import org.eclipse.jface.window.Window;
27
import org.eclipse.jface.wizard.WizardDialog;
28
import org.eclipse.jface.wizard.WizardDialog;
Lines 32-38 Link Here
32
import org.eclipse.pde.internal.ui.editor.contentassist.display.JavaDocCommentReader;
33
import org.eclipse.pde.internal.ui.editor.contentassist.display.JavaDocCommentReader;
33
import org.eclipse.pde.internal.ui.editor.plugin.JavaAttributeValue;
34
import org.eclipse.pde.internal.ui.editor.plugin.JavaAttributeValue;
34
import org.eclipse.pde.internal.ui.editor.plugin.JavaAttributeWizard;
35
import org.eclipse.pde.internal.ui.editor.plugin.JavaAttributeWizard;
35
import org.eclipse.pde.internal.ui.editor.text.HTMLPrinter;
36
import org.eclipse.swt.SWT;
36
import org.eclipse.swt.SWT;
37
import org.eclipse.swt.widgets.Display;
37
import org.eclipse.swt.widgets.Display;
38
import org.eclipse.swt.widgets.Text;
38
import org.eclipse.swt.widgets.Text;
(-)src/org/eclipse/pde/internal/ui/wizards/extension/PointSelectionPage.java (-1 / +1 lines)
Lines 18-23 Link Here
18
import org.eclipse.core.runtime.*;
18
import org.eclipse.core.runtime.*;
19
import org.eclipse.jface.dialogs.*;
19
import org.eclipse.jface.dialogs.*;
20
import org.eclipse.jface.dialogs.Dialog;
20
import org.eclipse.jface.dialogs.Dialog;
21
import org.eclipse.jface.internal.text.html.HTMLPrinter;
21
import org.eclipse.jface.viewers.*;
22
import org.eclipse.jface.viewers.*;
22
import org.eclipse.jface.wizard.IWizard;
23
import org.eclipse.jface.wizard.IWizard;
23
import org.eclipse.jface.wizard.IWizardNode;
24
import org.eclipse.jface.wizard.IWizardNode;
Lines 33-39 Link Here
33
import org.eclipse.pde.internal.ui.*;
34
import org.eclipse.pde.internal.ui.*;
34
import org.eclipse.pde.internal.ui.dialogs.PluginSelectionDialog;
35
import org.eclipse.pde.internal.ui.dialogs.PluginSelectionDialog;
35
import org.eclipse.pde.internal.ui.editor.contentassist.XMLInsertionComputer;
36
import org.eclipse.pde.internal.ui.editor.contentassist.XMLInsertionComputer;
36
import org.eclipse.pde.internal.ui.editor.text.HTMLPrinter;
37
import org.eclipse.pde.internal.ui.elements.DefaultContentProvider;
37
import org.eclipse.pde.internal.ui.elements.DefaultContentProvider;
38
import org.eclipse.pde.internal.ui.elements.ElementLabelProvider;
38
import org.eclipse.pde.internal.ui.elements.ElementLabelProvider;
39
import org.eclipse.pde.internal.ui.search.ShowDescriptionAction;
39
import org.eclipse.pde.internal.ui.search.ShowDescriptionAction;

Return to bug 158331