home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 3
/
AACD03.BIN
/
AACD
/
Programming
/
Triton
/
Source
/
classes
/
group.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-05-23
|
18KB
|
533 lines
/*
* OpenTriton -- A free release of the triton.library source code
* Copyright (C) 1993-1998 Stefan Zeiger
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/****** triton.library/class_Group ******
*
* NAME
* class_Group -- A grouping object
*
* SUPERCLASS
* class_DisplayObject
*
* SYNOPSIS
* TRGR_Horiz
* TRGR_Vert
*
* ATTRIBUTES
* <Default> : ULONG flags
* - TRGR_PROPSHARE : Divide objects
* proportionally
* - TRGR_EQUALSHARE : Divide objects equally
* - TRGR_PROPSPACES : Divide spaces
* proportionally
* - TRGR_ARRAY : Top group of an array. Lines
* or culumns can be built
* using TRGR_PROPSHARE groups.
* At least one group must
* be contained in an array.
* - TRGR_ALIGN : Align resizable objects in
* their secondary dimension
* - TRGR_CENTER : Center non-resizable
* objects in their secondary
* dimension
* - TRGR_FIXHORIZ : Don't allow horizontal
* resizing
* - TRGR_FIXVERT : Don't allow vertical
* resizing
* - TRGR_INDEP (V2) : Group is independent of
* surrounding array
* [create]
* TRAT_ID : ULONG objectid (V4)
* [create]
* <other> : Treated as elements of the group
* [create]
* TRGR_End : <unused> : Marks the end of the group
* [create]
*
* NOTES
* An array group must contain at least one non-space object.
*
******/
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////// Include our stuff //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define TR_THIS_IS_TRITON
#include <clib/alib_protos.h>
#include <libraries/triton.h>
#include <clib/triton_protos.h>
#include "/internal.h"
#include "group.def"
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////// Object data //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define OBJECT (&(object->DO.O))
#define DISPLAYOBJECT (&(object->DO))
#define GROUP object
#define CHILDOBJECT (&(child->O))
#define CHILDGROUP ((struct TROD_Group *)(child))
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////// Methods //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
TR_DEFAULTMETHOD(Group)
{
ULONG width=0, height=0, spacewidth=0, spaceheight=0,left,top,maxsize,totalsize,newmaxsize;
ULONG maxwidth=0, maxheight=0, maxspacewidth=0, maxspaceheight=0, newspacewidth, newspaceheight;
struct TROD_DisplayObject *child=NULL, *child2;
BOOL childresize;
struct TROM_NewData newdata;
struct TROM_InstallData installdata;
ULONG objecttype;
ULONG numobj=0,currobj;
BOOL resizable;
ULONG retval;
struct TROM_SetAttributeData sadata;
switch(messageid)
{
case TROM_NEW:
NEWDATA->parseargs=FALSE;
if(!TRDP_DisplayObject_NEW(object,messageid,data,metaclass->trc_SuperClass)) return NULL;
objecttype=NEWDATA->objecttype; /* Are we horiz. or vert.? */
GROUP->Flags=(ULONG)(NEWDATA->itemdata);
NewList((struct List *)&(GROUP->ObjectList));
/* Fill in the TROM_NewData fields for all child objects */
newdata.project=NEWDATA->project;
newdata.grouptype=objecttype;
newdata.backfilltype=DISPLAYOBJECT->BackfillType;
/* Set the resizability flags to their defaults */
if(objecttype==TRGR_Horiz)
{
if(GROUP->Flags&TRGR_PROPSPACES)
DISPLAYOBJECT->XResize=TRUE; else DISPLAYOBJECT->XResize=FALSE;
DISPLAYOBJECT->YResize=TRUE;
}
else
{
if(GROUP->Flags&TRGR_PROPSPACES)
DISPLAYOBJECT->YResize=TRUE; else DISPLAYOBJECT->YResize=FALSE;
DISPLAYOBJECT->XResize=TRUE;
}
for(;;) /* Go through all child objects */
continue_here:
{
if(NEWDATA->firstitem->ti_Tag==TRGR_End) break; /* No more objects */
if(!child) /* No objects yet */
if((TR_GetTagType(NEWDATA->firstitem->ti_Tag)==TRTG_OAT)&&(NEWDATA->firstitem->ti_Tag!=TRGR_End))
{
switch(NEWDATA->firstitem->ti_Tag)
{
case TRAT_ID:
DISPLAYOBJECT->ID=NEWDATA->firstitem->ti_Data;
break;
case TRAT_Disabled:
if(NEWDATA->firstitem->ti_Data) DISPLAYOBJECT->Flags|=TROB_DISPLAYOBJECT_DISABLED;
else DISPLAYOBJECT->Flags&=~TROB_DISPLAYOBJECT_DISABLED;
break;
default:
sadata.attribute=NEWDATA->firstitem->ti_Tag;
sadata.value=NEWDATA->firstitem->ti_Data;
TR_DoMethod(OBJECT,TROM_SETATTRIBUTE,(APTR)(&sadata));
}
NEWDATA->firstitem++;
goto continue_here;
}
/* Fill in the TROM_NewData fields for the next child object */
newdata.firstitem=(((struct TROM_NewData *)(data))->firstitem)+1;
newdata.objecttype=NEWDATA->firstitem->ti_Tag;
newdata.itemdata=NEWDATA->firstitem->ti_Data;
newdata.parseargs=TRUE;
/** Initialize the child object */
if(!(child=(struct TROD_DisplayObject *)TR_DoMethod(NULL,TROM_NEW,(APTR)&newdata)))
return NULL;
AddTail((struct List *)(&(GROUP->ObjectList)),(struct Node *)child);
NEWDATA->firstitem=newdata.firstitem;
/* Resizable object? */
if(GROUP->Flags&TRGR_PROPSPACES) /* Resizable spaces, fixed objects */
{
if(child->Flags&TROB_DISPLAYOBJECT_SPACE)
resizable=TRUE;
else resizable=FALSE;
}
else /* Resizablility depends on object */
{
if(((objecttype==TRGR_Horiz)&&(child->XResize==TRUE))||
((objecttype!=TRGR_Horiz)&&(child->YResize==TRUE)))
resizable=TRUE;
else resizable=FALSE;
}
if(resizable)
{
numobj++;
width+=child->MinWidth;
height+=child->MinHeight;
maxwidth=max(maxwidth,child->MinWidth);
maxheight=max(maxheight,child->MinHeight);
}
else
{
spacewidth+=child->MinWidth;
spaceheight+=child->MinHeight;
maxspacewidth=max(maxspacewidth,child->MinWidth);
maxspaceheight=max(maxspaceheight,child->MinHeight);
}
/* Alter the resizability flags */
if(objecttype==TRGR_Horiz)
{
if(child->XResize==TRUE) DISPLAYOBJECT->XResize=TRUE;
if(child->YResize==FALSE) DISPLAYOBJECT->YResize=FALSE;
}
else
{
if(child->YResize==TRUE) DISPLAYOBJECT->YResize=TRUE;
if(child->XResize==FALSE) DISPLAYOBJECT->XResize=FALSE;
}
}
/* Primary dimension */
if((NEWDATA->itemdata)&TRGR_EQUALSHARE)
{
if(objecttype==TRGR_Horiz) width=(maxwidth*numobj)+spacewidth;
else height=(maxheight*numobj)+spaceheight;
}
else /* TRGR_PROPSHARE or TRGR_PROPSPACES */
{
if(objecttype==TRGR_Horiz) width+=spacewidth;
else height+=spaceheight;
}
/* Secondary dimension */
if(objecttype==TRGR_Horiz) height=max(maxheight,maxspaceheight);
else width=max(maxwidth,maxspacewidth);
NEWDATA->firstitem++; /* The first item for the next object */
/* Fixed group? */
if((NEWDATA->itemdata)&TRGR_FIXHORIZ) DISPLAYOBJECT->XResize=FALSE;
if((NEWDATA->itemdata)&TRGR_FIXVERT) DISPLAYOBJECT->YResize=FALSE;
if((NEWDATA->itemdata)&TRGR_ARRAY) /* Correct dimensions in arrays */
{
for(numobj=0,totalsize=0;;numobj++,totalsize+=maxsize) /* Go through all 2nd level child objects */
{
/* Get maximum size */
maxsize=0;
childresize=TRUE;
for(child=(struct TROD_DisplayObject *)(GROUP->ObjectList.mlh_Head);
CHILDOBJECT->Node.mln_Succ;
child=(struct TROD_DisplayObject *)(CHILDOBJECT->Node.mln_Succ))
{
if(((CHILDOBJECT->Class->trc_Tag==TRGR_Horiz)||
(CHILDOBJECT->Class->trc_Tag==TRGR_Vert))
&&(!(CHILDGROUP->Flags&TRGR_INDEP)))
{ /* Get dimensions of embedded groups */
for(currobj=0,child2=(struct TROD_DisplayObject *)
(CHILDGROUP->ObjectList.mlh_Head);
(child2->O.Node.mln_Succ->mln_Succ)&&(currobj<numobj);
child2=(struct TROD_DisplayObject *)
(child2->O.Node.mln_Succ), currobj++);
if(currobj==numobj)
{
newmaxsize=(CHILDOBJECT->Class->trc_Tag==TRGR_Horiz)?
child2->MinWidth:child2->MinHeight;
maxsize=max(maxsize,newmaxsize);
if(CHILDOBJECT->Class->trc_Tag==TRGR_Horiz)
childresize=(!(child2->XResize))?FALSE:childresize;
else childresize=(!(child2->YResize))?FALSE:childresize;
}
}
}
if(!maxsize) break;
/* Set size in all objects */
for(child=(struct TROD_DisplayObject *)(GROUP->ObjectList.mlh_Head);
CHILDOBJECT->Node.mln_Succ;
child=(struct TROD_DisplayObject *)(CHILDOBJECT->Node.mln_Succ))
{
if(((CHILDOBJECT->Class->trc_Tag==TRGR_Horiz)||
(CHILDOBJECT->Class->trc_Tag==TRGR_Vert))
&&(!(CHILDGROUP->Flags&TRGR_INDEP)))
{ /* Set dimensions of embedded groups */
for(currobj=0,child2=(struct TROD_DisplayObject *)
(CHILDGROUP->ObjectList.mlh_Head);
(child2->O.Node.mln_Succ->mln_Succ)&&(currobj<numobj);
child2=(struct TROD_DisplayObject *)
(child2->O.Node.mln_Succ), currobj++);
if(currobj==numobj)
{
if((child2->O.Class->trc_Tag!=TRGR_Horiz)&& //--
(child2->O.Class->trc_Tag!=TRGR_Vert)) //--
if(CHILDOBJECT->Class->trc_Tag==TRGR_Horiz)
{
child->MinWidth=child->MinWidth-child2->MinWidth+maxsize;
child2->MinWidth=maxsize;
}
else
{
child->MinHeight=child->MinHeight-child2->MinHeight+maxsize;
child2->MinHeight=maxsize;
}
if(!childresize)
if(CHILDOBJECT->Class->trc_Tag==TRGR_Horiz) child2->XResize=FALSE;
else child2->YResize=FALSE;
}
}
}
}
if(objecttype==TRGR_Horiz) height=totalsize; else width=totalsize;
}
DISPLAYOBJECT->MinWidth=width;
DISPLAYOBJECT->MinHeight=height;
return (ULONG)TR_AddObjectToIDList(OBJECT->Project, object);
case TROM_INSTALL:
TRDP_DisplayObject_INSTALL(object,messageid,data,metaclass->trc_SuperClass);
width=((struct TROM_InstallData *)(data))->width;
height=((struct TROM_InstallData *)(data))->height;
/* Go through all child objects and get their sizes */
for(child=(struct TROD_DisplayObject *)(GROUP->ObjectList.mlh_Head);
CHILDOBJECT->Node.mln_Succ;
child=(struct TROD_DisplayObject *)(CHILDOBJECT->Node.mln_Succ))
{
/* Resizable object? */
if(GROUP->Flags&TRGR_PROPSPACES) /* Resizable spaces, fixed objects */
{
if(child->Flags&TROB_DISPLAYOBJECT_SPACE)
resizable=TRUE;
else resizable=FALSE;
}
else /* Resizablility depends on object */
{
if(((OBJECT->Class->trc_Tag==TRGR_Horiz)&&(child->XResize==TRUE))||
((OBJECT->Class->trc_Tag!=TRGR_Horiz)&&(child->YResize==TRUE)))
resizable=TRUE;
else resizable=FALSE;
}
if(resizable) /* Resizable */
{
numobj++;
maxwidth=max(maxwidth,child->MinWidth);
maxheight=max(maxheight,child->MinHeight);
}
else /* Not resizable */
{
spacewidth+=child->MinWidth;
spaceheight+=child->MinHeight;
maxspacewidth=max(maxspacewidth,child->MinWidth);
maxspaceheight=max(maxspaceheight,child->MinHeight);
}
}
left=DISPLAYOBJECT->Left;
top=DISPLAYOBJECT->Top;
newspacewidth=spacewidth;
newspaceheight=spaceheight;
/* Go through all child objects and install them */
for(child=(struct TROD_DisplayObject *)(GROUP->ObjectList.mlh_Head);
CHILDOBJECT->Node.mln_Succ;
child=(struct TROD_DisplayObject *)(CHILDOBJECT->Node.mln_Succ))
{
/* Resizable object? */
if(GROUP->Flags&TRGR_PROPSPACES) /* Resizable spaces, fixed objects */
{
if(child->Flags&TROB_DISPLAYOBJECT_SPACE)
resizable=TRUE;
else resizable=FALSE;
}
else /* Resizablility depends on object */
{
if(((OBJECT->Class->trc_Tag==TRGR_Horiz)&&(child->XResize==TRUE))||
((OBJECT->Class->trc_Tag!=TRGR_Horiz)&&(child->YResize==TRUE)))
resizable=TRUE;
else resizable=FALSE;
}
/* PRIMARY DIMENSION */
if(GROUP->Flags&TRGR_EQUALSHARE) /* TRGR_EQUALSHARE */
{
if(OBJECT->Class->trc_Tag==TRGR_Horiz)
{
if(resizable)
{
width=(DISPLAYOBJECT->Width-spacewidth)/numobj; /* Proportional size */
spacewidth+=width; numobj--; /* Error correction */
}
else width=child->MinWidth; /* Minimum size */
}
else /* Vertical */
{
if(resizable)
{
height=(DISPLAYOBJECT->Height-spaceheight)/numobj; /* Proportional size */
spaceheight+=height; numobj--; /* Error correction */
}
else height=child->MinHeight; /* Minimum size */
}
}
else /* TRGR_PROP... */
{
if(OBJECT->Class->trc_Tag==TRGR_Horiz) /* Horizontal */
{
if(resizable)
{
width=child->MinWidth
*(DISPLAYOBJECT->Width-newspacewidth)
/(DISPLAYOBJECT->MinWidth-spacewidth);
/* Error correction */
newspacewidth+=width;
spacewidth+=child->MinWidth;
numobj--;
}
else width=child->MinWidth; /* Minimum size */
}
else /* Vertical */
{
if(resizable)
{
height=child->MinHeight
*(DISPLAYOBJECT->Height-newspaceheight)
/(DISPLAYOBJECT->MinHeight-spaceheight);
TR_DoMethod(CHILDOBJECT,TROM_GETBETTERHEIGHT,(APTR)(&height));
/* Error correction */
newspaceheight+=height;
spaceheight+=child->MinHeight;
numobj--;
}
else height=child->MinHeight; /* Minimum size */
}
}
/* SECONDARY DIMENSION */
installdata.left=left;
installdata.top=top;
if(OBJECT->Class->trc_Tag==TRGR_Horiz)
{
installdata.height=child->MinHeight;
installdata.width=width;
}
else
{
installdata.width=child->MinWidth;
installdata.height=height;
}
if(GROUP->Flags&TRGR_ALIGN) /* Align the object */
{
if(OBJECT->Class->trc_Tag==TRGR_Horiz)
{
if(child->YResize) installdata.height=DISPLAYOBJECT->Height;
}
else
{
if(child->XResize) installdata.width=DISPLAYOBJECT->Width;
}
}
if(GROUP->Flags&TRGR_CENTER) /* Center the object */
{
if(OBJECT->Class->trc_Tag==TRGR_Horiz)
{
if(!(child->YResize))
installdata.top=top+(DISPLAYOBJECT->Height-child->MinHeight)/2;
}
else
{
if(!(child->XResize))
installdata.left=left+(DISPLAYOBJECT->Width-child->MinWidth)/2;
}
}
TR_DoMethod(CHILDOBJECT,TROM_INSTALL,(APTR)&installdata); /* Install the object */
if(OBJECT->Class->trc_Tag==TRGR_Horiz) left+=width; /* ...and calculate the... */
else top+=height; /* ...new position */
}
return 1;
case TROM_EVENT: /* BROADCAST AN EVENT MESSAGE */
/* Go through all child objects */
for(child=(struct TROD_DisplayObject *)(GROUP->ObjectList.mlh_Head);
CHILDOBJECT->Node.mln_Succ;
child=(struct TROD_DisplayObject *)(CHILDOBJECT->Node.mln_Succ))
{
if(TR_DoMethod(CHILDOBJECT,messageid,data)==1) return 1;
}
return NULL;
/* Ignore some methods */
case TROM_CREATECLASS:
case TROM_DISPOSECLASS:
case TROM_GETBETTERHEIGHT:
return NULL;
default: /* ALL OTHER MESSAGES ARE JUST BROADCAST TO THE CHILD OBJECTS */
TR_SUPERMETHOD;
retval=1L;
for(child=(struct TROD_DisplayObject *)(GROUP->ObjectList.mlh_Head);
CHILDOBJECT->Node.mln_Succ;
child=(struct TROD_DisplayObject *)(CHILDOBJECT->Node.mln_Succ))
{
/* If only one object fails,everything will fail */
if(TR_DoMethod(CHILDOBJECT,messageid,data)==FALSE) retval=NULL;
}
return retval;
}
}