#46 BoxLayoutManager working
authorKevin Lamonte <kevin.lamonte@gmail.com>
Sun, 18 Aug 2019 01:10:55 +0000 (20:10 -0500)
committerKevin Lamonte <kevin.lamonte@gmail.com>
Sun, 18 Aug 2019 01:10:55 +0000 (20:10 -0500)
12 files changed:
src/jexer/TComboBox.java
src/jexer/TPanel.java [new file with mode: 0644]
src/jexer/TText.java
src/jexer/TWidget.java
src/jexer/demos/Demo7.java [new file with mode: 0644]
src/jexer/demos/Demo7.properties [new file with mode: 0644]
src/jexer/demos/DemoCheckBoxWindow.java
src/jexer/demos/DemoMainWindow.java
src/jexer/demos/DemoMsgBoxWindow.java
src/jexer/demos/DemoTextFieldWindow.java
src/jexer/layout/BoxLayoutManager.java [new file with mode: 0644]
src/jexer/layout/StretchLayoutManager.java

index fe1366d3aad49693802efa0a3af0fee114abd3fc..2d1b2c07539f1755c88429b4764391a1ee3bde21 100644 (file)
@@ -222,8 +222,12 @@ public class TComboBox extends TWidget {
      */
     @Override
     public void setWidth(final int width) {
-        field.setWidth(width - 3);
-        list.setWidth(width);
+        if (field != null) {
+            field.setWidth(width - 3);
+        }
+        if (list != null) {
+            list.setWidth(width);
+        }
         super.setWidth(width);
     }
 
diff --git a/src/jexer/TPanel.java b/src/jexer/TPanel.java
new file mode 100644 (file)
index 0000000..1a8dab1
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ * Jexer - Java Text User Interface
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (C) 2019 Kevin Lamonte
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * @author Kevin Lamonte [kevin.lamonte@gmail.com]
+ * @version 1
+ */
+package jexer;
+
+/**
+ * TPanel is an empty container for other widgets.
+ */
+public class TPanel extends TWidget {
+
+    // ------------------------------------------------------------------------
+    // Variables --------------------------------------------------------------
+    // ------------------------------------------------------------------------
+
+    // ------------------------------------------------------------------------
+    // Constructors -----------------------------------------------------------
+    // ------------------------------------------------------------------------
+
+    /**
+     * Public constructor.
+     *
+     * @param parent parent widget
+     * @param x column relative to parent
+     * @param y row relative to parent
+     * @param width width of widget
+     * @param height height of widget
+     */
+    public TPanel(final TWidget parent, final int x, final int y,
+        final int width, final int height) {
+
+        super(parent, x, y, width, height);
+    }
+
+    // ------------------------------------------------------------------------
+    // TWidget ----------------------------------------------------------------
+    // ------------------------------------------------------------------------
+
+
+    // ------------------------------------------------------------------------
+    // TPanel -----------------------------------------------------------------
+    // ------------------------------------------------------------------------
+
+
+}
index e47a162c6f5fe7a38ca02381320d393bdace1a1e..6fea16f3a43ff066165eda982c100797cd517f0d 100644 (file)
@@ -164,8 +164,10 @@ public class TText extends TScrollableWidget {
 
         lines = new LinkedList<String>();
 
-        vScroller = new TVScroller(this, getWidth() - 1, 0, getHeight() - 1);
-        hScroller = new THScroller(this, 0, getHeight() - 1, getWidth() - 1);
+        vScroller = new TVScroller(this, getWidth() - 1, 0,
+            Math.max(1, getHeight() - 1));
+        hScroller = new THScroller(this, 0, getHeight() - 1,
+            Math.max(1, getWidth() - 1));
         reflowData();
     }
 
@@ -181,8 +183,12 @@ public class TText extends TScrollableWidget {
     @Override
     public void setWidth(final int width) {
         super.setWidth(width);
-        hScroller.setWidth(getWidth() - 1);
-        vScroller.setX(getWidth() - 1);
+        if (hScroller != null) {
+            hScroller.setWidth(getWidth() - 1);
+        }
+        if (vScroller != null) {
+            vScroller.setX(getWidth() - 1);
+        }
     }
 
     /**
@@ -194,8 +200,12 @@ public class TText extends TScrollableWidget {
     @Override
     public void setHeight(final int height) {
         super.setHeight(height);
-        hScroller.setY(getHeight() - 1);
-        vScroller.setHeight(getHeight() - 1);
+        if (hScroller != null) {
+            hScroller.setY(getHeight() - 1);
+        }
+        if (vScroller != null) {
+            vScroller.setHeight(getHeight() - 1);
+        }
     }
 
     /**
index 9dd21c1a08e9fa18d341fe310f7d1ac1c9aa894e..d48ffe4c9ad6e477123c1e940e659360b347a1ab 100644 (file)
@@ -577,7 +577,12 @@ public abstract class TWidget implements Comparable<TWidget> {
             width = resize.getWidth();
             height = resize.getHeight();
             if (layout != null) {
-                layout.onResize(resize);
+                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
@@ -2487,4 +2492,19 @@ public abstract class TWidget implements Comparable<TWidget> {
             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);
+    }
+
 }
diff --git a/src/jexer/demos/Demo7.java b/src/jexer/demos/Demo7.java
new file mode 100644 (file)
index 0000000..5f92347
--- /dev/null
@@ -0,0 +1,102 @@
+/*
+ * Jexer - Java Text User Interface
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (C) 2019 Kevin Lamonte
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * @author Kevin Lamonte [kevin.lamonte@gmail.com]
+ * @version 1
+ */
+package jexer.demos;
+
+import java.util.ResourceBundle;
+
+import jexer.TApplication;
+import jexer.TPanel;
+import jexer.TText;
+import jexer.TWindow;
+import jexer.layout.BoxLayoutManager;
+
+/**
+ * This class shows off BoxLayout and TPanel.
+ */
+public class Demo7 {
+
+    /**
+     * Translated strings.
+     */
+    private static final ResourceBundle i18n = ResourceBundle.getBundle(Demo7.class.getName());
+
+    // ------------------------------------------------------------------------
+    // Demo7 ------------------------------------------------------------------
+    // ------------------------------------------------------------------------
+
+    /**
+     * Main entry point.
+     *
+     * @param args Command line arguments
+     */
+    public static void main(final String [] args) throws Exception {
+        // This demo will build everything "from the outside".
+
+        // Swing is the default backend on Windows unless explicitly
+        // overridden by jexer.Swing.
+        TApplication.BackendType backendType = TApplication.BackendType.XTERM;
+        if (System.getProperty("os.name").startsWith("Windows")) {
+            backendType = TApplication.BackendType.SWING;
+        }
+        if (System.getProperty("os.name").startsWith("Mac")) {
+            backendType = TApplication.BackendType.SWING;
+        }
+        if (System.getProperty("jexer.Swing") != null) {
+            if (System.getProperty("jexer.Swing", "false").equals("true")) {
+                backendType = TApplication.BackendType.SWING;
+            } else {
+                backendType = TApplication.BackendType.XTERM;
+            }
+        }
+        TApplication app = new TApplication(backendType);
+        app.addToolMenu();
+        app.addFileMenu();
+        TWindow window = new TWindow(app, i18n.getString("windowTitle"),
+            60, 22);
+        window.setLayoutManager(new BoxLayoutManager(window.getWidth() - 2,
+                window.getHeight() - 2, false));
+
+        TPanel right = window.addPanel(0, 0, 10, 10);
+        TPanel left = window.addPanel(0, 0, 10, 10);
+        right.setLayoutManager(new BoxLayoutManager(right.getWidth(),
+                right.getHeight(), true));
+        left.setLayoutManager(new BoxLayoutManager(left.getWidth(),
+                left.getHeight(), true));
+
+        left.addText("C1", 0, 0, left.getWidth(), left.getHeight());
+        left.addText("C2", 0, 0, left.getWidth(), left.getHeight());
+        left.addText("C3", 0, 0, left.getWidth(), left.getHeight());
+        right.addText("C4", 0, 0, right.getWidth(), right.getHeight());
+        right.addText("C5", 0, 0, right.getWidth(), right.getHeight());
+        right.addText("C6", 0, 0, right.getWidth(), right.getHeight());
+
+        app.run();
+    }
+
+}
diff --git a/src/jexer/demos/Demo7.properties b/src/jexer/demos/Demo7.properties
new file mode 100644 (file)
index 0000000..e6fd7ee
--- /dev/null
@@ -0,0 +1 @@
+windowTitle=BoxLayoutManager Demo
index aa29506bceec5da91290044dded063fd80c0ce1a..fda7bd7a15ae6567eee7a21d17b090cc46648c4f 100644 (file)
@@ -88,7 +88,8 @@ public class DemoCheckBoxWindow extends TWindow {
         // centered on screen.
         super(parent, i18n.getString("windowTitle"), 0, 0, 60, 17, flags);
 
-        setLayoutManager(new StretchLayoutManager(getWidth(), getHeight()));
+        setLayoutManager(new StretchLayoutManager(getWidth() - 2,
+                getHeight() - 2));
 
         int row = 1;
 
index 1c8b4fbc154c3cf4d799990d09767fbaaf980f58..0be7088556e959b2c64c9d725e316ebbfb1b7321 100644 (file)
@@ -109,7 +109,8 @@ public class DemoMainWindow extends TWindow {
         // centered on screen.
         super(parent, i18n.getString("windowTitle"), 0, 0, 64, 23, flags);
 
-        setLayoutManager(new StretchLayoutManager(getWidth(), getHeight()));
+        setLayoutManager(new StretchLayoutManager(getWidth() - 2,
+                getHeight() - 2));
 
         int row = 1;
 
index 7d106c7b1087e60a82617bdcf2017df09603f2bc..0485f5184195a1a836f5842d1cda069ebe937dd6 100644 (file)
@@ -74,7 +74,8 @@ public class DemoMsgBoxWindow extends TWindow {
         // will be centered on screen.
         super(parent, i18n.getString("windowTitle"), 0, 0, 64, 18, flags);
 
-        setLayoutManager(new StretchLayoutManager(getWidth(), getHeight()));
+        setLayoutManager(new StretchLayoutManager(getWidth() - 2,
+                getHeight() - 2));
 
         int row = 1;
 
index 6e6b33099cc555886846d7db47ddfa3566d588c4..2c6116a980a4c0c243599c82a99fc0abee09f4a1 100644 (file)
@@ -101,7 +101,8 @@ public class DemoTextFieldWindow extends TWindow {
         // will be centered on screen.
         super(parent, i18n.getString("windowTitle"), 0, 0, 60, 20, flags);
 
-        setLayoutManager(new StretchLayoutManager(getWidth(), getHeight()));
+        setLayoutManager(new StretchLayoutManager(getWidth() - 2,
+                getHeight() - 2));
 
         int row = 1;
 
diff --git a/src/jexer/layout/BoxLayoutManager.java b/src/jexer/layout/BoxLayoutManager.java
new file mode 100644 (file)
index 0000000..c3d1280
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * Jexer - Java Text User Interface
+ *
+ * The MIT License (MIT)
+ *
+ * Copyright (C) 2019 Kevin Lamonte
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * @author Kevin Lamonte [kevin.lamonte@gmail.com]
+ * @version 1
+ */
+package jexer.layout;
+
+import java.util.ArrayList;
+
+import jexer.TWidget;
+import jexer.event.TResizeEvent;
+
+/**
+ * BoxLayoutManager repositions child widgets based on the order they are
+ * added to the parent widget and desired orientation.
+ */
+public class BoxLayoutManager implements LayoutManager {
+
+    // ------------------------------------------------------------------------
+    // Variables --------------------------------------------------------------
+    // ------------------------------------------------------------------------
+
+    /**
+     * If true, orient vertically.  If false, orient horizontally.
+     */
+    private boolean vertical = true;
+
+    /**
+     * Current width.
+     */
+    private int width = 0;
+
+    /**
+     * Current height.
+     */
+    private int height = 0;
+
+    /**
+     * Widgets being managed.
+     */
+    private ArrayList<TWidget> children = new ArrayList<TWidget>();
+
+    // ------------------------------------------------------------------------
+    // Constructors -----------------------------------------------------------
+    // ------------------------------------------------------------------------
+
+    /**
+     * Public constructor.
+     *
+     * @param width the width of the parent widget
+     * @param height the height of the parent widget
+     * @param vertical if true, arrange widgets vertically
+     */
+    public BoxLayoutManager(final int width, final int height,
+        final boolean vertical) {
+
+        this.width = width;
+        this.height = height;
+        this.vertical = vertical;
+    }
+
+    // ------------------------------------------------------------------------
+    // LayoutManager ----------------------------------------------------------
+    // ------------------------------------------------------------------------
+
+    /**
+     * Process the parent widget's resize event, and resize/reposition child
+     * widgets.
+     *
+     * @param resize resize event
+     */
+    public void onResize(final TResizeEvent resize) {
+        if (resize.getType() == TResizeEvent.Type.WIDGET) {
+            width = resize.getWidth();
+            height = resize.getHeight();
+            layoutChildren();
+        }
+    }
+
+    /**
+     * Add a child widget to manage.
+     *
+     * @param child the widget to manage
+     */
+    public void add(final TWidget child) {
+        children.add(child);
+        layoutChildren();
+    }
+
+    /**
+     * Remove a child widget from those managed by this LayoutManager.
+     *
+     * @param child the widget to remove
+     */
+    public void remove(final TWidget child) {
+        children.remove(child);
+        layoutChildren();
+    }
+
+    // ------------------------------------------------------------------------
+    // BoxLayoutManager -------------------------------------------------------
+    // ------------------------------------------------------------------------
+
+    /**
+     * Resize/reposition child widgets based on horizontal/vertical
+     * arrangement.
+     */
+    public void layoutChildren() {
+        if (children.size() == 0) {
+            return;
+        }
+        if (vertical) {
+            int widgetHeight = Math.max(1, height / children.size());
+            int leftoverHeight = height % children.size();
+            for (int i = 0; i < children.size() - 1; i++) {
+                TWidget child = children.get(i);
+                child.setDimensions(child.getX(), i * widgetHeight,
+                    width, widgetHeight);
+            }
+            TWidget child = children.get(children.size() - 1);
+            child.setDimensions(child.getX(),
+                (children.size() - 1) * widgetHeight, width,
+                widgetHeight + leftoverHeight);
+        } else {
+            int widgetWidth = Math.max(1, width / children.size());
+            int leftoverWidth = width % children.size();
+            for (int i = 0; i < children.size() - 1; i++) {
+                TWidget child = children.get(i);
+                child.setDimensions(i * widgetWidth, child.getY(),
+                    widgetWidth, height);
+            }
+            TWidget child = children.get(children.size() - 1);
+            child.setDimensions((children.size() - 1) * widgetWidth,
+                child.getY(), widgetWidth + leftoverWidth, height);
+        }
+    }
+
+}
index 3dd74521b533f8086adee17fc4ecb38e0ba0be2e..0ae7dff396be3ad685619f70d0a20dcea50cde31 100644 (file)
@@ -82,6 +82,8 @@ public class StretchLayoutManager implements LayoutManager {
     public StretchLayoutManager(final int width, final int height) {
         originalWidth = width;
         originalHeight = height;
+        this.width = width;
+        this.height = height;
     }
 
     // ------------------------------------------------------------------------
@@ -111,6 +113,7 @@ public class StretchLayoutManager implements LayoutManager {
         Rectangle rect = new Rectangle(child.getX(), child.getY(),
             child.getWidth(), child.getHeight());
         children.put(child, rect);
+        layoutChildren();
     }
 
     /**
@@ -120,6 +123,7 @@ public class StretchLayoutManager implements LayoutManager {
      */
     public void remove(final TWidget child) {
         children.remove(child);
+        layoutChildren();
     }
 
     // ------------------------------------------------------------------------