Examples of using crush


[] introduction, legacy, interfaces, examples, conclusions, references, appendix
The hush CORBA extensions may be used in a number of ways. For example, the client does not need to be linked with hush when only the server side is given a graphical user interface. In case also the client has a graphical user interface, the client side may dispatch incoming events to the server, as illustrated in the Canvas example. The communication between server and clients can be arbitrarily complex. The final example shows how to employ iterators and containers to give clients access to collections of information.

A remote interpreter kit

This example uses a remote kit. It shows how to get access to a message widget and a kit via a dot (which is a distributed object table). The client access the kit and the message widget by using a name (hello for the message widget and tk for the kit). The client can send Tcl/Tk interpreter commands to the kit.

A tk client

      hush::dot*      hush;      // (distributed) object tables
      widgets::dot*   widgets;   // widgets contains hush
  
      hush::kit* tk;             // remote objects, these must exist!
      widgets::message* banner;
  
      try {
          hush = widgets = widgets::dot::_bind (DOT, argv[1]);
  
          tk = hush->kit("tk");
          banner = widgets->message("hello"); // must exist
  
      } catch (...) {
           cerr << "Unexpected exception ..." << endl;
           return -1;
      }
  
      while (1) {
  	char text = readtext(); // from stdin
  	
  	banner->text( text );  // display text
  	tk->eval(text);
          }
  

slide: A tk client

This fragment shows how a distributed object table is obtained via the bind function. From this table, the client obtains a kit and a message area. Queries are read in from standard input, displayed in the message area and evaluated. Queries may be arbitrary Tcl/Tk commands. In this way the client may even construct a complete user interface through Tk commands.

The tk server

  class application : public session {
  public:
  application(int argc, char* argv[]) : session(argc,argv,"hello") {
  }
  void corba();
  int main() {
      tk->trace();
      kit::declare("tk",tk);
  
      message* m = new hello(".hello"); 
      m->pack();
  
      message::declare("hello",m);
  
      corba(); // make yourself available as a server
  
      return OK;
      }
  };
  

slide: The tk server

The server is realized as a standard hush program, except for the call to corba (for which the code is given below). Note that the calls to declare for both the kit and message objects is needed to make these objects accessible via the dot.

A tk application

  void application::corba() {
  
  widgets::dot* dw = new widgets_dot_srv(); // create dot for widgets
  
  try {
   CORBA::Orbix.registerIOCallback(it_orbix_fd_open, FD_OPEN_CALLBACK);
   CORBA::Orbix.registerIOCallback(it_orbix_fd_close, FD_CLOSE_CALLBACK);
  
   CORBA::Orbix.impl_is_ready(DOT,0);
   CORBA::Orbix.processEvents(0);
   }
  catch (...) {
       cout << "apparently something went wrong" << endl;
     }
  

slide: A tk application

In application::corba() a distributed object table is created. This object is exported as a server by a call to Orbix.impl_is_ready(DOT,0), where DOT is a macro defining the name of the server. Calling registerIOCallback is needed to merge the CORBA server event loop with the window event loop for hush.

Evaluating logical queries

With a few minor changes, the client program can be adapted for accessing a logical query evaluator.

Evaluating logical queries

      try {
  
          tk = hush->kit("bp");       // A kit for BinProlog
          tk->eval("consult(facts)");
          }
      catch(...) {
          cout << "An exception ... " << endl;
      }
  
      while (1) {
      	char* text = readtext();
          tk->eval(text);
          hush::term* t = tk->result();
          char* q = 0;
          while ( (q = t->next()) )
                  cout << "Result: " << q << endl;
  	}
  

slide: Evaluating logical queries

This fragment show how to obtain a kit for BinProlog and consult a facts database. Since queries may produce multiple answers the client must iterate over the term resulting from the query.

A remote canvas

This example shows how a client canvas can be used to draw on a remote canvas. For the Orbix 1.3 version there are still several bugs. Events do not work as they should, and quitting the remote application also does not work.

A canvas client

  class draw_clt : public canvas {  
[2]
public: void plug(widgets::canvas* x) { draw = x; } int operator()() { hush::event* e = hush->event(_event->type()); cerr << "Getting event " << e->type() << endl; e->x(_event->x()+10); e->y(_event->y()+10); //hush::event::_duplicate(e); // CORBA 2.0 e->_duplicate(); hush::event* res = draw->dispatch(e); return canvas::operator()(); } draw_clt(const widget* w, char* path ) : canvas(w,path) { configure("-background white"); geometry(200,100); self()->bind(this); dragging = 0; } draw_clt(char* path ) : canvas(path) { configure("-background white"); geometry(200,100); self()->bind(this); dragging = 0; } void press( event& ) { dragging = 1; } void motion( event& e) { if (dragging) { self()->circle(e.x(),e.y(),2,"-fill black"); draw->circle(e.x(),e.y(),3,"-fill yellow"); } } void release( event& ) { dragging = 0; } protected: int dragging; widgets::canvas* draw; };

slide: A (remote) canvas client

This fragmemt shows the implementation of a canvas which is simultaneously the client side of a remote canvas. The method plug allows for declaring the remote canvas, which is accessed via the instance variable draw in both the operator method and the motion method (whent dragging). In the operator() an event is created which is dispatched to the remote canvas. Note that this is possible since a canvas is a handler. In the motion method, a large yellow dot is drawn on the remote canvas, whereas the local canvas draws a black dot. Combined, the actions on the remote canvas result in drawing parallel yellow and black dots.

The server


A canvas server

  class draw_srv : public canvas {  
  public:
  
  draw_srv( const widget* w,  char* path ) : canvas(w,path) {  
(a)
geometry(200,100); self()->bind(this); dragging = 0; } void press( event& ) { dragging = 1; } void motion( event& e) { if (dragging) circle(e.x(),e.y(),10,"-fill black"); } void release( event& ) { dragging = 0; } protected: int dragging; };

slide: A canvas server

The canvas implementation on the server side straightforwardly implements a hush canvas. It is embedded in a CORBA server when an object reference is given to it via the distributed object table.

Moving items

This example is similar to the Canvas example, but shows some additional features, such as how to manipulate a list of items.

Moving items

      list<hush::item>* rlist =  new list<hush::item>;
      item* it = draw->circle(40,40,10,"-fill yellow");
      hush::item* rit = new item_srv(it);
      rlist->insert(rit);
      it = draw->circle(30,30,10,"-fill red");
      rit = new item_srv(it);
      rlist->insert(rit);
  
      hush::container* rx = new list_srv<hush::item>(rlist);
      list<hush::item>::declare("items",rx); // store server
  
      iter<hush::item>* riter = rlist->walk();
      iter<hush::item>::declare("riter",riter);
  

slide: Moving items

The fragment above illustrates the creation of a list of items. In addition it shows how to obtain an iterator and how the iterator may be declared to make it accessible via the distributed object table.
[] introduction, legacy, interfaces, examples, conclusions, references, appendix