Implemented proper hiding and showing behavior on OS X on uiForm and uiGrid.

This commit is contained in:
Pietro Gagliardi 2016-06-14 11:18:38 -04:00
parent 44b4fa9c68
commit cb81518e0f
4 changed files with 101 additions and 26 deletions

View File

@ -16,7 +16,10 @@ This README is being written.<br>
## Updates
*Note that today's entry may be updated later today.*
*Note that today's entry may be updated later today Eastern Time.*
* **14 June 2016**
* uiDarwinControl now has a `ChildVisibilityChanged()` method and a corresponding `NotifyVisibilityChanged()` function that is called by the default show/hide handlers. This is used to make visibility changes work on OS X; uiBox, uiForm, and uiGrid all respect these now.
* **13 June 2016**
* `intmax_t` and `uintmax_t` are no longer used for libui API functions; now we use `int`. This should make things much easier for bindings. `int` should be at least 32 bits wide; this should be sufficient for all but the most extreme cases.

View File

@ -23,7 +23,6 @@
uiForm *f;
NSMutableArray *children;
int padded;
int nStretchy;
NSLayoutConstraint *first;
NSMutableArray *inBetweens;
@ -45,6 +44,7 @@
- (void)setPadded:(int)p;
- (BOOL)hugsTrailing;
- (BOOL)hugsBottom;
- (int)nStretchy;
@end
struct uiForm {
@ -123,7 +123,6 @@ struct uiForm {
self->f = ff;
self->padded = 0;
self->children = [NSMutableArray new];
self->nStretchy = 0;
self->inBetweens = [NSMutableArray new];
self->widths = [NSMutableArray new];
@ -221,6 +220,9 @@ struct uiForm {
// first arrange the children vertically and make them the same width
prev = nil;
for (fc in self->children) {
[fc setHidden:!uiControlVisible(fc.c)];
if (!uiControlVisible(fc.c))
continue;
if (prev == nil) { // first view
self->first = mkConstraint(self, NSLayoutAttributeTop,
NSLayoutRelationEqual,
@ -259,6 +261,8 @@ struct uiForm {
prev = [fc view];
prevlabel = fc;
}
if (prev == nil) // all hidden; act as if nothing there
return;
self->last = mkConstraint(prev, NSLayoutAttributeBottom,
NSLayoutRelationEqual,
self, NSLayoutAttributeBottom,
@ -269,6 +273,8 @@ struct uiForm {
// now arrange the controls horizontally
for (fc in self->children) {
if (!uiControlVisible(fc.c))
continue;
c = mkConstraint(self, NSLayoutAttributeLeading,
NSLayoutRelationEqual,
fc, NSLayoutAttributeLeading,
@ -313,6 +319,8 @@ struct uiForm {
// and make all stretchy controls have the same height
prev = nil;
for (fc in self->children) {
if (!uiControlVisible(fc.c))
continue;
if (!fc.stretchy)
continue;
if (prev == nil) {
@ -375,15 +383,13 @@ struct uiForm {
@"uiForm baseline constraint");
[self addConstraint:fc.baseline];
oldnStretchy = [self nStretchy];
[self->children addObject:fc];
[self establishOurConstraints];
if (fc.stretchy) {
oldnStretchy = self->nStretchy;
self->nStretchy++;
if (fc.stretchy)
if (oldnStretchy == 0)
uiDarwinNotifyEdgeHuggingChanged(uiDarwinControl(self->f));
}
[fc release]; // we don't need the initial reference now
}
@ -416,7 +422,22 @@ struct uiForm {
- (BOOL)hugsBottom
{
// only hug if we have stretchy
return self->nStretchy != 0;
return [self nStretchy] != 0;
}
- (int)nStretchy
{
formChild *fc;
int n;
n = 0;
for (fc in self->children) {
if (!uiControlVisible(fc.c))
continue;
if (fc.stretchy)
n++;
}
return n;
}
@end

View File

@ -25,8 +25,6 @@
uiGrid *g;
NSMutableArray *children;
int padded;
int nhexpand;
int nvexpand;
NSMutableArray *edges;
NSMutableArray *inBetweens;
@ -45,6 +43,8 @@
- (void)setPadded:(int)p;
- (BOOL)hugsTrailing;
- (BOOL)hugsBottom;
- (int)nhexpand;
- (int)nvexpand;
@end
struct uiGrid {
@ -70,8 +70,6 @@ struct uiGrid {
self->g = gg;
self->padded = 0;
self->children = [NSMutableArray new];
self->nhexpand = 0;
self->nvexpand = 0;
self->edges = [NSMutableArray new];
self->inBetweens = [NSMutableArray new];
@ -132,6 +130,7 @@ struct uiGrid {
return uiDarwinPaddingAmount(NULL);
}
// LONGTERM stop early if all controls are hidden
- (void)establishOurConstraints
{
gridChild *gc;
@ -156,8 +155,11 @@ struct uiGrid {
padding = [self paddingAmount];
// first, figure out the minimum and maximum row and column numbers
// ignore hidden controls
first = YES;
for (gc in self->children) {
if (!uiControlVisible(gc.c))
continue;
if (first) {
xmin = gc.left;
ymin = gc.top;
@ -180,6 +182,7 @@ struct uiGrid {
// now build a topological map of the grid gg[y][x]
// also figure out which cells contain spanned views so they can be ignored later
// treat hidden controls by keeping the indices -1
gg = (int **) uiAlloc(ycount * sizeof (int *), "int[][]");
gspan = (BOOL **) uiAlloc(ycount * sizeof (BOOL *), "BOOL[][]");
for (y = 0; y < ycount; y++) {
@ -190,6 +193,8 @@ struct uiGrid {
}
for (i = 0; i < [self->children count]; i++) {
gc = (gridChild *) [self->children objectAtIndex:i];
if (!uiControlVisible(gc.c))
continue;
for (y = gc.top; y < gc.top + gc.yspan; y++)
for (x = gc.left; x < gc.left + gc.xspan; x++) {
gg[y - ymin][x - xmin] = i;
@ -255,6 +260,8 @@ struct uiGrid {
vexpand = (BOOL *) uiAlloc(ycount * sizeof (BOOL), "BOOL[]");
// first, which don't span
for (gc in self->children) {
if (!uiControlVisible(gc.c))
continue;
if (gc.hexpand && gc.xspan == 1)
hexpand[gc.left - xmin] = YES;
if (gc.vexpand && gc.yspan == 1)
@ -263,6 +270,8 @@ struct uiGrid {
// second, which do span
// the way we handle this is simple: if none of the spanned rows/columns expand, make all rows/columns expand
for (gc in self->children) {
if (!uiControlVisible(gc.c))
continue;
if (gc.hexpand && gc.xspan != 1) {
doit = YES;
for (x = gc.left; x < gc.left + gc.xspan; x++)
@ -391,6 +400,8 @@ struct uiGrid {
for (gc in self->children) {
NSLayoutPriority priority;
if (!uiControlVisible(gc.c))
continue;
if (hexpand[gc.left - xmin] || gc.xspan != 1)
priority = NSLayoutPriorityDefaultLow;
else
@ -422,7 +433,7 @@ struct uiGrid {
- (void)append:(gridChild *)gc
{
BOOL update;
int oldn;
int oldnh, oldnv;
uiControlSetParent(gc.c, uiControl(self->g));
uiDarwinControlSetSuperview(uiDarwinControl(gc.c), self);
@ -430,22 +441,18 @@ struct uiGrid {
// no need to set priority here; that's done in establishOurConstraints
oldnh = [self nhexpand];
oldnv = [self nvexpand];
[self->children addObject:gc];
[self establishOurConstraints];
update = NO;
if (gc.hexpand) {
oldn = self->nhexpand;
self->nhexpand++;
if (oldn == 0)
if (gc.hexpand)
if (oldnh == 0)
update = YES;
}
if (gc.vexpand) {
oldn = self->nvexpand;
self->nvexpand++;
if (oldn == 0)
if (gc.vexpand)
if (oldnv == 0)
update = YES;
}
if (update)
uiDarwinNotifyEdgeHuggingChanged(uiDarwinControl(self->g));
@ -524,13 +531,43 @@ dispatch_get_main_queue(),
- (BOOL)hugsTrailing
{
// only hug if we have horizontally expanding
return self->nhexpand != 0;
return [self nhexpand] != 0;
}
- (BOOL)hugsBottom
{
// only hug if we have vertically expanding
return self->nvexpand != 0;
return [self nvexpand] != 0;
}
- (int)nhexpand
{
gridChild *gc;
int n;
n = 0;
for (gc in self->children) {
if (!uiControlVisible(gc.c))
continue;
if (gc.hexpand)
n++;
}
return n;
}
- (int)nvexpand
{
gridChild *gc;
int n;
n = 0;
for (gc in self->children) {
if (!uiControlVisible(gc.c))
continue;
if (gc.vexpand)
n++;
}
return n;
}
@end

View File

@ -65,6 +65,16 @@ static void entryChanged(uiEntry *e, void *data)
uiFreeText(text);
}
static void showHide(uiButton *b, void *data)
{
uiControl *c = uiControl(data);
if (uiControlVisible(c))
uiControlHide(c);
else
uiControlShow(c);
}
uiBox *makePage13(void)
{
uiBox *page13;
@ -95,7 +105,6 @@ uiBox *makePage13(void)
uiBoxAppend(page13, uiControl(b), 0);
f = newForm();
uiBoxAppend(page13, uiControl(f), 1);
e = uiNewPasswordEntry();
uiEntryOnChanged(e, entryChanged, "password");
@ -107,5 +116,10 @@ uiBox *makePage13(void)
uiFormAppend(f, "MLE", uiControl(uiNewMultilineEntry()), 1);
b = uiNewButton("Show/Hide");
uiButtonOnClicked(b, showHide, e);
uiBoxAppend(page13, uiControl(b), 0);
uiBoxAppend(page13, uiControl(f), 1);
return page13;
}