home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 3 / AACD03.BIN / AACD / Programming / Triton / Source / classes / group.c < prev    next >
C/C++ Source or Header  |  1998-05-23  |  18KB  |  533 lines

  1. /*
  2.  *  OpenTriton -- A free release of the triton.library source code
  3.  *  Copyright (C) 1993-1998  Stefan Zeiger
  4.  *
  5.  *  This program is free software; you can redistribute it and/or modify
  6.  *  it under the terms of the GNU General Public License as published by
  7.  *  the Free Software Foundation; either version 2 of the License, or
  8.  *  (at your option) any later version.
  9.  *
  10.  *  This program is distributed in the hope that it will be useful,
  11.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  *  GNU General Public License for more details.
  14.  *
  15.  *  You should have received a copy of the GNU General Public License
  16.  *  along with this program; if not, write to the Free Software
  17.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  *
  19.  */
  20.  
  21.  
  22. /****** triton.library/class_Group ******
  23. *
  24. *   NAME    
  25. *    class_Group -- A grouping object
  26. *
  27. *   SUPERCLASS
  28. *    class_DisplayObject
  29. *
  30. *   SYNOPSIS
  31. *    TRGR_Horiz
  32. *    TRGR_Vert
  33. *
  34. *   ATTRIBUTES
  35. *    <Default>        : ULONG flags
  36. *                       - TRGR_PROPSHARE  : Divide objects
  37. *                                           proportionally
  38. *                       - TRGR_EQUALSHARE : Divide objects equally
  39. *                       - TRGR_PROPSPACES : Divide spaces
  40. *                                           proportionally
  41. *                       - TRGR_ARRAY      : Top group of an array. Lines
  42. *                                           or culumns can be built
  43. *                                           using TRGR_PROPSHARE groups.
  44. *                                           At least one group must
  45. *                                           be contained in an array.
  46. *                       - TRGR_ALIGN      : Align resizable objects in
  47. *                                           their secondary dimension
  48. *                       - TRGR_CENTER     : Center non-resizable
  49. *                                           objects in their secondary
  50. *                                           dimension
  51. *                       - TRGR_FIXHORIZ   : Don't allow horizontal
  52. *                                           resizing
  53. *                       - TRGR_FIXVERT    : Don't allow vertical
  54. *                                           resizing
  55. *                       - TRGR_INDEP (V2) : Group is independent of
  56. *                                           surrounding array
  57. *                       [create]
  58. *    TRAT_ID          : ULONG objectid (V4)
  59. *                       [create]
  60. *    <other>          : Treated as elements of the group
  61. *                       [create]
  62. *    TRGR_End         : <unused> : Marks the end of the group
  63. *                       [create]
  64. *
  65. *   NOTES
  66. *    An array group must contain at least one non-space object.
  67. *
  68. ******/
  69.  
  70.  
  71. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  72. //////////////////////////////////////////////////////////////////////////////////////// Include our stuff //
  73. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  74.  
  75. #define TR_THIS_IS_TRITON
  76.  
  77. #include <clib/alib_protos.h>
  78. #include <libraries/triton.h>
  79. #include <clib/triton_protos.h>
  80. #include "/internal.h"
  81. #include "group.def"
  82.  
  83.  
  84. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  85. ////////////////////////////////////////////////////////////////////////////////////////////// Object data //
  86. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  87.  
  88. #define OBJECT (&(object->DO.O))
  89. #define DISPLAYOBJECT (&(object->DO))
  90. #define GROUP object
  91.  
  92. #define CHILDOBJECT (&(child->O))
  93. #define CHILDGROUP ((struct TROD_Group *)(child))
  94.  
  95.  
  96. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  97. ////////////////////////////////////////////////////////////////////////////////////////////////// Methods //
  98. /////////////////////////////////////////////////////////////////////////////////////////////////////////////
  99.  
  100. TR_DEFAULTMETHOD(Group)
  101. {
  102.   ULONG width=0, height=0, spacewidth=0, spaceheight=0,left,top,maxsize,totalsize,newmaxsize;
  103.   ULONG maxwidth=0, maxheight=0, maxspacewidth=0, maxspaceheight=0, newspacewidth, newspaceheight;
  104.   struct TROD_DisplayObject *child=NULL, *child2;
  105.   BOOL childresize;
  106.   struct TROM_NewData newdata;
  107.   struct TROM_InstallData installdata;
  108.   ULONG objecttype;
  109.   ULONG numobj=0,currobj;
  110.   BOOL resizable;
  111.   ULONG retval;
  112.   struct TROM_SetAttributeData sadata;
  113.  
  114.   switch(messageid)
  115.   {
  116.     case TROM_NEW:
  117.  
  118.       NEWDATA->parseargs=FALSE;
  119.       if(!TRDP_DisplayObject_NEW(object,messageid,data,metaclass->trc_SuperClass)) return NULL;
  120.       objecttype=NEWDATA->objecttype; /* Are we horiz. or vert.? */
  121.       GROUP->Flags=(ULONG)(NEWDATA->itemdata);
  122.       NewList((struct List *)&(GROUP->ObjectList));
  123.  
  124.       /* Fill in the TROM_NewData fields for all child objects */
  125.       newdata.project=NEWDATA->project;
  126.       newdata.grouptype=objecttype;
  127.       newdata.backfilltype=DISPLAYOBJECT->BackfillType;
  128.  
  129.       /* Set the resizability flags to their defaults */
  130.       if(objecttype==TRGR_Horiz)
  131.     {
  132.       if(GROUP->Flags&TRGR_PROPSPACES)
  133.         DISPLAYOBJECT->XResize=TRUE; else DISPLAYOBJECT->XResize=FALSE;
  134.       DISPLAYOBJECT->YResize=TRUE;
  135.     }
  136.       else
  137.     {
  138.       if(GROUP->Flags&TRGR_PROPSPACES)
  139.         DISPLAYOBJECT->YResize=TRUE; else DISPLAYOBJECT->YResize=FALSE;
  140.       DISPLAYOBJECT->XResize=TRUE;
  141.     }
  142.  
  143.       for(;;) /* Go through all child objects */
  144.     continue_here:
  145.     {
  146.       if(NEWDATA->firstitem->ti_Tag==TRGR_End) break; /* No more objects */
  147.  
  148.       if(!child) /* No objects yet */
  149.         if((TR_GetTagType(NEWDATA->firstitem->ti_Tag)==TRTG_OAT)&&(NEWDATA->firstitem->ti_Tag!=TRGR_End))
  150.           {
  151.         switch(NEWDATA->firstitem->ti_Tag)
  152.           {
  153.           case TRAT_ID:
  154.             DISPLAYOBJECT->ID=NEWDATA->firstitem->ti_Data;
  155.             break;
  156.           case TRAT_Disabled:
  157.             if(NEWDATA->firstitem->ti_Data) DISPLAYOBJECT->Flags|=TROB_DISPLAYOBJECT_DISABLED;
  158.             else DISPLAYOBJECT->Flags&=~TROB_DISPLAYOBJECT_DISABLED;
  159.             break;
  160.           default:
  161.             sadata.attribute=NEWDATA->firstitem->ti_Tag;
  162.             sadata.value=NEWDATA->firstitem->ti_Data;
  163.             TR_DoMethod(OBJECT,TROM_SETATTRIBUTE,(APTR)(&sadata));
  164.           }
  165.         NEWDATA->firstitem++;
  166.         goto continue_here;
  167.           }
  168.  
  169.       /* Fill in the TROM_NewData fields for the next child object */
  170.       newdata.firstitem=(((struct TROM_NewData *)(data))->firstitem)+1;
  171.       newdata.objecttype=NEWDATA->firstitem->ti_Tag;
  172.       newdata.itemdata=NEWDATA->firstitem->ti_Data;
  173.       newdata.parseargs=TRUE;
  174.  
  175.       /** Initialize the child object */
  176.       if(!(child=(struct TROD_DisplayObject *)TR_DoMethod(NULL,TROM_NEW,(APTR)&newdata)))
  177.         return NULL;
  178.       AddTail((struct List *)(&(GROUP->ObjectList)),(struct Node *)child);
  179.       NEWDATA->firstitem=newdata.firstitem;
  180.  
  181.       /* Resizable object? */
  182.       if(GROUP->Flags&TRGR_PROPSPACES) /* Resizable spaces, fixed objects */
  183.         {
  184.           if(child->Flags&TROB_DISPLAYOBJECT_SPACE)
  185.         resizable=TRUE;
  186.           else resizable=FALSE;
  187.         }
  188.       else /* Resizablility depends on object */
  189.         {
  190.           if(((objecttype==TRGR_Horiz)&&(child->XResize==TRUE))||
  191.          ((objecttype!=TRGR_Horiz)&&(child->YResize==TRUE)))
  192.         resizable=TRUE;
  193.           else resizable=FALSE;
  194.         }
  195.  
  196.       if(resizable)
  197.         {
  198.           numobj++;
  199.           width+=child->MinWidth;
  200.           height+=child->MinHeight;
  201.           maxwidth=max(maxwidth,child->MinWidth);
  202.           maxheight=max(maxheight,child->MinHeight);
  203.         }
  204.       else
  205.         {
  206.           spacewidth+=child->MinWidth;
  207.           spaceheight+=child->MinHeight;
  208.           maxspacewidth=max(maxspacewidth,child->MinWidth);
  209.           maxspaceheight=max(maxspaceheight,child->MinHeight);
  210.         }
  211.  
  212.       /* Alter the resizability flags */
  213.       if(objecttype==TRGR_Horiz)
  214.         {
  215.           if(child->XResize==TRUE) DISPLAYOBJECT->XResize=TRUE;
  216.           if(child->YResize==FALSE) DISPLAYOBJECT->YResize=FALSE;
  217.         }
  218.       else
  219.         {
  220.           if(child->YResize==TRUE) DISPLAYOBJECT->YResize=TRUE;
  221.           if(child->XResize==FALSE) DISPLAYOBJECT->XResize=FALSE;
  222.         }
  223.     }
  224.  
  225.       /* Primary dimension */
  226.  
  227.       if((NEWDATA->itemdata)&TRGR_EQUALSHARE)
  228.     {
  229.       if(objecttype==TRGR_Horiz) width=(maxwidth*numobj)+spacewidth;
  230.       else height=(maxheight*numobj)+spaceheight;
  231.     }
  232.       else /* TRGR_PROPSHARE or TRGR_PROPSPACES */
  233.     {
  234.       if(objecttype==TRGR_Horiz) width+=spacewidth;
  235.       else height+=spaceheight;
  236.     }
  237.  
  238.       /* Secondary dimension */
  239.       if(objecttype==TRGR_Horiz) height=max(maxheight,maxspaceheight);
  240.       else width=max(maxwidth,maxspacewidth);
  241.  
  242.       NEWDATA->firstitem++; /* The first item for the next object */
  243.  
  244.       /* Fixed group? */
  245.       if((NEWDATA->itemdata)&TRGR_FIXHORIZ) DISPLAYOBJECT->XResize=FALSE;
  246.       if((NEWDATA->itemdata)&TRGR_FIXVERT) DISPLAYOBJECT->YResize=FALSE;
  247.  
  248.       if((NEWDATA->itemdata)&TRGR_ARRAY) /* Correct dimensions in arrays */
  249.     {
  250.       for(numobj=0,totalsize=0;;numobj++,totalsize+=maxsize) /* Go through all 2nd level child objects */
  251.         {
  252.           /* Get maximum size */
  253.           maxsize=0;
  254.           childresize=TRUE;
  255.           for(child=(struct TROD_DisplayObject *)(GROUP->ObjectList.mlh_Head);
  256.           CHILDOBJECT->Node.mln_Succ;
  257.           child=(struct TROD_DisplayObject *)(CHILDOBJECT->Node.mln_Succ))
  258.         {
  259.           if(((CHILDOBJECT->Class->trc_Tag==TRGR_Horiz)||
  260.               (CHILDOBJECT->Class->trc_Tag==TRGR_Vert))
  261.              &&(!(CHILDGROUP->Flags&TRGR_INDEP)))
  262.           { /* Get dimensions of embedded groups */
  263.             for(currobj=0,child2=(struct TROD_DisplayObject *)
  264.               (CHILDGROUP->ObjectList.mlh_Head);
  265.             (child2->O.Node.mln_Succ->mln_Succ)&&(currobj<numobj);
  266.             child2=(struct TROD_DisplayObject *)
  267.               (child2->O.Node.mln_Succ), currobj++);
  268.             if(currobj==numobj)
  269.               {
  270.             newmaxsize=(CHILDOBJECT->Class->trc_Tag==TRGR_Horiz)?
  271.               child2->MinWidth:child2->MinHeight;
  272.             maxsize=max(maxsize,newmaxsize);
  273.             if(CHILDOBJECT->Class->trc_Tag==TRGR_Horiz)
  274.               childresize=(!(child2->XResize))?FALSE:childresize;
  275.             else childresize=(!(child2->YResize))?FALSE:childresize;
  276.               }
  277.           }
  278.         }
  279.  
  280.           if(!maxsize) break;
  281.  
  282.           /* Set size in all objects */
  283.           for(child=(struct TROD_DisplayObject *)(GROUP->ObjectList.mlh_Head);
  284.           CHILDOBJECT->Node.mln_Succ;
  285.           child=(struct TROD_DisplayObject *)(CHILDOBJECT->Node.mln_Succ))
  286.         {
  287.           if(((CHILDOBJECT->Class->trc_Tag==TRGR_Horiz)||
  288.               (CHILDOBJECT->Class->trc_Tag==TRGR_Vert))
  289.              &&(!(CHILDGROUP->Flags&TRGR_INDEP)))
  290.           { /* Set dimensions of embedded groups */
  291.             for(currobj=0,child2=(struct TROD_DisplayObject *)
  292.               (CHILDGROUP->ObjectList.mlh_Head);
  293.             (child2->O.Node.mln_Succ->mln_Succ)&&(currobj<numobj);
  294.             child2=(struct TROD_DisplayObject *)
  295.               (child2->O.Node.mln_Succ), currobj++);
  296.             if(currobj==numobj)
  297.               {
  298.             if((child2->O.Class->trc_Tag!=TRGR_Horiz)&& //--
  299.                (child2->O.Class->trc_Tag!=TRGR_Vert))   //--
  300.             if(CHILDOBJECT->Class->trc_Tag==TRGR_Horiz)
  301.               {
  302.                 child->MinWidth=child->MinWidth-child2->MinWidth+maxsize;
  303.                 child2->MinWidth=maxsize;
  304.               }
  305.             else
  306.               {
  307.                 child->MinHeight=child->MinHeight-child2->MinHeight+maxsize;
  308.                 child2->MinHeight=maxsize;
  309.               }
  310.             if(!childresize)
  311.               if(CHILDOBJECT->Class->trc_Tag==TRGR_Horiz) child2->XResize=FALSE;
  312.               else child2->YResize=FALSE;
  313.               }
  314.           }
  315.         }
  316.         }
  317.  
  318.       if(objecttype==TRGR_Horiz) height=totalsize; else width=totalsize;
  319.     }
  320.  
  321.       DISPLAYOBJECT->MinWidth=width;
  322.       DISPLAYOBJECT->MinHeight=height;
  323.  
  324.       return (ULONG)TR_AddObjectToIDList(OBJECT->Project, object);
  325.  
  326.  
  327.   case TROM_INSTALL:
  328.  
  329.     TRDP_DisplayObject_INSTALL(object,messageid,data,metaclass->trc_SuperClass);
  330.  
  331.     width=((struct TROM_InstallData *)(data))->width;
  332.     height=((struct TROM_InstallData *)(data))->height;
  333.  
  334.     /* Go through all child objects and get their sizes */
  335.     for(child=(struct TROD_DisplayObject *)(GROUP->ObjectList.mlh_Head);
  336.     CHILDOBJECT->Node.mln_Succ;
  337.     child=(struct TROD_DisplayObject *)(CHILDOBJECT->Node.mln_Succ))
  338.       {
  339.         /* Resizable object? */
  340.         if(GROUP->Flags&TRGR_PROPSPACES) /* Resizable spaces, fixed objects */
  341.       {
  342.         if(child->Flags&TROB_DISPLAYOBJECT_SPACE)
  343.           resizable=TRUE;
  344.         else resizable=FALSE;
  345.       }
  346.         else /* Resizablility depends on object */
  347.       {
  348.         if(((OBJECT->Class->trc_Tag==TRGR_Horiz)&&(child->XResize==TRUE))||
  349.            ((OBJECT->Class->trc_Tag!=TRGR_Horiz)&&(child->YResize==TRUE)))
  350.           resizable=TRUE;
  351.         else resizable=FALSE;
  352.       }
  353.  
  354.         if(resizable) /* Resizable */
  355.       {
  356.         numobj++;
  357.         maxwidth=max(maxwidth,child->MinWidth);
  358.         maxheight=max(maxheight,child->MinHeight);
  359.       }
  360.         else /* Not resizable */
  361.       {
  362.         spacewidth+=child->MinWidth;
  363.         spaceheight+=child->MinHeight;
  364.         maxspacewidth=max(maxspacewidth,child->MinWidth);
  365.         maxspaceheight=max(maxspaceheight,child->MinHeight);
  366.       }
  367.       }
  368.  
  369.     left=DISPLAYOBJECT->Left;
  370.     top=DISPLAYOBJECT->Top;
  371.  
  372.     newspacewidth=spacewidth;
  373.     newspaceheight=spaceheight;
  374.  
  375.     /* Go through all child objects and install them */
  376.     for(child=(struct TROD_DisplayObject *)(GROUP->ObjectList.mlh_Head);
  377.     CHILDOBJECT->Node.mln_Succ;
  378.     child=(struct TROD_DisplayObject *)(CHILDOBJECT->Node.mln_Succ))
  379.       {
  380.         /* Resizable object? */
  381.     if(GROUP->Flags&TRGR_PROPSPACES) /* Resizable spaces, fixed objects */
  382.       {
  383.         if(child->Flags&TROB_DISPLAYOBJECT_SPACE)
  384.           resizable=TRUE;
  385.         else resizable=FALSE;
  386.       }
  387.         else /* Resizablility depends on object */
  388.       {
  389.         if(((OBJECT->Class->trc_Tag==TRGR_Horiz)&&(child->XResize==TRUE))||
  390.            ((OBJECT->Class->trc_Tag!=TRGR_Horiz)&&(child->YResize==TRUE)))
  391.           resizable=TRUE;
  392.         else resizable=FALSE;
  393.       }
  394.  
  395.         /* PRIMARY DIMENSION */
  396.     if(GROUP->Flags&TRGR_EQUALSHARE)                     /* TRGR_EQUALSHARE */
  397.       {
  398.         if(OBJECT->Class->trc_Tag==TRGR_Horiz)
  399.           {
  400.         if(resizable)
  401.           {
  402.             width=(DISPLAYOBJECT->Width-spacewidth)/numobj;       /* Proportional size */
  403.             spacewidth+=width; numobj--;                          /* Error correction */
  404.           }
  405.         else width=child->MinWidth;                               /* Minimum size */
  406.           }
  407.         else                                                          /* Vertical */
  408.           {
  409.         if(resizable)
  410.           {
  411.             height=(DISPLAYOBJECT->Height-spaceheight)/numobj;    /* Proportional size */
  412.             spaceheight+=height; numobj--;                        /* Error correction */
  413.           }
  414.         else height=child->MinHeight;                             /* Minimum size */
  415.           }
  416.       }
  417.     else                                                              /* TRGR_PROP... */
  418.       {
  419.         if(OBJECT->Class->trc_Tag==TRGR_Horiz)                        /* Horizontal */
  420.           {
  421.         if(resizable)
  422.           {
  423.             width=child->MinWidth
  424.               *(DISPLAYOBJECT->Width-newspacewidth)
  425.               /(DISPLAYOBJECT->MinWidth-spacewidth);
  426.  
  427.             /* Error correction */
  428.             newspacewidth+=width;
  429.             spacewidth+=child->MinWidth;
  430.             numobj--;
  431.           }
  432.         else width=child->MinWidth;                               /* Minimum size */
  433.           }
  434.         else                                                          /* Vertical */
  435.           {
  436.         if(resizable)
  437.           {
  438.             height=child->MinHeight
  439.               *(DISPLAYOBJECT->Height-newspaceheight)
  440.               /(DISPLAYOBJECT->MinHeight-spaceheight);
  441.             TR_DoMethod(CHILDOBJECT,TROM_GETBETTERHEIGHT,(APTR)(&height));
  442.  
  443.             /* Error correction */
  444.             newspaceheight+=height;
  445.             spaceheight+=child->MinHeight;
  446.             numobj--;
  447.           }
  448.         else height=child->MinHeight;                             /* Minimum size */
  449.           }
  450.       }
  451.  
  452.         /* SECONDARY DIMENSION */
  453.     installdata.left=left;
  454.     installdata.top=top;
  455.  
  456.     if(OBJECT->Class->trc_Tag==TRGR_Horiz)
  457.       {
  458.         installdata.height=child->MinHeight;
  459.         installdata.width=width;
  460.       }
  461.     else
  462.       {
  463.         installdata.width=child->MinWidth;
  464.         installdata.height=height;
  465.       }
  466.  
  467.     if(GROUP->Flags&TRGR_ALIGN) /* Align the object */
  468.       {
  469.         if(OBJECT->Class->trc_Tag==TRGR_Horiz)
  470.           {
  471.         if(child->YResize) installdata.height=DISPLAYOBJECT->Height;
  472.           }
  473.         else
  474.           {
  475.         if(child->XResize) installdata.width=DISPLAYOBJECT->Width;
  476.           }
  477.       }
  478.     if(GROUP->Flags&TRGR_CENTER) /* Center the object */
  479.       {
  480.         if(OBJECT->Class->trc_Tag==TRGR_Horiz)
  481.           {
  482.         if(!(child->YResize))
  483.           installdata.top=top+(DISPLAYOBJECT->Height-child->MinHeight)/2;
  484.           }
  485.         else
  486.           {
  487.         if(!(child->XResize))
  488.           installdata.left=left+(DISPLAYOBJECT->Width-child->MinWidth)/2;
  489.           }
  490.       }
  491.  
  492.     TR_DoMethod(CHILDOBJECT,TROM_INSTALL,(APTR)&installdata);         /* Install the object  */
  493.     if(OBJECT->Class->trc_Tag==TRGR_Horiz) left+=width;               /* ...and calculate the... */
  494.         else top+=height;                                                 /* ...new position         */
  495.       }
  496.     return 1;
  497.  
  498.  
  499.   case TROM_EVENT: /* BROADCAST AN EVENT MESSAGE */
  500.  
  501.     /* Go through all child objects */
  502.     for(child=(struct TROD_DisplayObject *)(GROUP->ObjectList.mlh_Head);
  503.     CHILDOBJECT->Node.mln_Succ;
  504.     child=(struct TROD_DisplayObject *)(CHILDOBJECT->Node.mln_Succ))
  505.       {
  506.         if(TR_DoMethod(CHILDOBJECT,messageid,data)==1) return 1;
  507.       }
  508.     return NULL;
  509.  
  510.  
  511.  
  512.   /* Ignore some methods */
  513.   case TROM_CREATECLASS:
  514.   case TROM_DISPOSECLASS:
  515.   case TROM_GETBETTERHEIGHT:
  516.     return NULL;
  517.  
  518.  
  519.   default: /* ALL OTHER MESSAGES ARE JUST BROADCAST TO THE CHILD OBJECTS */
  520.  
  521.     TR_SUPERMETHOD;
  522.     retval=1L;
  523.     for(child=(struct TROD_DisplayObject *)(GROUP->ObjectList.mlh_Head);
  524.     CHILDOBJECT->Node.mln_Succ;
  525.     child=(struct TROD_DisplayObject *)(CHILDOBJECT->Node.mln_Succ))
  526.       {
  527.     /* If only one object fails,everything will fail      */
  528.     if(TR_DoMethod(CHILDOBJECT,messageid,data)==FALSE) retval=NULL;
  529.       }
  530.     return retval;
  531.   }
  532. }
  533.