diff --git a/button_darwin.m b/button_darwin.m index d4b2a2b3..d422718d 100644 --- a/button_darwin.m +++ b/button_darwin.m @@ -1,30 +1,19 @@ // 7 april 2015 #import "uipriv_darwin.h" -#ifdef uiLogAllocations -@interface loggingNSButton : NSButton +@interface uiNSButton : NSButton +@property uiControl *uiC; +@property void (*uiOnClicked)(uiControl *, void *); +@property void *uiOnClickedData; +@property NSMutableArray *uiFreeList; @end -@implementation loggingNSButton +@implementation uiNSButton -uiLogObjCClassAllocations +uiLogObjCClassAllocations(uiDoFreeOnDealloc(self.uiFreeList);) +uiFreeOnDeallocImpl -@end -#else -#define loggingNSButton NSButton -#endif - -@interface button : NSObject -@property uiControl *c; -@property void (*onClicked)(uiControl *, void *); -@property void *onClickedData; -@end - -@implementation button - -uiLogObjCClassAllocations - -- (IBAction)buttonClicked:(id)sender +- (IBAction)uiButtonClicked:(id)sender { (*(self.onClicked))(self.c, self.onClickedData); } @@ -39,21 +28,21 @@ static void defaultOnClicked(uiControl *c, void *data) // TODO destruction uiControl *uiNewButton(const char *text) { - button *b; - NSButton *bb; + uiControl *c; + uiNSButton *b; - b = [button new]; - b.c = uiDarwinNewControl([loggingNSButton class], NO, NO, b); + c = uiDarwinNewControl([uiNSButton class], NO, NO, NULL); + b = (uiNSButton *) uiControlHandle(c); + b.c = c; - bb = (NSButton *) uiControlHandle(b.c); - [bb setTitle:toNSString(text)]; - [bb setButtonType:NSMomentaryPushInButton]; - [bb setBordered:YES]; - [bb setBezelStyle:NSRoundedBezelStyle]; + [b setTitle:toNSString(text)]; + [b setButtonType:NSMomentaryPushInButton]; + [b setBordered:YES]; + [b setBezelStyle:NSRoundedBezelStyle]; setStandardControlFont((NSControl *) bb); - [bb setTarget:b]; - [bb setAction:@selector(buttonClicked:)]; + [b setTarget:b]; + [b setAction:@selector(uiButtonClicked:)]; b.onClicked = defaultOnClicked; @@ -66,7 +55,7 @@ void uiButtonOnClicked(uiControl *c, void (*f)(uiControl *, void *), void *data) { button *b; - b = (button *) uiDarwinControlData(c); + b = (uiNSButton *) uiControlHandle(c); b.onClicked = f; b.onClickedData = data; } diff --git a/container_darwin.m b/container_darwin.m index f869f2cb..af1acee5 100644 --- a/container_darwin.m +++ b/container_darwin.m @@ -10,7 +10,10 @@ // thanks to mikeash and JtRip in irc.freenode.net/#macdev @implementation uiContainer -uiLogObjCClassAllocations +uiLogObjCClassAllocations( + if (self.child != NULL) + uiControlDestroy(self.child); +) - (void)setFrameSize:(NSSize)s { diff --git a/init_darwin.m b/init_darwin.m index d26c3fa5..bd27dee8 100644 --- a/init_darwin.m +++ b/init_darwin.m @@ -6,7 +6,7 @@ @implementation uiApplication -uiLogObjCClassAllocations +uiLogObjCClassAllocations() // hey look! we're overriding terminate:! // we're going to make sure we can go back to main() whether Cocoa likes it or not! diff --git a/newcontrol_darwin.m b/newcontrol_darwin.m index 9b9dd7bc..5a346f1b 100644 --- a/newcontrol_darwin.m +++ b/newcontrol_darwin.m @@ -13,6 +13,11 @@ struct uiSingleViewControl { #define S(c) ((uiSingleViewControl *) (c)) +static void singleDestroy(uiControl *c) +{ + [S(c)->view release]; +} + static uintptr_t singleHandle(uiControl *c) { return (uintptr_t) (S(c)->view); @@ -59,6 +64,7 @@ static void singleResize(uiControl *c, intmax_t x, intmax_t y, intmax_t width, i uiControl *uiDarwinNewControl(Class class, BOOL inScrollView, BOOL scrollViewHasBorder, void *data) { uiSingleViewControl *c; + uiFreeOnDealloc *freer; c = uiNew(uiSingleViewControl); // thanks to autoxr and arwyn in irc.freenode.net/#macdev @@ -79,6 +85,7 @@ uiControl *uiDarwinNewControl(Class class, BOOL inScrollView, BOOL scrollViewHas c->immediate = (NSView *) (c->scrollView); } + c->control.destroy = singleDestroy; c->control.handle = singleHandle; c->control.setParent = singleSetParent; c->control.preferredSize = singlePreferredSize; @@ -86,6 +93,9 @@ uiControl *uiDarwinNewControl(Class class, BOOL inScrollView, BOOL scrollViewHas c->data = data; + freer = (uiFreeOnDealloc *) (c->view); + [freer uiFreeOnDealloc:c]; + return (uiControl *) c; } diff --git a/uipriv_darwin.h b/uipriv_darwin.h index 514297cb..5e8c82e4 100644 --- a/uipriv_darwin.h +++ b/uipriv_darwin.h @@ -14,7 +14,7 @@ struct uiSizing { // TODO see if we can override alloc instead #ifdef uiLogAllocations #import -#define uiLogObjCClassAllocations \ +#define uiLogObjCClassAllocations(deallocCode) \ + (id)alloc \ { \ id thing; \ @@ -24,15 +24,32 @@ struct uiSizing { } \ - (void)dealloc \ { \ + deallocCode \ [super dealloc]; \ fprintf(stderr, "%p free\n", self); \ } #else -#define uiLogObjCClassAllocations +#define uiLogObjCClassAllocations(deallocCode) \ +- (void)dealloc \ +{ \ + deallocCode \ + [super dealloc]; \ +} #endif // util_darwin.m extern void setStandardControlFont(NSControl *); +@protocol uiFreeOnDealloc +- (void)uiFreeOnDealloc:(void *)p; +@end +#define uiFreeOnDeallocImpl \ +- (void)uiFreeOnDealloc:(void *)p \ +{ \ + if (self.uiFreeList == nil) \ + self.uiFreeList = [NSMutableArray new]; \ + [self.uiFreeList addObject:[NSValue valueWIthPointer:p]]; \ +} +extern void uiDoFreeOnDealloc(NSMutableArray *); // container_darwin.m @interface uiContainer : NSView diff --git a/util_darwin.m b/util_darwin.m index d8166e95..4ed562aa 100644 --- a/util_darwin.m +++ b/util_darwin.m @@ -6,3 +6,13 @@ void setStandardControlFont(NSControl *control) { [control setFont:[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]]]; } + +void uiDoFreeOnDealloc(NSMutableArray *m) +{ + [m enumerateObjectsUsingBlock:^(id obj, NSUInteger index, BOOL *stop) { + NSValue *v = (NSValue *) obj; + + uiFree([v pointerValue]); + }]; + [m release]; +} diff --git a/window_darwin.m b/window_darwin.m index 8d582c39..ad5506a2 100644 --- a/window_darwin.m +++ b/window_darwin.m @@ -10,7 +10,7 @@ @implementation loggingNSWindow -uiLogObjCClassAllocations +uiLogObjCClassAllocations() @end #else @@ -25,7 +25,7 @@ uiLogObjCClassAllocations @implementation uiWindowDelegate -uiLogObjCClassAllocations +uiLogObjCClassAllocations() - (BOOL)windowShouldClose:(id)win {