Saturday, July 30, 2011

New Sourcecode Module textTag.c

Added a new module to the core source, textTag.c. The creation of this module is simply to separate out tag related functions from the the text.c module. It looks like this will be a hefty file. The tag object has a great number of properties that need to be wrapped.

The timing of this corresponds to expanding the gnocl::text widget functionality to enable the 'dump' of buffer contents in a manner similar to Tk. Got most of it working now.

Tuesday, July 26, 2011

Loading a simple tag table

 Here's a quick way of creating multiple tags in one go.

set tagTable {
    {{Header 1} -font {Sans 12 Bold} }
    {{Header 2} -font {Sans 10 Bold} }
    {{Body} -font {Serif 10} -wrapMode word }
}

foreach {a} $tagTable {
    eval "$txt tag create $a"
}

$txt insert end \n
$txt insert end MANTRA\n -tags { {Header 1} }
$txt insert end "Om Ah Hum\n" -tags Body

gnocl::text tags

Still working on extending the text tag functionality. Its quite interesting really as it requires more understanding of the really powerful Tcl command libraries to build lists etc. Today I've added some extra functionality which pretty well follows the same guidelines of the Tk text widget, i.e.  tag names, raise and lower.

I'm still working on the robust parsing of tag options. One little tip for those out there, who like me, want spaces in names. Use the following to create tags:

$txt tag create [list {Heading 1}]

or,

$txt tag create {{Heading 1}}

If tags need to created proceedurally, then try:

$txt tag create [list [list $tagName]]



Friday, July 22, 2011

gnocl::text -markupTags

Extending pango markup string support is something of a challenge. One option that I've just added to the gnocl::text widget is -markupTags. This will specify whether to implement a set of tags corresponding to the 'Convenience Tags' listed in the Gnocl docs. Apart from saving time when scripting, this will allow the parsing of the text buffer for names tags for output of text blocks in pango markup. For example:

$txt insert end "APPLE" -tags {b}

can be parsed and output as:

<b>APPLE<\b>

The same should be possible for span attributes too:

$txt insert end "APPLE" -tags {b fg=r bg=y}

could be parsed and output as:

<span fgcolor="red" bgcolor="yellow"<b>APPLE<\b><\span>

Thursday, July 21, 2011

gnocl::text - tag dumping

Now that its possible create tags by either direct specification or through the use of Pango markup strings, its feasible to require the conversion of text buffer contents back into some form of markup format. Saving off large amounts of text as markup is ill-advised, use serialization to save/reload large buffers. What is in mind here is the ability to edit some rich text in a text buffer and then submit it for display in a list cell or label. Might sound an odd thing to do, but my translation editor does just this. A large body of writing is converted from a text file to a list, one entry per paragraph. These paragraphs are displayed in a gnocl::list in one column and their English translations in a second column alongside. Pango markup would allow those areas in the translation to be highlighted for future review.

Previously I had the bare bones of a widget 'dump' command in place and am now making further headway. Last night I added a 'ranges' sub-command to return the locations of where specific named tags are located. The recently added gtktextviewpango module also needed revisiting in order to add automatic tag naming.

Plan (hope, wish?) to complete this one before the end of the month.

Wednesday, July 20, 2011

gnocl::text now supports pango markup

Spent some time today looking at how to implement the rendering Pango markup strings in the gnocl::text widget. Found a module in the StarDict app that was exactly what was needed! It took a couple of minutes to added it to the gnocl sources, modify the makefile text.c module.

Screenshot:




Test script.

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

package require Gnocl

set pango_string(0)  {%<<span foreground="blue">Hello</span> <span foreground="red">World</span>}
set pango_string(1)  {<span foreground="blue">Hello</span> <span foreground="red">World</span>}
set pango_string(2)  {%<<span foreground="blue">Hello</span> <span foreground="red">World</span>}

set txt [gnocl::text]
gnocl::window -child $txt -width 600 -height 150

# the string is parse, and the leading %< stripped
$txt insert end $pango_string(0)\n
$txt insert end $pango_string(1)\n
$txt insert end $pango_string(2)

Tuesday, July 19, 2011

gnocl::listPicker -done

Completed this megawidget. Here's the script:

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

