changeset 1437:a50e8b486a1a

Initial layout engine 2.0 for the Mac... Windows and OS/2 may not compile until the the next commit later tonight or tomorrow.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Thu, 08 Dec 2011 06:47:05 +0000
parents 18c1b999dd65
children bde7ebced556
files dw.h mac/dw.m
diffstat 2 files changed, 150 insertions(+), 329 deletions(-) [+]
line wrap: on
line diff
--- a/dw.h	Wed Dec 07 19:03:05 2011 +0000
+++ b/dw.h	Thu Dec 08 06:47:05 2011 +0000
@@ -658,8 +658,6 @@
    int hsize, vsize;
    /* Padding */
    int pad;
-   /* Ratio of current item */
-   float xratio, yratio;
 } Item;
 
 typedef struct _box {
@@ -678,15 +676,13 @@
    /* Keep track of how box is packed */
    int hsize, vsize;
    /* Padding */
-   int pad, parentpad, grouppadx, grouppady;
+   int pad, grouppadx, grouppady;
    /* Groupbox */
    HWND grouphwnd;
    /* Default item */
    HWND defaultitem;
    /* Used as temporary storage in the calculation stage */
-   int upx, upy, minheight, minwidth;
-   /* Ratio in this box */
-   float xratio, yratio, parentxratio, parentyratio;
+   int usedpadx, usedpady, minheight, minwidth;
    /* Used for calculating individual item ratios */
    int width, height;
    /* Any combinations of flags describing the box */
--- a/mac/dw.m	Wed Dec 07 19:03:05 2011 +0000
+++ b/mac/dw.m	Thu Dec 08 06:47:05 2011 +0000
@@ -655,6 +655,8 @@
     if (self)
     {
         box = calloc(1, sizeof(Box));
+        box->vsize = box->hsize = SIZEEXPAND;
+        box->width = box->height = 1;
     }
     return self;
 }
@@ -2408,343 +2410,183 @@
 /* This function calculates how much space the widgets and boxes require
  * and does expansion as necessary.
  */
