
TOAD is...
Learn more:
The TOAD C++ GUI Library provides some standard features found in other GUI libraries like
The following features are unique:
Other planned features are, for example, a C++ scripting language to create a complete User Interface Management System (UIMS) for Rapid Prototyping.
Stable means that the API will not change for all 0.64.x releases.
toad-0.64.1.tar.bz2 [gpg sig] (uploaded Tue, 03 July 2007 22:30:40)
Requires GNU C++ 3.0 or higher, the X Window System, libpng and fontconfig 2.2.0 or higher.
Development releases are available via Subversion:
svn checkout https://svn.mark13.org/toad/trunk/toad toad cd toad svn checkout https://svn.mark13.org/toad/trunk/examples examples
There is also an experimental port to Mac OS X:
svn checkout https://svn.mark13.org/cocoa/trunk cocoa

This program subclasses the class TMyWindow from TOAD's window class TWindow and displays it.
The command
g++ `toad-config --cxxflags --libs` hello.cc
will compile the program.
// include declarations of TOAD basic classes
#include <toad.hh>
// use the TOAD namespace
using namespace toad;
// define a new window class, based on TWindow
class TMyWindow:
public TWindow
{
public:
// typical constructor for windows
TMyWindow(TWindow *parent, const string &title)
:TWindow(parent, title) {}
// define a new method to paint the windows content
void paint() {
// create a pen for this window and use it to...
TPen pen(this);
// ...draw a text at position (50, 50)
pen.drawString(50, 50, "Hello World!!!");
}
};
// initialize TOAD, create window and enter the message loop
int
main(int argc, char **argv, char **envv)
{
// initialize TOAD library
toad::initialize(argc, argv, envv);
// create window
TMyWindow *window = new TMyWindow(0, "Hello World");
// show window and handle user input until window is closed
toad::mainLoop();
// the window has been closed so we dispose of the object
delete window;
// clean up TOAD
toad::terminate();
return 0;
}

The dialog editor is integrated into the library and can be used at runtime.
This was done because most ideas on how to fine tune the layout of a program come when one actually uses the program.
Step 1: Write the Code
#include <toad/toad.hh>
#include <toad/dialog.hh>
#include <toad/textfield.hh>
#include <toad/pushbutton.hh>
class TMyWindow:
public TDialog
{
public:
TMyWindow(TWindow *parent, const string &title);
void printData();
// the data we're going to edit
TTextModel name, surname;
TUnsignedModel age;
};
int
main(int argc, char **argv, char **envv)
{
toad::initialize(argc, argv, envv);
{
// tell TOAD where to store/read the resource files
TOADBase::setResourcePrefix("file://resource/");
TMyWindow(NULL, "MyWindow");
// start the application
toad::mainLoop();
}
toad::terminate();
return 0;
}
TMyWindow::TMyWindow(TWindow *parent, const string &title):
TDialog(parent, title)
{
// create the widgets
TTextField *tf;
tf = new TTextField(this, "name", &name);
tf = new TTextField(this, "surname", &surname);
tf = new TTextField(this, "age", &age);
TPushButton *pb;
pb = new TPushButton(this, "print");
CONNECT(pb->;sigActivate, this, printData);
pb = new TPushButton(this, "quit");
CONNECT(pb->sigActivate, this, closeRequest);
// set a resource name for the layout
doLayout("MyWindow");
}
void
TMyWindow::printData()
{
// print the data
cout << "Name : " << name << endl
<< "Surname: " << surname << endl
<< "Age : " << age << endl;
}
Step 2: Execute your program

make ./program --layout-editor
When no earlier layout exists all the widgets are placed in the upper left corner of the window.
Step 3: Layout your widgets

Enable the layout editor and use the mouse to move and resize the widgets. You can even add additional graphical elements.
The dialog editor used here is names "TDialogLayout", which is the default for dialog windows. But one can easily use other layout algorithms, for example TSpringLayout.
Step 4: Fin

Once the layout is finished you can save the layout.
GUI applications are event driven, eg. the user pushes a button and an email is sent. The common way to do this is to create a TPushButton object and to instruct it to call you back when is was pushed:
class TMailApplication:
public TWindow
{
public:
TMailApplication() {
...
// create a pushbutton and...
TPushButton *btn = new TPushButton(this, "Send emailpush me");
// ... and tell it to call 'this->sendMail()' when it is pushed
CONNECT(btn->sigClicked, this, sendMail);
...
}
void sendMail() {
cout << "calling 'sendmail'" << endl;
...
}
};
The following happens here:
Below are some more examples to get the feel of it.
A feature which do I consider extremly cool is the TCLOSURE macro below. It mimics SmallTalk closures and allows you to write the code to be called back at the same place where you connect it to TSignal.
#include <toad/connect.hh>
struct TMySource
{
TSignal sigAction;
int value;
int getValue() { return value; }
};
struct TMyDestination
{
void doIt(int n) { cout << "doIt: " << n << endl; }
};
int
main()
{
TMySource *source = new TMySource();
source->value = 42;
TMyDestination *destination = new TMyDestination();
// ANSI C+ compatible call interface
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
connect(
source->sigAction, // when triggered
destination, &TMyDestination::doIt); // call method
connect_value_of(
source->sigAction, // when triggered
destination, &TMyDestination::doIt, // call method
source, &TMySource::getValue); // with the return value of method
connect_value_of(
source->sigAction, // when triggered
destination, &TMyDestination::doIt, // call method
&source->value); // with the return value of variable
connect_value(
source->sigAction, // when triggered
destination, &TMyDestination::doIt, // call method
source); // with the return value of 'getValue()'
// GNU C++ compatible call interface
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
CONNECT(
source->sigAction, // when triggered
destination, doIt); // call method
CONNECT_VALUE_OF(
source->sigAction, // when triggered
destination, doIt, // call method
source, getValue()); // with the return value of method
CONNECT_VALUE(
source->sigAction, // when triggered
destination, doIt, // call method
source); // with the return value of 'getValue()'
TCLOSURE2( // closure with two variables
source->sigAction, // the signal
dst, destination, // dst := destination
src, source, // src := source
dst->doIt(src->getValue()*10); // and execute this code
)
// triggering a signal
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
source->sigAction();
// disconnecting a signal
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
disconnect(source->sigAction); // remove all links
}