X-Git-Url: http://git.nikiroo.be/?a=blobdiff_plain;f=src%2Fjexer%2FTWidget.java;h=034c1e9b26f0ae8fdb1a06550456db2d46bee606;hb=6738825512004e0992555778e7124b568dd5044c;hp=b17b73f67b1c49f92c831591a62e5ef8452bd05d;hpb=8ab60a33f89f656b71751a45967c79179415f652;p=fanfix.git diff --git a/src/jexer/TWidget.java b/src/jexer/TWidget.java index b17b73f..034c1e9 100644 --- a/src/jexer/TWidget.java +++ b/src/jexer/TWidget.java @@ -43,6 +43,7 @@ import jexer.event.TKeypressEvent; import jexer.event.TMenuEvent; import jexer.event.TMouseEvent; import jexer.event.TResizeEvent; +import jexer.layout.LayoutManager; import jexer.menu.TMenu; import jexer.ttree.TTreeItem; import jexer.ttree.TTreeView; @@ -136,6 +137,11 @@ public abstract class TWidget implements Comparable { */ private int cursorY = 0; + /** + * Layout manager. + */ + private LayoutManager layout = null; + // ------------------------------------------------------------------------ // Constructors ----------------------------------------------------------- // ------------------------------------------------------------------------ @@ -212,15 +218,15 @@ public abstract class TWidget implements Comparable { this.parent = parent; children = new ArrayList(); - if (parent != null) { - this.window = parent.window; - parent.addChild(this); - } - this.x = x; this.y = y; this.width = width; this.height = height; + + if (parent != null) { + this.window = parent.window; + parent.addChild(this); + } } /** @@ -570,6 +576,14 @@ public abstract class TWidget implements Comparable { if (resize.getType() == TResizeEvent.Type.WIDGET) { width = resize.getWidth(); height = resize.getHeight(); + if (layout != null) { + if (this instanceof TWindow) { + layout.onResize(new TResizeEvent(TResizeEvent.Type.WIDGET, + width - 2, height - 2)); + } else { + layout.onResize(resize); + } + } } else { // Let children see the screen resize for (TWidget widget: children) { @@ -715,6 +729,15 @@ public abstract class TWidget implements Comparable { } } + /** + * Remove a child widget from this container. + * + * @param child the child widget to remove + */ + public final void remove(final TWidget child) { + remove(child, true); + } + /** * Remove a child widget from this container. * @@ -732,6 +755,10 @@ public abstract class TWidget implements Comparable { } children.remove(child); child.parent = null; + child.window = null; + if (layout != null) { + layout.remove(this); + } } /** @@ -746,29 +773,31 @@ public abstract class TWidget implements Comparable { if (parent != null) { parent.remove(this, doClose); + window = null; } assert (parent == null); - window = newParent.window; - newParent.addChild(this); + assert (window == null); + parent = newParent; + setWindow(parent.window); + parent.addChild(this); } /** - * Set this widget's window to a specific window. Parent must already be - * null. Having a null parent with a specified window is only used - * within Jexer by TStatusBar because TApplication routes events directly - * to it and calls its draw() method. Any other non-parented widgets - * will require similar special case functionality to receive events or - * be drawn to screen. + * Set this widget's window to a specific window. + * + * Having a null parent with a specified window is only used within Jexer + * by TStatusBar because TApplication routes events directly to it and + * calls its draw() method. Any other non-parented widgets will require + * similar special case functionality to receive events or be drawn to + * screen. * * @param window the window to use */ public final void setWindow(final TWindow window) { - - if (parent != null) { - throw new IllegalArgumentException("Cannot have different " + - "windows for parent and child"); - } this.window = window; + for (TWidget child: getChildren()) { + child.setWindow(window); + } } /** @@ -854,7 +883,7 @@ public abstract class TWidget implements Comparable { * * @return widget width */ - public final int getWidth() { + public int getWidth() { return this.width; } @@ -863,8 +892,12 @@ public abstract class TWidget implements Comparable { * * @param width new widget width */ - public final void setWidth(final int width) { + public void setWidth(final int width) { this.width = width; + if (layout != null) { + layout.onResize(new TResizeEvent(TResizeEvent.Type.WIDGET, + width, height)); + } } /** @@ -872,7 +905,7 @@ public abstract class TWidget implements Comparable { * * @return widget height */ - public final int getHeight() { + public int getHeight() { return this.height; } @@ -881,8 +914,12 @@ public abstract class TWidget implements Comparable { * * @param height new widget height */ - public final void setHeight(final int height) { + public void setHeight(final int height) { this.height = height; + if (layout != null) { + layout.onResize(new TResizeEvent(TResizeEvent.Type.WIDGET, + width, height)); + } } /** @@ -900,6 +937,39 @@ public abstract class TWidget implements Comparable { setY(y); setWidth(width); setHeight(height); + if (layout != null) { + layout.onResize(new TResizeEvent(TResizeEvent.Type.WIDGET, + width, height)); + } + } + + /** + * Get the layout manager. + * + * @return the layout manager, or null if not set + */ + public LayoutManager getLayoutManager() { + return layout; + } + + /** + * Set the layout manager. + * + * @param layout the new layout manager + */ + public void setLayoutManager(LayoutManager layout) { + if (this.layout != null) { + for (TWidget w: children) { + this.layout.remove(w); + } + this.layout = null; + } + this.layout = layout; + if (this.layout != null) { + for (TWidget w: children) { + this.layout.add(w); + } + } } /** @@ -984,6 +1054,11 @@ public abstract class TWidget implements Comparable { assert (window != null); + if (window instanceof TDesktop) { + // Desktop doesn't have a window border. + return cursorVisible; + } + // If cursor is out of my window's bounds, it is not visible. if ((getCursorAbsoluteX() >= window.getAbsoluteX() + window.getWidth() - 1) @@ -1036,19 +1111,25 @@ public abstract class TWidget implements Comparable { /** * Get this TWidget's parent TApplication. * - * @return the parent TApplication + * @return the parent TApplication, or null if not assigned */ public TApplication getApplication() { - return window.getApplication(); + if (window != null) { + return window.getApplication(); + } + return null; } /** * Get the Screen. * - * @return the Screen + * @return the Screen, or null if not assigned */ public Screen getScreen() { - return window.getScreen(); + if (window != null) { + return window.getScreen(); + } + return null; } /** @@ -1174,6 +1255,10 @@ public abstract class TWidget implements Comparable { * Called by parent to render to TWindow. Note package private access. */ final void drawChildren() { + if (window == null) { + return; + } + // Set my clipping rectangle assert (window != null); assert (getScreen() != null); @@ -1190,10 +1275,16 @@ public abstract class TWidget implements Comparable { int absoluteRightEdge = window.getAbsoluteX() + window.getWidth(); int absoluteBottomEdge = window.getAbsoluteY() + window.getHeight(); - if (!(this instanceof TWindow) && !(this instanceof TVScroller)) { + if (!(this instanceof TWindow) + && !(this instanceof TVScroller) + && !(parent instanceof TDesktop) + ) { absoluteRightEdge -= 1; } - if (!(this instanceof TWindow) && !(this instanceof THScroller)) { + if (!(this instanceof TWindow) + && !(this instanceof THScroller) + && !(parent instanceof TDesktop) + ) { absoluteBottomEdge -= 1; } int myRightEdge = getAbsoluteX() + width; @@ -1262,6 +1353,9 @@ public abstract class TWidget implements Comparable { for (int i = 0; i < children.size(); i++) { children.get(i).tabOrder = i; } + if (layout != null) { + layout.add(child); + } } /** @@ -1453,6 +1547,98 @@ public abstract class TWidget implements Comparable { return this; } + /** + * Split this widget into two, putting all of this widget's children into + * a new TPanel, and returning a new TSplitPane with that panel on the + * left or right pane. + * + * @param newWidgetOnLeft if true, the new widget (if specified) will be + * on the left pane, and this widget's children will be placed on the + * right pane + * @param newWidget the new widget to add to the other pane, or null + * @return the new split pane widget + */ + public TSplitPane splitVertical(final boolean newWidgetOnLeft, + final TWidget newWidget) { + + TPanel panel = new TPanel(null, x, y, width, height); + TSplitPane splitPane = new TSplitPane(null, x, y, width, height, true); + List widgets = new ArrayList(children); + for (TWidget w: widgets) { + w.setParent(panel, false); + } + children.clear(); + splitPane.setParent(parent, false); + parent = null; + window = null; + if (newWidgetOnLeft) { + splitPane.setLeft(newWidget); + splitPane.setRight(panel); + } else { + splitPane.setRight(newWidget); + splitPane.setLeft(panel); + } + activate(splitPane); + for (TWidget w: widgets) { + assert (w.window != null); + assert (w.parent != null); + } + assert (splitPane.getWindow() != null); + assert (splitPane.getParent() != null); + assert (panel.getWindow() != null); + assert (panel.getParent() != null); + assert (splitPane.isActive() == true); + assert (panel.isActive() == true); + return splitPane; + } + + /** + * Split this widget into two, putting all of this widget's children into + * a new TPanel, and returning a new TSplitPane with that panel on the + * top or bottom pane. + * + * @param newWidgetOnTop if true, the new widget (if specified) will be + * on the top pane, and this widget's children will be placed on the + * bottom pane + * @param newWidget the new widget to add to the other pane, or null + * @return the new split pane widget + */ + public TSplitPane splitHorizontal(final boolean newWidgetOnTop, + final TWidget newWidget) { + + TPanel panel = new TPanel(null, x, y, width, height); + TSplitPane splitPane = new TSplitPane(null, x, y, width, height, false); + List widgets = new ArrayList(children); + for (TWidget w: widgets) { + w.setParent(panel, false); + } + children.clear(); + splitPane.setParent(parent, false); + parent = null; + splitPane.setTop(panel); + parent = null; + window = null; + if (newWidgetOnTop) { + splitPane.setTop(newWidget); + splitPane.setBottom(panel); + } else { + splitPane.setBottom(newWidget); + splitPane.setTop(panel); + } + activate(splitPane); + for (TWidget w: widgets) { + assert (w.window != null); + assert (w.parent != null); + } + assert (splitPane.getWindow() != null); + assert (splitPane.getParent() != null); + assert (panel.getWindow() != null); + assert (panel.getParent() != null); + assert (splitPane.isActive() == true); + assert (panel.isActive() == true); + return splitPane; + } + // ------------------------------------------------------------------------ // Passthru for Screen functions ------------------------------------------ // ------------------------------------------------------------------------ @@ -2431,4 +2617,35 @@ public abstract class TWidget implements Comparable { gridRows); } + /** + * Convenience function to add a panel to this container/window. + * + * @param x column relative to parent + * @param y row relative to parent + * @param width width of text area + * @param height height of text area + * @return the new panel + */ + public final TPanel addPanel(final int x, final int y, final int width, + final int height) { + + return new TPanel(this, x, y, width, height); + } + + /** + * Convenience function to add a split pane to this container/window. + * + * @param x column relative to parent + * @param y row relative to parent + * @param width width of text area + * @param height height of text area + * @param vertical if true, split vertically + * @return the new split pane + */ + public final TSplitPane addSplitPane(final int x, final int y, + final int width, final int height, final boolean vertical) { + + return new TSplitPane(this, x, y, width, height, vertical); + } + }