comparison org.eclipse.jface.text/src/org/eclipse/jface/text/AbstractInformationControl.d @ 12:bc29606a740c

Added dwt-addons in original directory structure of eclipse.org
author Frank Benoit <benoit@tionex.de>
date Sat, 14 Mar 2009 18:23:29 +0100
parents
children
comparison
equal deleted inserted replaced
11:43904fec5dca 12:bc29606a740c
1 /*******************************************************************************
2 * Copyright (c) 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 * Port to the D programming language:
11 * Frank Benoit <benoit@tionex.de>
12 *******************************************************************************/
13 module org.eclipse.jface.text.AbstractInformationControl;
14
15 import org.eclipse.jface.text.IDocumentPartitioningListener; // packageimport
16 import org.eclipse.jface.text.DefaultTextHover; // packageimport
17 import org.eclipse.jface.text.TextUtilities; // packageimport
18 import org.eclipse.jface.text.IInformationControlCreatorExtension; // packageimport
19 import org.eclipse.jface.text.AbstractInformationControlManager; // packageimport
20 import org.eclipse.jface.text.ITextViewerExtension2; // packageimport
21 import org.eclipse.jface.text.IDocumentPartitioner; // packageimport
22 import org.eclipse.jface.text.DefaultIndentLineAutoEditStrategy; // packageimport
23 import org.eclipse.jface.text.ITextSelection; // packageimport
24 import org.eclipse.jface.text.Document; // packageimport
25 import org.eclipse.jface.text.FindReplaceDocumentAdapterContentProposalProvider; // packageimport
26 import org.eclipse.jface.text.ITextListener; // packageimport
27 import org.eclipse.jface.text.BadPartitioningException; // packageimport
28 import org.eclipse.jface.text.ITextViewerExtension5; // packageimport
29 import org.eclipse.jface.text.IDocumentPartitionerExtension3; // packageimport
30 import org.eclipse.jface.text.IUndoManager; // packageimport
31 import org.eclipse.jface.text.ITextHoverExtension2; // packageimport
32 import org.eclipse.jface.text.IRepairableDocument; // packageimport
33 import org.eclipse.jface.text.IRewriteTarget; // packageimport
34 import org.eclipse.jface.text.DefaultPositionUpdater; // packageimport
35 import org.eclipse.jface.text.RewriteSessionEditProcessor; // packageimport
36 import org.eclipse.jface.text.TextViewerHoverManager; // packageimport
37 import org.eclipse.jface.text.DocumentRewriteSession; // packageimport
38 import org.eclipse.jface.text.TextViewer; // packageimport
39 import org.eclipse.jface.text.ITextViewerExtension8; // packageimport
40 import org.eclipse.jface.text.RegExMessages; // packageimport
41 import org.eclipse.jface.text.IDelayedInputChangeProvider; // packageimport
42 import org.eclipse.jface.text.ITextOperationTargetExtension; // packageimport
43 import org.eclipse.jface.text.IWidgetTokenOwner; // packageimport
44 import org.eclipse.jface.text.IViewportListener; // packageimport
45 import org.eclipse.jface.text.GapTextStore; // packageimport
46 import org.eclipse.jface.text.MarkSelection; // packageimport
47 import org.eclipse.jface.text.IDocumentPartitioningListenerExtension; // packageimport
48 import org.eclipse.jface.text.IDocumentAdapterExtension; // packageimport
49 import org.eclipse.jface.text.IInformationControlExtension; // packageimport
50 import org.eclipse.jface.text.IDocumentPartitioningListenerExtension2; // packageimport
51 import org.eclipse.jface.text.DefaultDocumentAdapter; // packageimport
52 import org.eclipse.jface.text.ITextViewerExtension3; // packageimport
53 import org.eclipse.jface.text.IInformationControlCreator; // packageimport
54 import org.eclipse.jface.text.TypedRegion; // packageimport
55 import org.eclipse.jface.text.ISynchronizable; // packageimport
56 import org.eclipse.jface.text.IMarkRegionTarget; // packageimport
57 import org.eclipse.jface.text.TextViewerUndoManager; // packageimport
58 import org.eclipse.jface.text.IRegion; // packageimport
59 import org.eclipse.jface.text.IInformationControlExtension2; // packageimport
60 import org.eclipse.jface.text.IDocumentExtension4; // packageimport
61 import org.eclipse.jface.text.IDocumentExtension2; // packageimport
62 import org.eclipse.jface.text.IDocumentPartitionerExtension2; // packageimport
63 // import org.eclipse.jface.text.Assert; // packageimport
64 import org.eclipse.jface.text.DefaultInformationControl; // packageimport
65 import org.eclipse.jface.text.IWidgetTokenOwnerExtension; // packageimport
66 import org.eclipse.jface.text.DocumentClone; // packageimport
67 import org.eclipse.jface.text.DefaultUndoManager; // packageimport
68 import org.eclipse.jface.text.IFindReplaceTarget; // packageimport
69 import org.eclipse.jface.text.IAutoEditStrategy; // packageimport
70 import org.eclipse.jface.text.ILineTrackerExtension; // packageimport
71 import org.eclipse.jface.text.IUndoManagerExtension; // packageimport
72 import org.eclipse.jface.text.TextSelection; // packageimport
73 import org.eclipse.jface.text.DefaultAutoIndentStrategy; // packageimport
74 import org.eclipse.jface.text.IAutoIndentStrategy; // packageimport
75 import org.eclipse.jface.text.IPainter; // packageimport
76 import org.eclipse.jface.text.IInformationControl; // packageimport
77 import org.eclipse.jface.text.IInformationControlExtension3; // packageimport
78 import org.eclipse.jface.text.ITextViewerExtension6; // packageimport
79 import org.eclipse.jface.text.IInformationControlExtension4; // packageimport
80 import org.eclipse.jface.text.DefaultLineTracker; // packageimport
81 import org.eclipse.jface.text.IDocumentInformationMappingExtension; // packageimport
82 import org.eclipse.jface.text.IRepairableDocumentExtension; // packageimport
83 import org.eclipse.jface.text.ITextHover; // packageimport
84 import org.eclipse.jface.text.FindReplaceDocumentAdapter; // packageimport
85 import org.eclipse.jface.text.ILineTracker; // packageimport
86 import org.eclipse.jface.text.Line; // packageimport
87 import org.eclipse.jface.text.ITextViewerExtension; // packageimport
88 import org.eclipse.jface.text.IDocumentAdapter; // packageimport
89 import org.eclipse.jface.text.TextEvent; // packageimport
90 import org.eclipse.jface.text.BadLocationException; // packageimport
91 import org.eclipse.jface.text.AbstractDocument; // packageimport
92 import org.eclipse.jface.text.AbstractLineTracker; // packageimport
93 import org.eclipse.jface.text.TreeLineTracker; // packageimport
94 import org.eclipse.jface.text.ITextPresentationListener; // packageimport
95 import org.eclipse.jface.text.Region; // packageimport
96 import org.eclipse.jface.text.ITextViewer; // packageimport
97 import org.eclipse.jface.text.IDocumentInformationMapping; // packageimport
98 import org.eclipse.jface.text.MarginPainter; // packageimport
99 import org.eclipse.jface.text.IPaintPositionManager; // packageimport
100 import org.eclipse.jface.text.TextPresentation; // packageimport
101 import org.eclipse.jface.text.IFindReplaceTargetExtension; // packageimport
102 import org.eclipse.jface.text.ISlaveDocumentManagerExtension; // packageimport
103 import org.eclipse.jface.text.ISelectionValidator; // packageimport
104 import org.eclipse.jface.text.IDocumentExtension; // packageimport
105 import org.eclipse.jface.text.PropagatingFontFieldEditor; // packageimport
106 import org.eclipse.jface.text.ConfigurableLineTracker; // packageimport
107 import org.eclipse.jface.text.SlaveDocumentEvent; // packageimport
108 import org.eclipse.jface.text.IDocumentListener; // packageimport
109 import org.eclipse.jface.text.PaintManager; // packageimport
110 import org.eclipse.jface.text.IFindReplaceTargetExtension3; // packageimport
111 import org.eclipse.jface.text.ITextDoubleClickStrategy; // packageimport
112 import org.eclipse.jface.text.IDocumentExtension3; // packageimport
113 import org.eclipse.jface.text.Position; // packageimport
114 import org.eclipse.jface.text.TextMessages; // packageimport
115 import org.eclipse.jface.text.CopyOnWriteTextStore; // packageimport
116 import org.eclipse.jface.text.WhitespaceCharacterPainter; // packageimport
117 import org.eclipse.jface.text.IPositionUpdater; // packageimport
118 import org.eclipse.jface.text.DefaultTextDoubleClickStrategy; // packageimport
119 import org.eclipse.jface.text.ListLineTracker; // packageimport
120 import org.eclipse.jface.text.ITextInputListener; // packageimport
121 import org.eclipse.jface.text.BadPositionCategoryException; // packageimport
122 import org.eclipse.jface.text.IWidgetTokenKeeperExtension; // packageimport
123 import org.eclipse.jface.text.IInputChangedListener; // packageimport
124 import org.eclipse.jface.text.ITextOperationTarget; // packageimport
125 import org.eclipse.jface.text.IDocumentInformationMappingExtension2; // packageimport
126 import org.eclipse.jface.text.ITextViewerExtension7; // packageimport
127 import org.eclipse.jface.text.IInformationControlExtension5; // packageimport
128 import org.eclipse.jface.text.IDocumentRewriteSessionListener; // packageimport
129 import org.eclipse.jface.text.JFaceTextUtil; // packageimport
130 import org.eclipse.jface.text.AbstractReusableInformationControlCreator; // packageimport
131 import org.eclipse.jface.text.TabsToSpacesConverter; // packageimport
132 import org.eclipse.jface.text.CursorLinePainter; // packageimport
133 import org.eclipse.jface.text.ITextHoverExtension; // packageimport
134 import org.eclipse.jface.text.IEventConsumer; // packageimport
135 import org.eclipse.jface.text.IDocument; // packageimport
136 import org.eclipse.jface.text.IWidgetTokenKeeper; // packageimport
137 import org.eclipse.jface.text.DocumentCommand; // packageimport
138 import org.eclipse.jface.text.TypedPosition; // packageimport
139 import org.eclipse.jface.text.IEditingSupportRegistry; // packageimport
140 import org.eclipse.jface.text.IDocumentPartitionerExtension; // packageimport
141 import org.eclipse.jface.text.AbstractHoverInformationControlManager; // packageimport
142 import org.eclipse.jface.text.IEditingSupport; // packageimport
143 import org.eclipse.jface.text.IMarkSelection; // packageimport
144 import org.eclipse.jface.text.ISlaveDocumentManager; // packageimport
145 import org.eclipse.jface.text.DocumentEvent; // packageimport
146 import org.eclipse.jface.text.DocumentPartitioningChangedEvent; // packageimport
147 import org.eclipse.jface.text.ITextStore; // packageimport
148 import org.eclipse.jface.text.JFaceTextMessages; // packageimport
149 import org.eclipse.jface.text.DocumentRewriteSessionEvent; // packageimport
150 import org.eclipse.jface.text.SequentialRewriteTextStore; // packageimport
151 import org.eclipse.jface.text.DocumentRewriteSessionType; // packageimport
152 import org.eclipse.jface.text.TextAttribute; // packageimport
153 import org.eclipse.jface.text.ITextViewerExtension4; // packageimport
154 import org.eclipse.jface.text.ITypedRegion; // packageimport
155
156 import java.lang.all;
157 import java.util.Set;
158
159 import org.eclipse.swt.SWT;
160 import org.eclipse.swt.events.DisposeListener;
161 import org.eclipse.swt.events.FocusEvent;
162 import org.eclipse.swt.events.FocusListener;
163 import org.eclipse.swt.events.MouseAdapter;
164 import org.eclipse.swt.events.MouseEvent;
165 import org.eclipse.swt.events.MouseMoveListener;
166 import org.eclipse.swt.events.PaintEvent;
167 import org.eclipse.swt.events.PaintListener;
168 import org.eclipse.swt.graphics.Color;
169 import org.eclipse.swt.graphics.Cursor;
170 import org.eclipse.swt.graphics.Font;
171 import org.eclipse.swt.graphics.FontData;
172 import org.eclipse.swt.graphics.GC;
173 import org.eclipse.swt.graphics.Point;
174 import org.eclipse.swt.graphics.Rectangle;
175 import org.eclipse.swt.layout.FillLayout;
176 import org.eclipse.swt.layout.GridData;
177 import org.eclipse.swt.layout.GridLayout;
178 import org.eclipse.swt.widgets.Canvas;
179 import org.eclipse.swt.widgets.Composite;
180 import org.eclipse.swt.widgets.Control;
181 import org.eclipse.swt.widgets.Display;
182 import org.eclipse.swt.widgets.Event;
183 import org.eclipse.swt.widgets.Label;
184 import org.eclipse.swt.widgets.Listener;
185 import org.eclipse.swt.widgets.Shell;
186 import org.eclipse.swt.widgets.Slider;
187 import org.eclipse.swt.widgets.ToolBar;
188 import org.eclipse.core.runtime.Assert;
189 import org.eclipse.core.runtime.ListenerList;
190 import org.eclipse.jface.action.ToolBarManager;
191 import org.eclipse.jface.resource.JFaceResources;
192 import org.eclipse.jface.util.Geometry;
193
194
195 /**
196 * An abstract information control that can show content inside a shell.
197 * The information control can be created in two styles:
198 * <ul>
199 * <li>non-resizable tooltip with optional status</li>
200 * <li>resizable tooltip with optional tool bar</li>
201 * </ul>
202 * Additionally it can present either a status line containing a status text or
203 * a toolbar containing toolbar buttons.
204 * <p>
205 * Subclasses must either override {@link IInformationControl#setInformation(String)}
206 * or implement {@link IInformationControlExtension2}.
207 * They should also extend {@link #computeTrim()} if they create a content area
208 * with additional trim (e.g. scrollbars) and override {@link #getInformationPresenterControlCreator()}.
209 * </p>
210 *
211 * @since 3.4
212 */
213 public abstract class AbstractInformationControl : IInformationControl, IInformationControlExtension, IInformationControlExtension3, IInformationControlExtension4, IInformationControlExtension5 {
214
215 /** The information control's shell. */
216 private const Shell fShell;
217 /** Composite containing the content created by subclasses. */
218 private const Composite fContentComposite;
219 /** Whether the information control is resizable. */
220 private const bool fResizable;
221
222 /** Composite containing the status line content or <code>null</code> if none. */
223 private Composite fStatusComposite;
224 /** Separator between content and status line or <code>null</code> if none. */
225 private Label fSeparator;
226 /** Label in the status line or <code>null</code> if none. */
227 private Label fStatusLabel;
228 /** The toolbar manager used by the toolbar or <code>null</code> if none. */
229 private const ToolBarManager fToolBarManager;
230 /** Status line toolbar or <code>null</code> if none. */
231 private ToolBar fToolBar;
232
233 /** Listener for shell activation and deactivation. */
234 private Listener fShellListener;
235 /** All focus listeners registered to this information control. */
236 private ListenerList fFocusListeners;
237
238 /** Size constraints, x is the maxWidth and y is the maxHeight, or <code>null</code> if not set. */
239 private Point fSizeConstraints;
240 /** The size of the resize handle if already set, -1 otherwise */
241 private int fResizeHandleSize;
242
243 /**
244 * Creates an abstract information control with the given shell as parent.
245 * The control will not be resizable and optionally show a status line with
246 * the given status field text.
247 * <p>
248 * <em>Important: Subclasses are required to call {@link #create()} at the end of their constructor.</em>
249 * </p>
250 *
251 * @param parentShell the parent of this control's shell
252 * @param statusFieldText the text to be used in the status field or <code>null</code> to hide the status field
253 */
254 public this(Shell parentShell, String statusFieldText) {
255 this(parentShell, SWT.TOOL | SWT.ON_TOP, statusFieldText, null);
256 }
257
258 /**
259 * Creates an abstract information control with the given shell as parent.
260 * The control will be resizable and optionally show a tool bar managed by
261 * the given tool bar manager.
262 * <p>
263 * <em>Important: Subclasses are required to call {@link #create()} at the end of their constructor.</em>
264 * </p>
265 *
266 * @param parentShell the parent of this control's shell
267 * @param toolBarManager the manager or <code>null</code> if toolbar is not desired
268 */
269 public this(Shell parentShell, ToolBarManager toolBarManager) {
270 this(parentShell, SWT.TOOL | SWT.ON_TOP | SWT.RESIZE, null, toolBarManager);
271 }
272
273 /**
274 * Creates an abstract information control with the given shell as parent.
275 * <p>
276 * <em>Important: Subclasses are required to call {@link #create()} at the end of their constructor.</em>
277 * </p>
278 *
279 * @param parentShell the parent of this control's shell
280 * @param isResizable <code>true</code> if the control should be resizable
281 */
282 public this(Shell parentShell, bool isResizable) {
283 this(parentShell, SWT.TOOL | SWT.ON_TOP | (isResizable ? SWT.RESIZE : 0), null, null);
284 }
285
286 /**
287 * Creates an abstract information control with the given shell as parent.
288 * The given shell style is used for the shell (NO_TRIM will be removed to make sure there's a border).
289 * <p>
290 * The control will optionally show either a status line or a tool bar.
291 * At most one of <code>toolBarManager</code> or <code>statusFieldText</code> can be non-null.
292 * </p>
293 * <p>
294 * <strong>Important:</strong>: Subclasses are required to call {@link #create()} at the end of their constructor.
295 * </p>
296 *
297 * @param parentShell the parent of this control's shell
298 * @param shellStyle style of this control's shell
299 * @param statusFieldText the text to be used in the status field or <code>null</code> to hide the status field
300 * @param toolBarManager the manager or <code>null</code> if toolbar is not desired
301 *
302 * @deprecated clients should use one of the public constructors
303 */
304 this(Shell parentShell, int shellStyle, String statusFieldText, ToolBarManager toolBarManager) {
305
306 fFocusListeners= new ListenerList(ListenerList.IDENTITY);
307
308 Assert.isTrue(statusFieldText is null || toolBarManager is null);
309 fResizeHandleSize= -1;
310 fToolBarManager= toolBarManager;
311
312 if ((shellStyle & SWT.NO_TRIM) !is 0)
313 shellStyle&= ~(SWT.NO_TRIM | SWT.SHELL_TRIM); // make sure we get the OS border but no other trims
314
315 fResizable= (shellStyle & SWT.RESIZE) !is 0; // on GTK, Shell removes SWT.RESIZE if SWT.ON_TOP is set
316 fShell= new Shell(parentShell, shellStyle);
317 Display display= fShell.getDisplay();
318 Color foreground= display.getSystemColor(SWT.COLOR_INFO_FOREGROUND);
319 Color background= display.getSystemColor(SWT.COLOR_INFO_BACKGROUND);
320 setColor(fShell, foreground, background);
321
322 GridLayout layout= new GridLayout(1, false);
323 layout.marginHeight= 0;
324 layout.marginWidth= 0;
325 layout.verticalSpacing= 0;
326 fShell.setLayout(layout);
327
328 fContentComposite= new Composite(fShell, SWT.NONE);
329 fContentComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
330 fContentComposite.setLayout(new FillLayout());
331 setColor(fContentComposite, foreground, background);
332
333 createStatusComposite(statusFieldText, toolBarManager, foreground, background);
334 }
335
336 private void createStatusComposite(String statusFieldText, ToolBarManager toolBarManager, Color foreground, Color background) {
337 if (toolBarManager is null && statusFieldText is null)
338 return;
339
340 fStatusComposite= new Composite(fShell, SWT.NONE);
341 GridData gridData= new GridData(SWT.FILL, SWT.BOTTOM, true, false);
342 fStatusComposite.setLayoutData(gridData);
343 GridLayout statusLayout= new GridLayout(1, false);
344 statusLayout.marginHeight= 0;
345 statusLayout.marginWidth= 0;
346 statusLayout.verticalSpacing= 1;
347 fStatusComposite.setLayout(statusLayout);
348
349 fSeparator= new Label(fStatusComposite, SWT.SEPARATOR | SWT.HORIZONTAL);
350 fSeparator.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
351
352 if (statusFieldText !is null) {
353 createStatusLabel(statusFieldText, foreground, background);
354 } else {
355 createToolBar(toolBarManager);
356 }
357 }
358
359 private void createStatusLabel(String statusFieldText, Color foreground, Color background) {
360 fStatusLabel= new Label(fStatusComposite, SWT.RIGHT);
361 fStatusLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
362 fStatusLabel.setText(statusFieldText);
363
364 FontData[] fontDatas= JFaceResources.getDialogFont().getFontData();
365 for (int i= 0; i < fontDatas.length; i++) {
366 fontDatas[i].setHeight(fontDatas[i].getHeight() * 9 / 10);
367 }
368 fStatusLabel.setFont(new Font(fStatusLabel.getDisplay(), fontDatas));
369
370 fStatusLabel.setForeground(fStatusLabel.getDisplay().getSystemColor(SWT.COLOR_WIDGET_DARK_SHADOW));
371 fStatusLabel.setBackground(background);
372 setColor(fStatusComposite, foreground, background);
373 }
374
375 private void createToolBar(ToolBarManager toolBarManager) {
376 Composite bars= new Composite(fStatusComposite, SWT.NONE);
377 bars.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false));
378
379 GridLayout layout= new GridLayout(3, false);
380 layout.marginHeight= 0;
381 layout.marginWidth= 0;
382 layout.horizontalSpacing= 0;
383 layout.verticalSpacing= 0;
384 bars.setLayout(layout);
385
386 fToolBar= toolBarManager.createControl(bars);
387 GridData gd= new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false);
388 fToolBar.setLayoutData(gd);
389
390 Composite spacer= new Composite(bars, SWT.NONE);
391 gd= new GridData(SWT.FILL, SWT.FILL, true, true);
392 gd.widthHint= 0;
393 gd.heightHint= 0;
394 spacer.setLayoutData(gd);
395
396 addMoveSupport(spacer);
397 addResizeSupportIfNecessary(bars);
398 }
399
400 private void addResizeSupportIfNecessary(Composite bars) {
401 // XXX: workarounds for
402 // - https://bugs.eclipse.org/bugs/show_bug.cgi?id=219139 : API to add resize grip / grow box in lower right corner of shell
403 // - https://bugs.eclipse.org/bugs/show_bug.cgi?id=23980 : platform specific shell resize behavior
404 String platform= SWT.getPlatform();
405 bool isWin= platform.equals("win32"); //$NON-NLS-1$
406 if (!isWin && !platform.equals("gtk")) //$NON-NLS-1$
407 return;
408
409 Canvas resizer= new Canvas(bars, SWT.NONE);
410
411 int size= getResizeHandleSize(bars);
412
413 GridData data= new GridData(SWT.END, SWT.END, false, true);
414 data.widthHint= size;
415 data.heightHint= size;
416 resizer.setLayoutData(data);
417 resizer.addPaintListener(new class(isWin,resizer) PaintListener {
418 bool isWin_;
419 Canvas resizer_;
420 this(bool a, Canvas b ){
421 isWin_=a;
422 resizer_=b;
423 }
424 public void paintControl(PaintEvent e) {
425 Point s= resizer_.getSize();
426 int x= s.x - 2;
427 int y= s.y - 2;
428 int min= Math.min(x, y);
429 if (isWin_) {
430 // draw dots
431 e.gc.setBackground(resizer_.getDisplay().getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW));
432 int end= min - 1;
433 for (int i= 0; i <= 2; i++)
434 for (int j= 0; j <= 2 - i; j++)
435 e.gc.fillRectangle(end - 4 * i, end - 4 * j, 2, 2);
436 end--;
437 e.gc.setBackground(resizer_.getDisplay().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW));
438 for (int i= 0; i <= 2; i++)
439 for (int j= 0; j <= 2 - i; j++)
440 e.gc.fillRectangle(end - 4 * i, end - 4 * j, 2, 2);
441
442 } else {
443 // draw diagonal lines
444 e.gc.setForeground(resizer_.getDisplay().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW));
445 for (int i= 1; i < min; i+= 4) {
446 e.gc.drawLine(i, y, x, i);
447 }
448 e.gc.setForeground(resizer_.getDisplay().getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW));
449 for (int i= 2; i < min; i+= 4) {
450 e.gc.drawLine(i, y, x, i);
451 }
452 }
453 }
454 });
455
456 resizer.setCursor(new Cursor(resizer.getDisplay(), SWT.CURSOR_SIZESE));
457 MouseAdapter resizeSupport= new class(resizer) MouseAdapter {
458 Canvas resizer_;
459 this(Canvas a){
460 resizer_=a;
461 }
462 private MouseMoveListener fResizeListener;
463
464 public void mouseDown(MouseEvent e) {
465 Point shellSize= fShell.getSize();
466 int shellX= shellSize.x;
467 int shellY= shellSize.y;
468 Point mouseLoc= resizer_.toDisplay(e.x, e.y);
469 int mouseX= mouseLoc.x;
470 int mouseY= mouseLoc.y;
471 fResizeListener= new class(shellX,shellY,mouseX,mouseY) MouseMoveListener {
472 int shellX_;
473 int shellY_;
474 int mouseX_;
475 int mouseY_;
476 this(int a, int b, int c, int d ){
477 shellX_=a;
478 shellY_=b;
479 mouseX_=c;
480 mouseY_=d;
481 }
482 public void mouseMove(MouseEvent e2) {
483 Point mouseLoc2= resizer_.toDisplay(e2.x, e2.y);
484 int dx= mouseLoc2.x - mouseX_;
485 int dy= mouseLoc2.y - mouseY_;
486 setSize(shellX_ + dx, shellY_ + dy);
487 }
488 };
489 resizer_.addMouseMoveListener(fResizeListener);
490 }
491
492 public void mouseUp(MouseEvent e) {
493 resizer_.removeMouseMoveListener(fResizeListener);
494 fResizeListener= null;
495 }
496 };
497 resizer.addMouseListener(resizeSupport);
498 }
499
500 private int getResizeHandleSize(Composite parent) {
501 if (fResizeHandleSize is -1) {
502 Slider sliderV= new Slider(parent, SWT.VERTICAL);
503 Slider sliderH= new Slider(parent, SWT.HORIZONTAL);
504 int width= sliderV.computeSize(SWT.DEFAULT, SWT.DEFAULT).x;
505 int height= sliderH.computeSize(SWT.DEFAULT, SWT.DEFAULT).y;
506 sliderV.dispose();
507 sliderH.dispose();
508 fResizeHandleSize= Math.min(width, height);
509 }
510
511 return fResizeHandleSize;
512 }
513
514 /**
515 * Adds support to move the shell by dragging the given control.
516 *
517 * @param control the control that can be used to move the shell
518 */
519 private void addMoveSupport(Control control) {
520 MouseAdapter moveSupport= new class(control) MouseAdapter {
521 private MouseMoveListener fMoveListener;
522 Control control_;
523 this(Control a){
524 control_=a;
525 }
526 public void mouseDown(MouseEvent e) {
527 Point shellLoc= fShell.getLocation();
528 final int shellX= shellLoc.x;
529 final int shellY= shellLoc.y;
530 Point mouseLoc= control_.toDisplay(e.x, e.y);
531 final int mouseX= mouseLoc.x;
532 final int mouseY= mouseLoc.y;
533 fMoveListener= new class() MouseMoveListener {
534 public void mouseMove(MouseEvent e2) {
535 Point mouseLoc2= control_.toDisplay(e2.x, e2.y);
536 int dx= mouseLoc2.x - mouseX;
537 int dy= mouseLoc2.y - mouseY;
538 fShell.setLocation(shellX + dx, shellY + dy);
539 }
540 };
541 control_.addMouseMoveListener(fMoveListener);
542 }
543
544 public void mouseUp(MouseEvent e) {
545 control_.removeMouseMoveListener(fMoveListener);
546 fMoveListener= null;
547 }
548 };
549 control.addMouseListener(moveSupport);
550 }
551
552 /**
553 * Utility to set the foreground and the background color of the given
554 * control
555 *
556 * @param control the control to modify
557 * @param foreground the color to use for the foreground
558 * @param background the color to use for the background
559 */
560 private static void setColor(Control control, Color foreground, Color background) {
561 control.setForeground(foreground);
562 control.setBackground(background);
563 }
564
565 /**
566 * The shell of the popup window.
567 *
568 * @return the shell used for the popup window
569 */
570 protected final Shell getShell() {
571 return fShell;
572 }
573
574 /**
575 * The toolbar manager used to manage the toolbar, or <code>null</code> if
576 * no toolbar is shown.
577 *
578 * @return the tool bar manager or <code>null</code>
579 */
580 protected final ToolBarManager getToolBarManager() {
581 return fToolBarManager;
582 }
583
584 /**
585 * Creates the content of this information control. Subclasses must call
586 * this method at the end of their constructor(s).
587 */
588 protected final void create() {
589 createContent(fContentComposite);
590 }
591
592 /**
593 * Creates the content of the popup window.
594 * <p>
595 * Implementors will usually take over {@link Composite#getBackground()} and
596 * {@link Composite#getForeground()} from <code>parent</code>.
597 * </p>
598 * <p>
599 * Implementors are expected to consider {@link #isResizable()}: If
600 * <code>true</code>, they should show scrollbars if their content may
601 * exceed the size of the information control. If <code>false</code>,
602 * they should never show scrollbars.
603 * </p>
604 * <p>
605 * The given <code>parent</code> comes with a {@link FillLayout}.
606 * Subclasses may set a different layout.
607 * </p>
608 *
609 * @param parent the container of the content
610 */
611 protected abstract void createContent(Composite parent);
612
613 /**
614 * Sets the information to be presented by this information control.
615 * <p>
616 * The default implementation does nothing. Subclasses must either override this method
617 * or implement {@link IInformationControlExtension2}.
618 *
619 * @param information the information to be presented
620 *
621 * @see org.eclipse.jface.text.IInformationControl#setInformation(java.lang.String)
622 */
623 public void setInformation(String information) {
624
625 }
626
627 /**
628 * Returns whether the information control is resizable.
629 *
630 * @return <code>true</code> if the information control is resizable,
631 * <code>false</code> if it is not resizable.
632 */
633 public bool isResizable() {
634 return fResizable;
635 }
636
637 /*
638 * @see IInformationControl#setVisible(bool)
639 */
640 public void setVisible(bool visible) {
641 if (fShell.isVisible() is visible)
642 return;
643
644 fShell.setVisible(visible);
645 }
646
647 /*
648 * @see IInformationControl#dispose()
649 */
650 public void dispose() {
651 if (fShell !is null && !fShell.isDisposed())
652 fShell.dispose();
653 }
654
655 /*
656 * @see IInformationControl#setSize(int, int)
657 */
658 public void setSize(int width, int height) {
659 fShell.setSize(width, height);
660 }
661
662 /*
663 * @see IInformationControl#setLocation(Point)
664 */
665 public void setLocation(Point location) {
666 fShell.setLocation(location);
667 }
668
669 /*
670 * @see IInformationControl#setSizeConstraints(int, int)
671 */
672 public void setSizeConstraints(int maxWidth, int maxHeight) {
673 fSizeConstraints= new Point(maxWidth, maxHeight);
674 }
675
676 /**
677 * Returns the size constraints.
678 *
679 * @return the size constraints or <code>null</code> if not set
680 * @see #setSizeConstraints(int, int)
681 */
682 protected final Point getSizeConstraints() {
683 return fSizeConstraints !is null ? Geometry.copy(fSizeConstraints) : null;
684 }
685
686 /*
687 * @see IInformationControl#computeSizeHint()
688 */
689 public Point computeSizeHint() {
690 // XXX: Verify whether this is a good default implementation. If yes, document it.
691 Point constrains= getSizeConstraints();
692 if (constrains is null)
693 return fShell.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
694
695 return fShell.computeSize(constrains.x, constrains.y, true);
696 }
697
698 /**
699 * Computes the trim (status text and tool bar are considered as trim).
700 * Subclasses can extend this method to add additional trim (e.g. scroll
701 * bars for resizable information controls).
702 *
703 * @see org.eclipse.jface.text.IInformationControlExtension3#computeTrim()
704 */
705 public Rectangle computeTrim() {
706 Rectangle trim= fShell.computeTrim(0, 0, 0, 0);
707
708 if (fStatusComposite !is null)
709 trim.height+= fStatusComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT).y;
710
711 return trim;
712 }
713
714 /*
715 * @see org.eclipse.jface.text.IInformationControlExtension3#getBounds()
716 */
717 public Rectangle getBounds() {
718 return fShell.getBounds();
719 }
720
721 /**
722 * {@inheritDoc}
723 * <p>
724 * The default implementation always returns <code>false</code>.
725 * </p>
726 * @see org.eclipse.jface.text.IInformationControlExtension3#restoresLocation()
727 */
728 public bool restoresLocation() {
729 return false;
730 }
731
732 /**
733 * {@inheritDoc}
734 * <p>
735 * The default implementation always returns <code>false</code>.
736 * </p>
737 * @see org.eclipse.jface.text.IInformationControlExtension3#restoresSize()
738 */
739 public bool restoresSize() {
740 return false;
741 }
742
743 /*
744 * @see IInformationControl#addDisposeListener(DisposeListener)
745 */
746 public void addDisposeListener(DisposeListener listener) {
747 fShell.addDisposeListener(listener);
748 }
749
750 /*
751 * @see IInformationControl#removeDisposeListener(DisposeListener)
752 */
753 public void removeDisposeListener(DisposeListener listener) {
754 fShell.removeDisposeListener(listener);
755 }
756
757 /*
758 * @see IInformationControl#setForegroundColor(Color)
759 */
760 public void setForegroundColor(Color foreground) {
761 fContentComposite.setForeground(foreground);
762 }
763
764 /*
765 * @see IInformationControl#setBackgroundColor(Color)
766 */
767 public void setBackgroundColor(Color background) {
768 fContentComposite.setBackground(background);
769 }
770
771 /**
772 * {@inheritDoc}
773 * This method is not intended to be overridden by subclasses.
774 */
775 public bool isFocusControl() {
776 return fShell.getDisplay().getActiveShell() is fShell;
777 }
778
779 /**
780 * This default implementation sets the focus on the popup shell.
781 * Subclasses can override or extend.
782 *
783 * @see IInformationControl#setFocus()
784 */
785 public void setFocus() {
786 bool focusTaken= fShell.setFocus();
787 if (!focusTaken)
788 fShell.forceFocus();
789 }
790
791 /**
792 * {@inheritDoc}
793 * This method is not intended to be overridden by subclasses.
794 */
795 public void addFocusListener(FocusListener listener) {
796 if (fFocusListeners.isEmpty()) {
797 fShellListener= new class() Listener {
798
799 public void handleEvent(Event event) {
800 Object[] listeners= fFocusListeners.getListeners();
801 for (int i= 0; i < listeners.length; i++) {
802 FocusListener focusListener= cast(FocusListener)listeners[i];
803 if (event.type is SWT.Activate) {
804 focusListener.focusGained(new FocusEvent(event));
805 } else {
806 focusListener.focusLost(new FocusEvent(event));
807 }
808 }
809 }
810 };
811 fShell.addListener(SWT.Deactivate, fShellListener);
812 fShell.addListener(SWT.Activate, fShellListener);
813 }
814 fFocusListeners.add(cast(Object)listener);
815 }
816
817 /**
818 * {@inheritDoc}
819 * This method is not intended to be overridden by subclasses.
820 */
821 public void removeFocusListener(FocusListener listener) {
822 fFocusListeners.remove(cast(Object)listener);
823 if (fFocusListeners.isEmpty()) {
824 fShell.removeListener(SWT.Activate, fShellListener);
825 fShell.removeListener(SWT.Deactivate, fShellListener);
826 fShellListener= null;
827 }
828 }
829
830 /**
831 * Sets the text of the status field.
832 * <p>
833 * The default implementation currently only updates the status field when
834 * the popup shell is not visible. The status field can currently only be
835 * shown if the information control has been created with a non-null status
836 * field text.
837 * </p>
838 *
839 * @param statusFieldText the text to be used in the optional status field
840 * or <code>null</code> if the status field should be hidden
841 *
842 * @see org.eclipse.jface.text.IInformationControlExtension4#setStatusText(java.lang.String)
843 */
844 public void setStatusText(String statusFieldText) {
845 if (fStatusLabel !is null && ! getShell().isVisible()) {
846 if (statusFieldText is null ) {
847 fStatusComposite.setVisible(false);
848 } else {
849 fStatusLabel.setText(statusFieldText);
850 fStatusComposite.setVisible(true);
851 }
852 }
853 }
854
855 /*
856 * @see org.eclipse.jface.text.IInformationControlExtension5#containsControl(org.eclipse.swt.widgets.Control)
857 */
858 public bool containsControl(Control control) {
859 do {
860 if (control is fShell)
861 return true;
862 if (cast(Shell)control )
863 return false;
864 control= control.getParent();
865 } while (control !is null);
866 return false;
867 }
868
869 /*
870 * @see org.eclipse.jface.text.IInformationControlExtension5#isVisible()
871 */
872 public bool isVisible() {
873 return fShell !is null && !fShell.isDisposed() && fShell.isVisible();
874 }
875
876 /**
877 * {@inheritDoc}
878 * This default implementation returns <code>null</code>. Subclasses may override.
879 */
880 public IInformationControlCreator getInformationPresenterControlCreator() {
881 return null;
882 }
883
884 /**
885 * Computes the size constraints based on the
886 * {@link JFaceResources#getDialogFont() dialog font}. Subclasses can
887 * override or extend.
888 *
889 * @see org.eclipse.jface.text.IInformationControlExtension5#computeSizeConstraints(int, int)
890 */
891 public Point computeSizeConstraints(int widthInChars, int heightInChars) {
892 GC gc= new GC(fContentComposite);
893 gc.setFont(JFaceResources.getDialogFont());
894 int width= gc.getFontMetrics().getAverageCharWidth();
895 int height= gc.getFontMetrics().getHeight();
896 gc.dispose();
897
898 return new Point(widthInChars * width, heightInChars * height);
899 }
900
901 }