• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*******************************************************************************
2  * Copyright (c) 2011 Google, Inc.
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  *    Google, Inc. - initial API and implementation
10  *******************************************************************************/
11 package org.eclipse.wb.internal.core.utils.ui.dialogs;
12 
13 import org.eclipse.jface.dialogs.Dialog;
14 import org.eclipse.jface.dialogs.IDialogSettings;
15 import org.eclipse.swt.SWT;
16 import org.eclipse.swt.events.ControlEvent;
17 import org.eclipse.swt.events.ControlListener;
18 import org.eclipse.swt.graphics.Point;
19 import org.eclipse.swt.graphics.Rectangle;
20 import org.eclipse.swt.widgets.Shell;
21 import org.eclipse.ui.plugin.AbstractUIPlugin;
22 
23 /**
24  * {@link Dialog} that remembers location/size between usage sessions.
25  *
26  * @author scheglov_ke
27  * @coverage core.ui
28  */
29 public abstract class ResizableDialog extends Dialog {
30   /**
31    * Key for accessing {@link Dialog} from its {@link Shell}.
32    */
33   public static final String KEY_DIALOG = "KEY_DIALOG";
34   ////////////////////////////////////////////////////////////////////////////
35   //
36   // Internal constants
37   //
38   ////////////////////////////////////////////////////////////////////////////
39   private static final String X = "x";
40   private static final String Y = "y";
41   private static final String WIDTH = "width";
42   private static final String HEIGHT = "height";
43   ////////////////////////////////////////////////////////////////////////////
44   //
45   // Instance fields
46   //
47   ////////////////////////////////////////////////////////////////////////////
48   private final AbstractUIPlugin m_plugin;
49 
50   ////////////////////////////////////////////////////////////////////////////
51   //
52   // Constructor
53   //
54   ////////////////////////////////////////////////////////////////////////////
ResizableDialog(Shell parentShell, AbstractUIPlugin plugin)55   public ResizableDialog(Shell parentShell, AbstractUIPlugin plugin) {
56     super(parentShell);
57     m_plugin = plugin;
58     setShellStyle(getShellStyle() | SWT.RESIZE | SWT.MAX);
59   }
60 
61   ////////////////////////////////////////////////////////////////////////////
62   //
63   // Size
64   //
65   ////////////////////////////////////////////////////////////////////////////
66   @Override
getInitialSize()67   protected Point getInitialSize() {
68     // track the current dialog bounds
69     installDialogBoundsTracker();
70     // answer the size from the previous incarnation
71     Point defaultSize = getDefaultSize();
72     if ((getShellStyle() & SWT.RESIZE) != 0) {
73       Rectangle oldBounds = loadBounds();
74       if (oldBounds != null) {
75         Rectangle displayBounds = getShell().getDisplay().getBounds();
76         int width = Math.min(displayBounds.width, Math.max(oldBounds.width, defaultSize.x));
77         int height = Math.min(displayBounds.height, Math.max(oldBounds.height, defaultSize.y));
78         return new Point(width, height);
79       }
80     }
81     // use default size
82     return defaultSize;
83   }
84 
85   /**
86    * @return the default size of dialog.
87    */
getDefaultSize()88   protected Point getDefaultSize() {
89     return super.getInitialSize();
90   }
91 
92   ////////////////////////////////////////////////////////////////////////////
93   //
94   // Location
95   //
96   ////////////////////////////////////////////////////////////////////////////
97   @Override
getInitialLocation(Point initialSize)98   protected Point getInitialLocation(Point initialSize) {
99     Rectangle windowBounds;
100     {
101       Shell windowShell = m_plugin.getWorkbench().getActiveWorkbenchWindow().getShell();
102       windowBounds = windowShell.getBounds();
103     }
104     // answer the location from the previous incarnation
105     Rectangle bounds = loadBounds();
106     if (bounds != null) {
107       int x = bounds.x;
108       int y = bounds.y;
109       int maxX = windowBounds.x + windowBounds.width - initialSize.x;
110       int maxY = windowBounds.y + windowBounds.height - initialSize.y;
111       if (x > maxX) {
112         x = maxX;
113       }
114       if (y > maxY) {
115         y = maxY;
116       }
117       if (x < windowBounds.x) {
118         x = windowBounds.x;
119       }
120       if (y < windowBounds.y) {
121         y = windowBounds.y;
122       }
123       return new Point(x, y);
124     }
125     // default location - centered on workbench window
126     int x = windowBounds.x + (windowBounds.width - initialSize.x) / 2;
127     int y = windowBounds.y + (windowBounds.height - initialSize.y) / 2;
128     return new Point(x, y);
129   }
130 
131   ////////////////////////////////////////////////////////////////////////////
132   //
133   // Bounds
134   //
135   ////////////////////////////////////////////////////////////////////////////
136   /**
137    * Loads bounds from {@link IDialogSettings}.
138    */
loadBounds()139   private Rectangle loadBounds() {
140     IDialogSettings settings = getDialogSettings();
141     try {
142       return new Rectangle(settings.getInt(X),
143           settings.getInt(Y),
144           settings.getInt(WIDTH),
145           settings.getInt(HEIGHT));
146     } catch (NumberFormatException e) {
147       return null;
148     }
149   }
150 
151   /**
152    * Saves bounds to {@link IDialogSettings}.
153    */
saveBounds(Rectangle bounds)154   private void saveBounds(Rectangle bounds) {
155     IDialogSettings settings = getDialogSettings();
156     settings.put(X, bounds.x);
157     settings.put(Y, bounds.y);
158     settings.put(WIDTH, bounds.width);
159     settings.put(HEIGHT, bounds.height);
160   }
161 
162   /**
163    * @return the {@link IDialogSettings} for this dialog with this type.
164    */
getDialogSettings()165   protected IDialogSettings getDialogSettings() {
166     IDialogSettings settings = m_plugin.getDialogSettings();
167     String sectionName = getDialogSettingsSectionName();
168     if (settings.getSection(sectionName) == null) {
169       return settings.addNewSection(sectionName);
170     }
171     return settings.getSection(sectionName);
172   }
173 
174   /**
175    * @return the name of section for dialog specific bounds. By default uses name of {@link Class},
176    *         but if same dialog is used for displaying different content, then may be overridden.
177    */
getDialogSettingsSectionName()178   protected String getDialogSettingsSectionName() {
179     return getClass().getName();
180   }
181 
182   ////////////////////////////////////////////////////////////////////////////
183   //
184   // Size tracking
185   //
186   ////////////////////////////////////////////////////////////////////////////
187   protected Rectangle cachedBounds;
188 
installDialogBoundsTracker()189   private void installDialogBoundsTracker() {
190     getShell().addControlListener(new ControlListener() {
191       public void controlMoved(ControlEvent e) {
192         cachedBounds = getShell().getBounds();
193       }
194 
195       public void controlResized(ControlEvent e) {
196         cachedBounds = getShell().getBounds();
197       }
198     });
199   }
200 
201   @Override
close()202   public boolean close() {
203     boolean shellMaximized = getShell().getMaximized();
204     boolean closed = super.close();
205     if (closed && !shellMaximized && cachedBounds != null) {
206       saveBounds(cachedBounds);
207     }
208     return closed;
209   }
210 
211   ////////////////////////////////////////////////////////////////////////////
212   //
213   // Shell
214   //
215   ////////////////////////////////////////////////////////////////////////////
216   @Override
configureShell(Shell newShell)217   protected void configureShell(Shell newShell) {
218     super.configureShell(newShell);
219     newShell.setData(KEY_DIALOG, this);
220   }
221 }
222