16 min read

(For more resources on this topic, see here.)

qooxdoo uses the generic terminology of the graphical user interface. So, it is very easy to understand the concepts involved in it.. The basic building block in qooxdoo is termed a widget. Each widget (GUI component) is a subclass of the Widget class. A widget also acts as a container to hold more widgets. Wherever possible, grouping of the widgets to form a reusable component or custom widget is a good idea. This allows you to maintain consistency across your application and also helps you to build the application quicker than the normal time. It also increases maintainability, as you need to fix the defect at only one place. qooxdoo provides a set of containers too, to carry widgets, and provides public methods to manage.

Let’s start with the framework’s class hierarchy:

Base classes for widgets

qooxdoo framework abstracts the common functionalities required by all the widgets into a few base classes, so that it can be reused by any class through object inheritance. Let’s start with these base classes.

qx.core.Object

Object is the base class for all other qooxdoo classes either directly or indirectly. The qx.core.Object class has the implementation for most of the functionalities, such as, object management, logging, event handling, object-oriented features, and so on.

A class can extend the qx.core.Object class to get all the functionalities defined in the this class. When you want to add any functionality to your class, just inherit the Object class and add the extra functionalities in the subclass.

The major functionalities of the Object class are explained in the sections that follow.

Object management

 

The Object class provides the following methods for object management, such as, creation, destruction, and so on:

  • base(): This method calls base class method
  • dispose(): This method disposes or destroys the object
  • isDisposed(): This method returns a true value if the object is disposed
  • toString(): This method returns the object in string format
  • toHashCode(): This method returns hash code of the object

Event handling

The Object class provides the following methods for event creation, event firing, event listener, and so on:

  • addListener(): This method adds the listener on the event target and returns the ID of the listener
  • addListenerOnce(): This method adds the listener and listens only to the first occurrence of the event
  • dispatchEvent(): This method dispatches the event
  • fireDataEvent(): This method fires the data event
  • fireEvent(): This method fires the event
  • removeListener(): This method removes the listener
  • removeListenerById(): This method removes the listener by its ID, given by addListener()

Logging

The Object class provides the following methods to log the message at different levels:

  • warn(): Logs the message at warning level
  • info(): Logs the message at information level
  • error(): Logs the message at error level
  • debug(): Logs the message at the debugging level
  • trace(): Logs the message at the tracing level

Also, the Object class provides the methods for setters and getters for properties, and so on.

qx.core.LayoutItem

LayoutItem is the super most class in the hierarchy. You can place only the layout items in the layout manager. LayoutItem is an abstract class. The LayoutItem class mainly provides properties, such as, height, width, margins, shrinking, growing, and many more, for the item to be drawn on the screen. It also provides a set of public methods to alter these properties. Check the API documentation for a full set of class information.

qx.core.Widget

Next in the class hierarchy is the Widget class, which is the base class for all the GUI components. Widget is the super class for all the individual GUI components, such as, button, text field, combobox, container, and so on, as shown in the class hierarchy diagram. There are different kinds of widgets, such as, containers, menus, toolbars, form items, and so on; each kind of widgets are defined in different namespaces. We will see all the different namespaces or packages, one-by-one, in this article.

A widget consists of at least three HTML elements. The container element, which is added to the parent widget, has two child elements—the decoration and the content element. The decoration element decorates the widget. It has a lower z-index and contains markup to render the widget’s background and border styles, using an implementation of the qx.ui.decoration.IDecorator interface. The content element is positioned inside the container element, with the padding, and contains the real widget element.

Widget properties

