/*
* Copyright (C) 2011 Peransin Nicolas. All rights reserved.
* Use is subject to license terms.
*/
package org.mypsycho.swing.app.utils;
import java.awt.Component;
import java.awt.Container;
import java.awt.LayoutManager;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.JRootPane;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JViewport;
import javax.swing.RootPaneContainer;
/**
* Builder class for Swing component hierarchy.
*
* @author Peransin Nicolas
*/
public class SwingHelper extends Swings {
// Note '?' is used instead of ':' because ':' is a separator in properties files
public static final String VIEW_SUFFIX = "?view";
final Component root;
Component with;
public SwingHelper(Component r) {
if (r == null) {
throw new NullPointerException();
}
root = r;
root();
}
public SwingHelper(String name, Component r) {
this(r);
root.setName(name);
}
public SwingHelper(String name, LayoutManager l) {
this(name, new JPanel(l));
}
public SwingHelper(LayoutManager l) {
this(new JPanel(l));
}
public SwingHelper root() {
with = root;
return this;
}
public SwingHelper add(String name, LayoutManager l) {
return add(name, l, null);
}
public SwingHelper add(String name, LayoutManager l, Object constraint) {
return add(name, new JPanel(l), constraint);
}
public SwingHelper add(String name, Component c) {
return add(name, c, null);
}
public SwingHelper add(String name, Component c, Object constraint) {
// Compatible JTabbedPane
if (name == null) {
throw new NullPointerException("Helper requires named component to navigate");
}
c.setName(name);
Container parent = (Container) getContainer(with);
if (constraint == null) {
// Some well-known container constraint
if ((parent instanceof JSplitPane)
|| (parent.getLayout() instanceof BoxLayout)) {
constraint = name;
}
}
parent.add(c, constraint);
return this;
}
public SwingHelper with(String name) {
with = get(name);
return this;
}
public SwingHelper with(String name, String... path) {
with(name);
for (String step : path) {
with(step);
}
return this;
}
public SwingHelper with(String name, LayoutManager l) {
return with(name, l, null);
}
public SwingHelper with(String name, LayoutManager l, Object constraint) {
return with(name, new JPanel(l), constraint);
}
public SwingHelper with(String name, Component c) {
return with(name, c, null);
}
public SwingHelper with(String name, Component c, Object constraint) {
return add(name, c, constraint).with(name);
}
public SwingHelper back() {
if (with == root) {
throw new IllegalStateException("At root");
}
with = with.getParent();
boolean up = true;
while (up) {
if (with == root) {
up = false;
} else if (with instanceof JScrollPane) {
with = with.getParent();
} else if (with instanceof JViewport) {
with = with.getParent();
} else if ((with instanceof JLayeredPane) && (with.getParent() instanceof JRootPane)) {
with = with.getParent();
} else if (with instanceof JRootPane) {
with = with.getParent();
} else {
up = false;
}
}
return this;
}
public Component[] children() { // Iteration on with component children
return ((Container) getContainer(with)).getComponents();
}
@SuppressWarnings("unchecked")
public <C extends Component> C get(String name, String... path) {
Component c = get(name);
for (String step : path) {
c = getChild(c, step);
}
return (C) c;
}
@SuppressWarnings("unchecked")
public <C extends Component> C get(String name) {
return (C) getChild(with, name);
}
private static Component getContainer(Component parent) {
while (true) {
if (parent instanceof RootPaneContainer) {
parent = ((RootPaneContainer) parent).getRootPane();
} else if (parent instanceof JRootPane) {
parent = ((JRootPane) parent).getContentPane();
} else if (parent instanceof JScrollPane) {
parent = ((JScrollPane) parent).getViewport();
} else if (parent instanceof JViewport) {
parent = ((JViewport) parent).getView();
} else {
return parent;
}
}
}
public static Component getChild(Component parent, String name) {
parent = getContainer(parent);
if (parent instanceof JSplitPane) {
JSplitPane split = (JSplitPane) parent;
if (JSplitPane.TOP.equals(name)) {
return split.getTopComponent();
} else if (JSplitPane.LEFT.equals(name)) {
return split.getLeftComponent();
} else if (JSplitPane.RIGHT.equals(name)) {
return split.getRightComponent();
} else if (JSplitPane.BOTTOM.equals(name)) {
return split.getBottomComponent();
}
}
Container cont = (Container) parent;
for (int i = 0; i < cont.getComponentCount(); i++) {
Component comp = cont.getComponent(i);
if (name.equals(comp.getName())) {
return comp;
}
}
if (name.endsWith(VIEW_SUFFIX)) {
String subName = name.substring(0, name.length() - VIEW_SUFFIX.length());
if (subName.isEmpty()) {
return parent;
}
return getContainer(getChild(parent, subName));
}
throw new IllegalArgumentException("No component named " + name);
}
@SuppressWarnings("unchecked")
public <C extends Component> C get() {
return (C) with;
}
public SwingHelper label(String name) {
return add(name, new JLabel());
}
public SwingHelper label(String name, Object constraint) {
return add(name, new JLabel(), constraint);
}
public SwingHelper button(String name) {
return add(name, new JButton());
}
public SwingHelper button(String name, Object constraint) {
return add(name, new JButton(), constraint);
}
public SwingHelper check(String name) {
return add(name, new JCheckBox());
}
public SwingHelper check(String name, Object constraint) {
return add(name, new JCheckBox(), constraint);
}
public SwingHelper vsplit(String name) {
return vsplit(name, null);
}
public SwingHelper hsplit(String name) {
return hsplit(name, null);
}
public SwingHelper vsplit(String name, Object constraint) {
return with(name, new JSplitPane(JSplitPane.VERTICAL_SPLIT), constraint);
}
public SwingHelper hsplit(String name, Object constraint) {
return with(name, new JSplitPane(JSplitPane.HORIZONTAL_SPLIT), constraint);
}
public SwingHelper scroll(String name, Component view) {
return scroll(name, view, null);
}
public SwingHelper scroll(String name, Component view, Object constraint) {
return add(name, new JScrollPane(view), constraint);
}
}