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