Common widget properties include:

 

  • Visibility: This property controls the visibility of the widget. The possible values for this property are:
    • visible: Makes the widget visible on screen.
    • hidden: Hides the widget, but widget space will be occupied in the parent widget’s layout. This is similar to the CSS style visibility:hidden.
    • exclude: Hides the widget and removes from the parent widget’s layout, but the widget is still a child of its parent’s widget. This is similar to the CSS style display:none.
    • The methods to modify this property are show(), hide(), and exclude(). The methods to check the status are isVisible(), isHidden(), and isExcluded().

  • Tooltip: This property displays the tooltip when the cursor is pointing at the widget. This tooltip information consists of toolTipText and toolTipIcon. The different methods available to alter this property are:
    • setToolTip()/getToolTip(): Sets or returns the qx.ui.tooltip.ToolTip instance. The default value is null.
    • setToolTipIcon()/getToolTipIcon(): Sets or returns the URL for the icon. The default value is null.
    • setToolTipText()/getToolTipText(): Sets or returns the string text. It also supports the HTML markup. Default value is null.
  • Text color: The textColor property sets the frontend text color of the widget. The possible values for this property are any color or null.
  • Padding: This property is a shorthand group property for paddingTop, paddingRight, paddingBottom and paddingLeft of the widget. The available methods are setPadding() and resetPadding(), which sets values for top, right, bottom, and left padding, consecutively. If any values are missing, the opposite side values will be taken for that side. Also, set/get methods for each padding side are also available.
  • Tab index: This property controls the traversal of widgets on the Tab key press. Possible values for this property are any integer or null. The traversal order is from lower value to higher value. By default, tab index for the widgets is set in the order in which they are added to the container. If you want to provide a custom traversal order, set the tab index accordingly. The available methods are setTabIndex() and getTabIndex(). These methods, respectively set and return the integer value (0 to 32000) or null.
  • Font: The Font property defines the font for the widget. The possible value is either a font name defined in the theme, or an instance of qx.bom.Font, or null.
      The available methods are:
    • setFont(): Sets the font
    • getFont(): Retrieves the font
    • initFont(): Initializes the font
    • resetFont(): Resets the font
  • Enabled: This property enables or disables the widget for user input. Possible values are true or false (Boolean value). The default value is true. The widget invokes all the input events only if it is in the enabled state. In the disabled state, the widget will be grayed out and no user input is allowed. The only events invoked in the disabled state are mouseOver and mouseOut. In the disabled state, tab index and widget focus are ignored. The tab traversal focus will go to the next enabled widget. setEnabled()/getEnabled() are the methods to set or get a Boolean value, respectively.
  • Selectable: This property says whether the widget contents are selectable. When a widget contains text data and the property is true, native browser selection can be used to select the contents. Possible values are true or false. The default value is false. setSelectable(), getSelectable(), initSelectable(), resetSelectable(), and toggleSelectable() are the methods available to modify the Selectable property.
  • Appearance: This property controls style of the element and identifies the theme for the widget. Possible values are any string defined in the theme; the default value is widget. setAppearence(), getAppearence(), initAppearence(), and resetAppearence() are the methods to alter the appearance.
  • Cursor: This property specifies which type of cursor to display on mouse over the widget. The possible values are any valid CSS2 cursor name defined by W3C (any string) and null. The default value is null. Some of the W3C-defined cursor names are default, wait, text, help, pointer, crosshair, move, n-resize, ne-resize, e-resize, se-resize, s-resize, sw-resize, w-resize, and nw-resize. setCursor(), getCursor(), resetCursor(), and initCursor() are the methods available to alter the cursor property.

qx.application

The starting point for a qooxdoo application is to write a custom application class by inheriting one of the qooxdoo application classes in the qx.application namespace or package. Similar to the main method in Java, the qooxdoo application also starts from the main method in the custom application class.

qooxdoo supports three different kinds of applications:

  • Standalone: Uses the application root to build full-blown, standalone qooxdoo applications.
  • Inline: Uses the page root to build traditional web page-based applications, which are embedded into isles in the classic HTML page.
  • Native: This class is for applications that do not involve qooxdoo’s GUI toolkit. Typically, they only make use of the IO (AJAX) and BOM functionality (for example, to manipulate the existing DOM).

Whenever a user creates an application with the Python script, a custom application class gets generated with a default main method. Let’s see the custom application class generated for our Team Twitter application. After generation, the main function code is edited to add functionality to communicate to the RPC server and say “hello” to the qooxdoo world. The following code is the content of the Application.js class file with an RPC call to communicate with the server:

