Gnocl Q's and A's

I'm looking into rewriting some or all of my apps in gnocl, and finding that some features I'd like to see don't appear to be there yet. What I'm working on right now is WISH Checkbook. I've got the basic GUI assembled (see below); I still have to get it to work (notice the lack of any calculated totals), but I'm pretty sure that can be done. I'm still not seeing how to squeeze the toolbar into a smaller vertical space, but I can live with that if necessary.

http://www.geocities.com/pa_mcclamrock/gwishcheck.gif

What I would really like is to be able to use the gnocl::spinButton to do the "date-spinning" trick I can do with a Tk spinbox. (If you look really closely at the screenshot, you'll see that the date on the entry line is shown in a Tk spinbox, inserted into the Gnocl GUI by way of a socket.) Here's the code I use:

# Procedure to get spinbox to display correct date:
proc datespin {way w} {
    set datoa [$w get]
    set oldsecs [clock scan $datoa -format {%Y/%m/%d}]
    if {$way eq "up"} {
        set newsecs [clock add $oldsecs 1 day]
    } else {
        set newsecs [clock add $oldsecs -1 day]
    }
    set datoa [clock format $newsecs -format {%Y/%m/%d}]
    $w delete 0 end
    $w insert 0 $datoa
}

This causes the displayed date to be moved forward or back when the Up or Down spin-button is pressed, just as if it were an integer in an unmodified spinbox. It will work with a Tk spinbox, which allows you to delete and insert arbitrary text, but (so far as I can see) not with a Gnocl spinButton, which doesn't. Apparently the use of a socket slows down the GUI loading by some seconds, so I'd really like to do without it if possible. Is there a way to do the same thing with the existing Gnocl spinButton, or else a prospect of modifying the spinButton to accept deletion and insertion of arbitrary text?

WJG (06-Mar-09) gnocl::spinBox implements the GtkSpinBox widget which, for some reason, only supports ints and floats! Until I've made some equivalent for inclusion in the core, try this Tcl solution. Infact I think that listSpinner would be useful addition to the widget set. The script below to create the spinner will obviously need a little wrapping to suite your needs. I've modified the datespin proc' to be Gnocl compliant, and I've added two convenience command to the gnocl::entry code as a result of this quest, that is "get" and "set". The intended way of using the widget was to set the '-variable' associate with the widget, so you may want to explore this alternative. Happy Hacking!

# dateEntry.tcl
#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "[email protected]"

package require Gnocl

# Procedure to get spinbox to display correct date:
proc datespin {way w} {
    # set datoa [$w get]
    set datoa [$w cget -value]
    set oldsecs [clock scan $datoa -format {%Y/%m/%d}]
    if {$way eq "up"} {
        set newsecs [clock add $oldsecs 1 day]
    } else {
        set newsecs [clock add $oldsecs -1 day]
    }
    set datoa [clock format $newsecs -format {%Y/%m/%d}]
    # $w set $datoa
    $w configure -value $datoa
}

# Create our own entry spinner as gnocl::spinBox only supports ints and floats
proc dateSpinner { date variable {state 1}} {
  set dateEntry [gnocl::entry -value $date -variable $variable -editable $state -widthChars 10]
  set upArrow [gnocl::arrowButton -arrow up -relief normal -data $dateEntry -onClicked {datespin "up" [%w cget -data ] }]
  set downArrow [gnocl::arrowButton -arrow down -relief half -data $dateEntry -onClicked {datespin "up" [%w cget -data ]  }]
  set dateSpinner [gnocl::box -borderWidth 0 -padding 0 -spacing 0]
  $dateSpinner add [list $dateEntry $upArrow $downArrow] -fill {0 0} -expand 0
  return $dateSpinner
}

gnocl::window -child [dateSpinner "2009/03/06" ::date 0]
gnocl::mainLoop

PS> when I tried out the code I entered the date using British formatting, ie, 03/06/2009 and it crashed the script. Perhaps some error checking would be useful

D. McC 2009-Mar-6: It works, all right, but those big side-by-side arrow buttons would take up most of the space I need for the entry widget above the "Num" column! I hope you'll find some time to work on the core and fix the real spinButton (or spinBox, although I'm not seeing that name in the 0.9.92 documentation) to be able to do this trick before too long. Thanks in advance!

