Dynamic resizing and anchors
Often you'll want a program with no fixed window size. By default, sketch windows in Processing are not resizable but they can be made.
Call f.setResizable(true) (Processing also provides a method for this, but better call this one
when using guiSET). Now the user can resize and maximize the window! Generally, this is not enough
because now making the window bigger will just add extra empty space at the right and bottom. Worse: when
making the window smaller, content becomes inaccessible.
You need to adjust the content to fit the window and for that purpose guiSET provides so-called
anchors.
Each element can have up to four anchors, one for each edge (called TOP,
BOTTOM, LEFT, RIGHT). Once
an
anchor is set for one edge (let's say RIGHT), then the distance from the right side of the
element to the
right side of the parent is maintained when the parent is resized (of course this does and should not work
for flow containers). This way you can create a right-alignment. If you set for example a RIGHT
and a LEFT anchor, then the width of this element will be changed and it will grow or shrink
with its
parent. Same applies for TOP and BOTTOM.
So how to create an anchor? The method addAutoAnchors(int...newAnchors) (you can add multiple
anchors at
once) will take a 'snapshot' of the current distances
(does not work if the element has no parent
yet)
. If
afterwards you change the position or size (or x, y, width, height) of the element programmatically, the
anchors will be recalculated!
removeAnchor(int anchor) clears given anchor.
I'll give an example here (also part of the library examples and here).
import guiSET.core.*;
/*
* Example for a border layout.
* The window is split into a header, footer, two sidebars and the main area - a.k.a.
* north, south, west, east, and center.
*
* Their size is adjusted automatically when the window is resized.
*/
Frame f;
Container north;
Container west;
Container east;
Container south;
Container center;
int northHeight = 25; // (fixed) height of header ("north" section)
int southHeight = 30; // (fixed) height of footer ("south" section)
int eastWidth = 50; // (fixed) width of left sidebar ("west" section)
int westWidth = 50; // (fixed) width of right sidebar ("east" section)
void setup() {
size(400, 300); // choose any size
f = new Frame(this);
f.setResizable(true); // enable window resizing (default is off)
north = new Container(width, northHeight);
south = new Container(width, southHeight);
east = new Container(eastWidth, height - northHeight - southHeight);
west = new Container(westWidth, height - northHeight - southHeight);
center = new Container(width - eastWidth - westWidth, height - northHeight - southHeight);
f.add(north, south, west, east, center); // add them all to f before creating any anchors !
south.setY(height - southHeight);
west.setY(northHeight);
center.setPosition(westWidth, northHeight);
east.setPosition(width - eastWidth, northHeight);
north.addAutoAnchors(LEFT, RIGHT);
west.addAutoAnchors(TOP, BOTTOM);
east.addAutoAnchors(TOP, RIGHT, BOTTOM);
south.addAutoAnchors(LEFT, RIGHT, BOTTOM);
center.addAutoAnchors(LEFT, RIGHT, TOP, BOTTOM);
// Set background colors and add labels for demonstration purposes
north.setBackgroundColor(color(200));
north.add(new Label("North"));
west.setBackgroundColor(color(220, 50, 67));
west.add(new Label("West"));
east.setBackgroundColor(color(200, 83, 67));
east.add(new Label("East"));
south.setBackgroundColor(color(150));
south.add(new Label("South"));
center.setBackgroundColor(color(255, 252, 229));
center.add(new Label("Center"));
}
void draw() {
}
This is called a border layout: each side has a container (often named by the four compass directions) with either fixed width (east and west area) or fixed height (north and south area). The center containers size is set to fit all the remaining space. When resizing the window, all containers adjust accordingly to fill the space.
Another option to achieve this is to use setAnchor(int type, int value) which sets one anchor
to the
given value. This will
probably change the position and/or size of your element. If we have a button that we want to place in the
right bottom corner (i.e. with a spacing of 10px), we use:
myButton.setAnchor(RIGHT, 10); myButton.setAnchor(BOTTOM, 10);
And without setting the position of myButton manually, it will be moved to the right bottom
corner. This also
makes the above example easier - you do not need to think to much about the size and sometimes on the
positioning:
import guiSET.core.*;
Frame f;
Container north;
Container west;
Container east;
Container south;
Container center;
int northHeight = 25; // (fixed) height of header ("north" section)
int southHeight = 30; // (fixed) height of footer ("south" section)
int eastWidth = 50; // (fixed) width of left sidebar ("west" section)
int westWidth = 50; // (fixed) width of right sidebar ("east" section)
void setup() {
size(500, 400); // choose any size
f = new Frame(this);
f.setResizable(true);
north = new Container(width, northHeight); // I left this one the same
south = new Container();
west = new Container();
east = new Container();
center = new Container();
f.add(north, south, west, east, center); // add them all to f before creating any anchors !
north.addAutoAnchors(LEFT, RIGHT);
west.setWidth(westWidth);
west.setAnchor(TOP, northHeight);
west.setAnchor(BOTTOM, southHeight);
east.setWidth(eastWidth);
east.setAnchor(RIGHT, 0);
east.setAnchor(TOP, northHeight);
east.setAnchor(BOTTOM, southHeight);
south.setHeight(southHeight);
south.setAnchor(LEFT, 0);
south.setAnchor(RIGHT, 0);
south.setAnchor(BOTTOM, 0);
center.setAnchor(TOP, northHeight);
center.setAnchor(LEFT, westWidth);
center.setAnchor(RIGHT, eastWidth);
center.setAnchor(BOTTOM, southHeight);
// Set background colors and add labels for demonstration purposes
north.setBackgroundColor(color(200));
north.add(new Label("North"));
west.setBackgroundColor(color(220, 50, 67));
west.add(new Label("West"));
east.setBackgroundColor(color(200, 83, 67));
east.add(new Label("East"));
south.setBackgroundColor(color(150));
south.add(new Label("South"));
center.setBackgroundColor(color(255, 252, 229));
center.add(new Label("Center"));
}
void draw() {
}
By the way, Frame does not need anchors as it always follows the size of the window.
Also the window does not need to be resizable for anchors to come in useful. Maybe you have a container you want to change in size dynamically and make its content follow...
