summaryrefslogtreecommitdiff
path: root/iwidgets/generic/canvasprintbox.itk
diff options
context:
space:
mode:
authorKeith Seitz <keiths@redhat.com>2002-09-24 23:50:31 +0000
committerKeith Seitz <keiths@redhat.com>2002-09-24 23:50:31 +0000
commit43375e54d64ecea0b356c82d72b29fd95dd54cc9 (patch)
tree7582d7bb623964e848d993dde740802e40a748b0 /iwidgets/generic/canvasprintbox.itk
parent5a88d945c95d8c15e31bf74fc9850b8c01fdeaec (diff)
downloadgdb-43375e54d64ecea0b356c82d72b29fd95dd54cc9.tar.gz
import iwidgets 4.0.1tcltk840-20020924-branchpoint
Diffstat (limited to 'iwidgets/generic/canvasprintbox.itk')
-rw-r--r--iwidgets/generic/canvasprintbox.itk1111
1 files changed, 1111 insertions, 0 deletions
diff --git a/iwidgets/generic/canvasprintbox.itk b/iwidgets/generic/canvasprintbox.itk
new file mode 100644
index 00000000000..9d41daae25d
--- /dev/null
+++ b/iwidgets/generic/canvasprintbox.itk
@@ -0,0 +1,1111 @@
+#
+# CanvasPrintBox v1.5
+# ----------------------------------------------------------------------
+# Implements a print box for printing the contents of a canvas widget
+# to a printer or a file. It is possible to specify page orientation, the
+# number of pages to print the image on and if the output should be
+# stretched to fit the page.
+#
+# CanvasPrintBox is a "super-widget" that can be used as an
+# element in ones own GUIs. It is used to print the contents
+# of a canvas (called the source hereafter) to a printer or a
+# file. Possible settings include: portrait and landscape orientation
+# of the output, stretching the output to fit the page while maintaining
+# a proper aspect-ratio and posterizing to enlarge the output to fit on
+# multiple pages. A stamp-sized copy of the source will be shown (called
+# the stamp hereafter) at all times to reflect the effect of changing
+# the settings will have on the output.
+#
+# ----------------------------------------------------------------------
+# AUTHOR: Tako Schotanus EMAIL: Tako.Schotanus@bouw.tno.nl
+# ----------------------------------------------------------------------
+# Copyright (c) 1995 Tako Schotanus
+# ======================================================================
+# Permission is hereby granted, without written agreement and without
+# license or royalty fees, to use, copy, modify, and distribute this
+# software and its documentation for any purpose, provided that the
+# above copyright notice and the following two paragraphs appear in
+# all copies of this software.
+#
+# IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR
+# DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+# ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN
+# IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+# DAMAGE.
+#
+# THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING,
+# BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+# FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+# ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO
+# PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+# ======================================================================
+
+#
+# Default resources.
+#
+option add *Canvasprintbox.filename "canvas.ps" widgetDefault
+option add *Canvasprintbox.hPageCnt 1 widgetDefault
+option add *Canvasprintbox.orient landscape widgetDefault
+option add *Canvasprintbox.output printer widgetDefault
+option add *Canvasprintbox.pageSize A4 widgetDefault
+option add *Canvasprintbox.posterize 0 widgetDefault
+option add *Canvasprintbox.printCmd lpr widgetDefault
+option add *Canvasprintbox.printRegion "" widgetDefault
+option add *Canvasprintbox.vPageCnt 1 widgetDefault
+
+#
+# Usual options.
+#
+itk::usual Canvasprintbox {
+ keep -background -cursor -textbackground -foreground
+}
+
+#<
+#
+# CanvasPrintBox is a "super-widget" that can be used as an
+# element in ones own GUIs. It is used to print the contents
+# of a canvas (called the source hereafter) to a printer or a
+# file. Possible settings include: portrait and landscape orientation
+# of the output, stretching the output to fit the page while maintaining
+# a proper aspect-ratio and posterizing to enlarge the output to fit on
+# multiple pages. A stamp-sized copy of the source will be shown (called
+# the stamp hereafter) at all times to reflect the effect of changing
+# the settings will have on the output.
+#
+#>
+itcl::class iwidgets::Canvasprintbox {
+ inherit itk::Widget
+
+ #
+ # Holds the current state for all check- and radiobuttons.
+ #
+ itk_option define -filename filename FileName "canvas.ps"
+ itk_option define -hpagecnt hPageCnt PageCnt 1
+ itk_option define -orient orient Orient "landscape"
+ itk_option define -output output Output "printer"
+ itk_option define -pagesize pageSize PageSize "A4"
+ itk_option define -posterize posterize Posterize 0
+ itk_option define -printcmd printCmd PrintCmd ""
+ itk_option define -printregion printRegion PrintRegion ""
+ itk_option define -stretch stretch Stretch 0
+ itk_option define -vpagecnt vPageCnt PageCnt 1
+
+ constructor {args} {}
+ destructor {}
+
+ # ---------------------------------------------------------------
+ # PUBLIC
+ #----------------------------------------------------------------
+ public {
+ method getoutput {}
+ method print {}
+ method refresh {}
+ method setcanvas {canv}
+ method stop {}
+ }
+
+ # ---------------------------------------------------------------
+ # PROTECTED
+ #----------------------------------------------------------------
+ protected {
+ #
+ # Just holds the names of some widgets/objects. "win" is used to
+ # determine if the object is fully constructed and initialized.
+ #
+ variable win ""
+ variable canvw ""
+
+ #
+ # The canvas we want to print.
+ #
+ variable canvas ""
+
+ #
+ # Boolean indicating if the attribute "orient" is set
+ # to landscape or not.
+ #
+ variable rotate 1
+
+ #
+ # Holds the configure options that were used to create this object.
+ #
+ variable init_opts ""
+
+ #
+ # The following attributes hold a list of lines that are
+ # currently drawn on the "stamp" to show how the page(s) is/are
+ # oriented. The first holds the vertical dividing lines and the
+ # second the horizontal ones.
+ #
+ variable hlines ""
+ variable vlines ""
+
+ #
+ # Updating is set when the thumbnail is being drawn. Settings
+ # this to 0 while drawing is still busy will terminate the
+ # proces.
+ # Restart_update can be set to 1 when the thumbnail is being
+ # drawn to force a redraw.
+ #
+ variable _reposition ""
+ variable _update_attr_id ""
+
+ method _calc_poster_size {}
+ method _calc_print_region {}
+ method _calc_print_scale {}
+ method _mapEventHandler {}
+ method _update_attr {{when later}}
+ method _update_canvas {{when later}}
+
+ common _globVar
+
+ proc ezPaperInfo {size {attr ""} \
+ {orient "portrait"} {window ""}} {}
+ }
+}
+
+#
+# Provide a lowercased access method for the Canvasprintbox class.
+#
+proc ::iwidgets::canvasprintbox {args} {
+ uplevel ::iwidgets::Canvasprintbox $args
+}
+
+# ------------------------------------------------------------------
+# OPTIONS
+# ------------------------------------------------------------------
+
+#<
+# A list of four coordinates specifying which part of the canvas to print.
+# An empty list means that the canvas' entire scrollregion should be
+# printed. Any change to this attribute will automatically update the "stamp".
+# Defaults to an empty list.
+#>
+itcl::configbody iwidgets::Canvasprintbox::printregion {
+ if {$itk_option(-printregion) != ""
+ && [llength $itk_option(-printregion)] != 4} {
+ error {bad option "printregion": should contain 4 coordinates}
+ }
+ _update_canvas
+}
+
+#<
+# Specifies where the postscript output should go: to the printer
+# or to a file. Can take on the values "printer" or "file".
+# The corresponding entry-widget will reflect the contents of
+# either the printcmd attribute or the filename attribute.
+#>
+itcl::configbody iwidgets::Canvasprintbox::output {
+ switch $itk_option(-output) {
+ file - printer {
+ set _globVar($this,output) $itk_option(-output)
+ }
+ default {
+ error {bad output option \"$itk_option(-output)\":\
+ should be file or printer}
+ }
+ }
+ _update_attr
+}
+
+#<
+# The command to execute when printing the postscript output.
+# The command will get the postscript directed to its standard
+# input. (Only when output is set to "printer")
+#>
+itcl::configbody iwidgets::Canvasprintbox::printcmd {
+ set _globVar($this,printeref) $itk_option(-printcmd)
+ _update_attr
+}
+
+#<
+# The file to write the postscript output to (Only when output
+# is set to "file"). If posterizing is turned on and hpagecnt
+# and/or vpagecnt is more than 1, x.y is appended to the filename
+# where x is the horizontal page number and y the vertical page number.
+#>
+itcl::configbody iwidgets::Canvasprintbox::filename {
+ set _globVar($this,fileef) $itk_option(-filename)
+ _update_attr
+}
+
+#<
+# The pagesize the printer supports. Changes to this attribute
+# will be reflected immediately in the "stamp".
+#>
+itcl::configbody iwidgets::Canvasprintbox::pagesize {
+ set opt [string tolower $itk_option(-pagesize)]
+ set lst [string tolower [ezPaperInfo types]]
+ if {[lsearch $lst $opt] == -1} {
+ error "bad option \"pagesize\": should be one of: [ezPaperInfo types]"
+ }
+ $itk_component(paperom) select "*[string range $opt 1 end]"
+ _update_canvas
+}
+
+#<
+# Determines the orientation of the output to the printer (or file).
+# It can take the value "portrait" or "landscape" (default). Changes
+# to this attribute will be reflected immediately in the "stamp".
+#>
+itcl::configbody iwidgets::Canvasprintbox::orient {
+ switch $itk_option(-orient) {
+ "portrait" - "landscape" {
+ $itk_component(orientom) select $itk_option(-orient)
+ _update_canvas
+
+ }
+ default {
+ error "bad orient option \"$itk_option(-orient)\":\
+ should be portrait or landscape"
+ }
+ }
+}
+
+#<
+# Determines if the output should be stretched to fill the
+# page (as defined by the attribute pagesize) as large as
+# possible. The aspect-ratio of the output will be retained
+# and the output will never fall outside of the boundaries
+# of the page.
+#>
+itcl::configbody iwidgets::Canvasprintbox::stretch {
+ if {$itk_option(-stretch) != 0 && $itk_option(-stretch) != 1} {
+ error {bad option "stretch": should be a boolean}
+ }
+ set _globVar($this,stretchcb) $itk_option(-stretch)
+ _update_attr
+}
+
+#<
+# Indicates if posterizing is turned on or not. Posterizing
+# the output means that it is possible to distribute the
+# output over more than one page. This way it is possible to
+# print a canvas/region which is larger than the specified
+# pagesize without stretching. If used in combination with
+# stretching it can be used to "blow up" the contents of a
+# canvas to as large as size as you want (See attributes:
+# hpagecnt end vpagecnt). Any change to this attribute will
+# automatically update the "stamp".
+#>
+itcl::configbody iwidgets::Canvasprintbox::posterize {
+ if {$itk_option(-posterize) != "0" && $itk_option(-posterize) != "1"} {
+ error "expected boolean but got \"$itk_option(-posterize)\""
+ }
+ set _globVar($this,postercb) $itk_option(-posterize)
+ _update_canvas
+}
+
+#<
+# Is used in combination with "posterize" to determine over
+# how many pages the output should be distributed. This
+# attribute specifies how many pages should be used horizontaly.
+# Any change to this attribute will automatically update the "stamp".
+#>
+itcl::configbody iwidgets::Canvasprintbox::hpagecnt {
+ set _globVar($this,hpc) $itk_option(-hpagecnt)
+ _update_canvas
+}
+
+#<
+# Is used in combination with "posterize" to determine over
+# how many pages the output should be distributed. This
+# attribute specifies how many pages should be used verticaly.
+# Any change to this attribute will automatically update the "stamp".
+#>
+itcl::configbody iwidgets::Canvasprintbox::vpagecnt {
+ set _globVar($this,vpc) $itk_option(-vpagecnt)
+ _update_canvas
+}
+
+# ------------------------------------------------------------------
+# CONSTRUCTOR
+# ------------------------------------------------------------------
+itcl::body iwidgets::Canvasprintbox::constructor {args} {
+ set _globVar($this,output) printer
+ set _globVar($this,printeref) ""
+ set _globVar($this,fileef) "canvas.ps"
+ set _globVar($this,hpc) 1
+ set _globVar($this,vpc) 1
+ set _globVar($this,postercb) 0
+ set _globVar($this,stretchcb) 0
+
+ itk_component add canvasframe {
+ frame $itk_interior.f18 -bd 2
+ }
+
+ itk_component add canvas {
+ canvas $itk_component(canvasframe).c1 \
+ -bd 2 -relief sunken \
+ -scrollregion {0c 0c 10c 10c} \
+ -width 250
+ }
+ pack $itk_component(canvas) -expand 1 -fill both
+
+ itk_component add outputom {
+ iwidgets::Labeledframe $itk_interior.outputom \
+ -labelpos nw \
+ -labeltext "Output to"
+ }
+ set cs [$itk_component(outputom) childsite]
+
+ itk_component add printerrb {
+ radiobutton $cs.printerrb \
+ -text Printer \
+ -variable [itcl::scope _globVar($this,output)] \
+ -anchor w \
+ -justify left \
+ -value printer \
+ -command [itcl::code $this _update_attr]
+ } {
+ usual
+ rename -font -labelfont labelFont Font
+ }
+ itk_component add printeref {
+ iwidgets::entryfield $cs.printeref \
+ -labeltext "command:" \
+ -state normal \
+ -labelpos w \
+ -textvariable [itcl::scope _globVar($this,printeref)]
+ }
+
+ itk_component add filerb {
+ radiobutton $cs.filerb \
+ -text File \
+ -justify left \
+ -anchor w \
+ -variable [itcl::scope _globVar($this,output)] \
+ -value file \
+ -command [itcl::code $this _update_attr]
+ } {
+ usual
+ rename -font -labelfont labelFont Font
+ }
+ itk_component add fileef {
+ iwidgets::entryfield $cs.fileef \
+ -labeltext "filename:" \
+ -state disabled \
+ -labelpos w \
+ -textvariable [itcl::scope _globVar($this,fileef)]
+ }
+
+ itk_component add propsframe {
+ iwidgets::Labeledframe $itk_interior.propsframe \
+ -labelpos nw \
+ -labeltext "Properties"
+ }
+ set cs [$itk_component(propsframe) childsite]
+
+ itk_component add paperom {
+ iwidgets::optionmenu $cs.paperom \
+ -labelpos w -cyclicon 1 \
+ -labeltext "Paper size:" \
+ -command [itcl::code $this refresh]
+ } {
+ usual
+ rename -font -labelfont labelFont Font
+ }
+ eval $itk_component(paperom) insert end [ezPaperInfo types]
+ $itk_component(paperom) select A4
+
+ itk_component add orientom {
+ iwidgets::radiobox $itk_interior.orientom \
+ -labeltext "Orientation" -command [itcl::code $this refresh]
+ }
+ $itk_component(orientom) add landscape -text Landscape
+ $itk_component(orientom) add portrait -text Portrait
+ $itk_component(orientom) select 0
+
+ itk_component add stretchcb {
+ checkbutton $cs.stretchcb \
+ -relief flat \
+ -text {Stretch to fit} \
+ -justify left \
+ -anchor w \
+ -variable [itcl::scope _globVar($this,stretchcb)] \
+ -command [itcl::code $this refresh]
+ } {
+ usual
+ rename -font -labelfont labelFont Font
+ }
+
+ itk_component add postercb {
+ checkbutton $cs.postercb \
+ -relief flat \
+ -text Posterize \
+ -justify left \
+ -anchor w \
+ -variable [itcl::scope _globVar($this,postercb)] \
+ -command [itcl::code $this refresh]
+ } {
+ usual
+ rename -font -labelfont labelFont Font
+ }
+
+ itk_component add hpcnt {
+ iwidgets::entryfield $cs.hpcnt \
+ -labeltext on \
+ -textvariable [itcl::scope _globVar($this,hpc)] \
+ -validate integer -width 3 \
+ -command [itcl::code $this refresh]
+ }
+
+ itk_component add vpcnt {
+ iwidgets::entryfield $cs.vpcnt \
+ -labeltext by \
+ -textvariable [itcl::scope _globVar($this,vpc)] \
+ -validate integer -width 3 \
+ -command [itcl::code $this refresh]
+ }
+
+ itk_component add pages {
+ label $cs.pages -text pages.
+ } {
+ usual
+ rename -font -labelfont labelFont Font
+ }
+
+ set init_opts $args
+
+ grid $itk_component(canvasframe) -row 0 -column 0 -rowspan 4 -sticky nsew
+ grid $itk_component(propsframe) -row 0 -column 1 -sticky nsew
+ grid $itk_component(outputom) -row 1 -column 1 -sticky nsew
+ grid $itk_component(orientom) -row 2 -column 1 -sticky nsew
+ grid columnconfigure $itk_interior 0 -weight 1
+ grid rowconfigure $itk_interior 3 -weight 1
+
+ grid $itk_component(printerrb) -row 0 -column 0 -sticky nsw
+ grid $itk_component(printeref) -row 0 -column 1 -sticky nsw
+ grid $itk_component(filerb) -row 1 -column 0 -sticky nsw
+ grid $itk_component(fileef) -row 1 -column 1 -sticky nsw
+ iwidgets::Labeledwidget::alignlabels $itk_component(printeref) $itk_component(fileef)
+ grid columnconfigure $itk_component(outputom) 1 -weight 1
+
+ grid $itk_component(paperom) -row 0 -column 0 -columnspan 2 -sticky nsw
+ grid $itk_component(stretchcb) -row 1 -column 0 -sticky nsw
+ grid $itk_component(postercb) -row 2 -column 0 -sticky nsw
+ grid $itk_component(hpcnt) -row 2 -column 1 -sticky nsw
+ grid $itk_component(vpcnt) -row 2 -column 2 -sticky nsw
+ grid $itk_component(pages) -row 2 -column 3 -sticky nsw
+ grid columnconfigure $itk_component(propsframe) 3 -weight 1
+
+ eval itk_initialize $args
+
+ bind $itk_component(pages) <Map> +[itcl::code $this _mapEventHandler]
+ bind $itk_component(canvas) <Configure> +[itcl::code $this refresh]
+}
+
+
+# ---------------------------------------------------------------
+# PUBLIC METHODS
+#----------------------------------------------------------------
+
+#<
+# This is used to set the canvas that has to be printed.
+# A stamp-sized copy will automatically be drawn to show how the
+# output would look with the current settings.
+#
+# In: canv - The canvas to be printed
+# Out: canvas (attrib) - Holds the canvas to be printed
+#>
+itcl::body iwidgets::Canvasprintbox::setcanvas {canv} {
+ set canvas $canv
+ _update_canvas
+}
+
+#<
+# Returns the value of the -printercmd or -filename option
+# depending on the current setting of -output.
+#
+# In: itk_option (attrib)
+# Out: The value of -printercmd or -filename
+#>
+itcl::body iwidgets::Canvasprintbox::getoutput {} {
+ switch $_globVar($this,output) {
+ "file" {
+ return $_globVar($this,fileef)
+ }
+ "printer" {
+ return $_globVar($this,printeref)
+ }
+ }
+ return ""
+}
+
+#<
+# Perfrom the actual printing of the canvas using the current settings of
+# all the attributes.
+#
+# In: itk_option, rotate (attrib)
+# Out: A boolean indicating wether printing was successful
+#>
+itcl::body iwidgets::Canvasprintbox::print {} {
+
+ global env tcl_platform
+
+ stop
+
+ if {$itk_option(-output) == "file"} {
+ set nm $_globVar($this,fileef)
+ if {[string range $nm 0 1] == "~/"} {
+ set nm "$env(HOME)/[string range $nm 2 end]"
+ }
+ } else {
+ set nm "/tmp/xge[winfo id $canvas]"
+ }
+
+ set pr [_calc_print_region]
+ set x1 [lindex $pr 0]
+ set y1 [lindex $pr 1]
+ set x2 [lindex $pr 2]
+ set y2 [lindex $pr 3]
+ set cx [expr {int(($x2 + $x1) / 2)}]
+ set cy [expr {int(($y2 + $y1) / 2)}]
+ if {!$itk_option(-stretch)} {
+ set ps [_calc_poster_size]
+ set pshw [expr {int([lindex $ps 0] / 2)}]
+ set pshh [expr {int([lindex $ps 1] / 2)}]
+ set x [expr {$cx - $pshw}]
+ set y [expr {$cy - $pshh}]
+ set w [ezPaperInfo $itk_option(-pagesize) pwidth $itk_option(-orient) $win]
+ set h [ezPaperInfo $itk_option(-pagesize) pheight $itk_option(-orient) $win]
+ } else {
+ set x $x1
+ set y $y1
+ set w [expr {($x2-$x1) / $_globVar($this,hpc)}]
+ set h [expr {($y2-$y1) / $_globVar($this,vpc)}]
+ }
+
+ set i 0
+ set px $x
+ while {$i < $_globVar($this,hpc)} {
+ set j 0
+ set py $y
+ while {$j < $_globVar($this,vpc)} {
+ set nm2 [expr {$_globVar($this,hpc) > 1 || $_globVar($this,vpc) > 1 ? "$nm$i.$j" : $nm}]
+
+ if {$itk_option(-stretch)} {
+ $canvas postscript \
+ -file $nm2 \
+ -rotate $rotate \
+ -x $px -y $py \
+ -width $w \
+ -height $h \
+ -pagex [ezPaperInfo $itk_option(-pagesize) centerx] \
+ -pagey [ezPaperInfo $itk_option(-pagesize) centery] \
+ -pagewidth [ezPaperInfo $itk_option(-pagesize) pwidth $itk_option(-orient)] \
+ -pageheight [ezPaperInfo $itk_option(-pagesize) pheight $itk_option(-orient)]
+ } else {
+ $canvas postscript \
+ -file $nm2 \
+ -rotate $rotate \
+ -x $px -y $py \
+ -width $w \
+ -height $h \
+ -pagex [ezPaperInfo $itk_option(-pagesize) centerx] \
+ -pagey [ezPaperInfo $itk_option(-pagesize) centery]
+ }
+
+ if {$itk_option(-output) == "printer"} {
+ set cmd "$itk_option(-printcmd) < $nm2"
+ if {[catch {eval exec $cmd &}]} {
+ return 0
+ }
+ }
+
+ set py [expr {$py + $h}]
+ incr j
+ }
+ set px [expr {$px + $w}]
+ incr i
+ }
+
+ return 1
+}
+
+#<
+# Retrieves the current value for all edit fields and updates
+# the stamp accordingly. Is useful for Apply-buttons.
+#>
+itcl::body iwidgets::Canvasprintbox::refresh {} {
+ stop
+ _update_canvas
+ return
+}
+
+#<
+# Stops the drawing of the "stamp". I'm currently unable to detect
+# when a Canvasprintbox gets withdrawn. It's therefore advised
+# that you perform a stop before you do something like that.
+#>
+itcl::body iwidgets::Canvasprintbox::stop {} {
+
+ if {$_reposition != ""} {
+ after cancel $_reposition
+ set _reposition ""
+ }
+
+ if {$_update_attr_id != ""} {
+ after cancel $_update_attr_id
+ set _update_attr_id ""
+ }
+
+ return
+}
+
+# ---------------------------------------------------------------
+# PROTECTED METHODS
+#----------------------------------------------------------------
+
+#
+# Calculate the total size the output would be with the current
+# settings for "pagesize" and "posterize" (and "hpagecnt" and
+# "vpagecnt"). This size will be the size of the printable area,
+# some space has been substracted to take into account that a
+# page should have borders because most printers can't print on
+# the very edge of the paper.
+#
+# In: posterize, hpagecnt, vpagecnt, pagesize, orient (attrib)
+# Out: A list of two numbers indicating the width and the height
+# of the total paper area which will be used for printing
+# in pixels.
+#
+itcl::body iwidgets::Canvasprintbox::_calc_poster_size {} {
+ set tpw [expr {[ezPaperInfo $itk_option(-pagesize) \
+ pwidth $itk_option(-orient) $win]*$_globVar($this,hpc)}]
+ set tph [expr {[ezPaperInfo $itk_option(-pagesize) \
+ pheight $itk_option(-orient) $win]*$_globVar($this,vpc)}]
+
+ return "$tpw $tph"
+}
+
+#
+# Determine which area of the "source" canvas will be printed.
+# If "printregion" was set by the "user" this will be used and
+# converted to pixel-coordinates. If the user didn't set it
+# the bounding box that contains all canvas-items will be used
+# instead.
+#
+# In: printregion, canvas (attrib)
+# Out: Four floats specifying the region to be printed in
+# pixel-coordinates (topleft & bottomright).
+#
+itcl::body iwidgets::Canvasprintbox::_calc_print_region {} {
+ set printreg [expr {$itk_option(-printregion) != ""
+ ? $itk_option(-printregion) : [$canvas bbox all]}]
+
+ if {$printreg != ""} {
+ set prx1 [winfo fpixels $canvas [lindex $printreg 0]]
+ set pry1 [winfo fpixels $canvas [lindex $printreg 1]]
+ set prx2 [winfo fpixels $canvas [lindex $printreg 2]]
+ set pry2 [winfo fpixels $canvas [lindex $printreg 3]]
+
+ set res "$prx1 $pry1 $prx2 $pry2"
+ } else {
+ set res "0 0 0 0"
+ }
+
+ return $res
+}
+
+#
+# Calculate the scaling factor needed if the output was
+# to be stretched to fit exactly on the page (or pages).
+# If stretching is turned off this will always return 1.0.
+#
+# In: stretch (attrib)
+# Out: A float specifying the scaling factor.
+#
+itcl::body iwidgets::Canvasprintbox::_calc_print_scale {} {
+ if {$itk_option(-stretch)} {
+ set pr [_calc_print_region]
+ set prw [expr {[lindex $pr 2] - [lindex $pr 0]}]
+ set prh [expr {[lindex $pr 3] - [lindex $pr 1]}]
+ set ps [_calc_poster_size]
+ set psw [lindex $ps 0]
+ set psh [lindex $ps 1]
+ set sfx [expr {$psw / $prw}]
+ set sfy [expr {$psh / $prh}]
+ set sf [expr {$sfx < $sfy ? $sfx : $sfy}]
+ return $sf
+ } else {
+ return 1.0
+ }
+}
+
+#
+# Schedule the thread that makes a copy of the "source"
+# canvas to the "stamp".
+#
+# In: win, canvas (attrib)
+# Out: -
+#
+itcl::body iwidgets::Canvasprintbox::_update_canvas {{when later}} {
+ if {$win == "" || $canvas == "" || [$canvas find all] == ""} {
+ return
+ }
+ if {$when == "later"} {
+ if {$_reposition == ""} {
+ set _reposition [after idle [itcl::code $this _update_canvas now]]
+ }
+ return
+ }
+
+ _update_attr now
+
+ #
+ # Make a copy of the "source" canvas to the "stamp".
+ #
+ if {$_globVar($this,hpc) == [llength $vlines] &&
+ $_globVar($this,vpc) == [llength $hlines]} {
+ stop
+ return
+ }
+
+ $canvw delete all
+
+ set width [winfo width $canvw]
+ set height [winfo height $canvw]
+ set ps [_calc_poster_size]
+
+ #
+ # Calculate the scaling factor that would be needed to fit the
+ # whole "source" into the "stamp". This takes into account the
+ # total amount of "paper" that would be needed to print the
+ # contents of the "source".
+ #
+ set xsf [expr {$width/[lindex $ps 0]}]
+ set ysf [expr {$height/[lindex $ps 1]}]
+ set sf [expr {$xsf < $ysf ? $xsf : $ysf}]
+ set w [expr {[lindex $ps 0]*$sf}]
+ set h [expr {[lindex $ps 1]*$sf}]
+ set x1 [expr {($width-$w)/2}]
+ set y1 [expr {($height-$h)/2}]
+ set x2 [expr {$x1+$w}]
+ set y2 [expr {$y1+$h}]
+ set cx [expr {($x2+$x1)/ 2}]
+ set cy [expr {($y2+$y1)/ 2}]
+
+ set printreg [_calc_print_region]
+ set prx1 [lindex $printreg 0]
+ set pry1 [lindex $printreg 1]
+ set prx2 [lindex $printreg 2]
+ set pry2 [lindex $printreg 3]
+ set prcx [expr {($prx2+$prx1)/2}]
+ set prcy [expr {($pry2+$pry1)/2}]
+
+ set psf [_calc_print_scale]
+
+ #
+ # Copy all items from the "real" canvas to the canvas
+ # showing what we'll send to the printer. Bitmaps and
+ # texts are not copied because they can't be scaled,
+ # a rectangle will be created instead.
+ #
+ set tsf [expr {$sf * $psf}]
+ set dx [expr {$cx-($prcx*$tsf)}]
+ set dy [expr {$cy-($prcy*$tsf)}]
+ $canvw create rectangle \
+ [expr {$x1+0}] \
+ [expr {$y1+0}] \
+ [expr {$x2-0}] \
+ [expr {$y2-0}] -fill white
+ set items [eval "$canvas find overlapping $printreg"]
+
+ set itemCount [llength $items]
+ for {set cnt 0} {$cnt < $itemCount} {incr cnt} {
+ #
+ # Determine the item's type and coordinates
+ #
+ set i [lindex $items $cnt]
+ set t [$canvas type $i]
+ set crds [$canvas coords $i]
+
+ #
+ # Ask for the item's configuration settings and strip
+ # it to leave only a list of option names and values.
+ #
+ set cfg [$canvas itemconfigure $i]
+ set cfg2 ""
+ foreach c $cfg {
+ if {[llength $c] == 5} {
+ lappend cfg2 [lindex $c 0] [lindex $c 4]
+ }
+ }
+
+ #
+ # Handle texts and bitmaps differently: they will
+ # be represented as rectangles.
+ #
+ if {$t == "text" || $t == "bitmap" || $t == "window"} {
+ set t "rectangle"
+ set crds [$canvas bbox $i]
+ set cfg2 "-outline {} -fill gray"
+ }
+
+ #
+ # Remove the arrows from a line item when the scale
+ # factor drops below 1/3rd of the original size.
+ # This to prevent the arrowheads from dominating the
+ # display.
+ #
+ if {$t == "line" && $tsf < 0.33} {
+ lappend cfg2 -arrow none
+ }
+
+ #
+ # Create a copy of the item on the "printing" canvas.
+ #
+ set i2 [eval "$canvw create $t $crds $cfg2"]
+ $canvw scale $i2 0 0 $tsf $tsf
+ $canvw move $i2 $dx $dy
+
+ if {($cnt%25) == 0} {
+ update
+ }
+ if {$_reposition == ""} {
+ return
+ }
+ }
+
+ set p $x1
+ set i 1
+ set vlines {}
+ while {$i < $_globVar($this,hpc)} {
+ set p [expr {$p + ($w/$_globVar($this,hpc))}]
+ set l [$canvw create line $p $y1 $p $y2]
+ lappend vlines $l
+ incr i
+ }
+
+ set p $y1
+ set i 1
+ set vlines {}
+ while {$i < $_globVar($this,vpc)} {
+ set p [expr {$p + ($h/$_globVar($this,vpc))}]
+ set l [$canvw create line $x1 $p $x2 $p]
+ lappend vlines $l
+ incr i
+ }
+
+ set _reposition ""
+}
+
+#
+# Update the attributes to reflect changes made in the user-
+# interface.
+#
+# In: itk_option (attrib) - the attributes to update
+# itk_component (attrib) - the widgets
+# _globVar (common) - the global var holding the state
+# of all radiobuttons and checkboxes.
+# Out: -
+#
+itcl::body iwidgets::Canvasprintbox::_update_attr {{when "later"}} {
+ if {$when != "now"} {
+ if {$_update_attr_id == ""} {
+ set _update_attr_id [after idle [itcl::code $this _update_attr now]]
+ }
+ return
+ }
+
+ set itk_option(-printcmd) $_globVar($this,printeref)
+ set itk_option(-filename) $_globVar($this,fileef)
+ set itk_option(-output) $_globVar($this,output)
+ set itk_option(-pagesize) [string tolower [$itk_component(paperom) get]]
+ set itk_option(-stretch) $_globVar($this,stretchcb)
+ set itk_option(-posterize) $_globVar($this,postercb)
+ set itk_option(-vpagecnt) $_globVar($this,vpc)
+ set itk_option(-hpagecnt) $_globVar($this,hpc)
+ set itk_option(-orient) [$itk_component(orientom) get]
+ set rotate [expr {$itk_option(-orient) == "landscape"}]
+
+ if {$_globVar($this,output) == "file"} {
+ $itk_component(fileef) configure \
+ -state normal -foreground $itk_option(-foreground)
+ $itk_component(printeref) configure \
+ -state disabled -foreground $itk_option(-disabledforeground)
+ } else {
+ $itk_component(fileef) configure \
+ -state disabled -foreground $itk_option(-disabledforeground)
+ $itk_component(printeref) configure \
+ -state normal -foreground $itk_option(-foreground)
+ }
+
+ set fg [expr {$_globVar($this,postercb) \
+ ? $itk_option(-foreground) : $itk_option(-disabledforeground)}]
+
+ $itk_component(vpcnt) configure -foreground $fg
+ $itk_component(hpcnt) configure -foreground $fg
+ $itk_component(pages) configure -foreground $fg
+
+ #
+ # Update dependencies among widgets. (For example: disabling
+ # an entry-widget when its associated checkbox-button is used
+ # to turn of the option (the entry's value is not needed
+ # anymore and this should be reflected in the fact that it
+ # isn't possible to change it anymore).
+ #
+ # former method:_update_widgets/_update_UI
+ #
+ set state [expr {$itk_option(-posterize) ? "normal" : "disabled"}]
+ $itk_component(vpcnt) configure -state $state
+ $itk_component(hpcnt) configure -state $state
+ $itk_component(paperom) select "*[string range $itk_option(-pagesize) 1 end]"
+
+ set _update_attr_id ""
+}
+
+#
+# Gets called when the CanvasPrintBox-widget gets mapped.
+#
+itcl::body iwidgets::Canvasprintbox::_mapEventHandler {} {
+ set win $itk_interior
+ set canvw $itk_component(canvas)
+ if {$canvas != ""} {
+ setcanvas $canvas
+ }
+ _update_attr
+}
+
+#
+# Destroy this object and its associated widgets.
+#
+itcl::body iwidgets::Canvasprintbox::destructor {} {
+ stop
+}
+
+#
+# Hold the information about common paper sizes. A bit of a hack, but it
+# should be possible to add your own if you take a look at it.
+#
+itcl::body iwidgets::Canvasprintbox::ezPaperInfo {size {attr ""} \
+ {orient "portrait"} {window ""}} {
+
+ set size [string tolower $size]
+ set attr [string tolower $attr]
+ set orient [string tolower $orient]
+
+ case $size in {
+ types {
+ return "A5 A4 A3 A2 A1 Legal Letter"
+ }
+ a5 {
+ set paper(x1) "1.0c"
+ set paper(y1) "1.0c"
+ set paper(x2) "13.85c"
+ set paper(y2) "20.0c"
+ set paper(pheight) "19.0c"
+ set paper(pwidth) "12.85c"
+ set paper(height) "21.0c"
+ set paper(width) "14.85c"
+ set paper(centerx) "7.425c"
+ set paper(centery) "10.5c"
+ }
+ a4 {
+ set paper(x1) "1.0c"
+ set paper(y1) "1.0c"
+ set paper(x2) "20.0c"
+ set paper(y2) "28.7c"
+ set paper(pheight) "27.7c"
+ set paper(pwidth) "19.0c"
+ set paper(height) "29.7c"
+ set paper(width) "21.0c"
+ set paper(centerx) "10.5c"
+ set paper(centery) "14.85c"
+ }
+ a3 {
+ set paper(x1) "1.0c"
+ set paper(y1) "1.0c"
+ set paper(x2) "28.7c"
+ set paper(y2) "41.0c"
+ set paper(pheight) "40.0c"
+ set paper(pwidth) "27.7c"
+ set paper(height) "42.0c"
+ set paper(width) "29.7c"
+ set paper(centerx) "14.85c"
+ set paper(centery) "21.0c"
+ }
+ a2 {
+ set paper(x1) "1.0c"
+ set paper(y1) "1.0c"
+ set paper(x2) "41.0c"
+ set paper(y2) "58.4c"
+ set paper(pheight) "57.4c"
+ set paper(pwidth) "40.0c"
+ set paper(height) "59.4c"
+ set paper(width) "42.0c"
+ set paper(centerx) "21.0c"
+ set paper(centery) "29.7c"
+ }
+ a1 {
+ set paper(x1) "1.0c"
+ set paper(y1) "1.0c"
+ set paper(x2) "58.4c"
+ set paper(y2) "83.0c"
+ set paper(pheight) "82.0c"
+ set paper(pwidth) "57.4c"
+ set paper(height) "84.0c"
+ set paper(width) "59.4c"
+ set paper(centerx) "29.7c"
+ set paper(centery) "42.0c"
+ }
+ legal {
+ set paper(x1) "0.2i"
+ set paper(y1) "0.2i"
+ set paper(x2) "8.3i"
+ set paper(y2) "13.8i"
+ set paper(pheight) "13.6i"
+ set paper(pwidth) "8.1i"
+ set paper(height) "14.0i"
+ set paper(width) "8.5i"
+ set paper(centerx) "4.25i"
+ set paper(centery) "7.0i"
+ }
+ letter {
+ set paper(x1) "0.2i"
+ set paper(y1) "0.2i"
+ set paper(x2) "8.3i"
+ set paper(y2) "10.8i"
+ set paper(pheight) "10.6i"
+ set paper(pwidth) "8.1i"
+ set paper(height) "11.0i"
+ set paper(width) "8.5i"
+ set paper(centerx) "4.25i"
+ set paper(centery) "5.5i"
+ }
+ default {
+ error "ezPaperInfo: Unknown paper type ($type)"
+ }
+ }
+
+ set inv(x1) "y1"
+ set inv(x2) "y2"
+ set inv(y1) "x1"
+ set inv(y2) "x2"
+ set inv(pwidth) "pheight"
+ set inv(pheight) "pwidth"
+ set inv(width) "height"
+ set inv(height) "width"
+ set inv(centerx) "centery"
+ set inv(centery) "centerx"
+
+ case $orient in {
+ landscape {
+ set res $paper($inv($attr))
+ }
+ portrait {
+ set res $paper($attr)
+ }
+ default {
+ error "ezPaperInfo: orientation should be\
+ portrait or landscape (not $orient)"
+ }
+ }
+
+ if {$window != ""} {
+ set res [winfo fpixels $window $res]
+ }
+
+ return $res
+}