mirror of
				https://github.com/davidgiven/fluxengine.git
				synced 2025-10-24 11:11:02 -07:00 
			
		
		
		
	
		
			
				
	
	
		
			293 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Objective-C
		
	
	
	
	
	
			
		
		
	
	
			293 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Objective-C
		
	
	
	
	
	
| // 15 august 2015
 | |
| #import "uipriv_darwin.h"
 | |
| 
 | |
| // TODO need to jiggle on tab change too (second page disabled tab label initially ambiguous)
 | |
| 
 | |
| @interface tabPage : NSObject {
 | |
| 	uiprivSingleChildConstraints constraints;
 | |
| 	int margined;
 | |
| 	NSView *view;		// the NSTabViewItem view itself
 | |
| 	NSObject *pageID;
 | |
| }
 | |
| @property uiControl *c;
 | |
| @property NSLayoutPriority oldHorzHuggingPri;
 | |
| @property NSLayoutPriority oldVertHuggingPri;
 | |
| - (id)initWithView:(NSView *)v pageID:(NSObject *)o;
 | |
| - (NSView *)childView;
 | |
| - (void)establishChildConstraints;
 | |
| - (void)removeChildConstraints;
 | |
| - (int)isMargined;
 | |
| - (void)setMargined:(int)m;
 | |
| @end
 | |
| 
 | |
| struct uiTab {
 | |
| 	uiDarwinControl c;
 | |
| 	NSTabView *tabview;
 | |
| 	NSMutableArray *pages;
 | |
| 	NSLayoutPriority horzHuggingPri;
 | |
| 	NSLayoutPriority vertHuggingPri;
 | |
| };
 | |
| 
 | |
| @implementation tabPage
 | |
| 
 | |
| - (id)initWithView:(NSView *)v pageID:(NSObject *)o
 | |
| {
 | |
| 	self = [super init];
 | |
| 	if (self != nil) {
 | |
| 		self->view = [v retain];
 | |
| 		self->pageID = [o retain];
 | |
| 	}
 | |
| 	return self;
 | |
| }
 | |
| 
 | |
| - (void)dealloc
 | |
| {
 | |
| 	[self removeChildConstraints];
 | |
| 	[self->view release];
 | |
| 	[self->pageID release];
 | |
| 	[super dealloc];
 | |
| }
 | |
| 
 | |
| - (NSView *)childView
 | |
| {
 | |
| 	return (NSView *) uiControlHandle(self.c);
 | |
| }
 | |
| 
 | |
| - (void)establishChildConstraints
 | |
| {
 | |
| 	[self removeChildConstraints];
 | |
| 	if (self.c == NULL)
 | |
| 		return;
 | |
| 	uiprivSingleChildConstraintsEstablish(&(self->constraints),
 | |
| 		self->view, [self childView],
 | |
| 		uiDarwinControlHugsTrailingEdge(uiDarwinControl(self.c)),
 | |
| 		uiDarwinControlHugsBottom(uiDarwinControl(self.c)),
 | |
| 		self->margined,
 | |
| 		@"uiTab page");
 | |
| }
 | |
| 
 | |
| - (void)removeChildConstraints
 | |
| {
 | |
| 	uiprivSingleChildConstraintsRemove(&(self->constraints), self->view);
 | |
| }
 | |
| 
 | |
| - (int)isMargined
 | |
| {
 | |
| 	return self->margined;
 | |
| }
 | |
| 
 | |
| - (void)setMargined:(int)m
 | |
| {
 | |
| 	self->margined = m;
 | |
| 	uiprivSingleChildConstraintsSetMargined(&(self->constraints), self->margined);
 | |
| }
 | |
| 
 | |
| @end
 | |
| 
 | |
| static void uiTabDestroy(uiControl *c)
 | |
| {
 | |
| 	uiTab *t = uiTab(c);
 | |
| 	tabPage *page;
 | |
| 
 | |
| 	// first remove all tab pages so we can destroy all the children
 | |
| 	while ([t->tabview numberOfTabViewItems] != 0)
 | |
| 		[t->tabview removeTabViewItem:[t->tabview tabViewItemAtIndex:0]];
 | |
| 	// then destroy all the children
 | |
| 	for (page in t->pages) {
 | |
| 		[page removeChildConstraints];
 | |
| 		uiControlSetParent(page.c, NULL);
 | |
| 		uiDarwinControlSetSuperview(uiDarwinControl(page.c), nil);
 | |
| 		uiControlDestroy(page.c);
 | |
| 	}
 | |
| 	// and finally destroy ourselves
 | |
| 	[t->pages release];
 | |
| 	[t->tabview release];
 | |
| 	uiFreeControl(uiControl(t));
 | |
| }
 | |
| 
 | |