-static int _resize_box(Box *thisbox, int *depth, int x, int y, int *usedx, int *usedy,
-                       int pass, int *usedpadx, int *usedpady)
-{
-    int z, currentx = 0, currenty = 0;
+static void _resize_box(Box *thisbox, int *depth, int x, int y, int pass)
+{
+    /* Current item position */
+    int z, currentx = thisbox->pad, currenty = thisbox->pad;
+    /* Used x, y and padding maximum values...
+     * These will be used to find the widest or
+     * tallest items in a box.
+     */
     int uymax = 0, uxmax = 0;
     int upymax = 0, upxmax = 0;
-    /* Used for the SIZEEXPAND */
-    int nux = *usedx, nuy = *usedy;
-    int nupx = *usedpadx, nupy = *usedpady;
-    int thispadx = thisbox->pad * 2;
-    int thispady = thisbox->pad * 2;
+    
+    /* Reset the box sizes */
+    thisbox->minwidth = thisbox->minheight = thisbox->usedpadx = thisbox->usedpady = thisbox->pad * 2;
 
     /* Handle special groupbox case */
     if(thisbox->grouphwnd)
     {
-        DWGroupBox *groupbox = thisbox->grouphwnd;
-        NSSize borderSize = [groupbox borderSize];
-        NSRect titleRect;
-
-        if(borderSize.width == 0 || borderSize.height == 0)
-        {
-            borderSize = [groupbox initBorder];
-        }
-        /* Get the title size for a more accurate groupbox padding size */
-        titleRect = [groupbox titleRect];
-
-        thisbox->grouppadx = borderSize.width;
-        thisbox->grouppady = borderSize.height + titleRect.size.height;
-
-        (*usedx) += thisbox->grouppadx;
-        (*usedpadx) += thisbox->grouppadx;
-        (*usedy) += thisbox->grouppady;
-        (*usedpady) += thisbox->grouppady;
-    }
-
-    (*usedx) += thispadx;
-    (*usedy) += thispady;
-
+        /* Only calculate the size on the first pass...
+         * used the cached values on second.
+         */
+        if(pass == 1)
+        {
+            DWGroupBox *groupbox = thisbox->grouphwnd;
+            NSSize borderSize = [groupbox borderSize];
+            NSRect titleRect;
+
+            if(borderSize.width == 0 || borderSize.height == 0)
+            {
+                borderSize = [groupbox initBorder];
+            }
+            /* Get the title size for a more accurate groupbox padding size */
+            titleRect = [groupbox titleRect];
+
+            thisbox->grouppadx = borderSize.width;
+            thisbox->grouppady = borderSize.height + titleRect.size.height;
+        }
+        
+        thisbox->minwidth += thisbox->grouppadx;
+        thisbox->usedpadx += thisbox->grouppadx;
+        thisbox->minheight += thisbox->grouppady;
+        thisbox->usedpady += thisbox->grouppady;
+    }
+    
+    /* Count up all the space for all items in the box */
     for(z=0;z<thisbox->count;z++)
     {
+        int itempad, itemwidth, itemheight;
+        
         if(thisbox->items[z].type == TYPEBOX)
         {
-            int initialx, initialy;
             id box = thisbox->items[z].hwnd;
             Box *tmp = [box box];
 
-            initialx = x - (*usedx);
-            initialy = y - (*usedy);
-
             if(tmp)
             {
-                int newx, newy;
-                int nux = *usedx, nuy = *usedy;
-                int tmppadx = tmp->pad*2;
-                int tmppady = tmp->pad*2;
-                int upx, upy;
-
-                upx = *usedpadx + tmppadx;
-                upy = *usedpady + tmppady;
-
-                /* On the second pass we know how big the box needs to be and how
-                 * much space we have, so we can calculate a ratio for the new box.
-                 */
-                if(pass > 1)
+                /* On the first pass calculate the box contents */
+                if(pass == 1)
                 {
-                    int deep = *depth + 1;
-                    int tux = nux, tuy = nuy, tupx = upx, tupy = upy;
-
-                    _resize_box(tmp, &deep, x, y, &tux, &tuy, 1, &tupx, &tupy);
-
-                    tmp->upx = tupx - *usedpadx;
-                    tmp->upy = tupy - *usedpady;
-
-                    newx = x - tux;
-                    newy = y - tuy;
-
-                    tmp->width = thisbox->items[z].width = initialx - newx;
-                    tmp->height = thisbox->items[z].height = initialy - newy;
-
-                    tmp->parentxratio = thisbox->xratio;
-                    tmp->parentyratio = thisbox->yratio;
-
-                    tmp->parentpad = tmp->pad;
-                    tmp->hsize = thisbox->items[z].hsize;
-                    tmp->vsize = thisbox->items[z].vsize;
-
-                    /* Just in case */
-                    tmp->xratio = thisbox->xratio;
-                    tmp->yratio = thisbox->yratio;
-
-                    if(thisbox->type == DW_VERT)
-                    {
-                        int tmppad = (thisbox->items[z].pad*2)+(tmp->pad*2)+tmp->grouppady;
-
-                        if((thisbox->items[z].width - tmppad)!=0)
-                            tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-tmppad))/((float)(thisbox->items[z].width-tmppad));
-                    }
-                    else
-                    {
-                        if((thisbox->items[z].width-tmp->upx)!=0)
-                            tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-tmp->upx))/((float)(thisbox->items[z].width-tmp->upx));
-                    }
-                    if(thisbox->type == DW_HORZ)
-                    {
-                        int tmppad = (thisbox->items[z].pad*2)+(tmp->pad*2)+tmp->grouppadx;
-
-                        if((thisbox->items[z].height-tmppad)!=0)
-                            tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-tmppad))/((float)(thisbox->items[z].height-tmppad));
-                    }
-                    else
-                    {
-                        if((thisbox->items[z].height-tmp->upy)!=0)
-                            tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-tmp->upy))/((float)(thisbox->items[z].height-tmp->upy));
-                    }
+                    (*depth)++;
+                    
+                    /* Save the newly calculated values on the box */
+                    _resize_box(tmp, depth, x, y, pass);
+                    
+                    /* Duplicate the values in the item list for use below */
+                    thisbox->items[z].width = tmp->minwidth;
+                    thisbox->items[z].height = tmp->minheight;
+                
+                    (*depth)--;
                 }
