Posts Tagged ‘javascript’

Nominate Qooxdoo for SourceForge Community Choice Awards

Saturday, May 16th, 2009

I’ve just voted Qooxdoo for Most Likely to Change the Way You Do Everything category.

You can use the link below to vote yourself:

Bookmark and Share

Using Layouts In Qooxdoo – Index

Thursday, April 30th, 2009

Using Layouts In Qooxdoo tutorial series is finished. I tried my best to explain how layout managers work and how they differ from each other. This tutorial is for those who have little or no object oriented GUI programming experience. Especially JavaScript/DOM programmers learning Qooxdoo. I hope it is helpful.

Complete list of parts:

  1. Introduction
  2. VBox Layout
  3. HBox Layout
  4. Grid Layout
  5. Basic & Canvas Layouts
Bookmark and Share

Using Layouts In Qooxdoo – Part 5: Basic & Canvas

Thursday, April 30th, 2009

This is the fifth part of a tutorial series about layout managers, container objects and object hierarchies in Qooxdoo. Read the first part here.

Basic Layout Manager

qx.ui.layout.Basic layout manager positions your widgets with absolute coordinates. It doesn’t have much to offer except the freedom of manual positioning.

We supply a left and top property when we add our widgets. Following example places buttons in a circular path, like a clock.

   1 /*
   2 #asset(qooxdoolayouts/*)
   3 */
   4 qx.Class.define("qooxdoolayouts.Application",
   5 {
   6     extend: qx.application.Standalone,
   7     members: {
   8         main: function(){
   9             this.base(arguments);
  10 
  11             var main_container = new qx.ui.container.Composite();
  12 
  13             var layout_manager = new qx.ui.layout.Basic();
  14             main_container.setLayout(layout_manager);
  15 
  16             var btn_size = 50;
  17             var distance = 175;
  18             var pi2 = 2 * 3.141592;
  19             center = {
  20                 x: Math.round(qx.bom.Viewport.getWidth()/2)-btn_size/2,
  21                 y: Math.round(qx.bom.Viewport.getHeight()/2)-btn_size/2
  22             }
  23 
  24             for (var i=0; i<12; i++) {
  25                 var button = new qx.ui.form.Button("CW"+(i+1).toString());
  26                 button.setWidth(btn_size);
  27                 button.setHeight(btn_size);
  28                 var dist_x = Math.round(distance * Math.sin(-(i/12+0.5)*pi2));
  29                 var dist_y = Math.round(distance * Math.cos(-(i/12+0.5)*pi2));
  30                 main_container.add(button, {
  31                     left: center.x + dist_x,
  32                     top: center.y + dist_y
  33                 });
  34             }
  35 
  36             var application_root = this.getRoot();
  37             application_root.add(main_container);
  38         }
  39     }
  40 });
Basic Example

Basic Example

Nevermind the math. What is important is; this would be much harder to achieve with other, more advanced managers such as Grid.

Canvas Layout Manager

qx.ui.layout.Canvas is a slightly advanced version of Basic. Canvas lets you define margins (of all four directions) and dimensions in percentage as well as in pixels.

Canvas allows you to define all four margins. You don’t have to define all of them of course. For example if you define a top and bottom margin remaining space will be your widget’s height1. Alternatively you can specify a bottom margin and a height for you widget. This way it will keep its position relative to container’s bottom edge.

One thing to keep in mind is margins are defined against container, not against a bounding box like DOM. Say, if you set the same left on two widgets, they’ll be stacked on top of each other if they happen to have the same vertical coordinates. The following example mimics a Grid layout using Canvas:

   1 /*
   2 #asset(qooxdoolayouts/*)
   3 */
   4 qx.Class.define("qooxdoolayouts.Application",
   5 {
   6     extend: qx.application.Standalone,
   7     members: {
   8         main: function(){
   9             this.base(arguments);
  10 
  11             var main_container = new qx.ui.container.Composite();
  12 
  13             var layout_manager = new qx.ui.layout.Canvas();
  14             main_container.setLayout(layout_manager);
  15 
  16             main_container.add(new qx.ui.form.Button("Child Widget 1"), {
  17                 left: 20,
  18                 top: 10
  19             });
  20             main_container.add(new qx.ui.form.Button("Child Widget 2"), {
  21                 left: 140,
  22                 right: 20,
  23                 top: 10
  24             });
  25             main_container.add(new qx.ui.form.Button("Child Widget 3"), {
  26                 left: 20,
  27                 top: 50,
  28                 bottom: 10
  29             });
  30             main_container.add(new qx.ui.form.Button("Child Widget 4"), {
  31                 left: 140,
  32                 right: 20,
  33                 top: 50,
  34                 bottom: 10
  35             });
  36 
  37             main_container.getChildren()[0].setWidth(100);
  38             main_container.getChildren()[2].setWidth(100);
  39 
  40             var application_root = this.getRoot();
  41             application_root.add(main_container);
  42 
  43             application_root.addListener("resize", function(e) {
  44                 main_container.set({
  45                     "width": qx.bom.Viewport.getWidth(),
  46                     "height": qx.bom.Viewport.getHeight(),
  47                 });
  48             }, this);
  49         }
  50     }
  51 });
