Mercurial > dwindows
comparison mac/dw.m @ 928:43a5b3c78c41
Two fixes... the first is on the fly calculation of groupbox border size. This also fixes some initial window issues...
because the groupbox border height couldn't be calculated until it was size. So first time we size the groupbox to
100x100 and calculate the border size... then the title calculation also works since it has been sized.
Second is the first major update to the layout engine in probably 10 years. The layout engine has now been
divided into 3 passes instead of 2. Previously the calculation and layout were done together in the second
pass... but this could cause layout to happen before all the box variables were finalized causing occassional
layout issues. Now the layout is done separately in a third pass after all the calculation is settled.
author | bsmith@81767d24-ef19-dc11-ae90-00e081727c95 |
---|---|
date | Sat, 23 Apr 2011 13:05:03 +0000 |
parents | e8c5bcf7846d |
children | d7e88ac1647c |
comparison
equal
deleted
inserted
replaced
927:e8c5bcf7846d | 928:43a5b3c78c41 |
---|---|
604 /* Subclass for a group box type */ | 604 /* Subclass for a group box type */ |
605 @interface DWGroupBox : NSBox | 605 @interface DWGroupBox : NSBox |
606 { | 606 { |
607 void *userdata; | 607 void *userdata; |
608 NSColor *bgcolor; | 608 NSColor *bgcolor; |
609 NSSize borderSize; | |
609 } | 610 } |
610 -(Box *)box; | 611 -(Box *)box; |
611 -(void *)userdata; | 612 -(void *)userdata; |
612 -(void)setUserdata:(void *)input; | 613 -(void)setUserdata:(void *)input; |
613 @end | 614 @end |
614 | 615 |
615 @implementation DWGroupBox | 616 @implementation DWGroupBox |
616 -(Box *)box { return [[self contentView] box]; } | 617 -(Box *)box { return [[self contentView] box]; } |
617 -(void *)userdata { return userdata; } | 618 -(void *)userdata { return userdata; } |
619 -(NSSize)borderSize { return borderSize; } | |
620 -(NSSize)initBorder | |
621 { | |
622 NSSize frameSize = [self frame].size; | |
623 | |
624 if(frameSize.height < 20 || frameSize.width < 20) | |
625 { | |
626 frameSize.width = frameSize.height = 100; | |
627 [self setFrameSize:frameSize]; | |
628 } | |
629 NSSize contentSize = [[self contentView] frame].size; | |
630 NSSize titleSize = [self titleRect].size; | |
631 | |
632 borderSize.width = 100-contentSize.width; | |
633 borderSize.height = (100-contentSize.height)-titleSize.height; | |
634 return borderSize; | |
635 } | |
618 -(void)setUserdata:(void *)input { userdata = input; } | 636 -(void)setUserdata:(void *)input { userdata = input; } |
619 @end | 637 @end |
620 | 638 |
621 @interface DWWindow : NSWindow | 639 @interface DWWindow : NSWindow |
622 -(void)sendEvent:(NSEvent *)theEvent; | 640 -(void)sendEvent:(NSEvent *)theEvent; |
669 { | 687 { |
670 NSSize size = [self frame].size; | 688 NSSize size = [self frame].size; |
671 | 689 |
672 if(oldsize.width != size.width || oldsize.height != size.height) | 690 if(oldsize.width != size.width || oldsize.height != size.height) |
673 { | 691 { |
674 _do_resize(box, size.width, size.height); | |
675 _do_resize(box, size.width, size.height); | 692 _do_resize(box, size.width, size.height); |
676 _event_handler([self window], nil, 1); | 693 _event_handler([self window], nil, 1); |
677 oldsize.width = size.width; | 694 oldsize.width = size.width; |
678 oldsize.height = size.height; | 695 oldsize.height = size.height; |
679 _handle_resize_events(box); | 696 _handle_resize_events(box); |
1993 | 2010 |
1994 /* This function calculates how much space the widgets and boxes require | 2011 /* This function calculates how much space the widgets and boxes require |
1995 * and does expansion as necessary. | 2012 * and does expansion as necessary. |
1996 */ | 2013 */ |
1997 static int _resize_box(Box *thisbox, int *depth, int x, int y, int *usedx, int *usedy, | 2014 static int _resize_box(Box *thisbox, int *depth, int x, int y, int *usedx, int *usedy, |
1998 int pass, int *usedpadx, int *usedpady) | 2015 int pass, int *usedpadx, int *usedpady) |
1999 { | 2016 { |
2000 int z, currentx = 0, currenty = 0; | 2017 int z, currentx = 0, currenty = 0; |
2001 int uymax = 0, uxmax = 0; | 2018 int uymax = 0, uxmax = 0; |
2002 int upymax = 0, upxmax = 0; | 2019 int upymax = 0, upxmax = 0; |
2003 /* Used for the SIZEEXPAND */ | 2020 /* Used for the SIZEEXPAND */ |
2004 int nux = *usedx, nuy = *usedy; | 2021 int nux = *usedx, nuy = *usedy; |
2005 int nupx = *usedpadx, nupy = *usedpady; | 2022 int nupx = *usedpadx, nupy = *usedpady; |
2006 int thispadx = thisbox->pad * 2; | 2023 int thispadx = thisbox->pad * 2; |
2007 int thispady = thisbox->pad * 2; | 2024 int thispady = thisbox->pad * 2; |
2008 | 2025 char tmpbuf[20], tabbuf[] = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; |
2026 strcpy(tmpbuf, tabbuf); | |
2027 | |
2028 tmpbuf[*depth] = '\0'; | |
2029 | |
2009 /* Handle special groupbox case */ | 2030 /* Handle special groupbox case */ |
2010 if(thisbox->grouphwnd) | 2031 if(thisbox->grouphwnd) |
2011 { | 2032 { |
2012 DWGroupBox *groupbox = thisbox->grouphwnd; | 2033 DWGroupBox *groupbox = thisbox->grouphwnd; |
2034 NSSize borderSize = [groupbox borderSize]; | |
2013 NSRect titleRect; | 2035 NSRect titleRect; |
2014 | 2036 |
2037 if(borderSize.width == 0 || borderSize.height == 0) | |
2038 { | |
2039 borderSize = [groupbox initBorder]; | |
2040 } | |
2015 /* Get the title size for a more accurate groupbox padding size */ | 2041 /* Get the title size for a more accurate groupbox padding size */ |
2016 titleRect = [groupbox titleRect]; | 2042 titleRect = [groupbox titleRect]; |
2017 thisbox->grouppadx = 16; | 2043 |
2018 thisbox->grouppady = 9 + titleRect.size.height; | 2044 thisbox->grouppadx = borderSize.width; |
2045 thisbox->grouppady = borderSize.height + titleRect.size.height; | |
2019 | 2046 |
2020 (*usedx) += thisbox->grouppadx; | 2047 (*usedx) += thisbox->grouppadx; |
2021 (*usedpadx) += thisbox->grouppadx; | 2048 (*usedpadx) += thisbox->grouppadx; |
2022 (*usedy) += thisbox->grouppady; | 2049 (*usedy) += thisbox->grouppady; |
2023 (*usedpady) += thisbox->grouppady; | 2050 (*usedpady) += thisbox->grouppady; |
2024 } | 2051 } |
2025 | 2052 |
2026 (*usedx) += thispadx; | 2053 (*usedx) += thispadx; |
2027 (*usedy) += thispady; | 2054 (*usedy) += thispady; |
2028 | 2055 |
2029 for(z=0;z<thisbox->count;z++) | 2056 for(z=0;z<thisbox->count;z++) |
2030 { | 2057 { |
2031 if(thisbox->items[z].type == TYPEBOX) | 2058 if(thisbox->items[z].type == TYPEBOX) |
2032 { | 2059 { |
2033 int initialx, initialy; | 2060 int initialx, initialy; |
2034 id box = thisbox->items[z].hwnd; | |
2035 Box *tmp = [box box]; | |
2036 | |
2037 initialx = x - (*usedx); | |
2038 initialy = y - (*usedy); | |
2039 | |
2040 if(tmp) | |
2041 { | |
2042 int newx, newy; | |
2043 int nux = *usedx, nuy = *usedy; | |
2044 int tmppadx = tmp->pad*2; | |
2045 int tmppady = tmp->pad*2; | |
2046 int upx, upy; | |
2047 | |
2048 upx = *usedpadx + tmppadx; | |
2049 upy = *usedpady + tmppady; | |
2050 | |
2051 /* On the second pass we know how big the box needs to be and how | |
2052 * much space we have, so we can calculate a ratio for the new box. | |
2053 */ | |
2054 if(pass == 2) | |
2055 { | |
2056 int deep = *depth + 1; | |
2057 | |
2058 _resize_box(tmp, &deep, x, y, &nux, &nuy, 1, &upx, &upy); | |
2059 | |
2060 tmp->upx = upx - *usedpadx; | |
2061 tmp->upy = upy - *usedpady; | |
2062 | |
2063 newx = x - nux; | |
2064 newy = y - nuy; | |
2065 | |
2066 tmp->width = thisbox->items[z].width = initialx - newx; | |
2067 tmp->height = thisbox->items[z].height = initialy - newy; | |
2068 | |
2069 tmp->parentxratio = thisbox->xratio; | |
2070 tmp->parentyratio = thisbox->yratio; | |
2071 | |
2072 tmp->parentpad = tmp->pad; | |
2073 | |
2074 /* Just in case */ | |
2075 tmp->xratio = thisbox->xratio; | |
2076 tmp->yratio = thisbox->yratio; | |
2077 | |
2078 if(thisbox->type == DW_VERT) | |
2079 { | |
2080 int tmppad = (thisbox->items[z].pad*2)+(tmp->pad*2)+tmp->grouppady; | |
2081 | |
2082 if((thisbox->items[z].width - tmppad)!=0) | |
2083 tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-tmppad))/((float)(thisbox->items[z].width-tmppad)); | |
2084 } | |
2085 else | |
2086 { | |
2087 if((thisbox->items[z].width-tmp->upx)!=0) | |
2088 tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-tmp->upx))/((float)(thisbox->items[z].width-tmp->upx)); | |
2089 } | |
2090 if(thisbox->type == DW_HORZ) | |
2091 { | |
2092 int tmppad = (thisbox->items[z].pad*2)+(tmp->pad*2)+tmp->grouppadx; | |
2093 | |
2094 if((thisbox->items[z].height-tmppad)!=0) | |
2095 tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-tmppad))/((float)(thisbox->items[z].height-tmppad)); | |
2096 } | |
2097 else | |
2098 { | |
2099 if((thisbox->items[z].height-tmp->upy)!=0) | |
2100 tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-tmp->upy))/((float)(thisbox->items[z].height-tmp->upy)); | |
2101 } | |
2102 | |
2103 nux = *usedx; nuy = *usedy; | |
2104 upx = *usedpadx + tmppadx; upy = *usedpady + tmppady; | |
2105 } | |
2106 | |
2107 (*depth)++; | |
2108 | |
2109 _resize_box(tmp, depth, x, y, &nux, &nuy, pass, &upx, &upy); | |
2110 | |
2111 (*depth)--; | |
2112 | |
2113 newx = x - nux; | |
2114 newy = y - nuy; | |
2115 | |
2116 tmp->minwidth = thisbox->items[z].width = initialx - newx; | |
2117 tmp->minheight = thisbox->items[z].height = initialy - newy; | |
2118 } | |
2119 } | |
2120 | |
2121 if(pass > 1 && *depth > 0) | |
2122 { | |
2123 if(thisbox->type == DW_VERT) | |
2124 { | |
2125 int tmppad = (thisbox->items[z].pad*2)+(thisbox->parentpad*2)+thisbox->grouppadx; | |
2126 | |
2127 if((thisbox->minwidth-tmppad) == 0) | |
2128 thisbox->items[z].xratio = 1.0; | |
2129 else | |
2130 thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-tmppad))/((float)(thisbox->minwidth-tmppad)); | |
2131 } | |
2132 else | |
2133 { | |
2134 if(thisbox->minwidth-thisbox->upx == 0) | |
2135 thisbox->items[z].xratio = 1.0; | |
2136 else | |
2137 thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-thisbox->upx))/((float)(thisbox->minwidth-thisbox->upx)); | |
2138 } | |
2139 | |
2140 if(thisbox->type == DW_HORZ) | |
2141 { | |
2142 int tmppad = (thisbox->items[z].pad*2)+(thisbox->parentpad*2)+thisbox->grouppady; | |
2143 | |
2144 if((thisbox->minheight-tmppad) == 0) | |
2145 thisbox->items[z].yratio = 1.0; | |
2146 else | |
2147 thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-tmppad))/((float)(thisbox->minheight-tmppad)); | |
2148 } | |
2149 else | |
2150 { | |
2151 if(thisbox->minheight-thisbox->upy == 0) | |
2152 thisbox->items[z].yratio = 1.0; | |
2153 else | |
2154 thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-thisbox->upy))/((float)(thisbox->minheight-thisbox->upy)); | |
2155 } | |
2156 | |
2157 if(thisbox->items[z].type == TYPEBOX) | |
2158 { | |
2159 id box = thisbox->items[z].hwnd; | 2061 id box = thisbox->items[z].hwnd; |
2160 Box *tmp = [box box]; | 2062 Box *tmp = [box box]; |
2161 | 2063 |
2064 initialx = x - (*usedx); | |
2065 initialy = y - (*usedy); | |
2066 | |
2162 if(tmp) | 2067 if(tmp) |
2163 { | 2068 { |
2164 tmp->parentxratio = thisbox->items[z].xratio; | 2069 int newx, newy; |
2165 tmp->parentyratio = thisbox->items[z].yratio; | 2070 int nux = *usedx, nuy = *usedy; |
2071 int tmppadx = tmp->pad*2; | |
2072 int tmppady = tmp->pad*2; | |
2073 int upx, upy; | |
2074 | |
2075 upx = *usedpadx + tmppadx; | |
2076 upy = *usedpady + tmppady; | |
2077 | |
2078 /* On the second pass we know how big the box needs to be and how | |
2079 * much space we have, so we can calculate a ratio for the new box. | |
2080 */ | |
2081 if(pass > 1) | |
2082 { | |
2083 int deep = *depth + 1; | |
2084 int tux = nux, tuy = nuy, tupx = upx, tupy = upy; | |
2085 | |
2086 _resize_box(tmp, &deep, x, y, &tux, &tuy, 1, &tupx, &tupy); | |
2087 | |
2088 tmp->upx = tupx - *usedpadx; | |
2089 tmp->upy = tupy - *usedpady; | |
2090 | |
2091 newx = x - tux; | |
2092 newy = y - tuy; | |
2093 | |
2094 tmp->width = thisbox->items[z].width = initialx - newx; | |
2095 tmp->height = thisbox->items[z].height = initialy - newy; | |
2096 | |
2097 tmp->parentxratio = thisbox->xratio; | |
2098 tmp->parentyratio = thisbox->yratio; | |
2099 | |
2100 tmp->parentpad = tmp->pad; | |
2101 | |
2102 /* Just in case */ | |
2103 tmp->xratio = thisbox->xratio; | |
2104 tmp->yratio = thisbox->yratio; | |
2105 | |
2106 if(thisbox->type == DW_VERT) | |
2107 { | |
2108 int tmppad = (thisbox->items[z].pad*2)+(tmp->pad*2)+tmp->grouppady; | |
2109 | |
2110 if((thisbox->items[z].width - tmppad)!=0) | |
2111 tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-tmppad))/((float)(thisbox->items[z].width-tmppad)); | |
2112 } | |
2113 else | |
2114 { | |
2115 if((thisbox->items[z].width-tmp->upx)!=0) | |
2116 tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-tmp->upx))/((float)(thisbox->items[z].width-tmp->upx)); | |
2117 } | |
2118 if(thisbox->type == DW_HORZ) | |
2119 { | |
2120 int tmppad = (thisbox->items[z].pad*2)+(tmp->pad*2)+tmp->grouppadx; | |
2121 | |
2122 if((thisbox->items[z].height-tmppad)!=0) | |
2123 tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-tmppad))/((float)(thisbox->items[z].height-tmppad)); | |
2124 } | |
2125 else | |
2126 { | |
2127 if((thisbox->items[z].height-tmp->upy)!=0) | |
2128 tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-tmp->upy))/((float)(thisbox->items[z].height-tmp->upy)); | |
2129 } | |
2130 } | |
2131 | |
2132 (*depth)++; | |
2133 | |
2134 _resize_box(tmp, depth, x, y, &nux, &nuy, pass, &upx, &upy); | |
2135 | |
2136 (*depth)--; | |
2137 | |
2138 newx = x - nux; | |
2139 newy = y - nuy; | |
2140 | |
2141 tmp->minwidth = thisbox->items[z].width = initialx - newx; | |
2142 tmp->minheight = thisbox->items[z].height = initialy - newy; | |
2166 } | 2143 } |
2167 } | 2144 } |
2168 } | 2145 |
2169 else | 2146 if(pass > 1 && *depth > 0) |
2170 { | 2147 { |
2171 thisbox->items[z].xratio = thisbox->xratio; | 2148 if(thisbox->type == DW_VERT) |
2172 thisbox->items[z].yratio = thisbox->yratio; | 2149 { |
2173 } | 2150 int tmppad = (thisbox->items[z].pad*2)+(thisbox->parentpad*2)+thisbox->grouppadx; |
2174 | 2151 |
2175 if(thisbox->type == DW_VERT) | 2152 if((thisbox->minwidth-tmppad) == 0) |
2176 { | 2153 thisbox->items[z].xratio = 1.0; |
2177 if((thisbox->items[z].width + (thisbox->items[z].pad*2)) > uxmax) | 2154 else |
2178 uxmax = (thisbox->items[z].width + (thisbox->items[z].pad*2)); | 2155 thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-tmppad))/((float)(thisbox->minwidth-tmppad)); |
2179 if(thisbox->items[z].hsize != SIZEEXPAND) | 2156 } |
2180 { | 2157 else |
2181 if(((thisbox->items[z].pad*2) + thisbox->items[z].width) > upxmax) | 2158 { |
2182 upxmax = (thisbox->items[z].pad*2) + thisbox->items[z].width; | 2159 if(thisbox->minwidth-thisbox->upx == 0) |
2183 } | 2160 thisbox->items[z].xratio = 1.0; |
2184 else | 2161 else |
2185 { | 2162 thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-thisbox->upx))/((float)(thisbox->minwidth-thisbox->upx)); |
2186 if(thisbox->items[z].pad*2 > upxmax) | 2163 } |
2187 upxmax = thisbox->items[z].pad*2; | 2164 |
2188 } | 2165 if(thisbox->type == DW_HORZ) |
2189 } | 2166 { |
2190 else | 2167 int tmppad = (thisbox->items[z].pad*2)+(thisbox->parentpad*2)+thisbox->grouppady; |
2191 { | 2168 |
2192 if(thisbox->items[z].width == -1) | 2169 if((thisbox->minheight-tmppad) == 0) |
2193 { | 2170 thisbox->items[z].yratio = 1.0; |
2194 /* figure out how much space this item requires */ | 2171 else |
2195 /* thisbox->items[z].width = */ | 2172 thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-tmppad))/((float)(thisbox->minheight-tmppad)); |
2196 } | 2173 } |
2197 else | 2174 else |
2198 { | 2175 { |
2199 (*usedx) += thisbox->items[z].width + (thisbox->items[z].pad*2); | 2176 if(thisbox->minheight-thisbox->upy == 0) |
2177 thisbox->items[z].yratio = 1.0; | |
2178 else | |
2179 thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-thisbox->upy))/((float)(thisbox->minheight-thisbox->upy)); | |
2180 } | |
2181 | |
2182 if(thisbox->items[z].type == TYPEBOX) | |
2183 { | |
2184 id box = thisbox->items[z].hwnd; | |
2185 Box *tmp = [box box]; | |
2186 | |
2187 if(tmp) | |
2188 { | |
2189 tmp->parentxratio = thisbox->items[z].xratio; | |
2190 tmp->parentyratio = thisbox->items[z].yratio; | |
2191 } | |
2192 } | |
2193 } | |
2194 else | |
2195 { | |
2196 thisbox->items[z].xratio = thisbox->xratio; | |
2197 thisbox->items[z].yratio = thisbox->yratio; | |
2198 } | |
2199 | |
2200 if(thisbox->type == DW_VERT) | |
2201 { | |
2202 if((thisbox->items[z].width + (thisbox->items[z].pad*2)) > uxmax) | |
2203 uxmax = (thisbox->items[z].width + (thisbox->items[z].pad*2)); | |
2200 if(thisbox->items[z].hsize != SIZEEXPAND) | 2204 if(thisbox->items[z].hsize != SIZEEXPAND) |
2201 (*usedpadx) += (thisbox->items[z].pad*2) + thisbox->items[z].width; | 2205 { |
2206 if(((thisbox->items[z].pad*2) + thisbox->items[z].width) > upxmax) | |
2207 upxmax = (thisbox->items[z].pad*2) + thisbox->items[z].width; | |
2208 } | |
2202 else | 2209 else |
2203 (*usedpadx) += thisbox->items[z].pad*2; | 2210 { |
2204 } | 2211 if(thisbox->items[z].pad*2 > upxmax) |
2205 } | 2212 upxmax = thisbox->items[z].pad*2; |
2206 if(thisbox->type == DW_HORZ) | 2213 } |
2207 { | 2214 } |
2208 if((thisbox->items[z].height + (thisbox->items[z].pad*2)) > uymax) | 2215 else |
2209 uymax = (thisbox->items[z].height + (thisbox->items[z].pad*2)); | 2216 { |
2210 if(thisbox->items[z].vsize != SIZEEXPAND) | 2217 if(thisbox->items[z].width == -1) |
2211 { | 2218 { |
2212 if(((thisbox->items[z].pad*2) + thisbox->items[z].height) > upymax) | 2219 /* figure out how much space this item requires */ |
2213 upymax = (thisbox->items[z].pad*2) + thisbox->items[z].height; | 2220 /* thisbox->items[z].width = */ |
2214 } | 2221 } |
2215 else | 2222 else |
2216 { | 2223 { |
2217 if(thisbox->items[z].pad*2 > upymax) | 2224 (*usedx) += thisbox->items[z].width + (thisbox->items[z].pad*2); |
2218 upymax = thisbox->items[z].pad*2; | 2225 if(thisbox->items[z].hsize != SIZEEXPAND) |
2219 } | 2226 (*usedpadx) += (thisbox->items[z].pad*2) + thisbox->items[z].width; |
2220 } | 2227 else |
2221 else | 2228 (*usedpadx) += thisbox->items[z].pad*2; |
2222 { | 2229 } |
2223 if(thisbox->items[z].height == -1) | 2230 } |
2224 { | 2231 if(thisbox->type == DW_HORZ) |
2225 /* figure out how much space this item requires */ | 2232 { |
2226 /* thisbox->items[z].height = */ | 2233 if((thisbox->items[z].height + (thisbox->items[z].pad*2)) > uymax) |
2227 } | 2234 uymax = (thisbox->items[z].height + (thisbox->items[z].pad*2)); |
2228 else | |
2229 { | |
2230 (*usedy) += thisbox->items[z].height + (thisbox->items[z].pad*2); | |
2231 if(thisbox->items[z].vsize != SIZEEXPAND) | 2235 if(thisbox->items[z].vsize != SIZEEXPAND) |
2232 (*usedpady) += (thisbox->items[z].pad*2) + thisbox->items[z].height; | 2236 { |
2237 if(((thisbox->items[z].pad*2) + thisbox->items[z].height) > upymax) | |
2238 upymax = (thisbox->items[z].pad*2) + thisbox->items[z].height; | |
2239 } | |
2233 else | 2240 else |
2234 (*usedpady) += thisbox->items[z].pad*2; | 2241 { |
2235 } | 2242 if(thisbox->items[z].pad*2 > upymax) |
2236 } | 2243 upymax = thisbox->items[z].pad*2; |
2237 } | 2244 } |
2238 | 2245 } |
2239 (*usedx) += uxmax; | 2246 else |
2240 (*usedy) += uymax; | 2247 { |
2241 (*usedpadx) += upxmax; | 2248 if(thisbox->items[z].height == -1) |
2242 (*usedpady) += upymax; | 2249 { |
2243 | 2250 /* figure out how much space this item requires */ |
2251 /* thisbox->items[z].height = */ | |
2252 } | |
2253 else | |
2254 { | |
2255 (*usedy) += thisbox->items[z].height + (thisbox->items[z].pad*2); | |
2256 if(thisbox->items[z].vsize != SIZEEXPAND) | |
2257 (*usedpady) += (thisbox->items[z].pad*2) + thisbox->items[z].height; | |
2258 else | |
2259 (*usedpady) += thisbox->items[z].pad*2; | |
2260 } | |
2261 } | |
2262 } | |
2263 | |
2264 (*usedx) += uxmax; | |
2265 (*usedy) += uymax; | |
2266 (*usedpadx) += upxmax; | |
2267 (*usedpady) += upymax; | |
2268 | |
2244 currentx += thisbox->pad; | 2269 currentx += thisbox->pad; |
2245 currenty += thisbox->pad; | 2270 currenty += thisbox->pad; |
2246 | 2271 |
2247 /* The second pass is for expansion and actual placement. */ | 2272 /* The second pass is for expansion. */ |
2248 if(pass > 1) | 2273 if(pass > 1) |
2249 { | 2274 { |
2250 /* Any SIZEEXPAND items should be set to uxmax/uymax */ | 2275 /* Any SIZEEXPAND items should be set to uxmax/uymax */ |
2251 for(z=0;z<thisbox->count;z++) | 2276 for(z=0;z<thisbox->count;z++) |
2252 { | 2277 { |
2253 if(thisbox->items[z].hsize == SIZEEXPAND && thisbox->type == DW_VERT) | 2278 if(thisbox->items[z].hsize == SIZEEXPAND && thisbox->type == DW_VERT) |
2254 thisbox->items[z].width = uxmax-(thisbox->items[z].pad*2); | 2279 thisbox->items[z].width = uxmax-(thisbox->items[z].pad*2); |
2255 if(thisbox->items[z].vsize == SIZEEXPAND && thisbox->type == DW_HORZ) | 2280 if(thisbox->items[z].vsize == SIZEEXPAND && thisbox->type == DW_HORZ) |
2256 thisbox->items[z].height = uymax-(thisbox->items[z].pad*2); | 2281 thisbox->items[z].height = uymax-(thisbox->items[z].pad*2); |
2257 /* Run this code segment again to finalize the sized after setting uxmax/uymax values. */ | 2282 /* Run this code segment again to finalize the sized after setting uxmax/uymax values. */ |
2258 if(thisbox->items[z].type == TYPEBOX) | 2283 if(thisbox->items[z].type == TYPEBOX) |
2259 { | |
2260 id box = thisbox->items[z].hwnd; | |
2261 Box *tmp = [box box]; | |
2262 | |
2263 if(tmp) | |
2264 { | 2284 { |
2265 if(*depth > 0) | 2285 int tux = nux, tuy = nuy, tupx = nupx, tupy = nupy; |
2266 { | 2286 id box = thisbox->items[z].hwnd; |
2267 float calcval; | 2287 Box *tmp = [box box]; |
2268 | 2288 |
2269 if(thisbox->type == DW_VERT) | 2289 if(tmp) |
2270 { | |
2271 calcval = (float)(tmp->minwidth-((thisbox->items[z].pad*2)+thispadx)); | |
2272 if(calcval == 0.0) | |
2273 tmp->xratio = thisbox->xratio; | |
2274 else | |
2275 tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-((thisbox->items[z].pad*2)+thispadx)))/calcval; | |
2276 tmp->width = thisbox->items[z].width; | |
2277 } | |
2278 if(thisbox->type == DW_HORZ) | |
2279 { | |
2280 calcval = (float)(tmp->minheight-((thisbox->items[z].pad*2)+thispady)); | |
2281 if(calcval == 0.0) | |
2282 tmp->yratio = thisbox->yratio; | |
2283 else | |
2284 tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-((thisbox->items[z].pad*2)+thispady)))/calcval; | |
2285 tmp->height = thisbox->items[z].height; | |
2286 } | |
2287 } | |
2288 | |
2289 (*depth)++; | |
2290 | |
2291 _resize_box(tmp, depth, x, y, &nux, &nuy, 3, &nupx, &nupy); | |
2292 | |
2293 (*depth)--; | |
2294 | |
2295 } | |
2296 } | |
2297 } | |
2298 | |
2299 for(z=0;z<(thisbox->count);z++) | |
2300 { | |
2301 int height = thisbox->items[z].height; | |
2302 int width = thisbox->items[z].width; | |
2303 int pad = thisbox->items[z].pad; | |
2304 NSView *handle = thisbox->items[z].hwnd; | |
2305 NSPoint point; | |
2306 NSSize size; | |
2307 int vectorx, vectory; | |
2308 | |
2309 /* When upxmax != pad*2 then ratios are incorrect. */ | |
2310 vectorx = (int)((width*thisbox->items[z].xratio)-width); | |
2311 vectory = (int)((height*thisbox->items[z].yratio)-height); | |
2312 | |
2313 if(width > 0 && height > 0) | |
2314 { | |
2315 /* This is a hack to fix rounding of the sizing */ | |
2316 if(*depth == 0) | |
2317 { | |
2318 vectorx++; | |
2319 vectory++; | |
2320 } | |
2321 | |
2322 /* If this item isn't going to expand... reset the vectors to 0 */ | |
2323 if(thisbox->items[z].vsize != SIZEEXPAND) | |
2324 vectory = 0; | |
2325 if(thisbox->items[z].hsize != SIZEEXPAND) | |
2326 vectorx = 0; | |
2327 | |
2328 point.x = currentx + pad; | |
2329 point.y = currenty + pad; | |
2330 size.width = width + vectorx; | |
2331 size.height = height + vectory; | |
2332 [handle setFrameOrigin:point]; | |
2333 [handle setFrameSize:size]; | |
2334 | |
2335 /* Special handling for notebook controls */ | |
2336 if([handle isMemberOfClass:[DWNotebook class]]) | |
2337 { | |
2338 DWNotebook *notebook = (DWNotebook *)handle; | |
2339 DWNotebookPage *notepage = (DWNotebookPage *)[notebook selectedTabViewItem]; | |
2340 id view = [notepage view]; | |
2341 | |
2342 if(view != nil) | |
2343 { | 2290 { |
2344 Box *box = [view box]; | 2291 if(*depth > 0) |
2345 NSSize size = [view frame].size; | 2292 { |
2346 _do_resize(box, size.width, size.height); | 2293 float calcval; |
2347 _handle_resize_events(box); | 2294 |
2295 if(thisbox->type == DW_VERT) | |
2296 { | |
2297 calcval = (float)(tmp->minwidth-((thisbox->items[z].pad*2)+thispadx)); | |
2298 if(calcval == 0.0) | |
2299 tmp->xratio = thisbox->xratio; | |
2300 else | |
2301 tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-((thisbox->items[z].pad*2)+thispadx)))/calcval; | |
2302 tmp->width = thisbox->items[z].width; | |
2303 } | |
2304 if(thisbox->type == DW_HORZ) | |
2305 { | |
2306 calcval = (float)(tmp->minheight-((thisbox->items[z].pad*2)+thispady)); | |
2307 if(calcval == 0.0) | |
2308 tmp->yratio = thisbox->yratio; | |
2309 else | |
2310 tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-((thisbox->items[z].pad*2)+thispady)))/calcval; | |
2311 tmp->height = thisbox->items[z].height; | |
2312 } | |
2313 } | |
2314 | |
2315 | |
2316 (*depth)++; | |
2317 | |
2318 _resize_box(tmp, depth, x, y, &tux, &tuy, pass, &tupx, &tupy); | |
2319 | |
2320 (*depth)--; | |
2321 | |
2348 } | 2322 } |
2349 } | 2323 } |
2350 /* Handle laying out scrollviews... if required space is less | 2324 } |
2351 * than available space, then expand. Otherwise use required space. | 2325 } |
2352 */ | 2326 |
2353 else if([handle isMemberOfClass:[DWScrollBox class]]) | 2327 /* The third pass is for actual placement. */ |
2328 if(pass > 2) | |
2329 { | |
2330 for(z=0;z<(thisbox->count);z++) | |
2331 { | |
2332 int height = thisbox->items[z].height; | |
2333 int width = thisbox->items[z].width; | |
2334 int pad = thisbox->items[z].pad; | |
2335 NSView *handle = thisbox->items[z].hwnd; | |
2336 NSPoint point; | |
2337 NSSize size; | |
2338 int vectorx, vectory; | |
2339 | |
2340 /* When upxmax != pad*2 then ratios are incorrect. */ | |
2341 vectorx = (int)((width*thisbox->items[z].xratio)-width); | |
2342 vectory = (int)((height*thisbox->items[z].yratio)-height); | |
2343 | |
2344 if(width > 0 && height > 0) | |
2354 { | 2345 { |
2355 int usedx = 0, usedy = 0, usedpadx = 0, usedpady = 0, depth = 0; | 2346 /* This is a hack to fix rounding of the sizing */ |
2356 DWScrollBox *scrollbox = (DWScrollBox *)handle; | 2347 if(*depth == 0) |
2357 DWBox *contentbox = [scrollbox documentView]; | 2348 { |
2358 Box *thisbox = [contentbox box]; | 2349 vectorx++; |
2359 NSSize contentsize = [scrollbox contentSize]; | 2350 vectory++; |
2351 } | |
2360 | 2352 |
2361 /* Get the required space for the box */ | 2353 /* If this item isn't going to expand... reset the vectors to 0 */ |
2362 _resize_box(thisbox, &depth, x, y, &usedx, &usedy, 1, &usedpadx, &usedpady); | 2354 if(thisbox->items[z].vsize != SIZEEXPAND) |
2355 vectory = 0; | |
2356 if(thisbox->items[z].hsize != SIZEEXPAND) | |
2357 vectorx = 0; | |
2363 | 2358 |
2364 if(contentsize.width < usedx) | 2359 point.x = currentx + pad; |
2360 point.y = currenty + pad; | |
2361 size.width = width + vectorx; | |
2362 size.height = height + vectory; | |
2363 [handle setFrameOrigin:point]; | |
2364 [handle setFrameSize:size]; | |
2365 | |
2366 /* After placing a box... place its components */ | |
2367 if(thisbox->items[z].type == TYPEBOX) | |
2365 { | 2368 { |
2366 contentsize.width = usedx; | 2369 id box = thisbox->items[z].hwnd; |
2370 Box *tmp = [box box]; | |
2371 | |
2372 if(tmp) | |
2373 { | |
2374 (*depth)++; | |
2375 _resize_box(tmp, depth, x, y, &nux, &nuy, pass, &nupx, &nupy); | |
2376 (*depth)--; | |
2377 } | |
2367 } | 2378 } |
2368 if(contentsize.height < usedy) | 2379 |
2380 /* Special handling for notebook controls */ | |
2381 if([handle isMemberOfClass:[DWNotebook class]]) | |
2369 { | 2382 { |
2370 contentsize.height = usedy; | 2383 DWNotebook *notebook = (DWNotebook *)handle; |
2384 DWNotebookPage *notepage = (DWNotebookPage *)[notebook selectedTabViewItem]; | |
2385 id view = [notepage view]; | |
2386 | |
2387 if(view != nil) | |
2388 { | |
2389 Box *box = [view box]; | |
2390 NSSize size = [view frame].size; | |
2391 _do_resize(box, size.width, size.height); | |
2392 _handle_resize_events(box); | |
2393 } | |
2371 } | 2394 } |
2372 [contentbox setFrameSize:contentsize]; | 2395 /* Handle laying out scrollviews... if required space is less |
2373 | 2396 * than available space, then expand. Otherwise use required space. |
2374 /* Layout the content of the scrollbox */ | 2397 */ |
2375 _do_resize(thisbox, contentsize.width, contentsize.height); | 2398 else if([handle isMemberOfClass:[DWScrollBox class]]) |
2399 { | |
2400 int usedx = 0, usedy = 0, usedpadx = 0, usedpady = 0, depth = 0; | |
2401 DWScrollBox *scrollbox = (DWScrollBox *)handle; | |
2402 DWBox *contentbox = [scrollbox documentView]; | |
2403 Box *thisbox = [contentbox box]; | |
2404 NSSize contentsize = [scrollbox contentSize]; | |
2405 | |
2406 /* Get the required space for the box */ | |
2407 _resize_box(thisbox, &depth, x, y, &usedx, &usedy, 1, &usedpadx, &usedpady); | |
2408 | |
2409 if(contentsize.width < usedx) | |
2410 { | |
2411 contentsize.width = usedx; | |
2412 } | |
2413 if(contentsize.height < usedy) | |
2414 { | |
2415 contentsize.height = usedy; | |
2416 } | |
2417 [contentbox setFrameSize:contentsize]; | |
2418 | |
2419 /* Layout the content of the scrollbox */ | |
2420 _do_resize(thisbox, contentsize.width, contentsize.height); | |
2421 } | |
2422 /* Special handling for spinbutton controls */ | |
2423 else if([handle isMemberOfClass:[DWSpinButton class]]) | |
2424 { | |
2425 DWSpinButton *spinbutton = (DWSpinButton *)handle; | |
2426 NSTextField *textfield = [spinbutton textfield]; | |
2427 NSStepper *stepper = [spinbutton stepper]; | |
2428 [textfield setFrameOrigin:NSMakePoint(0,0)]; | |
2429 [textfield setFrameSize:NSMakeSize(size.width-20,size.height)]; | |
2430 [stepper setFrameOrigin:NSMakePoint(size.width-20,0)]; | |
2431 [stepper setFrameSize:NSMakeSize(20,size.height)]; | |
2432 } | |
2433 else if([handle isMemberOfClass:[DWSplitBar class]] && size.width > 20 && size.height > 20) | |
2434 { | |
2435 DWSplitBar *split = (DWSplitBar *)handle; | |
2436 float percent = [split percent]; | |
2437 | |
2438 if(percent > 0) | |
2439 { | |
2440 dw_splitbar_set(handle, percent); | |
2441 [split setPercent:0]; | |
2442 } | |
2443 } | |
2444 if(thisbox->type == DW_HORZ) | |
2445 currentx += width + vectorx + (pad * 2); | |
2446 if(thisbox->type == DW_VERT) | |
2447 currenty += height + vectory + (pad * 2); | |
2376 } | 2448 } |
2377 /* Special handling for spinbutton controls */ | 2449 } |
2378 else if([handle isMemberOfClass:[DWSpinButton class]]) | 2450 } |
2379 { | 2451 return 0; |
2380 DWSpinButton *spinbutton = (DWSpinButton *)handle; | |
2381 NSTextField *textfield = [spinbutton textfield]; | |
2382 NSStepper *stepper = [spinbutton stepper]; | |
2383 [textfield setFrameOrigin:NSMakePoint(0,0)]; | |
2384 [textfield setFrameSize:NSMakeSize(size.width-20,size.height)]; | |
2385 [stepper setFrameOrigin:NSMakePoint(size.width-20,0)]; | |
2386 [stepper setFrameSize:NSMakeSize(20,size.height)]; | |
2387 } | |
2388 else if([handle isMemberOfClass:[DWSplitBar class]] && size.width > 20 && size.height > 20) | |
2389 { | |
2390 DWSplitBar *split = (DWSplitBar *)handle; | |
2391 float percent = [split percent]; | |
2392 | |
2393 if(percent > 0) | |
2394 { | |
2395 dw_splitbar_set(handle, percent); | |
2396 [split setPercent:0]; | |
2397 } | |
2398 } | |
2399 #if 0 | |
2400 /* Used this to figure out the groupbox border size... | |
2401 * Groupbox size 520x607 content 504x584 title 280x14 border 520x600 diff 16x9 | |
2402 */ | |
2403 else if([handle isMemberOfClass:[DWGroupBox class]]) | |
2404 { | |
2405 DWGroupBox *groupbox = thisbox->items[z].hwnd; | |
2406 NSSize contentSize = [[groupbox contentView] frame].size; | |
2407 NSSize titleSize = [groupbox titleRect].size; | |
2408 NSSize borderSize = [groupbox borderRect].size; | |
2409 | |
2410 NSLog(@"Groupbox size %dx%d content %dx%d title %dx%d border %dx%d diff %dx%d", | |
2411 (int)size.width, (int)size.height, | |
2412 (int)contentSize.width, (int)contentSize.height, | |
2413 (int)titleSize.width, (int)titleSize.height, | |
2414 (int)borderSize.width, (int)borderSize.height, | |
2415 (int)(size.width-contentSize.width), (int)((size.height-contentSize.height)-titleSize.height)); | |
2416 } | |
2417 #endif | |
2418 if(thisbox->type == DW_HORZ) | |
2419 currentx += width + vectorx + (pad * 2); | |
2420 if(thisbox->type == DW_VERT) | |
2421 currenty += height + vectory + (pad * 2); | |
2422 } | |
2423 } | |
2424 } | |
2425 return 0; | |
2426 } | 2452 } |
2427 | 2453 |
2428 static void _do_resize(Box *thisbox, int x, int y) | 2454 static void _do_resize(Box *thisbox, int x, int y) |
2429 { | 2455 { |
2430 if(x != 0 && y != 0) | 2456 if(x != 0 && y != 0) |
2431 { | 2457 { |
2432 if(thisbox) | 2458 if(thisbox) |
2433 { | 2459 { |
2434 int usedx = 0, usedy = 0, usedpadx = 0, usedpady = 0, depth = 0; | 2460 int usedx = 0, usedy = 0, usedpadx = 0, usedpady = 0, depth = 0; |
2435 | 2461 |
2436 _resize_box(thisbox, &depth, x, y, &usedx, &usedy, 1, &usedpadx, &usedpady); | 2462 /* Calculate space requirements */ |
2437 | 2463 _resize_box(thisbox, &depth, x, y, &usedx, &usedy, 1, &usedpadx, &usedpady); |
2438 if(usedx-usedpadx == 0 || usedy-usedpady == 0) | 2464 |
2439 return; | 2465 if(usedx-usedpadx == 0 || usedy-usedpady == 0) |
2440 | 2466 return; |
2441 thisbox->xratio = ((float)(x-usedpadx))/((float)(usedx-usedpadx)); | 2467 |
2442 thisbox->yratio = ((float)(y-usedpady))/((float)(usedy-usedpady)); | 2468 thisbox->xratio = ((float)(x-usedpadx))/((float)(usedx-usedpadx)); |
2443 | 2469 thisbox->yratio = ((float)(y-usedpady))/((float)(usedy-usedpady)); |
2444 usedx = usedy = usedpadx = usedpady = depth = 0; | 2470 |
2445 | 2471 usedx = usedy = usedpadx = usedpady = depth = 0; |
2446 _resize_box(thisbox, &depth, x, y, &usedx, &usedy, 2, &usedpadx, &usedpady); | 2472 |
2447 } | 2473 /* Calculate sub-box ratios for expansion */ |
2448 } | 2474 _resize_box(thisbox, &depth, x, y, &usedx, &usedy, 2, &usedpadx, &usedpady); |
2475 | |
2476 thisbox->xratio = ((float)(x-usedpadx))/((float)(usedx-usedpadx)); | |
2477 thisbox->yratio = ((float)(y-usedpady))/((float)(usedy-usedpady)); | |
2478 | |
2479 usedx = usedy = usedpadx = usedpady = depth = 0; | |
2480 | |
2481 /* Finally place all the boxes and controls */ | |
2482 _resize_box(thisbox, &depth, x, y, &usedx, &usedy, 3, &usedpadx, &usedpady); | |
2483 } | |
2484 } | |
2449 } | 2485 } |
2450 | 2486 |
2451 NSMenu *_generate_main_menu() | 2487 NSMenu *_generate_main_menu() |
2452 { | 2488 { |
2453 NSString *applicationName = nil; | 2489 NSString *applicationName = nil; |