#46 StretchLayoutManager working
authorKevin Lamonte <kevin.lamonte@gmail.com>
Sat, 17 Aug 2019 14:32:45 +0000 (09:32 -0500)
committerKevin Lamonte <kevin.lamonte@gmail.com>
Sat, 17 Aug 2019 14:32:45 +0000 (09:32 -0500)
13 files changed:
src/jexer/TButton.java
src/jexer/TComboBox.java
src/jexer/TField.java
src/jexer/TLabel.java
src/jexer/TProgressBar.java
src/jexer/TRadioButton.java
src/jexer/TRadioGroup.java
src/jexer/TWidget.java
src/jexer/demos/DemoCheckBoxWindow.java
src/jexer/demos/DemoMainWindow.java
src/jexer/demos/DemoMsgBoxWindow.java
src/jexer/demos/DemoTextFieldWindow.java
src/jexer/layout/StretchLayoutManager.java

index 82a638922df56ed7ad6086fcfd5ba4aff385e28f..3938c737aff1f18036e17fd7ad93e307c9984a3f 100644 (file)
@@ -98,13 +98,20 @@ public class TButton extends TWidget {
 
         setX(x);
         setY(y);
-        setHeight(2);
-        setWidth(StringUtils.width(mnemonic.getRawLabel()) + 3);
+        super.setHeight(2);
+        super.setWidth(StringUtils.width(mnemonic.getRawLabel()) + 3);
 
         shadowColor = new CellAttributes();
         shadowColor.setTo(getWindow().getBackground());
         shadowColor.setForeColor(Color.BLACK);
         shadowColor.setBold(false);
+
+        // Since we set dimensions after TWidget's constructor, we need to
+        // update the layout manager.
+        if (getParent().getLayoutManager() != null) {
+            getParent().getLayoutManager().remove(this);
+            getParent().getLayoutManager().add(this);
+        }
     }
 
     /**
@@ -215,6 +222,27 @@ public class TButton extends TWidget {
     // TWidget ----------------------------------------------------------------
     // ------------------------------------------------------------------------
 
+    /**
+     * Override TWidget's width: we can only set width at construction time.
+     *
+     * @param width new widget width (ignored)
+     */
+    @Override
+    public void setWidth(final int width) {
+        // Do nothing
+    }
+
+    /**
+     * Override TWidget's height: we can only set height at construction
+     * time.
+     *
+     * @param height new widget height (ignored)
+     */
+    @Override
+    public void setHeight(final int height) {
+        // Do nothing
+    }
+
     /**
      * Draw a button with a shadow.
      */
