Saturday, February 05, 2011

NedNews: GUI

The other "Hello world to RSS reader" series tack on a GUI at the very end. One of the draws for Tcl is the easy integration with a GUI (using Tk). For small projects, seeing something right away is helpful for keeping focused and motivated.

Let's start with the GUI right away!

I have set up my code on Github, so you can see it all there!

Getting started:
I am on a Windows machine, using a "batteries included" Tcl install from ActiveState. Tcl is cross platform, so everything should just work on Linux or MacOS. You may need to install various packages (probably Tcl, Tk, and Sqlite). Also, I heavily recommend tkcon on Linux. I am using Tcl 8.5 which includes a lot of improvements over 8.4.

I do most of my development "live" (inside a Tcl windowed shell - wish). That gives me instant feedback on changes, and allows me to test code in the running environment. No compile, breakpoint, test loop!


wm withdraw .
toplevel .tMain


This is a little bit of boilerplate I use on all projects.

Wish will give you a default top level window (named "."). The problem is, if "." is destroyed (closed), then wish will exit, and you lose your session.

Using the window manager command (wm), I "withdraw" the default toplevel (which causes it to disappear). That way, I can't accidentally close it.

I then create a new toplevel. Putting everything into a new top level allows me to close it, and start over, while keeping the rest of my session.

Let's create our three pane display. There is one pane on the left, to show all the news sources. The right side is split into a top and bottom, showing headers and bodies.

## a splitter for left and right windows
pack [ttk::panedwindow .tMain.splitLR -orient horizontal] -expand 1 -fill both
# a tree for news sources
.tMain.splitLR add [ttk::treeview .tMain.splitLR.tSrcs]


Here we can see a comment (starting with "#"), and a line using nested execution. Execution begins inside the square brackets. I use the new (to Tk 8.5) "Themed Tk" (ttk) namespace command "panedwindow", which will divide up my window into panes (duh).

This is our left-to-right split. All of the Tk widget commands return the widget name (.tMain.splitLR in this case). That allows me to chain the command into pack.

pack activates the packing algorithm. Many GUI systems require you to place widgets at specific x,y points. This then requires a GUI builder to arrange everything so it looks nice (there is a GUI builder for Tcl called "v", which uses the place layout algorithm).

Not so pack. I can just give all my widgets over to pack, and it does a good job of arranging them all neatly. The arguments -expand and -fill tell it I want all the window space given to this big widget (it helps to have all the documentation open, so you can see all the options for these commands).

We pile in some more widgets in a similar way (note that the panedwindow is its own sort of packer for the sub-windows)

## a splitter for top and bottom (headers and bodies)
.tMain.splitLR add [ttk::panedwindow .tMain.splitLR.splitRTB -orient vertical]

# a tree for headers (threaded view)
.tMain.splitLR.splitRTB add [ttk::treeview .tMain.splitLR.splitRTB.tHdr]

# textbox for bodies
.tMain.splitLR.splitRTB add [text .tMain.splitLR.splitRTB.xBdy -state disabled]


Eighteen lines of code, five of which are blank, and six are comments. And a lot of explanation on this blog. That's why I like Tcl. Very concise.

No comments: