From: eb303 on
Hello all,

I've been trying to do a text editor showing line numbers on the left
side of a text, which can also set the initial position of the
insertion point. To do this, I pack 2 texts side by side, one for the
line numbers and one for the actual text, and configure them to scroll
together whenever one of them is scrolling. To see the initial cursor
position, I use the 'see' subcommand on the text, but it seems
something's wrong, since it doesn't seem to work.

Here is a simplified script demonstrating the problem:
-----------------
## Frame for both texts
pack [frame .texts] -side top
## Text for line numbers
text .texts.lines -width 5
pack .texts.lines -side left -fill y
## Text for actual text
text .texts.txt
pack .texts.txt -side left -fill both

## Vertical scrollbar
scrollbar .texts.vscroll -orient vertical -command { .texts.txt
yview }

## Trick to make both texts scroll together, as well as update the
scrollbar
proc scroll_text { first last } {
.texts.vscroll set $first $last
.texts.lines yview moveto $first
}
proc scroll_lines { first last } {
.texts.vscroll set $first $last
.texts.txt yview moveto $first
}
..texts.txt configure -yscrollcommand scroll_text
..texts.lines configure -yscrollcommand scroll_lines


## Fill text and line numbers with dummy lines
for { set i 1 } { $i <= 2000 } { incr i } {
.texts.lines insert end "$i\n"
.texts.txt insert end "This is line number $i\n"
}

## Procedure to center the text on a given line and set the insertion
point on it
proc center_text {} {
.texts.txt see 789.0
.texts.txt mark set insert 789.0
}

## Initial positionning <= does not work
center_text

## Button to do positionning again <= works
button .btn -text Center -command center_text
pack .btn

focus .texts.txt
-----------------

The initial call to center_text doesn't work: the insertion point is
actually moved, but the line is not centered in the text. However,
after the initial display, clicking on the 'Center' button works: the
insertion point moves, and the line is centered.

I've tried various tricks to make this work, like calls to 'update' or
'update idletasks' before calling center_text, or triggering it later
via an 'after idle', but with no result: I can't get the line to be
centered on display.

Do I do anything wrong here? Is it the trick I used to scroll both
texts at the same time that messes things up?

My tcl version is 8.5.5; I've tried this on Linux (Fedora Core 10) and
Mac OS X 10.5, and the result is the same.

Thanks.
- Eric -
From: eb303 on
On Feb 10, 4:32 pm, eb303 <eric.brunel.pragma...(a)gmail.com> wrote:
> Hello all,
>
> I've been trying to do a text editor showing line numbers on the left
> side of a text, which can also set the initial position of the
> insertion point. To do this, I pack 2 texts side by side, one for the
> line numbers and one for the actual text, and configure them to scroll
> together whenever one of them is scrolling. To see the initial cursor
> position, I use the 'see' subcommand on the text, but it seems
> something's wrong, since it doesn't seem to work.
>
> Here is a simplified script demonstrating the problem:
> -----------------
> ## Frame for both texts
> pack [frame .texts] -side top
> ## Text for line numbers
> text .texts.lines -width 5
> pack .texts.lines -side left -fill y
> ## Text for actual text
> text .texts.txt
> pack .texts.txt -side left -fill both
>
> ## Vertical scrollbar
> scrollbar .texts.vscroll -orient vertical -command { .texts.txt
> yview }
>
> ## Trick to make both texts scroll together, as well as update the
> scrollbar
> proc scroll_text { first last } {
>   .texts.vscroll set $first $last
>   .texts.lines yview moveto $first}
>
> proc scroll_lines { first last } {
>   .texts.vscroll set $first $last
>   .texts.txt yview moveto $first}
>
> .texts.txt configure -yscrollcommand scroll_text
> .texts.lines configure -yscrollcommand scroll_lines
>
> ## Fill text and line numbers with dummy lines
> for { set i 1 } { $i <= 2000 } { incr i } {
>   .texts.lines insert end "$i\n"
>   .texts.txt insert end "This is line number $i\n"
>
> }
>
> ## Procedure to center the text on a given line and set the insertion
> point on it
> proc center_text {} {
>   .texts.txt see 789.0
>   .texts.txt mark set insert 789.0
>
> }
>
> ## Initial positionning <= does not work
> center_text
>
> ## Button to do positionning again <= works
> button .btn -text Center -command center_text
> pack .btn
>
> focus .texts.txt
> -----------------
>
> The initial call to center_text doesn't work: the insertion point is
> actually moved, but the line is not centered in the text. However,
> after the initial display, clicking on the 'Center' button works: the
> insertion point moves, and the line is centered.
>
> I've tried various tricks to make this work, like calls to 'update' or
> 'update idletasks' before calling center_text, or triggering it later
> via an 'after idle', but with no result: I can't get the line to be
> centered on display.
>
> Do I do anything wrong here? Is it the trick I used to scroll both
> texts at the same time that messes things up?
>
> My tcl version is 8.5.5; I've tried this on Linux (Fedora Core 10) and
> Mac OS X 10.5, and the result is the same.
>
> Thanks.
>  - Eric -

