aboutsummaryrefslogtreecommitdiff
path: root/src/libui_sdl/libui/darwin/multilineentry.m
diff options
context:
space:
mode:
authorStapleButter <thetotalworm@gmail.com>2017-09-09 02:30:51 +0200
committerStapleButter <thetotalworm@gmail.com>2017-09-09 02:30:51 +0200
commit70e4841d311d68689724768157cc9cbfbde7a9fc (patch)
treeba9499f77d1258530a7e60aa6e1732c41d98161c /src/libui_sdl/libui/darwin/multilineentry.m
parent81747d6c34eb159481a6ca3f283d065fa3568617 (diff)
another UI attempt, I guess.
sorry.
Diffstat (limited to 'src/libui_sdl/libui/darwin/multilineentry.m')
-rw-r--r--src/libui_sdl/libui/darwin/multilineentry.m233
1 files changed, 233 insertions, 0 deletions
diff --git a/src/libui_sdl/libui/darwin/multilineentry.m b/src/libui_sdl/libui/darwin/multilineentry.m
new file mode 100644
index 0000000..605e900
--- /dev/null
+++ b/src/libui_sdl/libui/darwin/multilineentry.m
@@ -0,0 +1,233 @@
+// 8 december 2015
+#import "uipriv_darwin.h"
+
+// 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 {
+ uiMultilineEntry *libui_e;
+}
+- (id)initWithFrame:(NSRect)r e:(uiMultilineEntry *)e;
+@end
+
+struct uiMultilineEntry {
+ uiDarwinControl c;
+ NSScrollView *sv;
+ intrinsicSizeTextView *tv;
+ struct scrollViewData *d;
+ void (*onChanged)(uiMultilineEntry *, void *);
+ void *onChangedData;
+ BOOL changing;
+};
+
+@implementation intrinsicSizeTextView
+
+- (id)initWithFrame:(NSRect)r e:(uiMultilineEntry *)e
+{
+ self = [super initWithFrame:r];
+ if (self)
+ self->libui_e = e;
+ return self;
+}
+
+- (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];
+ if (!self->libui_e->changing)
+ (*(self->libui_e->onChanged))(self->libui_e, self->libui_e->onChangedData);
+}
+
+@end
+
+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)
+{
+ [[e->tv textStorage] replaceCharactersInRange:NSMakeRange(0, [[e->tv string] length])
+ withString:toNSString(text)];
+ // must be called explicitly according to the documentation of shouldChangeTextInRange:replacementString:
+ e->changing = YES;
+ [e->tv didChangeText];
+ e->changing = NO;
+}
+
+// TODO scroll to end?
+void uiMultilineEntryAppend(uiMultilineEntry *e, const char *text)
+{
+ [[e->tv textStorage] replaceCharactersInRange:NSMakeRange([[e->tv string] length], 0)
+ withString:toNSString(text)];
+ e->changing = YES;
+ [e->tv didChangeText];
+ e->changing = NO;
+}
+
+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 e:e];
+
+ // verified against Interface Builder for a sufficiently customized text view
+
+ // NSText properties:
+ // this is what Interface Builder sets the background color to
+ [e->tv setBackgroundColor:[NSColor colorWithCalibratedWhite:1.0 alpha:1.0]];
+ [e->tv setDrawsBackground:YES];
+ [e->tv setEditable:YES];
+ [e->tv setSelectable:YES];
+ [e->tv setFieldEditor:NO];
+ [e->tv setRichText:NO];
+ [e->tv setImportsGraphics:NO];
+ [e->tv setUsesFontPanel:NO];
+ [e->tv setRulerVisible:NO];
+ // we'll handle font last
+ // while setAlignment: has been around since 10.0, the named constant "NSTextAlignmentNatural" seems to have only been introduced in 10.11
+#define ourNSTextAlignmentNatural 4
+ [e->tv setAlignment:ourNSTextAlignmentNatural];
+ // textColor is set to nil, just keep the dfault
+ [e->tv setBaseWritingDirection:NSWritingDirectionNatural];
+ [e->tv setHorizontallyResizable:NO];
+ [e->tv setVerticallyResizable:YES];
+
+ // NSTextView properties:
+ [e->tv setAllowsDocumentBackgroundColorChange:NO];
+ [e->tv setAllowsUndo:YES];
+ // default paragraph style is nil; keep default
+ [e->tv setAllowsImageEditing:NO];
+ [e->tv setAutomaticQuoteSubstitutionEnabled:NO];
+ [e->tv setAutomaticLinkDetectionEnabled:NO];
+ [e->tv setDisplaysLinkToolTips:YES];
+ [e->tv setUsesRuler:NO];
+ [e->tv setUsesInspectorBar:NO];
+ [e->tv setSelectionGranularity:NSSelectByCharacter];
+ // there is a dedicated named insertion point color but oh well
+ [e->tv setInsertionPointColor:[NSColor controlTextColor]];
+ // typing attributes is nil; keep default (we change it below for fonts though)
+ [e->tv setSmartInsertDeleteEnabled:NO];
+ [e->tv setContinuousSpellCheckingEnabled:NO];
+ [e->tv setGrammarCheckingEnabled:NO];
+ [e->tv setUsesFindPanel:YES];
+ [e->tv setEnabledTextCheckingTypes:0];
+ [e->tv setAutomaticDashSubstitutionEnabled:NO];
+ [e->tv setAutomaticDataDetectionEnabled:NO];
+ [e->tv setAutomaticSpellingCorrectionEnabled:NO];
+ [e->tv setAutomaticTextReplacementEnabled:NO];
+ [e->tv setUsesFindBar:NO];
+ [e->tv setIncrementalSearchingEnabled:NO];
+
+ // NSTextContainer properties:
+ [[e->tv textContainer] setWidthTracksTextView:YES];
+ [[e->tv textContainer] setHeightTracksTextView:NO];
+
+ // NSLayoutManager properties:
+ [[e->tv layoutManager] setAllowsNonContiguousLayout:YES];
+
+ // now just to be safe; this will do some of the above but whatever
+ disableAutocorrect(e->tv);
+
+ // see https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/TextUILayer/Tasks/TextInScrollView.html
+ // notice we don't use the Auto Layout code; see scrollview.m for more details
+ [e->tv setMaxSize:NSMakeSize(CGFLOAT_MAX, CGFLOAT_MAX)];
+ [e->tv setVerticallyResizable:YES];
+ [e->tv setHorizontallyResizable:hscroll];
+ if (hscroll) {
+ [e->tv setAutoresizingMask:(NSViewWidthSizable | NSViewHeightSizable)];
+ [[e->tv textContainer] setWidthTracksTextView:NO];
+ } else {
+ [e->tv setAutoresizingMask:NSViewWidthSizable];
+ [[e->tv textContainer] setWidthTracksTextView:YES];
+ }
+ [[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);
+}