org.eclipse.swt.custom.CBanner Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of org.eclipse.swt.gtk.linux.aarch64 Show documentation
Show all versions of org.eclipse.swt.gtk.linux.aarch64 Show documentation
Standard Widget Toolkit for GTK on aarch64
The newest version!
/*******************************************************************************
* Copyright (c) 2000, 2021 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.swt.custom;
import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
/**
* Instances of this class implement a Composite that lays out its
* children and allows programmatic control of the layout. It draws
* a separator between the left and right children which can be dragged
* to resize the right control.
* CBanner is used in the workbench to layout the toolbar area and
* perspective switching toolbar.
*
* Note that although this class is a subclass of Composite
,
* it does not make sense to set a layout on it.
*
*
* - Styles:
* - NONE
* - Events:
* - (None)
*
*
* IMPORTANT: This class is not intended to be subclassed.
*
*
* @see Sample code and further information
*
* @since 3.0
* @noextend This class is not intended to be subclassed by clients.
*/
public class CBanner extends Composite {
Control left;
Control right;
Control bottom;
boolean simple = true;
int[] curve = new int[0];
int curveStart = 0;
Rectangle curveRect = new Rectangle(0, 0, 0, 0);
int curve_width = 5;
int curve_indent = -2;
int rightWidth = SWT.DEFAULT;
int rightMinWidth = 0;
int rightMinHeight = 0;
Cursor resizeCursor;
boolean dragging = false;
int rightDragDisplacement = 0;
Listener listener;
static final int OFFSCREEN = -200;
static final int BORDER_BOTTOM = 2;
static final int BORDER_TOP = 3;
static final int BORDER_STRIPE = 1;
static final int CURVE_TAIL = 200;
static final int BEZIER_RIGHT = 30;
static final int BEZIER_LEFT = 30;
static final int MIN_LEFT = 10;
static int BORDER1 = SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW;
/**
* Constructs a new instance of this class given its parent
* and a style value describing its behavior and appearance.
*
* The style value is either one of the style constants defined in
* class SWT
which is applicable to instances of this
* class, or must be built by bitwise OR'ing together
* (that is, using the int
"|" operator) two or more
* of those SWT
style constants. The class description
* lists the style constants that are applicable to the class.
* Style bits are also inherited from superclasses.
*
*
* @param parent a widget which will be the parent of the new instance (cannot be null)
* @param style the style of widget to construct
*
* @exception IllegalArgumentException
* - ERROR_NULL_ARGUMENT - if the parent is null
*
* @exception SWTException
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent
*
*/
public CBanner(Composite parent, int style) {
super(parent, checkStyle(style));
super.setLayout(new CBannerLayout());
resizeCursor = getDisplay().getSystemCursor(SWT.CURSOR_SIZEWE);
listener = e -> {
switch (e.type) {
case SWT.Dispose:
onDispose(e); break;
case SWT.MouseDown:
onMouseDown (e.x, e.y); break;
case SWT.MouseExit:
onMouseExit(); break;
case SWT.MouseMove:
onMouseMove(e.x, e.y); break;
case SWT.MouseUp:
onMouseUp(); break;
case SWT.Paint:
onPaint(e.gc); break;
case SWT.Resize:
onResize(); break;
}
};
int[] events = new int[] {SWT.Dispose, SWT.MouseDown, SWT.MouseExit, SWT.MouseMove, SWT.MouseUp, SWT.Paint, SWT.Resize};
for (int event : events) {
addListener(event, listener);
}
}
static int[] bezier(int x0, int y0, int x1, int y1, int x2, int y2, int x3, int y3, int count) {
// The parametric equations for a Bezier curve for x[t] and y[t] where 0 <= t <=1 are:
// x[t] = x0+3(x1-x0)t+3(x0+x2-2x1)t^2+(x3-x0+3x1-3x2)t^3
// y[t] = y0+3(y1-y0)t+3(y0+y2-2y1)t^2+(y3-y0+3y1-3y2)t^3
double a0 = x0;
double a1 = 3*(x1 - x0);
double a2 = 3*(x0 + x2 - 2*x1);
double a3 = x3 - x0 + 3*x1 - 3*x2;
double b0 = y0;
double b1 = 3*(y1 - y0);
double b2 = 3*(y0 + y2 - 2*y1);
double b3 = y3 - y0 + 3*y1 - 3*y2;
int[] polygon = new int[2*count + 2];
for (int i = 0; i <= count; i++) {
double t = (double)i / (double)count;
polygon[2*i] = (int)(a0 + a1*t + a2*t*t + a3*t*t*t);
polygon[2*i + 1] = (int)(b0 + b1*t + b2*t*t + b3*t*t*t);
}
return polygon;
}
static int checkStyle (int style) {
return SWT.NONE;
}
/*
* This class was not intended to be subclassed but this restriction
* cannot be enforced without breaking backward compatibility.
*/
//protected void checkSubclass () {
// String name = getClass ().getName ();
// int index = name.lastIndexOf ('.');
// if (!name.substring (0, index + 1).equals ("org.eclipse.swt.custom.")) {
// SWT.error (SWT.ERROR_INVALID_SUBCLASS);
// }
//}
/**
* Returns the Control that appears on the bottom side of the banner.
*
* @return the control that appears on the bottom side of the banner or null
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*
* @since 3.0
*/
public Control getBottom() {
checkWidget();
return bottom;
}
@Override
public Rectangle getClientArea() {
return new Rectangle(0, 0, 0, 0);
}
/**
* Returns the Control that appears on the left side of the banner.
*
* @return the control that appears on the left side of the banner or null
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*
* @since 3.0
*/
public Control getLeft() {
checkWidget();
return left;
}
/**
* Returns the Control that appears on the right side of the banner.
*
* @return the control that appears on the right side of the banner or null
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*
* @since 3.0
*/
public Control getRight() {
checkWidget();
return right;
}
/**
* Returns the minimum size of the control that appears on the right of the banner.
*
* @return the minimum size of the control that appears on the right of the banner
*
* @since 3.1
*/
public Point getRightMinimumSize() {
checkWidget();
return new Point(rightMinWidth, rightMinHeight);
}
/**
* Returns the width of the control that appears on the right of the banner.
*
* @return the width of the control that appears on the right of the banner
*
* @since 3.0
*/
public int getRightWidth() {
checkWidget();
if (right == null) return 0;
if (rightWidth == SWT.DEFAULT) {
Point size = right.computeSize(SWT.DEFAULT, SWT.DEFAULT, false);
return size.x;
}
return rightWidth;
}
/**
* Returns true
if the CBanner is rendered
* with a simple, traditional shape.
*
* @return true
if the CBanner is rendered with a simple shape
*
* @since 3.0
*/
public boolean getSimple() {
checkWidget();
return simple;
}
void onDispose(Event event) {
removeListener(SWT.Dispose, listener);
notifyListeners(SWT.Dispose, event);
event.type = SWT.None;
resizeCursor = null;
left = null;
right = null;
bottom = null;
}
void onMouseDown (int x, int y) {
if (curveRect.contains(x, y)) {
dragging = true;
rightDragDisplacement = curveStart - x + curve_width - curve_indent;
}
}
void onMouseExit() {
if (!dragging) setCursor(null);
}
void onMouseMove(int x, int y) {
if (dragging) {
Point size = getSize();
if (!(0 < x && x < size.x)) return;
rightWidth = Math.max(0, size.x - x - rightDragDisplacement);
if (rightMinWidth == SWT.DEFAULT) {
Point minSize = right.computeSize(rightMinWidth, rightMinHeight);
rightWidth = Math.max(minSize.x, rightWidth);
} else {
rightWidth = Math.max(rightMinWidth, rightWidth);
}
layout(false);
return;
}
if (curveRect.contains(x, y)) {
setCursor(resizeCursor);
} else {
setCursor(null);
}
}
void onMouseUp () {
dragging = false;
}
void onPaint(GC gc) {
// Useful for debugging paint problems
// {
// Point size = getSize();
// gc.setBackground(getDisplay().getSystemColor(SWT.COLOR_GREEN));
// gc.fillRectangle(-10, -10, size.x+20, size.y+20);
// }
if (left == null && right == null) return;
Point size = getSize();
Color border1 = getDisplay().getSystemColor(BORDER1);
if (bottom != null) {
int y = bottom.getBounds().y - BORDER_STRIPE - 1;
gc.setForeground(border1);
gc.drawLine(0, y, size.x, y);
}
if (left == null || right == null) return;
int[] line1 = new int[curve.length+6];
int index = 0;
int x = curveStart;
line1[index++] = x + 1;
line1[index++] = size.y - BORDER_STRIPE;
for (int i = 0; i < curve.length/2; i++) {
line1[index++]=x+curve[2*i];
line1[index++]=curve[2*i+1];
}
line1[index++] = x + curve_width;
line1[index++] = 0;
line1[index++] = size.x;
line1[index++] = 0;
Color background = getBackground();
if (getDisplay().getDepth() >= 15) {
// Anti- aliasing
int[] line2 = new int[line1.length];
index = 0;
for (int i = 0; i < line1.length/2; i++) {
line2[index] = line1[index++] - 1;
line2[index] = line1[index++];
}
int[] line3 = new int[line1.length];
index = 0;
for (int i = 0; i < line1.length/2; i++) {
line3[index] = line1[index++] + 1;
line3[index] = line1[index++];
}
RGB from = border1.getRGB();
RGB to = background.getRGB();
int red = from.red + 3*(to.red - from.red)/4;
int green = from.green + 3*(to.green - from.green)/4;
int blue = from.blue + 3*(to.blue - from.blue)/4;
Color color = new Color(red, green, blue);
gc.setForeground(color);
gc.drawPolyline(line2);
gc.drawPolyline(line3);
// draw tail fading to background
int x1 = Math.max(0, curveStart - CURVE_TAIL);
gc.setForeground(background);
gc.setBackground(border1);
gc.fillGradientRectangle(x1, size.y - BORDER_STRIPE, curveStart-x1+1, 1, false);
} else {
// draw solid tail
int x1 = Math.max(0, curveStart - CURVE_TAIL);
gc.setForeground(border1);
gc.drawLine(x1, size.y - BORDER_STRIPE, curveStart+1, size.y - BORDER_STRIPE);
}
// draw border
gc.setForeground(border1);
gc.drawPolyline(line1);
}
void onResize() {
updateCurve(getSize().y);
}
/**
* Set the control that appears on the bottom side of the banner.
* The bottom control is optional. Setting the bottom control to null will remove it from
* the banner - however, the creator of the control must dispose of the control.
*
* @param control the control to be displayed on the bottom or null
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
* - ERROR_INVALID_ARGUMENT - if the bottom control was not created as a child of the receiver
*
*
* @since 3.0
*/
public void setBottom(Control control) {
checkWidget();
if (control != null && control.getParent() != this) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
if (bottom != null && !bottom.isDisposed()) {
Point size = bottom.getSize();
bottom.setLocation(OFFSCREEN - size.x, OFFSCREEN - size.y);
}
bottom = control;
layout(false);
}
/**
* Sets the layout which is associated with the receiver to be
* the argument which may be null.
*
* Note: No Layout can be set on this Control because it already
* manages the size and position of its children.
*
*
* @param layout the receiver's new layout or null
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*/
@Override
public void setLayout (Layout layout) {
checkWidget();
return;
}
/**
* Set the control that appears on the left side of the banner.
* The left control is optional. Setting the left control to null will remove it from
* the banner - however, the creator of the control must dispose of the control.
*
* @param control the control to be displayed on the left or null
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
* - ERROR_INVALID_ARGUMENT - if the left control was not created as a child of the receiver
*
*
* @since 3.0
*/
public void setLeft(Control control) {
checkWidget();
if (control != null && control.getParent() != this) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
if (left != null && !left.isDisposed()) {
Point size = left.getSize();
left.setLocation(OFFSCREEN - size.x, OFFSCREEN - size.y);
}
left = control;
layout(false);
}
/**
* Set the control that appears on the right side of the banner.
* The right control is optional. Setting the right control to null will remove it from
* the banner - however, the creator of the control must dispose of the control.
*
* @param control the control to be displayed on the right or null
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
* - ERROR_INVALID_ARGUMENT - if the right control was not created as a child of the receiver
*
*
* @since 3.0
*/
public void setRight(Control control) {
checkWidget();
if (control != null && control.getParent() != this) {
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
}
if (right != null && !right.isDisposed()) {
Point size = right.getSize();
right.setLocation(OFFSCREEN - size.x, OFFSCREEN - size.y);
}
right = control;
layout(false);
}
/**
* Set the minimum height of the control that appears on the right side of the banner.
*
* @param size the minimum size of the control on the right
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
* - ERROR_INVALID_ARGUMENT - if the size is null or the values of size are less than SWT.DEFAULT
*
*
* @since 3.1
*/
public void setRightMinimumSize(Point size) {
checkWidget();
if (size == null || size.x < SWT.DEFAULT || size.y < SWT.DEFAULT) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
rightMinWidth = size.x;
rightMinHeight = size.y;
layout(false);
}
/**
* Set the width of the control that appears on the right side of the banner.
*
* @param width the width of the control on the right
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
* - ERROR_INVALID_ARGUMENT - if width is less than SWT.DEFAULT
*
*
* @since 3.0
*/
public void setRightWidth(int width) {
checkWidget();
if (width < SWT.DEFAULT) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
rightWidth = width;
layout(false);
}
/**
* Sets the shape that the CBanner will use to render itself.
*
* @param simple true
if the CBanner should render itself in a simple, traditional style
*
* @exception SWTException
* - ERROR_WIDGET_DISPOSED - if the receiver has been disposed
* - ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver
*
*
* @since 3.0
*/
public void setSimple(boolean simple) {
checkWidget();
if (this.simple != simple) {
this.simple = simple;
if (simple) {
curve_width = 5;
curve_indent = -2;
} else {
curve_width = 50;
curve_indent = 5;
}
updateCurve(getSize().y);
layout(false);
redraw();
}
}
void updateCurve(int height) {
int h = height - BORDER_STRIPE;
if (simple) {
curve = new int[] {0,h, 1,h, 2,h-1, 3,h-2,
3,2, 4,1, 5,0,};
} else {
curve = bezier(0, h+1, BEZIER_LEFT, h+1,
curve_width-BEZIER_RIGHT, 0, curve_width, 0,
curve_width);
}
}
}