Replying to myself: my problem seems to be related to bug 1739605
(http://sourceforge.net/tracker/?
func=detail&aid=1739605&group_id=12997&atid=112997), except in my
case, 'update idletasks' does not seem to make things work. I tried
everything I could think of ('after idle', 'tkwait visibility',
posting custom events and doing the 'see' when they are received and
combinations of all of the above), but I only succeeded in making it
work with an 'after <delay>'. The problem now is that the delay seems
to depend on the number of lines I display: the more lines there is,
the bigger the delay must be. Quite unsatisfactory...
From: Alexandre Ferrieux on
On Feb 10, 5:27 pm, eb303 <eric.brunel.pragma...(a)gmail.com> wrote:
> On Feb 10, 4:32 pm, eb303 <eric.brunel.pragma...(a)gmail.com> wrote:
>
>
>
>
>
> > Hello all,
>
> > I've been trying to do a text editor showing line numbers on the left
> > side of a text, which can also set the initial position of the
> > insertion point. To do this, I pack 2 texts side by side, one for the
> > line numbers and one for the actual text, and configure them to scroll
> > together whenever one of them is scrolling. To see the initial cursor
> > position, I use the 'see' subcommand on the text, but it seems
> > something's wrong, since it doesn't seem to work.
>
> > Here is a simplified script demonstrating the problem:
> > -----------------
> > ## Frame for both texts
> > pack [frame .texts] -side top
> > ## Text for line numbers
> > text .texts.lines -width 5
> > pack .texts.lines -side left -fill y
> > ## Text for actual text
> > text .texts.txt
> > pack .texts.txt -side left -fill both
>
> > ## Vertical scrollbar
> > scrollbar .texts.vscroll -orient vertical -command { .texts.txt
> > yview }
>
> > ## Trick to make both texts scroll together, as well as update the
> > scrollbar
> > proc scroll_text { first last } {
> >   .texts.vscroll set $first $last
> >   .texts.lines yview moveto $first}
>
> > proc scroll_lines { first last } {
> >   .texts.vscroll set $first $last
> >   .texts.txt yview moveto $first}
>
> > .texts.txt configure -yscrollcommand scroll_text
> > .texts.lines configure -yscrollcommand scroll_lines
>
> > ## Fill text and line numbers with dummy lines
> > for { set i 1 } { $i <= 2000 } { incr i } {
> >   .texts.lines insert end "$i\n"
> >   .texts.txt insert end "This is line number $i\n"
>
> > }
>
> > ## Procedure to center the text on a given line and set the insertion
> > point on it
> > proc center_text {} {
> >   .texts.txt see 789.0
> >   .texts.txt mark set insert 789.0
>
> > }
>
> > ## Initial positionning <= does not work
> > center_text
>
> > ## Button to do positionning again <= works
> > button .btn -text Center -command center_text
> > pack .btn
>
> > focus .texts.txt
> > -----------------
>
> > The initial call to center_text doesn't work: the insertion point is
> > actually moved, but the line is not centered in the text. However,
> > after the initial display, clicking on the 'Center' button works: the
> > insertion point moves, and the line is centered.
>
> > I've tried various tricks to make this work, like calls to 'update' or
> > 'update idletasks' before calling center_text, or triggering it later
> > via an 'after idle', but with no result: I can't get the line to be
> > centered on display.
>
> > Do I do anything wrong here? Is it the trick I used to scroll both
> > texts at the same time that messes things up?
>
> > My tcl version is 8.5.5; I've tried this on Linux (Fedora Core 10) and
> > Mac OS X 10.5, and the result is the same.
>
> > Thanks.
> >  - Eric -
>
> Replying to myself: my problem seems to be related to bug 1739605
> (http://sourceforge.net/tracker/?
> func=detail&aid=1739605&group_id=12997&atid=112997), except in my
> case, 'update idletasks' does not seem to make things work. I tried
> everything I could think of ('after idle', 'tkwait visibility',
> posting custom events and doing the 'see' when they are received and
> combinations of all of the above), but I only succeeded in making it
> work with an 'after <delay>'. The problem now is that the delay seems
> to depend on the number of lines I display: the more lines there is,
> the bigger the delay must be. Quite unsatisfactory...

Indeed !

The problem is that idle tasks in Tk do some real work, and we lack a
"after really_idle"...
Even calling center_text from within a <Configure> binding (which is
called many times) doesn't seem to help.
Sigh.

Please report a fresh bug. If it is the same as an older one, at least
that isn't obvious. No shame in marking it as duplicate afterwards ;-)

-Alex
From: Peter Spjuth on
On Feb 10, 4:32 pm, eb303 <eric.brunel.pragma...(a)gmail.com> wrote:
> I've been trying to do a text editor showing line numbers on the left
> side of a text, which can also set the initial position of the
> insertion point. To do this, I pack 2 texts side by side, one for the
> line numbers and one for the actual text, and configure them to scroll
> together whenever one of them is scrolling. To see the initial cursor
> position, I use the 'see' subcommand on the text, but it seems
> something's wrong, since it doesn't seem to work.

The text widget will do some background calculations that
need to settle before the "see" command can do its job.
Those are not idle tasks, so update will not help there.
It can be considered a bug that "see" does not force those
calculations but that's another issue. Let's focus on a
workaround.

First, the text widget has wrapping on by default which means
the calculations become dependent on the widget's geometry.
Add "-wrap none" to the text widget to get past that. I'm not sure
it helps much with the issue, but you probably want that anyway
when you try to keep the texts scrolled in sync.

Second, you need to force the background calculations to happen.
The only command I know that does that is count -ypixels:
proc center_text {} {
.texts.txt count -update -ypixels 1.0 end
.texts.lines count -update -ypixels 1.0 end
.texts.txt see 789.0
.texts.txt mark set insert 789.0
}

Third, give events and misc updates a chance to happen:
tkwait visibility .texts
after idle after 5 center_text

With that I got it to work.

/Peter
From: eb303 on
On Feb 11, 12:04 am, Peter Spjuth <peter.spj...(a)gmail.com> wrote:
> On Feb 10, 4:32 pm, eb303 <eric.brunel.pragma...(a)gmail.com> wrote:
>
> > I've been trying to do a text editor showing line numbers on the left
> > side of a text, which can also set the initial position of the
> > insertion point. To do this, I pack 2 texts side by side, one for the
> > line numbers and one for the actual text, and configure them to scroll
> > together whenever one of them is scrolling. To see the initial cursor
> > position, I use the 'see' subcommand on the text, but it seems
> > something's wrong, since it doesn't seem to work.
>
> The text widget will do some background calculations that
> need to settle before the "see" command can do its job.
> Those are not idle tasks, so update will not help there.
> It can be considered a bug that "see" does not force those
> calculations but that's another issue. Let's focus on a
> workaround.
>
> First, the text widget has wrapping on by default which means
> the calculations become dependent on the widget's geometry.
> Add "-wrap none" to the text widget to get past that. I'm not sure
> it helps much with the issue, but you probably want that anyway
> when you try to keep the texts scrolled in sync.
>
> Second, you need to force the background calculations to happen.
> The only command I know that does that is count -ypixels:
> proc center_text {} {
>     .texts.txt count -update -ypixels 1.0 end
>     .texts.lines count -update -ypixels 1.0 end
>     .texts.txt see 789.0
>     .texts.txt mark set insert 789.0
>
> }
>
> Third, give events and misc updates a chance to happen:
> tkwait visibility .texts
> after idle after 5 center_text
>
> With that I got it to work.
>
> /Peter

Thanks a lot Peter, it's working. And 'after 5' seems to work whatever
number of lines are in the text, so that's great (I usually don't
really like relying on after, but it seems OK here).
 |  Next  |  Last
Pages: 1 2 3
Prev: get highlighted text
Next: Keybinding hell.