/*******************************************************************************
* Copyright (c) 2008 Laurent Muller and others.
* 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:
* IBM Corporation - initial API and implementation
* Laurent Muller - updated API
*******************************************************************************/
package nu.bibi.breadcrumb;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
/**
* @author Laurent Muller
* @version 1.0
*/
class SizeGrip extends Canvas {
/*
* The default width
*/
private static final int WIDTH = 13;
/*
* The default height
*/
private static final int HEIGHT = 13;
/*
* the right to left flag
*/
private final boolean rightToLeft;
/*
* The resize cursor
*/
private final Cursor cursor;
/*
* The mouse down flag
*/
private boolean down;
/*
* The mouse down location
*/
private Point mouseDownOffset;
/*
* The minimum shell size
*/
private Point minimumSize;
/*
* The maximum size
*/
private Point maximumSize;
/**
* Constructs a new instance of this class given its parent and a style
* value describing its behavior and appearance.
*
* @param parent
* a composite control which will be the parent of the new
* instance (cannot be null)
* @param style
* the style of control to construct
*/
public SizeGrip(final Composite parent, final int style) {
super(parent, style | SWT.DOUBLE_BUFFERED);
rightToLeft = (style & SWT.RIGHT_TO_LEFT) != 0;
final int cursorStyle = rightToLeft ? SWT.CURSOR_SIZESW
: SWT.CURSOR_SIZESE;
cursor = new Cursor(parent.getDisplay(), cursorStyle);
setCursor(cursor);
final Shell shell = parent.getShell();
addListener(SWT.Paint, new Listener() {
@Override
public void handleEvent(final Event event) {
if (!shell.getMaximized()) {
onPaint(event);
}
}
});
addListener(SWT.Dispose, new Listener() {
@Override
public void handleEvent(final Event event) {
if (cursor != null && !cursor.isDisposed()) {
cursor.dispose();
}
}
});
addListener(SWT.MouseDown, new Listener() {
@Override
public void handleEvent(final Event event) {
if (event.button == 1 && !shell.getMaximized()) {
down = true;
mouseDownOffset = new Point(event.x, event.y);
}
}
});
addListener(SWT.MouseUp, new Listener() {
@Override
public void handleEvent(final Event event) {
down = false;
}
});
addListener(SWT.MouseMove, new Listener() {
@Override
public void handleEvent(final Event event) {
if (!down) {
return;
}
final Point size = shell.getSize();
int newX = size.x + event.x - mouseDownOffset.x;
int newY = size.y + event.y - mouseDownOffset.y;
if (minimumSize != null) {
newX = Math.max(newX, minimumSize.x);
newY = Math.max(newY, minimumSize.y);
}
if (maximumSize != null) {
newX = Math.min(newX, maximumSize.x);
newY = Math.min(newY, maximumSize.y);
}
if (newX != size.x || newY != size.y) {
if (rightToLeft) {
final Rectangle bounds = shell.getBounds();
final int dx = newX - size.x;
final int dy = newY - size.y;
bounds.x -= dx;
bounds.width += dx;
bounds.height += dy;
shell.setBounds(bounds);
} else {
shell.setSize(newX, newY);
}
}
}
});
}
/*
* (non-Javadoc)
* @see org.eclipse.swt.widgets.Composite#computeSize(int, int, boolean)
*/
@Override
public Point computeSize(int wHint, int hHint, final boolean changed) {
checkWidget();
if (wHint == SWT.DEFAULT) {
wHint = WIDTH;
}
if (hHint == SWT.DEFAULT) {
hHint = HEIGHT;
}
return new Point(wHint, hHint);
}
/**
* Returns the maximum shell size allowed.
*
* @return the maximum shell size allowed.
*/
public Point getMaximumSize() {
return maximumSize;
}
/**
* Returns the minimum shell size allowed.
*
* @return the minimum shell size allowed.
*/
public Point getMinimumSize() {
return minimumSize;
}
/**
* Sets the maximum shell size allowed.
*
* @param maximumSize
* the maximum shell size allowed to set.
*/
public void setMaximumSize(final Point maximumSize) {
this.maximumSize = maximumSize;
}
/**
* Sets the minimum shell size allowed.
*
* @param minimumSize
* the minimum shell size allowed to set.
*/
public void setMinimumSize(final Point minimumSize) {
this.minimumSize = minimumSize;
}
/**
* Handles the paint event.
*
* @param event
* the event containing data for the paint event.
*/
protected void onPaint(final Event event) {
final Rectangle r = getClientArea();
if (r.width <= 0 || r.height <= 0) {
return;
}
final GC gc = event.gc;
final Display display = event.display;
final Color shadow = display
.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
final Color highlight = display
.getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW);
final int right = r.x + r.width;
final int bottom = r.y + r.height;
gc.setBackground(highlight);
gc.fillRectangle(right - 3, bottom - 3, 2, 2);
gc.fillRectangle(right - 7, bottom - 3, 2, 2);
gc.fillRectangle(right - 11, bottom - 3, 2, 2);
gc.fillRectangle(right - 3, bottom - 7, 2, 2);
gc.fillRectangle(right - 7, bottom - 7, 2, 2);
gc.fillRectangle(right - 3, bottom - 11, 2, 2);
gc.setBackground(shadow);
gc.fillRectangle(right - 4, bottom - 4, 2, 2);
gc.fillRectangle(right - 8, bottom - 4, 2, 2);
gc.fillRectangle(right - 12, bottom - 4, 2, 2);
gc.fillRectangle(right - 4, bottom - 8, 2, 2);
gc.fillRectangle(right - 8, bottom - 8, 2, 2);
gc.fillRectangle(right - 4, bottom - 12, 2, 2);
}
}