Thursday, November 18, 2010

Another distraction?

I regularly use ImageMagick to post-process documents scanned under the control of a Tcl script using the exec command. All works well, albeit a little slowly. So, I thought that I'd get a copy of TclMagick which didn't compile and so on and so on.... So, I thought that I'd put together my own package using those commands that I use most regularly. I'm so pleased with the result that I think I'll abandon the pixbufFilter module that I was experimenting with in favour of this new approach. I have the package running and able to implement the processes much more quickly than calling the convert command. What I need to explore now, however, is how to pipe GdkPixbuf data across to a wand object. -I think I see how this was done in TkMagic!

Here's the test script -oddly, the command to get an image height is really slow, why?

# test-gnoclWand.tcl

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

package require Gnocl
package require GnoclWand
set pb1 [gnocl::wand load pelican.png]

$pb1 swirl 1200
$pb1 resize 400 400
$pb1 save resize.png

set pb2 [gnocl::wand load image-0007.pnm]
$pb2 deskew
$pb2 save skew.tif
#puts "width = [$pb2 width]"
#puts "height = [$pb2 height]"

Sunday, November 14, 2010

gnocl::drawingArea

This little beastie got a whole lotta TLC today. Implemented most of the the gdk drawing functions only to find that these have been deprecated in Gtk +2.22 in favour of Cairo! No matter, the code will work and besides, there was already a cairo based module in the pipeline anyway!

#---------------
# test-drawingArea.tcl
#---------------
# William J Giddings
# 02-Nov-2010
#---------------

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

package require Gnocl

proc scanZone {} {

set da [gnocl::drawingArea]

$da option add [list \
    -onPointerMotion \
    -onButtonPress \
    -onButtonRelease \
    -onKeyPress \
    -onKeyRelease \
    -onExpose]

return $da
}

set sz [scanZone]

gnocl::window -child $sz

if {0} {
set pb [gnocl::pixBuf load -file EU_flag.jpg]
gnocl::window -child [gnocl::image -image "%?$pb"]
set pb [gnocl::pixBuf load -file wjg_icon.png]
}

$sz configure -onPointerMotion {

    #%w draw line [list %x 0 %x 10]
    #%w draw line [list 0 %y 10 %y ]

    set x1 [expr %x - 5] ; set y1 [expr %y - 5]
    set x2 [expr %x + 5] ; set y2 [expr %y - 5]
    set x3 [expr %x + 5] ; set y3 [expr %y + 5]
    set x4 [expr %x - 5] ; set y4 [expr %y + 5]

    #%w draw point [list %x %y]
    #%w draw points [list $x1 $y1 $x2 $y2 $x3 $y3 $x4 $y4]
    #%w draw lines [list $x1 $y1 %x %y $x2 $y2] ;#$x3 $y3 $x4 $y4 $x1 $y1]

    #%w draw pixbuf $pb -from [list %x %y 10 10] -to [list %x %y] -dither none -offset {0 0}
    #%w draw rectangle [list $x1 $y1 10 10] -filled 1

    #%w draw arc [list $x1 $y1 50 50 30 120] -filled 1
    #%w draw     polygon [list $x1 $y1 $x2 $y2 $x3 $y3 $x4 $y4] -filled 1

    set x1 %x ; set y1 [expr %y -10]
    set x2 %x ; set y2 [expr %y +10]
    set x3 [expr %x -10] ; set y3 %y
    set x4 [expr %x +10] ; set y4 %y

    #%w draw segments [list $x1 $y1 $x2 $y2 $x3 $y3 $x4 $y4]

    set y1    %y
    set x11 %x
    set x21 [expr %x + 50]
    set y2    [expr %y + 50]
    set x12 [expr %x - 50]
    set x22 [expr %x + 50]

    %w draw  trapezoids [list $y1 $x11 $x21 $y2 $x12 $x22 ]
    }

Saturday, November 13, 2010

Recent activity -Scripting...

The past couple of days has seen me gnocl scripting rather than working on core code. One pet project of mine is the automated creation of edocs and ebooks. Although I have an old version of AbbySoft Professional which runs on my laptop and an equally ancient version of Acrobat 6, I want to add docs as I work on my desktop machine. To do this I created a front Tcl/Gnocl front end to control the scanning, clean-up and cropping of scans, the conversion to DJVU with OCR and packing of graphics to a multipage TIF for later processing in FineReader. Everything works fine but my control script had been hacked to gether over the past year or more and so some rationalisation is in order. But, but, but... Who likes writing code from scratch all the time? Creating new basic GUIs is always a chore so I thought that I'd create something to the growing gnocl megawidgets package. Todays addition will build a container and add the main control elements for menus, toolbars, the main content area and status block. Names and aliases for these items is returned as a list for future modification. Its still all basic at the moment, but it make life easier. Perhaps I should include this with the next release? Well, here's the proc itself:

#---------------
# Create a boilerplate application window
#---------------
proc gnocl::default {args} {
# set some defaults here
set opts(menubar) ""
set opts(toolbar) ""
set opts(box) ""
set opts(status) ""
foreach {arg val} $args {
    switch -- $arg {
        -opt1 -
        -opt2 { append opts(menubar) "$arg $val " }
        -opt3 -
        -opt4 { append opts(toolbar) "$arg $val " }
        -opt5 -
        -opt6 { append opts(box) "$arg $val " }
        -opt7 -
        -opt8 { append opts(status) "$arg $val " }
        default { puts "WARNING: Invalid option $arg."    }
        }
}
set app(menuBar) [gnocl::menuBar]
set app(toolBar) [gnocl::toolBar]
set app(box) [gnocl::box]
set app(status) [gnocl::statusBar]
set app(container) [gnocl::box -orientation vertical]
$app(container) add $app(menuBar)
$app(container) add $app(toolBar)
$app(container) add $app(box) -fill {1 1} -expand 1
$app(container) add $app(status)
# create menus
# file i/0
# create menus
set app(menu,file) [gnocl::menu]
set app(menu,help) [gnocl::menu]
#attach items
$app(menuBar) add [gnocl::menuItem -text "%__File" -submenu $app(menu,file)]
$app(menuBar) add [gnocl::menuItem -text "%__Help" -submenu $app(menu,help)]
#add menu sub-items
$app(menu,file) add [gnocl::menuItem -text "%#Quit" -onClicked exit]
$app(menu,help) add [gnocl::menuItem -text "%__About" -onClicked {puts "About Gnocl"}]
# create toolbars
$app(toolBar) add item -text "Button1" -onClicked {puts Button1}
$app(toolBar) add space
$app(toolBar) add checkItem -text "Button2" -onToggled {puts Buton2}
#eval "set app(top) [gnocl::window -visible 1 -child $app(container) ]"
#$app(top) center
#eval "$app(top) configure $winArgs"
$app(status) push "Ready"
# return a list consiting of widget aliases and names
return [array get app]

}

Recent activity -Scripting...

The past couple of days has seen me gnocl scripting rather than working on core code. One pet project of mine is the automated creation of edocs and ebooks. Althought I have an old version of AbbySoft FineReader Professional which runs on my laptop and an equally ancient version of Acrobat 6 (on my Linux box I have PDF Studio which is brilliant value for money) I want to add docs as I work on my desktop machine. To do this I created a front Tcl/Gnocl front end to control the scanning, clean-up and cropping of scans, the conversion to DJVU with OCR and packing of graphics to a multipage TIF for later processing in AbbySoft FineReader.  Everything works fine but my control script have been hacked to gether over the past year or so and so some rationalisation is in order. But, but, but who likes writing code from scratch all the time! Creating new basic GUIs is always a chore so I thought that I'd create something to the growing gnocl megawidgets package. Todays addition will build a container and add the main control elements for menus, toolbars, the main content area and status block. Names and aliases for these items is returned as a list for future modification. Its still all basic at the moment, but it make life easier. Perhaps I should include this with the next release? Well, here's the proc itself:

#---------------
# Create a boilerplate application window
#---------------
proc gnocl::default {args} {

# set some defaults here
set opts(menubar) ""
set opts(toolbar) ""
set opts(box) ""
set opts(status) ""
 
# apportion values
foreach {arg val} $args {
    switch -- $arg {
        -opt1 -
        -opt2 { append opts(menubar) "$arg $val " }
        -opt3 -
        -opt4 { append opts(toolbar) "$arg $val " }
        -opt5 -
        -opt6 { append opts(box) "$arg $val " }
        -opt7 -
        -opt8 { append opts(status) "$arg $val " }
        default { puts "WARNING: Invalid option $arg."    }
        }
}

# create components
set app(menuBar) [gnocl::menuBar]
set app(toolBar) [gnocl::toolBar]
set app(box) [gnocl::box]
set app(status) [gnocl::statusBar]
set app(container) [gnocl::box -orientation vertical]
 
# assemble
$app(container) add $app(menuBar)
$app(container) add $app(toolBar)
$app(container) add $app(box) -fill {1 1} -expand 1
$app(container) add $app(status)
 
# create menus
# file i/0
# create menus
set app(menu,file) [gnocl::menu]
set app(menu,help) [gnocl::menu]
 
#attach items
$app(menuBar) add [gnocl::menuItem -text "%__File" -submenu $app(menu,file)]
$app(menuBar) add [gnocl::menuItem -text "%__Help" -submenu $app(menu,help)]
 
#add menu sub-items
$app(menu,file) add [gnocl::menuItem -text "%#Quit" -onClicked exit]
$app(menu,help) add [gnocl::menuItem -text "%__About" -onClicked {puts "About Gnocl"}]
 
# create toolbars
$app(toolBar) add item -text "Button1" -onClicked {puts Button1}
$app(toolBar) add space
$app(toolBar) add checkItem -text "Button2" -onToggled {puts Buton2}

#eval "set app(top) [gnocl::window -visible 1 -child $app(container) ]"
#$app(top) center
#eval "$app(top) configure $winArgs"
 
$app(status) push "Ready"
 
# return a list consiting of widget aliases and names
return [array get app]
}

Wednesday, November 10, 2010

gnocl::calendar

Given this module some attention today. Added some of the more package wide options to the module and created customised handler for setting the month. (For some odd reason months are are counted 0-11 whereas days are 1-31.) There's still a little more to do to this one including the addition of code to store diary details. Here's the working test script to show the range of options at work. The percentage substitution string item %e explores something that I've been toying with, the name of the signal/event that initiated the call. Ok, a script can keep its own internal trace but who knows, it might prove useful.

#---------------
# calendarTest.tcl
#---------------
# Author:   William J Giddings
# Date:     07/05/09
#---------------
#!/bin/sh
# the next line restarts using tclsh \
exec tclsh "$0" "$@"
#---------------

package require Gnocl

set cal [gnocl::calendar]

$cal configure -day 8 -month 7 -year 1956
$cal configure -rowHeight 1 -colWidth 1
$cal configure -monthChange 1
$cal configure -dayNames 1
$cal configure -details 1
$cal configure -heading 1
$cal configure -weekNumbers 1
$cal configure -font {Courier 12}
$cal configure -baseColor #ffffdd
$cal configure -sensitive 1
$cal configure -visible 1
$cal configure -tooltip "Calendar"

$cal configure -onDaySelected {puts "%e %d %m %y"}

$cal configure -onDoubleDaySelected {
    puts " %e %d %m %y"
    %w detail add -date [list %d %m %y] -text {birthday}
    }

$cal configure -onMonthChanged {puts "%e %d %m %y"}
$cal configure -onNextMonth {puts "%e %d %m %y"}
$cal configure -onNextYear {puts "%e %d %m %y"}
$cal configure -onPrevMonth {puts "%e %d %m %y"}
$cal configure -onPrevYear {puts "%e %d %m %y"}

gnocl::window -child $cal -title gnocl::calendar

gnocl::mainLoop

Wednesday, November 03, 2010

gnocl::layout and gnocl::aspectFrame

I've just added the modules for these two widgets. They are pretty obscure. The gnocl::layout object is a sort of mid between a frame and a drawing area and the gnocl::aspectFrame always forces a widget to keep its original aspect ratio. With the inclusion of these two new objects, I think that the bindings to the GTK+ 2.18 release which I'm compiling against is almost done. When all objects have some level of support, then I think it would be possible to notch up an other release - 0.9.96 or thereabouts.

Here's a test code snippet for these new widgets.


set lo [gnocl::layout -width 500 -height 4000]

set but1 [gnocl::button -text "Button"]
set but2 [gnocl::button -text "DEL $but1"]

set x 10

$lo add $but1 -x $x -y 10
$but1 configure -onClicked {$lo move %w -x [incr x 10] -y 10}

$lo add $but2 -x $x -y 50
$but2 configure -onClicked {$lo remove $but1}

gnocl::window -child $lo -title "Layout"

set but3 [gnocl::button -text "BUTTON-3" -onClicked {puts "HELLO [$af cget -xalign]" } ]
set af [gnocl::aspectFrame -child $but3 -xalign 0.5]
gnocl::window -child $af -title "Aspect Frame"

The gnocl::aspectFrame module has been quite interesting, as there are no  get-property functions for this object, I've had to take a peek at the Gtk+ sources. It was interesting, resulted in a long winded hack of the 'get' equivalent, which I promptly abandoned and handled the whole lot through pointers.




gnocl::drawingArea ----> working forward ---->

This mornings programming stint sees the bare bones in place now for drawing commands on the gnocl::drawingArea widget. I've also added pages in the docs for the cursor settings. The test script changes reflect the progress so far as a stroke based paint program begins to take shape.



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

package require Gnocl

# create and display the drawingArea widget
set da [gnocl::drawingArea]
gnocl::window -widthRequest 320 -heightRequest 200 -child $da

# add options...
$da option add -onPointerMotion
$da option add -onEnter
$da option add -onLeave
$da option add -onButtonPress
$da option add -onButtonRelease
$da option add [list -onKeyPress -onKeyRelease -onExpose]

# configure them
$da configure -onPointerMotion {addPoint %w %x %y}
$da configure -onEnter {puts "Enter -Hello!"}
$da configure -onLeave {puts "Leave -Bye!"}
$da configure -onButtonPress {
    puts "-- Start Drawing --"
    set draw 1
    $da configure -cursor pencil
    }
$da configure -onButtonRelease {
    puts "-- End Drawing --"
    set draw 0
    $da configure -cursor last
    }
$da configure -onKeyPress {puts "Press"}
$da configure -onKeyRelease {puts "Release"}
$da configure -onExpose {
    reDraw %w
    }

set draw 0
set points {}

proc addPoint { w x y } {
    if { $::draw } {
        lappend ::points [list $x $y]
        puts adding
        $w draw point [list $x $y]
    }
}

proc reDraw {w} {
    foreach point $::points {
        $w draw point $point
    }
}




gnocl::drawingArea -more progress

I'm really pleased with the progress that I've made with this module today. The test script below gives some indication of how its shaping up. I''ve just added the ability to pass a list the option add command. Think that I've done enough for today.


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

package require Gnocl

# create and display the drawingArea widget
set da [gnocl::drawingArea]
gnocl::window -widthRequest 320 -heightRequest 200 -child $da

# add options...
$da option add -onPointerMotion
$da option add -onEnter
$da option add -onLeave
$da option add [list -onButtonPress -onButtonRelease]
$da option add [list -onKeyPress -onKeyRelease -onExpose]

# configure them
$da configure -onPointerMotion {puts "%x %y"}
$da configure -onEnter {puts "Enter -Hello!"}
$da configure -onLeave {puts "Leave -Bye!"}
$da configure -onButtonPress {puts "You Clicked!"}
$da configure -onButtonRelease {puts "You Left-Go!"}
$da configure -onKeyPress {puts "Press"}
$da configure -onKeyRelease {puts "Release"}
$da configure -onExpose {puts "Exposed!"}

gnocl::mainLoop

Tuesday, November 02, 2010

gnocl::drawingArea -more work done

GtkDrawingArea is basically the blank canvas from which other widgets are built up. The developer decided what signals and properties are to be applied to the object. The basic module for the gnocl::drawingArea has been around for some time and today I got it all running a little more smoothly and now that remains is to hard-code into the module the various choices and options that can be added during run-time. Here's the test script to show how simply the process is working out.

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