-
-                (*depth)++;
-
-                _resize_box(tmp, depth, x, y, &nux, &nuy, pass, &upx, &upy);
-
-                (*depth)--;
-
-                newx = x - nux;
-                newy = y - nuy;
-
-                tmp->minwidth = thisbox->items[z].width = initialx - newx;
-                tmp->minheight = thisbox->items[z].height = initialy - newy;
             }
         }
-
-        if(pass > 1 && *depth > 0)
-        {
-            if(thisbox->type == DW_VERT)
+        
+        /* Precalculate these values, since they will
+         * be used used repeatedly in the next section.
+         */
+        itempad = thisbox->items[z].pad * 2;
+        itemwidth = thisbox->items[z].width + itempad;
+        itemheight = thisbox->items[z].height + itempad;
+        
+        /* Calculate the totals and maximums */
+        if(thisbox->type == DW_VERT)
+        {
+            if(itemwidth > uxmax)
+                uxmax = itemwidth;
+            
+            if(thisbox->items[z].hsize != SIZEEXPAND)
             {
-                int tmppad = (thisbox->items[z].pad*2)+(thisbox->parentpad*2)+thisbox->grouppadx;
-
-                if((thisbox->minwidth-tmppad) == 0)
-                    thisbox->items[z].xratio = 1.0;
-                else
-                    thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-tmppad))/((float)(thisbox->minwidth-tmppad));
+                if(itemwidth > upxmax)
+                    upxmax = itemwidth;
             }
             else
             {
-                if(thisbox->minwidth-thisbox->upx == 0)
-                    thisbox->items[z].xratio = 1.0;
-                else
-                    thisbox->items[z].xratio = ((float)((thisbox->width * thisbox->parentxratio)-thisbox->upx))/((float)(thisbox->minwidth-thisbox->upx));
+                if(itempad > upxmax)
+                    upxmax = itempad;
             }
-
-            if(thisbox->type == DW_HORZ)
-            {
-                int tmppad = (thisbox->items[z].pad*2)+(thisbox->parentpad*2)+thisbox->grouppady;
-
-                if((thisbox->minheight-tmppad) == 0)
-                    thisbox->items[z].yratio = 1.0;
-                else
-                    thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-tmppad))/((float)(thisbox->minheight-tmppad));
-            }
+            thisbox->minheight += itemheight;
+            if(thisbox->items[z].vsize != SIZEEXPAND)
+                thisbox->usedpady += itemheight;
             else
