Skip to content

Add fixed positioning, and the ability to set and get a component size #332

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 26 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions common/controlsigs.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#define uiDateTimePickerSignature 0x44545069
#define uiEditableComboboxSignature 0x45644362
#define uiEntrySignature 0x456E7472
#define uiFixedSignature 0x46697864
#define uiFontButtonSignature 0x466F6E42
#define uiFormSignature 0x466F726D
#define uiGridSignature 0x47726964
Expand Down
1 change: 1 addition & 0 deletions darwin/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ list(APPEND _LIBUI_SOURCES
darwin/drawtext.m
darwin/editablecombo.m
darwin/entry.m
darwin/fixed.m
darwin/fontbutton.m
darwin/fontmatch.m
darwin/fonttraits.m
Expand Down
198 changes: 198 additions & 0 deletions darwin/fixed.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
// 15 august 2015
#import "uipriv_darwin.h"

@interface uiprivFixedChild : NSObject
@property uiControl *c;
@property int x;
@property int y;
- (NSView *)view;
@end

@interface uiprivFixedView : NSView {
uiFixed *b;
NSMutableArray *children;
}
- (id)initFixed:(uiFixed *)bb;
- (void)onDestroy;
- (void)syncEnableStates:(int)enabled;
- (void)append:(uiControl *)c x:(int)x y:(int)y;
- (void)move:(uiControl *)c x:(int)x y:(int)y;
- (void)reloadPositions;
@end

struct uiFixed {
uiDarwinControl c;
uiprivFixedView *view;
};

@implementation uiprivFixedChild

- (NSView *)view
{
return (NSView *) uiControlHandle(self.c);
}

@end

@implementation uiprivFixedView

- (id)initFixed:(uiFixed *)bb
{
self = [super initWithFrame:NSZeroRect];
self.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Always use Objective-C method syntax, even for superclass property getters and setters.

Put this line in the if block.

libui uses Auto Layout; uiprivFixedView should be controllable with Auto Layout, but its contents don't necessarily have to be. I have to figure out how this would work.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think the autoresizingMask is strictly necessary, I think I just added that when trying to debug why the components weren't being sized correctly.

if (self != nil) {
// the weird names vert and bb are to shut the compiler up about shadowing because implicit this/self is stupid
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to copy this comment over from the other files.

self->b = bb;
self->children = [NSMutableArray new];
}

return self;
}

- (BOOL)isFlipped
{
return YES;
}

- (void)onDestroy
{
uiprivFixedChild *bc;

for (bc in self->children) {
uiControlSetParent(bc.c, NULL);
uiDarwinControlSetSuperview(uiDarwinControl(bc.c), nil);
uiControlDestroy(bc.c);
}
[self->children release];
}

- (void)syncEnableStates:(int)enabled
{
uiprivFixedChild *bc;

for (bc in self->children)
uiDarwinControlSyncEnableState(uiDarwinControl(bc.c), enabled);
}

- (void)append:(uiControl *)c x:(int)x y:(int)y
{
uiprivFixedChild *bc;

bc = [uiprivFixedChild new];
bc.c = c;
bc.x = x;
bc.y = y;

uiControlSetParent(bc.c, uiControl(self->b));
uiDarwinControlSetSuperview(uiDarwinControl(bc.c), self);
uiDarwinControlSyncEnableState(uiDarwinControl(bc.c), uiControlEnabledToUser(uiControl(self->b)));

[self->children addObject:bc];

[self reloadPositions];

[bc release]; // we don't need the initial reference now
}

- (void)move:(uiControl *)c x:(int)x y:(int)y
{
uiprivFixedChild *fc;

for (fc in self->children) {
if (fc.c == c) {
fc.x = x;
fc.y = y;
[self reloadPositions];
return;
}
}
}

- (void)reloadPositions
{
uiprivFixedChild *fc;
CGPoint pos;
NSView *view;

for (fc in self->children) {
if (!uiControlVisible(fc.c))
continue;
pos = CGPointMake(fc.x, fc.y);
view = [fc view];
[view setFrame:(CGRect){.origin = pos, .size=view.frame.size}];
}
}

@end

static void uiFixedDestroy(uiControl *c)
{
uiFixed *b = uiFixed(c);

[b->view onDestroy];
[b->view release];
uiFreeControl(uiControl(b));
}

uiDarwinControlDefaultHandle(uiFixed, view)
uiDarwinControlDefaultParent(uiFixed, view)
uiDarwinControlDefaultSetParent(uiFixed, view)
uiDarwinControlDefaultToplevel(uiFixed, view)
uiDarwinControlDefaultVisible(uiFixed, view)
uiDarwinControlDefaultShow(uiFixed, view)
uiDarwinControlDefaultHide(uiFixed, view)
uiDarwinControlDefaultEnabled(uiFixed, view)
uiDarwinControlDefaultEnable(uiFixed, view)
uiDarwinControlDefaultDisable(uiFixed, view)

static void uiFixedSyncEnableState(uiDarwinControl *c, int enabled)
{
uiFixed *b = uiFixed(c);

if (uiDarwinShouldStopSyncEnableState(uiDarwinControl(b), enabled))
return;
[b->view syncEnableStates:enabled];
}

uiDarwinControlDefaultSetSuperview(uiFixed, view)

uiDarwinControlDefaultHuggingPriority(uiFixed, view)
uiDarwinControlDefaultSetHuggingPriority(uiFixed, view)
uiDarwinControlDefaultHugsTrailingEdge(uiFixed, view)
uiDarwinControlDefaultHugsBottom(uiFixed, view)
uiDarwinControlDefaultChildEdgeHuggingChanged(uiFixed, view)

static void uiuiprivFixedChildVisibilityChanged(uiDarwinControl *c)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One "ui" too much

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah I pushed so that I could check the changes in my VM. I'll fix that.

{
uiFixed *b = uiFixed(c);

[b->view reloadPositions];
}

void uiFixedAppend(uiFixed *b, uiControl *c, int x, int y)
{
// LONGTERM on other platforms
// or at leat allow this and implicitly turn it into a spacer
if (c == NULL)
userbug("You cannot add NULL to a uiFixed.");
[b->view append:c x:x y:y];
}

void uiFixedMove(uiFixed *b, uiControl *c, int x, int y)
{
// LONGTERM on other platforms
// or at leat allow this and implicitly turn it into a spacer
if (c == NULL)
userbug("You cannot move NULL to a uiFixed.");
[b->view move:c x:x y:y];
}

uiFixed *uiNewFixed(void)
{
uiFixed *f;
uiDarwinNewControl(uiFixed, f);

f->view = [[uiprivFixedView alloc] initFixed:f];

return f;
}
48 changes: 48 additions & 0 deletions darwin/main.m
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,41 @@
static BOOL (^isRunning)(void);
static BOOL stepsIsRunning;

@interface sizeWrapper : NSView {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is any of this necessary? You also are not properly initializing or uninitializing instances of these objects.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was weird to me also. When I used uiDarwinControlHandle and cast it to a NSView*, it complained about fixed not being a property. If I enclosed it in an interface that subclassed NSView, then it worked fine.

NSView *view;
}
- (id)addControl:(uiControl *)c;
- (CGRect)getSize;
- (void)setS:(CGSize)s;

@end

@implementation sizeWrapper

- (id)addControl:(uiControl *)c
{
view = (NSView *)uiControlHandle(c);
return self;
}

- (CGRect)getSize
{
return view.frame;
}

- (void)setS:(CGSize)s
{
CGRect bounds = view.bounds;
bounds.size = s;
view.bounds = bounds;

CGRect frame = view.frame;
frame.size = s;
view.frame = frame;
}

@end

@implementation applicationClass

- (void)sendEvent:(NSEvent *)e
Expand Down Expand Up @@ -243,3 +278,16 @@ void uiQueueMain(void (*f)(void *data), void *data)
// the signature of f matches dispatch_function_t
dispatch_async_f(dispatch_get_main_queue(), data, f);
}

void uiSize(uiControl *control, int *width, int *height)
{
CGRect size = [[[sizeWrapper alloc] addControl:control] getSize];
*width = size.size.width;
*height = size.size.height;
}

void uiSetSize(uiControl *control, int width, int height)
{
CGSize s = CGSizeMake(width, height);
[[[sizeWrapper alloc] addControl:control] setS:s];
}
11 changes: 11 additions & 0 deletions examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ _add_example(controlgallery
${_EXAMPLE_RESOURCES_RC}
)

_add_example(layout-test
layout-test/main.c
${_EXAMPLE_RESOURCES_RC}
)

_add_example(histogram
histogram/main.c
${_EXAMPLE_RESOURCES_RC}
Expand All @@ -42,9 +47,15 @@ _add_example(drawtext
${_EXAMPLE_RESOURCES_RC}
)

set_target_properties(layout-test PROPERTIES
OUTPUT_NAME layout-test
WIN32_EXECUTABLE FALSE
)

add_custom_target(examples
DEPENDS
controlgallery
histogram
cpp-multithread
layout-test
drawtext)
46 changes: 46 additions & 0 deletions examples/layout-test/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include <stdio.h>
#include <string.h>
#include "../../ui.h"

int main(void)
{
uiInitOptions options;
const char *err;

memset(&options, 0, sizeof (uiInitOptions));
err = uiInit(&options);
if (err != NULL) {
fprintf(stderr, "error initializing libui: %s", err);
uiFreeInitError(err);
return 1;
}

uiWindow *mainwin = uiNewWindow("Layout test", 640, 480, 1);

uiFixed *fixed = uiNewFixed();

uiWindowSetChild(mainwin, uiControl(fixed));

uiLabel *label = uiNewLabel("Hello");

uiFixedAppend(fixed, uiControl(label), 150, 200);

uiButton *button = uiNewButton("Button");

uiFixedAppend(fixed, uiControl(button), 50, 50);

uiControlShow(uiControl(mainwin));


int width, height;

uiFixedMove(fixed, uiControl(button), 0, 100);

uiSize(uiControl(button), &width, &height);
printf("Width: %d, Height: %d\n", width, height);

uiSetSize(uiControl(button), 50, 50);

uiMain();
return 0;
}
8 changes: 8 additions & 0 deletions ui.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ _UI_EXTERN void uiControlHide(uiControl *);
_UI_EXTERN int uiControlEnabled(uiControl *);
_UI_EXTERN void uiControlEnable(uiControl *);
_UI_EXTERN void uiControlDisable(uiControl *);
_UI_EXTERN void uiSize(uiControl *control, int *width, int *height);
_UI_EXTERN void uiSetSize(uiControl *control, int width, int height);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency, should these be names uiControlSize and uiControlSetSize, respectively?


_UI_EXTERN uiControl *uiAllocControl(size_t n, uint32_t OSsig, uint32_t typesig, const char *typenamestr);
_UI_EXTERN void uiFreeControl(uiControl *);
Expand Down Expand Up @@ -1110,6 +1112,12 @@ _UI_EXTERN int uiGridPadded(uiGrid *g);
_UI_EXTERN void uiGridSetPadded(uiGrid *g, int padded);
_UI_EXTERN uiGrid *uiNewGrid(void);

typedef struct uiFixed uiFixed;
#define uiFixed(this) ((uiFixed *) (this))
_UI_EXTERN void uiFixedAppend(uiFixed *g, uiControl *c, int x, int y);
_UI_EXTERN void uiFixedMove(uiFixed *g, uiControl *c, int x, int y);
_UI_EXTERN uiFixed *uiNewFixed(void);

#ifdef __cplusplus
}
#endif
Expand Down
Loading