• Operate only on the visible lines in a text window

    From Shaun Deacon@21:1/5 to All on Tue Jul 9 17:57:17 2024
    My application uses a text widget to display chip 'test vectors' from a
    loaded file. Each vector occupies a line - for example :

    0011010XXLLLHH
    0100110XXLHHLH
    ...
    0110110XXHHHHH

    A highlighting operation colors specified values (for example all 1's)
    for all lines of text in the widget. For small and medium sized files
    this is fine. However, test files can often be large (over 500,000
    vectors). The highlight operation applied to all lines is too slow in
    this case - the vectors are much longer strings in real life too.

    The obvious solution to me is to just highlight the currently visible
    lines (or a range of lines spanning the current view - say 1000 or so)
    and when the user scrolls the window, highlight the new set of lines.

    Suggestions on the best way to find the indexes for the currently
    visible lines when the widget has been scrolled would be great.

    Can someone please point me in the right direction ?

    For some reason, I can't seem to find what I'm looking for in CLT, the
    wiki or the man pages.

    thanks
    Shaun

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From et99@21:1/5 to Shaun Deacon on Tue Jul 9 22:26:54 2024
    On 7/9/2024 5:57 PM, Shaun Deacon wrote:
    My application uses a text widget to display chip 'test vectors' from a loaded file. Each vector occupies a line - for example :

    0011010XXLLLHH
    0100110XXLHHLH
    ...
    0110110XXHHHHH

    A highlighting operation colors specified values (for example all 1's) for all lines of text in the widget. For small and medium sized files this is fine. However, test files can often be large (over 500,000 vectors). The highlight operation applied to
    all lines is too slow in this case - the vectors are much longer strings in real life too.

    The obvious solution to me is to just highlight the currently visible lines (or a range of lines spanning the current view - say 1000 or so) and when the user scrolls the window, highlight the new set of lines.

    Suggestions on the best way to find the indexes for the currently visible lines when the widget has been scrolled would be great.

    Can someone please point me in the right direction ?

    For some reason, I can't seem to find what I'm looking for in CLT, the wiki or the man pages.

    thanks
    Shaun


    Can't you use the current cursor position? How is it scrolled, mouse wheel? scroll bar? The current cursor is at,

    .textwidget index insert

    You could likely estimate it using scrollbar info. But if there are 500k lines, how might someone get to the middle, by some sort of search?

    The only way I know to find what lines in a text widget are on screen without any other info is using the bbox method. You can test if any particular $line is visible by using

    .textwidget bbox $line.0

    which will return a null list if not on screen, otherwise a list of numbers.

    This could involve a large search to find the first and last line on-screen. I don't know how fast or slow that would be. You could likely test every Nth line if you know how many lines fit on screen.

    et

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From [email protected]@21:1/5 to All on Wed Jul 10 05:41:30 2024

    Suggestions on the best way to find the indexes for the currently
    visible lines when the widget has been scrolled would be great.

    Try using the @x,y indices (see INDICES in the man page) and the text box index subcommand

    For a text box named .t

    .t index @0,0

    returns the line number and column number of the character in the top left corner.

    lindex [split [.t index @0,0] .] 0

    returns just the line number of the top left character (droping the column number)

    use winfo height .t to get the last line in the text box. perhaps using:

    lindex [split [.t index @0,[winfo height .t]] .] 0


    Dave B

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Ralf Fassel@21:1/5 to All on Wed Jul 10 10:59:00 2024
    * Shaun Deacon <[email protected]>
    | The obvious solution to me is to just highlight the currently visible
    | lines (or a range of lines spanning the current view - say 1000 or so)
    | and when the user scrolls the window, highlight the new set of lines.

    | Suggestions on the best way to find the indexes for the currently
    | visible lines when the widget has been scrolled would be great.

    | Can someone please point me in the right direction ?

    You could try 'text yview' and derive the displayed lines from that:

    grid [text .t -yscrollcommand {recalc {.s set}}] -sticky ewns -row 0 -column 0
    grid [scrollbar .s -command {recalc {.t yview}} -orient vertical] -sticky ns -row 0 -column 1
    grid [label .l] - -sticky ewns
    grid rowconfigure . 0 -weight 1
    grid columnconfigure . 0 -weight 1
    for {set l 1} {$l < 1000} {incr l} {
    .t insert end "Line $l\n"
    }

    proc recalc {cmd args} {
    # scroll if required
    if {$cmd ne ""} {
    {*}$cmd {*}$args
    }
    # Determine the visible range
    lassign [.t yview] start end
    # Get line count
    set lines [lindex [split [.t index end] "."] 0]
    # Get first and last line displayed.
    # Here you need to determine what to do with the partially displayed lines
    set first [format %.1f [expr {$start*$lines+1}]]
    set last [format %.1f [expr {$end*$lines}]]

    .l configure -text "visible Lines $first ... $last"
    }
    bind . <Configure> [list recalc ""]

    HTH
    R'

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Shaun Deacon@21:1/5 to Ralf Fassel on Wed Jul 10 10:38:03 2024
    Ralf Fassel wrote:
    * Shaun Deacon <[email protected]>
    | The obvious solution to me is to just highlight the currently visible
    | lines (or a range of lines spanning the current view - say 1000 or so)
    | and when the user scrolls the window, highlight the new set of lines.

    | Suggestions on the best way to find the indexes for the currently
    | visible lines when the widget has been scrolled would be great.

    | Can someone please point me in the right direction ?

    You could try 'text yview' and derive the displayed lines from that:

    grid [text .t -yscrollcommand {recalc {.s set}}] -sticky ewns -row 0 -column 0
    grid [scrollbar .s -command {recalc {.t yview}} -orient vertical] -sticky ns -row 0 -column 1
    grid [label .l] - -sticky ewns
    grid rowconfigure . 0 -weight 1
    grid columnconfigure . 0 -weight 1
    for {set l 1} {$l < 1000} {incr l} {
    .t insert end "Line $l\n"
    }

    proc recalc {cmd args} {
    # scroll if required
    if {$cmd ne ""} {
    {*}$cmd {*}$args
    }
    # Determine the visible range
    lassign [.t yview] start end
    # Get line count
    set lines [lindex [split [.t index end] "."] 0]
    # Get first and last line displayed.
    # Here you need to determine what to do with the partially displayed lines
    set first [format %.1f [expr {$start*$lines+1}]]
    set last [format %.1f [expr {$end*$lines}]]

    .l configure -text "visible Lines $first ... $last"
    }
    bind . <Configure> [list recalc ""]

    HTH
    R'


    Thanks Ralf, this looks promising to me.
    Shaun

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)