| uiDarwinControlDefaultHandle(uiTab, tabview)
 | |
| uiDarwinControlDefaultParent(uiTab, tabview)
 | |
| uiDarwinControlDefaultSetParent(uiTab, tabview)
 | |
| uiDarwinControlDefaultToplevel(uiTab, tabview)
 | |
| uiDarwinControlDefaultVisible(uiTab, tabview)
 | |
| uiDarwinControlDefaultShow(uiTab, tabview)
 | |
| uiDarwinControlDefaultHide(uiTab, tabview)
 | |
| uiDarwinControlDefaultEnabled(uiTab, tabview)
 | |
| uiDarwinControlDefaultEnable(uiTab, tabview)
 | |
| uiDarwinControlDefaultDisable(uiTab, tabview)
 | |
| 
 | |
| static void uiTabSyncEnableState(uiDarwinControl *c, int enabled)
 | |
| {
 | |
| 	uiTab *t = uiTab(c);
 | |
| 	tabPage *page;
 | |
| 
 | |
| 	if (uiDarwinShouldStopSyncEnableState(uiDarwinControl(t), enabled))
 | |
| 		return;
 | |
| 	for (page in t->pages)
 | |
| 		uiDarwinControlSyncEnableState(uiDarwinControl(page.c), enabled);
 | |
| }
 | |
| 
 | |
| uiDarwinControlDefaultSetSuperview(uiTab, tabview)
 | |
| 
 | |
| static void tabRelayout(uiTab *t)
 | |
| {
 | |
| 	tabPage *page;
 | |
| 
 | |
| 	for (page in t->pages)
 | |
| 		[page establishChildConstraints];
 | |
| 	// and this gets rid of some weird issues with regards to box alignment
 | |
| 	uiprivJiggleViewLayout(t->tabview);
 | |
| }
 | |
| 
 | |
| BOOL uiTabHugsTrailingEdge(uiDarwinControl *c)
 | |
| {
 | |
| 	uiTab *t = uiTab(c);
 | |
| 
 | |
| 	return t->horzHuggingPri < NSLayoutPriorityWindowSizeStayPut;
 | |
| }
 | |
| 
 | |
| BOOL uiTabHugsBottom(uiDarwinControl *c)
 | |
| {
 | |
| 	uiTab *t = uiTab(c);
 | |
| 
 | |
| 	return t->vertHuggingPri < NSLayoutPriorityWindowSizeStayPut;
 | |
| }
 | |
| 
 | |
| static void uiTabChildEdgeHuggingChanged(uiDarwinControl *c)
 | |
| {
 | |
| 	uiTab *t = uiTab(c);
 | |
| 
 | |
| 	tabRelayout(t);
 | |
| }
 | |
| 
 | |
| static NSLayoutPriority uiTabHuggingPriority(uiDarwinControl *c, NSLayoutConstraintOrientation orientation)
 | |
| {
 | |
| 	uiTab *t = uiTab(c);
 | |
| 
 | |
| 	if (orientation == NSLayoutConstraintOrientationHorizontal)
 | |
| 		return t->horzHuggingPri;
 | |
| 	return t->vertHuggingPri;
 | |
| }
 | |
| 
 | |
| static void uiTabSetHuggingPriority(uiDarwinControl *c, NSLayoutPriority priority, NSLayoutConstraintOrientation orientation)
 | |
| {
 | |
| 	uiTab *t = uiTab(c);
 | |
| 
 | |
| 	if (orientation == NSLayoutConstraintOrientationHorizontal)
 | |
| 		t->horzHuggingPri = priority;
 | |
| 	else
 | |
| 		t->vertHuggingPri = priority;
 | |
| 	uiDarwinNotifyEdgeHuggingChanged(uiDarwinControl(t));
 | |
| }
 | |
| 
 | |
| static void uiTabChildVisibilityChanged(uiDarwinControl *c)
 | |
| {
 | |
| 	uiTab *t = uiTab(c);
 | |
| 
 | |
| 	tabRelayout(t);
 | |
| }
 | |
| 
 | |
| void uiTabAppend(uiTab *t, const char *name, uiControl *child)
 | |
| {
 | |
| 	uiTabInsertAt(t, name, [t->pages count], child);
 | |
| }
 | |
| 
 | |
| void uiTabInsertAt(uiTab *t, const char *name, int n, uiControl *child)
 | |
| {
 | |
| 	tabPage *page;
 | |
| 	NSView *view;
 | |
| 	NSTabViewItem *i;
 | |
| 	NSObject *pageID;
 | |
| 
 | |
| 	uiControlSetParent(child, uiControl(t));
 | |
| 
 | |
| 	view = [[[NSView alloc] initWithFrame:NSZeroRect] autorelease];
 | |
| 	// note: if we turn off the autoresizing mask, nothing shows up
 | |
| 	uiDarwinControlSetSuperview(uiDarwinControl(child), view);
 | |
| 	uiDarwinControlSyncEnableState(uiDarwinControl(child), uiControlEnabledToUser(uiControl(t)));
 | |
| 
 | |
| 	// the documentation says these can be nil but the headers say these must not be; let's be safe and make them non-nil anyway
 | |
| 	pageID = [NSObject new];
 | |
| 	page = [[[tabPage alloc] initWithView:view pageID:pageID] autorelease];
 | |
| 	page.c = child;
 | |
| 
 | |
| 	// don't hug, just in case we're a stretchy tab
 | |
| 	page.oldHorzHuggingPri = uiDarwinControlHuggingPriority(uiDarwinControl(page.c), NSLayoutConstraintOrientationHorizontal);
 | |
| 	page.oldVertHuggingPri = uiDarwinControlHuggingPriority(uiDarwinControl(page.c), NSLayoutConstraintOrientationVertical);
 | |
| 	uiDarwinControlSetHuggingPriority(uiDarwinControl(page.c), NSLayoutPriorityDefaultLow, NSLayoutConstraintOrientationHorizontal);
 | |
| 	uiDarwinControlSetHuggingPriority(uiDarwinControl(page.c), NSLayoutPriorityDefaultLow, NSLayoutConstraintOrientationVertical);
 | |
| 
 | |
| 	[t->pages insertObject:page atIndex:n];
 | |
| 
 | |
| 	i = [[[NSTabViewItem alloc] initWithIdentifier:pageID] autorelease];
 | |
| 	[i setLabel:uiprivToNSString(name)];
 | |
| 	[i setView:view];
 | |
| 	[t->tabview insertTabViewItem:i atIndex:n];
 | |
| 
 | |
| 	tabRelayout(t);
 | |
| }
 | |
| 
 | |
| void uiTabDelete(uiTab *t, int n)
 | |
| {
 | |
| 	tabPage *page;
 | |
| 	uiControl *child;
 | |
| 	NSTabViewItem *i;
 | |
| 
 | |
| 	page = (tabPage *) [t->pages objectAtIndex:n];
 | |
| 
 | |
| 	uiDarwinControlSetHuggingPriority(uiDarwinControl(page.c), page.oldHorzHuggingPri, NSLayoutConstraintOrientationHorizontal);
 | |
| 	uiDarwinControlSetHuggingPriority(uiDarwinControl(page.c), page.oldVertHuggingPri, NSLayoutConstraintOrientationVertical);
 | |
| 
 | |
| 	child = page.c;
 | |
| 	[page removeChildConstraints];
 | |
| 	[t->pages removeObjectAtIndex:n];
 | |
| 
 | |
| 	uiControlSetParent(child, NULL);
 | |
| 	uiDarwinControlSetSuperview(uiDarwinControl(child), nil);
 | |
| 
 | |
| 	i = [t->tabview tabViewItemAtIndex:n];
 | |
| 	[t->tabview removeTabViewItem:i];
 | |
| 
 | |
| 	tabRelayout(t);
 | |
| }
 | |
| 
 | |
| int uiTabNumPages(uiTab *t)
 | |
| {
 | |
| 	return [t->pages count];
 | |
| }
 | |
| 
 | |
| int uiTabMargined(uiTab *t, int n)
 | |
| {
 | |
| 	tabPage *page;
 | |
| 
 | |
| 	page = (tabPage *) [t->pages objectAtIndex:n];
 | |
| 	return [page isMargined];
 | |
| }
 | |
| 
 | |
| void uiTabSetMargined(uiTab *t, int n, int margined)
 | |
| {
 | |
| 	tabPage *page;
 | |
| 
 | |
| 	page = (tabPage *) [t->pages objectAtIndex:n];
 | |
| 	[page setMargined:margined];
 | |
| }
 | |
| 
 | |
| uiTab *uiNewTab(void)
 | |
| {
 | |
| 	uiTab *t;
 | |
| 
 | |
| 	uiDarwinNewControl(uiTab, t);
 | |
| 
 | |
| 	t->tabview = [[NSTabView alloc] initWithFrame:NSZeroRect];
 | |
| 	// also good for NSTabView (same selector and everything)
 | |
| 	uiDarwinSetControlFont((NSControl *) (t->tabview), NSRegularControlSize);
 | |
| 
 | |
| 	t->pages = [NSMutableArray new];
 | |
| 
 | |
| 	// default to low hugging to not hug edges
 | |
| 	t->horzHuggingPri = NSLayoutPriorityDefaultLow;
 | |
| 	t->vertHuggingPri = NSLayoutPriorityDefaultLow;
 | |
| 
 | |
| 	return t;
 | |
| }
 |