Ubit Toolkit: Quick Tutorial

Eric Lecolinet - ENST

Ubit Home Page - Documentation Main Page - Examples and Tutorial


The following steps show how to create a simple text editor.

Step 1: A Simple application: sedit1.cpp

This section shows how to create a Ubit application. This application creates a main window that contains a multiline text editing widget (source code in file: sedit1.cpp)

#include <ubit/ubit.hpp>
using namespace ubit;

class SEdit : public UFrame {
public:
  SEdit();
private:
  UTextarea textbox;    // the text area widget
  UStr      content;    // the string contained in the textbox
};

The first thing to do is to include the ubit header and tell the compiler that we will use the ubit namespace. We can now define SEdit, the main class of our application. It derives from UFrame which is the class for toplevel windows. SEdit have two variables.

These variables are not pointers but C++ "plain" objects (which means that the variables contain the object instead of pointing to it). These objects are automatically created and initialized when an instance of SEdit is created. This syntax is typical of C++ but does not exist in Java (we should use pointers and the new primitive to create each object). We'll see how to use C++ pointers in a safe way at a later stage.

int main(int argc, char* argv[]) {
  UAppli appli(argc, argv);
 
  SEdit sedit;
  appli.add(sedit);
  sedit.show();
 
  return appli.start();
}
The main() function performs the following actions: We must now write the body of the SEdit constructor:
SEdit::SEdit() {	
  content = "Editable text";
  textbox.add(content);
  this->addlist( uwidth(400) + uheight(300) + textbox);
}

Step 2: Properties: sedit2.cpp

This example shows how to define widget properties such as the size, the scale, the font, the background and foreground colors, etc. (source code in file: sedit2.cpp)

We introduced the UWidth and UHeight properties in the previous section to specify the size of the main frame:

  addlist(uwidth(400) + uheight(300) + textbox);
First, it is important to notice that we can add properties to widgets by using the add() and the addlist() methods. In fact, these methods can be used to add almost any Ubit object to a widget

Second, a major feature of the Ubit toolkit is that widgets don't have properties of their own. This is very different from a toolkit such as Java Swing where most widgets have their own font, foreground and backround color, etc. Ubit widgets are just very ligthweithed "empty" containers. Their default appearence is specified by their style (each widget class is associated to a UStyle object that defines its appearance). Besides, graphical properties, such as the font or the foreground color, are often inherited from the parents of the widget (styles also define which properties are inherited).

This model is very similar to XML or HTML. For instance a <p> or a <h1> nodes have default apperances in HTML. This can be modified by changing their style or by adding attributes to them. Ubit widgets work exactly in the same way: to change a widget appearance, one can modify its associated UStyle or just add properties to it as in the following example:

  textbox.addlist(UFont::bold + UColor::red + UBgcolor::yellow + content);
This source code adds 3 properties to 'textbox'. They specify its font, its foreground color and its background color. UFont::bold, UColor::red and UBgcolor::yellow are predefined constants of the UFont, UColor and UBgcolor classes. Of course, we could also use instances of these classes as we did before with UWidth and UHeight; for instance:
  textbox.addlist(ucolor("pink") + uscale(2.5) + content);
which is equivalent to:
  textbox.addlist(*new UColor("pink") + *new UScale(2.5) + content);
Colors can be specified from predefined constants, color names or RGB values (see class UColor). The UBgcolor::none constant specifies that the widget is fully transparent. The UAlpha property controls its level of transparency. The UBackground property associates a background image or a pattern to the widget.

UScale is another interesting property which specifies the scale of the widget. Its argument is the magnifying factor that is applied to the object. A value < 1 reduces its size, a value > 1 increases it (note that this value should be positive).

Of course, properties can also be variables. This is what we are going to do now so that we will be able to change the properties of the 'textbox' widget interactively (this will be done in the next section when we see callbacks). Here is the new definition od class SEdit:

