Clarify comments about user attribute changing now that I've figured out a way for it to work. Rewrite the actions to match.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@15852 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Alexander Malmberg 2003-02-02 01:37:27 +00:00
parent 5d36c3e89a
commit 94ecd621eb
3 changed files with 227 additions and 163 deletions

View file

@ -1,3 +1,9 @@
2003-02-02 02:31 Alexander Malmberg <alexander@malmberg.org>
* Source/NSTextView.m, Source/NSTextView_actions.m: Clarify
comments about user attribute changing now that I've figured out
a way for it to work. Rewrite the actions to match.
2003-02-02 Fred Kiefer <FredKiefer@gmx.de>
* Source/NSTextView.m
@ -9,7 +15,7 @@
[setFrame:display:]. Use [NSScreen visibleFrame] here and in
[stringWithSavedFrame]. Implemented [cascadeTopLeftFromPoint:].
Removed unused and empty methods [performHide:] and [performUnhide:].
2003-02-01 15:09 Alexander Malmberg <alexander@malmberg.org>
* Source/NSTextView.m (-shouldChangeTextInRange:replacementString:):

View file

@ -87,16 +87,6 @@ TODOs:
think hard about insertion point management
When should the typing attributes be changed? Docs imply that normally
you don't touch them at all, you just change the attributes of the
selection and the typing attributes will update automagically, but if
the selection is empty, you should change the typing attributes instead.
In a non-rich-text text view, I assume that the typing attributes always
hold the attributes of the text. Will need to look over methods that deal
with attributes to make sure this holds.
How should resizing work? If the text view is set to track the used part
of the text container, when does it actually update its size? Might need
a new internal method called from NSLayoutManager when text has changed.
@ -1983,7 +1973,9 @@ replacementString should be the string that will replace the affected range
(disregarding attributes), or nil if only attributes are changed.
If the affected range or replacement string can't be determined, pass in
NSNotFound for the range's location and nil for the string
NSNotFound for the range's location and nil for the string. (Ie. even if
you know the range, you should pass in NSNotFound so the delegate can tell
the difference between a pure attribute change and an unknown change.)
TODO: What if the view isn't first responder? It should be impossible for

View file

