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;