Canvas Example 1

Canvas Example 1

We set two widgets’ widths manually (see lines 37 & 38) to get all the margins (almost) equal. The first row only has top margin set, but the second row has both top and bottom margins. We have given widgets in the second row top margins taking:

  • Top margin of first row
  • Height of the widgets in the first row

and

  • Margin between first and second rows

into account. The same thing is true for the left margin of second column. This is because, as I mentioned, margins are calculated relative to container edges.

If you need to position your controls relative to one another, like DOM positioning, you should probably look into other layout managers like Grid. A good example of a use case for Canvas can be a mapping application such as Google Maps.

As I mentioned earlier Canvas layout accepts parameters in percentages. Following example sets vertical margins in pixels but horizontal margins in percentages:

   1 /*
   2 #asset(qooxdoolayouts/*)
   3 */
   4 qx.Class.define("qooxdoolayouts.Application",
   5 {
   6     extend: qx.application.Standalone,
   7     members: {
   8         main: function(){
   9             this.base(arguments);
  10 
  11             var main_container = new qx.ui.container.Composite();
  12 
  13             var layout_manager = new qx.ui.layout.Canvas();
  14             main_container.setLayout(layout_manager);
  15 
  16             var button = new qx.ui.form.Button("Child Widget 1");
  17             button.setMinWidth(250);
  18             button.setMaxWidth(400);
  19             main_container.add(button, {
  20                 left: "30%",
  21                 right: "30%",
  22                 top: 40,
  23                 bottom: 40
  24             });
  25 
  26             var application_root = this.getRoot();
  27             application_root.add(main_container);
  28 
  29             application_root.addListener("resize", function(e) {
  30                 main_container.set({
  31                     "width": qx.bom.Viewport.getWidth(),
  32                     "height": qx.bom.Viewport.getHeight(),
  33                 });
  34             }, this);
  35         }
  36     }
  37 });

1: Whether your widget grows this high depends. Let’s say that height is reserved for your widget.

Bookmark and Share

Using Layouts In Qooxdoo – Part 4: Grid Layout

Saturday, February 21st, 2009

This is the fourth part of a tutorial series about layout managers, container objects and object hierarchies in Qooxdoo. Read the first part here.

qx.ui.layout.Grid is like a combined VBox & Hbox. Grid supports:

  • Variable width/height columns/rows.
  • Cells spanning multiple columns/rows.
  • Empty cells.
Grid Layout

Grid Layout

Here is a simple application using a Grid layout:

   1 /*
   2 #asset(grid/*)
   3 */
   4 qx.Class.define("grid.Application",
   5 {
   6     extend: qx.application.Standalone,
   7     members: {
   8         main: function(){
   9             this.base(arguments);
  10 
  11             var main_container = new qx.ui.container.Composite();
  12 
  13             var layout_manager = new qx.ui.layout.Grid();
  14             main_container.setLayout(layout_manager);
  15 
  16             main_container.add(new qx.ui.form.Button("Child Widget 1"), {row: 0, column: 0});
  17             main_container.add(new qx.ui.form.Button("Child Widget 2"), {row: 0, column: 1});
  18             main_container.add(new qx.ui.form.Button("Child Widget 3"), {row: 0, column: 2});
  19             main_container.add(new qx.ui.form.Button("Child Widget 4"), {row: 1, column: 0});
  20             main_container.add(new qx.ui.form.Button("Child Widget 5"), {row: 1, column: 1});
  21             main_container.add(new qx.ui.form.Button("Child Widget 6"), {row: 1, column: 2});
  22 
  23             var application_root = this.getRoot();
  24             application_root.add(main_container);
  25         }
  26     }
  27 });
Grid Example 1

Grid Example 1

We have created an 3×2 table layout without explicitly stating row/column count. Just set your row and column layout preferences when you add your child widgets.

Try commenting out some cells to see what happens. If you, for example, comment out second (0,1) and fifth (1,1) cells the second column disappears. But missing cells are OK otherwise. You can see below the layout when third and fifth cells are commented:

Grid Example 1 - Missing Cells

Grid Example 1 - Missing Cells

