-
Notifications
You must be signed in to change notification settings - Fork 622
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
base: master
Are you sure you want to change the base?
Changes from 15 commits
4d049e7
6e13520
eb2cf91
12b4e09
9420237
1e0e131
8f3d3e9
0d52537
7ed39c3
c2ab097
8ce458d
c82d891
66095ae
c839153
84f81c2
452742f
fbabdff
1def874
11710e4
570f7e0
9bbc402
5d4f9f7
c89fc32
cb1fae6
3c326ee
1ed637a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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; | ||
if (self != nil) { | ||
// the weird names vert and bb are to shut the compiler up about shadowing because implicit this/self is stupid | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One "ui" too much There was a problem hiding this comment. Choose a reason for hiding this commentThe 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; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,41 @@ | |
static BOOL (^isRunning)(void); | ||
static BOOL stepsIsRunning; | ||
|
||
@interface sizeWrapper : NSView { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||
|
@@ -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]; | ||
} |
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; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 *); | ||
|
@@ -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 | ||
|
There was a problem hiding this comment.
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.There was a problem hiding this comment.
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.