andlabs-ui/redo/basicctrls_darwin.m

255 lines
6.3 KiB
Objective-C

// 16 july 2014
#import "objc_darwin.h"
#import "_cgo_export.h"
#import <Cocoa/Cocoa.h>
#define toNSButton(x) ((NSButton *) (x))
#define toNSTextField(x) ((NSTextField *) (x))
#define toNSView(x) ((NSView *) (x))
#define toNSPopover(x) ((NSPopover *) (x))
#define toNSBox(x) ((NSBox *) (x))
@interface goControlDelegate : NSObject <NSTextFieldDelegate> {
@public
void *gocontrol;
}
@end
@implementation goControlDelegate
- (IBAction)buttonClicked:(id)sender
{
buttonClicked(self->gocontrol);
}
- (IBAction)checkboxToggled:(id)sender
{
checkboxToggled(self->gocontrol);
}
- (void)controlTextDidChange:(NSNotification *)note
{
textfieldChanged(self->gocontrol);
}
@end
id newButton(void)
{
NSButton *b;
b = [[NSButton alloc] initWithFrame:NSZeroRect];
[b setButtonType:NSMomentaryPushInButton];
[b setBordered:YES];
[b setBezelStyle:NSRoundedBezelStyle];
setStandardControlFont((id) b);
return (id) b;
}
void buttonSetDelegate(id button, void *b)
{
goControlDelegate *d;
d = [goControlDelegate new];
d->gocontrol = b;
[toNSButton(button) setTarget:d];
[toNSButton(button) setAction:@selector(buttonClicked:)];
}
const char *buttonText(id button)
{
return [[toNSButton(button) title] UTF8String];
}
void buttonSetText(id button, char *text)
{
[toNSButton(button) setTitle:[NSString stringWithUTF8String:text]];
}
id newCheckbox(void)
{
NSButton *c;
c = [[NSButton alloc] initWithFrame:NSZeroRect];
[c setButtonType:NSSwitchButton];
[c setBordered:NO];
setStandardControlFont((id) c);
return (id) c;
}
void checkboxSetDelegate(id checkbox, void *b)
{
goControlDelegate *d;
d = [goControlDelegate new];
d->gocontrol = b;
[toNSButton(checkbox) setTarget:d];
[toNSButton(checkbox) setAction:@selector(checkboxToggled:)];
}
BOOL checkboxChecked(id c)
{
if ([toNSButton(c) state] == NSOnState)
return YES;
return NO;
}
void checkboxSetChecked(id c, BOOL checked)
{
NSInteger state;
state = NSOnState;
if (checked == NO)
state = NSOffState;
[toNSButton(c) setState:state];
}
// also good for labels
// not static because area_darwin.m uses it
id finishNewTextField(id _t, BOOL bordered)
{
NSTextField *t = toNSTextField(_t);
// same for text fields, password fields, and labels
setStandardControlFont((id) t);
// these three are the same across text fields, password fields, and labels; the only difference is the setBezeled: value, and it's only different on labels
// THE ORDER OF THESE CALLS IS IMPORTANT; CHANGE IT AND THE BORDERS WILL DISAPPEAR
[t setBordered:NO];
[t setBezelStyle:NSTextFieldSquareBezel];
[t setBezeled:bordered];
// smart quotes and other autocorrect features are handled by the window; see newWindow() in window_darwin.m for details
// Interface Builder does this to make the text box behave properly
// this disables both word wrap AND ellipsizing in one fell swoop
// however, we need to send it to the control's cell, not to the control directly
[[t cell] setLineBreakMode:NSLineBreakByClipping];
// Interface Builder also sets this to allow horizontal scrolling
// it also sets this for labels, despite those not being scrollable
[[t cell] setScrollable:YES];
return (id) t;
}
id newTextField(void)
{
NSTextField *t;
t = [[NSTextField alloc] initWithFrame:NSZeroRect];
return finishNewTextField((id) t, YES);
}
id newPasswordField(void)
{
NSSecureTextField *t;
t = [[NSSecureTextField alloc] initWithFrame:NSZeroRect];
return finishNewTextField((id) t, YES);
}
void textfieldSetDelegate(id textfield, void *t)
{
goControlDelegate *d;
d = [goControlDelegate new];
d->gocontrol = t;
[toNSTextField(textfield) setDelegate:d];
}
// also good for labels
const char *textFieldText(id t)
{
return [[toNSTextField(t) stringValue] UTF8String];
}
// also good for labels
void textFieldSetText(id t, char *text)
{
[toNSTextField(t) setStringValue:[NSString stringWithUTF8String:text]];
}
id textfieldOpenInvalidPopover(id textfield, char *reason)
{
// step 1: set up the display
NSTextField *label;
NSTextAttachmentCell *cell;
NSTextAttachment *attachment;
NSAttributedString *strImage;
NSAttributedString *strText;
NSFont *font;
NSMutableAttributedString *str;
// method thanks to Anne in http://stackoverflow.com/a/5303517/3408572
// TODO improve appearance
label = toNSTextField(newLabel());
cell = [[NSTextAttachmentCell alloc] initImageCell:[NSImage imageNamed:NSImageNameCaution]];
attachment = [NSTextAttachment new];
[attachment setAttachmentCell:cell];
strImage = [NSAttributedString attributedStringWithAttachment:attachment];
font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]];
strText = [[NSAttributedString alloc] initWithString:[NSString stringWithUTF8String:reason] attributes:[[font fontDescriptor] fontAttributes]];
str = [[NSMutableAttributedString alloc] initWithAttributedString:strImage];
[str appendAttributedString:strText];
[label setAttributedStringValue:str];
// step 2: set up the popover
NSPopover *popover;
NSViewController *vc;
vc = [NSViewController new];
[vc setView:label];
popover = [NSPopover new];
[popover setContentViewController:vc];
[label sizeToFit];
[popover setContentSize:[label frame].size];
// step 3: show the popover
// NSMaxYEdge is the bottom edge when looking (maximum edge in window coordinates)
[popover showRelativeToRect:NSZeroRect ofView:toNSView(textfield) preferredEdge:NSMaxYEdge];
// and beep
NSBeep();
return (id) popover;
}
void textfieldCloseInvalidPopover(id popover)
{
[toNSPopover(popover) close];
[toNSPopover(popover) release];
}
id newLabel(void)
{
NSTextField *l;
l = [[NSTextField alloc] initWithFrame:NSZeroRect];
[l setEditable:NO];
[l setSelectable:NO];
[l setDrawsBackground:NO];
return finishNewTextField((id) l, NO);
}
id newGroup(id container)
{
NSBox *group;
group = [[NSBox alloc] initWithFrame:NSZeroRect];
[group setBorderType:NSLineBorder];
[group setBoxType:NSBoxPrimary];
[group setTransparent:NO];
// can't use setSmallControlFont() here because the selector is different
[group setTitleFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]]];
[group setTitlePosition:NSAtTop];
[group setContentView:toNSView(container)];
return (id) group;
}
const char *groupText(id group)
{
return [[toNSBox(group) title] UTF8String];
}
void groupSetText(id group, char *text)
{
[toNSBox(group) setTitle:[NSString stringWithUTF8String:text]];
}