package com.peterhi.ui;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Proxy;
import java.net.URL;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Monitor;
import org.eclipse.swt.widgets.Shell;
import org.jdesktop.core.animation.timing.Animator;
import org.jdesktop.core.animation.timing.TimingSource;
import org.jdesktop.swt.animation.timing.sources.SWTTimingSource;
import com.peterhi.runtime.RT;
import com.peterhi.runtime.Constants;
public final class UI {
public static final int FPS = 60;
public static final int MSPF = Math.round(1000.0f / (float )FPS);
public static final String FMT_MNEMONIC = "{0} (&{1})";
public static final String FMT_FILE_PNG = "{0}{1}.png";
public static final String FMT_FILE_ZIP = "{0}{1}.zip";
public static final String FMT_FILE_TXT = "{0}{1}.txt";
public static final String METHOD_IS_DISPOSED = "isDisposed";
public static final String METHOD_DISPOSE = "dispose";
public static final String PROPERTY_BOUNDS = "bounds";
public static final String PROPERTY_CLIENT_AREA = "clientArea";
public static final class Trims {
public static final Trim window;
public static final Trim tabPane;
static {
Display d = Display.getDefault();
Window win = new Window(d);
FillLayout lay = new FillLayout();
lay.marginWidth = 0;
lay.marginHeight = 0;
lay.spacing = 0;
win.setLayout(lay);
TabPane tab = new TabPane(win, SWT.NONE);
win.setSize(1024, 600);
win.layout();
{
Rect out = getBounds(win, true);
Rect in = getClientArea(win, true);
Trim t = new Trim();
t.left(in.left() - out.left());
t.top(in.top() - out.top());
t.right(out.right() - in.right());
t.bottom(out.bottom() - in.bottom());
window = t.immutable();
}
{
Rect out = getBounds(tab, true);
Rect in = getClientArea(tab, true);
Trim t = new Trim();
t.left(in.left() - out.left());
t.top(in.top() - out.top());
t.right(out.right() - in.right());
t.bottom(out.bottom() - in.bottom());
tabPane = t.immutable();
}
}
}
private static Map<URL, Image[]> images;
private static Map<RGB, Image> splitBarImages;
private static Map<URL, String> texts;
private static Image panelSplitImage;
private static Shell shell;
public static void initialize() {
Display display = Display.getDefault();
TimingSource source = new SWTTimingSource(MSPF, TimeUnit.MILLISECONDS, display);
source.init();
Animator.setDefaultTimingSource(source);
}
public static Rect map(Rect rect, Control from, Control to) {
if (rect == null) {
throw new NullPointerException();
}
Point upperLeft = new Point(rect.left(), rect.top());
if (from != null) {
upperLeft = from.toDisplay(upperLeft);
}
if (to != null) {
upperLeft = to.toControl(upperLeft);
}
Rect value = rect.clone();
value.x(upperLeft.x);
value.y(upperLeft.y);
return value;
}
public static Rect getBounds(Object target) {
return getRectProperty(target, PROPERTY_BOUNDS);
}
public static Rect getBounds(Control control, boolean screen) {
Rect rect = getBounds(control);
if (screen) {
Composite parent = control.getParent();
if (parent == null) {
return rect;
}
rect = map(rect, parent, null);
}
return rect;
}
public static void setBounds(Object target, Rect value, Class<?> type) {
setRectProperty(target, PROPERTY_BOUNDS, value, type);
}
public static void setBounds(Control control, Rect value, boolean screen) {
if (screen) {
Composite parent = control.getParent();
if (parent != null) {
value = map(value, null, parent);
}
}
setBounds(control, value, org.eclipse.swt.graphics.Rectangle.class);
}
public static Rect getClientArea(Object target) {
return getRectProperty(target, PROPERTY_CLIENT_AREA);
}
public static Rect getClientArea(Composite composite, boolean screen) {
Rect rect = getClientArea(composite);
if (screen) {
rect = map(rect, composite, null);
}
return rect;
}
public static Rect getRectProperty(Object owner, String name) {
if (owner == null) {
throw new NullPointerException();
}
if (name == null) {
throw new NullPointerException();
}
if (name.isEmpty()) {
throw new IllegalArgumentException();
}
try {
Object source = RT.get(owner, name);
Rect rect = new Rect(source);
return rect;
} catch (InvocationTargetException ex) {
throw new RuntimeException(ex.getCause());
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
private static void setRectProperty(Object owner, String name, Rect value, Class<?> type) {
if (owner == null) {
throw new NullPointerException();
}
if (name == null) {
throw new NullPointerException();
}
if (type == null) {
throw new NullPointerException();
}
if (name.isEmpty()) {
throw new IllegalArgumentException();
}
try {
Object target = null;
if (value != null) {
target = value.export(type);
}
RT.set(owner, name, target);
} catch (InvocationTargetException ex) {
throw new RuntimeException(ex.getCause());
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
}
}
public static Rect convert(RectangleExpression expression, Rect[] screen) {
if (expression == null) {
throw new NullPointerException();
}
String x = expression.getX();
String y = expression.getY();
String w = expression.getWidth();
String h = expression.getHeight();
if (RT.isEmpty(x)) {
throw new IllegalArgumentException();
}
if (RT.isEmpty(y)) {
throw new IllegalArgumentException();
}
if (RT.isEmpty(w)) {
throw new IllegalArgumentException();
}
if (RT.isEmpty(h)) {
throw new IllegalArgumentException();
}
Double.parseDouble(x);
Double.parseDouble(y);
Double.parseDouble(w);
Double.parseDouble(h);
boolean ptr = false;
boolean val = false;
if (screen != null) {
if (screen.length > 0) {
ptr = true;
if (screen[0] != null) {
val = true;
}
}
}
Rect ref;
if (val) {
ref = screen[0];
} else {
Display d = Display.getDefault();
Point cur = d.getCursorLocation();
Monitor[] mons = d.getMonitors();
Monitor mon = null;
for (int i = 0; i < mons.length; i++) {
Rectangle rt = mons[i].getBounds();
if (rt.contains(cur)) {
mon = mons[i];
break;
}
}
Object target = mon;
if (target == null) {
target = d;
}
ref = getClientArea(target);
}
if (ptr) {
screen[0] = ref;
}
Rect rt = new Rect();
int n;
float f;
if (x.startsWith("-")) {
try {
n = -Integer.parseInt(x);
} catch (NumberFormatException ex) {
f = -Float.parseFloat(x);
f *= ref.width();
n = Math.round(f);
}
rt.left(ref.right() - n);
} else {
try {
n = Integer.parseInt(x);
} catch (NumberFormatException ex) {
f = Float.parseFloat(x);
f *= ref.width();
n = Math.round(f);
}
rt.left(ref.left() + n);
}
if (y.startsWith("-")) {
try {
n = -Integer.parseInt(y);
} catch (NumberFormatException ex) {
f = -Float.parseFloat(y);
f *= ref.height();
n = Math.round(f);
}
rt.top(ref.bottom() - n);
} else {
try {
n = Integer.parseInt(y);
} catch (NumberFormatException ex) {
f = Float.parseFloat(y);
f *= ref.height();
n = Math.round(f);
}
rt.top(ref.top() + n);
}
if (w.startsWith("-")) {
try {
n = -Integer.parseInt(w);
} catch (NumberFormatException ex) {
f = -Float.parseFloat(w);
f *= ref.width();
n = Math.round(f);
}
rt.right(rt.left());
rt.left(rt.right() - n);
} else {
try {
n = Integer.parseInt(w);
} catch (NumberFormatException ex) {
f = Float.parseFloat(w);
f *= ref.width;
n = Math.round(f);
}
rt.right(rt.left() + n);
}
if (h.startsWith("-")) {
try {
n = -Integer.parseInt(h);
} catch (NumberFormatException ex) {
f = -Float.parseFloat(h);
f *= ref.height;
n = Math.round(f);
}
rt.bottom(rt.top());
rt.top(rt.bottom() - n);
} else {
try {
n = Integer.parseInt(h);
} catch (NumberFormatException ex) {
f = Float.parseFloat(h);
f *= ref.height;
n = Math.round(f);
}
rt.bottom(rt.top() + n);
}
return rt;
}
public static boolean isDisposed(Object target) {
if (target == null) {
return true;
}
try {
return (Boolean )RT.call(target, "isDisposed");
} catch (RuntimeException ex) {
throw ex;
} catch (InvocationTargetException ex) {
throw new RuntimeException(ex.getCause());
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
public static boolean dispose(Object target) {
if (isDisposed(target)) {
return false;
}
try {
RT.call(target, "dispose");
return true;
} catch (RuntimeException ex) {
throw ex;
} catch (InvocationTargetException ex) {
throw new RuntimeException(ex.getCause());
} catch (Exception ex) {
throw new RuntimeException(ex);
}
}
public static Rectangle untrim(Composite composite, Rectangle bounds) {
if (composite == null) {
throw new NullPointerException();
}
if (bounds == null) {
bounds = composite.getBounds();
}
Rectangle trimBounds = composite.computeTrim(bounds.x, bounds.y, bounds.width, bounds.height);
int left = bounds.x + (bounds.x - trimBounds.x);
int top = bounds.y + (bounds.y - trimBounds.y);
int width = bounds.width - (bounds.x - trimBounds.x) - ((trimBounds.x + trimBounds.width) - (bounds.x + bounds.width));
int height = bounds.height - (bounds.y - trimBounds.y) - ((trimBounds.y + trimBounds.height) - (bounds.y + bounds.height));
return new Rectangle(left, top, width, height);
}
public static void destroy() {
TimingSource source = Animator.getDefaultTimingSource();
Animator.setDefaultTimingSource(null);
source.dispose();
if (images != null) {
for (Image[] array : images.values()) {
for (Image image : array) {
if (image != null && !image.isDisposed()) {
image.dispose();
}
}
}
images = null;
}
if (panelSplitImage != null && !panelSplitImage.isDisposed()) {
panelSplitImage.dispose();
}
}
public static Image getSplitBarImage(Color color) {
Display display = Display.getDefault();
RGB rgb = color.getRGB();
Image newImage = getSplitBarImages().get(rgb);
if (newImage == null || newImage.isDisposed()) {
Color low = display.getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW);
Color high = display.getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW);
Image refImage = UIImageResource.T.closeNormal10();
ImageData refData = refImage.getImageData();
ImageData newData = new ImageData(4, 4, refData.depth, refData.palette);
newData.transparentPixel = color.getRGB().hashCode();
newImage = new Image(display, newData);
GC gc = new GC(newImage);
Color old = gc.getBackground();
gc.setBackground(color);
gc.fillRectangle(newImage.getBounds());
gc.setBackground(low);
gc.fillRectangle(0, 0, 1, 1);
gc.fillRectangle(2, 2, 1, 1);
gc.setBackground(high);
gc.fillRectangle(1, 1, 1, 1);
gc.fillRectangle(3, 3, 1, 1);
gc.setBackground(old);
gc.dispose();
}
return newImage;
}
public static Image getSplitBarImage() {
Display display = Display.getDefault();
int cr = SWT.COLOR_WIDGET_BACKGROUND;
Color color = display.getSystemColor(cr);
return getSplitBarImage(color);
}
public static String getText(URL url) throws IOException {
if (url == null) {
throw new NullPointerException();
}
String text = getTexts().get(url);
if (text == null || text.isEmpty()) {
InputStream stream = url.openStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
StringBuilder builder = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null) {
builder.append(line);
builder.append('\n');
}
text = builder.toString();
getTexts().put(url, text);
}
return text;
}
public static Image[] getImages(URL url) throws IOException {
if (url == null) {
throw new NullPointerException();
}
Display display = Display.getDefault();
Image[] images = getImages().get(url);
if (images != null) {
boolean disposed = false;
for (Image item : images) {
if (item == null || item.isDisposed()) {
disposed = true;
}
}
if (disposed) {
for (Image item : images) {
if (item != null && !item.isDisposed()) {
item.dispose();
}
}
images = null;
}
}
if (images == null) {
String name = url.getFile().toLowerCase();
if (name.endsWith(Constants.EXTENSION_PNG)) {
InputStream inputStream = new BufferedInputStream(url.openStream());
images = new Image[] { new Image(display, inputStream) };
} else if (name.endsWith(Constants.EXTENSION_ZIP)) {
SortedMap<String, Image> map = new TreeMap<String, Image>();
ZipInputStream inputStream = new ZipInputStream(new BufferedInputStream(url.openStream()));
ZipEntry entry = null;
while ((entry = inputStream.getNextEntry()) != null) {
name = entry.getName();
if (name.endsWith(Constants.EXTENSION_PNG)) {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] buffer = new byte[Constants.SIZE_FILE_BUFFER];
int read = -1;
while ((read = inputStream.read(buffer)) >= 0) {
outputStream.write(buffer, 0, read);
}
Image image = new Image(display, new ByteArrayInputStream(outputStream.toByteArray()));
map.put(name, image);
}
inputStream.closeEntry();
}
inputStream.close();
images = map.values().toArray(new Image[map.size()]);
} else {
throw new IllegalArgumentException();
}
getImages().put(url, images);
}
return images;
}
public static <T extends ImageResource> T getResourceImage(Class<T> type) {
if (type == null) {
throw new NullPointerException();
}
InvocationHandler invocationHandler = new ImageResourceInvocationHandler(type);
Class<?>[] interfaces = new Class<?>[] { type };
ClassLoader loader = type.getClassLoader();
Object object = Proxy.newProxyInstance(loader, interfaces, invocationHandler);
return type.cast(object);
}
public static <T extends TextResource> T getResourceText(Class<T> type) {
if (type == null) {
throw new NullPointerException();
}
InvocationHandler invocationHandler = new TextResourceInvocationHandler(type);
Class<?>[] interfaces = new Class<?>[] { type };
ClassLoader loader = type.getClassLoader();
Object object = Proxy.newProxyInstance(loader, interfaces, invocationHandler);
return type.cast(object);
}
public static Point toDisplay(Control control, Point point) {
if (point == null) {
throw new NullPointerException();
}
if (control == null) {
return point;
}
if (control.isDisposed()) {
throw new IllegalArgumentException();
}
return control.toDisplay(point);
}
public static Rectangle toDisplay(Control control, Rectangle rect) {
if (rect == null) {
throw new NullPointerException();
}
if (control == null) {
return rect;
}
if (control.isDisposed()) {
throw new IllegalArgumentException();
}
Point point = new Point(rect.x, rect.y);
point = UI.toDisplay(control, point);
return new Rectangle(point.x, point.y, rect.width, rect.height);
}
public static Point toControl(Control control, Point point) {
if (point == null) {
throw new NullPointerException();
}
if (control == null) {
return point;
}
if (control.isDisposed()) {
throw new IllegalArgumentException();
}
return control.toControl(point);
}
public static Rectangle toControl(Control control, Rectangle rect) {
if (rect == null) {
throw new NullPointerException();
}
if (control == null) {
return rect;
}
if (control.isDisposed()) {
throw new IllegalArgumentException();
}
Point point = new Point(rect.x, rect.y);
point = UI.toControl(control, point);
return new Rectangle(point.x, point.y, rect.width, rect.height);
}
public static Rectangle getDisplayBounds(Control control) {
if (control == null) {
throw new NullPointerException();
}
if (control.isDisposed()) {
throw new IllegalArgumentException();
}
Composite parent = control.getParent();
Rectangle bounds = control.getBounds();
return UI.toDisplay(parent, bounds);
}
public static Point mapLocation(Control from, Control to, Point point) {
if (point == null) {
throw new NullPointerException();
}
return UI.toControl(to, UI.toDisplay(from, point));
}
public static Rectangle mapBounds(Control from, Control to, Rectangle rect) {
if (rect == null) {
throw new NullPointerException();
}
return UI.toControl(to, UI.toDisplay(from, rect));
}
public static int indexOf(Composite parent, Control child) {
if (parent == null || child == null || parent.isDisposed() || child.isDisposed()) {
throw new IllegalArgumentException();
}
Control[] children = parent.getChildren();
for (int i = 0; i < children.length; i++) {
if (children[i] == child) {
return i;
}
}
return -1;
}
public static void insert(Composite parent, Control child, int index) {
if (parent == null || child == null || parent.isDisposed() || child.isDisposed()) {
throw new IllegalArgumentException();
}
Control[] children = parent.getChildren();
if (index < 0 || index > children.length) {
throw new IllegalArgumentException();
}
for (int i = index; i < children.length; i++) {
children[i].setParent(getShell());
}
child.setParent(parent);
for (int i = index; i < children.length; i++) {
children[i].setParent(parent);
}
parent.layout();
}
public static String getKeyText(int key) {
UIStringResource res = UIStringResource.INSTANCE;
switch (key) {
case SWT.SPACE:
return res.vkSpace();
case SWT.BS:
return res.vkBackspace();
case SWT.TAB:
return res.vkTab();
case SWT.CR:
case SWT.LF:
return res.vkEnter();
case SWT.INSERT:
return res.vkInsert();
case SWT.DEL:
return res.vkDelete();
case SWT.HOME:
return res.vkHome();
case SWT.END:
return res.vkEnd();
case SWT.PAGE_UP:
return res.vkPageUp();
case SWT.PAGE_DOWN:
return res.vkPageDown();
case SWT.ARROW_UP:
return res.vkArrowUp();
case SWT.ARROW_DOWN:
return res.vkArrowDown();
case SWT.ARROW_LEFT:
return res.vkArrowLeft();
case SWT.ARROW_RIGHT:
return res.vkArrowRight();
case SWT.F1:
case SWT.F2:
case SWT.F3:
case SWT.F4:
case SWT.F5:
case SWT.F6:
case SWT.F7:
case SWT.F8:
case SWT.F9:
case SWT.F10:
case SWT.F11:
case SWT.F12:
case SWT.F13:
case SWT.F14:
case SWT.F15:
case SWT.F16:
case SWT.F17:
case SWT.F18:
case SWT.F19:
case SWT.F20:
return MessageFormat.format("F{0}", key - SWT.F1 + 1);
default:
return MessageFormat.format("{0}", Character.toUpperCase((char )key));
}
}
public static String formatMnemonic(String text, char mnemonic) {
if (text == null || text.isEmpty()) {
throw new IllegalArgumentException();
}
if (mnemonic == '\0') {
return text;
}
StringBuilder builder = new StringBuilder();
String lowerCase = text.toLowerCase();
int index = lowerCase.indexOf(mnemonic);
if (index < 0) {
mnemonic = Character.toUpperCase(mnemonic);
String format = FMT_MNEMONIC;
String newText = MessageFormat.format(format, text, mnemonic);
builder.append(newText);
} else {
builder.append(text);
builder.insert(index, '&');
}
return builder.toString();
}
public static String formatAccelerator(int accelerator) {
if (accelerator == 0) {
return "";
}
StringBuilder builder = new StringBuilder();
if ((accelerator & SWT.CTRL) == SWT.CTRL) {
builder.append("Ctrl");
}
if ((accelerator & SWT.ALT) == SWT.ALT) {
if (builder.length() != 0) {
builder.append("+");
}
builder.append("Alt");
}
if ((accelerator & SWT.SHIFT) == SWT.SHIFT) {
if (builder.length() != 0) {
builder.append("+");
}
builder.append("Shift");
}
accelerator &= ~(SWT.CTRL | SWT.ALT | SWT.SHIFT);
if (builder.length() != 0) {
builder.append("+");
}
builder.append(UI.getKeyText(accelerator));
return builder.toString();
}
public static Rectangle getIntersection(Rectangle rect0, Rectangle rect1) {
int left = Math.max(rect0.x, rect1.x);
int top = Math.max(rect0.y, rect1.y);
int right = Math.min(rect0.x + rect0.width, rect1.x + rect1.width);
int bottom = Math.min(rect0.y + rect0.height, rect1.y + rect1.height);
int width = right - left;
int height = bottom - top;
if (width <= 0 || height <= 0) {
return null;
}
return new Rectangle(left, top, width, height);
}
public static RGB getRGB(int id) {
return getColor(id).getRGB();
}
public static Color getColor(int id) {
Display display = Display.getDefault();
return display.getSystemColor(id);
}
public static Color newColor(RGB value) {
return newColor(value.red, value.green, value.blue);
}
public static Color newColor(int red, int green, int blue) {
Display display = Display.getDefault();
return new Color(display, red, green, blue);
}
private static Map<RGB, Image> getSplitBarImages() {
if (splitBarImages == null) {
splitBarImages = new HashMap<RGB, Image>();
}
return splitBarImages;
}
private static Map<URL, Image[]> getImages() {
if (images == null) {
images = new HashMap<URL, Image[]>();
}
return images;
}
private static Map<URL, String> getTexts() {
if (texts == null) {
texts = new HashMap<URL, String>();
}
return texts;
}
private static Shell getShell() {
Display display = Display.getDefault();
if (shell == null || shell.isDisposed()) {
shell = new Shell(display);
shell.setLayout(null);
shell.setVisible(false);
shell.setBounds(0, 0, 0, 0);
}
return shell;
}
public static boolean isParentOf(Control parent, Control child) {
if (parent == null) {
throw new NullPointerException();
}
if (child == null) {
throw new NullPointerException();
}
Control testParent = child.getParent();
if (testParent == null) {
return false;
}
if (testParent.equals(parent)) {
return true;
}
return isParentOf(parent, testParent);
}
public static Rectangle convert(RectangleExpression bounds, Rectangle[] screenPtr) {
if (bounds == null) {
throw new NullPointerException();
}
if (RT.isEmpty(bounds.getX())) {
throw new IllegalArgumentException();
}
if (RT.isEmpty(bounds.getY())) {
throw new IllegalArgumentException();
}
if (RT.isEmpty(bounds.getWidth())) {
throw new IllegalArgumentException();
}
if (RT.isEmpty(bounds.getHeight())) {
throw new IllegalArgumentException();
}
Double.parseDouble(bounds.getX());
Double.parseDouble(bounds.getY());
Double.parseDouble(bounds.getWidth());
Double.parseDouble(bounds.getHeight());
boolean hasPtr = false;
boolean hasValue = false;
if (screenPtr != null) {
if (screenPtr.length > 0) {
hasPtr = true;
if (screenPtr[0] != null) {
hasValue = true;
}
}
}
Rectangle client;
if (hasValue) {
client = screenPtr[0];
} else {
Display display = Display.getDefault();
Point mouse = display.getCursorLocation();
Monitor active = null;
for (Monitor monitor : display.getMonitors()) {
if (monitor.getBounds().contains(mouse)) {
active = monitor;
break;
}
}
if (active == null) {
client = display.getClientArea();
} else {
client = active.getClientArea();
}
if (hasPtr) {
screenPtr[0] = client;
}
}
int left;
int top;
int right;
int bottom;
if (bounds.getX().startsWith("-")) {
try {
left = (client.x + client.width) - Math.abs(Integer.parseInt(bounds.getX()));
} catch (NumberFormatException ex) {
left = (client.x + client.width) - Math.abs(Math.round(client.width * Float.parseFloat(bounds.getX())));
}
} else {
try {
left = client.x + Integer.parseInt(bounds.getX());
} catch (NumberFormatException ex) {
left = client.x + Math.round(client.width * Float.parseFloat(bounds.getX()));
}
}
if (bounds.getY().startsWith("-")) {
try {
top = (client.y + client.height) - Math.abs(Integer.parseInt(bounds.getY()));
} catch (NumberFormatException ex) {
top = (client.y + client.height) - Math.abs(Math.round(client.height * Float.parseFloat(bounds.getY())));
}
} else {
try {
top = client.y + Integer.parseInt(bounds.getY());
} catch (NumberFormatException ex) {
top = client.y + Math.round(client.height * Float.parseFloat(bounds.getY()));
}
}
if (bounds.getWidth().startsWith("-")) {
right = left;
try {
left = right - Math.abs(Integer.parseInt(bounds.getWidth()));
} catch (NumberFormatException ex) {
left = right - Math.abs(Math.round(client.width * Float.parseFloat(bounds.getWidth())));
}
} else {
try {
right = left + Integer.parseInt(bounds.getWidth());
} catch (NumberFormatException ex) {
right = left + Math.round(client.width * Float.parseFloat(bounds.getWidth()));
}
}
if (bounds.getHeight().startsWith("-")) {
bottom = top;
try {
top = bottom - Math.abs(Integer.parseInt(bounds.getHeight()));
} catch (NumberFormatException ex) {
top = bottom - Math.abs(Math.round(client.height * Float.parseFloat(bounds.getHeight())));
}
} else {
try {
bottom = top + Integer.parseInt(bounds.getHeight());
} catch (NumberFormatException ex) {
bottom = top + Math.round(client.height * Float.parseFloat(bounds.getHeight()));
}
}
return new Rectangle(left, top, right - left, bottom - top);
}
public static int convert(ExtentExpression expression, int maxValue) {
if (expression == null) {
throw new NullPointerException();
}
if (expression.getValue() == null) {
throw new IllegalArgumentException();
}
if (expression.getValue().isEmpty()) {
throw new IllegalArgumentException();
}
if (maxValue < 0) {
throw new IllegalArgumentException();
}
if (maxValue == 0) {
throw new IllegalArgumentException();
}
String extent = expression.getValue();
Double.parseDouble(extent);
int value;
if (expression.getValue().startsWith("-")) {
try {
value = maxValue - Integer.parseInt(extent);
} catch (NumberFormatException ex) {
value = maxValue - Math.round(maxValue * Float.parseFloat(extent));
}
} else {
try {
value = Integer.parseInt(extent);
} catch (NumberFormatException ex) {
value = Math.round(maxValue * Float.parseFloat(extent));
}
}
return value;
}
}