1#
2# Scrolledtext
3# ----------------------------------------------------------------------
4# Implements a scrolled text widget with additional options to manage
5# the vertical scrollbar.  This includes options to control the method
6# in which the scrollbar is displayed, i.e. statically or  dynamically.
7# Options also exist for adding a label to the scrolled text area and
8# controlling its position.  Import/export of methods are provided for
9# file I/O.
10#
11# ----------------------------------------------------------------------
12#  AUTHOR: Mark L. Ulferts              EMAIL: mulferts@austin.dsccc.com
13#
14#  @(#) $Id: scrolledtext.itk,v 1.5 2002/09/10 03:05:25 smithc Exp $
15# ----------------------------------------------------------------------
16#            Copyright (c) 1995 DSC Technologies Corporation
17# ======================================================================
18# Permission to use, copy, modify, distribute and license this software
19# and its documentation for any purpose, and without fee or written
20# agreement with DSC, is hereby granted, provided that the above copyright
21# notice appears in all copies and that both the copyright notice and
22# warranty disclaimer below appear in supporting documentation, and that
23# the names of DSC Technologies Corporation or DSC Communications
24# Corporation not be used in advertising or publicity pertaining to the
25# software without specific, written prior permission.
26#
27# DSC DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
28# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, AND NON-
29# INFRINGEMENT. THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND THE
30# AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE,
31# SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. IN NO EVENT SHALL
32# DSC BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
33# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
34# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTUOUS ACTION,
35# ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
36# SOFTWARE.
37# ======================================================================
38
39#
40# Usual options.
41#
42itk::usual Scrolledtext {
43    keep -activebackground -activerelief -background -borderwidth -cursor \
44	 -elementborderwidth -foreground -highlightcolor -highlightthickness \
45	 -insertbackground -insertborderwidth -insertofftime -insertontime \
46	 -insertwidth -jump -labelfont -selectbackground -selectborderwidth \
47	 -selectforeground -textbackground -textfont -troughcolor
48}
49
50# ------------------------------------------------------------------
51#                           SCROLLEDTEXT
52# ------------------------------------------------------------------
53itcl::class iwidgets::Scrolledtext {
54    inherit iwidgets::Scrolledwidget
55
56    constructor {args} {}
57    destructor {}
58
59    itk_option define -width width Width 0
60    itk_option define -height height Height 0
61    itk_option define -visibleitems visibleItems VisibleItems 80x24
62
63    public method bbox {index}
64    public method childsite {}
65    public method clear {}
66    public method import {filename {index end}}
67    public method export {filename}
68    public method compare {index1 op index2}
69    public method debug {args}
70    public method delete {first {last {}}}
71    public method dlineinfo {index}
72    public method get {index1 {index2 {}}}
73    public method image {option args}
74    public method index {index}
75    public method insert {args}
76    public method mark {option args}
77    public method scan {option args}
78    public method search {args}
79    public method see {index}
80    public method tag {option args}
81    public method window {option args}
82    public method xview {args}
83    public method yview {args}
84}
85
86#
87# Provide a lowercased access method for the Scrolledtext class.
88#
89proc ::iwidgets::scrolledtext {pathName args} {
90    uplevel ::iwidgets::Scrolledtext $pathName $args
91}
92
93#
94# Use option database to override default resources of base classes.
95#
96option add *Scrolledtext.labelPos n widgetDefault
97
98# ------------------------------------------------------------------
99#                        CONSTRUCTOR
100# ------------------------------------------------------------------
101itcl::body iwidgets::Scrolledtext::constructor {args} {
102    #
103    # Our -width and -height options are slightly different than
104    # those implemented by our base class, so we're going to
105    # remove them and redefine our own.
106    #
107    itk_option remove iwidgets::Scrolledwidget::width
108    itk_option remove iwidgets::Scrolledwidget::height
109
110    #
111    # Create a clipping frame which will provide the border for
112    # relief display.
113    #
114    itk_component add clipper {
115	frame $itk_interior.clipper
116    } {
117	usual
118
119	keep -borderwidth -relief -highlightthickness -highlightcolor
120	rename -highlightbackground -background background Background
121    }
122    grid $itk_component(clipper) -row 0 -column 0 -sticky nsew
123    grid rowconfigure $_interior 0 -weight 1
124    grid columnconfigure $_interior 0 -weight 1
125
126    #
127    # Create the text area.
128    #
129    itk_component add text {
130	text $itk_component(clipper).text \
131		-width 1 -height 1 \
132	        -xscrollcommand \
133		[itcl::code $this _scrollWidget $itk_interior.horizsb] \
134		-yscrollcommand \
135		[itcl::code $this _scrollWidget $itk_interior.vertsb] \
136	        -borderwidth 0 -highlightthickness 0
137    } {
138	usual
139
140	ignore -highlightthickness -highlightcolor -borderwidth
141
142	keep -exportselection -padx -pady -setgrid \
143	     -spacing1 -spacing2 -spacing3 -state -tabs -wrap
144
145	rename -font -textfont textFont Font
146	rename -background -textbackground textBackground Background
147    }
148    grid $itk_component(text) -row 0 -column 0 -sticky nsew
149    grid rowconfigure $itk_component(clipper) 0 -weight 1
150    grid columnconfigure $itk_component(clipper) 0 -weight 1
151
152    #
153    # Configure the command on the vertical scroll bar in the base class.
154    #
155    $itk_component(vertsb) configure \
156	-command [itcl::code $itk_component(text) yview]
157
158    #
159    # Configure the command on the horizontal scroll bar in the base class.
160    #
161    $itk_component(horizsb) configure \
162		-command [itcl::code $itk_component(text) xview]
163
164    #
165    # Initialize the widget based on the command line options.
166    #
167    eval itk_initialize $args
168}
169
170# ------------------------------------------------------------------
171#                           DESTURCTOR
172# ------------------------------------------------------------------
173itcl::body iwidgets::Scrolledtext::destructor {} {
174}
175
176# ------------------------------------------------------------------
177#                             OPTIONS
178# ------------------------------------------------------------------
179
180# ------------------------------------------------------------------
181# OPTION: -width
182#
183# Specifies the width of the scrolled text as an entire unit.
184# The value may be specified in any of the forms acceptable to
185# Tk_GetPixels.  Any additional space needed to display the other
186# components such as labels, margins, and scrollbars force the text
187# to be compressed.  A value of zero along with the same value for
188# the height causes the value given for the visibleitems option
189# to be applied which administers geometry constraints in a different
190# manner.
191# ------------------------------------------------------------------
192itcl::configbody iwidgets::Scrolledtext::width {
193    if {$itk_option(-width) != 0} {
194	set shell [lindex [grid info $itk_component(clipper)] 1]
195
196	#
197	# Due to a bug in the tk4.2 grid, we have to check the
198	# propagation before setting it.  Setting it to the same
199	# value it already is will cause it to toggle.
200	#
201	if {[grid propagate $shell]} {
202	    grid propagate $shell no
203	}
204
205	$itk_component(text) configure -width 1
206	$shell configure \
207		-width [winfo pixels $shell $itk_option(-width)]
208    } else {
209	configure -visibleitems $itk_option(-visibleitems)
210    }
211}
212
213# ------------------------------------------------------------------
214# OPTION: -height
215#
216# Specifies the height of the scrolled text as an entire unit.
217# The value may be specified in any of the forms acceptable to
218# Tk_GetPixels.  Any additional space needed to display the other
219# components such as labels, margins, and scrollbars force the text
220# to be compressed.  A value of zero along with the same value for
221# the width causes the value given for the visibleitems option
222# to be applied which administers geometry constraints in a different
223# manner.
224# ------------------------------------------------------------------
225itcl::configbody iwidgets::Scrolledtext::height {
226    if {$itk_option(-height) != 0} {
227	set shell [lindex [grid info $itk_component(clipper)] 1]
228
229	#
230	# Due to a bug in the tk4.2 grid, we have to check the
231	# propagation before setting it.  Setting it to the same
232	# value it already is will cause it to toggle.
233	#
234	if {[grid propagate $shell]} {
235	    grid propagate $shell no
236	}
237
238	$itk_component(text) configure -height 1
239	$shell configure \
240		-height [winfo pixels $shell $itk_option(-height)]
241    } else {
242	configure -visibleitems $itk_option(-visibleitems)
243    }
244}
245
246# ------------------------------------------------------------------
247# OPTION: -visibleitems
248#
249# Specified the widthxheight in characters and lines for the text.
250# This option is only administered if the width and height options
251# are both set to zero, otherwise they take precedence.  With the
252# visibleitems option engaged, geometry constraints are maintained
253# only on the text.  The size of the other components such as
254# labels, margins, and scroll bars, are additive and independent,
255# effecting the overall size of the scrolled text.  In contrast,
256# should the width and height options have non zero values, they
257# are applied to the scrolled text as a whole.  The text is
258# compressed or expanded to maintain the geometry constraints.
259# ------------------------------------------------------------------
260itcl::configbody iwidgets::Scrolledtext::visibleitems {
261    if {[regexp {^[0-9]+x[0-9]+$} $itk_option(-visibleitems)]} {
262	if {($itk_option(-width) == 0) && \
263		($itk_option(-height) == 0)} {
264	    set chars [lindex [split $itk_option(-visibleitems) x] 0]
265	    set lines [lindex [split $itk_option(-visibleitems) x] 1]
266
267	    set shell [lindex [grid info $itk_component(clipper)] 1]
268
269	    #
270	    # Due to a bug in the tk4.2 grid, we have to check the
271	    # propagation before setting it.  Setting it to the same
272	    # value it already is will cause it to toggle.
273	    #
274	    if {! [grid propagate $shell]} {
275		grid propagate $shell yes
276	    }
277
278	    $itk_component(text) configure -width $chars -height $lines
279	}
280
281    } else {
282	error "bad visibleitems option\
283		\"$itk_option(-visibleitems)\": should be\
284		widthxheight"
285    }
286}
287
288# ------------------------------------------------------------------
289#                            METHODS
290# ------------------------------------------------------------------
291
292# ------------------------------------------------------------------
293# METHOD: childsite
294#
295# Returns the path name of the child site widget.
296# ------------------------------------------------------------------
297itcl::body iwidgets::Scrolledtext::childsite {} {
298    return $itk_component(text)
299}
300
301# ------------------------------------------------------------------
302# METHOD: bbox index
303#
304# Returns four element list describing the bounding box for the list
305# item at index
306# ------------------------------------------------------------------
307itcl::body iwidgets::Scrolledtext::bbox {index} {
308    return [$itk_component(text) bbox $index]
309}
310
311# ------------------------------------------------------------------
312# METHOD clear
313#
314# Clear the text area.
315# ------------------------------------------------------------------
316itcl::body iwidgets::Scrolledtext::clear {} {
317    $itk_component(text) delete 1.0 end
318}
319
320# ------------------------------------------------------------------
321# METHOD import filename
322#
323# Load text from an existing file (import filename)
324# ------------------------------------------------------------------
325itcl::body iwidgets::Scrolledtext::import {filename {index end}} {
326    set f [open $filename r]
327    insert $index [read $f]
328    close $f
329}
330
331# ------------------------------------------------------------------
332# METHOD export filename
333#
334# write text to a file (export filename)
335# ------------------------------------------------------------------
336itcl::body iwidgets::Scrolledtext::export {filename} {
337    set f [open $filename w]
338
339    set txt [$itk_component(text) get 1.0 end]
340    puts $f $txt
341
342    flush $f
343    close $f
344}
345
346# ------------------------------------------------------------------
347# METHOD compare index1 op index2
348#
349# Compare indices according to relational operator.
350# ------------------------------------------------------------------
351itcl::body iwidgets::Scrolledtext::compare {index1 op index2} {
352    return [$itk_component(text) compare $index1 $op $index2]
353}
354
355# ------------------------------------------------------------------
356# METHOD debug ?boolean?
357#
358# Activates consistency checks in B-tree code associated with text
359# widgets.
360# ------------------------------------------------------------------
361itcl::body iwidgets::Scrolledtext::debug {args} {
362    eval $itk_component(text) debug $args
363}
364
365# ------------------------------------------------------------------
366# METHOD delete first ?last?
367#
368# Delete a range of characters from the text.
369# ------------------------------------------------------------------
370itcl::body iwidgets::Scrolledtext::delete {first {last {}}} {
371    $itk_component(text) delete $first $last
372}
373
374# ------------------------------------------------------------------
375# METHOD dlineinfo index
376#
377# Returns a five element list describing the area occupied by the
378# display line containing index.
379# ------------------------------------------------------------------
380itcl::body iwidgets::Scrolledtext::dlineinfo {index} {
381    return [$itk_component(text) dlineinfo $index]
382}
383
384# ------------------------------------------------------------------
385# METHOD get index1 ?index2?
386#
387# Return text from start index to end index.
388# ------------------------------------------------------------------
389itcl::body iwidgets::Scrolledtext::get {index1 {index2 {}}} {
390    return [$itk_component(text) get $index1 $index2]
391}
392
393# ------------------------------------------------------------------
394# METHOD image option ?arg arg ...?
395#
396# Manipulate images dependent on options.
397#
398# ------------------------------------------------------------------
399itcl::body iwidgets::Scrolledtext::image {option args} {
400  return [eval $itk_component(text) image $option $args]
401}
402
403
404# ------------------------------------------------------------------
405# METHOD index index
406#
407# Return position corresponding to index.
408# ------------------------------------------------------------------
409itcl::body iwidgets::Scrolledtext::index {index} {
410    return [$itk_component(text) index $index]
411}
412
413# ------------------------------------------------------------------
414# METHOD insert index chars ?tagList?
415#
416# Insert text at index.
417# ------------------------------------------------------------------
418itcl::body iwidgets::Scrolledtext::insert {args} {
419    eval $itk_component(text) insert $args
420}
421
422# ------------------------------------------------------------------
423# METHOD mark option ?arg arg ...?
424#
425# Manipulate marks dependent on options.
426# ------------------------------------------------------------------
427itcl::body iwidgets::Scrolledtext::mark {option args} {
428    return [eval $itk_component(text) mark $option $args]
429}
430
431# ------------------------------------------------------------------
432# METHOD scan option args
433#
434# Implements scanning on texts.
435# ------------------------------------------------------------------
436itcl::body iwidgets::Scrolledtext::scan {option args} {
437    eval $itk_component(text) scan $option $args
438}
439
440# ------------------------------------------------------------------
441# METHOD search ?switches? pattern index ?varName?
442#
443# Searches the text for characters matching a pattern.
444# ------------------------------------------------------------------
445itcl::body iwidgets::Scrolledtext::search {args} {
446    #-----------------------------------------------------------
447    # BUG FIX: csmith (Chad Smith: csmith@adc.com), 11/18/99
448    #-----------------------------------------------------------
449    # Need to run this command up one level on the stack since
450    # the text widget may modify one of the arguments, which is
451    # the case when -count is specified.
452    #-----------------------------------------------------------
453    return [uplevel eval $itk_component(text) search $args]
454}
455
456# ------------------------------------------------------------------
457# METHOD see index
458#
459# Adjusts the view in the window so the character at index is
460# visible.
461# ------------------------------------------------------------------
462itcl::body iwidgets::Scrolledtext::see {index} {
463    $itk_component(text) see $index
464}
465
466# ------------------------------------------------------------------
467# METHOD tag option ?arg arg ...?
468#
469# Manipulate tags dependent on options.
470# ------------------------------------------------------------------
471itcl::body iwidgets::Scrolledtext::tag {option args} {
472    return [eval $itk_component(text) tag $option $args]
473}
474
475# ------------------------------------------------------------------
476# METHOD window option ?arg arg ...?
477#
478# Manipulate embedded windows.
479# ------------------------------------------------------------------
480itcl::body iwidgets::Scrolledtext::window {option args} {
481    return [eval $itk_component(text) window $option $args]
482}
483
484# ------------------------------------------------------------------
485# METHOD xview
486#
487# Changes x view in widget's window.
488# ------------------------------------------------------------------
489itcl::body iwidgets::Scrolledtext::xview {args} {
490    return [eval $itk_component(text) xview $args]
491}
492
493# ------------------------------------------------------------------
494# METHOD yview
495#
496# Changes y view in widget's window.
497# ------------------------------------------------------------------
498itcl::body iwidgets::Scrolledtext::yview {args} {
499    return [eval $itk_component(text) yview $args]
500}
501
502