example simple bwise widget block use

by Theo Verelst but of course as always feel free to add.

In this time of UI confusion and a lot of great looking things getting started (in general I mean not tk) it is not so clear anymore what the elements of a UI can simply be and how they could work together in a simple enough or effectively defined way.

Object models get in the way, detailed knowledge about graphics and process scheduling are needed, and the programming of simple graphical examples since the time of windows and X has not been exactly trivialized the last decades.

It should be possible to keep some things simple enough though, and this page, building on the bwise package, should at least at second thought make some things simpler and more overseeable for some not very complicated or involved User Interface examples.

Check out the bwise page for download links, and a bwise introduction with graphical examples. Currently this one-file version of bwise is the latest: [1 ] ; download it and run it with wish or double click it. In fact you might want to add command(s) to the bottom of the file (or a personal startup script calling it) to make sure a console window comes up:

 # my startup file for bwise
 set mybwisepath "" ;        # fill in when you want/need, current dir per default
 source [file join $mybwisepath bwise034.tcl]
 console show                # when on windows (and I guess some old macs)
 # source unixconsole.tcl    # when you are on linux/unix/osx (I guess)

You should now see the bwise main window (in the . toplevel), the procedure window, and a console window to type commands in on your screen.

for the simplest idea of how a UI can work the bwise way, create these blocks:

 newentry 60 30 {} {} 162 79
 newmon 0 80 65 {} {} 375 79
 newproc {} {} in out 40 {} {} 277 79

and connect them up:

 connect {} Entry1 out Proc1 in 
 connect {} Mon1 in Proc1 out 

Now fill in a value in the leftmost entry, which will act as input entry, and right-click on the yellow part of that block and select Funprop (functional propagate). The network will get activated to transfer the value you entered in the entry to the Proc1 block, which simply copies the value, and then that value will be transfered to the in pin of the Mon block, which when automatically activated will show it in the text window.

Image Bwise uiexas1.jpg

In fact when <return> is pressed in the entry, the chain will also get activated because of a standard binding at the time of the Entry creation, but this binding is lost when the canvas is saved and reloaded, and the method is a 'flooding' type of network 'run' method, which is most of the time less efficient, and sometimes ***very*** slow, for big graphs.

bwise deals with the calling of the blocks in order, that on itself isn't directly a UI related subject, but it can be important in the context. Here, 3 blocks are easily understood to be executed in order (from left to right) as an input receiving block, a currently transparent block, and a text output visualize block. It is possible for the computation to be a lot more complicated in structure, and to require many inputs and outputs, and that is where bwise comes in, but that isn't the subject of this page.


For saving the widgets of the example above, you'll need the updated save procedure from Saving Bwise widgets on the canvas . just paste it in the console before you press the Save button.


What are the UI points of this exercise?

Bwise isn't primarily a user interface tool, but it does contain principles in action which happen to be important for any UI design, such as the ordering of computations, stepwise refined definitions, etc. On the other hand, it simply uses Tk user interface elements, such as in this case the canvas and bwise controlling widgets like popup menus, and evidently a entry and a small text widget.

These are interesting in their own respect and deserve attention, which of course they receive in numerous examples on the wiki, and additionally, bwise includes then in a way which is less often used: as part of a canvas, technically speaking as canvas window item based widget. In fact bwise also makes use of canvas widget trees, such as for the shell and oscilloscope blocks, which are more complicated and at the moment aren't saved automatically.

The example is intended to be of tbe model / view / controller kind, which is a decent way to look at general user interface use. This simplest example doesn't make that very clear yet, the idea is that the UI makes us view a behaviour which is captured by a certain moder, and lets us control the parameters to the model.

We could for instance make the Proc1 block compute something, and control the computation by the part of bwise which allows blocks to be automatically executed in sequence, with the data being automatically transfered between pins connected with wires. That we have already done by right-clicking on the entry block and chosing FunProp. After we have first filled in some parameter in the entry and the 'running' is finished, the result can be viewed.

Using typed commands in the console, we can also control all of this, by first setting the variable which is linked with the entry, adding a computation tcl script to the Proc1 block, and 'running' the network by a bwise command (the same which is automatically called from the popup menu).

 set Entry1.out 3.1415926535                         ;# that's PI of course
 set Proc1.bfunc {set Proc1.out 2.0*${Proc1.in} }    ;# set the compuation for Proc1 such that it doubles it's input
 net_funprop Entry1                                  ;# execute the graph starting from the leftmost block

I deliberately left the second line as it was, but that doesn't do what we wanted. A block function in bwise is just a tcl script which is supposed to perform all computations to update the (right hand side) output pins with the latest information of the left hand side input pins, so if we want numerical computations, in our user interface example, we need the tcl command to do these, which is of course expr .

 set Proc1.bfunc {set Proc1.out [expr 2.0*${Proc1.in}] }
 net_funprop Entry1

Should do the trick.