-            {
-                if(thisbox->minheight-thisbox->upy == 0)
-                    thisbox->items[z].yratio = 1.0;
-                else
-                    thisbox->items[z].yratio = ((float)((thisbox->height * thisbox->parentyratio)-thisbox->upy))/((float)(thisbox->minheight-thisbox->upy));
-            }
-
-            if(thisbox->items[z].type == TYPEBOX)
-            {
-                id box = thisbox->items[z].hwnd;
-                Box *tmp = [box box];
-
-                if(tmp)
-                {
-                    tmp->parentxratio = thisbox->items[z].xratio;
-                    tmp->parentyratio = thisbox->items[z].yratio;
-                }
-            }
+                thisbox->usedpady += itempad;
         }
         else
         {
-            thisbox->items[z].xratio = thisbox->xratio;
-            thisbox->items[z].yratio = thisbox->yratio;
-        }
-
-        if(thisbox->type == DW_VERT)
-        {
-            if((thisbox->items[z].width + (thisbox->items[z].pad*2)) > uxmax)
-                uxmax = (thisbox->items[z].width + (thisbox->items[z].pad*2));
-            if(thisbox->items[z].hsize != SIZEEXPAND)
-            {
-                if(((thisbox->items[z].pad*2) + thisbox->items[z].width) > upxmax)
-                    upxmax = (thisbox->items[z].pad*2) + thisbox->items[z].width;
-            }
-            else
-            {
-                if(thisbox->items[z].pad*2 > upxmax)
-                    upxmax = thisbox->items[z].pad*2;
-            }
-        }
-        else
-        {
-            (*usedx) += thisbox->items[z].width + (thisbox->items[z].pad*2);
-            if(thisbox->items[z].hsize != SIZEEXPAND)
-                (*usedpadx) += (thisbox->items[z].pad*2) + thisbox->items[z].width;
-            else
-                (*usedpadx) += thisbox->items[z].pad*2;
-        }
-        if(thisbox->type == DW_HORZ)
-        {
-            if((thisbox->items[z].height + (thisbox->items[z].pad*2)) > uymax)
-                uymax = (thisbox->items[z].height + (thisbox->items[z].pad*2));
+            if(itemheight > uymax)
+                uymax = itemheight;
             if(thisbox->items[z].vsize != SIZEEXPAND)
             {
-                if(((thisbox->items[z].pad*2) + thisbox->items[z].height) > upymax)
-                    upymax = (thisbox->items[z].pad*2) + thisbox->items[z].height;
+                if(itemheight > upymax)
+                    upymax = itemheight;
             }
             else
             {
-                if(thisbox->items[z].pad*2 > upymax)
-                    upymax = thisbox->items[z].pad*2;
+                if(itempad > upymax)
+                    upymax = itempad;
             }
-        }
-        else
-        {
-            (*usedy) += thisbox->items[z].height + (thisbox->items[z].pad*2);
-            if(thisbox->items[z].vsize != SIZEEXPAND)
-                (*usedpady) += (thisbox->items[z].pad*2) + thisbox->items[z].height;
+            thisbox->minwidth += itemwidth;
+            if(thisbox->items[z].hsize != SIZEEXPAND)
+                thisbox->usedpadx += itemwidth;
             else
-                (*usedpady) += thisbox->items[z].pad*2;
-        }
-    }
-
-    (*usedx) += uxmax;
-    (*usedy) += uymax;
-    (*usedpadx) += upxmax;
-    (*usedpady) += upymax;
-
-    currentx += thisbox->pad;
-    currenty += thisbox->pad;
-
-    /* The second pass is for expansion. */
+                thisbox->usedpadx += itempad;
+        }
+    }
+
+    /* Add the maximums which were calculated in the previous loop */
+    thisbox->minwidth += uxmax;
+    thisbox->minheight += uymax;
+    thisbox->usedpadx += upxmax;
+    thisbox->usedpady += upymax;
+
+    /* The second pass is for actual placement. */
     if(pass > 1)
     {
-        /* Any SIZEEXPAND items should be set to uxmax/uymax */
-        for(z=0;z<thisbox->count;z++)
-        {
-            if(thisbox->items[z].hsize == SIZEEXPAND && thisbox->type == DW_VERT)
-                thisbox->items[z].width = uxmax-(thisbox->items[z].pad*2);
-            if(thisbox->items[z].vsize == SIZEEXPAND && thisbox->type == DW_HORZ)
-                thisbox->items[z].height = uymax-(thisbox->items[z].pad*2);
-            /* Run this code segment again to finalize the sized after setting uxmax/uymax values. */
-            if(thisbox->items[z].type == TYPEBOX)
-            {
-                int tux = nux, tuy = nuy, tupx = nupx, tupy = nupy;
-                id box = thisbox->items[z].hwnd;
-                Box *tmp = [box box];
-
-                if(tmp)
-                {
-                    if(*depth > 0)
-                    {
-                        float calcval;
-
-                        if(thisbox->type == DW_VERT)
-                        {
-                            calcval = (float)(tmp->minwidth-((thisbox->items[z].pad*2)+thispadx));
-                            if(calcval == 0.0)
-                                tmp->xratio = thisbox->xratio;
-                            else
-                                tmp->xratio = ((float)((thisbox->items[z].width * thisbox->xratio)-((thisbox->items[z].pad*2)+thispadx)))/calcval;
-                            tmp->width = thisbox->items[z].width;
-                        }
-                        if(thisbox->type == DW_HORZ)
-                        {
-                            calcval = (float)(tmp->minheight-((thisbox->items[z].pad*2)+thispady));
-                            if(calcval == 0.0)
-                                tmp->yratio = thisbox->yratio;
-                            else
-                                tmp->yratio = ((float)((thisbox->items[z].height * thisbox->yratio)-((thisbox->items[z].pad*2)+thispady)))/calcval;
-                            tmp->height = thisbox->items[z].height;
-                        }
-                    }
-
-
-                    (*depth)++;
-
-                    _resize_box(tmp, depth, x, y, &tux, &tuy, pass, &tupx, &tupy);
-
-                    (*depth)--;
-
-                }
-            }
-        }
-    }
-
-    /* The third pass is for actual placement. */
-    if(pass > 2)
-    {
         for(z=0;z<(thisbox->count);z++)
         {
             int height = thisbox->items[z].height;
             int width = thisbox->items[z].width;
-            int pad = thisbox->items[z].pad;
-            NSView *handle = thisbox->items[z].hwnd;
-            NSPoint point;
-            NSSize size;
-            int vectorx, vectory;
-
-            /* When upxmax != pad*2 then ratios are incorrect. */
-            vectorx = (int)((width*thisbox->items[z].xratio)-width);
-            vectory = (int)((height*thisbox->items[z].yratio)-height);
-
-            if(width > 0 && height > 0)
+            int itempad = thisbox->items[z].pad * 2;
+            int thispad = thisbox->pad * 2;
+
+            /* Calculate the new sizes */
+            if(thisbox->items[z].hsize == SIZEEXPAND)
+            {
+                if(thisbox->type == DW_HORZ)
+                {
+                    int expandablex = thisbox->minwidth - thisbox->usedpadx;
+                
+                    if(expandablex)
+                        width = (int)(((float)width / (float)expandablex) * (float)(x - thisbox->usedpadx));
+                }
+                else
+                    width = x - (itempad + thispad + thisbox->grouppadx);
+            }
+            if(thisbox->items[z].vsize == SIZEEXPAND)
             {
-                /* This is a hack to fix rounding of the sizing */
-                if(*depth == 0)
+                if(thisbox->type == DW_VERT)
                 {
-                    vectorx++;
-                    vectory++;
+                    int expandabley = thisbox->minheight - thisbox->usedpady;
+                
+                    if(expandabley)
+                        height = (int)(((float)height / (float)expandabley) * (float)(y - thisbox->usedpady));
                 }
-
-                /* If this item isn't going to expand... reset the vectors to 0 */
-                if(thisbox->items[z].vsize != SIZEEXPAND)
-                    vectory = 0;
-                if(thisbox->items[z].hsize != SIZEEXPAND)
-                    vectorx = 0;
-
+                else
+                    height = y - (itempad + thispad + thisbox->grouppady);
+            }
+            
+            /* If the calculated size is valid... */
+            if(height > 0 && width > 0)
+            {
+                int pad = thisbox->items[z].pad;
+                NSView *handle = thisbox->items[z].hwnd;
+                NSPoint point;
+                NSSize size;
+                
                 point.x = currentx + pad;
                 point.y = currenty + pad;
-                if(thisbox->type == DW_VERT && thisbox->hsize == SIZESTATIC && thisbox->items[z].hsize == SIZEEXPAND && thisbox->width)
-                    size.width = thisbox->width;
-                else
-                    size.width = width + vectorx;
-                if(thisbox->type == DW_HORZ && thisbox->vsize == SIZESTATIC && thisbox->items[z].vsize == SIZEEXPAND && thisbox->height)
-                    size.height = thisbox->height;
-                else
-                    size.height = height + vectory;
+                size.width = width;
+                size.height = height;
                 [handle setFrameOrigin:point];
                 [handle setFrameSize:size];
 
@@ -2757,7 +2599,7 @@
                     if(tmp)
                     {
                         (*depth)++;
-                        _resize_box(tmp, depth, x, y, &nux, &nuy, pass, &nupx, &nupy);
+                        _resize_box(tmp, depth, width, height, pass);
                         (*depth)--;
                     }
                 }
@@ -2782,22 +2624,22 @@
                  */
                 else if([handle isMemberOfClass:[DWScrollBox class]])
                 {
-                    int usedx = 0, usedy = 0, usedpadx = 0, usedpady = 0, depth = 0;
+                    int depth = 0;
                     DWScrollBox *scrollbox = (DWScrollBox *)handle;
                     DWBox *contentbox = [scrollbox documentView];
                     Box *thisbox = [contentbox box];
                     NSSize contentsize = [scrollbox contentSize];
 
                     /* Get the required space for the box */
-                    _resize_box(thisbox, &depth, x, y, &usedx, &usedy, 1, &usedpadx, &usedpady);
-
-                    if(contentsize.width < usedx)
+                    _resize_box(thisbox, &depth, x, y, 1);
+
+                    if(contentsize.width < thisbox->minwidth)
                     {
-                        contentsize.width = usedx;
+                        contentsize.width = thisbox->minwidth;
                     }
-                    if(contentsize.height < usedy)
+                    if(contentsize.height < thisbox->minheight)
                     {
-                        contentsize.height = usedy;
+                        contentsize.height = thisbox->minheight;
                     }
                     [contentbox setFrameSize:contentsize];
 
@@ -2833,13 +2675,12 @@
                     }
                 }
                 if(thisbox->type == DW_HORZ)
-                    currentx += width + vectorx + (pad * 2);
+                    currentx += width + (pad * 2);
                 if(thisbox->type == DW_VERT)
-                    currenty += height + vectory + (pad * 2);
+                    currenty += height + (pad * 2);
             }
         }
     }