/** * This is the main application class of your custom application "teamtwitter" */ qx.Class.define("teamtwitter.Application", { extend : qx.application.Standalone, members : { /** * This method contains the initial application code and gets called during startup of the application * @lint ignoreDeprecated(alert) */ main : function() { // Call super class this.base(arguments); // Enable logging in debug variant if (qx.core.Variant.isSet("qx.debug", "on")) { // support native logging capabilities, e.g. Firebug for Firefox qx.log.appender.Native; // support additional cross-browser console. Press F7 to toggle visibility qx.log.appender.Console; } /* Below is your actual application code... */ // Create a button var button1 = new qx.ui.form.Button("First Button", "teamtwitter/test.png"); // Document is the application root var doc = this.getRoot(); // Add button to document at fixed coordinates doc.add(button1, {left: 100, top: 50}); // Add an event listener button1.addListener("execute", function(e) { var rpc = new qx.io.remote.Rpc(); rpc.setCrossDomain( false ); rpc.setTimeout(1000); var host = window.location.host; var proto = window.location.protocol; var webURL = proto + "//" + host + "/teamtwitter/.qxrpc"; rpc.setUrl(webURL); rpc.setServiceName("qooxdoo.test"); rpc.callAsync(function(result, ex, id){ if (ex == null) { alert(result); } else { alert("Async(" + id + ") exception: " + ex); } }, "echo", "Hello to qooxdoo World!"); }); } } });

We’ve had an overview of the class hierarchy of the qooxdoo framework and got to know the base classes for the widgets. Now, we have an idea of the core functionalities available for the widgets, the core properties of the widgets, and the methods to manage those properties. We’ve received more information on the application in the qooxdoo framework.

Now, it is time to learn about the containers.

Containers

A container is a kind of widget. It holds multiple widgets and exposes public methods to manage their child widgets. One can configure a layout manager for the container to position all the child widgets in the container. qooxdoo provides different containers for different purposes.

Let’s check different containers provided by the qooxdoo framework and understand the purpose of each container. Once you understand the purpose of each container, you can select the right container when you design your application.

Scroll

Whenever the content widget size (width and height) is larger than the container size (width and height), the Scroll container provides vertical, or horizontal, or both scroll bars automatically. You have to set the Scroll container’s size carefully to make it work properly. The Scroll container is used most commonly if the application screen size is large.

The Scroll container has a fixed layout and it can hold a single child. So, there is no need to configure the layout for this container.

The following code snippet demonstrates how to use the Scroll container:

// create scroll container
var scroll = new qx.ui.container.Scroll().set({
width: 300,
height: 200
});
// adding a widget with larger widget and height of the scroll
scroll.add(new qx.ui.core.Widget().set({
width: 600,
minWidth: 600,
height: 400,
minHeight: 400
})); // add to the root widget.
this.getRoot().add(scroll);

The GUI look for the preceding code is as follows:

Stack

The Stack container puts a widget on top of an old widget. This container displays only the topmost widget. The Stack container is used if there are set of tasks to be carried out in a flow. An application user can work on each user interface one-by-one in order.

The following code snippet demonstrates how to use the Stack container:

// create stack container
var stack = new qx.ui.container.Stack();
// add some children
stack.add(new qx.ui.core.Widget().set({
backgroundColor: "red"
}));
stack.add(new qx.ui.core.Widget().set({
backgroundColor: "green"
}));
stack.add(new qx.ui.core.Widget().set({
backgroundColor: "blue"
}));
this.getRoot().add(stack);

The GUI look for the preceding code is as follows:

Resizer

Resizer is a container that gives flexibility for resizing at runtime. This container should be used only if you want to allow the application user to dynamically resize the container.

The following code snippet demonstrates how to use the Resizer container:

var resizer = new qx.ui.container.Resizer().set({
marginTop : 50,
marginLeft : 50,
width: 200,
height: 100
});
resizer.setLayout(new qx.ui.layout.HBox());
var label = new qx.ui.basic.Label("Resize me
I'm resizable");
label.setRich(true);
resizer.add(label);
this.getRoot().add(resizer);

The GUI look for the preceding code is as follows:

Composite

This is a generic container. If you do not want any of the specific features, such as, resize on runtime, stack, scroll, and so on, but just want a container, you can use this container. This is one of the mostly used containers.

The following code snippet demonstrates the Composite container usage. A horizontal layout is configured to the Composite container. A label and a text field are added to the container. The horizontal layout manager places them horizontally:

// create the composite
var composite = new qx.ui.container.Composite()
// configure a layout.
composite.setLayout(new qx.ui.layout.HBox());
// add some child widgets
composite.add(new qx.ui.basic.Label("Enter Text: "));
composite.add(new qx.ui.form.TextField());
// add to the root widget.
this.getRoot().add(composite);

The GUI look for the preceding code is as follows:

Window

Window is a container that has all features, such as, minimize, maximize, restore, and close. The icons for these operations will appear on the top-right corner. Different themes can be set to get the look and feel of a native window within a browser. This window is best used when an application requires Multiple Document Interface (MDI) or Single Document Interface (SDI). The following code snippet demonstrates a window creation and display:

var win = new qx.ui.window.Window("First Window");
win.setWidth(300);
win.setHeight(200);
// neglecting minimize button
win.setShowMinimize(false);
this.getRoot().add(win, {left:20, top:20});
win.open();

The GUI look for the preceding code is as follows:

TabView

The TabView container allows you to display multiple tabs, but only one tab is active at a time. The TabView container simplifies the GUI by avoiding the expansive content spreading to multiple pages, with a scroll. Instead, the TabView container provides the tab title buttons to navigate to other tabs. You can group the related fields into each tab and try to avoid the scroll by keeping the most-used tab as the first tab and making it active. Application users can move to other tabs, if required.

TabView is the best example for the stack container usage. It stacks all pages one over the other and displays one page at a time. Each page will have a button at the top, in a button bar, to allow switching the page. Tabview allows positioning the button bar on top, bottom, left, or right. TabView also allows adding pages dynamically; a scroll appears when the page buttons exceed the size.

The following code snippet demonstrates the usage of TabView:

var tabView = new qx.ui.tabview.TabView();
// create a page
var page1 = new qx.ui.tabview.Page("Layout",
"icon/16/apps/utilitiesterminal.png");
// add page to tabview
tabView.add(page1);
var page2 = new qx.ui.tabview.Page("Notes",
"icon/16/apps/utilitiesnotes.png");
page2.setLayout(new qx.ui.layout.VBox());
page2.add(new qx.ui.basic.Label("Notes..."));
tabView.add(page2);
var page3 = new qx.ui.tabview.Page("Calculator", "icon/16/apps/
utilities-calculator.png");
tabView.add(page3);
this.getRoot().add(tabView, {edge : 0});

The GUI look for the preceding code is as follows:

GroupBox

GroupBox groups a set of form widgets and shows an effective visualization with the use of a legend, which supports text and icons to describe the group. As with the container, you can configure any layout manager and allow adding a number of form widgets to the GroupBox.

Additionally, it is possible to use checkboxes or radio buttons within the legend. This allows you to provide group functionalities such as selecting or unselecting all the options in the group. This feature is most important for complex forms with multiple choices.

The following code snippet demonstrates the usage of GroupBox:

// group box
var grpBox = new qx.ui.groupbox.GroupBox("I am a box");
this.getRoot().add(grpBox, {left: 20, top: 70});
// radio group box
var rGrpBox = new qx.ui.groupbox.RadioGroupBox("I am a box");
rGrpBox.setLayout(new qx.ui.layout.VBox(4));
rGrpBox.add(new qx.ui.form.RadioButton("Option1"));
rGrpBox.add(new qx.ui.form.RadioButton("Option2"));
this.getRoot().add(rGrpBox, {left: 160, top: 70});
// check group box
var cGrpBox = new qx.ui.groupbox.CheckGroupBox("I am a box");
this.getRoot().add(cGrpBox, {left: 300, top: 70});

The GUI look for the preceding code is as follows:

We got to know the different containers available in the qooxdoo framework. Each container provides a particular functionality. Based on the information displayed on the GUI, you should choose the right container to have better usability of the application.

Containers are the outer-most widgets in the GUI. Once you decide on the containers for your user interface, the next thing to do is to configure the layout manager for the container. Layout manager places the child widgets in the container, on the basis of the configured layout manager’s policies. Now, it’s time to learn how to place and arrange widgets inside the container, that is, how to lay out the container.


Subscribe to the weekly Packt Hub newsletter

* indicates required

LEAVE A REPLY

Please enter your comment!
Please enter your name here