package com.peterhi.ui;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import com.peterhi.ui.UI.Trims;
public final class Organizer {
private final Window mainWindow;
private final List<View> viewList;
public Organizer(Window mainWindow) {
if (mainWindow == null) {
throw new NullPointerException();
}
this.mainWindow = mainWindow;
this.viewList = new ArrayList<View>();
}
public Window getMainWindow() {
return mainWindow;
}
public View findView(String id) {
if (id == null) {
throw new NullPointerException();
}
if (id.isEmpty()) {
throw new IllegalArgumentException();
}
View[] views = getViews();
for (View view : views) {
String viewId = view.getId();
if (viewId.equals(id)) {
return view;
}
}
return null;
}
public void add(View view, Placement placement) {
if (view == null) {
throw new NullPointerException();
}
if (placement == null) {
throw new NullPointerException();
}
if (placement instanceof Root) {
Root root = (Root )placement;
Composite parent = root.getParent();
if (parent == null) {
} else {
RectangleExpression expression = root.getBounds();
if (expression == null) {
expression = new RectangleExpression("0.1f", "0.1f", "0.8f", "0.8f");
}
Rect[] screen = new Rect[1];
Rect win = UI.convert(expression, screen);
Rect vw = win.clone();
vw.inflate(Trims.window, true);
vw.inflate(Trims.tabPane, true);
Point min = view.getMinimumSize();
int dx;
int dy;
dx = min.x - vw.width();
dy = min.y - vw.height();
if (dx > 0) {
win.width2(dx);
}
if (dy > 0) {
win.height2(dy);
}
dx = win.right() - screen[0].right();
dy = win.bottom() - screen[0].bottom();
if (dx > 0) {
win.x2(dx);
}
if (dy > 0) {
win.y2(dy);
}
if (win.left() < screen[0].left()) {
win.left(screen[0].left());
}
if (win.top() < screen[0].top()) {
win.top(screen[0].top());
}
UI.setBounds(mainWindow, win, false);
TabPane pane = new TabPane(parent, SWT.NONE);
UI.setBounds(pane, UI.getClientArea(parent, false), Rectangle.class);
view.setParent(pane);
TabPane.Item item = new TabPane.Item(pane, SWT.NONE);
item.setText(view.getTitle());
item.setImage(view.getImage());
item.setControl(view);
viewList.add(view);
}
// addRootViewSpec(view, root);
} else if (placement instanceof Tab) {
Tab tabViewSpec = (Tab )placement;
addRefViewSpec(view, tabViewSpec);
} else if (placement instanceof Split) {
Split splitViewSpec = (Split )placement;
addSplitViewSpec(view, splitViewSpec);
}
Window window = view.getShell();
Composite contentPane = window.getContentPane();
Point size = contentPane.computeSize(SWT.DEFAULT, SWT.DEFAULT);
Rectangle trim = window.computeTrim(0, 0, size.x, size.y);
window.setMinimumSize(trim.width, trim.height);
}
public View[] getViews() {
View[] views = new View[viewList.size()];
views = viewList.toArray(views);
return views;
}
private void addRootViewSpec(View view, Root spec) {
if (view == null) {
throw new NullPointerException();
}
if (spec == null) {
throw new NullPointerException();
}
if (spec.getParent() == null) {
// TODO: create new window
} else {
RectangleExpression expression = spec.getBounds();
if (expression == null) {
expression = new RectangleExpression("0.1f", "0.1f", "0.8f", "0.8f");
}
TabPane panel = new TabPane(spec.getParent(), SWT.BORDER);
TabPane.Item item = new TabPane.Item(panel, SWT.CLOSE);
if (view.getTitle() != null) {
item.setText(view.getTitle());
}
if (view.getImage() != null) {
item.setImage(view.getImage());
}
Rectangle[] ptr = new Rectangle[1];
Rectangle rtWindow = UI.convert(expression, ptr);
Rectangle rtContainer = UI.untrim(mainWindow, rtWindow);
Rectangle rtView = UI.untrim(panel, rtContainer);
Point min = view.getMinimumSize();
int lTrim = rtView.x - rtWindow.x;
int tTrim = rtView.y - rtWindow.y;
int rTrim = (rtWindow.x + rtWindow.width) - (rtView.x + rtView.width);
int bTrim = (rtWindow.y + rtWindow.height) - (rtView.y + rtView.height);
int xTrim = lTrim + rTrim;
int yTrim = tTrim + bTrim;
if (rtView.width < min.x) {
rtWindow.width += min.x - rtView.width;
}
if (rtView.height < min.y) {
rtWindow.height += min.y - rtView.height;
}
if (rtWindow.x + rtWindow.width > ptr[0].x + ptr[0].width) {
rtWindow.x = (ptr[0].x + ptr[0].width) - rtWindow.width;
}
if (rtWindow.y + rtWindow.height > ptr[0].y + ptr[0].height) {
rtWindow.y = (ptr[0].y + ptr[0].height) - rtWindow.height;
}
if (rtWindow.x < ptr[0].x) {
rtWindow.x = ptr[0].x;
}
if (rtWindow.y < ptr[0].y) {
rtWindow.y = ptr[0].y;
}
mainWindow.setBounds(rtWindow);
panel.setBounds(spec.getParent().getClientArea());
view.setParent(panel);
item.setControl(view);
viewList.add(view);
}
}
private void addRefViewSpec(View view, Tab spec) {
if (view == null) {
throw new NullPointerException();
}
if (spec == null) {
throw new NullPointerException();
}
if (spec.getReferenceView() == null) {
// use currently active view
} else {
if (!viewList.contains(spec.getReferenceView())) {
throw new IllegalArgumentException();
}
TabPane.Item item = (TabPane.Item )itemOf(spec.getReferenceView());
if (item instanceof TabPane.Item) {
TabPane tab = (TabPane )item.getParent();
int index = tab.indexOf(item);
if (spec.isPositionAfter()) {
index ++;
}
TabPane.Item neo = new TabPane.Item(tab, SWT.NONE, index);
neo.setShowClose(true);
if (view.getTitle() != null) {
neo.setText(view.getTitle());
}
if (view.getImage() != null) {
neo.setImage(view.getImage());
}
view.setParent(tab);
neo.setControl(view);
viewList.add(view);
} else {
// autohide item
}
}
}
private void addSplitViewSpec(View view, Split spec) {
if (spec.getReferenceView() == null) {
// use currently active view
} else {
if (!viewList.contains(spec.getReferenceView())) {
throw new IllegalArgumentException();
}
TabPane.Item item = (TabPane.Item )itemOf(spec.getReferenceView());
if (item == null) {
throw new IllegalArgumentException();
}
ExtentExpression expression = spec.getExtentExpression();
if (expression == null ||
expression.getValue() == null ||
expression.getValue().isEmpty()) {
expression = new ExtentExpression("0.5f");
}
TabPane tab = (TabPane )item.getParent();
Window window = (Window )tab.getShell();
SplitPane contentPane = (SplitPane )window.getContentPane();
Rectangle bounds = tab.getBounds();
int space = contentPane.getGap();
int extent;
if (spec.isPositionVertical()) {
extent = UI.convert(expression, bounds.height - space);
} else {
extent = UI.convert(expression, bounds.width - space);
}
Rectangle old = new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height);
Rectangle mid = new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height);
Rectangle neo = new Rectangle(bounds.x, bounds.y, bounds.width, bounds.height);
if (spec.isPositionVertical()) {
old.height -= extent + space;
mid.height = space;
neo.height = extent;
} else {
old.width -= extent + space;
mid.width = space;
neo.width = extent;
}
if (spec.getPosition() == Split.POSITION_LEFT) {
old.x = bounds.x + (extent + space);
mid.x = bounds.x + (extent);
} else if (spec.getPosition() == Split.POSITION_TOP) {
old.y = bounds.y + (extent + space);
mid.y = bounds.y + (extent);
} else if (spec.getPosition() == Split.POSITION_BOTTOM) {
mid.y = (bounds.y + bounds.height) - (extent + space);
neo.y = (bounds.y + bounds.height) - (extent);
} else {
mid.x = (bounds.x + bounds.width) - (extent + space);
neo.x = (bounds.x + bounds.width) - (extent);
}
Rectangle oldNoTrim = UI.untrim(tab, old);
Rectangle newNoTrim = UI.untrim(tab, neo);
if (spec.isPositionHorizontal()) {
if (newNoTrim.width < view.getMinimumSize().x) {
throw new IllegalArgumentException();
}
if (oldNoTrim.width < spec.getReferenceView().getMinimumSize().x) {
throw new IllegalArgumentException();
}
} else {
if (newNoTrim.height < view.getMinimumSize().y) {
throw new IllegalArgumentException();
}
if (oldNoTrim.height < spec.getReferenceView().getMinimumSize().y) {
throw new IllegalArgumentException();
}
}
tab.setBounds(old);
TabPane newTabs = new TabPane(tab.getParent(), SWT.BORDER);
TabPane.Item newItem = new TabPane.Item(newTabs, SWT.NONE);
newItem.setShowClose(true);
if (view.getTitle() != null) {
newItem.setText(view.getTitle());
}
if (view.getImage() != null) {
newItem.setImage(view.getImage());
}
newTabs.setBounds(neo);
view.setParent(newTabs);
newItem.setControl(view);
newTabs.setSelection(newItem);
viewList.add(view);
}
}
private Item itemOf(View view) {
Composite parent = view.getParent();
if (parent instanceof TabPane) {
TabPane tab = (TabPane )parent;
for (int i = 0; i < tab.getItemCount(); i++) {
TabPane.Item item = (TabPane.Item )tab.getItem(i);
if (view.equals(item.getControl())) {
return item;
}
}
}
return null;
}
public static void main(String[] args) {
UI.initialize();
class SampleView extends View {
private Button control;
public SampleView(Composite parent, int style, String id) {
super(parent, style, id);
control = new Button(this, SWT.NONE);
FillLayout viewLayout = new FillLayout();
viewLayout.marginWidth = 0;
viewLayout.marginHeight = 0;
viewLayout.spacing = 0;
setLayout(viewLayout);
}
public String getText() {
return control.getText();
}
public void setText(String value) {
control.setText(value);
}
}
Display display = Display.getDefault();
Window mainWindow = new Window(display);
Organizer viewManager = new Organizer(mainWindow);
final SampleView view0 = new SampleView(mainWindow.getContentPane(), SWT.NONE, "view0");
view0.setTitle("View 0");
view0.setImage(UIImageResource.T.about16());
view0.setMinimumSize(200, 200);
view0.setText("View 0");
Root spec0 = new Root();
spec0.setParent(mainWindow.getContentPane());
spec0.setBounds(new RectangleExpression("100", "100", "438", "267"));
try {
viewManager.add(view0, spec0);
} catch (Exception ex) {
ex.printStackTrace();
}
final SampleView view1 = new SampleView(mainWindow.getContentPane(), SWT.NONE, "view1");
view1.setTitle("View 1");
view1.setImage(UIImageResource.T.addContact16());
view1.setMinimumSize(200, 200);
view1.setText("View 1");
Split spec1 = new Split();
spec1.setReferenceView(view0);
spec1.setPosition(Split.POSITION_RIGHT);
spec1.setExtentExpression(new ExtentExpression("0.5f"));
try {
viewManager.add(view1, spec1);
} catch (Exception ex) {
ex.printStackTrace();
}
view0.addListener(SWT.Resize, new Listener() {
@Override
public void handleEvent(Event event) {
Control control = (Control )event.widget;
Shell shell = control.getShell();
Rectangle controlBounds = control.getBounds();
Rectangle shellBounds = shell.getBounds();
System.out.println("view0: " + controlBounds);
System.out.println("shell: " + shellBounds);
}
});
view1.addListener(SWT.Resize, new Listener() {
@Override
public void handleEvent(Event event) {
Control control = (Control )event.widget;
Rectangle controlBounds = control.getBounds();
System.out.println("view1: " + controlBounds);
}
});
mainWindow.open();
Composite contentPane = mainWindow.getContentPane();
Point size = contentPane.computeSize(SWT.DEFAULT, SWT.DEFAULT);
Rectangle trim = mainWindow.computeTrim(0, 0, size.x, size.y);
mainWindow.setMinimumSize(trim.width, trim.height);
while (!mainWindow.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
UI.destroy();
}
}