I also noticed another little thing that seems to need improvement: in my list of column types, I found I had to make them all "string" except for the one boolean checkbox. This is because "integer" and "float" columns won't accept blanks (i.e., "", null), and three columns in this program have to have lots of blanks in them: Num (for transactions that don't have check numbers), Deposit (for transactions that are withdrawals, not deposits), and W/draw (for transactions that are deposits, not withdrawals). Is there any chance that integer and float columns might be modified to accept blanks?

WJG 2009-03-07: Ok. Using gnocl::arrowButtons will always produce 'largish' buttons because of the borders created for the GtkButton widget type. There is a way round this on the Tcl side however, and that it to use images embedded into a gnocl::eventBox. The following solution will provide the 'compact' feature that you like, but the 'spinbuttons' will not follow the selected GtkTheme as they are pixmaps. Here's the code:

#----------------
# datespinner using eventboxes to create vertical spinbuttons
#----------------
proc dateSpinner { date variable {state 1}} {
    set dateEntry [gnocl::entry \
        -value $date \
        -variable $variable \
        -editable $state \
        -widthChars 10]

    set upArrow [gnocl::image -image %/upArrow.png]
    set downArrow [gnocl::image -image %/downArrow.png]
   
    set up [gnocl::eventBox \
        -background black \
        -child $upArrow \
        -data $dateEntry \
        -onButtonPress {
            set _tmp_ [%w cget -child]
            $_tmp_ configure -image %/upArrow_shade.png
            datespin "up" [%w cget -data ] } \
        -onButtonRelease {
            $_tmp_ configure -image %/upArrow.png
                  unset _tmp_
    }]
   
    set down [gnocl::eventBox \
            -child $downArrow \
          -data $dateEntry \
          -onButtonPress {
                  set _tmp_ [%w cget -child]
                  $_tmp_ configure -image %/downArrow_shade.png
                  datespin "down" [%w cget -data] } \
          -onButtonRelease {
                  $_tmp_ configure -image %/downArrow.png
                  unset _tmp_ } ]
   
    set box [gnocl::box \
        -orientation vertical \
        -spacing 0 \
        -padding 0 \
        -borderWidth 0 \
        -align left]
   
    $box add [list $up $down] -fill {0 0} -expand 0
   
    # container for all items
    set dateSpinner [gnocl::box -borderWidth 0 -padding 0 -spacing 0]
    $dateSpinner add [list $dateEntry $box] -fill {0 0} -expand 0
   
    return $dateSpinner
}

To produce the following on screen:

http://wjgiddings.googlepages.com/Screenshot_DateEntry2.png

The current module that I'm working on is a Gnocl interface to the Gtk drawing and image libraries so, within a short while it'll be possible to include pixmaps and bitmaps within scripts as data strings. In the meantime, please get the whole shebang from the Sourceforge nightly build. Search for dateEntry2.tcl.

ZB Pay attention, that date separators are usually used to suggest the order - so the slashes usage means "American date" (MM/DD/YYYY), dots are standing for "german date" (or rather "european" one) (DD.MM.YYYY), and dashes for "japanese" notation (or nowadays "international" rather) (YYYY-MM-DD).

Of course, your example is rather obvious, because you've included four-digits year. But there could be a real confusion, if two-digit year have been used... especially now, where "year counter" is below 12, (and during following years will be still below 31).

Yes, I'm aware, that British are using slashes for DD/MM/YYYY - no idea, how to distinguish that from American notation.

D. McC 2009 Mar 7: Pixmaps for the up and down arrows, as data strings within the script, should do the job. They could be made to fit into the current GTK+ theme just by changing a few color codes. (Is there a way to have the script detect a change in the GTK+ theme while running?) I'm also looking forward to being able to use pixmaps as data strings because then there will be no possibility of getting error messages like the one I just got:

% dateSpinner $date $var
Failed to open file 'upArrow.png': No such file or directory

Where are upArrow.png and downArrow.png supposed to be located, anyway? WJG I've just updated the SourceForge site; get everything from there. To keep the column try setting it as a string rather than float. Any calculations on the Tcl side, after all, will be made on string representations of floats. Here's what I mean...

set list [gnocl::list \
    -titles {bool string string string string} \
    -types {boolean string string string string}]

$list add {{0 list -104 1.45} {0 window {} 9.58}}
$list add {{0 list -104 1.45} {0 window {} {}}}

# a cell must have previous content to modify it
$list cellConfigure 0 0 -value 1
$list cellConfigure 0 1 -value WJG
$list cellConfigure 0 3 -value 1956.07

$list cellConfigure 3  0 -value 1
$list cellConfigure 3  1 -value LXY
$list cellConfigure 3  3 -value 1964.10

D. McC 2009-03-07: Thanks! And now I've got one more little question: I've also been looking into rewriting Wish Mini-Console in Gnocl (see below for another screenshot of an as-yet-non-functional GUI), but I'm not seeing how to keep the cursor out of the prompt area. In the existing Tk version, I do this by having the script detect when the cursor has entered an area with the prompt tag, and "promptly" ejecting it if it has. I'm not seeing how to detect what tags are under the cursor, and what are the ranges of those tags, in a Gnocl text widget. Can this be done yet? If so, how?

http://www.geocities.com/pa_mcclamrock/gwishmin.gif

WJG 2009-03-07: Again, this is possible using the 0.9.93a version. Here's a snippet:

set txt [gnocl::text \
   -onEnter {
       %w configure -cursorVisible 1} \
   -onLeave {
       %w configure -cursorVisible 0 }]

Responding to the enter/leave signals will allow you to pick-up the pointer movements and then you can determine whether or not to display the insert cursor. There's still some work to do on the widget, but the planned gnocl::vte is probably the answer for you. [1 ]

Above, you ask about detecting theme changes during run time. I see no reason why not, after all Gnocl is only a 'wrapper' around the Gtk/Gdk library. If you want special colours etc., and want to make wholesale changes in one sweep, then use resource files. Here's an example. First the script:

#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "[email protected]"

package require Gnocl

gnocl::resourceFile .gtkrc

set box [gnocl::box -orientation vertical]
set ent [gnocl::entry -name entry -value .gtkrc]

$box add [list $ent] -fill {1 1} -expand 1
set topl [gnocl::window -title ".gtkrc" -child $box -widthRequest 130 -heightRequest 50]

gnocl::mainLoop

Here's the resource file (.gtkrc):

style entry
{
xthickness = 5
ythickness = 5
fg[ACTIVE] = "#FF0000"
fg[SELECTED] = "#003366"
fg[NORMAL] = "#CCCCCC"
fg[PRELIGHT] = "#FFFFFF"
fg[INSENSITIVE] = "#999999"
text[NORMAL] = { 0, 65536, 0}
base[NORMAL] = { 65536, 65536, 0}
bg[ACTIVE] = "#003366"
bg[SELECTED] = "#FF0000"
bg[NORMAL] = "#666666"
bg[PRELIGHT] = "#003366"
bg[INSENSITIVE] = "#666666"
font_name = "Sans Bold 14"
}
class "GtkEntry" style "entry"

And, here's the effect. Not to my taste, but one file controls the reconfiguration or re-styling of all widgets of a specified class.

Here's the effect of the above:

http://wjgiddings.googlepages.com/Screenshot_gtkrc.png

RLH That is nice. The .gtkrc...not the coloring. :-)


Q: What facilities does Gnocl have for putting applications in the system tray?

WJG 2009-03-09: A little windows-speak there, methinks! Seriously though, Gnocl does support the creation of Gnome Panel Applets, which is possibly what you're looking for. In addition, there is a panel applet called the 'Notification Area', [2 ], is this what you're referring to?

RLH: I implement the ssh launcher from the wiki witch uses freedock to allow a program to sit in the system tray. I thought about trying to do the same in Gnocl (while making it a little better).

WJG: No, this is new to me. It would be an interesting extension. What needs to be done?

RLH: I don't know personally. But I have listed a couple resources below that might help you.

http://library.gnome.org/devel/gtk/stable/GtkStatusIcon.html

http://yettocome.blogspot.com/2007/08/gtk-system-tray-icon-example.html

WJG 2009-03-10: RLH, thanks for the links. I've now got a basic module and the rudiments working. Adding this feature is an interesting project as the GtkTaskIcon is not a widget and so extra code needs writing for it to work in a Gnocl sorta way. Will keep you informed of developments.


RLH Resources...how do I assign my own icon to a button and what are the stock icons used for buttons?

WJG 2009-04-01: The gnocl::button widget makes it nice and easy to apply icons. The secret lies in using 'percent strings'. Lets take a look at some sample code.

#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "[email protected]"

package require Gnocl

# make a container to hold all widgets
set box [gnocl::box -buttonType 1]

# 1) using the -icon option only 
$box add [gnocl::button -icon %#No]

# 2) simply using the -text option
$box add [gnocl::button -text %#Cancel]

# 3) combining the -text and -icon options
$box add [gnocl::button -text %_S_ave -icon %#Save]

gnocl::window -title Buttons -child $box -onDelete {exit}
gnocl::mainLoop

The button widget has two options whose functions overlap slightly, ie -text and -icon. If you simply want to display a graphic choose the -icon option. From this point you need to determine if you want to use a 'stock item', ie a pre-existing named icon from the current Gnome theme that's being use, or perhaps a graphic stored on disk.The way to tell the gnocl option parser about your choice is to use a so called 'percent string'. Here the prefix %# for a stock item, or %/ for a file on disk or %_ for a mark-up string.

The following line will produce a button whose sole content is an icon.

gnocl::button -icon %#No

Next,

gnocl::button -text %#Cancel

Will produce a button with both an icon and text. The first letter by default will be marked as the accelarator key and underscored to reflect his.

Next,

gnocl::button -text %_S_ave -icon %#Save

This results in a button displaying both and icon and text but the text will now be modified. "%_" communicates to the parse that the following "_" before the letter "a" marks that this will function as the new accelarator key.

Here's a screengrab of the result.

http://wjgiddings.googlepages.com/Screenshot-Buttons-Icons.png

Stock icons. Each Gnome theme will include a wide range of stock icons in order to maintain consistences of theming between applications. To find out the names of the various stock items on and how they look on your system, run the following Gnocl script.

#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "[email protected]"

package require Gnocl
set table [gnocl::table -borderWidth 0 -rowSpacing 0 -columnSpacing 0]
set items ""
set stocks [lsort [gnocl::info allStockItems]]
foreach el $stocks {
    if {[catch {set but [gnocl::button -text %#$el]}] == 0} {
        lappend items [gnocl::box -label "$el" -children $but -fill 1 -expand 1]
        if {[llength $items] == 6} {
            $table addRow $items -fill 1
            set items {} 
        }
    }
}
if {[llength $items] > 0} {
  $table addRow $items -fill 1
}
gnocl::window -title "Stock Buttons" -child $table

Finally, to use an image file of your own creation in a button simply use:

gnocl::button -text {Hello World} -icon %/./world.png

Happy Hacking ;-)