Converted uiRadioButtons on OS X to use a NSView of NSButtons instead of NSMatrix; the latter was deprecated on 10.8 and has lots of little quirks that made it annoying to use.
This commit is contained in:
parent
46a280cf46
commit
2c0e333ca0
|
@ -110,6 +110,7 @@ uiCheckbox *uiNewCheckbox(const char *text)
|
||||||
|
|
||||||
uiDarwinNewControl(uiCheckbox, c);
|
uiDarwinNewControl(uiCheckbox, c);
|
||||||
|
|
||||||
|
// TODO bezel style? transparent?
|
||||||
c->button = [[NSButton alloc] initWithFrame:NSZeroRect];
|
c->button = [[NSButton alloc] initWithFrame:NSZeroRect];
|
||||||
[c->button setTitle:toNSString(text)];
|
[c->button setTitle:toNSString(text)];
|
||||||
[c->button setButtonType:NSSwitchButton];
|
[c->button setButtonType:NSSwitchButton];
|
||||||
|
|
|
@ -1,68 +1,130 @@
|
||||||
// 14 august 2015
|
// 14 august 2015
|
||||||
#import "uipriv_darwin.h"
|
#import "uipriv_darwin.h"
|
||||||
|
|
||||||
// TODO the selection should NOT be lost when starting a new drag
|
// In the old days you would use a NSMatrix for this; as of OS X 10.8 this was deprecated and now you need just a bunch of NSButtons with the same superview AND same action method.
|
||||||
|
// This is documented on the NSMatrix page, but the rest of the OS X documentation says to still use NSMatrix.
|
||||||
|
// NSMatrix has weird quirks anyway...
|
||||||
|
// TODO verify this works on 10.7.
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
// - check that multiple radio buttons on the same parent container work right
|
||||||
|
// - 6 units of spacing between buttons, as suggested by Interface Builder?
|
||||||
|
|
||||||
struct uiRadioButtons {
|
struct uiRadioButtons {
|
||||||
uiDarwinControl c;
|
uiDarwinControl c;
|
||||||
NSMatrix *matrix;
|
NSView *view;
|
||||||
|
NSMutableArray *buttons;
|
||||||
|
NSMutableArray *constraints;
|
||||||
|
NSLayoutConstraint *lastv;
|
||||||
};
|
};
|
||||||
|
|
||||||
uiDarwinControlAllDefaults(uiRadioButtons, matrix)
|
uiDarwinControlAllDefaultsExceptDestroy(uiRadioButtons, view)
|
||||||
|
|
||||||
static NSButtonCell *cellAt(uiRadioButtons *r, uintmax_t n)
|
static void uiRadioButtonsDestroy(uiControl *c)
|
||||||
{
|
{
|
||||||
return (NSButtonCell *) [r->matrix cellAtRow:n column:0];
|
uiRadioButtons *r = uiRadioButtons(c);
|
||||||
|
NSButton *b;
|
||||||
|
|
||||||
|
// drop the constraints
|
||||||
|
[r->view removeConstraints:r->constraints];
|
||||||
|
[r->constraints release];
|
||||||
|
if (r->lastv != nil)
|
||||||
|
[r->lastv release];
|
||||||
|
// destroy the buttons
|
||||||
|
for (b in r->buttons)
|
||||||
|
[b removeFromSuperview];
|
||||||
|
[r->buttons release];
|
||||||
|
// and destroy ourselves
|
||||||
|
[r->view release];
|
||||||
|
uiFreeControl(uiControl(r));
|
||||||
|
}
|
||||||
|
|
||||||
|
static NSButton *buttonAt(uiRadioButtons *r, uintmax_t n)
|
||||||
|
{
|
||||||
|
return (NSButton *) [r->buttons objectAtIndex:n];
|
||||||
}
|
}
|
||||||
|
|
||||||
void uiRadioButtonsAppend(uiRadioButtons *r, const char *text)
|
void uiRadioButtonsAppend(uiRadioButtons *r, const char *text)
|
||||||
{
|
{
|
||||||
intmax_t prevSelection;
|
NSButton *b, *b2;
|
||||||
|
NSLayoutConstraint *constraint;
|
||||||
|
|
||||||
// renewRows:columns: will reset the selection
|
// TODO bezel style? transparent?
|
||||||
prevSelection = [r->matrix selectedRow];
|
b = [[NSButton alloc] initWithFrame:NSZeroRect];
|
||||||
|
[b setTitle:toNSString(text)];
|
||||||
|
[b setButtonType:NSRadioButton];
|
||||||
|
[b setBordered:NO];
|
||||||
|
uiDarwinSetControlFont(b, NSRegularControlSize);
|
||||||
|
[b setTranslatesAutoresizingMaskIntoConstraints:NO];
|
||||||
|
|
||||||
[r->matrix renewRows:([r->matrix numberOfRows] + 1) columns:1];
|
// TODO set target
|
||||||
[cellAt(r, [r->matrix numberOfRows] - 1) setTitle:toNSString(text)];
|
[b setAction:@selector(onClicked:)];
|
||||||
|
|
||||||
// this will definitely cause a resize in at least the vertical direction, even if not in the horizontal
|
[r->buttons addObject:b];
|
||||||
// DO NOT CALL sizeToCells! this will glitch out; see http://stackoverflow.com/questions/32162562/dynamically-adding-cells-to-a-nsmatrix-laid-out-with-auto-layout-has-weird-effec
|
[r->view addSubview:b];
|
||||||
|
|
||||||
// and renew the previous selection
|
// pin horizontally to the edges of the superview
|
||||||
// we need to turn on allowing empty selection for this to work properly on the initial state
|
constraint = mkConstraint(b, NSLayoutAttributeLeading,
|
||||||
// TODO this doesn't actually work
|
NSLayoutRelationEqual,
|
||||||
[r->matrix setAllowsEmptySelection:YES];
|
r->view, NSLayoutAttributeLeading,
|
||||||
[r->matrix selectCellAtRow:prevSelection column:0];
|
1, 0,
|
||||||
[r->matrix setAllowsEmptySelection:NO];
|
@"uiRadioButtons button leading constraint");
|
||||||
|
[r->view addConstraint:constraint];
|
||||||
|
[r->constraints addObject:constraint];
|
||||||
|
constraint = mkConstraint(b, NSLayoutAttributeTrailing,
|
||||||
|
NSLayoutRelationEqual,
|
||||||
|
r->view, NSLayoutAttributeTrailing,
|
||||||
|
1, 0,
|
||||||
|
@"uiRadioButtons button trailing constraint");
|
||||||
|
[r->view addConstraint:constraint];
|
||||||
|
[r->constraints addObject:constraint];
|
||||||
|
|
||||||
|
// if this is the first view, pin it to the top
|
||||||
|
// otherwise pin to the bottom of the last
|
||||||
|
if ([r->buttons count] == 1)
|
||||||
|
constraint = mkConstraint(b, NSLayoutAttributeTop,
|
||||||
|
NSLayoutRelationEqual,
|
||||||
|
r->view, NSLayoutAttributeTop,
|
||||||
|
1, 0,
|
||||||
|
@"uiRadioButtons first button top constraint");
|
||||||
|
else {
|
||||||
|
b2 = buttonAt(r, [r->buttons count] - 2);
|
||||||
|
constraint = mkConstraint(b, NSLayoutAttributeTop,
|
||||||
|
NSLayoutRelationEqual,
|
||||||
|
b2, NSLayoutAttributeBottom,
|
||||||
|
1, 0,
|
||||||
|
@"uiRadioButtons non-first button top constraint");
|
||||||
|
}
|
||||||
|
[r->view addConstraint:constraint];
|
||||||
|
[r->constraints addObject:constraint];
|
||||||
|
|
||||||
|
// if there is a previous bottom constraint, remove it
|
||||||
|
if (r->lastv != nil) {
|
||||||
|
[r->view removeConstraint:r->lastv];
|
||||||
|
[r->constraints removeObject:r->lastv];
|
||||||
|
[r->lastv release];
|
||||||
|
}
|
||||||
|
|
||||||
|
// and make the new bottom constraint
|
||||||
|
r->lastv = mkConstraint(b, NSLayoutAttributeBottom,
|
||||||
|
NSLayoutRelationEqual,
|
||||||
|
r->view, NSLayoutAttributeBottom,
|
||||||
|
1, 0,
|
||||||
|
@"uiRadioButtons last button bottom constraint");
|
||||||
|
[r->view addConstraint:r->lastv];
|
||||||
|
[r->constraints addObject:r->lastv];
|
||||||
|
[r->lastv retain];
|
||||||
}
|
}
|
||||||
|
|
||||||
uiRadioButtons *uiNewRadioButtons(void)
|
uiRadioButtons *uiNewRadioButtons(void)
|
||||||
{
|
{
|
||||||
uiRadioButtons *r;
|
uiRadioButtons *r;
|
||||||
NSButtonCell *cell;
|
|
||||||
|
|
||||||
uiDarwinNewControl(uiRadioButtons, r);
|
uiDarwinNewControl(uiRadioButtons, r);
|
||||||
|
|
||||||
// we have to set up the NSMatrix this way (prototype first)
|
r->view = [[NSView alloc] initWithFrame:NSZeroRect];
|
||||||
// otherwise we won't be able to change its properties (such as the button type)
|
r->buttons = [NSMutableArray new];
|
||||||
cell = [NSButtonCell new];
|
r->constraints = [NSMutableArray new];
|
||||||
[cell setButtonType:NSRadioButton];
|
|
||||||
// works on NSCells too (same selector)
|
|
||||||
uiDarwinSetControlFont((NSControl *) cell, NSRegularControlSize);
|
|
||||||
|
|
||||||
r->matrix = [[NSMatrix alloc] initWithFrame:NSZeroRect
|
|
||||||
mode:NSRadioModeMatrix
|
|
||||||
prototype:cell
|
|
||||||
numberOfRows:0
|
|
||||||
numberOfColumns:0];
|
|
||||||
// we manually twiddle this property to allow programmatic non-selection state
|
|
||||||
[r->matrix setAllowsEmptySelection:NO];
|
|
||||||
[r->matrix setSelectionByRect:YES];
|
|
||||||
[r->matrix setIntercellSpacing:NSMakeSize(4, 2)];
|
|
||||||
[r->matrix setAutorecalculatesCellSize:YES];
|
|
||||||
[r->matrix setDrawsBackground:NO];
|
|
||||||
[r->matrix setDrawsCellBackground:NO];
|
|
||||||
[r->matrix setAutosizesCells:YES];
|
|
||||||
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue