blob: 307c2f672f961929a529c593775053d98d4c51ad [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011 Google, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Google, Inc. - initial API and implementation
*******************************************************************************/
package org.eclipse.wb.internal.core.utils.ui.dialogs;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.plugin.AbstractUIPlugin;
/**
* {@link Dialog} that remembers location/size between usage sessions.
*
* @author scheglov_ke
* @coverage core.ui
*/
public abstract class ResizableDialog extends Dialog {
/**
* Key for accessing {@link Dialog} from its {@link Shell}.
*/
public static final String KEY_DIALOG = "KEY_DIALOG";
////////////////////////////////////////////////////////////////////////////
//
// Internal constants
//
////////////////////////////////////////////////////////////////////////////
private static final String X = "x";
private static final String Y = "y";
private static final String WIDTH = "width";
private static final String HEIGHT = "height";
////////////////////////////////////////////////////////////////////////////
//
// Instance fields
//
////////////////////////////////////////////////////////////////////////////
private final AbstractUIPlugin m_plugin;
////////////////////////////////////////////////////////////////////////////
//
// Constructor
//
////////////////////////////////////////////////////////////////////////////
public ResizableDialog(Shell parentShell, AbstractUIPlugin plugin) {
super(parentShell);
m_plugin = plugin;
setShellStyle(getShellStyle() | SWT.RESIZE | SWT.MAX);
}
////////////////////////////////////////////////////////////////////////////
//
// Size
//
////////////////////////////////////////////////////////////////////////////
@Override
protected Point getInitialSize() {
// track the current dialog bounds
installDialogBoundsTracker();
// answer the size from the previous incarnation
Point defaultSize = getDefaultSize();
if ((getShellStyle() & SWT.RESIZE) != 0) {
Rectangle oldBounds = loadBounds();
if (oldBounds != null) {
Rectangle displayBounds = getShell().getDisplay().getBounds();
int width = Math.min(displayBounds.width, Math.max(oldBounds.width, defaultSize.x));
int height = Math.min(displayBounds.height, Math.max(oldBounds.height, defaultSize.y));
return new Point(width, height);
}
}
// use default size
return defaultSize;
}
/**
* @return the default size of dialog.
*/
protected Point getDefaultSize() {
return super.getInitialSize();
}
////////////////////////////////////////////////////////////////////////////
//
// Location
//
////////////////////////////////////////////////////////////////////////////
@Override
protected Point getInitialLocation(Point initialSize) {
Rectangle windowBounds;
{
Shell windowShell = m_plugin.getWorkbench().getActiveWorkbenchWindow().getShell();
windowBounds = windowShell.getBounds();
}
// answer the location from the previous incarnation
Rectangle bounds = loadBounds();
if (bounds != null) {
int x = bounds.x;
int y = bounds.y;
int maxX = windowBounds.x + windowBounds.width - initialSize.x;
int maxY = windowBounds.y + windowBounds.height - initialSize.y;
if (x > maxX) {
x = maxX;
}
if (y > maxY) {
y = maxY;
}
if (x < windowBounds.x) {
x = windowBounds.x;
}
if (y < windowBounds.y) {
y = windowBounds.y;
}
return new Point(x, y);
}
// default location - centered on workbench window
int x = windowBounds.x + (windowBounds.width - initialSize.x) / 2;
int y = windowBounds.y + (windowBounds.height - initialSize.y) / 2;
return new Point(x, y);
}
////////////////////////////////////////////////////////////////////////////
//
// Bounds
//
////////////////////////////////////////////////////////////////////////////
/**
* Loads bounds from {@link IDialogSettings}.
*/
private Rectangle loadBounds() {
IDialogSettings settings = getDialogSettings();
try {
return new Rectangle(settings.getInt(X),
settings.getInt(Y),
settings.getInt(WIDTH),
settings.getInt(HEIGHT));
} catch (NumberFormatException e) {
return null;
}
}
/**
* Saves bounds to {@link IDialogSettings}.
*/
private void saveBounds(Rectangle bounds) {
IDialogSettings settings = getDialogSettings();
settings.put(X, bounds.x);
settings.put(Y, bounds.y);
settings.put(WIDTH, bounds.width);
settings.put(HEIGHT, bounds.height);
}
/**
* @return the {@link IDialogSettings} for this dialog with this type.
*/
protected IDialogSettings getDialogSettings() {
IDialogSettings settings = m_plugin.getDialogSettings();
String sectionName = getDialogSettingsSectionName();
if (settings.getSection(sectionName) == null) {
return settings.addNewSection(sectionName);
}
return settings.getSection(sectionName);
}
/**
* @return the name of section for dialog specific bounds. By default uses name of {@link Class},
* but if same dialog is used for displaying different content, then may be overridden.
*/
protected String getDialogSettingsSectionName() {
return getClass().getName();
}
////////////////////////////////////////////////////////////////////////////
//
// Size tracking
//
////////////////////////////////////////////////////////////////////////////
protected Rectangle cachedBounds;
private void installDialogBoundsTracker() {
getShell().addControlListener(new ControlListener() {
public void controlMoved(ControlEvent e) {
cachedBounds = getShell().getBounds();
}
public void controlResized(ControlEvent e) {
cachedBounds = getShell().getBounds();
}
});
}
@Override
public boolean close() {
boolean shellMaximized = getShell().getMaximized();
boolean closed = super.close();
if (closed && !shellMaximized && cachedBounds != null) {
saveBounds(cachedBounds);
}
return closed;
}
////////////////////////////////////////////////////////////////////////////
//
// Shell
//
////////////////////////////////////////////////////////////////////////////
@Override
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setData(KEY_DIALOG, this);
}
}