index fe2fdacf7a794e5620fad37fabeeec49097196c9..4abdd6fbc7445b89378dffd3ec7e40923d88bec6 100644 (file)
@@ -114,7 +114,7 @@ public class TComboBox extends TWidget {
                     field.setText(list.getSelected());
                     list.setEnabled(false);
                     list.setVisible(false);
-                    TComboBox.this.setHeight(1);
+                    TComboBox.super.setHeight(1);
                     if (TComboBox.this.limitToListValue == false) {
                         TComboBox.this.activate(field);
                     }
@@ -130,7 +130,7 @@ public class TComboBox extends TWidget {
 
         list.setEnabled(false);
         list.setVisible(false);
-        setHeight(1);
+        super.setHeight(1);
         if (limitToListValue) {
             field.setEnabled(false);
         } else {
@@ -215,6 +215,27 @@ public class TComboBox extends TWidget {
     // TWidget ----------------------------------------------------------------
     // ------------------------------------------------------------------------
 
+    /**
+     * Override TWidget's width: we can only set width at construction time.
+     *
+     * @param width new widget width (ignored)
+     */
+    @Override
+    public void setWidth(final int width) {
+        // Do nothing
+    }
+
+    /**
+     * Override TWidget's height: we can only set height at construction
+     * time.
+     *
+     * @param height new widget height (ignored)
+     */
+    @Override
+    public void setHeight(final int height) {
+        // Do nothing
+    }
+
     /**
      * Draw the combobox down arrow.
      */
@@ -253,7 +274,7 @@ public class TComboBox extends TWidget {
     public void hideList() {
         list.setEnabled(false);
         list.setVisible(false);
-        setHeight(1);
+        super.setHeight(1);
         if (limitToListValue == false) {
             activate(field);
         }
@@ -265,7 +286,7 @@ public class TComboBox extends TWidget {
     public void showList() {
         list.setEnabled(true);
         list.setVisible(true);
-        setHeight(list.getHeight() + 1);
+        super.setHeight(list.getHeight() + 1);
         activate(list);
     }
 
index 6aaf5912497659bfa3b3b07fc0ff1e64743ba0ad..1a706b16db6c2a33a928cc4d543497ac09764cec 100644 (file)
@@ -378,6 +378,17 @@ public class TField extends TWidget {
     // TWidget ----------------------------------------------------------------
     // ------------------------------------------------------------------------
 
+    /**
+     * Override TWidget's height: we can only set height at construction
+     * time.
+     *
+     * @param height new widget height (ignored)
+     */
+    @Override
+    public void setHeight(final int height) {
+        // Do nothing
+    }
+
     /**
      * Draw the text field.
      */
index 38c014c26ea256441d37bb2a03c88417c49fd8c1..0c62250ec79b3cd3cfa6af0307c34f7caeac8b86 100644 (file)
@@ -170,6 +170,17 @@ public class TLabel extends TWidget {
     // TWidget ----------------------------------------------------------------
     // ------------------------------------------------------------------------
 
+    /**
+     * Override TWidget's height: we can only set height at construction
+     * time.
+     *
+     * @param height new widget height (ignored)
+     */
+    @Override
+    public void setHeight(final int height) {
+        // Do nothing
+    }
+
     /**
      * Draw a static label.
      */
index b144fd2757fddda34aa620698e40c3eed3bba2da..1e3b55a34e17d05c4717aea78ed9e20b8e5a3b43 100644 (file)
@@ -86,6 +86,17 @@ public class TProgressBar extends TWidget {
     // TWidget ----------------------------------------------------------------
     // ------------------------------------------------------------------------
 
+    /**
+     * Override TWidget's height: we can only set height at construction
+     * time.
+     *
+     * @param height new widget height (ignored)
+     */
+    @Override
+    public void setHeight(final int height) {
+        // Do nothing
+    }
+
     /**
      * Draw a static progress bar.
      */
index 2d602fa3abc1218b8612061c97743176b12ef0c6..60a628845ca2c5c920863bd31be7597c95709266 100644 (file)
@@ -156,6 +156,27 @@ public class TRadioButton extends TWidget {
     // TWidget ----------------------------------------------------------------
     // ------------------------------------------------------------------------
 
+    /**
+     * Override TWidget's width: we can only set width at construction time.
+     *
+     * @param width new widget width (ignored)
+     */
+    @Override
+    public void setWidth(final int width) {
+        // Do nothing
+    }
+
+    /**
+     * Override TWidget's height: we can only set height at construction
+     * time.
+     *
+     * @param height new widget height (ignored)
+     */
+    @Override
+    public void setHeight(final int height) {
+        // Do nothing
+    }
+
     /**
      * Draw a radio button with label.
      */
index 7460de413b653a2d3c2898a6d8a73a8a2ad172fd..58c65e2b11eb679a4110802cde00ea90d06e3366 100644 (file)
@@ -81,6 +81,27 @@ public class TRadioGroup extends TWidget {
     // TWidget ----------------------------------------------------------------
     // ------------------------------------------------------------------------
 
+    /**
+     * Override TWidget's width: we can only set width at construction time.
+     *
+     * @param width new widget width (ignored)
+     */
+    @Override
+    public void setWidth(final int width) {
+        // Do nothing
+    }
+
+    /**
+     * Override TWidget's height: we can only set height at construction
+     * time.
+     *
+     * @param height new widget height (ignored)
+     */
+    @Override
+    public void setHeight(final int height) {
+        // Do nothing
+    }
+
     /**
      * Draw a radio button with label.
      */
@@ -163,9 +184,9 @@ public class TRadioGroup extends TWidget {
         int buttonX = 1;
         int buttonY = getChildren().size() + 1;
         if (StringUtils.width(label) + 4 > getWidth()) {
-            setWidth(StringUtils.width(label) + 7);
+            super.setWidth(StringUtils.width(label) + 7);
         }
-        setHeight(getChildren().size() + 3);
+        super.setHeight(getChildren().size() + 3);
         TRadioButton button = new TRadioButton(this, buttonX, buttonY, label,
             getChildren().size() + 1);
 
index b17b73f67b1c49f92c831591a62e5ef8452bd05d..9dd21c1a08e9fa18d341fe310f7d1ac1c9aa894e 100644 (file)
@@ -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<TWidget> {
      */
     private int cursorY = 0;
 
+    /**
+     * Layout manager.
+     */
+    private LayoutManager layout = null;
+
     // ------------------------------------------------------------------------
     // Constructors -----------------------------------------------------------
     // ------------------------------------------------------------------------
@@ -212,15 +218,15 @@ public abstract class TWidget implements Comparable<TWidget> {
         this.parent = parent;
         children = new ArrayList<TWidget>();
 
-        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,9 @@ public abstract class TWidget implements Comparable<TWidget> {
         if (resize.getType() == TResizeEvent.Type.WIDGET) {
             width = resize.getWidth();
             height = resize.getHeight();
+            if (layout != null) {
+                layout.onResize(resize);
+            }
         } else {
             // Let children see the screen resize
             for (TWidget widget: children) {
@@ -732,6 +741,9 @@ public abstract class TWidget implements Comparable<TWidget> {
         }
         children.remove(child);
         child.parent = null;
+        if (layout != null) {
+            layout.remove(this);
+        }
     }
 
     /**
@@ -854,7 +866,7 @@ public abstract class TWidget implements Comparable<TWidget> {
      *
      * @return widget width
      */
-    public final int getWidth() {
+    public int getWidth() {
         return this.width;
     }
 
@@ -863,8 +875,12 @@ public abstract class TWidget implements Comparable<TWidget> {
      *
      * @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 +888,7 @@ public abstract class TWidget implements Comparable<TWidget> {
      *
      * @return widget height
      */
-    public final int getHeight() {
+    public int getHeight() {
         return this.height;
     }
 
@@ -881,8 +897,12 @@ public abstract class TWidget implements Comparable<TWidget> {
      *
      * @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 +920,39 @@ public abstract class TWidget implements Comparable<TWidget> {
         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);
+            }
+        }
     }
 
     /**
@@ -1262,6 +1315,9 @@ public abstract class TWidget implements Comparable<TWidget> {
         for (int i = 0; i < children.size(); i++) {
             children.get(i).tabOrder = i;
         }
+        if (layout != null) {
+            layout.add(child);
+        }
     }
 
     /**
index c982244f9d2e5ad1bf68ef36ce552a6262169dff..aa29506bceec5da91290044dded063fd80c0ce1a 100644 (file)
@@ -39,6 +39,7 @@ import jexer.TComboBox;
 import jexer.TMessageBox;
 import jexer.TRadioGroup;
 import jexer.TWindow;
+import jexer.layout.StretchLayoutManager;
 import static jexer.TCommand.*;
 import static jexer.TKeypress.*;
 
@@ -87,6 +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()));
+
         int row = 1;
 
         // Add some widgets
index 54234ba32a3a9ab56cea51e81171a6c3943c53df..1c8b4fbc154c3cf4d799990d09767fbaaf980f58 100644 (file)
@@ -44,6 +44,7 @@ import jexer.TTimer;
 import jexer.TWidget;
 import jexer.TWindow;
 import jexer.event.TCommandEvent;
+import jexer.layout.StretchLayoutManager;
 import static jexer.TCommand.*;
 import static jexer.TKeypress.*;
 
@@ -108,6 +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()));
+
         int row = 1;
 
         // Add some widgets
index c2d4ff61e8d5baf49cb59216ed9c96af222681b4..7d106c7b1087e60a82617bdcf2017df09603f2bc 100644 (file)
@@ -36,6 +36,7 @@ import jexer.TApplication;
 import jexer.TInputBox;
 import jexer.TMessageBox;
 import jexer.TWindow;
+import jexer.layout.StretchLayoutManager;
 import static jexer.TCommand.*;
 import static jexer.TKeypress.*;
 
@@ -73,6 +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()));
+
         int row = 1;
 
         // Add some widgets
index 7eb68d6a0c9d58300fcafbc8962800b6ee252b2a..6e6b33099cc555886846d7db47ddfa3566d588c4 100644 (file)
@@ -42,6 +42,7 @@ import jexer.TField;
 import jexer.TLabel;
 import jexer.TMessageBox;
 import jexer.TWindow;
+import jexer.layout.StretchLayoutManager;
 import static jexer.TCommand.*;
 import static jexer.TKeypress.*;
 
@@ -100,6 +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()));
+
         int row = 1;
 
         addLabel(i18n.getString("textField1"), 1, row);
index 548c04a713cb7b496e708b8550363787265d2825..3dd74521b533f8086adee17fc4ecb38e0ba0be2e 100644 (file)
@@ -28,6 +28,9 @@
  */
 package jexer.layout;
 
+import java.awt.Rectangle;
+import java.util.HashMap;
+
 import jexer.TWidget;
 import jexer.event.TResizeEvent;
 
@@ -41,10 +44,45 @@ public class StretchLayoutManager implements LayoutManager {
     // Variables --------------------------------------------------------------
     // ------------------------------------------------------------------------
 
+    /**
+     * Current width.
+     */
+    private int width = 0;
+
+    /**
+     * Current height.
+     */
+    private int height = 0;
+
+    /**
+     * Original width.
+     */
+    private int originalWidth = 0;
+
+    /**
+     * Original height.
+     */
+    private int originalHeight = 0;
+
+    /**
+     * Map of widget to original dimensions.
+     */
+    private HashMap<TWidget, Rectangle> children = new HashMap<TWidget, Rectangle>();
+
     // ------------------------------------------------------------------------
     // Constructors -----------------------------------------------------------
     // ------------------------------------------------------------------------
 
+    /**
+     * Public constructor.
+     *
+     * @param width the width of the parent widget
+     * @param height the height of the parent widget
+     */
+    public StretchLayoutManager(final int width, final int height) {
+        originalWidth = width;
+        originalHeight = height;
+    }
 
     // ------------------------------------------------------------------------
     // LayoutManager ----------------------------------------------------------
@@ -57,7 +95,11 @@ public class StretchLayoutManager implements LayoutManager {
      * @param resize resize event
      */
     public void onResize(final TResizeEvent resize) {
-        // TODO
+        if (resize.getType() == TResizeEvent.Type.WIDGET) {
+            width = resize.getWidth();
+            height = resize.getHeight();
+            layoutChildren();
+        }
     }
 
     /**
@@ -66,7 +108,9 @@ public class StretchLayoutManager implements LayoutManager {
      * @param child the widget to manage
      */
     public void add(final TWidget child) {
-        // TODO
+        Rectangle rect = new Rectangle(child.getX(), child.getY(),
+            child.getWidth(), child.getHeight());
+        children.put(child, rect);
     }
 
     /**
@@ -75,7 +119,33 @@ public class StretchLayoutManager implements LayoutManager {
      * @param child the widget to remove
      */
     public void remove(final TWidget child) {
-        // TODO
+        children.remove(child);
+    }
+
+    // ------------------------------------------------------------------------
+    // StretchLayoutManager ---------------------------------------------------
+    // ------------------------------------------------------------------------
+
+    /**
+     * Resize/reposition child widgets based on difference between current
+     * dimensions and the original dimensions.
+     */
+    public void layoutChildren() {
+        double widthRatio = (double) width / originalWidth;
+        if (!Double.isFinite(widthRatio)) {
+            widthRatio = 1;
+        }
+        double heightRatio = (double) height / originalHeight;
+        if (!Double.isFinite(heightRatio)) {
+            heightRatio = 1;
+        }
+        for (TWidget child: children.keySet()) {
+            Rectangle rect = children.get(child);
+            child.setDimensions((int) (rect.getX() * widthRatio),
+                (int) (rect.getY() * heightRatio),
+                (int) (rect.getWidth() * widthRatio),
+                (int) (rect.getHeight() * heightRatio));
+        }
     }
 
 }