@ -66,6 +66,23 @@ All actions from NSResponder that make sense for a text view should be
implemented here, but this is _not_ the place to add new actions.
When changing attributes, the range returned by
rangeForUserCharacterAttributeChange or rangeForUserParagraphAttributeChange
should be used. If the location is NSNotFound, nothing should be done (in
particular, the typing attributes should _not_ be changed). Otherwise,
-shouldChangeTextInRange:replacementString: should be called, and if it
returns YES, the attributes of the range and the typing attributes should be
changed, and -didChangeText should be called.
In a non-rich-text text view, the typing attributes _must_always_ hold the
attributes of the text. Thus, the typing attributes muse always be changed
in the same way that the attributes of the text are changed.
(TODO: Will need to look over methods that deal with attributes to make
sure this holds.)
Not all user actions are here. Exceptions:
-toggleRuler:
@ -109,6 +126,10 @@ send -shouldChangeTextInRange:replacementString: or -didChangeText.
-(void) _illegalMovement: (int)textMovement;
-(void) _changeAttribute: (NSString *)name
inRange: (NSRange)r
using: (id (*)(id))func;
@end
@ -146,69 +167,177 @@ send -shouldChangeTextInRange:replacementString: or -didChangeText.
return;
}
-(void) _changeAttribute: (NSString *)name
inRange: (NSRange)r
using: (id (*)(id))func
{
unsigned int i;
NSRange e, r2;
id current, new;
if (![self shouldChangeTextInRange: r replacementString: nil])
return;
[_textStorage beginEditing];
for (i = r.location; i < NSMaxRange(r); )
{
current = [_textStorage attribute: name
atIndex: i
effectiveRange: &e];
r2 = NSMakeRange(i, NSMaxRange(e) - i);
r2 = NSIntersectionRange(r2, r);
i = NSMaxRange(e);
new = func(current);
if (new != current)
{
if (!new)
{
[_textStorage removeAttribute: name
range: r2];
}
else
{
[_textStorage addAttribute: name
value: new
range: r2];
}
}
}
[_textStorage endEditing];
current = [_layoutManager->_typingAttributes objectForKey: name];
new = func(current);
if (new != current)
{
if (!new)
{
[_layoutManager->_typingAttributes removeObjectForKey: name];
}
else
{
[_layoutManager->_typingAttributes setObject: new forKey: name];
}
}
[self didChangeText];
}
@end
@implementation NSTextView (user_actions)
/* Helpers used with _changeAttribute:inRange:using:. */
static NSNumber *int_minus_one(NSNumber *cur)
{
int value;
if (cur)
value = [cur intValue] - 1;
else
value = -1;
if (value)
return [NSNumber numberWithInt: value];
else
return nil;
}
static NSNumber *int_plus_one(NSNumber *cur)
{
int value;
if (cur)
value = [cur intValue] + 1;
else
value = 1;
if (value)
return [NSNumber numberWithInt: value];
else
return nil;
}
static NSNumber *float_minus_one(NSNumber *cur)
{
float value;
if (cur)
value = [cur floatValue] - 1;
else
value = -1;
if (value)
return [NSNumber numberWithFloat: value];
else
return nil;
}
static NSNumber *float_plus_one(NSNumber *cur)
{
int value;
if (cur)
value = [cur floatValue] + 1;
else
value = 1;
if (value)
return [NSNumber numberWithFloat: value];
else
return nil;
}
-(void) subscript: (id)sender
{
NSNumber *value = [_layoutManager->_typingAttributes
objectForKey: NSSuperscriptAttributeName];
int sValue;
NSRange aRange = [self rangeForUserCharacterAttributeChange];
NSRange r = [self rangeForUserCharacterAttributeChange];
if (aRange.location == NSNotFound)
if (r.location == NSNotFound)
return;
if (aRange.length)
{
if (![self shouldChangeTextInRange: aRange
replacementString: nil])
return;
[_textStorage beginEditing];
[_textStorage subscriptRange: aRange];
[_textStorage endEditing];
[self didChangeText];
}
// Set the typing attributes
if (value != nil)
sValue = [value intValue] - 1;
else
sValue = -1;
[_layoutManager->_typingAttributes setObject: [NSNumber numberWithInt: sValue]
forKey: NSSuperscriptAttributeName];
[self _changeAttribute: NSSuperscriptAttributeName
inRange: r
using: int_minus_one];
}
-(void) superscript: (id)sender
{
NSNumber *value = [_layoutManager->_typingAttributes
objectForKey: NSSuperscriptAttributeName];
int sValue;
NSRange aRange = [self rangeForUserCharacterAttributeChange];
NSRange r = [self rangeForUserCharacterAttributeChange];
if (aRange.location == NSNotFound)
if (r.location == NSNotFound)
return;
if (aRange.length)
{
if (![self shouldChangeTextInRange: aRange
replacementString: nil])
return;
[_textStorage beginEditing];
[_textStorage superscriptRange: aRange];
[_textStorage endEditing];
[self didChangeText];
}
[self _changeAttribute: NSSuperscriptAttributeName
inRange: r
using: int_plus_one];
}
// Set the typing attributes
if (value != nil)
sValue = [value intValue] + 1;
else
sValue = 1;
[_layoutManager->_typingAttributes setObject: [NSNumber numberWithInt: sValue]
forKey: NSSuperscriptAttributeName];
-(void) lowerBaseline: (id)sender
{
NSRange r = [self rangeForUserCharacterAttributeChange];
if (r.location == NSNotFound)
return;
[self _changeAttribute: NSSuperscriptAttributeName
inRange: r
using: float_plus_one];
}
-(void) raiseBaseline: (id)sender
{
NSRange r = [self rangeForUserCharacterAttributeChange];
if (r.location == NSNotFound)
return;
[self _changeAttribute: NSBaselineOffsetAttributeName
inRange: r
using: float_minus_one];
}
-(void) unscript: (id)sender
@ -218,21 +347,27 @@ send -shouldChangeTextInRange:replacementString: or -didChangeText.
if (aRange.location == NSNotFound)
return;
if (![self shouldChangeTextInRange: aRange
replacementString: nil])
return;
if (aRange.length)
{
if (![self shouldChangeTextInRange: aRange
replacementString: nil])
return;
[_textStorage beginEditing];
[_textStorage unscriptRange: aRange];
[_textStorage removeAttribute: NSSuperscriptAttributeName
range: aRange];
[_textStorage removeAttribute: NSBaselineOffsetAttributeName
range: aRange];
[_textStorage endEditing];
[self didChangeText];
}
// Set the typing attributes
[_layoutManager->_typingAttributes removeObjectForKey: NSSuperscriptAttributeName];
[_layoutManager->_typingAttributes removeObjectForKey: NSBaselineOffsetAttributeName];
[self didChangeText];
}
-(void) underline: (id)sender
{
BOOL doUnderline = YES;
@ -264,81 +399,20 @@ send -shouldChangeTextInRange:replacementString: or -didChangeText.
forKey: NSUnderlineStyleAttributeName];
}
-(void) useStandardKerning: (id)sender
{
// rekern for selected range if rich text, else rekern entire document.
NSRange aRange = [self rangeForUserCharacterAttributeChange];
if (aRange.location == NSNotFound)
return;
if (![self shouldChangeTextInRange: aRange
replacementString: nil])
return;
[_textStorage beginEditing];
[_textStorage removeAttribute: NSKernAttributeName
range: aRange];
[_textStorage endEditing];
[self didChangeText];
}
-(void) lowerBaseline: (id)sender
{
id value;
float sValue;
NSRange effRange;
NSRange aRange = [self rangeForUserCharacterAttributeChange];
if (aRange.location == NSNotFound)
return;
if (![self shouldChangeTextInRange: aRange
replacementString: nil])
return;
[_textStorage beginEditing];
// We take the value form the first character and use it for the whole range
value = [_textStorage attribute: NSBaselineOffsetAttributeName
atIndex: aRange.location
effectiveRange: &effRange];
if (value != nil)
sValue = [value floatValue] + 1.0;
else
sValue = 1.0;
[_textStorage addAttribute: NSBaselineOffsetAttributeName
value: [NSNumber numberWithFloat: sValue]
range: aRange];
}
-(void) raiseBaseline: (id)sender
{
id value;
float sValue;
NSRange effRange;
NSRange aRange = [self rangeForUserCharacterAttributeChange];
if (aRange.location == NSNotFound)
return;
if (![self shouldChangeTextInRange: aRange
replacementString: nil])
return;
[_textStorage beginEditing];
// We take the value form the first character and use it for the whole range
value = [_textStorage attribute: NSBaselineOffsetAttributeName
atIndex: aRange.location
effectiveRange: &effRange];
if (value != nil)
sValue = [value floatValue] - 1.0;
else
sValue = -1.0;
[_textStorage addAttribute: NSBaselineOffsetAttributeName
value: [NSNumber numberWithFloat: sValue]
range: aRange];
[_textStorage endEditing];
[_layoutManager->_typingAttributes removeObjectForKey: NSKernAttributeName];
[self didChangeText];
}
@ -348,54 +422,40 @@ send -shouldChangeTextInRange:replacementString: or -didChangeText.
if (aRange.location == NSNotFound)
return;
if (![self shouldChangeTextInRange: aRange
replacementString: nil])
return;
[_textStorage beginEditing];
[_textStorage addAttribute: NSKernAttributeName
value: [NSNumber numberWithFloat: 0.0]
range: aRange];
[_textStorage endEditing];
[_layoutManager->_typingAttributes setObject: [NSNumber numberWithFloat: 0.0]
forKey: NSKernAttributeName];
[self didChangeText];
}
-(void) loosenKerning: (id)sender
{
NSRange aRange = [self rangeForUserCharacterAttributeChange];
NSRange r = [self rangeForUserCharacterAttributeChange];
if (aRange.location == NSNotFound)
if (r.location == NSNotFound)
return;
if (![self shouldChangeTextInRange: aRange
replacementString: nil])
return;
[_textStorage beginEditing];
// FIXME: Should use the current kerning and work relative to point size
[_textStorage addAttribute: NSKernAttributeName
value: [NSNumber numberWithFloat: 1.0]
range: aRange];
[_textStorage endEditing];
[self didChangeText];
[self _changeAttribute: NSKernAttributeName
inRange: r
using: float_plus_one];
}
-(void) tightenKerning: (id)sender
{
NSRange aRange = [self rangeForUserCharacterAttributeChange];
NSRange r = [self rangeForUserCharacterAttributeChange];
if (aRange.location == NSNotFound)
if (r.location == NSNotFound)
return;
if (![self shouldChangeTextInRange: aRange
replacementString: nil])
return;
[_textStorage beginEditing];
// FIXME: Should use the current kerning and work relative to point size
[_textStorage addAttribute: NSKernAttributeName
value: [NSNumber numberWithFloat: -1.0]
range: aRange];
[_textStorage endEditing];
[self didChangeText];
[self _changeAttribute: NSKernAttributeName
inRange: r
using: float_minus_one];
}
-(void) useStandardLigatures: (id)sender
@ -408,11 +468,11 @@ send -shouldChangeTextInRange:replacementString: or -didChangeText.
if (![self shouldChangeTextInRange: aRange
replacementString: nil])
return;
[_textStorage beginEditing];
[_textStorage addAttribute: NSLigatureAttributeName
value: [NSNumber numberWithInt: 1]
range: aRange];
[_textStorage endEditing];
[_layoutManager->_typingAttributes setObject: [NSNumber numberWithInt: 1]
forKey: NSLigatureAttributeName];
[self didChangeText];
}
@ -426,11 +486,10 @@ send -shouldChangeTextInRange:replacementString: or -didChangeText.
if (![self shouldChangeTextInRange: aRange
replacementString: nil])
return;
[_textStorage beginEditing];
[_textStorage addAttribute: NSLigatureAttributeName
value: [NSNumber numberWithInt: 0]
[_textStorage removeAttribute: NSLigatureAttributeName
range: aRange];
[_textStorage endEditing];
[_layoutManager->_typingAttributes removeObjectForKey: NSLigatureAttributeName];
[self didChangeText];
}
@ -444,11 +503,11 @@ send -shouldChangeTextInRange:replacementString: or -didChangeText.
if (![self shouldChangeTextInRange: aRange
replacementString: nil])
return;
[_textStorage beginEditing];
[_textStorage addAttribute: NSLigatureAttributeName
value: [NSNumber numberWithInt: 2]
range: aRange];
[_textStorage endEditing];
[_layoutManager->_typingAttributes setObject: [NSNumber numberWithInt: 2]
forKey: NSLigatureAttributeName];
[self didChangeText];
}
@ -459,6 +518,7 @@ send -shouldChangeTextInRange:replacementString: or -didChangeText.
"toggleTraditionalCharacterShape:", "NSTextView");
}
-(void) insertNewline: (id)sender
{
if (_tf.is_field_editor)
@ -492,6 +552,7 @@ send -shouldChangeTextInRange:replacementString: or -didChangeText.
//[self insertText: @"\t"];
}
-(void) deleteForward: (id)sender
{
NSRange range = [self rangeForUserTextChange];
@ -577,6 +638,7 @@ send -shouldChangeTextInRange:replacementString: or -didChangeText.
[self setSelectedRange: NSMakeRange (range.location, 0)];
}
-(void) moveUp: (id)sender
{
/* float originalInsertionPoint;
@ -1109,6 +1171,7 @@ send -shouldChangeTextInRange:replacementString: or -didChangeText.
#endif
}
-(void) scrollLineDown: (id)sender
{
// TODO
@ -1146,7 +1209,8 @@ send -shouldChangeTextInRange:replacementString: or -didChangeText.
{
NSRange aRange;
NSRect ignored;
/* TODO: broken. assumes glyph==character */
ignored = [_layoutManager lineFragmentRectForGlyphAtIndex:
_layoutManager->_selected_range.location
effectiveRange: &aRange];
@ -1155,6 +1219,7 @@ send -shouldChangeTextInRange:replacementString: or -didChangeText.
}
}
/* The following method is bound to 'Control-t', and must work like
* pressing 'Control-t' inside Emacs. For example, say that I type
* 'Nicoal' in a NSTextView. Then, I press 'Control-t'. This should
@ -1202,6 +1267,7 @@ insertion point. (see also: miswart)
}
}
-(void) delete: (id)sender
{
[self deleteForward: sender];