| # |
| # 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 |
| } |