Posts

Showing posts from 2012

gnocl::cairo instropection

Image
The gnocl::cairo command is not intended to be some form of canvas object, but a means of drawing onto images for display on screen used perhaps in the creation of widgets or images. Bearing in mind the relatively small number of actions required for this task, it's reasonable to assume that the overhead of making multiple calls to the gnocl::cairo command is a worthwhile compromise.

In response to the problem of how to get the extents of rendered text back from Cairo I came up with the solution highlighted in the following code:


set pb(1) [gnocl::pixBuf new -width 256 -height 256]
set myString "Peter Piper picked a peck of pickled peppers."
set actions "
    select_font_face {Sans normal bold}
    set_font_size 15.0
    text_extents $myString"  
array set extents [gnocl::cairo $pb(1) -actions $actions]

In the example above, the following values were obtained.

extents(height)    = 14.0
extents(width)     = 320.0
extents(x_advance) = 322.0
extents(x_bearing) = 1.0
extents(y_…

New Pacakge gnocl::cairo

Image
The process of tidying up the development code prior to a release increment has led me to weeding out some unused or difficult to maintain functions. One of these was the cairo.c module. This was experimental block of code which was an offshoot of developing the gnocl::splashscreen widget.  But, with the transition to Gtk3 on the horizon, all drawing operations will be performed by Cairo and so I thought that it was a good opportunity to make use of some of that old code. Hence, a new package. There's still way to go before it's finished and I'm still working on drawing to pixbufs but things are looking good. Here's the syntax for the command:

gnocl::cairo <drawable-id> -actions <script>

Where the script is simply a list of cairo operations.  Here's a snippet from my test script.

set actions "
# {sample set-line-join}
set_line_width 40.96
move_to {76.8 84.48}
rel_line_to {51.2 -51.2}
rel_line_to {51.2 51.2}
set_line_join miter
stroke

move_to {76.8 161…

gnocl::button -align

Image
Yesterday I was playing with the Glade interface designer and noticed that the UI included buttons with icons whose contents were left aligned. The Gnocl default is centred and I thought that a gnocl::button -align option might be useful. The button icon and label sub-widgets are in turn held within a GtkHBox and positioned by a GtkAlignment container. It was a relatively simple task to create the code to add the alignment option. For the present, plain text will remain centred. Here's my test script.

# test-buttonAlign.tcl
#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "$@"

package require Gnocl

proc gnocl::buttonBox { {str <<TITLE>>} b} {
    set box(1) [gnocl::box -orientation vertical -padding 0 ]
    set but(1) [gnocl::button -icon %#Remove -text $str -align centre]
    set box(2) [gnocl::box -orientation vertical -padding 0 ]

    $box(1) add $but(1) -fill {1 1}
    $box(1) add $box(2)
    $box(2) add $b

    $box(1) configure -data "b…

Getting Closer to Gnocl 0.9.97

Over the past few months a lot of modifications have been made to the development code to warrant a release increment albeit just by 0.0.01! Before this happens, it would be useful to hear from any (?) Gnocl users out there who are using the package and what they expect to see. Foremost, some feedback from users working with glade/builder files would be useful. The code for loading the xml files is something of a load and it might be more suited to branching out into a separate Gnocl family package. What would also be useful is any bug or performance reports from users.

Many thanks...

gnocl::tooltip trigger

Did a little more to the demo script to show how the "trigger" sub-command actually works.

# test-tooltip.tcl
#! /bin/sh/
#\
exec tclsh "$0" "$@"
package require Gnocl

set lab(1) [gnocl::label -text "TANNOY" ]
set lab(2) [ gnocl::label -text "CAMPER 1" -tooltip "Hi-Di-Hi!!!" ]
set lab(3) [ gnocl::label -text "CAMPER 2" -tooltip "quiet" ]

set box [gnocl::box -orientation  vertical ]
$box add $lab(1) -expand 1 -fill {1 1}
$box add $lab(2) -expand 1 -fill {1 1}
$box add $lab(3) -expand 1 -fill {1 1}

set main [gnocl::window -title "Rise-n-Shine" -child $box -setSize 0.125]

#---------------
# create custom tooltip
#---------------
#
proc myToolTip {} {

    # create custom tooltip window
    set lab [gnocl::label -text "Ho-Di-Ho" -xPad 10]
    set im [gnocl::image -image %#About ]
    set box [gnocl::box -borderWidth 1 -shadow in]

    $box add $im
    $box add $lab

    # keep copy of component widget ids using -data …

Entry widget undo/redo in Tcl.

Hacked together a simple proof of method script to implement Undo/Redo functionality for the gnocl::entry widget. There are some improvements that can be done such as overloading the basic entry widget to allow undo/redo as a widget command. Keyboard bindings are fully there too. I'll take a look at these at a later time.



#---------------
# entryundo($ent)Redo.tcl
#---------------
# Created by William J Giddings
# October, 2012
#---------------
# Description:
# Demonstrates simple entry undo($ent)/redo functionality.
#---------------
# Notes:
# cd /Desktop/GnoclEdit_2/undo($ent)er/wjgstuff
#
# This version has a single buffer to show edit history
#
#---------------

# basic Tcl/Gnocl Script
#! /bin/sh/
#\
exec tclsh "$0" "$@"

package require Gnocl

#---------------
#
#---------------
#
proc entry:resetUndo {ent } {
    global undo idx
    set idx($ent) -1
    set undo($ent) ""
}

#---------------
#
#---------------
#
proc entry:undo {ent} {
    global i…

Customized Tooltip Windows

Gtk allows the user to create custom tooltips which might include mixed items such as icons, images and text. The recent addition of the gnocl::tooltip command to allows such things to be done. The following test script shows how its done.

# test-tooltip.tcl
#! /bin/sh/
#\
exec tclsh "$0" "$@"
package require Gnocl


set lab(1) [ gnocl::label -text "LABEL 1" -tooltip "I'm label #1" ]
set lab(2) [ gnocl::label -text "LABEL 2" -tooltip "I'm label #2" ]
set box [gnocl::box]
$box add $lab(1) -expand 1 -fill {1 1}
$box add $lab(2) -expand 1 -fill {1 1}

set main [gnocl::window -title main -tooltip "HELLO WORLD!" -child $box -setSize 0.25]

#---------------
# create custom tooltip
#---------------
#
proc myToolTip {} {

    # create custom tooltip window
    set lab [gnocl::label -text HIDIHI -xPad 10]
    set im [gnocl::image -image %#About ]
    set box [gnocl::box -borderWidth 1 -shadow in]

    $box add $im
    $box add $lab

    # keep co…

Text Zooming

The widgets in the Tk package have the really nifty sub-command cget which enables the settings for widget options to be extracted. Implementation of cget functionality within Gnocl is patchy for the most part as in most cases custom code needs to be added to extract settings. I've just added cget -baseFont for the text widget. This means that simple text zooming can be implemented in conjunction with the -onScroll option.

#---------------
# text widget zoom
#---------------
# arguments
#    w    text widget id
#    d    direction of scroll, ie up or down.
#    s    state of keytboard modifiers, must be Ctrl+scroll to run.
# returns
#    nil
proc TextZoom {w d s} {

  if { [$w class] != "text" } { return -1 }

  set fnt "[$w cget -baseFont]"

  set fsize [lindex $fnt 1]

  if {$s != 4} { return }

  switch $d {
      up { incr fsize 2 }
      down {incr fsize -2 }
      }

  lset fnt 1 $fsize  

  eval $w configure -baseFont [list $fnt]
}

gnocl::text new option -variable

All of the standard entry widgets have a -variable option much like those encountered in Tk. This means that setting the value of a widget will cause a named variable to contain a copy of this data. The idea of using the -variable option lies in the ease of setting application wide settings or the setting or obtaining  values from a data entry form. The only exception to this was the text widget.

I've been working on a forms based dictionary and glossary edit library which needed something more than the standard gnocl::entry. After hacking around with Tcl scripts to gather data from a text widget I decided to work on the C-side of things. This required a little bit of tweaking of the C sourcecode which, as it would turn out, was an easier approach than scripting. It should be pointed out, however, that only plain unicode text will be copied. Any tags or invisible text will not be captured.

Here's the test script I used to work through the implementation.

#---------------
# test-…

gnocl::label new option -resizable

If the label widget is used for well, labelling other widgets, the overall size of the label is pretty-well fixed and then only to a few number of words. But, the Gtk+ label is much more powerful than this. Because the widget is a container for pango text, its a really useful, high-speed alternative to the gnocl::text widget for the display of extensive pieces of text. Added to this, the use of pango markup, which is pretty well the same as a standard html string, makes run time formatting a something of a breeze.

gnocl::label new options

Image
Just added two new options to the label widget, -mnemonicText and -mnemonicWidget. Whilst these titles are straight from the GtkWidget api, perhaps they need renaming before adding to the distribution. Basically, these options allow fields to be accessed using quick keyboard routes. Something that has been lacking to date. Here's the script that I'm experimenting with:

#---------------
# test-mnemonic.tcl
#---------------
#!/bin/sh
#\
exec tclsh "$0" "$@"

package require Gnocl


proc labelEntry {str var} {
    upvar $var v
    set box [gnocl::box]
    set ent [gnocl::entry -sizeGroup a]
    set lab [gnocl::label -align right -widthGroup aa -mnemonicText $str -mnemonicWidget $ent]
    $box add $lab
    $box add $ent
    return $box
}

set str(1) PRAJNA
set str(2) KARUNA
set str(3) MAITRI

set box [gnocl::box -orientation vertical]

$box add [labelEntry _Prajna str(1)]
$box add [labelEntry _Karuna str(2)]
$box add [labelEntry _Maitri str(3)]

gnocl::window -child $box -setSize 0.125

And,…

Setting tree/list column header widget

Just added a new option to the gnocl::tree/gnocl::list columnConfigure sub-command to allow embedded widgets.

#---------------
# test-columnWidget.tcl
#---------------
#!/bin/sh
#\
exec tclsh "$0" "$@"

package require Gnocl

set tree [gnocl::tree \
    -types {string integer} \
    -titles {"" "# of Legs"}]

$tree add {} {Mamals Birds Bugs}
$tree add 0 {{Cat 4} {Dog 4} {Human 2}}

foreach {paro pred} [$tree add 1 {Parrots Predator}] {}

$tree add $paro {{Cockatoo 2} {Amazone 2}}
$tree add $pred {{Hawk 2} {Eagle 2}}

$tree expand \
    -path "1" \
    -recursive 1

gnocl::window \
    -title "Tree" \
    -child $tree \
    -defaultWidth 300 \


set but(1) [gnocl::button -text HIDIHI]
$tree columnConfigure 1 -widget $but(1)

gnocl::text -- getSelectionBounds

Image
Just added new command to the text widget functionality to retrieve the bounds of the text buffer selection. If there is no selection, then an empty string is returned, otherwise there is a list of four integers, in the form startRow startCol endRow endCol.

#---------------
# test-selectionBounds.tcl
#---------------
#!/bin/sh
#\
exec tclsh "$0" "$@"
package require Gnocl

set txt [gnocl::text -wrapMode word]
$txt configure -onButtonRelease {
    puts [%w getSelectionBounds]
    }

$txt lorem

gnocl::window -child $txt -setSize 0.25


gnocl::setStyle -new command

Image
Gtk regards many widget properties as part of a system theme and are called 'style properties' and are not generally accessible via the Gtk+ api. The defaults for the widget can be over-ridden during run time and the loading of a resource file is an example of this. An alternative route, one in which only single changes are intended, can be taken using the new gnocl::setStyle command. This takes three arguments, the specific widget name, the style property name and the value to be assigned.  By default the widget names are NULL strings and, at present, can only be set following widget creation. One useful trick is to name the widget with its own gnocl id. The following script and screenshot show the command at work.


#---------------
# test-style.tcl
#---------------
#!/bin/sh
#\
exec tclsh "$0" "$@"

package require Gnocl

set ent(1) [gnocl::entry -name b1 -value "Gnocl"]
set ent(2) [gnocl::entry -name b2 -value "Gnocl"]
set ent(3) [gnocl::entry -na…

gnocl::progress -visible * NOW WORKING

Image
In the Gtk2+ Libs the "visible" property in GtkProgress widget is not implemented. In order todo this the commands gtk_widget_show and  gtk_widget_hide have to be called. Hitherto it was possible to set the gnocl::progresssBar -visible option but it would have no effect. This has now been remedied. It will respond as expected.



Working with application preferences using gnocl::keyFile

Image
Its easy enough to load/save script settings as some form of serialization on an array, but what if we want to conform to Gtk+ standards and save settings as an *.ini file? The following script shows how this can be done.



#---------------
# test-keyfile.tcl
#---------------
# William J Giddings, 19/05/2012
#---------------

#!/bin/sh
#\
exec tclsh "$0" "$@"

package require Gnocl

#---------------
# manipulate application preferences
#---------------
# preferences stored in global two-dimensional array name "prefs"
# array names are equivalent to the group/key pairings required for keyFile
#---------------
# args
#    cmd        one of load, edit, save
#    keyfile    name of keyfile to load/save, ignored for edit
# returns
#   none
#---------------
proc preferences {cmd {keyFile {} } } {

 global prefs

 switch $cmd {

    load {

        set kf [gnocl::keyFile load $keyFile]
        set prefs(comment) [$kf get comment]

        foreach group [$kf get groups] {
            foreach key [$kf…

pango markup functionality

Image
The arrangement for creating markup strings from the contents of text widget is almost complete. I've just got to add some extra toolbar buttons for the remaining settings and then the job will be done! Here's a screenshot.



gnocl::toolbar cget

Image
Did a little more work on the gnocl::toolbar to implement the cget function. Not fully implemented as any cget implementation needs a lots of wrapping to get the job done! All changes posted to SF in today's NB.


gnocl::text pango markup

Image
Getting closer towards some working code. I've expanded the list of automatically created pango style text tags to include those which are possible using the GtkTextView widget. One nice feature in pango, ie using unique strikethrough colours isn't available as a text tag attribute. The fg/bg colours are restricted at the moment to red, green, blue, cyan, magenta, yellow, black, gray and white. Apart from the default theme font, the other two settings are serif and sans. Setting unique values for these would not be an impossibility, but these can be created on the fly as normal text tags in a Tcl script.


Obtaining Pango Markup Strings -80% done!

Image
Got this Tcl formatting pango markup strings based upon predefined tags in a gnocl::text widget. At the moment a core set of tags is intialized by setting the -markupTags option to '1'. Like many instances of machine produced code the markup strings are lengthy! But it works. When I have the time I'll look at implementing a C version of the proc an incorporating it into the gnocl sources. At that point it might be worth considering the creation of a new gnocl widget for the task as a separate package.

#---------------
# obtain markup strings from gnocl::text object
#---------------
# args:
#    txt    gnocl text widget containing rich text
# return
#    string with suitable pango markups
# notes:
#    initialize preset markup tags in widget using the -markupTags 1 option
proc gnocl:text_pango {txt} {
    set str ""
    for {set line 0} {$line < [$txt getLineCount]} {incr line} {
        set char 0
        while  {$char < [$txt getLineLength $line]} {

            # get ch…

Working on Tcl script to convert gnoc::text tags into pango markup strings.

Image
Getting working pango strings from text widget contents is not a simple issue, the various Gtk/Gnome programming sites contain many references to the possibility but.. Ok, the purposes are different - pango is only for marking up short strings. I want, however to edit pango formatted gnocl::list/tree strings in my text editor. At the moment my solution is working, albeit with rather long, messy mark-up sequences. Why? Pango doesn't allow tags to be overlapped. For example:

tag1On asdasd tag2On asdasdad tag1Off sasdasd tag2Off

Would produce an error. This would have to be:

tag1On asdasd tag2On asdasdad tag2Offtag1Offtag2On sasdasd tag2Off

So far my solution has been to create markups for each character in a string. The next step is simplifying that string.


Substring markup

Image
I find the Tcl string map subcommand very useful and use it quite extensively in text manipulation. Here's an example of where I wanted to highlight substrings within a piece of text using pango markup.

#---------------
# test-substring-markup.tcl
#---------------
#!/bin/sh
#\
exec tclsh "$0" "$@"
package require Gnocl

#---------------
# search for str2 in str1, then add pango markup formatting
#---------------
proc markup_substring {str1 str2 format} {
    # add necessary quote marks around property values
    set format [string map [list = =\" { } {" }] "$format "]
    set str3 "<span $format>$str2</span>" ;#"
    return [string map [list $str2 $str3] $str1 ]
}


set lab [gnocl::label]
gnocl::window -child $lab -setSize 0.25

# set string text
set str "how now brown cow"

# markup first word
set str [markup_substring $str brown "foreground=red weight=bold background=yellow"]

# cascaded markup is possible but, problems …

Removed imageviewer reference in base distribution.

Image
Whilst the GtkImageViewer widget is a pretty nice tool to use, its not built from default Gtk libraries and requires extra dependencies to be installed before successful compilation can be obtained. With this in mind, the gnocl::imageViewer command has been branched off into a package in its own right. This should enable most users to recompile with the minimal amount of fuss.

Removing widgets from gnocl::box containers

Image
Hitherto it has been possible to add widgets to a box but not to remove them, perhaps for repacking or hiding. The addition of the remove command to the gnocl::box object will now allow this to be done.  Here's a demo script:

#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "$@"

package require Gnocl

set title "Shared Buffer"

set tb [gnocl::textBuffer]
set tv(1) [gnocl::text -wrapMode word -buffer $tb]
set tv(2) [gnocl::text -wrapMode word -baseColor #FDFDB3 -buffer $tb]

$tv(1) lorem

# create maincontainer
set box(main) [gnocl::box \
    -orientation vertical \
    -align topLeft]

set box(texts) [gnocl::box \
    -orientation vertical \
    -children [list $tv(1)] \
    -fill {1 1} \
    -expand 1]

 # create toolBar
 set split 0
 set toolBar [gnocl::toolBar]
 $toolBar add widget [gnocl::toggleButton \
    -variable split \
    -text "Split" \
    -onToggled {
        if {$split} {
            $box(texts) add $tv(2) -fill {1 1} -expand 1
        } else…

gnocl::menuItem: new option -data and new sub-command cget

Image
I'm working on a script that requires popup menus to be built proceedurall and on-the-fly. As a result, there are a number of parameters that I want to send to the popup callback but without the expense of creating and managing global variables or namespaces. This is where the widget -data option comes in. It means that data strings can be conveniently grouped together with a widget, managed throught the Gtk libraries which is totally (hopefully!) secure. The following code-snipetts shows how it can be used.

#---------------
## display popup menu
#---------------
#\code
proc doTagPopup {args} {

    gnocl::setOpts [list a 1 b 2 c 3]
    gnocl::setOpts $args

    puts "a= $a b= $b c= $c"
    puts "w = $w ; t = $t ; n =$n"

    foreach {arg val} $args { puts "$arg = [set [string trimleft $arg -]]" }

    #set matches OM|MANI|PADME|HUM|HRIH
    if {$t == "buttonPress" && $b == "3" } {

        # these may need runtime re-definition
        proc …

Talk to me Linux!

Image
Just hacked together a simple proc to read text strings aloud using the espeak Linux command. Its good fun. It also shows how useful the gnocl::setOpts command  can be.

#---------------
# espeak.tcl
#---------------
## \file
# File documentation.
#\verbatim
#!/bin/sh
#\
exec tclsh "$0" "$@"
#\endverbatim

package require Gnocl

##
# -f <text file>
#       Text file to speak
# -a <integer>
#       Amplitude, 0 to 200, default is 100
# -g <integer>
#       Word gap. Pause between words, units of 10mS at the default speed
# -l <integer>
#       Line length. If not zero (which is the default), consider
#       lines less than this length as end-of-clause
# -p <integer>
#       Pitch adjustment, 0 to 99, default is 50
# -s <integer>
#       Speed in words per minute, 80 to 390, default is 170
# -v <voice name>
#       Use voice file of this name from espeak-data/voices
# -w <wave file name>
#       Write output to this WAV file, rather than speaking i…

gnocl::dialog new options

Image
Just added -height, -width, -x and -y options to the gnocl::dialog widget.

gnocl::setOpts -new command

Image
Sometimes I want to set a block of variables within procedure either as a set of defaults or as variables passed to a proc as options. Hitherto I've used a tcl proc to do this work but thought it high time to add this utility to the gnocl core. Ok, its not strictly graphics but it does make writing event handlers easier. Take the following for example:

doTagPopup -w %w -t %t -n %n -b %b -x %X -y %Y -matches OM|MANI|PADME|HUM|HRIH

The -w options can be used to create local variables. Here's a test snippet:


proc test-setOpts {args} { 
    gnocl::setOpts $args
    puts "$x $y $z"

    gnocl::setOpts [list j 4 k 5 l 6]
    puts "$j $k $l"
}

test-setOpts -x 1 -y 2 -z 3

In the first call the args string is parsed and values set en bloc. The leading '-' will be stripped away. In the second example, a paired list is given from which values will be set.


Getting text tag ranges

Image
Completed code for returning a list of the ranges of a text tag within a gnocl::text widget.

widgetId tag ranges tagName


Implmenting text tag popup menus

Image
Here's a short script to show how to get popup menus appearing for text tag objects.

#---------------
# texttag-popup.tcl
#---------------
#!/bin/sh
#\
exec tclsh "$0" "$@"

package require Gnocl

set txt [gnocl::text -wrapMode word]

gnocl::window -child $txt -setSize 0.25

#---------------
# display popup menu
#---------------
proc doTagPopup {args} {

    foreach {arg val} $args { set [string trimleft $arg "-"] $val }

    if {$t == "buttonPress" && $b == "3" } {

        # these may need runtime re-definition
        proc doHello {} {puts hello}
        proc doGoodBye {} {puts goodbye}

        set menu [gnocl::menu -title "menu" -tearoff 0]
        $menu add [gnocl::menuItem -text "Hello" -onClicked doHello]
        $menu add [gnocl::menuItem -text "Goodbye" -onClicked doGoodBye]
        $menu popup $x $y

        #proc doHello {} {}
        #proc doGoodBye {} {}       
    }

}


$txt tag create tag_popup -onEvent {doTagPop…

Another simple error fixed -gnocl::dialog

Image
The gnocl::dialog command has been throwing out a 'message-type' warning. The cause of this has now been removed.


gnocl::dialog -messy closure fixed

Image
The glib warnings put to the console when the dialog is closed has now been fixed.

gnocl::dialog

Image
Made some enhancements here today.  Added the Gtk "other" option  to the range of dialog types, i.e. no icon. But more significantly, implemented automatic setting of type to "other" if the -child option set.

Hiitherto, the gnocl::dialog was simply a means of giving yes/no feedback. Now, however, it's more useful for the setting of parameters and other forms of settings.

Here's a snippet from my current coding project which requires export to Abiword format. The following proc will build a dialog for the setting of vars. The code is not complete, but shows how the gnocl::dialog enhancements are working.

#---------------
# set file export properties
#---------------
# Args
#
# Return
#---------------
proc abi:properties {} {
    global metaData
    global pageSetup

    set nb [gnocl::notebook]

    # file metadata
    set box(1) [gnocl::box -orientation vertical]
    foreach name [lsort [array names metaData]] {
        $box(1) add [gnocl::labelEntry \
            -labelWidth…

gnocl::text serialization

Image
The GTK libs include a means of serlizaing/deserializing the contents of a GtkTextBuffer but the documentation on how to craft such handlers is basically non-existent. There is one package OSXCART which will load save a buffer as an rtf which is often discussed but the process of building such handlers is cumbersome and need to be built into the gnocl sources themselves. The whole process is more speedily handled on the Tcl side using the various tag sub-commands which will provide all the necessary information. How does the process work? Each row and column of the text is parsed firsly for changes in tag states (ie on or off) and the for the text content. If a new tag is added, its name is kept in a list of applied tags. The text is then accumulated until a further tag state change occurs whereupon firstly the tag and then text changes are written an output string. The text accumulator is then reset to empty and so the process continues. If a tag is turned off, the reverse occurs; t…

Release 0.9.96

Image
Just uploaded the latest stable release to Sourceforge. It been some time since the last major release and a of enhancements have been made. For me the next milestone was implementing the recentFiles functionality available through Gtk+. This is working, although a lot more options and commands need to be implemented for the gnocl::recentManager widget. Having said that, though, I can see that bulk of the functionality would only be rarely used.

Regular readers of this blog may have noticed that the posts have reduced over the past few months. This isn't due to any loss of interest in Gnocl, far from it! I've also been working on my own translation tools which, I have to say, is the basic fuel which keeps the development work going.

Over the past four years or so that I've been working on Gnocl an awful lot of code has been added to the sources. Code that not only provide Tcl access to Gtk resources but provides a whole lot of advanced features which makes coding a breeze.

H…