-    return 0;
 }
 
 static void _do_resize(Box *thisbox, int x, int y)
@@ -2848,29 +2689,13 @@
     {
         if(thisbox)
         {
-            int usedx = 0, usedy = 0, usedpadx = 0, usedpady = 0, depth = 0;
-
+            int depth = 0;
+            
             /* Calculate space requirements */
-            _resize_box(thisbox, &depth, x, y, &usedx, &usedy, 1, &usedpadx, &usedpady);
-
-            if(usedx-usedpadx == 0 || usedy-usedpady == 0)
-                return;
-
-            thisbox->xratio = ((float)(x-usedpadx))/((float)(usedx-usedpadx));
-            thisbox->yratio = ((float)(y-usedpady))/((float)(usedy-usedpady));
-
-            usedx = usedy = usedpadx = usedpady = depth = 0;
-
-            /* Calculate sub-box ratios for expansion */
-            _resize_box(thisbox, &depth, x, y, &usedx, &usedy, 2, &usedpadx, &usedpady);
-
-            thisbox->xratio = ((float)(x-usedpadx))/((float)(usedx-usedpadx));
-            thisbox->yratio = ((float)(y-usedpady))/((float)(usedy-usedpady));
-
-            usedx = usedy = usedpadx = usedpady = depth = 0;
-
+            _resize_box(thisbox, &depth, x, y, 1);
+            
             /* Finally place all the boxes and controls */
-            _resize_box(thisbox, &depth, x, y, &usedx, &usedy, 3, &usedpadx, &usedpady);
+            _resize_box(thisbox, &depth, x, y, 2);
         }
     }
 }