311 lines
9.4 KiB
Objective-C
311 lines
9.4 KiB
Objective-C
// 8 december 2015
|
|
#import "uipriv_darwin.h"
|
|
|
|
// TODO you actually have to click on parts with a line in them in order to start editing; clicking below the last line doesn't give focus
|
|
|
|
// NSTextView has no intrinsic content size by default, which wreaks havoc on a pure-Auto Layout system
|
|
// we'll have to take over to get it to work
|
|
// see also http://stackoverflow.com/questions/24210153/nstextview-not-properly-resizing-with-auto-layout and http://stackoverflow.com/questions/11237622/using-autolayout-with-expanding-nstextviews
|
|
@interface intrinsicSizeTextView : NSTextView
|
|
@end
|
|
|
|
@implementation intrinsicSizeTextView
|
|
|
|
- (NSSize)intrinsicContentSize
|
|
{
|
|
NSTextContainer *textContainer;
|
|
NSLayoutManager *layoutManager;
|
|
NSRect rect;
|
|
|
|
textContainer = [self textContainer];
|
|
layoutManager = [self layoutManager];
|
|
[layoutManager ensureLayoutForTextContainer:textContainer];
|
|
rect = [layoutManager usedRectForTextContainer:textContainer];
|
|
return rect.size;
|
|
}
|
|
|
|
- (void)didChangeText
|
|
{
|
|
[super didChangeText];
|
|
[self invalidateIntrinsicContentSize];
|
|
}
|
|
|
|
// TODO this doesn't call the above?
|
|
// TODO this also isn't perfect; play around with cpp-multithread
|
|
- (void)setString:(NSString *)str
|
|
{
|
|
[super setString:str];
|
|
[self didChangeText];
|
|
}
|
|
|
|
@end
|
|
|
|
struct uiMultilineEntry {
|
|
uiDarwinControl c;
|
|
NSScrollView *sv;
|
|
intrinsicSizeTextView *tv;
|
|
struct scrollViewData *d;
|
|
void (*onChanged)(uiMultilineEntry *, void *);
|
|
void *onChangedData;
|
|
};
|
|
|
|
// TODO events
|
|
|
|
uiDarwinControlAllDefaultsExceptDestroy(uiMultilineEntry, sv)
|
|
|
|
static void uiMultilineEntryDestroy(uiControl *c)
|
|
{
|
|
uiMultilineEntry *e = uiMultilineEntry(c);
|
|
|
|
scrollViewFreeData(e->sv, e->d);
|
|
[e->tv release];
|
|
[e->sv release];
|
|
uiFreeControl(uiControl(e));
|
|
}
|
|
|
|
static void defaultOnChanged(uiMultilineEntry *e, void *data)
|
|
{
|
|
// do nothing
|
|
}
|
|
|
|
char *uiMultilineEntryText(uiMultilineEntry *e)
|
|
{
|
|
return uiDarwinNSStringToText([e->tv string]);
|
|
}
|
|
|
|
void uiMultilineEntrySetText(uiMultilineEntry *e, const char *text)
|
|
{
|
|
// TODO does this send a changed signal?
|
|
[e->tv setString:toNSString(text)];
|
|
}
|
|
|
|
// TODO scroll to end?
|
|
void uiMultilineEntryAppend(uiMultilineEntry *e, const char *text)
|
|
{
|
|
// TODO better way?
|
|
NSString *str;
|
|
|
|
// TODO does this send a changed signal?
|
|
str = [e->tv string];
|
|
str = [str stringByAppendingString:toNSString(text)];
|
|
[e->tv setString:str];
|
|
}
|
|
|
|
void uiMultilineEntryOnChanged(uiMultilineEntry *e, void (*f)(uiMultilineEntry *e, void *data), void *data)
|
|
{
|
|
e->onChanged = f;
|
|
e->onChangedData = data;
|
|
}
|
|
|
|
int uiMultilineEntryReadOnly(uiMultilineEntry *e)
|
|
{
|
|
return [e->tv isEditable] == NO;
|
|
}
|
|
|
|
void uiMultilineEntrySetReadOnly(uiMultilineEntry *e, int readonly)
|
|
{
|
|
BOOL editable;
|
|
|
|
editable = YES;
|
|
if (readonly)
|
|
editable = NO;
|
|
[e->tv setEditable:editable];
|
|
}
|
|
|
|
static uiMultilineEntry *finishMultilineEntry(BOOL hscroll)
|
|
{
|
|
uiMultilineEntry *e;
|
|
NSFont *font;
|
|
struct scrollViewCreateParams p;
|
|
|
|
uiDarwinNewControl(uiMultilineEntry, e);
|
|
|
|
e->tv = [[intrinsicSizeTextView alloc] initWithFrame:NSZeroRect];
|
|
// verified against Interface Builder, except for rich text options
|
|
[e->tv setAllowsDocumentBackgroundColorChange:NO];
|
|
[e->tv setBackgroundColor:[NSColor textBackgroundColor]];
|
|
[e->tv setTextColor:[NSColor textColor]];
|
|
[e->tv setAllowsUndo:YES];
|
|
[e->tv setEditable:YES];
|
|
[e->tv setSelectable:YES];
|
|
[e->tv setRichText:NO];
|
|
[e->tv setImportsGraphics:NO];
|
|
[e->tv setBaseWritingDirection:NSWritingDirectionNatural];
|
|
// TODO default paragraph format
|
|
[e->tv setAllowsImageEditing:NO];
|
|
[e->tv setAutomaticQuoteSubstitutionEnabled:NO];
|
|
[e->tv setAutomaticLinkDetectionEnabled:NO];
|
|
[e->tv setUsesRuler:NO];
|
|
[e->tv setRulerVisible:NO];
|
|
[e->tv setUsesInspectorBar:NO];
|
|
[e->tv setSelectionGranularity:NSSelectByCharacter];
|
|
//TODO [e->tv setInsertionPointColor:[NSColor insertionColor]];
|
|
[e->tv setContinuousSpellCheckingEnabled:NO];
|
|
[e->tv setGrammarCheckingEnabled:NO];
|
|
[e->tv setUsesFontPanel:NO];
|
|
[e->tv setEnabledTextCheckingTypes:0];
|
|
[e->tv setAutomaticDashSubstitutionEnabled:NO];
|
|
[e->tv setAutomaticSpellingCorrectionEnabled:NO];
|
|
[e->tv setAutomaticTextReplacementEnabled:NO];
|
|
[e->tv setSmartInsertDeleteEnabled:NO];
|
|
[e->tv setLayoutOrientation:NSTextLayoutOrientationHorizontal];
|
|
// TODO default find panel behavior
|
|
// now just to be safe; this will do some of the above but whatever
|
|
disableAutocorrect(e->tv);
|
|
// this option is complex; just set it to the Interface Builder default
|
|
[[e->tv layoutManager] setAllowsNonContiguousLayout:YES];
|
|
if (hscroll) {
|
|
// TODO this is a giant mess
|
|
[e->tv setHorizontallyResizable:YES];
|
|
[[e->tv textContainer] setWidthTracksTextView:NO];
|
|
[[e->tv textContainer] setContainerSize:NSMakeSize(CGFLOAT_MAX, CGFLOAT_MAX)];
|
|
}
|
|
// don't use uiDarwinSetControlFont() directly; we have to do a little extra work to set the font
|
|
font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]];
|
|
[e->tv setTypingAttributes:[NSDictionary
|
|
dictionaryWithObject:font
|
|
forKey:NSFontAttributeName]];
|
|
// e->tv font from Interface Builder is nil, but setFont:nil throws an exception
|
|
// let's just set it to the standard control font anyway, just to be safe
|
|
[e->tv setFont:font];
|
|
|
|
memset(&p, 0, sizeof (struct scrollViewCreateParams));
|
|
p.DocumentView = e->tv;
|
|
// this is what Interface Builder sets it to
|
|
p.BackgroundColor = [NSColor colorWithCalibratedWhite:1.0 alpha:1.0];
|
|
p.DrawsBackground = YES;
|
|
p.Bordered = YES;
|
|
p.HScroll = hscroll;
|
|
p.VScroll = YES;
|
|
e->sv = mkScrollView(&p, &(e->d));
|
|
|
|
uiMultilineEntryOnChanged(e, defaultOnChanged, NULL);
|
|
|
|
return e;
|
|
}
|
|
|
|
uiMultilineEntry *uiNewMultilineEntry(void)
|
|
{
|
|
return finishMultilineEntry(NO);
|
|
}
|
|
|
|
uiMultilineEntry *uiNewNonWrappingMultilineEntry(void)
|
|
{
|
|
return finishMultilineEntry(YES);
|
|
}
|
|
|
|
// TODO
|
|
#if 0
|
|
|
|
NSMutableString *s;
|
|
static void add(const char *fmt, ...)
|
|
{
|
|
va_list ap;
|
|
NSString *fmts;
|
|
NSString *a;
|
|
|
|
va_start(ap, fmt);
|
|
fmts = [NSString stringWithUTF8String:fmt];
|
|
a = [[NSString alloc] initWithFormat:fmts arguments:ap];
|
|
[s appendString:a];
|
|
[s appendString:@"\n"];
|
|
va_end(ap);
|
|
}
|
|
|
|
static NSString *edgeInsetsStr(NSEdgeInsets i)
|
|
{
|
|
return [NSString
|
|
stringWithFormat:@"left:%g top:%g right:%g bottom:%g",
|
|
i.left, i.top, i.right, i.bottom];
|
|
}
|
|
|
|
void printinfo(NSScrollView *sv, NSTextView *tv)
|
|
{
|
|
s = [NSMutableString new];
|
|
|
|
#define self _s
|
|
struct {
|
|
NSScrollView *sv;
|
|
NSTextView *tv;
|
|
} _s;
|
|
_s.sv = sv;
|
|
_s.tv = tv;
|
|
|
|
add("NSTextView");
|
|
add(" textContainerInset %@",
|
|
NSStringFromSize([self.tv textContainerInset]));
|
|
add(" textContainerOrigin %@",
|
|
NSStringFromPoint([self.tv textContainerOrigin]));
|
|
add(" backgroundColor %@", [self.tv backgroundColor]);
|
|
add(" drawsBackground %d", [self.tv drawsBackground]);
|
|
add(" allowsDocumentBackgroundColorChange %d",
|
|
[self.tv allowsDocumentBackgroundColorChange]);
|
|
add(" allowedInputSourceLocales %@",
|
|
[self.tv allowedInputSourceLocales]);
|
|
add(" allowsUndo %d", [self.tv allowsUndo]);
|
|
add(" isEditable %d", [self.tv isEditable]);
|
|
add(" isSelectable %d", [self.tv isSelectable]);
|
|
add(" isFieldEditor %d", [self.tv isFieldEditor]);
|
|
add(" isRichText %d", [self.tv isRichText]);
|
|
add(" importsGraphics %d", [self.tv importsGraphics]);
|
|
add(" defaultParagraphStyle %@",
|
|
[self.tv defaultParagraphStyle]);
|
|
add(" allowsImageEditing %d", [self.tv allowsImageEditing]);
|
|
add(" isAutomaticQuoteSubstitutionEnabled %d",
|
|
[self.tv isAutomaticQuoteSubstitutionEnabled]);
|
|
add(" isAutomaticLinkDetectionEnabled %d",
|
|
[self.tv isAutomaticLinkDetectionEnabled]);
|
|
add(" displaysLinkToolTips %d", [self.tv displaysLinkToolTips]);
|
|
add(" usesRuler %d", [self.tv usesRuler]);
|
|
add(" isRulerVisible %d", [self.tv isRulerVisible]);
|
|
add(" usesInspectorBar %d", [self.tv usesInspectorBar]);
|
|
add(" selectionAffinity %d", [self.tv selectionAffinity]);
|
|
add(" selectionGranularity %d", [self.tv selectionGranularity]);
|
|
add(" insertionPointColor %@", [self.tv insertionPointColor]);
|
|
add(" selectedTextAttributes %@",
|
|
[self.tv selectedTextAttributes]);
|
|
add(" markedTextAttributes %@", [self.tv markedTextAttributes]);
|
|
add(" linkTextAttributes %@", [self.tv linkTextAttributes]);
|
|
add(" typingAttributes %@", [self.tv typingAttributes]);
|
|
add(" smartInsertDeleteEnabled %d",
|
|
[self.tv smartInsertDeleteEnabled]);
|
|
add(" isContinuousSpellCheckingEnabled %d",
|
|
[self.tv isContinuousSpellCheckingEnabled]);
|
|
add(" isGrammarCheckingEnabled %d",
|
|
[self.tv isGrammarCheckingEnabled]);
|
|
add(" acceptsGlyphInfo %d", [self.tv acceptsGlyphInfo]);
|
|
add(" usesFontPanel %d", [self.tv usesFontPanel]);
|
|
add(" usesFindPanel %d", [self.tv usesFindPanel]);
|
|
add(" enabledTextCheckingTypes %d",
|
|
[self.tv enabledTextCheckingTypes]);
|
|
add(" isAutomaticDashSubstitutionEnabled %d",
|
|
[self.tv isAutomaticDashSubstitutionEnabled]);
|
|
add(" isAutomaticDataDetectionEnabled %d",
|
|
[self.tv isAutomaticDataDetectionEnabled]);
|
|
add(" isAutomaticSpellingCorrectionEnabled %d",
|
|
[self.tv isAutomaticSpellingCorrectionEnabled]);
|
|
add(" isAutomaticTextReplacementEnabled %d",
|
|
[self.tv isAutomaticTextReplacementEnabled]);
|
|
add(" usesFindBar %d", [self.tv usesFindBar]);
|
|
add(" isIncrementalSearchingEnabled %d",
|
|
[self.tv isIncrementalSearchingEnabled]);
|
|
add(" NSText:");
|
|
add(" font %@", [self.tv font]);
|
|
add(" textColor %@", [self.tv textColor]);
|
|
add(" baseWritingDirection %d", [self.tv baseWritingDirection]);
|
|
add(" maxSize %@",
|
|
NSStringFromSize([self.tv maxSize]));
|
|
add(" minSize %@",
|
|
NSStringFromSize([self.tv minSize]));
|
|
add(" isVerticallyResizable %d",
|
|
[self.tv isVerticallyResizable]);
|
|
add(" isHorizontallyResizable %d",
|
|
[self.tv isHorizontallyResizable]);
|
|
|
|
#undef self
|
|
|
|
fprintf(stdout, "%s", [s UTF8String]);
|
|
}
|
|
|
|
#endif
|