Main Page   Alphabetical List   Data Structures   File List   Data Fields   Globals  

gadget_Group.c

Go to the documentation of this file.
00001 /*
00002  *    gui - [gega user interface] the flexible solution for user interface problems
00003  *    Copyright (C) 2002  Gergely Gati
00004  *
00005  *    This program is free software; you can redistribute it and/or modify
00006  *    it under the terms of the GNU General Public License as published by
00007  *    the Free Software Foundation; version 2 of the License.
00008  *
00009  *    This program is distributed in the hope that it will be useful,
00010  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *    GNU General Public License for more details.
00013  *
00014  *    You should have received a copy of the GNU General Public License
00015  *    along with this program; if not, write to the Free Software
00016  *    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  *
00018  *    Gergely Gati
00019  *      email:           g.gati@freemail.hu
00020  *      AIM screenname:  GatiGergely
00021  *      ICQ number:      93131690
00022  *
00023  */
00024 /*
00025  *  group.c
00026  */
00027 #include <stdlib.h>
00028 
00029 #include "debug.h"
00030 #include "classes.h"
00031 #include "Memory.h"
00032 #include "Bases.h"
00033 #include "Module.h"
00034 #include "Common.h"
00035 
00036 #include "gadgets/gadget_Group.h"
00037 
00038 
00039 #define ERR_NOTYPE                   "No orientation given"
00040 #define ERR_BADID                    "Bad ID given"
00041 #define ERR_BADSIZE                  "Bad size given for layout"
00042 #define ERR_DONT_SUGGEST_LARGER_SIZE "Don't suggest larger size"
00043 #define ERR_BADGADEV                 "Bad Gadget_t event arrived"
00044 
00045 #define MIN   0
00046 #define MAX   1
00047 
00048 struct gadget_stat
00049 {
00050   Gadget_t *gad;      /* pointer to the gadget          */
00051   int curr;           /* actual size                    */
00052   int limit[2];       /* 0-min 1-max                    */
00053   int in_race;        /* race for area                  */
00054   int weight;
00055   Extent_t minsize;
00056   Extent_t maxsize;
00057   Rect_t counted_rect;
00058 };
00059 
00060 struct _group
00061 {
00062   Gadget_t gadget;
00063   struct gadget_stat *gad_stat;
00064   int gad_stat_cnt;
00065   int orientation;
00066   int size;
00067   int gap_size;
00068   int border_size;
00069   int gadget_count;
00070   Rect_t act_rect;
00071   Extent_t min_ext;
00072   Extent_t max_ext;
00073   Extent_t sug_ext;
00074 };
00075 
00076 
00077 static u32 group_add_gadget(Gadget_t *this_gadget, tag *taglist);
00078 static u32 group_add_gadget_tail(Gadget_t *this_gadget, tag *taglist);
00079 static u32 group_remove_gadget(Gadget_t *this_gadget, tag *taglist);
00080 static u32 group_get_gadget(Gadget_t *this_gadget, tag *taglist);
00081 static u32 group_resize(Gadget_t *this_gadget, tag *taglist);
00082 static u32 group_get_size(Gadget_t *this_gadget, tag *taglist);
00083 static u32 group_invalidate_size(Gadget_t *this_gadget, tag *taglist);
00084 
00085 
00086 static bases_Modules_t *api;
00087 VERSION("Group.gadget",1,0,"Gergely Gati","g.gati@freemail.hu");
00088 
00089 static gadget_Method_t methods[]=
00090 {
00091   {"add_gadget",group_add_gadget,0L},
00092   {"add_gadget_tail",group_add_gadget_tail,0L},
00093   {"remove_gadget",group_remove_gadget,0L},
00094   {"get_gadget",group_get_gadget,0L},
00095   {"resize",group_resize,0L},
00096   {"get_size",group_get_size,0L},
00097   {"invalidate_size",group_invalidate_size,0L},
00098   GADGET_METHOD_DONE
00099 };
00100 
00101 
00102 static gadget_Binding_t binding[]=
00103 {
00104   {"orientation",TAG_GRP_ORIENTATION,GADGET_SELECT,"horizontal|vertical|matrix"},
00105   {"gapsize",TAG_GRP_GAPSIZE,GADGET_INT,NULL},
00106   {"bordersize",TAG_GRP_BORDERSIZE,GADGET_INT,NULL},
00107   {"size",TAG_GRP_SIZE,GADGET_SELECT,"flexible|fixed_width|fixed_height|fixed"},
00108   GADGET_BINDING_DONE
00109 };
00110 
00111 
00112 /*
00113  *  At the first call of group_get_extent() calls this to count
00114  *  the actual extents, but the following calls uses this stored
00115  *  values, and they don't call this function anymore.
00116  */
00117 static void group_real_get_extent(Gadget_t *this, Extent_t *min, Extent_t *max)
00118 {
00119   Gadget_t *node;
00120   Extent_t child_min,child_max;
00121   int gadget_count=0;
00122 
00123   debug_Begin();
00124 
00125   min->width=min->height=0;
00126   if(((group *)this)->orientation==GRP_ORIENTATION_HORIZONTAL)
00127   {
00128     debug_Message("horizontal group");
00129     max->width=0;
00130     max->height=GADGET_MAXIMUM_SIZE;
00131     for(node=(Gadget_t *)api->gadget_Call(GADGET_FIRST_CHILD,TAG_GADGET_OBJECT,this,TAG_DONE);node!=NULL;node=(Gadget_t *)api->gadget_Call(GADGET_RIGHT_BROTHER,TAG_GADGET_OBJECT,node,TAG_DONE))
00132     {
00133       debug_Message("node: %s.%04lx",node->class_data->class_name,node->gadget_id);
00134       if((node->class_data->flags&GAD_INVISIBLE)!=0) continue;
00135       api->gadget_Call(GADGET_GET_EXTENT,TAG_GADGET_OBJECT,node,TAG_GADGET_MIN,&child_min,TAG_GADGET_MAX,&child_max,TAG_DONE);
00136       debug_Message("  extent (min): %dx%d",child_min.width,child_min.height);
00137       min->width+=child_min.width;
00138       max->width+=child_max.width;
00139       if(child_min.height>min->height) min->height=child_min.height;
00140       if(child_max.height<max->height) max->height=child_max.height;
00141       gadget_count++;
00142     }
00143     if(gadget_count==0) {debug_End();return;}
00144     min->width+=(gadget_count-1)*((group *)this)->gap_size;
00145     max->width+=(gadget_count-1)*((group *)this)->gap_size;
00146   }
00147 
00148   if(((group *)this)->orientation==GRP_ORIENTATION_VERTICAL)
00149   {
00150     debug_Message("vertical group");
00151     max->width=GADGET_MAXIMUM_SIZE;
00152     max->height=0;
00153     for(node=(Gadget_t *)api->gadget_Call(GADGET_FIRST_CHILD,TAG_GADGET_OBJECT,this,TAG_DONE);node!=NULL;node=(Gadget_t *)api->gadget_Call(GADGET_RIGHT_BROTHER,TAG_GADGET_OBJECT,node,TAG_DONE))
00154     {
00155       debug_Message("node: %s.%04lx",node->class_data->class_name,node->gadget_id);
00156       if((node->class_data->flags&GAD_INVISIBLE)!=0) continue;
00157       api->gadget_Call(GADGET_GET_EXTENT,TAG_GADGET_OBJECT,node,TAG_GADGET_MIN,&child_min,TAG_GADGET_MAX,&child_max,TAG_DONE);
00158       debug_Message("  extent (min): %dx%d",child_min.width,child_min.height);
00159       min->height+=child_min.height;
00160       max->height+=child_max.height;
00161       if(child_min.width>min->width) min->width=child_min.width;
00162       if(child_max.width<max->width) max->width=child_max.width;
00163       gadget_count++;
00164     }
00165     if(gadget_count==0) {debug_End();return;}
00166     min->height+=(gadget_count-1)*((group *)this)->gap_size;
00167     max->height+=(gadget_count-1)*((group *)this)->gap_size;
00168   }
00169 
00170   if(max->height<min->height) max->height=min->height;
00171   if(max->width<min->width) max->width=min->width;
00172   debug_Message("  ID=%04lx -- %dx%d -> %dx%d (+border=%d)",this->gadget_id,min->width,min->height,max->width,max->height,((group *)this)->border_size);
00173   min->width+=((group *)this)->border_size*2;
00174   max->width+=((group *)this)->border_size*2;
00175   min->height+=((group *)this)->border_size*2;
00176   max->height+=((group *)this)->border_size*2;
00177   if(((group *)this)->size==GRP_SIZE_FIXED_HEIGHT) max->height=min->height;
00178   if(((group *)this)->size==GRP_SIZE_FIXED_WIDTH) max->width=min->width;
00179   ((group *)this)->gadget_count=gadget_count;
00180   debug_Message("TOTAL: %d gadgets",gadget_count);
00181 
00182   debug_End();
00183 }
00184 
00185 
00186 /*
00187  *  This function is always called after the Gadget_t has been created and
00188  *  attached to the Gadget_t tree, but before the call to group_layout(). It may be
00189  *  called more than once. It must fill in the Gadget_t's minimum and maximum
00190  *  sizes into the supplied extent structures.
00191  */
00192 static void group_get_extent(Gadget_t *this, Extent_t *min, Extent_t *max)
00193 {
00194   debug_Begin();
00195 
00196   if(this!=NULL)
00197   {
00198     if(((group *)this)->min_ext.width>0)
00199     {
00200       min->width=((group *)this)->min_ext.width;
00201       min->height=((group *)this)->min_ext.height;
00202       max->width=((group *)this)->max_ext.width;
00203       max->height=((group *)this)->max_ext.height;
00204     }
00205     else
00206     {
00207       group_real_get_extent(this,min,max);
00208       ((group *)this)->min_ext.width=min->width;
00209       ((group *)this)->min_ext.height=min->height;
00210       ((group *)this)->max_ext.width=max->width;
00211       ((group *)this)->max_ext.height=max->height;
00212     }
00213   }
00214   debug_Message("  ID=%04lx  %dx%d -> %dx%d",this->gadget_id,min->width,min->height,max->width,max->height);
00215 
00216   debug_End();
00217 }
00218 
00219 
00220 static void group_damage(Gadget_t *this, Rect_t *rect)
00221 {
00222   int i;
00223   group *gad=(group *)this;
00224   Rect_t rgad;
00225 
00226   debug_Begin();
00227 
00228   for(i=0;i<gad->gadget_count;i++)
00229   {
00230     if(api->gui_Call(GUI_ISOVERLAP,TAG_GUI_R1,rect,TAG_GUI_R2,&gad->gad_stat[i].counted_rect,TAG_DONE))
00231     {
00232       api->gui_Call(GUI_CALCULATEOVERLAP,TAG_GUI_R1,rect,TAG_GUI_R2,&gad->gad_stat[i].counted_rect,TAG_GUI_R3,&rgad,TAG_DONE);
00233       api->gadget_Call(GADGET_DAMAGE,TAG_GADGET_OBJECT,gad->gad_stat[i].gad,TAG_GADGET_RECT,&rgad,TAG_DONE);
00234     }
00235   }
00236 
00237   debug_End();
00238 }
00239 
00240 
00241 static int group_calculate_layout_sizes(group *this, Rect_t *rect)
00242 {
00243   Gadget_t *gad;
00244   int gad_cnt,W,i,dist=0,dist2;
00245   struct gadget_stat *gadst;
00246   Rect_t srect;
00247   int left,top,lm,w,racers;
00248   int opt_inc,cur_inc,max_inc,need;
00249 
00250   debug_Begin();
00251 
00252   if(this->gadget_count>0&&(this->gad_stat!=NULL||NULL!=(this->gad_stat=mem_malloc(this->gadget_count*sizeof(struct gadget_stat)))))
00253   {
00254     gadst=this->gad_stat;
00255     memcpy(&this->act_rect,rect,sizeof(Rect_t));
00256     this->sug_ext.width=rect->width;
00257     this->sug_ext.height=rect->height;
00258 
00259     if(this->orientation==GRP_ORIENTATION_HORIZONTAL) dist=rect->width;
00260     else if(this->orientation==GRP_ORIENTATION_VERTICAL) dist=rect->height;
00261     else debug_Error("Orientation not supported!");
00262 
00263     for(i=W=0,gad=(Gadget_t *)api->gadget_Call(GADGET_FIRST_CHILD,TAG_GADGET_OBJECT,(Gadget_t *)this,TAG_DONE);gad!=NULL;gad=(Gadget_t *)api->gadget_Call(GADGET_RIGHT_BROTHER,TAG_GADGET_OBJECT,gad,TAG_DONE))
00264     {
00265       if((gad->class_data->flags&GAD_INVISIBLE)==0)
00266       {
00267         W+=gad->weight;
00268         gadst[i].in_race=1;
00269         gadst[i].gad=gad;
00270         gadst[i].weight=gad->weight;
00271         api->gadget_Call(GADGET_GET_EXTENT,TAG_GADGET_OBJECT,gadst[i].gad,TAG_GADGET_MIN,&gadst[i].minsize,TAG_GADGET_MAX,&gadst[i].maxsize,TAG_DONE);
00272         if(this->orientation==GRP_ORIENTATION_HORIZONTAL)
00273         {
00274           gadst[i].limit[MIN]=gadst[i].minsize.width;
00275           gadst[i].limit[MAX]=gadst[i].maxsize.width;
00276         }
00277         else // ha tobb orientation lesz, akkor ide else if() kell
00278         {
00279           gadst[i].limit[MIN]=gadst[i].minsize.height;
00280           gadst[i].limit[MAX]=gadst[i].maxsize.height;
00281         }
00282         i++;
00283       }
00284     }
00285     this->gad_stat_cnt=gad_cnt=i;
00286     dist-=((gad_cnt-1)*this->gap_size)+(this->border_size<<1);
00287 
00288     do
00289     {
00290       for(dist2=dist,w=W,i=0;i<gad_cnt;i++)
00291       {
00292         if(gadst[i].in_race==0) continue;
00293         gadst[i].curr=(dist2*gadst[i].weight)/w;
00294         dist-=gadst[i].curr;
00295         dist2-=gadst[i].curr;
00296         w-=gadst[i].weight;
00297         if(gadst[i].curr<gadst[i].limit[MIN])
00298         {
00299           dist+=gadst[i].curr-gadst[i].limit[MIN];
00300           gadst[i].curr=gadst[i].limit[MIN];
00301         }
00302         else if(gadst[i].curr>gadst[i].limit[MAX])
00303         {
00304           dist+=gadst[i].curr-gadst[i].limit[MAX];
00305           gadst[i].curr=gadst[i].limit[MAX];
00306         }
00307       }
00308       if(dist==0) break;
00309       lm=(dist>0?MAX:MIN);
00310       for(i=0;i<gad_cnt;i++)
00311       {
00312         if(gadst[i].in_race==0) continue;
00313         if(gadst[i].curr==gadst[i].limit[lm])
00314         {
00315           gadst[i].in_race=0;
00316           W-=gadst[i].weight;
00317         }
00318         else dist+=gadst[i].curr;
00319       }
00320     } while(1);
00321 
00322     // suggest extent
00323     need=W=racers=0;
00324     if(this->orientation==GRP_ORIENTATION_HORIZONTAL)
00325     {
00326       for(i=0;i<gad_cnt;i++)
00327       {
00328         gadst[i].counted_rect.width=gadst[i].curr;
00329         gadst[i].counted_rect.height=rect->height-(this->border_size<<1);
00330         if(gadst[i].maxsize.height<gadst[i].counted_rect.height) gadst[i].counted_rect.height=gadst[i].maxsize.height;
00331         memcpy(&srect,&gadst[i].counted_rect,sizeof(Rect_t));
00332         debug_Message("[horiz] %04lx's child: %04lx min=%dx%d max=%dx%d curr=%dx%d",this->gadget.gadget_id,gadst[i].gad->gadget_id,gadst[i].minsize.width,gadst[i].minsize.height,gadst[i].maxsize.width,gadst[i].maxsize.height,srect.width,srect.height);
00333         if(srect.height<gadst[i].minsize.height) debug_Error("ROSSZ MAGASSAG ID=%04lx min=%d curr=%d rect.height=%d",gadst[i].gad->gadget_id,gadst[i].minsize.height,srect.height,rect->height);
00334         api->gadget_Call(GADGET_SUGGEST_EXTENT,TAG_GADGET_OBJECT,gadst[i].gad,TAG_GADGET_RECT,&srect,TAG_DONE);
00335         gadst[i].in_race=1;
00336         W+=gadst[i].weight;
00337         if(srect.width<=gadst[i].counted_rect.width&&srect.height<=gadst[i].counted_rect.height)
00338         {
00339           gadst[i].counted_rect.height=srect.height;
00340           if(srect.width<gadst[i].counted_rect.width)
00341           {
00342             gadst[i].in_race=0;
00343             W-=gadst[i].weight;
00344             need+=gadst[i].counted_rect.width-srect.width;
00345             gadst[i].counted_rect.width=srect.width;
00346           }
00347         }
00348         else debug_Error(ERR_DONT_SUGGEST_LARGER_SIZE " gadget_id=%04lx",gadst[i].gad->gadget_id);
00349         gadst[i].curr=gadst[i].counted_rect.width;
00350         racers+=gadst[i].in_race;
00351       }
00352     }
00353     else // GRP_ORIENTATION_VERTICAL
00354     {
00355       for(i=0;i<gad_cnt;i++)
00356       {
00357         gadst[i].counted_rect.width=rect->width-(this->border_size<<1);
00358         gadst[i].counted_rect.height=gadst[i].curr;
00359         if(gadst[i].maxsize.width<gadst[i].counted_rect.width) gadst[i].counted_rect.width=gadst[i].maxsize.width;
00360         memcpy(&srect,&gadst[i].counted_rect,sizeof(Rect_t));
00361         debug_Message("[vert] %04lx's child: %04lx min=%dx%d max=%dx%d curr=%dx%d",this->gadget.gadget_id,gadst[i].gad->gadget_id,gadst[i].minsize.width,gadst[i].minsize.height,gadst[i].maxsize.width,gadst[i].maxsize.height,srect.width,srect.height);
00362         if(srect.width<gadst[i].minsize.width) debug_Error("ROSSZ SZELESSEG ID=%04lx min=%d curr=%d",gadst[i].gad->gadget_id,gadst[i].minsize.width,srect.width);
00363         api->gadget_Call(GADGET_SUGGEST_EXTENT,TAG_GADGET_OBJECT,gadst[i].gad,TAG_GADGET_RECT,&srect,TAG_DONE);
00364         gadst[i].in_race=1;
00365         W+=gadst[i].weight;
00366         if(srect.width<=gadst[i].counted_rect.width&&srect.height<=gadst[i].counted_rect.height)
00367         {
00368           gadst[i].counted_rect.width=srect.width;
00369           if(srect.height<gadst[i].counted_rect.height)
00370           {
00371             gadst[i].in_race=0;
00372             W-=gadst[i].weight;
00373             need+=gadst[i].counted_rect.height-srect.height;
00374             gadst[i].counted_rect.height=srect.height;
00375           }
00376         }
00377         else debug_Error(ERR_DONT_SUGGEST_LARGER_SIZE " gadget_id=%04lx",gadst[i].gad->gadget_id);
00378         gadst[i].curr=gadst[i].counted_rect.height;
00379         racers+=gadst[i].in_race;
00380       }
00381     }
00382     while(racers>0&&need>0)
00383     {
00384       for(w=W,i=0;i<gad_cnt;i++)
00385       {
00386         if(gadst[i].in_race==0) continue;
00387         opt_inc=(need*gadst[i].weight)/w;
00388         max_inc=gadst[i].limit[MAX]-gadst[i].curr;
00389         cur_inc=min(opt_inc,max_inc);
00390         if(opt_inc>=max_inc)
00391         {
00392           cur_inc=max_inc;
00393           racers--;
00394           gadst[i].in_race=0;
00395           W-=gadst[i].weight;
00396         }
00397         w-=gadst[i].weight;
00398         gadst[i].curr+=cur_inc;
00399         need-=cur_inc;
00400       }
00401     }
00402 
00403     left=rect->left+this->border_size;
00404     top=rect->top+this->border_size;
00405     if(this->orientation==GRP_ORIENTATION_HORIZONTAL)
00406     {
00407       this->sug_ext.height=0;
00408       left+=need>>1;
00409       for(i=0;i<gad_cnt;i++)
00410       {
00411         gadst[i].counted_rect.width=gadst[i].curr;
00412         gadst[i].counted_rect.top=top+(((rect->height-(this->border_size<<1))-gadst[i].counted_rect.height)>>1);
00413         gadst[i].counted_rect.left=left;
00414         if(gadst[i].counted_rect.height>this->sug_ext.height) this->sug_ext.height=gadst[i].counted_rect.height;
00415         left+=gadst[i].counted_rect.width+this->gap_size;
00416       }
00417       this->sug_ext.width=rect->width-need;
00418       this->sug_ext.height+=this->border_size<<1;
00419     }
00420     else if(this->orientation==GRP_ORIENTATION_VERTICAL)
00421     {
00422       this->sug_ext.width=0;
00423       top+=need>>1;
00424       for(i=0;i<gad_cnt;i++)
00425       {
00426         gadst[i].counted_rect.height=gadst[i].curr;
00427         gadst[i].counted_rect.top=top;
00428         gadst[i].counted_rect.left=left+(((rect->width-(this->border_size<<1))-gadst[i].counted_rect.width)>>1);
00429         if(gadst[i].counted_rect.width>this->sug_ext.width) this->sug_ext.width=gadst[i].counted_rect.width;
00430         top+=gadst[i].counted_rect.height+this->gap_size;
00431       }
00432       this->sug_ext.width+=this->border_size<<1;
00433       this->sug_ext.height=rect->height-need;
00434     }
00435   }
00436 
00437   debug_End();
00438 
00439   return(0);
00440 }
00441 
00442 
00443 static void group_suggest_extent(Gadget_t *this, Rect_t *rect)
00444 {
00445 
00446   debug_Begin();
00447 
00448   if(0==(group_calculate_layout_sizes((group *)this, rect)))
00449   {
00450     rect->width=((group *)this)->sug_ext.width;
00451     rect->height=((group *)this)->sug_ext.height;
00452   }
00453 
00454   debug_End();
00455 }
00456 
00457 /*
00458  *  This function is called always after group_get_extent() has been called at
00459  *  least once. It receives a position and an extent which determine the
00460  *  position and the size of the Gadget_t on the screen. This extent is always
00461  *  between the minimum and maximum sizes which were returned by
00462  *  group_get_extent() of the same gadget. After this call the Gadget_t is made
00463  *  visible.
00464  */
00465 static void group_layout(Gadget_t *this, Rect_t *rect)
00466 {
00467   int i;
00468 
00469   debug_Begin();
00470 
00471   debug_Message("----ID=%04lx  %dx%d",this->gadget_id,rect->width,rect->height);
00472   if(0==(group_calculate_layout_sizes((group *)this,rect)))
00473   {
00474     for(i=0;i<((group *)this)->gad_stat_cnt;i++)
00475     {
00476       api->gadget_Call(GADGET_LAYOUT,TAG_GADGET_OBJECT,((group *)this)->gad_stat[i].gad,TAG_GADGET_RECT,&((group *)this)->gad_stat[i].counted_rect,TAG_DONE);
00477     }
00478   }
00479 
00480   debug_End();
00481 }
00482 
00483 
00484 static int group_input_event_handler(Gadget_t *gad, struct glw_Event *event)
00485 {
00486   group *this;
00487   int ret=-1;
00488 
00489   debug_Begin();
00490 
00491   this=(group *)gad;
00492   switch(event->event)
00493   {
00494     case GLWEV_KEYUP:
00495     {
00496       printf("%04lx key up\n",gad->gadget_id);
00497       ret=0;
00498       break;
00499     }
00500     case GLWEV_KEYDOWN:
00501     {
00502       printf("%04lx key down\n",gad->gadget_id);
00503       ret=0;
00504       break;
00505     }
00506   }
00507 
00508   debug_End();
00509 
00510   return(ret);
00511 }
00512 
00513 
00514 static int group_init_gadget(Gadget_t *this, tag *taglist)
00515 {
00516   debug_Begin();
00517 
00518   ((group *)this)->orientation=tag_GetTagData(taglist,TAG_GRP_ORIENTATION,0L);
00519   ((group *)this)->size=tag_GetTagData(taglist,TAG_GRP_SIZE,0L);
00520   ((group *)this)->gap_size=tag_GetTagData(taglist,TAG_GRP_GAPSIZE,0L);
00521   ((group *)this)->border_size=tag_GetTagData(taglist,TAG_GRP_BORDERSIZE,0L);
00522   ((group *)this)->gad_stat=NULL;
00523   ((group *)this)->min_ext.width=-1;
00524   ((group *)this)->max_ext.width=-1;
00525   ((group *)this)->min_ext.height=-1;
00526   ((group *)this)->max_ext.height=-1;
00527   ((group *)this)->gadget_count=0;
00528 
00529   debug_End();
00530 
00531   return(0);
00532 }
00533 
00534 static void group_delete_gadget(Gadget_t *this)
00535 {
00536   if(((group *)this)->gad_stat!=NULL)
00537   {
00538     mem_free(((group *)this)->gad_stat);
00539     ((group *)this)->gad_stat=NULL;
00540   }
00541 }
00542 
00543 /*
00544  *  Since the group become dynamic, you able to add gadgets (or groups) to it.
00545  *  You must create (and setup) your gadgets and call this function to add
00546  *  and make visible the new Gadget_t in the group. This function may returns
00547  *  FALSE, if the available extents less than the required. In this case the
00548  *  Gadget_t isn't added.
00549  */
00550 static u32 group_add_gadget_tail(Gadget_t *this_gadget, tag *taglist)
00551 {
00552   return(0L);
00553 }
00554 
00555 static u32 group_add_gadget(Gadget_t *this_gadget, tag *taglist)
00556 {
00557   return(0L);
00558 }
00559 
00560 
00561 /*
00562  *  Removes the given gadget.
00563  */
00564 static u32 group_remove_gadget(Gadget_t *this_gadget, tag *taglist)
00565 {
00566   return(0L);
00567 }
00568 
00569 
00570 /*
00571  *  Returns the Gadget_t at position 'index'.
00572  */
00573 static u32 group_get_gadget(Gadget_t *this_gadget, tag *taglist)
00574 {
00575   return(0L);
00576 }
00577 
00578 
00579 /*
00580  *  Experimental function, do not use. It works fine, but it doesn't fit into our concepts.
00581  *  Until the window doesn't become resizeable it's unusable.
00582  */
00583 static u32 group_resize(Gadget_t *this_gadget, tag *taglist)
00584 {
00585   return(0L);
00586 }
00587 
00588 
00589 /*
00590  *  Returns the actual extent of the given group.
00591  */
00592 static u32 group_get_size(Gadget_t *this_gadget, tag *taglist)
00593 {
00594   return(0L);
00595 }
00596 
00597 
00598 static u32 group_invalidate_size(Gadget_t *this_gadget, tag *taglist)
00599 {
00600   if(this_gadget!=NULL) ((group *)this_gadget)->min_ext.width=-1;
00601   return(0L);
00602 }
00603 
00604 static int group_gadget_event_handler(Gadget_t *this, int event, tag *taglist)
00605 {
00606   int ret=-1;
00607 
00608   debug_Begin();
00609 
00610   if(this!=NULL&&event>=0)
00611   {
00612     switch(event)
00613     {
00614       case GADEV_INIT_GADGET:
00615       {
00616         ret=group_init_gadget(this,taglist);
00617         break;
00618       }
00619       case GADEV_DELETE_GADGET:
00620       {
00621         group_delete_gadget(this);
00622         ret=0;
00623         break;
00624       }
00625       case GADEV_GET_EXTENT:
00626       {
00627         Extent_t *min,*max,n,x;
00628         min=(Extent_t *)tag_GetTagData(taglist,TAG_GAD_EXTMIN,(u32)&n);
00629         max=(Extent_t *)tag_GetTagData(taglist,TAG_GAD_EXTMAX,(u32)&x);
00630         group_get_extent(this,min,max);
00631         ret=0;
00632         break;
00633       }
00634       case GADEV_SUGGEST_EXTENT:
00635       {
00636         Rect_t *rect,r;
00637         rect=(Rect_t *)tag_GetTagData(taglist,TAG_GAD_RECT,(u32)&r);
00638         group_suggest_extent(this,rect);
00639         ret=0;
00640         break;
00641       }
00642       case GADEV_LAYOUT:
00643       {
00644         Rect_t *rect,r;
00645         rect=(Rect_t *)tag_GetTagData(taglist,TAG_GAD_RECT,(u32)&r);
00646         group_layout(this,rect);
00647         ret=0;
00648         break;
00649       }
00650       case GADEV_DAMAGE:
00651       {
00652         Rect_t *rect,r;
00653         rect=(Rect_t *)tag_GetTagData(taglist,TAG_GAD_RECT,(u32)&r);
00654         group_damage(this,rect);
00655         ret=0;
00656         break;
00657       }
00658       case GADEV_SAVE:
00659       {
00660         u8 **mem;
00661         int *size;
00662         u32 *p;
00663         mem=(u8 **)tag_GetTagData(taglist,TAG_GADGET_MEM,0L);
00664         size=(int *)tag_GetTagData(taglist,TAG_GADGET_SIZE,0L);
00665         *size=4*sizeof(u32);
00666         if(NULL!=(*mem=mem_malloc(*size)))
00667         {
00668           p=(u32 *)*mem;
00669           *p++=api->glw_Call(GLW_HTONL2,TAG_GLW_VALUE,(u32)((group *)this)->orientation,TAG_DONE);
00670           *p++=api->glw_Call(GLW_HTONL2,TAG_GLW_VALUE,(u32)((group *)this)->size,TAG_DONE);
00671           *p++=api->glw_Call(GLW_HTONL2,TAG_GLW_VALUE,(u32)((group *)this)->gap_size,TAG_DONE);
00672           *p++=api->glw_Call(GLW_HTONL2,TAG_GLW_VALUE,(u32)((group *)this)->border_size,TAG_DONE);
00673           ret=0;
00674         }
00675         break;
00676       }
00677       case GADEV_RESTORE:
00678       {
00679         u8 *mem;
00680         int size;
00681         u32 *p;
00682         mem=(u8 *)tag_GetTagData(taglist,TAG_GADGET_MEM,0L);
00683         size=(int)tag_GetTagData(taglist,TAG_GADGET_SIZE,0L);
00684         if(size==(4*sizeof(u32)))
00685         {
00686           p=(u32 *)mem;
00687           ((group *)this)->orientation=(int)api->glw_Call(GLW_NTOHL2,TAG_GLW_VALUE,*p++,TAG_DONE);
00688           ((group *)this)->size=(int)api->glw_Call(GLW_NTOHL2,TAG_GLW_VALUE,*p++,TAG_DONE);
00689           ((group *)this)->gap_size=(int)api->glw_Call(GLW_NTOHL2,TAG_GLW_VALUE,*p++,TAG_DONE);
00690           ((group *)this)->border_size=(int)api->glw_Call(GLW_NTOHL2,TAG_GLW_VALUE,*p++,TAG_DONE);
00691           ret=0;
00692         }
00693         break;
00694       }
00695     }
00696   }
00697 
00698   debug_End();
00699 
00700   return(ret);
00701 }
00702 
00703 
00704 /*
00705  *  This function is called once before the creation of any Gadget_t of this
00706  *  class. Gadgets can be created only after this function has been called.
00707  */
00708 static void init_group_class(u32 module)
00709 {
00710   api->gadget_Call(GADGET_REGISTER_CLASS,
00711                             TAG_GADGET_CLASS_ID,CLASS_GROUP_ID,
00712                             TAG_GADGET_NAME,CLASS_GROUP_NAME,
00713                 TAG_GADGET_BINDING,binding,
00714                 TAG_GADGET_COLOR_NAMES,NULL,
00715                 TAG_GADGET_CUSTOM_NAMES,NULL,
00716                 TAG_GADGET_STATE_MASK,GADSTF_NORMAL,
00717                 TAG_GADGET_MODULE,module,
00718                 TAG_GADGET_GADGET_SIZE,sizeof(group),
00719                 TAG_GADGET_METHODS,methods,
00720                 TAG_GADGET_INPUT_EVENT_HANDLER,group_input_event_handler,
00721                 TAG_GADGET_EVENT_HANDLER,NULL,
00722                 TAG_GADGET_GADGET_EVENT_HANDLER,group_gadget_event_handler,
00723                 TAG_DONE);
00724 }
00725 
00726 
00727 EXPORT int module_Init(u32 module, bases_Modules_t *bases)
00728 {
00729     api=bases;
00730     init_group_class(module);
00731     return(0);
00732 }

Generated on Tue Jan 7 12:11:19 2003 for THEGUI by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002