ulis, 2003-06-23 A text widget can be serialized by saving its state in a string that can be used to restore later the state of the widget.
A serialized widget can be cloned or made persistent.
Note that in 8.5 an alternative is to use the text widget peer functionality to permit two text widgets to share a single underlying data tree (assuming you are serializing to clone rather than to some storage). peer is much more efficient than clone.
marcDouglas, 2020-05-28 As this is not mine, I will not remove the lower, but I feel this is a full replacement for the text:save.
proc text:save {w} { return [$w dump -all 1.0 end] }
Upon restoring, I found if the window name didn't match the saved name restoration would fail. The insert cursor would also move...
This works so far..
method text:restore {w save} \ { # create items, restoring their attributes foreach {key value index} $save \ { switch $key \ { exec { eval [string replace $value 0 [string first " " $value]-1 $w] } image { $w image create $index -name $value } text { $w insert $index $value } mark { switch $value { current { set currentIndex $index } insert { set insertIndex $index} default { $w mark set $value $index } } } tagon { set tag($value) $index } tagoff { $w tag add $value $tag($value) $index } window { $w window create $index -window $value } } } $w mark set current $currentIndex $w mark set insert $insertIndex }
if I want an exact match.. I had to delete the last line (could not find out how it was added) after the I focused away from it and then back.
focus $w.text focus $w.titleFrame.anotherWidget focus $w.text $w.text delete end-1lines end
I hope that fixes everything for a perfect serialization restore.
The procs (clone, save, restore, dump)
# ============================== # # clone a text widget # # ============================== # ---------- # text:clone proc # ---------- # parm1: text widget # parm2: clone text widget # ---------- proc text:clone {text clone} { text:restore $clone [text:save $text] } # ---------- # text:save proc # # serialize a text widget # ---------- # parm1: text widget path # ---------- # return: serialized widget # ---------- proc text:save {w} \ { # the resulting string set save {} # get the state of the widget set dump [$w dump -mark 1.0 end] append dump " " append dump [$w dump -all 1.0 {end -1 ch}] # add more details foreach {key value index} $dump \ { switch $key \ { image \ { # add attributes of an image set exec "\$w image create $index" foreach k {-align -image -name -padx -pady} \ { set v [$w image cget $index $k] if {$v != ""} { append exec " $k \{$v\}" } } lappend save exec $exec {} } mark \ { # add attributes of a mark lappend save $key $value $index set exec "$w mark gravity $value [$w mark gravity $value]" lappend save exec $exec {} } tagoff \ { # add attributes of a tag set exec "\$w tag configure $value" set keys {} lappend keys -background -bgstipple -borderwidth -elide -fgstipple lappend keys -font -foreground -justify -lmargin1 -lmargin2 -offset lappend keys -overstrike -relief -rmargin -spacing1 -spacing2 lappend keys -spacing3 -tabs -underline -wrap foreach k $keys \ { set v [$w tag cget $value $k] if {$v != ""} { append exec " $k \{$v\}" } } lappend save exec $exec {} lappend save $key $value $index } window \ { # add attributes of a window lappend save $key $value $index set exec "$w window configure $index" foreach k {-align -create -padx -pady -stretch} \ { set v [$w window cget $index $k] if {$v != ""} { append exec " $k \{$v\}" } } lappend save exec $exec {} } default \ { lappend save $key $value $index } } } # return the serialized widget return $save } # ---------- # text:restore proc # # restore a serialized text widget # ---------- # parm1: text widget path # parm2: serialized widget to restore # ---------- proc text:restore {w save} \ { # empty the text widget $w delete 1.0 end # create items, restoring their attributes foreach {key value index} $save \ { switch $key \ { exec { eval $value } image { $w image create $index -name $value } text { $w insert $index $value } mark \ { if {$value == "current"} { set current $index } $w mark set $value $index } tagon { set tag($value) $index } tagoff { $w tag add $value $tag($value) $index } window { $w window create $index -window $value } } } # restore the "current" index $w mark set current $current } # ---------- # text:dump proc # # display the content of a text widget # ---------- # parm1: text widget path # ---------- proc text:dump {w} \ { puts "$w:" foreach {key value index} [$w dump -all 1.0 end] \ { puts "\t$key\t\"$index\"\t\"$value\"" } puts "----" }
The demo
# ========= # demo # ========= # show debug info catch { console show } # create widgets pack [text .text -width 30 -height 10] pack [button .b -text clone -command {text:clone .text .clone}] -pady 10 pack [text .clone -width 30 -height 10] # fill text widget .text insert end text1\n .text insert end text2\n .text tag configure blue -foreground blue .text tag add blue 2.0 3.0 .text insert end text3\n update # clone the text widget after 1000 text:clone .text .clone # add an image to the text widget after 1000 image create photo img img put \ { {#bdbdbd #949494 #7b7b7b #848484 #a5a5a5 #bdbdbd} {#9c9c9c #848484 #8c8c8c #949494 #9c9c9c #adadad} {#949494 #949494 #9c9c9c #a5a5a5 #adadad #adadad} {#a5a5a5 #adadad #adadad #b5b5b5 #b5b5b5 #bdbdbd} {#bdbdbd #bdbdbd #bdbdbd #c6c6c6 #c6c6c6 #bdbdbd} {#bdbdbd #c6c6c6 #c6c6c6 #cecece #c6c6c6 #bdbdbd} } .text image create 1.2 -image img update # clone the text widget after 1000 text:clone .text .clone # add a window to the text widget, and dump it after 1000 .text window create 2.0 -window [entry .e] text:dump .text update # clone the text widget, and dump it after 1000 text:clone .text .clone text:dump .clone
I omitted here to clone the embedded widgets...
See also
which deals with data and tags.
So this page contains a partial example of serializing. Perhaps someone could take the work by these two individuals, and turn it into a general facility which could take any text widget and serialize it?