class SEdit : public UFrame {
public:
  SEdit();
private:
  UTextarea textbox;
  UStr      content;
  UFont     font;
  UColor    color;
  UBgcolor  bgcolor;
  UScale    scale;
};
And the new version of its constructor:
SEdit::SEdit() {	
  content = "Editable text";
  font = UFont::bold;
  color.set(255, 0, 0);   // RGB spec
  bgcolor = UBgcolor::yellow;
  scale = 2.5;
  textbox.addlist(font + color + bgcolor + scale + content);
  addlist( uwidth(400) + uheight(300) + textbox);
}
Final remarks: Properties have many other interesting features: Finally, the Ubit tookit also provides more sophisticated features such as attribute lists and the ability to create multimedia and hypermedia documents that combines images, multiformatted text and hyperlinks. These capabilities will be shown in another section.


Step 3: Callback functions and methods: sedit3.cpp

This example shows how to define callback functions and callback methods Note that this example has an ugly layout. This problem will ne solved in the next section. (source code in file: sedit3.cpp)

The declaration of the SEdit class contains what precedes plus:

class SEdit : public UFrame {
  ....                        // same as above
  void setFont(UFont*);
};

void showMsg(const char* msg) {
  cout << "message " << msg << endl;
}
setFont() ia a callback method that will change the font of the 'textbox'. showMsg() is a callback function that will print some useful message on the terminal. Here is the beginning of the new definition of the SEdit constructor:
SEdit::SEdit() {	
  content = "Editable text";
  textbox.addlist(font + color + bgcolor + scale + content);
  
  UBox& font_box = uhbox 
    (UPix::edit + "Font: "
     + ubutton("Bold"   + ucall(this, &UFont::bold,   &SEdit::setFont))
     + ubutton("Italic" + ucall(this, &UFont::italic, &SEdit::setFont))
     + ubutton("Normal" + ucall(this, &UFont::normal, &SEdit::setFont))
     );
First, UBox& font_box = uhbox( ... ) creates a new UHbox object. UHbox is a horizontal box (UVbox is a vertical box). This expression is equivalent to: UBox& font_box = *new UHbox( ... ).

UBox& font_box is not an instance variable of SEdit but a local variable of the constructor, because there is no need to keep track of it after initialisation time. As for the addlist() method, The uhbox( ) shortcut function (and the UHbox( ) constructor) can take a +list as an argument. This +list contains:

Each button contains; As setFont is a SEdit method, the first argument of the ucall expression must be a SEdit instance. The second argument is given as a parameter to the setFont() method. A callback method, such as setFont, can have 0 to 2 parameters (instead of 1 in this example). The number and the type of the arguments given to the ucall expression must match with those of the called method, or the program won't compile. Here is the second part of the SEdit constructor:
  UBox& color_box = uhbox
    (UPix::colors + "Colors: "
     + ubutton("Red"   + uset(&color, &UColor::red))
     + ubutton("Blue"  + uset(&color, &UColor::blue))
     + ubutton("Green" + uset(&color, &UColor::green))
     );
This piece of code is similar to the previous one except that we use the uset( ) construct. uset( ) is shortcut that calls the set( ) method of its argument. For instance:
uset(&color, &UColor::red)
means that: color->set (&UColor::red) will be called when the button is activated. Obviously, this constructs will only work is the the first argument of uset() has a set() method. Note that we could also have use uset() in the previous case.

The last part of the SEdit constructor is:

  UBox& event_box = uhbox 
    (UPix::edit + "Font: " xxxxxxx
     + ubutton("Event test"
                + ucall(this, &UFont::bold,   &SEdit::setFont))
     + ubutton("Italic" + ucall(this, &UFont::italic, &SEdit::setFont))
     + ubutton("Normal" + ucall(this, &UFont::normal, &SEdit::setFont))
     );

  addlist
    (uwidth(400) + uheight(300) 
    + textbox + font_box + color_box + event_box
  );
  }
(to be continued)

Step 4: Layout

Examples sedit4.cpp and LayoutAndText.cpp shows how to create editable text and how to specify simple layout constraints.
The main frame contains 3 parts: a tool bar, a text area contained in a scroll pane and status bar. These 3 elements are flexible in the horizontal direction. The scroll pane is also flexible in the vertical dimension. These behaviors are specified by inserting uhflex(), utop(), uvflex(), ubottom() in the child list of the UFrame.

The tool bar contains a text field with an editable string. This text is appended to the central text area when pressing the Return key or clicking the "Ok" button.


(to be continued)