diff --git a/ChangeLog b/ChangeLog index 760fbd2d9..6368f6155 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2003-02-15 18:22 Alexander Malmberg + + * Headers/gnustep/gui/NSTextView.h, Source/NSLayoutManager.m, + Source/NSTextView.m: Change the way the text view is told about + layout invalidation. Change NSTextView to update its state as + late as possible before displaying, and make sure it's updated + when it's resized. + 2003-02-15 18:11 Alexander Malmberg * Source/NSParagraphStyle.m ([NSMutableParagraphStyle diff --git a/Headers/gnustep/gui/NSTextView.h b/Headers/gnustep/gui/NSTextView.h index c4844dd50..c41ab1e60 100644 --- a/Headers/gnustep/gui/NSTextView.h +++ b/Headers/gnustep/gui/NSTextView.h @@ -525,6 +525,12 @@ already been laid out. */ /* For internal use. */ -(void) _syncTextViewsByCalling: (SEL)action withFlag: (BOOL)flag; -(void) _recacheDelegateResponses; + +/* +NSLayoutManager will send this message to a text view when layout information +for that text view has been invalidated. +*/ +-(void) _layoutManagerDidInvalidateLayout; @end diff --git a/Source/NSLayoutManager.m b/Source/NSLayoutManager.m index 37840c4b2..5b9e5fcb5 100644 --- a/Source/NSLayoutManager.m +++ b/Source/NSLayoutManager.m @@ -1547,7 +1547,7 @@ TODO: not really clear what these should do unsigned int g; int i; - /* Invalidate display from the first glyph not laid out (which will + /* Invalidate from the first glyph not laid out (which will generally be the first glyph to have been invalidated). */ g = layout_glyph; @@ -1559,8 +1559,7 @@ TODO: not really clear what these should do g < textcontainers[i].pos + textcontainers[i].length) continue; - [[textcontainers[i].textContainer textView] sizeToFit]; - [[textcontainers[i].textContainer textView] setNeedsDisplay: YES]; + [[textcontainers[i].textContainer textView] _layoutManagerDidInvalidateLayout]; } } diff --git a/Source/NSTextView.m b/Source/NSTextView.m index fac93cb27..e28a03180 100644 --- a/Source/NSTextView.m +++ b/Source/NSTextView.m @@ -52,6 +52,7 @@ #include #include #include +#include #include #include #include @@ -292,6 +293,55 @@ decoded. } } + +/* +Called when our state needs updating due to external changes. Currently, +this happens when layout has been invalidated, and when we are resized. +*/ +-(void) _updateState: (id)sender +{ + [self sizeToFit]; + /* TODO: we don't have to redisplay the entire view */ + [self setNeedsDisplay: YES]; + [self updateInsertionPointStateAndRestartTimer: + [self shouldDrawInsertionPoint]]; +} + +-(void) _layoutManagerDidInvalidateLayout +{ + /* + We don't want to do the update right away, since the invalidation might + be followed by further invalidation if the user of the text system is + making large rearrangements of the text network. This also makes us a + lot more forgiving; no real works is done until "later", so the user can + have the text network in an inconsistent state for short periods of time. + (This shouldn't be relied on, though. If possible, avoid it.) + + Actually, we want to run as late as possible. However, it seems to me that + we must run before [NSWindow -_handleWindowNeedsDisplay:] (or that it + would be a very good idea to do so, since we might end up resizing + ourselves and stuff like that). Thus, we use -performSelector:... with + an order 1 under that for window updating. + + If the update method is not called before the real redisplay (if someone + forces a redisplay right away), we might draw incorrectly, but it shouldn't + cause any other harm. + */ + [[NSRunLoop currentRunLoop] cancelPerformSelector: @selector(_updateState:) + target: self + argument: nil]; + [[NSRunLoop currentRunLoop] + performSelector: @selector(_updateState:) + target: self + argument: nil + order: 599999 + modes: [NSArray arrayWithObjects: /* TODO: set up array in advance */ + NSDefaultRunLoopMode, + NSModalPanelRunLoopMode, + NSEventTrackingRunLoopMode, nil]]; +} + + @end @@ -433,6 +483,12 @@ If a text view is added to an empty text network, it keeps its attributes. [container setTextView: self]; [self invalidateTextContainerOrigin]; + [self setPostsFrameChangedNotifications: YES]; + [[NSNotificationCenter defaultCenter] addObserver: self + selector: @selector(_updateState:) + name: NSViewFrameDidChangeNotification + object: self]; + return self; } @@ -606,6 +662,12 @@ _tf.delegate_responds_to* */ [self _recacheDelegateResponses]; [self invalidateTextContainerOrigin]; + [self setPostsFrameChangedNotifications: YES]; + [[NSNotificationCenter defaultCenter] addObserver: self + selector: @selector(_updateState:) + name: NSViewFrameDidChangeNotification + object: self]; + return self; } @@ -634,6 +696,13 @@ _tf.delegate_responds_to* */ } } + [[NSNotificationCenter defaultCenter] removeObserver: self + name: NSViewFrameDidChangeNotification + object: self]; + [[NSRunLoop currentRunLoop] cancelPerformSelector: @selector(_updateState:) + target: self + argument: nil]; + DESTROY(_selectedTextAttributes); DESTROY(_markedTextAttributes); DESTROY(_insertionPointColor);