Version 16 of Gnocl Q's and A's

Updated 2009-03-07 11:55:35 by WJG

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" "$@"

 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 (07-MAR-09) 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 libaries 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.

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 Mar 7: 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) I'll have a look, but gnocl::vte is probably the answer for you: [L1 ]