#---------------
# megawidget to contain Ok/Cancel buttons
#---------------
proc gnocl::listPicker { args } {
    set titles {"Item" data}
    set types {string string}
    set ls(from) [gnocl::list \
        -titles $titles \
        -types $types ]
    set ls(to) [gnocl::list \
        -titles $titles \
        -types $types ]   
    # are any names data?
    set i [lsearch $titles data ]
    $ls(from) columnConfigure $i -visible 0
    $ls(to) columnConfigure $i -visible 0
   
    #~~~~~~~~~~~~~~~
    # move items between two lists
    #~~~~~~~~~~~~~~~       
    proc ::moveItem { from to i} {
        set active [$from getSelection]
        if {$active == ""} {return}
        set rows [$from getNumChildren]
        set a [$from get $active 0]
        set b [$from get $active 1]
        $from erase $active
        set rows [$from getNumChildren]
        # set new active row
        if { $active < $rows } {
            $from setSelection $active
        } elseif {$rows == 1} {
            $from setSelection 0
        } else {
            if { $rows != 0 } { $from setSelection [incr rows -1] }
        }
        $to add "\{\{$a\} \{$b\}\}"
    }

    #~~~~~~~~~~~~~~~
    # return a list of selected items
    #~~~~~~~~~~~~~~~
    proc ::getList { w } {
        set r 0
        while {$r < [$w getNumChildren] } {
            lappend str [ list [$w get $r 0] [$w get $r 1] ]
            incr r
        }
        return $str
    }

    # selection buttons
    set but(from) [gnocl::button \
        -icon %#GoForward \
        -onClicked  "::moveItem $ls(from) $ls(to) $i" ]
       
    set but(to) [gnocl::button \
        -icon %#GoBack \
        -onClicked "::moveItem $ls(to) $ls(from) $i"]
   
    set bx(1) [gnocl::fixed ]
    $bx(1) add $but(from) \
        -x 0 -y 50 \
        -width 70 -height 35
    $bx(1) add $but(to) \
        -x 0 -y 100 \
        -width 70 -height 35
    set bx(2) [gnocl::box]
    $bx(2) add $ls(from) \
        -fill {1 1} \
        -expand 1
    $bx(2) add $bx(1) -fill {0 1}
    $bx(2) add $ls(to) \
        -fill {1 1} \
        -expand 1
    $bx(2) configure -data $ls(to)
   
    # allocate which elements get which settings
    foreach {a b} $args {
        switch -- $a {
            -items {
                # create from list from supplied items
                foreach row $b {
                    $ls(from) add "\{$row\}"   
                }
            }
            -headersVisible {
                # create from list from supplied items
                $ls(from) configure $a $b   
                $ls(to) configure $a $b
            }
            default {
                # nothing in here yet!
            }
        }
    }

    # overload the box to add commands
    rename $bx(2) _$bx(2)

    #~~~~~~~~~~~~~~~
    # overload box widget to create new commands
    #~~~~~~~~~~~~~~~
    proc $bx(2) {cmd args} {
        set self [lindex [::info level 0] 0]
            switch -- $cmd {
                get {
                    return [::getList [_$self cget -data] ]
                    }
                default {uplevel 1 _$self $cmd $args}
                }
    }

    return $bx(2)
}

set items {
    {New "New File"}
    {Open "Open File"}   
    {Save "Save File"}
    {Help "Help Me"}
    }

set box [gnocl::box -orientation vertical]
set lp [gnocl::listPicker -items $items -headersVisible 0]
set bt [gnocl::button -text "Get Selected Options" -onClicked { puts [$lp get]}]
$box add $lp -fill {1 1} -expand 1
$box add $bt -fill {0 0} -expand 0 -align right

gnocl::window -child $box -setSize 0.25

Monday, July 18, 2011

gnocl::listPicker

Things on the Gnocl front have been quiet these past few days. My work load has been heavy and my second hard-drive on my workstations (ie HOME) started giving me sector errors which, is always bad news. Coupled with this, my workstation has parts in it dating back to the mid-1990s and so spares are scarce! Well, as luck would have it I still have spare drives floating around from a pile of old Acer laptops one of which will soon me in my OpenSUSE workstation. At the moment, running on a totally reliable (yet very noisy) 8.5GB IBM PATA hard drive circa 1998 so space is tight. However, spent a couple of hours this evening putting the basics together for a scripted listchooser widget. Here's a screenshot:



My prototype in running ok at the moment and, once finished, I'll post the code to the Gnocl website.


Sunday, July 03, 2011

cget -data

One of the great features of Tk/Gnocl widgets is data association. For some time now its been possible to set the -data options but not to extract it. The reason for this is that such associations are not gtk widget properties although support for the feature is via the Gdk libraries. I'm currently working on a Gnocl scripted megawidget which needs extra items of data passes to its events handlers, the -data option is ideal for this. Implementing the feature is a simple process, as the following code extract from the entry.c module cget function shows.

static const int variableIdx = 0;
static const int onChangedIdx = 1;
static const int valueIdx = 2;
static const int cursorIdx = 3;
static const int primaryIconIdx = 4;
static const int secondaryIconIdx = 5;
static const int dataIdx = 6;

static GnoclOption entryOptions[] =
{
    /* gnocl unique and complex options handled through configure */
    { "-variable", GNOCL_STRING, NULL },        /* 0 */
    { "-onChanged", GNOCL_STRING, NULL },   /* 1 */
    { "-value", GNOCL_STRING, NULL },            /* 2 */
    { "-showCursor", GNOCL_BOOL, NULL},      /* 3 */
    { "-primaryIcon", GNOCL_OBJ, NULL },        /* 4 */
    { "-secondaryIcon", GNOCL_OBJ, NULL },    /* 5 */
    { "-data", GNOCL_OBJ, "", gnoclOptData },  /* 6 */
...

static int cget ( Tcl_Interp *interp, EntryParams *para, GnoclOption options[], int idx )
{
    if ( idx == dataIdx )
    {
        obj = Tcl_NewStringObj ( g_object_get_data ( para->entry, "gnocl::data" ), -1 );
    }
...


The next step is ensuring that the functionality works for all widgets.

Saturday, July 02, 2011

gnocl::text - obtaining names of tags applied to specific locations

The following script shows how to obtain details of which tag applies to a particular position in a block of text.

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

package require Gnocl

set txt [gnocl::text -baseFont {Serif 14}]
$txt tag create red -foreground red
$txt tag create black -foreground black
$txt tag create bold -fontWeight bold

gnocl::window -child $txt -setSize 0.25

$txt insert end "the quick brown fox " -tags red
$txt insert end "jumps " -tags {red bold black}
$txt insert end "over the lazy dog" -tags red

$txt configure -onKeyRelease {
    puts [%w tag get [%w getCursor]]
    }

$txt configure -onButtonRelease {
    puts [%w tag get [%w getCursor]]
    }