/**
* Copyright 2014 the staff of 52°North Initiative for Geospatial Open
* Source Software GmbH in their free time
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package spare.n52.yadarts.themes;
import java.io.FileNotFoundException;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* A convenience class to visually wrap a {@link Control} component
* with a {@link Theme}-based border.
*
* A sub-class of this shall provide the {@link Control} to be wrapped
* via the {@link #createContents(Composite)} method.
*
* <br/>
* <br/>
* Example:
* <br/>
* <br/>
* <code>
*
* new BorderedControlContainer(theShell, SWT.NONE) {<br/>
* @Override<br/>
* protected Control createContents(Composite parent) {<br/>
* Label l = new Label(parent, SWT.NONE);<br/>
* l.setText("HI!!!!!");<br/>
* return l;<br/>
* }<br/>
* };<br/>
* </code>
*
*/
public abstract class BorderedControlContainer extends Composite {
private static final Logger logger = LoggerFactory.getLogger(BorderedControlContainer.class);
private static Shell theShell;
private static Image bgAlt;
private static Image cornerTopLeft;
private static Image cornerTopRight;
private static Image cornerBottomRight;
private static Image cornerBottomLeft;
private static Image borderLeft;
private static Image borderTop;
private static Image borderRight;
private static Image borderBottom;
private boolean imagesLoaded;
private void readImageResources() {
try {
bgAlt = Theme.getCurrentTheme().getBackgroundAlt(getDisplay());
cornerTopLeft = Theme.getCurrentTheme().getCornerTopLeft(getDisplay());
cornerTopRight = rotateImage(cornerTopLeft, 90);
cornerBottomRight = rotateImage(cornerTopRight, 90);
cornerBottomLeft = rotateImage(cornerBottomRight, 90);
borderLeft = Theme.getCurrentTheme().getBorderLeft(getDisplay());
borderTop = Theme.getCurrentTheme().getBorderTop(getDisplay());
borderRight = rotateImage(borderLeft, 180);
borderBottom = rotateImage(borderTop, 180);
} catch (FileNotFoundException e) {
logger.warn(e.getMessage(), e);
}
}
public static void main(String[] args) {
final Display display = Display.getDefault();
theShell = new Shell(display);
theShell.setLayout(new FillLayout());
theShell.setMinimumSize(800, 600);
new BorderedControlContainer(theShell, SWT.NONE) {
@Override
protected Control createContents(Composite parent) {
Label l = new Label(parent, SWT.NONE);
l.setText("HI!°!!!!");
return l;
}
};
theShell.setSize(800, 600);
Rectangle splashBounds = theShell.getBounds();
Rectangle displayBounds = theShell.getDisplay().getPrimaryMonitor()
.getBounds();
int x = (displayBounds.width - splashBounds.width) / 2;
int y = (displayBounds.height - splashBounds.height) / 2;
theShell.setLocation(x, y);
theShell.open();
while (!theShell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
display.dispose();
}
public BorderedControlContainer(Composite parent, int style) {
super(parent, style);
synchronized (BorderedControlContainer.class) {
if (!imagesLoaded) {
readImageResources();
imagesLoaded = true;
}
}
initLayout();
}
private void initLayout() {
GridLayout layout = new GridLayout(3, false);
layout.horizontalSpacing = 0;
layout.verticalSpacing = 0;
layout.marginHeight = 0;
layout.marginWidth = 0;
layout.marginTop = 0;
layout.marginLeft = 0;
layout.marginRight = 0;
layout.marginBottom = 0;
this.setLayout(layout);
/*
* top row
*/
Label topLeft = new Label(this, SWT.NONE);
topLeft.setImage(cornerTopLeft);
Label top = new Label(this, SWT.NONE);
top.setBackgroundImage(borderTop);
// top.setBackground(new Color(shell.getDisplay(), new RGB(0, 255, 0)));
GridData gd = new GridData(SWT.FILL, SWT.FILL, true, false);
top.setLayoutData(gd);
Label topRight = new Label(this, SWT.NONE);
topRight.setImage(cornerTopRight);
/*
* mid row
*/
Control midLeft = new Label(this, SWT.NONE);
midLeft.setBackgroundImage(borderLeft);
gd = new GridData(SWT.FILL, SWT.FILL, false, true);
midLeft.setLayoutData(gd);
Control mid = createContents(this);
mid.setBackgroundImage(bgAlt);
gd = new GridData(SWT.FILL, SWT.FILL, true, true);
mid.setLayoutData(gd);
Label midRight = new Label(this, SWT.NONE);
gd = new GridData(SWT.FILL, SWT.FILL, false, true);
midRight.setBackgroundImage(borderRight);
midRight.setLayoutData(gd);
/*
* bottom row
*/
Label bottomLeft = new Label(this, SWT.NONE);
bottomLeft.setImage(cornerBottomLeft);
Label bottom = new Label(this, SWT.NONE);
bottom.setImage(borderBottom);
bottom.setBackgroundImage(borderBottom);
gd = new GridData(SWT.FILL, SWT.FILL, true, false);
bottom.setLayoutData(gd);
Label bottomRight = new Label(this, SWT.NONE);
bottomRight.setImage(cornerBottomRight);
this.pack();
}
protected abstract Control createContents(Composite parent);
private Image rotateImage(Image src, int angle) {
int rotateType;
switch (angle) {
case 90:
rotateType = SWT.RIGHT;
break;
case 180:
rotateType = SWT.DOWN;
break;
case 270:
rotateType = SWT.LEFT;
break;
default:
rotateType = SWT.RIGHT;
break;
}
return new Image(this.getDisplay(), rotate(src.getImageData(),
rotateType));
}
static ImageData rotate(ImageData srcData, int direction) {
int bytesPerPixel = srcData.bytesPerLine / srcData.width;
int destBytesPerLine = (direction == SWT.DOWN) ? srcData.width
* bytesPerPixel : srcData.height * bytesPerPixel;
byte[] newData = new byte[(direction == SWT.DOWN) ? srcData.height
* destBytesPerLine : srcData.width * destBytesPerLine];
int width = 0, height = 0;
for (int srcY = 0; srcY < srcData.height; srcY++) {
for (int srcX = 0; srcX < srcData.width; srcX++) {
int destX = 0, destY = 0, destIndex = 0, srcIndex = 0;
switch (direction) {
case SWT.LEFT: // left 90 degrees
destX = srcY;
destY = srcData.width - srcX - 1;
width = srcData.height;
height = srcData.width;
break;
case SWT.RIGHT: // right 90 degrees
destX = srcData.height - srcY - 1;
destY = srcX;
width = srcData.height;
height = srcData.width;
break;
case SWT.DOWN: // 180 degrees
destX = srcData.width - srcX - 1;
destY = srcData.height - srcY - 1;
width = srcData.width;
height = srcData.height;
break;
}
destIndex = (destY * destBytesPerLine) + (destX * bytesPerPixel);
srcIndex = (srcY * srcData.bytesPerLine) + (srcX * bytesPerPixel);
System.arraycopy(srcData.data, srcIndex, newData, destIndex,
bytesPerPixel);
}
}
// destBytesPerLine is used as scanlinePad to ensure that no padding is
// required
return new ImageData(width, height, srcData.depth, srcData.palette,
srcData.scanlinePad, newData);
}
}