/****************************************************************************
* Copyright (c) 2005-2006 Jeremy Dowdall
* 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:
* Jeremy Dowdall <jeremyd@aspencloud.com> - initial API and implementation
*****************************************************************************/
package org.eclipse.nebula.widgets.ctree;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridLayout;
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.Layout;
import org.eclipse.swt.widgets.Listener;
/**
* <p>
* NOTE: THIS WIDGET AND ITS API ARE STILL UNDER DEVELOPMENT. THIS IS A PRE-RELEASE ALPHA
* VERSION. USERS SHOULD EXPECT API CHANGES IN FUTURE VERSIONS.
* </p>
*/
public class SComposite extends Canvas implements Listener {
/**
* Style setting indicating that Border should NOT be drawn
*/
public static int NONE = 0;
/**
* Style setting indicating that a Border should be drawn
*/
public static int BORDER = 1 << 0;
/**
* Style setting indicating that the Border should be drawn with a Flat appearance,
* otherwise the border will have a subtle raised appearance.
*/
public static int FLAT = 1 << 1;
/**
* Style setting indicating that the Border should be drawn with Square corners,
* otherwise the corners will be rounded.
*/
public static int SQUARE = 1 << 2;
private static Color WHITE = Display.getCurrent().getSystemColor(SWT.COLOR_WHITE);
private Color borderColor;
private int borderStyle;
private int borderWidth;
private Color normalBorderColor;
private boolean advancedGraphics;
/**
* styles:
* default is a Raised Rounded Corner border
* SWT.FLAT - flat
* SWT.SIMPLE - rectangular corners
* @param parent
* @param style
*/
public SComposite(Composite parent) {
this(parent, SWT.NONE);
}
public SComposite(Composite parent, int style) {
super(parent, SWT.NONE);
borderStyle = style;
borderWidth = 0;
updateBackground();
setBackground(parent.getBackground());
// setup graphics support
GC gc = new GC(Display.getCurrent());
gc.setAdvanced(true);
advancedGraphics = gc.getAdvanced();
gc.dispose();
setLayout(new GridLayout());
setMargins(0,0);
addListener(SWT.Paint, this);
}
public int getBorderStyle() {
return borderStyle;
}
public int getBorderWidth() {
return borderWidth;
}
public void handleEvent(Event event) {
if(event.type == SWT.Paint) {
paintControl(event.gc);
}
}
private void paintControl(GC gc) {
if((borderStyle & BORDER) != 0) {
if(advancedGraphics) {
gc.setAntialias(SWT.ON);
}
gc.setLineWidth(borderWidth);
Rectangle r = getClientArea();
if((borderStyle & SQUARE) != 0) {
if((borderStyle & FLAT) == 0) {
gc.setForeground(WHITE);
gc.drawLine(r.x+1,r.y+1, r.x+1,r.y+r.height-3);
gc.drawLine(r.x+1,r.y+1, r.x+r.width-3,r.y+1);
}
gc.setForeground(borderColor);
gc.drawRectangle(r.x,r.y, r.width-1,r.height-1);
} else {
if((borderStyle & FLAT) == 0) {
gc.setForeground(WHITE);
gc.drawLine(r.x+1,r.y+1, r.x+1,r.y+r.height-3);
gc.drawLine(r.x+1,r.y+1, r.x+r.width-3,r.y+1);
}
gc.setForeground(borderColor);
gc.drawRoundRectangle(r.x+(borderWidth/2),r.y+(borderWidth/2), r.width-borderWidth,r.height-borderWidth, borderWidth*5, borderWidth*5);
}
}
}
/**
* The setBackground method of an SComposite does not actually set its own
* background color, as a typical Composite does, but rather the color of its border.
* This enables its parent to set the background color on all child controls with an
* identical call: <code>((Control) child).setBackground(color)</code>, and have the
* SComposite do its job of drawing a color coordinated border.<br />
* To set the actual background of the SComposite, see the <code>updateBackground</code>
* method.
* @see #updateBackground()
* {@inheritDoc}
*/
public void setBackground(Color color) {
if(getBackground().getRGB().equals(color.getRGB())) {
if(normalBorderColor == null) {
normalBorderColor = getDisplay().getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
}
borderColor = normalBorderColor;
} else {
borderColor = color;
}
}
/**
* Convenience method; simply calls setBorderStyle(style) and then setBorderWidth(width).
* @param style
* @param width
* @see #setBorderStyle(int)
* @see #setBorderWidth(int)
*/
public void setBorder(int style, int width) {
setBorderStyle(style);
setBorderWidth(width);
}
/**
* Set the style of border to be drawn.<br />
* If turning the border OFF after it has been ON, the margins may need to be reset.<br />
* Valid Styles:
* <ul>
* <li>NONE (default)</li>
* <li>BORDER</li>
* <li>FLAT</li>
* <li>SQUARE</li>
* </ul>
* @param style
* @see #setMargins(int, int)
*/
public void setBorderStyle(int style) {
if(borderStyle != style) {
borderStyle = style;
updateLayout();
}
}
/**
* Set the line width of the border to be drawn.
* @param width
*/
public void setBorderWidth(int width) {
if(borderWidth != width) {
borderWidth = width;
updateLayout();
}
}
/**
* Sets the layout ONLY if layout is a GridLayout
* and makes sure that there is room for the borders by setting the margins as
* shown below:
* <ol>
* <li>BORDER: (borderWidth+1) pixels all around (arc gets cut otherwise)</li>
* <li>BORDER | FLAT: (borderWidth+1) pixels all around</li>
* <li>BORDER | SQUARE: (borderWidth+1) pixels left & top, borderWidth pixels right & bottom</li>
* <li>BORDER | SQUARE | FLAT: borderWidth pixels all around</li>
* </ol>
*/
public void setLayout(Layout layout) {
if((layout != null) && (layout instanceof GridLayout)) {
super.setLayout(layout);
updateLayout();
}
}
/**
* Set the margin for the layout. Internally this method calls setLayout(layout)
* so that the border is guaranteed to show properly.
* Call this method AFTER setting the border style.
* @param width
* @param height
* @see #setLayout(Layout)
*/
public void setMargins(int width, int height) {
GridLayout layout = (GridLayout) getLayout();
layout.marginWidth = width;
layout.marginHeight = height;
updateLayout();
}
/**
* Set the color of the border to be drawn when the cell is NOT selected.<br />
* @param color
*/
public void setNormalBorderColor(Color color) {
normalBorderColor = color;
}
/**
* This method to sets the actual background of this SComposite
* to match that of its parent. Use when the parent's background has been changed.
*/
public void updateBackground() {
super.setBackground(getParent().getBackground());
}
private void updateLayout() {
GridLayout gridlayout = (GridLayout) getLayout();
if((borderStyle & BORDER) != 0) {
if((borderStyle & SQUARE) != 0) {
if(gridlayout.marginHeight < (borderWidth+1)) {
if(gridlayout.marginTop < (borderWidth+1)) gridlayout.marginTop = (borderWidth+1);
if(gridlayout.marginBottom < (borderWidth+1)) gridlayout.marginBottom = (borderWidth+1);
}
if(gridlayout.marginWidth < (borderWidth+1)) {
if(gridlayout.marginLeft < (borderWidth+1)) gridlayout.marginLeft = (borderWidth+1);
if(gridlayout.marginRight < (borderWidth+1)) gridlayout.marginRight = (borderWidth+1);
}
} else {
if((borderStyle & FLAT) != 0) {
if(gridlayout.marginHeight < borderWidth) {
if(gridlayout.marginTop < borderWidth) gridlayout.marginTop = borderWidth;
if(gridlayout.marginBottom < borderWidth) gridlayout.marginBottom = borderWidth;
}
if(gridlayout.marginWidth < borderWidth) {
if(gridlayout.marginLeft < borderWidth) gridlayout.marginLeft = borderWidth;
if(gridlayout.marginRight < borderWidth) gridlayout.marginRight = borderWidth;
}
} else {
if(gridlayout.marginHeight < (borderWidth+1)) {
if(gridlayout.marginTop < (borderWidth+1)) gridlayout.marginTop = (borderWidth+1);
if(gridlayout.marginBottom < (borderWidth+1)) gridlayout.marginBottom = (borderWidth+1);
}
if(gridlayout.marginWidth < (borderWidth+1)) {
if(gridlayout.marginLeft < (borderWidth+1)) gridlayout.marginLeft = (borderWidth+1);
if(gridlayout.marginRight < (borderWidth+1)) gridlayout.marginRight = (borderWidth+1);
}
}
}
}
}
}