/*******************************************************************************
* Copyright (c) 2012, 2015 IBM Corporation 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
* Marc-Andre Laperle (Ericsson) - Bug 463245
******************************************************************************/
package org.eclipse.e4.ui.widgets;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Image;
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.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ToolBar;
public class ImageBasedFrame extends Canvas {
//TODO: Change to the public after API freeze
private static final String HANDLE_IMAGE= "handleImage"; //$NON-NLS-1$
private static final String FRAME_IMAGE= "frameImage"; //$NON-NLS-1$
private Control framedControl;
private boolean draggable = true;
private boolean vertical = true;
private int w1;
private int w2;
private int w3;
private int h1;
private int h2;
private int h3;
private Image imageCache;
private Image handle;
private int handleWidth;
private int handleHeight;
protected String id;
public ImageBasedFrame(Composite parent, Control toWrap, boolean vertical,
boolean draggable) {
super(parent, SWT.NONE);
this.framedControl = toWrap;
this.vertical = vertical;
this.draggable = draggable;
addPaintListener(new PaintListener() {
@Override
public void paintControl(PaintEvent e) {
drawFrame(e);
}
});
addListener(SWT.MouseExit, new Listener() {
@Override
public void handleEvent(Event event) {
ImageBasedFrame frame = (ImageBasedFrame) event.widget;
frame.setCursor(null);
}
});
addMouseMoveListener(new MouseMoveListener() {
@Override
public void mouseMove(MouseEvent e) {
// Compute the display location for the handle
// Note that this is an empty rect if !draggable
Rectangle handleRect = getHandleRect();
ImageBasedFrame frame = (ImageBasedFrame) e.widget;
if (handleRect.contains(e.x, e.y)) {
frame.setCursor(frame.getDisplay().getSystemCursor(
SWT.CURSOR_SIZEALL));
} else {
frame.setCursor(null);
}
}
});
toWrap.setParent(this);
toWrap.pack(true);
toWrap.addControlListener(new ControlListener() {
@Override
public void controlResized(ControlEvent e) {
pack(true);
}
@Override
public void controlMoved(ControlEvent e) {
// Bug 463245 - The framed control should always stay at the same location
setFramedControlLocation();
}
});
setFramedControlLocation();
setSize(computeSize(-1, -1));
if (toWrap instanceof ToolBar) {
id = "TB";// ((ToolBar) toWrap).getItem(0).getToolTipText(); //$NON-NLS-1$
}
}
private void setFramedControlLocation() {
if (vertical) {
framedControl.setLocation(w1, h1 + handleHeight);
} else {
framedControl.setLocation(w1 + handleWidth, h1);
}
}
public Rectangle getHandleRect() {
Rectangle handleRect = new Rectangle(0, 0, 0, 0);
if (!draggable || handle.isDisposed())
return handleRect;
if (vertical) {
handleRect.x = w1;
handleRect.y = h1;
handleRect.width = framedControl.getSize().x;
handleRect.height = handle.getBounds().height;
} else {
handleRect.x = w1;
handleRect.y = h1;
handleRect.width = handle.getBounds().width;
handleRect.height = framedControl.getSize().y;
}
return handleRect;
}
@Override
public Point computeSize(int wHint, int hHint) {
if (framedControl == null || framedControl.isDisposed())
return new Point(0, 0);
if (vertical) {
int width = w1 + framedControl.getSize().x + w3;
int height = h1 + handleHeight + framedControl.getSize().y + h3;
return new Point(width, height);
} else {
int width = w1 + handleWidth + framedControl.getSize().x + w3;
int height = h1 + framedControl.getSize().y + h3;
return new Point(width, height);
}
}
protected void drawFrame(PaintEvent e) {
if (handle.isDisposed() || (imageCache != null && imageCache.isDisposed())) {
reskin(SWT.NONE);
return;
}
if (framedControl == null || framedControl.isDisposed())
return;
Point inner = framedControl.getSize();
int handleWidth = (handle != null && !vertical) ? handle.getBounds().width
: 0;
int handleHeight = (handle != null && vertical) ? handle.getBounds().height
: 0;
Rectangle srcRect = new Rectangle(0, 0, 0, 0);
Rectangle dstRect = new Rectangle(0, 0, 0, 0);
// Top Left
srcRect.x = 0;
srcRect.y = 0;
srcRect.width = w1;
srcRect.height = h1;
dstRect.x = 0;
dstRect.y = 0;
dstRect.width = w1;
dstRect.height = h1;
e.gc.drawImage(imageCache, srcRect.x, srcRect.y, srcRect.width,
srcRect.height, dstRect.x, dstRect.y, dstRect.width,
dstRect.height);
// Top Rail
srcRect.x = w1;
srcRect.y = 0;
srcRect.width = w2;
srcRect.height = h1;
dstRect.x = w1;
dstRect.y = 0;
dstRect.width = inner.x + handleWidth;
dstRect.height = h1;
e.gc.drawImage(imageCache, srcRect.x, srcRect.y, srcRect.width,
srcRect.height, dstRect.x, dstRect.y, dstRect.width,
dstRect.height);
// handle (if vertical)
if (handleHeight > 0) {
srcRect.x = 0;
srcRect.y = 0;
srcRect.width = handle.getBounds().width;
srcRect.height = handle.getBounds().height;
dstRect.x = w1;
dstRect.y = h1;
dstRect.width = inner.x;
dstRect.height = handleHeight;
e.gc.drawImage(handle, srcRect.x, srcRect.y, srcRect.width,
srcRect.height, dstRect.x, dstRect.y, dstRect.width,
dstRect.height);
}
// Top Right
srcRect.x = w1 + w2;
srcRect.y = 0;
srcRect.width = w3;
srcRect.height = h1;
dstRect.x = w1 + handleWidth + inner.x;
dstRect.y = 0;
dstRect.width = w3;
dstRect.height = h3;
e.gc.drawImage(imageCache, srcRect.x, srcRect.y, srcRect.width,
srcRect.height, dstRect.x, dstRect.y, dstRect.width,
dstRect.height);
// Left Rail
srcRect.x = 0;
srcRect.y = h1;
srcRect.width = w1;
srcRect.height = h2;
dstRect.x = 0;
dstRect.y = h1;
dstRect.width = w1;
dstRect.height = inner.y + handleHeight;
e.gc.drawImage(imageCache, srcRect.x, srcRect.y, srcRect.width,
srcRect.height, dstRect.x, dstRect.y, dstRect.width,
dstRect.height);
// Handle (if horizontal)
if (handleWidth > 0) {
srcRect.x = 0;
srcRect.y = 0;
srcRect.width = handle.getBounds().width;
srcRect.height = handle.getBounds().height;
dstRect.x = w1;
dstRect.y = h1;
dstRect.width = handleWidth;
dstRect.height = inner.y;
e.gc.drawImage(handle, srcRect.x, srcRect.y, srcRect.width,
srcRect.height, dstRect.x, dstRect.y, dstRect.width,
dstRect.height);
}
// Right Rail
srcRect.x = w1 + w2;
srcRect.y = h1;
srcRect.width = w3;
srcRect.height = h2;
dstRect.x = w1 + handleWidth + inner.x;
dstRect.y = h1;
dstRect.width = w3;
dstRect.height = inner.y + handleHeight;
e.gc.drawImage(imageCache, srcRect.x, srcRect.y, srcRect.width,
srcRect.height, dstRect.x, dstRect.y, dstRect.width,
dstRect.height);
// Bottom Left
srcRect.x = 0;
srcRect.y = h1 + h2;
srcRect.width = w1;
srcRect.height = h3;
dstRect.x = 0;
dstRect.y = h1 + handleHeight + inner.y;
dstRect.width = w1;
dstRect.height = h3;
e.gc.drawImage(imageCache, srcRect.x, srcRect.y, srcRect.width,
srcRect.height, dstRect.x, dstRect.y, dstRect.width,
dstRect.height);
// Bottom Rail
srcRect.x = w1;
srcRect.y = h1 + h2;
srcRect.width = w2;
srcRect.height = h3;
dstRect.x = w1;
dstRect.y = h1 + handleHeight + inner.y;
dstRect.width = handleWidth + inner.x;
dstRect.height = h3;
e.gc.drawImage(imageCache, srcRect.x, srcRect.y, srcRect.width,
srcRect.height, dstRect.x, dstRect.y, dstRect.width,
dstRect.height);
// Bottom right
srcRect.x = w1 + w2;
srcRect.y = h1 + h2;
srcRect.width = w3;
srcRect.height = h3;
dstRect.x = w1 + handleWidth + inner.x;
dstRect.y = h1 + handleHeight + inner.y;
dstRect.width = w3;
dstRect.height = h3;
e.gc.drawImage(imageCache, srcRect.x, srcRect.y, srcRect.width,
srcRect.height, dstRect.x, dstRect.y, dstRect.width,
dstRect.height);
// Imterior
srcRect.x = w1;
srcRect.y = h1;
srcRect.width = w2;
srcRect.height = h2;
dstRect.x = w1 + handleWidth;
dstRect.y = h1 + handleHeight;
dstRect.width = inner.x;
dstRect.height = inner.y;
e.gc.drawImage(imageCache, srcRect.x, srcRect.y, srcRect.width,
srcRect.height, dstRect.x, dstRect.y, dstRect.width,
dstRect.height);
}
public Image getImageCache() {
return imageCache;
}
public Image getHandleImage() {
return handle;
}
public void setImages(Image frameImage, Integer[] frameInts,
Image handleImage) {
if (frameImage != null) {
imageCache = frameImage;
setData(FRAME_IMAGE, frameImage);
}
if (handleImage != null) {
handle = handleImage;
setData(HANDLE_IMAGE, handleImage);
}
if (frameInts != null) {
w1 = frameInts[0];
w2 = frameInts[1];
h1 = frameInts[2];
h2 = frameInts[3];
w3 = imageCache.getBounds().width - (w1 + w2);
h3 = imageCache.getBounds().height - (h1 + h2);
}
// Compute the size of the handle in the 'offset' dimension
handleWidth = (handle != null && !vertical) ? handle.getBounds().width
: 0;
handleHeight = (handle != null && vertical) ? handle.getBounds().height
: 0;
if (vertical) {
framedControl.setLocation(w1, h1 + handleHeight);
} else {
framedControl.setLocation(w1 + handleWidth, h1);
}
setSize(computeSize(-1, -1));
}
}