LCOV - code coverage report
Current view: top level - gdraw - ghvbox.c (source / functions) Hit Total Coverage
Test: FontForge coverage report 2017-08-04 01:21:11+02:00 (commit d35f7e4107a9e1db65cce47c468fcc914cecb8fd) Lines: 0 433 0.0 %
Date: 2017-08-04 Functions: 0 21 0.0 %

          Line data    Source code
       1             : /* Copyright (C) 2006-2012 by George Williams */
       2             : /*
       3             :  * Redistribution and use in source and binary forms, with or without
       4             :  * modification, are permitted provided that the following conditions are met:
       5             : 
       6             :  * Redistributions of source code must retain the above copyright notice, this
       7             :  * list of conditions and the following disclaimer.
       8             : 
       9             :  * Redistributions in binary form must reproduce the above copyright notice,
      10             :  * this list of conditions and the following disclaimer in the documentation
      11             :  * and/or other materials provided with the distribution.
      12             : 
      13             :  * The name of the author may not be used to endorse or promote products
      14             :  * derived from this software without specific prior written permission.
      15             : 
      16             :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
      17             :  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
      18             :  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
      19             :  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      20             :  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
      21             :  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
      22             :  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
      23             :  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
      24             :  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
      25             :  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      26             :  */
      27             : #include "gdraw.h"
      28             : #include "ggadgetP.h"
      29             : #include <string.h>
      30             : 
      31             : /* If the locale is hebrew or arabic should we lay out boxes right to left???*/
      32             : 
      33             : #define GG_Glue         ((GGadget *) -1)        /* Special entries */
      34             : #define GG_ColSpan      ((GGadget *) -2)        /* for box elements */
      35             : #define GG_RowSpan      ((GGadget *) -3)        /* Must match those in ggadget.h */
      36             : #define GG_HPad10       ((GGadget *) -4)
      37             : 
      38             : static GBox hvgroup_box = GBOX_EMPTY; /* Don't initialize here */
      39             : static GBox hvbox_box = GBOX_EMPTY; /* Don't initialize here */
      40             : static int ghvbox_inited = false;
      41             : 
      42             : GResInfo ghvgroupbox_ri = {
      43             :     NULL, &ggadget_ri, NULL, NULL,
      44             :     &hvgroup_box,
      45             :     NULL,
      46             :     NULL,
      47             :     NULL,
      48             :     N_("HV Group Box"),
      49             :     N_("A box drawn around other gadgets"),
      50             :     "GGroup",
      51             :     "Gdraw",
      52             :     false,
      53             :     omf_border_type|omf_border_shape|omf_padding|omf_main_background|omf_disabled_background,
      54             :     NULL,
      55             :     GBOX_EMPTY,
      56             :     NULL,
      57             :     NULL,
      58             :     NULL
      59             : };
      60             : 
      61           0 : static void _GHVBox_Init(void) {
      62           0 :     if ( ghvbox_inited )
      63           0 : return;
      64           0 :     _GGadgetCopyDefaultBox(&hvgroup_box);
      65           0 :     _GGadgetCopyDefaultBox(&hvbox_box);
      66           0 :     hvgroup_box.border_type = bt_engraved;
      67           0 :     hvbox_box.border_type = bt_none;
      68           0 :     hvbox_box.border_width = 0;
      69           0 :     hvgroup_box.border_shape = hvbox_box.border_shape = bs_rect;
      70           0 :     hvgroup_box.padding = 2;
      71           0 :     hvbox_box.padding = 0;
      72             :     /*hvgroup_box.flags = hvbox_box.flags = 0;*/
      73           0 :     hvgroup_box.main_background = COLOR_TRANSPARENT;
      74           0 :     hvgroup_box.disabled_background = COLOR_TRANSPARENT;
      75           0 :     _GGadgetInitDefaultBox("GHVBox.",&hvbox_box,NULL);
      76           0 :     _GGadgetInitDefaultBox("GGroup.",&hvgroup_box,NULL);
      77           0 :     ghvbox_inited = true;
      78             : }
      79             : 
      80           0 : static void GHVBox_destroy(GGadget *g) {
      81           0 :     GHVBox *gb = (GHVBox *) g;
      82             :     int i;
      83             : 
      84           0 :     if ( gb->label != NULL )
      85           0 :         GGadgetDestroy( gb->label );
      86           0 :     for ( i=0; i<gb->rows*gb->cols; ++i )
      87           0 :         if ( gb->children[i]!=GG_Glue && gb->children[i]!=GG_ColSpan &&
      88           0 :                 gb->children[i]!=GG_RowSpan && gb->children[i]!=GG_HPad10 )
      89           0 :             GGadgetDestroy(gb->children[i]);
      90           0 :     free(gb->children);
      91           0 :     _ggadget_destroy(g);
      92           0 : }
      93             : 
      94           0 : static void GHVBoxMove(GGadget *g, int32 x, int32 y) {
      95           0 :     GHVBox *gb = (GHVBox *) g;
      96           0 :     int offx = x-g->r.x, offy = y-g->r.y;
      97             :     int i;
      98             : 
      99           0 :     if ( gb->label!=NULL )
     100           0 :         GGadgetMove(gb->label,gb->label->inner.x+offx,gb->label->inner.y+offy);
     101           0 :     for ( i=0; i<gb->rows*gb->cols; ++i )
     102           0 :         if ( gb->children[i]!=GG_Glue && gb->children[i]!=GG_ColSpan &&
     103           0 :                 gb->children[i]!=GG_RowSpan && gb->children[i]!=GG_HPad10 )
     104           0 :             GGadgetMove(gb->children[i],
     105           0 :                     gb->children[i]->r.x+offx, gb->children[i]->r.y+offy);
     106           0 :     _ggadget_move(g,x,y);
     107           0 : }
     108             : 
     109             : struct sizedata {
     110             :     int extra_space;            /* a default button has "extra_space" */
     111             :     int min;                    /* This value includes padding */
     112             :     int sized;
     113             :     int allocated;
     114             :     int allglue;
     115             : };
     116             : 
     117             : struct sizeinfo {
     118             :     struct sizedata *cols;
     119             :     struct sizedata *rows;
     120             :     int label_height, label_width;
     121             :     int width, height;
     122             :     int minwidth, minheight;
     123             : };
     124             : 
     125           0 : static void GHVBoxGatherSizeInfo(GHVBox *gb,struct sizeinfo *si) {
     126             :     int i,c,r,spanc, spanr, totc,totr, max, plus, extra, es;
     127             :     GRect outer;
     128           0 :     int ten = GDrawPointsToPixels(gb->g.base,10);
     129             : 
     130           0 :     memset(si,0,sizeof(*si));
     131           0 :     si->cols = calloc(gb->cols,sizeof(struct sizedata));
     132           0 :     si->rows = calloc(gb->rows,sizeof(struct sizedata));
     133           0 :     for ( c=0; c<gb->cols; ++c ) si->cols[c].allglue = true;
     134           0 :     for ( r=0; r<gb->rows; ++r ) si->rows[r].allglue = true;
     135             : 
     136           0 :     for ( r=0; r<gb->rows; ++r ) {
     137           0 :         for ( c=0; c<gb->cols; ++c ) {
     138           0 :             GGadget *g = gb->children[r*gb->cols+c];
     139           0 :             if ( g==GG_Glue ) {
     140           0 :                 if ( c+1!=gb->cols && si->cols[c].min<gb->hpad ) si->cols[c].min = gb->hpad;
     141           0 :                 if ( r+1!=gb->rows && si->rows[r].min<gb->vpad ) si->rows[r].min = gb->vpad;
     142           0 :             } else if ( g==GG_HPad10 ) {
     143           0 :                 if ( c+1!=gb->cols && si->cols[c].min<gb->hpad+ten ) si->cols[c].min = gb->hpad+ten;
     144           0 :                 if ( r+1!=gb->rows && si->rows[r].min<gb->vpad ) si->rows[r].min = gb->vpad+ten/2;
     145           0 :                 si->cols[c].allglue = false;
     146           0 :             } else if ( g==GG_ColSpan || g==GG_RowSpan )
     147             :                 /* Skip it */;
     148           0 :             else if ( (r+1<gb->rows && gb->children[(r+1)*gb->cols+c]==GG_RowSpan) ||
     149           0 :                       (c+1<gb->cols && gb->children[r*gb->cols+c+1]==GG_ColSpan))
     150             :                 /* This gadget spans some columns or rows. Come back later */;
     151             :             else {
     152           0 :                 GGadgetGetDesiredSize(g,&outer,NULL);
     153           0 :                 es = GBoxExtraSpace(g);
     154           0 :                 if ( c+1!=gb->cols && g->state!=gs_invisible )
     155           0 :                     outer.width += gb->hpad;
     156           0 :                 if ( r+1!=gb->rows && g->state!=gs_invisible )
     157           0 :                     outer.height += gb->vpad;
     158           0 :                 si->cols[c].allglue = false;
     159           0 :                 if ( si->cols[c].extra_space<es ) si->cols[c].extra_space=es;
     160           0 :                 if ( si->cols[c].min<outer.width ) si->cols[c].min=outer.width;
     161           0 :                 si->rows[r].allglue = false;
     162           0 :                 if ( si->rows[r].min<outer.height ) si->rows[r].min=outer.height;
     163           0 :                 if ( si->rows[r].extra_space<es ) si->rows[r].extra_space=es;
     164             :             }
     165             :         }
     166             :     }
     167             : 
     168           0 :     for ( r=0; r<gb->rows; ++r ) {
     169           0 :         for ( c=0; c<gb->cols; ++c ) {
     170           0 :             GGadget *g = gb->children[r*gb->cols+c];
     171           0 :             if ( g==GG_Glue || g==GG_ColSpan || g==GG_RowSpan || g==GG_HPad10 )
     172             :                 /* Skip it */;
     173           0 :             else if ( (r+1<gb->rows && gb->children[(r+1)*gb->cols+c]==GG_RowSpan) ||
     174           0 :                       (c+1<gb->cols && gb->children[r*gb->cols+c+1]==GG_ColSpan)) {
     175           0 :                 si->rows[r].allglue = false;
     176           0 :                 totr = si->rows[r].min;
     177           0 :                 for ( spanr=1; r+spanr<gb->rows &&
     178           0 :                         gb->children[(r+spanr)*gb->cols+c]==GG_RowSpan; ++spanr ) {
     179           0 :                     si->rows[r+spanr].allglue = false;
     180           0 :                     totr += si->rows[r+spanr].min;
     181             :                 }
     182           0 :                 si->cols[c].allglue = false;
     183           0 :                 totc = si->cols[c].min;
     184           0 :                 for ( spanc=1; c+spanc<gb->cols &&
     185           0 :                         gb->children[r*gb->cols+c+spanc]==GG_ColSpan; ++spanc ) {
     186           0 :                     si->cols[c+spanc].allglue = false;
     187           0 :                     totc += si->cols[c+spanc].min;
     188             :                 }
     189           0 :                 GGadgetGetDesiredSize(g,&outer,NULL);
     190           0 :                 es = GBoxExtraSpace(g);
     191           0 :                 if ( c+spanc!=gb->cols && g->state!=gs_invisible )
     192           0 :                     outer.width += gb->hpad;
     193           0 :                 if ( r+spanr!=gb->rows && g->state!=gs_invisible )
     194           0 :                     outer.height += gb->vpad;
     195           0 :                 if ( outer.width>totc ) {
     196           0 :                     plus = (outer.width-totc)/spanc;
     197           0 :                     extra = (outer.width-totc-spanc*plus);
     198           0 :                     for ( i=0; i<spanc; ++i ) {
     199           0 :                         si->cols[c+i].min += plus + (extra>0);
     200           0 :                         --extra;
     201             :                     }
     202             :                 }
     203           0 :                 if ( outer.height>totr ) {
     204           0 :                     plus = (outer.height-totr)/spanr;
     205           0 :                     extra = (outer.height-totr-spanr*plus);
     206           0 :                     for ( i=0; i<spanr; ++i ) {
     207           0 :                         si->rows[r+i].min += plus + (extra>0);
     208           0 :                         --extra;
     209             :                     }
     210             :                 }
     211           0 :                 if ( es!=0 ) {
     212           0 :                     for ( i=0; i<spanc; ++i ) {
     213           0 :                         if ( es>si->cols[c+i].extra_space )
     214           0 :                             si->cols[c+i].extra_space = es;
     215             :                     }
     216           0 :                     for ( i=0; i<spanr; ++i ) {
     217           0 :                         if ( es>si->rows[r+i].extra_space )
     218           0 :                             si->rows[r+i].extra_space = es;
     219             :                     }
     220             :                 }
     221             :             }
     222             :         }
     223             :     }
     224             : 
     225           0 :     if ( gb->label!=NULL ) {
     226           0 :         GGadgetGetDesiredSize(gb->label,&outer,NULL);
     227           0 :         totc = 0;
     228           0 :         for ( c=0; c<gb->cols ; ++c )
     229           0 :             totc += si->cols[c].min;
     230           0 :         outer.width += 20;              /* Set back on each side */
     231           0 :         if ( outer.width>totc ) {
     232           0 :             plus = (outer.width-totc)/gb->cols;
     233           0 :             extra = (outer.width-totc-gb->cols*plus);
     234           0 :             for ( i=0; i<gb->cols; ++i ) {
     235           0 :                 si->cols[i].min += plus + (extra>0);
     236           0 :                 --extra;
     237             :             }
     238             :         }
     239           0 :         si->label_height = outer.height;
     240           0 :         si->label_width = outer.width;
     241             :     }
     242             : 
     243           0 :     for ( max=c=0; c<gb->cols; ++c )
     244           0 :         si->cols[c].sized = si->cols[c].min;
     245           0 :     for ( max=r=0; r<gb->rows; ++r )
     246           0 :         si->rows[r].sized = si->rows[r].min;
     247             : 
     248           0 :     if ( gb->grow_col==gb_samesize ) {
     249           0 :         for ( max=c=0; c<gb->cols; ++c )
     250           0 :             if ( max<si->cols[c].sized ) max = si->cols[c].sized;
     251           0 :         for ( c=0; c<gb->cols; ++c )
     252           0 :             if ( si->cols[c].min!=0 || si->cols[c].allglue )
     253           0 :                 si->cols[c].sized = max;
     254           0 :     } else if ( gb->grow_col==gb_expandgluesame ) {
     255           0 :         for ( max=c=0; c<gb->cols; ++c )
     256           0 :             if ( max<si->cols[c].sized && !si->cols[c].allglue ) max = si->cols[c].sized;
     257           0 :         for ( c=0; c<gb->cols; ++c )
     258           0 :             if ( !si->cols[c].allglue && si->cols[c].min!=0 )     /* Must have at least one visible element */
     259           0 :                 si->cols[c].sized = max;
     260             :     }
     261             : 
     262           0 :     if ( gb->grow_row==gb_samesize ) {
     263           0 :         for ( max=r=0; r<gb->rows; ++r )
     264           0 :             if ( max<si->rows[r].sized ) max = si->rows[r].sized;
     265           0 :         for ( r=0; r<gb->rows; ++r )
     266           0 :             if ( si->rows[r].min!=0 || si->rows[r].allglue )
     267           0 :                 si->rows[r].sized = max;
     268           0 :     } else if ( gb->grow_row==gb_expandgluesame ) {
     269           0 :         for ( max=r=0; r<gb->rows; ++r )
     270           0 :             if ( max<si->rows[r].sized && !si->rows[r].allglue ) max = si->rows[r].sized;
     271           0 :         for ( r=0; r<gb->rows; ++r )
     272           0 :             if ( !si->rows[r].allglue && si->rows[r].min>0 )
     273           0 :                 si->rows[r].sized = max;
     274             :     }
     275             : 
     276           0 :     for ( i=si->width = si->minwidth = 0; i<gb->cols; ++i ) {
     277           0 :         si->width += si->cols[i].sized;
     278           0 :         si->minwidth += si->cols[i].min;
     279             :     }
     280           0 :     for ( i=0, si->height=si->minheight = si->label_height; i<gb->rows; ++i ) {
     281           0 :         si->height += si->rows[i].sized;
     282           0 :         si->minheight += si->rows[i].min;
     283             :     }
     284           0 : }
     285             : 
     286           0 : static void GHVBoxResize(GGadget *g, int32 width, int32 height) {
     287             :     struct sizeinfo si;
     288           0 :     GHVBox *gb = (GHVBox *) g;
     289           0 :     int bp = GBoxBorderWidth(g->base,g->box);
     290             :     int i,c,r,spanc, spanr, totc,totr, glue_cnt, plus, extra;
     291             :     int x,y;
     292           0 :     int old_enabled = GDrawEnableExposeRequests(g->base,false);
     293             : 
     294           0 :     GHVBoxGatherSizeInfo(gb,&si);
     295           0 :     width -= 2*bp; height -= 2*bp;
     296             : 
     297           0 :     if(width < si.minwidth) width = si.minwidth;
     298           0 :     if(height < si.minheight) height = si.minheight;
     299             : 
     300           0 :     gb->g.inner.x = gb->g.r.x + bp; gb->g.inner.y = gb->g.r.y + bp;
     301           0 :     if ( gb->label!=NULL ) {
     302           0 :         gb->label_height = si.label_height;
     303           0 :         g->inner.y += si.label_height;
     304             :     }
     305             : 
     306           0 :     if ( si.width!=width ) {
     307           0 :         int vcols=0;
     308           0 :         for ( i=0; i<gb->cols-1; ++i )
     309           0 :             if ( si.cols[i].sized>0 )
     310           0 :                 ++vcols;
     311           0 :         int vcols1 = vcols;
     312           0 :         if(si.cols[gb->cols-1].sized > 0)
     313           0 :             ++ vcols1;
     314           0 :         if ( width<si.width ) {
     315           0 :             for ( i=0; i<gb->cols; ++i )
     316           0 :                 si.cols[i].sized = si.cols[i].min;
     317           0 :             si.width = si.minwidth;
     318           0 :             if ( width<si.width && gb->hpad>1 && vcols>0 ) {
     319           0 :                 int reduce_pad = (si.width-width)/vcols + 1;
     320           0 :                 if ( reduce_pad>gb->hpad-1 ) reduce_pad = gb->hpad-1;
     321           0 :                 for ( i=0; i<gb->cols-1; ++i )
     322           0 :                     if ( si.cols[i].sized > 0 )
     323           0 :                         si.cols[i].sized -= reduce_pad;
     324           0 :                 si.width -= vcols*reduce_pad;
     325             :             }
     326             :         }
     327           0 :         if((width > si.width) && (gb->grow_col==gb_expandglue || gb->grow_col==gb_expandgluesame )) {
     328           0 :             for ( i=glue_cnt=0; i<gb->cols; ++i )
     329           0 :                 if ( si.cols[i].allglue )
     330           0 :                     ++glue_cnt;
     331           0 :             if ( glue_cnt!=0 ) {
     332           0 :                 plus = (width-si.width)/glue_cnt;
     333           0 :                 extra = (width-si.width-glue_cnt*plus);
     334           0 :                 for ( i=0; i<gb->cols; ++i ) if ( si.cols[i].allglue ) {
     335           0 :                     si.cols[i].sized += plus + (extra>0);
     336           0 :                     si.width += plus + (extra>0);
     337           0 :                     --extra;
     338             :                 }
     339             :             }
     340             :         } 
     341           0 :         if ((width != si.width) && gb->grow_col>=0 ) {
     342           0 :             int * ss = &(si.cols[gb->grow_col].sized);
     343           0 :             int w = si.width - *ss;
     344           0 :             *ss += (width-si.width);
     345           0 :             if(*ss < gb->hpad + 3)
     346           0 :                 *ss = gb->hpad + 3;
     347           0 :             si.width = w + *ss;
     348             :         } 
     349           0 :         if ((width > si.width) && (vcols1!=0)) {
     350           0 :             plus = (width-si.width)/vcols1;
     351           0 :             extra = (width-si.width-vcols1*plus);
     352           0 :             for ( i=0; i<gb->cols; ++i ) {
     353           0 :                 if ( si.cols[i].sized>0 ) {
     354           0 :                     si.cols[i].sized += plus + (extra>0);
     355           0 :                     si.width += plus + (extra>0);
     356           0 :                     --extra;
     357             :                 }
     358             :             }
     359             :         }
     360           0 :         width = si.width;
     361             :     }
     362             : 
     363           0 :     if ( si.height!=height ) {
     364           0 :         int vrows=0;
     365           0 :         for ( i=0; i<gb->rows-1; ++i )
     366           0 :             if ( si.rows[i].sized>0 )
     367           0 :                 ++vrows;
     368           0 :         int vrows1 = vrows;
     369           0 :         if(si.rows[gb->rows-1].sized > 0)
     370           0 :             ++ vrows1;
     371           0 :         if ( height<si.height ) {
     372           0 :             for ( i=0; i<gb->rows; ++i )
     373           0 :                 si.rows[i].sized = si.rows[i].min;
     374           0 :             si.height = si.minheight;
     375           0 :             if ( height<si.height && gb->vpad>1 && vrows>0 ) {
     376           0 :                 int reduce_pad = (si.height-height)/vrows + 1;
     377           0 :                 if ( reduce_pad>gb->vpad-1 ) reduce_pad = gb->vpad-1;
     378           0 :                 for ( i=0; i<gb->rows-1; ++i )
     379           0 :                     if ( si.rows[i].sized > 0 )
     380           0 :                         si.rows[i].sized -= reduce_pad;
     381           0 :                 si.height -= vrows*reduce_pad;
     382             :             }
     383             :         }
     384           0 :         if((height > si.height) && (gb->grow_row==gb_expandglue || gb->grow_row==gb_expandgluesame )) {
     385           0 :             for ( i=glue_cnt=0; i<gb->rows; ++i )
     386           0 :                 if ( si.rows[i].allglue )
     387           0 :                     ++glue_cnt;
     388           0 :             if ( glue_cnt!=0 ){
     389           0 :                 plus = (height-si.height)/glue_cnt;
     390           0 :                 extra = (height-si.height-glue_cnt*plus);
     391           0 :                 for ( i=0; i<gb->rows; ++i ) if ( si.rows[i].allglue ) {
     392           0 :                     si.rows[i].sized += plus + (extra>0);
     393           0 :                     si.height += plus + (extra>0);
     394           0 :                     --extra;
     395             :                 }
     396             :             }
     397             :         } 
     398           0 :         if ((height != si.height) && gb->grow_row>=0 ) {
     399           0 :             int * ss = &(si.rows[gb->grow_row].sized);
     400           0 :             int h = si.height - *ss;
     401           0 :             *ss += (height-si.height);
     402           0 :             if(*ss < gb->vpad + 3)
     403           0 :                 *ss = gb->vpad + 3;
     404           0 :             si.height = h + *ss;
     405             :         } 
     406           0 :         if ((height > si.height) && (vrows1!=0)) {
     407           0 :             plus = (height-si.height)/vrows1;
     408           0 :             extra = (height-si.height-vrows1*plus);
     409           0 :             for ( i=0; i<gb->rows; ++i ) {
     410           0 :                 if ( si.rows[i].sized>0 ) {
     411           0 :                     si.rows[i].sized += plus + (extra>0);
     412           0 :                     si.height += plus + (extra>0);
     413           0 :                     --extra;
     414             :                 }
     415             :             }
     416             :         }
     417           0 :         height = si.height;
     418             :     }
     419             : 
     420           0 :     y = gb->g.inner.y;
     421           0 :     if ( gb->label!=NULL ) {
     422           0 :         if ( gb->label->state!=gs_invisible )
     423           0 :             GGadgetResize( gb->label, si.label_width, si.label_height);
     424           0 :         GGadgetMove( gb->label, gb->g.inner.x+10, y-si.label_height-bp/2);
     425             :     }
     426           0 :     for ( r=0; r<gb->rows; ++r ) {
     427           0 :         x = gb->g.inner.x;
     428           0 :         for ( c=0; c<gb->cols; ++c ) {
     429           0 :             GGadget *g = gb->children[r*gb->cols+c];
     430           0 :             if ( g==GG_Glue || g==GG_ColSpan || g==GG_RowSpan || g==GG_HPad10 )
     431             :                 /* Skip it */;
     432             :             else {
     433             :                 int xes, yes, es;
     434           0 :                 totr = si.rows[r].sized;
     435           0 :                 for ( spanr=1; r+spanr<gb->rows &&
     436           0 :                         gb->children[(r+spanr)*gb->cols+c]==GG_RowSpan; ++spanr )
     437           0 :                     totr += si.rows[r+spanr].sized;
     438           0 :                 totc = si.cols[c].sized;
     439           0 :                 for ( spanc=1; c+spanc<gb->cols &&
     440           0 :                         gb->children[r*gb->cols+c+spanc]==GG_ColSpan; ++spanc )
     441           0 :                     totc += si.cols[c+spanc].sized;
     442           0 :                 if ( r+spanr!=gb->rows ) totr -= gb->vpad;
     443           0 :                 if ( c+spanc!=gb->cols ) totc -= gb->hpad;
     444           0 :                 es = GBoxExtraSpace(g);
     445           0 :                 xes = si.cols[c].extra_space - es;
     446           0 :                 yes = si.rows[r].extra_space - es;
     447           0 :                 if ( g->state!=gs_invisible )
     448           0 :                     GGadgetResize(g,totc-2*xes,totr-2*yes);
     449           0 :                 GGadgetMove(g,x+xes,y+yes);
     450             :             }
     451           0 :             x += si.cols[c].sized;
     452             :         }
     453           0 :         y += si.rows[r].sized;
     454             :     }
     455             : 
     456           0 :     free(si.cols); free(si.rows);
     457             : 
     458           0 :     gb->g.inner.width = width; gb->g.inner.height = height;
     459           0 :     gb->g.r.width = width + 2*bp; gb->g.r.height = height + 2*bp;
     460           0 :     GDrawEnableExposeRequests(g->base,old_enabled);
     461           0 :     GDrawRequestExpose(g->base,&g->r,false);
     462           0 : }
     463             : 
     464           0 : static void GHVBoxGetDesiredSize(GGadget *g, GRect *outer, GRect *inner) {
     465             :     struct sizeinfo si;
     466           0 :     GHVBox *gb = (GHVBox *) g;
     467           0 :     int bp = GBoxBorderWidth(g->base,g->box);
     468             : 
     469           0 :     GHVBoxGatherSizeInfo(gb,&si);
     470           0 :     if ( g->desired_width>0 ) si.width = g->desired_width;
     471           0 :     if ( g->desired_height>0 ) si.height = g->desired_height;
     472             : 
     473           0 :     if ( inner!=NULL ) {
     474           0 :         inner->x = inner->y = 0;
     475           0 :         inner->width = si.width; inner->height = si.height;
     476             :     }
     477           0 :     if ( outer!=NULL ) {
     478           0 :         outer->x = outer->y = 0;
     479           0 :         outer->width = si.width+2*bp; outer->height = si.height+2*bp;
     480             :     }
     481           0 :     free(si.cols); free(si.rows);
     482           0 : }
     483             : 
     484           0 : static int GHVBoxFillsWindow(GGadget *g) {
     485           0 : return( true );
     486             : }
     487             : 
     488           0 : static int expose_nothing(GWindow pixmap, GGadget *g, GEvent *event) {
     489           0 :     GHVBox *gb = (GHVBox *) g;
     490             :     GRect r;
     491             : 
     492           0 :     if ( g->state==gs_invisible )
     493           0 : return( true );
     494             : 
     495           0 :     if ( gb->label==NULL )
     496           0 :         GBoxDrawBorder(pixmap,&g->r,g->box,g->state,false);
     497             :     else {
     498           0 :         r = g->r;
     499           0 :         r.y += gb->label_height/2;
     500           0 :         r.height -= gb->label_height/2;
     501           0 :         GBoxDrawBorder(pixmap,&r,g->box,g->state,false);
     502             :         /* Background is transperant */
     503           0 :         (gb->label->funcs->handle_expose)(pixmap,gb->label,event);
     504             :     }
     505           0 : return( true );
     506             : }
     507             : 
     508             : struct gfuncs ghvbox_funcs = {
     509             :     0,
     510             :     sizeof(struct gfuncs),
     511             : 
     512             :     expose_nothing,     /* Expose */
     513             :     _ggadget_noop,      /* Mouse */
     514             :     _ggadget_noop,      /* Key */
     515             :     NULL,
     516             :     NULL,               /* Focus */
     517             :     NULL,
     518             :     NULL,
     519             : 
     520             :     _ggadget_redraw,
     521             :     GHVBoxMove,
     522             :     GHVBoxResize,
     523             :     _ggadget_setvisible,
     524             :     _ggadget_setenabled,
     525             :     _ggadget_getsize,
     526             :     _ggadget_getinnersize,
     527             : 
     528             :     GHVBox_destroy,
     529             : 
     530             :     NULL,
     531             :     NULL,
     532             :     NULL,
     533             :     NULL,
     534             :     NULL,
     535             : 
     536             :     NULL,
     537             :     NULL,
     538             : 
     539             :     NULL,
     540             :     NULL,
     541             :     NULL,
     542             :     NULL,
     543             :     NULL,
     544             :     NULL,
     545             :     NULL,
     546             :     NULL,
     547             :     NULL,
     548             :     NULL,
     549             :     NULL,
     550             : 
     551             :     GHVBoxGetDesiredSize,
     552             :     _ggadget_setDesiredSize,
     553             :     GHVBoxFillsWindow,
     554             :     NULL
     555             : };
     556             : 
     557           0 : void GHVBoxSetExpandableCol(GGadget *g,int col) {
     558           0 :     GHVBox *gb = (GHVBox *) g;
     559           0 :     if ( col<gb->cols )
     560           0 :         gb->grow_col = col;
     561           0 : }
     562             : 
     563           0 : void GHVBoxSetExpandableRow(GGadget *g,int row) {
     564           0 :     GHVBox *gb = (GHVBox *) g;
     565           0 :     if ( row < gb->rows )
     566           0 :         gb->grow_row = row;
     567           0 : }
     568             : 
     569           0 : void GHVBoxSetPadding(GGadget *g,int hpad, int vpad) {
     570           0 :     GHVBox *gb = (GHVBox *) g;
     571           0 :     gb->hpad = hpad;
     572           0 :     gb->vpad = vpad;
     573           0 : }
     574             : 
     575           0 : static GHVBox *_GHVBoxCreate(struct gwindow *base, GGadgetData *gd,void *data,
     576             :         int hcnt, int vcnt, GBox *def_box) {
     577           0 :     GHVBox *gb = calloc(1,sizeof(GHVBox));
     578             :     int i, h, v;
     579           0 :     GGadgetCreateData *label = (GGadgetCreateData *) (gd->label);
     580             : 
     581           0 :     if ( !ghvbox_inited )
     582           0 :         _GHVBox_Init();
     583             : 
     584           0 :     gd->label = NULL;
     585           0 :     gb->g.funcs = &ghvbox_funcs;
     586           0 :     _GGadget_Create(&gb->g,base,gd,data,def_box);
     587           0 :     gb->rows = vcnt; gb->cols = hcnt;
     588           0 :     gb->grow_col = gb->grow_row = gb_expandall;
     589           0 :     gb->hpad = gb->vpad = GDrawPointsToPixels(base,2);
     590             : 
     591           0 :     gb->g.takes_input = false; gb->g.takes_keyboard = false; gb->g.focusable = false;
     592             : 
     593           0 :     if ( label != NULL ) {
     594           0 :         gb->label = label->ret =
     595           0 :                 (label->creator)(base,&label->gd,label->data);
     596           0 :         gb->label->contained = true;
     597             :     }
     598             : 
     599           0 :     gb->children = malloc(vcnt*hcnt*sizeof(GGadget *));
     600           0 :     for ( i=v=0; v<vcnt; ++v ) {
     601           0 :         for ( h=0; h<hcnt && gd->u.boxelements[i]!=NULL; ++h, ++i ) {
     602           0 :             GGadgetCreateData *gcd = gd->u.boxelements[i];
     603           0 :             if ( gcd==GCD_Glue ||
     604           0 :                     gcd==GCD_ColSpan ||
     605           0 :                     gcd==GCD_RowSpan ||
     606             :                     gcd==GCD_HPad10 )
     607           0 :                 gb->children[v*hcnt+h] = (GGadget *) gcd;
     608             :             else {
     609           0 :                 gcd->gd.pos.x = gcd->gd.pos.y = 1;
     610           0 :                 gb->children[v*hcnt+h] = gcd->ret =
     611           0 :                         (gcd->creator)(base,&gcd->gd,gcd->data);
     612           0 :                 gcd->ret->contained = true;
     613             :             }
     614             :         }
     615           0 :         while ( h<hcnt )
     616           0 :             gb->children[v*hcnt+h++] = GG_Glue;
     617           0 :         if ( gd->u.boxelements[i]==NULL )
     618           0 :             ++i;
     619             :     }
     620           0 : return( gb );
     621             : }
     622             : 
     623           0 : GGadget *GHBoxCreate(struct gwindow *base, GGadgetData *gd,void *data) {
     624             :     GHVBox *gb;
     625             :     int hcnt;
     626             : 
     627           0 :     for ( hcnt=0; gd->u.boxelements[hcnt]!=NULL; ++hcnt );
     628           0 :     gb = _GHVBoxCreate(base,gd,data,hcnt,1,&hvbox_box);
     629             : 
     630           0 : return( &gb->g );
     631             : }
     632             : 
     633           0 : GGadget *GVBoxCreate(struct gwindow *base, GGadgetData *gd,void *data) {
     634             :     GHVBox *gb;
     635             :     int vcnt;
     636             : 
     637           0 :     for ( vcnt=0; gd->u.boxelements[vcnt]!=NULL; ++vcnt );
     638           0 :     gb = _GHVBoxCreate(base,gd,data,1,vcnt,&hvbox_box);
     639             : 
     640           0 : return( &gb->g );
     641             : }
     642             : 
     643           0 : GGadget *GHVBoxCreate(struct gwindow *base, GGadgetData *gd,void *data) {
     644             :     GHVBox *gb;
     645             :     int hcnt, vcnt, i;
     646             : 
     647           0 :     for ( hcnt=0; gd->u.boxelements[hcnt]!=NULL; ++hcnt );
     648           0 :     for ( i=0, vcnt=1; gd->u.boxelements[i]!=NULL || gd->u.boxelements[i+1]!=NULL ; ++i )
     649           0 :         if ( gd->u.boxelements[i]==NULL )
     650           0 :             ++vcnt;
     651           0 :     gb = _GHVBoxCreate(base,gd,data,hcnt,vcnt,&hvbox_box);
     652             : 
     653           0 : return( &gb->g );
     654             : }
     655             : 
     656           0 : GGadget *GHVGroupCreate(struct gwindow *base, GGadgetData *gd,void *data) {
     657             :     GHVBox *gb;
     658             :     int hcnt, vcnt, i;
     659             : 
     660           0 :     for ( hcnt=0; gd->u.boxelements[hcnt]!=NULL; ++hcnt );
     661           0 :     for ( i=0, vcnt=1; gd->u.boxelements[i]!=NULL || gd->u.boxelements[i+1]!=NULL ; ++i )
     662           0 :         if ( gd->u.boxelements[i]==NULL )
     663           0 :             ++vcnt;
     664           0 :     gb = _GHVBoxCreate(base,gd,data,hcnt,vcnt,&hvgroup_box);
     665             : 
     666           0 : return( &gb->g );
     667             : }
     668             : 
     669           0 : static void _GHVBoxFitWindow(GGadget *g, int center) {
     670             :     GRect outer, cur, screen;
     671             : 
     672           0 :     if ( !GGadgetFillsWindow(g)) {
     673           0 :         fprintf( stderr, "Call to GHVBoxFitWindow in something not an HVBox\n" );
     674           0 : return;
     675             :     }
     676           0 :     GHVBoxGetDesiredSize(g,&outer, NULL );
     677           0 :     GDrawGetSize(GDrawGetRoot(NULL),&screen);
     678           0 :     if ( outer.width > screen.width-20 ) outer.width = screen.width-20;
     679           0 :     if ( outer.height > screen.height-40 ) outer.height = screen.height-40;
     680           0 :     GDrawGetSize(g->base,&cur);
     681             :     /* Make any offset simmetrical */
     682           0 :     outer.width += 2*g->r.x;
     683           0 :     outer.height += 2*g->r.y;
     684           0 :     if ( cur.width!=outer.width || cur.height!=outer.height ) {
     685           0 :         GDrawResize(g->base, outer.width, outer.height );
     686             :         /* We want to get the resize before we set the window visible */
     687             :         /*  and window managers make synchronizing an issue... */
     688           0 :         GDrawSync(GDrawGetDisplayOfWindow(g->base));
     689           0 :         GDrawProcessPendingEvents(GDrawGetDisplayOfWindow(g->base));
     690           0 :         GDrawSync(GDrawGetDisplayOfWindow(g->base));
     691           0 :         GDrawProcessPendingEvents(GDrawGetDisplayOfWindow(g->base));
     692             :     } else
     693           0 :         GGadgetResize(g, outer.width-2*g->r.x, outer.height-2*g->r.y );
     694           0 :     if ( center ) {
     695           0 :         GDrawMove(g->base,(screen.width-outer.width)/2,(screen.height-outer.height)/2);
     696             :         /* I don't think this one matters as much, but try a little */
     697           0 :         GDrawSync(GDrawGetDisplayOfWindow(g->base));
     698           0 :         GDrawProcessPendingEvents(GDrawGetDisplayOfWindow(g->base));
     699             :     }
     700             : }
     701             : 
     702           0 : void GHVBoxFitWindow(GGadget *g) {
     703           0 :     _GHVBoxFitWindow(g,false);
     704           0 : }
     705             : 
     706           0 : void GHVBoxFitWindowCentered(GGadget *g) {
     707           0 :     _GHVBoxFitWindow(g,true);
     708           0 : }
     709             : 
     710           0 : void GHVBoxReflow(GGadget *g) {
     711           0 :     GHVBoxResize(g, g->r.width, g->r.height);
     712           0 : }
     713             : 
     714           0 : GResInfo *_GHVBoxRIHead(void) {
     715             : 
     716           0 :     _GHVBox_Init();
     717           0 : return( &ghvgroupbox_ri );
     718             : }

Generated by: LCOV version 1.10