0

How can I use both the line number and the read only proxies in the same Tkinter text widget? I can get both visible, but either one or the other works. I assume the problem is in the code piece below that is identical for both:

     self.tk.eval('''
        rename {widget} _{widget}
        interp alias {{}} ::{widget} {{}} widget_proxy _{widget} 
    '''.format(widget=str(self)))

The following makes only the read-only part work, switching the order makes Custom Text work.

    class TextOfBryan(ReadOnly, CustomText):
          pass

When I copy/paste the content of both classes into one I get an error that a name ".xxxx.xxxx" already exists and connot be renamed.

Community
  • 1
  • 1
ingo
  • 117
  • 10

1 Answers1

1

You will need to combine the two widget_proxy definitions into one. It would look something like this:

self.tk.eval('''
    proc widget_proxy {actual_widget widget_command args} {

        set command [lindex $args 0]
        if {$command == "insert"} {
            set index [lindex $args 0]
            if [_is_readonly $actual_widget $index "$index+1c"] {
                bell
                return ""
            }
        }
        if {$command == "delete"} {
            foreach {index1 index2} [lrange $args 1 end] {
                if {[_is_readonly $actual_widget $index1 $index2]} {
                    bell
                    return ""
                }
            }
        }

        # call the real tk widget command with the real args
        set result [uplevel [linsert $args 0 $widget_command]]

        # generate the event for certain types of commands
        if {([lindex $args 0] in {insert replace delete}) ||
            ([lrange $args 0 2] == {mark set insert}) || 
            ([lrange $args 0 1] == {xview moveto}) ||
            ([lrange $args 0 1] == {xview scroll}) ||
            ([lrange $args 0 1] == {yview moveto}) ||
            ([lrange $args 0 1] == {yview scroll})} {

            event generate  $actual_widget <<Change>> -when tail
        }

        # return the result from the real widget command
        return $result
    }
    proc _is_readonly {widget index1 index2} {
        # return true if any text in the range between
        # index1 and index2 has the tag "readonly"
        set result false
        if {$index2 eq ""} {set index2 "$index1+1c"}
        # see if "readonly" is applied to any character in the
        # range. There's probably a more efficient way to do this, but
        # this is Good Enough
        for {set index $index1} \
            {[$widget compare $index < $index2]} \
            {set index [$widget index "$index+1c"]} {
                if {"readonly" in [$widget tag names $index]} {
                    set result true
                    break
                }
            }
        return $result
    }

    ''')
ingo
  • 117
  • 10
Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685