Following example illustrates row/column spanning:

   1 /*
   2 #asset(grid/ *)
   3 */
   4 qx.Class.define("grid.Application",
   5 {
   6     extend: qx.application.Standalone,
   7     members: {
   8         main: function(){
   9             this.base(arguments);
  10 
  11             var main_container = new qx.ui.container.Composite();
  12 
  13             var layout_manager = new qx.ui.layout.Grid();
  14             main_container.setLayout(layout_manager);
  15 
  16             main_container.add(new qx.ui.form.Button("Child Widget 1"), {
  17                 row: 0,
  18                 column: 0,
  19                 rowSpan: 2
  20             });
  21             main_container.add(new qx.ui.form.Button("Child Widget 2"), {
  22                 row: 0,
  23                 column: 1,
  24                 colSpan: 2
  25             });
  26             main_container.add(new qx.ui.form.Button("Child Widget 3"), {
  27                 row: 1,
  28                 column: 1
  29             });
  30             main_container.add(new qx.ui.form.Button("Child Widget 4"), {
  31                 row: 1,
  32                 column: 2
  33             });
  34 
  35             var application_root = this.getRoot();
  36             application_root.add(main_container);
  37         }
  38     }
  39 });
Grid Example 2

Grid Example 2

Spanning is easy, just like HTML tables. But we set placement (row and column parameters) explicitly. We can add our widgets in any order and still get the same layout if we use the same preferences.

As I said in the beginning of this part Grid is like a combination of VBox and HBox. Therefore flexing is two dimensional:

   1 /*
   2 #asset(grid/ *)
   3 */
   4 qx.Class.define("grid.Application",
   5 {
   6     extend: qx.application.Standalone,
   7     members: {
   8         main: function(){
   9             this.base(arguments);
  10 
  11             var main_container = new qx.ui.container.Composite();
  12 
  13             var layout_manager = new qx.ui.layout.Grid();
  14             layout_manager.setRowFlex(0, 1);
  15             layout_manager.setRowFlex(1, 1);
  16             layout_manager.setColumnFlex(0, 1);
  17             layout_manager.setColumnFlex(2, 1);
  18             main_container.setLayout(layout_manager);
  19 
  20             main_container.add(new qx.ui.form.Button("Child Widget 1"), {
  21                 row: 0,
  22                 column: 0,
  23                 rowSpan: 2
  24             });
  25             main_container.add(new qx.ui.form.Button("Child Widget 2"), {
  26                 row: 0,
  27                 column: 1,
  28                 colSpan: 2
  29             });
  30             main_container.add(new qx.ui.form.Button("Child Widget 3"), {
  31                 row: 1,
  32                 column: 1
  33             });
  34             main_container.add(new qx.ui.form.Button("Child Widget 4"), {
  35                 row: 1,
  36                 column: 2
  37             });
  38 
  39             var application_root = this.getRoot();
  40             application_root.add(main_container);
  41 
  42             application_root.addListener("resize", function(e) {
  43                 main_container.set({
  44                     "width": qx.bom.Viewport.getWidth(),
  45                     "height": qx.bom.Viewport.getHeight(),
  46                 });
  47             }, this);
  48         }
  49     }
  50 });
Grid Example 3

Grid Example 3

We have set rowFlex (vertical) and columnFlex (horizontal) for specific rows/columns on the layout manager itself. Try resizing the window to see how cells react. Note that second column (column index 1) doesn’t flex horizontally.

NEXT PART: Back To Basics

Bookmark and Share

Using Layouts In Qooxdoo – Part 3: HBox Layout

Sunday, February 15th, 2009

This is the third part of a tutorial series about layout managers, container objects and object hierarchies in Qooxdoo. Read the first part here.

qx.ui.layout.HBox layout manager is similar to VBox but it places its children side by side.

HBox Layout

HBox Layout

Let us begin with a simple application:

   1 /*
   2 #asset(hbox/*)
   3 */
   4 qx.Class.define("hbox.Application",
   5 {
   6     extend: qx.application.Standalone,
   7     members: {
   8         main: function(){
   9             this.base(arguments);
  10 
  11             var main_container = new qx.ui.container.Composite();
  12 
  13             var layout_manager = new qx.ui.layout.HBox();
  14             main_container.setLayout(layout_manager);
  15 
  16             main_container.add(new qx.ui.form.Button("Child Widget 1"));
  17             main_container.add(new qx.ui.form.Button("Child Widget 2"));
  18             main_container.add(new qx.ui.form.Button("Child Widget 3"));
  19 
  20             var application_root = this.getRoot();
  21             application_root.add(main_container);
  22         }
  23     }
  24 });
HBox Example 1

HBox Example 1