package require Gnocl

# create and display the drawingArea widget
set da [gnocl::drawingArea]
gnocl::window -widthRequest 320 -heightRequest 200 -child $da

$da option add -onPointerMotion
$da configure -onPointerMotion {puts "%x %y YIPPEEE!!!"}
$da option add -onEnter
$da configure -onEnter {puts "Enter -Hello!"}
$da option add -onLeave
$da configure -onLeave {puts "Leave -Bye!"}
$da option add -onButtonPress
$da configure -onButtonPress {puts "You Clicked!"}

gnocl::mainLoop

There's still some way to go, more error checking, the ability add a list of options etc...

Also did some more tidying up of the gnocl::ruler code.







gnocl::volumeButton -done

Gave the gnocl::volumeButton a little bit of TLC tonight. Added signal handlers and options for a number of inherited properties. Getting this one to work as required some trial and error as only some of the inherited options are permitted but not indicated in the docs. No, screenshot as the popup prevents this. But, here's the test script...

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

package require Gnocl

set ent [gnocl::label -textVariable vol]
set vb [gnocl::volumeButton]
set box [gnocl::box]
$box add [list $vb $ent]

gnocl::window -child $box

$vb configure -value 1.0
$vb configure -onPopup {puts "popup %w"}
$vb configure -onPopdown {puts "popdown %w"}
$vb configure -onValueChanged {puts "valueChanged %w %v" ; set vol %v}
$vb configure -visible 1
$vb configure -sensitive 1
$vb configure -relief none
$vb configure -borderWidth 20
$vb configure -prelightBackgroundColor green 


gnocl::mainLoop

Monday, November 01, 2010

gnocl::iconView - adding items with labels

I've now created the structure to add options to the iconview add
command. This will be useful if some other info apart from a filepath is
needed. Also, in progress is the use of percentage markup strings. This
will enable the choice between file, stockitem and pixbuf sources. If
the specified icon is unavailable then a default item will be displayed.
Here's a sample of the test code...


set iv [gnocl::iconView \
    -columns 1 \

    -orientation vertical \

    -itemWidth 100 ]

gnocl::window \

    -title VERTICAL \

    -child $iv \

    -width 150 \

    -height 300 \

    -onDestroy {exit}


for {set i 1}  { $i <= 3} { incr i } {

  $iv add "%?im-0001.pnm" -label "item $i"
}
$iv add pointer.png -label pointer

$iv add upArrow.png -label up

$iv add downArrow.png -label down


And the result...








gnocl::infoBar -done!

Well, lets say 85% done. Enough for now anyway. This is a 'querky' sort of widget. The docs say:

GtkInfoBar is a widget that can be used to show messages to the user without showing a dialog. It is often temporarily shown at the top or bottom of a document. In contrast to GtkDialog, which has a horizontal action area at the bottom, GtkInfoBar has a vertical action area at the side.

Well. here's a screenshot and test script:



#---------------
# test-infobar.tcl
#---------------
# William J Giddings
# 01-Nov-2010
#---------------

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

package require Gnocl

set ib [gnocl::infoBar]

$ib configure -onResponse {
        switch -- %d \
            $but(OK)      {puts "You clicked the OK button."} \
            $but(CANCEL) {puts "You clicked the CANCEL button."} \
            default      {puts "You clicked something else!"}
         }

puts "$ib is a widget class: [$ib class]"

set box [gnocl::box]
set lab [gnocl::label -text "Add Extra Items Here!"]

$box add $lab -fill {1 0} -expand 1
$ib configure -child $box ;#-type info

set but(OK) [$ib add button OK]
set but(CANCEL) [$ib add button Cancel]

$ib configure -default 2

set txt [gnocl::text]
set frame [gnocl::box -orientation vertical]

$frame add $txt -fill {1 1} -expand 1
$frame add $ib

gnocl::window -child $frame

gnocl::infoBar -new module

Just added the bare bones module for the GtkInfoBar binding. This widget was introduced with Gtk+ 2.15. Hope to get a working demo finished before the end of the week.