-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgeneric.tcl
2138 lines (1984 loc) · 70.5 KB
/
generic.tcl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
## generic.tcl
##
# Class Class_with_getvar
# This class is meant to be used as a superclass. It adds method "getvar"
# to its subclasses which allows to retrieve the value of any of the
# object's instance variables.
#
# Instance variables: none
#
# Constructor arguments: none
##
oo::class create Class_with_getvar {
constructor {} {
return
}
destructor {
return
}
}
##
# Class_with_getvar getvar
#
# arguments:
# varName: the name of the instance variable the value of which
# has to be retrieved.
#
# returns: the value of instance variable with name 'varName'
##
oo::define Class_with_getvar {
method getvar {varName} {
my variable $varName
set value [subst $[subst $varName]]
# eval "set value \$$varName"
return $value
}
}
##
# A GenDialog object displays a toplevel window containing a message
# and a number of buttons. The "wait" method waits for the user to press
# one of the buttons and returns the label of the pressed button.
#
# A GenDialog object is created as follows:
#
# GenDialog new ?option? .... ?option?
# where option is any of the following
# -parent $parent: the toplevel parent window
# -title $title: the title to give to the toplevel window that is created
# -message $message: the text to display on the window. This is the translated
# text.
# -msgWidth $msgWidth: the width in pixels of the message
# -defaultButton $defaultButton: the untranslated label of the default button, i.e.
# the button that initially gets the focus
# -buttonList $buttonList: the list of untranslated labels for the buttons that
# will be displayed.
#
# These objects can be in 1 of 3 modes: normal, wait, callback.
# 1. normal mode: after creating the object it is in 'normal' mode. The
# object will be destroyed when the object's window is destroyed.
# 2. wait mode: After creating the object, call the object's wait method.
# This method does not return before the dialog window is destroyed.
# It returns the result. The object is destroyed after returning from
# the wait method.
# 3. callback mode: After creating the object call method defineCallBack.
# It defines a script that will be executed when the window is
# destroyed. This script MUST either call the getResult method,
# which in turn destroys the object, or destroy the object.
##
oo::class create GenDialog {
superclass Class_with_getvar
variable window buttonPressed mode callback
constructor {args} {
# default values for options
set parent {.}
set title "GenDialog"
set message "No message defined"
set msgWidth 200
set defaultButton btnOK
set buttonList btnOK
# set options from args
dict for {option value} $args {
if {$option in {-parent -title -message -msgWidth -defaultButton -buttonList}} then {
set [string range $option 1 end] $value
} else {
puts "GenDialog: '$option' unknown option"
}
}
set mode "normal"
set callback {}
set window [toplevel \
[appendToPath $parent [namespace tail [string tolower [self namespace]]]]]
set buttonPressed {}
wm title $window $title
wm transient $window $parent
set x [expr [winfo rootx $parent] + 100]
set y [expr [winfo rooty $parent] + 50]
wm geometry $window "+${x}+${y}"
set msg [message ${window}.msg \
-width $msgWidth \
-justify left \
-text $message]
set frm [ttk::frame ${window}.frm]
set row 0
foreach btnLabel $buttonList {
set btn [defineButton $frm.$btnLabel $window $btnLabel \
[list [self object] onButton $btnLabel]]
grid $btn -row 0 -column $row
incr row
}
pack $msg -side top -expand 1 -fill both -padx {10 10} -pady {10 10}
pack $frm -side top -pady {0 10}
if {$defaultButton in $buttonList} then {
focus $frm.$defaultButton
}
bindToplevelOnly $window <Destroy> [list [self object] onDestroy]
bind $window <KeyPress-Escape> [list destroy $window]
}
destructor {
return
}
}
##
# method onDestroy
# This method is an event procedure that is meant to be bound to
# the destroy event of the toplevel window. If the method 'wait' was
# not previously called, it destroys the object.
#
# arguments: none
##
oo::define GenDialog {
method onDestroy {} {
if {$mode eq "normal"} then {
# neither wait, nor defineCallBack was called. Just destroy object.
after idle [list [self object] destroy]
} elseif {$mode eq "callback"} then {
eval $callback
# It is up to the object's creator to destroy the object
# e.g. by calling getResult
} else {
# wait mode: don't do anything. The wait method was called
# which will destroy the object.
}
return
}
}
##
# method onButton
# This method is an event procedure that is meant to be called when
# one of the dialogue buttons is pressed. It registers which button
# has been pressed and then destroys the window, but not the object.
#
# arguments:
# - btnLabel: the text that will be returned to the user of the object
# by the wait method.
##
oo::define GenDialog {
method onButton {btnLabel} {
set buttonPressed $btnLabel
destroy $window
return
}
}
##
# method wait
# This method lets the calling procedure wait until the user has
# pressed one of the dialogue's buttons or until the window is
# destroyed. It returns the label of the button that was pressed, or
# the empty string. The object is automatically destroyed after returning
# from wait.
##
oo::define GenDialog {
method wait {} {
set mode "wait"
tkwait window $window
after idle [list [self object] destroy]
return $buttonPressed
}
}
##
# GenDialog defineCallBack $script
# This method sets $script as call back script to be called when the
# toplevel window is destroyed. It sets the GenDialog object in
# callback mode.
# arguments:
# - script: this script should call the getResult method to
# to get the result from the dialogue.
##
oo::define GenDialog {
method defineCallBack {script} {
set callback $script
set mode "callback"
return
}
}
##
# method getResult
# This method should be called from the callback script that was defined
# by method defineCallBack. It returns the label of the button that was pressed, or
# the empty string. The object is automatically destroyed after returning
# from getResult.
##
oo::define GenDialog {
method getResult {} {
after idle [list [self object] destroy]
return $buttonPressed
}
}
##
# Class GenForm
#
# A GenForm object displays a toplevel window which enables the user to
# see and modify a number of data.
#
# A GenForm object is created as follows:
#
# GenForm new $parent $title $dataList
#
# where: $parent: is the parent's window path
#
# $title: title for window
#
# $dataList is a list containing an item for each data item
# that is displayed on the window, and where each item
# is a dict with the folling keys:
# -name: data item's name which must be unique
# within this dialog
# -type: the data item's type, which must be one of
# string, bool, password
# -value: the data item's initial value
# -valuelist: a list of allowed values. If this
# list is not empty, a combox is used, else
# a normal text entry is used.
#
# These objects can be in 1 of 3 modes: normal, wait, callback
#
# 1. normal mode: after creating the object it is in 'normal' mode.
# 2. wait mode: After creating the object, call the object's wait method.
# This method does not return before the form window is destroyed.
# It returns the result. The object is destroyed after returning from
# the wait method.
# 3. callback mode: After creating the object call method defineCallBack.
# It defines a script that will be executed when the window is
# destroyed. This script MUST either call the getResult method,
# which in turn destroys the object, or destroy the object.
##
oo::class create GenForm {
superclass Class_with_getvar
variable data window pressedOK frm1 callback mode
constructor {parent title dataList} {
set pressedOK 0
set mode "normal"
set callback {}
set window [toplevel \
[appendToPath $parent [namespace tail [string tolower [self namespace]]]]]
wm transient $window $parent
set x [expr [winfo rootx $parent] + 100]
set y [expr [winfo rooty $parent] + 50]
wm geometry $window "+${x}+${y}"
wm title $window $title
set frm1 [ttk::frame ${window}.frm1]
set entrywidth 40
set idx 0
foreach item $dataList {
set name [dict get $item name]
set type [dict get $item type]
set value [dict get $item value]
set valuelist [dict get $item valuelist]
set data($name) $value
set label [ttk::label $frm1.lb$idx -text $name \
-compound right -image ::img::empty_5_9]
set varName [my varname data($name)]
if {$type eq "bool"} then {
set control [ttk::checkbutton $frm1.cont$idx \
-variable $varName \
-onvalue 1 -offvalue 0]
set sticky w
set focusWidget $control
} elseif {$type eq "password"} then {
set control [entry $frm1.cont$idx \
-textvariable $varName -width $entrywidth \
-show "*"]
set sticky we
set focusWidget $control
} elseif {($type eq "filename") || ([llength $valuelist] > 0)} then {
set varName [my varname data($name)]
if {$type eq "filename"} then {
set filetypes [dict get $item filetypes]
set cmd [list [self object] onSelectFile $varName $filetypes]
} else {
set cmd [list [self object] onSelectValue $varName $name $valuelist]
}
set control [ttk::frame $frm1.cont$idx -takefocus 0]
set entry [entry $control.file$idx -textvariable $varName \
-width $entrywidth]
$entry configure -state {readonly}
set btn [ttk::button $control.sel$idx \
-image ::img::arrow_down \
-takefocus 0 \
-command $cmd]
bind $entry <Alt-KeyPress-s> [list $btn invoke]
bind $entry <KeyPress-Down> [list $btn invoke]
pack $entry -side left -expand 1 -fill x
pack $btn -side left -fill both
set sticky we
set focusWidget $entry
} else {
set control [entry $frm1.cont$idx -width $entrywidth \
-textvariable [my varname data($name)]]
set sticky we
set focusWidget $control
}
bind $focusWidget <FocusIn> \
[list $label configure -compound right -image ::img::arrow_right]
bind $focusWidget <FocusOut> \
[list $label configure -compound right -image ::img::empty_5_9]
if {$idx == 0} then {
focus $focusWidget
}
grid $label -column 0 -row $idx -sticky $sticky
grid $control -column 1 -row $idx -sticky $sticky
incr idx
}
grid columnconfigure $frm1 1 -weight 1
pack $frm1 -side top -padx {10 10} -pady {10 10} -fill x
set frm2 [ttk::frame ${window}.frm2]
set btnOK [defineButton $frm2.ok $window btnOK [list [self object] onOK]]
set btnCancel [defineButton $frm2.cancel $window btnCancel \
[list [self object] onCancel]]
pack $btnCancel -side right
pack $btnOK -side right
pack $frm2 -side top -fill x -padx {10 10} -pady {0 10}
bindToplevelOnly $window <Destroy> [list [self object] onDestroy]
bind $window <KeyPress-Escape> [list destroy $window]
# bind $window <KeyPress-Down> {focus [tk_focusNext [focus]]}
# bind $window <KeyPress-Up> {focus [tk_focusPrev [focus]]}
bind $window <KeyPress-Return> [list [self object] onOK]
}
destructor {
}
}
##
# method onDestroy
# This method is an event procedure which is meant to be bound
# to the destroy event of the toplevel window. It destroys the
# object if the 'wait' method was not previously called.
##
oo::define GenForm {
method onDestroy {} {
if {$mode eq "normal"} then {
after idle [list [self object] destroy]
} elseif {$mode eq "callback"} then {
eval $callback
# object should be destroyed by callback by calling getResult
} else {
# mode eq wait: do nothing. Object is destroyed by wait method
}
return
}
}
##
# method wait $resultVar
# This method is called to wait for the result of the user input.
#
# arguments:
# - resultVar: the name of the result array which will contain the
# user input after returning from the wait method.
#
# returns: a boolean which indicates whether or not the OK button
# was pressed.
##
oo::define GenForm {
method wait {resultVar} {
upvar $resultVar result
set mode "wait"
tkwait window $window
array set result [array get data]
after idle [list [self object] destroy]
return $pressedOK
}
}
##
# method getResult $resultVar
# This method is called to get the result. After calling this method
# the GenForm object is destroyed. It should be called by the script
# defined as 'callback' script with the defineCallBack method.
#
# arguments:
# - resultVar: the name of the result array which will contain the
# user input after returning from the wait method.
#
# returns: a boolean which indicates whether or not the OK button
# was pressed.
##
oo::define GenForm {
method getResult {resultVar} {
upvar $resultVar result
array set result [array get data]
after idle [list [self object] destroy]
return $pressedOK
}
}
##
# method onOK
# This method is an event procedure which is meant to be called
# when the user has pressed the OK button. It registers that the
# user has pressed OK and destroys the window.
#
# arguments: none
##
oo::define GenForm {
method onOK {} {
set pressedOK 1
destroy $window
return
}
}
##
# method onCancel
# This method is an event procedure which is meant to be called
# when the user has pressed the Cancel button. It registers that
# the user has pressed Cancel and destroys the window.
#
# arguments: none
##
oo::define GenForm {
method onCancel {} {
set pressedOK 0
destroy $window
return
}
}
##
# method displayHelpText
# This method can be used to display a help text for the user
# at the top of the window.
#
# arguments:
# - helpText: the text to be displayed.
##
oo::define GenForm {
method displayHelpText {helpText} {
set lbHelp [ttk::label ${window}.lbHelp -text $helpText \
-padding {10 10 10 10}]
pack $lbHelp -side top -before $frm1
return
}
}
##
# GenForm defineCallBack $callBackScript
# This method sets $callBackScript as script to be called when the
# toplevel window is destroyed. It sets the GenForm object in
# callback mode.
# arguments:
# - callBackScript: this script should call the getResult method to
# to get the result from the form.
##
oo::define GenForm {
method defineCallBack {callBackScript} {
set mode "callback"
set callback $callBackScript
return
}
}
oo::define GenForm {
method onSelectFile {filenameName filetypes} {
upvar $filenameName filename
if {[string length $filename]} then {
set fullpath [file normalize $filename]
set directory [file dirname $fullpath]
set tailname [file tail $fullpath]
} else {
set directory [tkpOptions getOption fileselection lastdir]
set tailname {}
}
set fs [FileSelection new -parent $window -directory $directory \
-filename $tailname -filetypes $filetypes]
set newfile [$fs wait]
if {$newfile ne {}} then {
set filename $newfile
}
return
}
}
oo::define GenForm {
method onSelectValue {dataName name valuelist} {
upvar $dataName data
set selected [lsearch -exact $valuelist $data]
if {$selected < 0} then {
set selected 0
}
set lsb [ListBox new $window [mc miscChoose $name] $name \
$valuelist $selected]
if {[$lsb wait result]} then {
set data $result
}
return
}
}
##
# A TextEdit object displays a window in which the user can see
# and possibly edit a text. To create a TextEdit object use:
#
# TextEdit new $parent $title $initialText $readOnly
#
# where: - $parent is the widget pathname of the parent window
# - $title is the window title
# - $initialText: is the text that will be displayed initially
# - $readOnly: 0 or 1, indicating whether the user is allowed
# to edit the text.
#
# After creating the object, there are 3 possible modes of use.
#
# 1. Normal mode: In this mode, the initial text is displayed, but
# it is not possible to get any result. You don't
# have to worry about deleting the object. It is
# deleted automatically when the user presses OK or
# Cancel, or when he destroys the window. This mode
# is only usefull for readOnly text.
#
# 2. Wait mode: In this mode, after creating the object, you call
# the object's "wait" method. This method does not
# return before the user has pressed OK or Cancel, or
# has destroyed the window. The wait method should be
# called as follows:
#
# textEditObject wait textVarName
#
# It returns 1 or 0 edpending on whether OK or Cancel
# was pressed, and it stores the result in the variable
# with the name textVarName. You don't have to worry
# about deleting the object. It is automatically deleted
# after returning from the wait method.
#
# 3. CallBack mode: In this mode, after creating the object, you call
# the object's "defineCallBack" method. This method is
# called as follows:
#
# textEditObject defineCallBack callBackScript
#
# This callBackScript must call the object's getText
# method as follows:
#
# textEditObject getText textVarName
#
# It returns 1 or 0 depending on whether OK or Cancel
# was pressed, and it stores the result in the variable
# with the name textVarName. After returning from this
# method, the textEditObject no longer exists. So, you
# can call this method only once.
#
# You can also add custom menus to the this widget using the method
# addMenuItem
#
# textEditObject addMenuItem $btnLabel $type $arg
#
# where $type is either command or cascade
#
# $arg is then either a script to be called when the menuitem is invoked,
# or the name of a menu in case of cascade.
#
# In case of command, you can use %T to represent the text widget's pathname.
#
# If you want to destroy the object, do not call object destroy, but
# call the destroyWindow method instead.
#
# Instance variables:
# - window: the Tk path of the toplevel window associated with
# the TextEdit object
# - menubar: the Tk path of the menubar on the TextEdit window
# - readOnly: boolean indicating whether this TextEdit is readonly
# - txtWidget: Tk path of the text widget
# - actualText: variable that is set to the text in the text widget
# after the user has pressed OK.
# - wrap: boolean that is bound to the 'Wrap' checkbutton. When true
# the text widget's word wrap is switched on. When false, lines
# are not wrapped at the widget boundery.
# - btnFrame: the Tk path of the frame containing the buttons.
# - entSearch: the Tk path of the entry for entering the search pattern.
# - pressedOK: boolean: 1 user has pressed OK, 0 user has not pressed OK
# - mode: one of {normal wait callback}
# - callback: the callback script as defined by the user in the
# defineCallBack method.
##
oo::class create TextEdit {
superclass Class_with_getvar
variable window menubar readOnly txtWidget actualText wrap btnFrame \
entSearch pressedOK mode callback
constructor {parent title initialText c_readOnly} {
set actualText {}
set wrap "none"
set mode "normal"
set callback {}
set pressedOK 0
set readOnly $c_readOnly
my setupWindow $parent $title $initialText
}
destructor {
}
}
##
# TextEdit setupWindow $parent $title $initialText
# This method sets up the TextEdit window and its widgets.
# arguments:
# - parent: Tk path of the parent window
# - title: window title
# - initialText: the text that is displayed initially.
##
oo::define TextEdit {
method setupWindow {parent title initialText} {
set window [toplevel [appendToPath $parent [namespace tail [string tolower [self namespace]]]]]
wm title $window $title
wm geometry $window [join [geometry::getSize text] {x}]
set menubar [my setupMenus]
$window configure -menu $menubar
set txtWidget [text $window.txt -width 1 -height 1 -wrap $wrap]
$txtWidget tag configure blue -foreground {medium blue}
$txtWidget tag configure red -foreground {red4}
$txtWidget tag configure green -foreground {green4}
if {$readOnly} then {
$txtWidget configure -background $::readonlyBackground
}
set vsb [ttk::scrollbar $window.vsb -orient vertical \
-command [list $txtWidget yview]]
set hsb [ttk::scrollbar $window.hsb -orient horizontal \
-command [list $txtWidget xview]]
$txtWidget configure \
-yscrollcommand [list $vsb set] \
-xscrollcommand [list $hsb set]
$txtWidget insert end $initialText
$txtWidget mark set insert 1.0
$txtWidget yview 0
set btnFrame [ttk::frame $window.btnFrame]
if {!$readOnly} then {
set btnOK [defineButton $btnFrame.btnOK $window btnOK \
[list [self object] onOK]]
} else {
set lbReadOnly [ttk::label $btnFrame.rdonly \
-text [mc lbReadOnly] -foreground {medium blue}]
$txtWidget configure -state disabled
}
set btnCancel [defineButton $btnFrame.btnCancel $window btnCancel \
[list [self object] onCancel]]
set btnWrap [defineCheckbutton $btnFrame.btnWrap $window btnWrap \
[list [self object] onWrap] [my varname wrap] word none]
set searchFrm [ttk::frame $btnFrame.search]
set btnSearch [defineButton $searchFrm.btn $window btnSearch \
[list [self object] onSearch]]
set entSearch [entry $searchFrm.ent]
bind $entSearch <KeyPress-Return> [list [self object] onSearch]
pack $btnSearch -side right
pack $entSearch -side right -expand 1 -fill both
grid $txtWidget -column 0 -row 1 -sticky wens
grid $vsb -column 1 -row 1 -sticky ns
grid $hsb -column 0 -row 2 -sticky we
grid $btnFrame -column 0 -columnspan 2 -row 3 -sticky we \
-pady {10 10} -padx {10 10}
grid [ttk::sizegrip ${window}.sg] -column 0 -columnspan 2 \
-row 4 -sticky e
grid columnconfigure $window 0 -weight 1
grid rowconfigure $window 1 -weight 1
pack $btnCancel -side right
if {!$readOnly} then {
pack $btnOK -side right
} else {
pack $lbReadOnly -side right
}
pack $searchFrm -side right -expand 1 -fill x
pack $btnWrap -side right
set tpOnly [bindToplevelOnly $window <Destroy> [list [self object] onDestroy]]
bind $tpOnly <Configure> {geometry::setSize text {%w %h}}
bind $window <KeyPress-Escape> [list destroy $window]
focus $txtWidget
return
}
}
##
# TextEdit setupMenus
# This method defines the TextEdit menus
##
oo::define TextEdit {
method setupMenus {} {
set menu [menu ${window}.menubar -tearoff 0]
set mnuText [menu ${menu}.text -tearoff 0]
#::addMenuItem $mnuText mnuTxtSave command [list [self object] onSave]
#::addMenuItem $mnuText mnuTxtPrint command [list [self object] onPrint]
::addMenuItem $mnuText mnuTxtClose command [list destroy $window]
$mnuText entryconfigure 0 -accelerator {Esc}
::addMenuItem $menu mnuText cascade $mnuText
return $menu
}
}
##
# TextEdit onDestroy
# This method is an event procedure which is meant to be called
# when the window is destroyed.
##
oo::define TextEdit {
method onDestroy {} {
switch $mode {
normal {
after idle [list [self object] destroy]
}
callback {
eval $callback
# It is up to the creator of the object to destroy it
# e.g. by calling method getText or destroy
}
default {
# wait was called, which will destroy the object.
}
}
return
}
}
##
# TextEdit onPrint
# This method is called when the user activates the Print menu.
# It calls the printTextWidget procedure
##
#oo::define TextEdit {
#method onPrint {} {
#printTextWidget $txtWidget $window
#return
#}
#}
##
# TextEdit onSave
# This method is called when the user activates the Save menu.
##
#oo::define TextEdit {
#method onSave {} {
#saveTxtFromWidget $txtWidget $window
#return
#}
#}
##
# TextEdit onWrap
# This method is called when the user clicks the 'Wrap' checkbutton.
##
oo::define TextEdit {
method onWrap {} {
$txtWidget configure -wrap $wrap
return
}
}
oo::define TextEdit {
method setWrap {value} {
set wrap $value
my onWrap
return
}
}
##
# TextEdir renderBold
# This method looks for the <b> ... </b> tags and renders the text
# between them as bold.
oo::define TextEdit {
method renderBold {} {
$txtWidget configure -state normal
$txtWidget tag delete bold
set first "1.0"
while {1} {
set first [$txtWidget search {<b>} $first]
if {$first ne {}} then {
$txtWidget delete $first "${first} + 3 chars"
set last [$txtWidget search {</b>} $first]
if {$last ne {}} then {
$txtWidget delete $last "${last} + 4 chars"
$txtWidget tag add bold $first $last
set first $last
} else {
chan puts stderr "TextEdit renderBold: </b> missing"
break
}
} else {
break
}
}
$txtWidget tag configure bold -font {-weight bold}
if {$readOnly} then {
$txtWidget configure -state disabled
}
return
}
}
##
# TextEdit gotoBegin
# This method can be called to set the cursor to begin of the text.
##
oo::define TextEdit {
method gotoBegin {} {
$txtWidget mark set insert 1.0
$txtWidget yview 0
return
}
}
##
# TextEdit onSearch
# This method is ab event procedure that is meant to be called
# when the user presses the Search button.
##
oo::define TextEdit {
method onSearch {} {
focus $entSearch
set pattern [$entSearch get]
if {[string length $pattern]} then {
set searchPosition [$txtWidget index insert]
$txtWidget tag delete match
set searchPosition [$txtWidget search -nocase \
$pattern $searchPosition end]
if {$searchPosition ne {}} then {
set endmatch [$txtWidget index \
"$searchPosition +[string length $pattern] chars"]
$txtWidget tag add match $searchPosition $endmatch
$txtWidget tag configure match -background yellow
$txtWidget mark set insert $endmatch
$txtWidget see insert
} else {
tkp_message [mc searchEOT] $window
$txtWidget mark set insert 1.0
$txtWidget see insert
}
}
return
}
}
##
# TextEdit onOK
# This method is an event procedure that is called when the user
# presses OK. It copies the text from the text widget in the
# 'actualText' instance variable and destroys the toplevel window.
##
oo::define TextEdit {
method onOK {} {
set pressedOK 1
set actualText [$txtWidget get 1.0 "end - 1 chars"]
destroy $window
return
}
}
##
# TextEdit onCancel
# This method is an event procedure that is called when the user
# pressed Cancel. It destroys the toplevel window.
##
oo::define TextEdit {
method onCancel {} {
set pressedOK 0
set actualText {}
destroy $window
return
}
}
##
# TextEdit addMenuItem $itemLabel $itemType $argument
# This method can be called to add a menu item to the TextEdit window.
# arguments:
# - itemLabel: the text for the label of the menu item
# - itemType: one of {command cascade}
# - argument:
# - if $itemType == 'command':
# A script to be called when the item is activated. In this
# script '%T' can be used to represent the text widget's
# Tk path.
# - if $itemType == 'cascade':
# The Tk path of another menu.
##
oo::define TextEdit {
method addMenuItem {itemLabel itemType argument} {
set argument [string map [list %T $txtWidget] $argument]
::addMenuItem $menubar $itemLabel $itemType $argument
return
}
}
##
# TextEdit getText $textVar
# This method should be called in 'callback' mode. It copies the
# actualText instance variable to the variable with name $textVar.
# arguments:
# - textVar: the name of the variable that will receive the text.
# returns: 1 if the user has pressed OK, 0 if the user did not press
# OK. In the latter case the $textVar variable is not modified.
##
oo::define TextEdit {
method getText {textVar} {
upvar $textVar result
if {$pressedOK} then {
set result $actualText
}
after idle [list [self object] destroy]
return $pressedOK
}
}
##
# TextEdit setText $textVar
# This method copies the text in the variable with name $textVar
# to the TextEdit's text widget.
# arguments:
# - textvar: the name of the variable that contains the text.
##
oo::define TextEdit {
method setText {textVar} {
upvar $textVar text
if {$readOnly} then {
$txtWidget configure -state normal
}
$txtWidget delete 1.0 end
$txtWidget insert end $text
if {$readOnly} then {
$txtWidget configure -state disabled
}
return
}
}
##
# TextEdit appendText $text $colour
# This method appends $text to the TextEdit's text widget.
# arguments:
# - textvar: the name of the variable that contains the text.
# - colour: one of {red green blue black}
##