Ok, nothing special here. In the next example we will see how we can apply different constraints to individual child elements:

   1 /*
   2 #asset(hbox/*)
   3 */
   4 qx.Class.define("hbox.Application",
   5 {
   6     extend: qx.application.Standalone,
   7     members: {
   8         main: function(){
   9             this.base(arguments);
  10 
  11             var main_container = new qx.ui.container.Composite();
  12 
  13             var layout_manager = new qx.ui.layout.HBox();
  14             main_container.setLayout(layout_manager);
  15 
  16             main_container.add(new qx.ui.form.Button(
  17                                            "Child Widget 1").set({width:300}));
  18             main_container.add(new qx.ui.form.Button("Child Widget 2"));
  19             main_container.add(new qx.ui.form.Button(
  20                                             "Child Widget 3").set({width:75}));
  21             main_container.add(new qx.ui.form.Button(
  22                                 "Child Widget 4 has a slightly longer title"));
  23 
  24             var application_root = this.getRoot();
  25             application_root.add(main_container);
  26         }
  27     }
  28 });
HBox Example 2

HBox Example 2

We have set some properties on child widgets here. I know, it’s a bit ugly doing it on the same line with the addition. But screen space is more expensive now on the intertubes since the economic crisis1. The important point here is we have set width of first and third widgets explicitly. Second and fourth will be automatically sized. Also notice that the fourth widget is wider. Buttons consider length of their labels when calculating their sizes.

The container will also be auto-sized on creation. But it won’t fill the viewport since we haven’t coded this behaviour (see previous part). Next example will include this behaviour:

   1 /*
   2 #asset(hbox/*)
   3 */
   4 qx.Class.define("hbox.Application",
   5 {
   6     extend: qx.application.Standalone,
   7     members: {
   8         main: function(){
   9             this.base(arguments);
  10 
  11             var main_container = new qx.ui.container.Composite();
  12 
  13             var layout_manager = new qx.ui.layout.HBox();
  14             main_container.setLayout(layout_manager);
  15 
  16             main_container.add(new qx.ui.form.Button("Child Widget 1").set({
  17                 width: 300,
  18                 allowGrowX: true,
  19             }), {flex: 1});
  20             main_container.add(new qx.ui.form.Button("Child Widget 2").set({
  21                 minWidth: 75,
  22                 maxWidth: 200,
  23             }), {flex: 1});
  24             main_container.add(new qx.ui.form.Button("Child Widget 3").set({
  25                 width: 75,
  26                 allowGrowX: false,
  27             }), {flex: 1});
  28 
  29             var application_root = this.getRoot();
  30             application_root.add(main_container);
  31 
  32             application_root.addListener("resize", function(e) {
  33                 main_container.set({
  34                     "width": qx.bom.Viewport.getWidth(),
  35                 });
  36             }, this);
  37         }
  38     }
  39 });
HBox Example 3

HBox Example 3

We have quite a few changes this time. First of all each widget is set to flex. First and third widgets have their (different) widths explicitly set. Growing is enabled for the first2 and disabled for the third. For the second widget we have created different constraints; we have set the maximum and minimum values for width.

Try resizing the window to see how each widget reacts. We should note that the second widget never goes beyond its limits. While the other two conform to fit the containers space. MinWidth and MaxWidth are stronger constraints than width.

Let’s try constraining the container’s size:

   1 /*
   2 #asset(hbox/ *)
   3 */
   4 qx.Class.define("hbox.Application",
   5 {
   6     extend: qx.application.Standalone,
   7     members: {
   8         main: function(){
   9             this.base(arguments);
  10 
  11             var main_container = new qx.ui.container.Composite();
  12 
  13             var layout_manager = new qx.ui.layout.HBox();
  14             main_container.setLayout(layout_manager);
  15             main_container.set({
  16                 maxWidth: 900,
  17                 minWidth: 400,
  18             });
  19 
  20             main_container.add(new qx.ui.form.Button("Child Widget 1").set({
  21                 width: 300,
  22                 allowGrowX: true,
  23             }), {flex: 1});
  24             main_container.add(new qx.ui.form.Button("Child Widget 2").set({
  25                 minWidth: 75,
  26                 maxWidth: 200,
  27             }), {flex: 1});
  28             main_container.add(new qx.ui.form.Button("Child Widget 3").set({
  29                 width: 75,
  30                 allowGrowX: false,
  31             }), {flex: 1});
  32 
  33             var application_root = this.getRoot();
  34             application_root.add(main_container);
  35 
  36             application_root.addListener("resize", function(e) {
  37                 main_container.set({
  38                     "width": qx.bom.Viewport.getWidth(),
  39                 });
  40             }, this);
  41         }
  42     }
  43 });

We have set the maximum and minimum width for the container widget. If you resize the window you should notice the container obeying these constraints.

VBox & HBox Wrap-up

VBox and HBox are simple layout managers. I have mostly tried to illustrate how container preferences, layout preferences and child widget preferences work together with examples. In the next chapters we’ll work on more advanced layout managers and then composite layouts with multiple containers.

NEXT PART: Grid Layout


1: This is a lame joke, I’ve just done that for the sake of brevity.

2: This is redundant. Grow and Shrink properties are true by default.

Bookmark and Share