#include "apricot.h"
#include "guts.h"
#include "Widget.h"
#include "private/Widget.h"
#ifdef __cplusplus
extern
"C"
{
#endif
static
void
Widget_pack_enter( Handle self);
static
void
Widget_pack_leave( Handle self);
static
void
Widget_place_enter( Handle self);
static
void
Widget_place_leave( Handle self);
#define MASTER ((var->geometry != gtGrowMode && var->geomInfo.in)?var->geomInfo.in:var->owner)
#define geometry_reset_all() geometry_reset(MASTER,-1)
static
void
geometry_reset( Handle self,
int
geometry)
{
if
( !self)
return
;
if
(
(var-> geometry == gtGrowMode) &&
(var-> growMode & gmCenter) &&
( geometry == gtGrowMode || geometry < 0)
) {
my-> set_centered( self, var-> growMode & gmXCenter, var-> growMode & gmYCenter);
}
if
( geometry == gtPack || geometry < 0)
Widget_pack_slaves( self);
if
( geometry == gtPlace || geometry < 0)
Widget_place_slaves( self);
if
( geometry == gtGrid || geometry < 0)
Widget_grid_slaves( self);
}
int
Widget_geometry( Handle self, Bool set,
int
geometry)
{
if
( !set)
return
var-> geometry;
if
( geometry == var-> geometry) {
if
((var-> geometry == gtGrowMode) && (var-> growMode & gmCenter))
my-> set_centered( self, var-> growMode & gmXCenter, var-> growMode & gmYCenter);
return
geometry;
}
if
( geometry < gtDefault || geometry > gtMax)
croak(
"Prima::Widget::geometry: invalid value passed"
);
switch
( var-> geometry) {
case
gtPlace:
Widget_place_leave( self);
break
;
case
gtPack:
Widget_pack_leave( self);
break
;
case
gtGrid:
Widget_grid_leave( self);
break
;
}
var-> geometry = geometry;
switch
( var-> geometry) {
case
gtGrowMode:
if
( var-> growMode & gmCenter)
my-> set_centered( self, var-> growMode & gmXCenter, var-> growMode & gmYCenter);
break
;
case
gtPlace:
Widget_place_enter( self);
break
;
case
gtPack:
Widget_pack_enter( self);
break
;
case
gtGrid:
Widget_grid_enter( self);
break
;
}
geometry_reset_all();
return
var-> geometry;
}
Point
Widget_geomSize( Handle self, Bool set, Point geomSize)
{
if
( !set)
return
var-> geomSize;
var-> geomSize = geomSize;
if
( var-> geometry == gtDefault)
my-> set_size( self, var-> geomSize);
else
geometry_reset_all();
return
var-> geomSize;
}
int
Widget_geomHeight( Handle self, Bool set,
int
geomHeight)
{
if
( set) {
Point p = { var-> geomSize. x, geomHeight};
my-> set_geomSize( self, p);
}
return
var-> geomSize. y;
}
int
Widget_geomWidth( Handle self, Bool set,
int
geomWidth)
{
if
( set) {
Point p = { geomWidth, var-> geomSize. y};
my-> set_geomSize( self, p);
}
return
var-> geomSize. x;
}
Bool
Widget_packPropagate( Handle self, Bool set, Bool propagate)
{
Bool repack;
if
( !set)
return
is_opt( optPackPropagate);
repack = !(is_opt( optPackPropagate)) && propagate;
opt_assign( optPackPropagate, propagate);
if
( repack) geometry_reset(self,-1);
return
is_opt( optPackPropagate);
}
void
Widget_reset_children_geometry( Handle self)
{
Widget_pack_slaves( self);
Widget_place_slaves( self);
Widget_grid_slaves( self);
}
Handle
Widget_check_in( Handle self, Handle in,
int
geometry)
{
Handle h = in;
char
* method =
(geometry == gtPack) ?
"Prima::Widget::pack"
:
((geometry == gtGrid) ?
"Prima::Widget::grid"
:
"Prima::Widget::place"
);
if
( !in || !kind_of( in, CWidget))
croak(
"%s: invalid 'in': not a widget"
, method);
while
( h) {
if
( h == self)
croak(
"%s: invalid 'in': is already a child"
, method);
h = PWidget( h)-> owner;
}
h = PWidget( in)-> packSlaves;
while
( h) {
if
( h == in)
croak(
"%s: invalid 'in': already a pack slave"
, method);
h = PWidget( h)-> geomInfo. next;
}
h = PWidget( in)-> placeSlaves;
while
( h) {
if
( h == in)
croak(
"%s: invalid 'in': already a place slave"
, method);
h = PWidget( h)-> geomInfo. next;
}
if
( geometry != gtGrid && Widget_is_grid_slave(in, self))
croak(
"%s: invalid 'in': already in a grid"
, method);
if
( geometry == gtGrid && PWidget(in)->packSlaves)
croak(
"%s: cannot grid into a pack master"
, method);
if
( geometry == gtPack && Widget_has_grid_slaves(in))
croak(
"%s: cannot pack into a grid master"
, method);
return
in;
}
Point
Widget_sizeMin( Handle self, Bool set, Point min)
{
if
( !set)
return
var-> sizeMin;
var-> sizeMin = min;
if
( var-> stage <= csFrozen) {
Point sizeActual = my-> get_size( self);
Point newSize = sizeActual;
if
( sizeActual. x < min. x) newSize. x = min. x;
if
( sizeActual. y < min. y) newSize. y = min. y;
if
(( newSize. x != sizeActual. x) || ( newSize. y != sizeActual. y))
my-> set_size( self, newSize);
if
( var-> geometry != gtDefault)
geometry_reset_all();
}
apc_widget_set_size_bounds( self, var-> sizeMin, var-> sizeMax);
return
min;
}
Point
Widget_sizeMax( Handle self, Bool set, Point max)
{
if
( !set)
return
var-> sizeMax;
var-> sizeMax = max;
if
( var-> stage <= csFrozen) {
Point sizeActual = my-> get_size( self);
Point newSize = sizeActual;
if
( sizeActual. x > max. x) newSize. x = max. x;
if
( sizeActual. y > max. y) newSize. y = max. y;
if
(( newSize. x != sizeActual. x) || ( newSize. y != sizeActual. y))
my-> set_size( self, newSize);
if
( var-> geometry != gtDefault)
geometry_reset_all();
}
apc_widget_set_size_bounds( self, var-> sizeMin, var-> sizeMax);
return
max;
}
Bool
Widget_size_notify( Handle self, Handle child,
const
Rect* metrix)
{
if
( his-> growMode && his->geometry == gtGrowMode) {
Point size = his-> self-> get_virtual_size( child);
Point pos = his-> self-> get_origin( child);
Point osize = size, opos = pos;
int
dx = ((Rect *) metrix)-> right - ((Rect *) metrix)-> left;
int
dy = ((Rect *) metrix)-> top - ((Rect *) metrix)-> bottom;
if
( his-> growMode & gmGrowLoX) pos. x += dx;
if
( his-> growMode & gmGrowHiX) size. x += dx;
if
( his-> growMode & gmGrowLoY) pos. y += dy;
if
( his-> growMode & gmGrowHiY) size. y += dy;
if
( his-> growMode & gmXCenter) pos. x = (((Rect *) metrix)-> right - size. x) / 2;
if
( his-> growMode & gmYCenter) pos. y = (((Rect *) metrix)-> top - size. y) / 2;
if
( pos.x != opos.x || pos.y != opos.y || size.x != osize.x || size.y != osize.y) {
if
( pos.x == opos.x && pos.y == opos.y) {
his-> self-> set_size( child, size);
}
else
if
( size.x == osize.x && size.y == osize.y) {
his-> self-> set_origin( child, pos);
}
else
{
Rect r;
r. left = pos. x;
r. bottom = pos. y;
r. right = pos. x + size. x;
r. top = pos. y + size. y;
his-> self-> set_rect( child, r);
}
}
}
return
false
;
}
Bool
Widget_move_notify( Handle self, Handle child, Point * moveTo)
{
Bool clp = his-> self-> get_clipOwner( child);
int
dx = moveTo-> x - var-> pos. x;
int
dy = moveTo-> y - var-> pos. y;
Point p;
if
( his-> geometry != gtGrowMode )
return
false
;
if
( his-> growMode & gmDontCare) {
if
( !clp)
return
false
;
p = his-> self-> get_origin( child);
p. x -= dx;
p. y -= dy;
his-> self-> set_origin( child, p);
}
else
{
if
( clp)
return
false
;
p = his-> self-> get_origin( child);
p. x += dx;
p. y += dy;
his-> self-> set_origin( child, p);
}
return
false
;
}
#define LEFT 0
#define BOTTOM 1
#define RIGHT 2
#define TOP 3
#define SOUTH 0
#define NORTH 2
#define WEST 0
#define EAST 2
#define CENTER 1
static
int
slave_width(
register
PWidget slavePtr,
register
int
plus)
{
register
int
width =
slavePtr-> geomSize. x +
slavePtr-> geomInfo. pad.x +
slavePtr-> geomInfo. ipad.x +
plus;
if
( width < slavePtr-> sizeMin.x) width = slavePtr-> sizeMin.x;
if
( width > slavePtr-> sizeMax.x) width = slavePtr-> sizeMax.x;
return
width;
}
static
int
slave_height(
register
PWidget slavePtr,
register
int
plus)
{
register
int
height =
slavePtr-> geomSize.y +
slavePtr-> geomInfo. pad.y +
slavePtr-> geomInfo. ipad.y +
plus;
if
( height < slavePtr-> sizeMin.y) height = slavePtr-> sizeMin.y;
if
( height > slavePtr-> sizeMax.y) height = slavePtr-> sizeMax.y;
return
height;
}
static
int
XExpansion(
register
PWidget slavePtr,
int
cavityWidth
) {
int
numExpand, minExpand, curExpand;
int
childWidth;
minExpand = cavityWidth;
numExpand = 0;
for
(
;
slavePtr != NULL;
slavePtr = ( PWidget) slavePtr-> geomInfo. next
) {
childWidth = slave_width(slavePtr, 0);
if
((slavePtr-> geomInfo. side == TOP) || (slavePtr-> geomInfo. side == BOTTOM)) {
curExpand = (cavityWidth - childWidth)/numExpand;
if
(curExpand < minExpand)
minExpand = curExpand;
}
else
{
cavityWidth -= childWidth;
if
(slavePtr->geomInfo. expand)
numExpand++;
}
}
curExpand = cavityWidth / numExpand;
if
(curExpand < minExpand)
minExpand = curExpand;
return
(minExpand < 0) ? 0 : minExpand;
}
static
int
YExpansion(
register
PWidget slavePtr,
int
cavityHeight
) {
int
numExpand, minExpand, curExpand;
int
childHeight;
minExpand = cavityHeight;
numExpand = 0;
for
(
;
slavePtr != NULL;
slavePtr = (PWidget) slavePtr->geomInfo. next
) {
childHeight = slave_height(slavePtr, 0);
if
((slavePtr-> geomInfo. side == LEFT) || (slavePtr-> geomInfo. side == RIGHT)) {
curExpand = (cavityHeight - childHeight)/numExpand;
if
(curExpand < minExpand)
minExpand = curExpand;
}
else
{
cavityHeight -= childHeight;
if
(slavePtr-> geomInfo. expand)
numExpand++;
}
}
curExpand = cavityHeight/numExpand;
if
(curExpand < minExpand)
minExpand = curExpand;
return
(minExpand < 0) ? 0 : minExpand;
}
void
Widget_pack_slaves( Handle self)
{
PWidget masterPtr, slavePtr;
int
cavityX, cavityY, cavityWidth, cavityHeight;
int
frameX, frameY, frameWidth, frameHeight;
int
x, y, width, height;
int
maxWidth, maxHeight, tmp;
int
borderX, borderY;
Point size;
if
( var-> stage > csNormal)
return
;
if
(!( masterPtr = ( PWidget) var-> packSlaves))
return
;
width = height = maxWidth = maxHeight = 0;
for
(
slavePtr = masterPtr;
slavePtr != NULL;
slavePtr = ( PWidget) slavePtr-> geomInfo. next
) {
if
(
(slavePtr-> geomInfo. side == TOP ) ||
(slavePtr-> geomInfo. side == BOTTOM)
) {
tmp = slave_width( slavePtr, width);
if
(tmp > maxWidth) maxWidth = tmp;
height += slave_height(slavePtr,0);
}
else
{
tmp = slave_height(slavePtr, height);
if
(tmp > maxHeight) maxHeight = tmp;
width += slave_width(slavePtr,0);
}
}
if
(width > maxWidth)
maxWidth = width;
if
(height > maxHeight)
maxHeight = height;
if
(
is_opt( optPackPropagate) && (
maxWidth != my-> get_geomWidth(self) ||
maxHeight != my-> get_geomHeight(self)
)
) {
Point p, oldsize;
p. x = maxWidth;
p. y = maxHeight;
oldsize = my-> get_size( self);
my-> set_geomSize( self, p);
size = my-> get_size( self);
if
( oldsize. x != size. x || oldsize. y != size. y)
return
;
}
else
{
size = my-> get_size( self);
}
cavityX = cavityY = x = y = 0;
cavityWidth = size. x;
cavityHeight = size. y;
for
(
slavePtr = masterPtr;
slavePtr != NULL;
slavePtr = ( PWidget) slavePtr-> geomInfo. next
) {
if
(
(slavePtr-> geomInfo. side == TOP ) ||
(slavePtr-> geomInfo. side == BOTTOM)
) {
frameWidth = cavityWidth;
frameHeight = slave_height(slavePtr,0);
if
(slavePtr-> geomInfo. expand)
frameHeight += YExpansion(slavePtr, cavityHeight);
cavityHeight -= frameHeight;
if
(cavityHeight < 0) {
frameHeight += cavityHeight;
cavityHeight = 0;
}
frameX = cavityX;
if
(slavePtr-> geomInfo. side == BOTTOM) {
frameY = cavityY;
cavityY += frameHeight;
}
else
{
frameY = cavityY + cavityHeight;
}
}
else
{
frameHeight = cavityHeight;
frameWidth = slave_width(slavePtr,0);
if
(slavePtr-> geomInfo. expand)
frameWidth += XExpansion(slavePtr, cavityWidth);
cavityWidth -= frameWidth;
if
(cavityWidth < 0) {
frameWidth += cavityWidth;
cavityWidth = 0;
}
frameY = cavityY;
if
(slavePtr-> geomInfo. side == LEFT) {
frameX = cavityX;
cavityX += frameWidth;
}
else
{
frameX = cavityX + cavityWidth;
}
}
borderX = slavePtr-> geomInfo. pad.x;
borderY = slavePtr-> geomInfo. pad.y;
width = slavePtr-> geomSize. x + slavePtr-> geomInfo. ipad.x;
if
(slavePtr-> geomInfo. fillx || (width > (frameWidth - borderX)))
width = frameWidth - borderX;
height = slavePtr-> geomSize. y + slavePtr-> geomInfo. ipad.y;
if
(slavePtr-> geomInfo. filly || (height > (frameHeight - borderY)))
height = frameHeight - borderY;
borderX /= 2;
borderY /= 2;
if
( width < slavePtr-> sizeMin.x) width = slavePtr-> sizeMin.x;
if
( height < slavePtr-> sizeMin.y) height = slavePtr-> sizeMin.y;
if
( width > slavePtr-> sizeMax.x) width = slavePtr-> sizeMax.x;
if
( height > slavePtr-> sizeMax.y) height = slavePtr-> sizeMax.y;
switch
(slavePtr-> geomInfo. anchorx) {
case
WEST:
x = frameX + borderX;
break
;
case
CENTER:
x = frameX + (frameWidth - width)/2;
break
;
case
EAST:
x = frameX + frameWidth - width - borderX;
break
;
}
switch
(slavePtr-> geomInfo. anchory) {
case
SOUTH:
y = frameY + borderY;
break
;
case
CENTER:
y = frameY + (frameHeight - height)/2;
break
;
case
NORTH:
y = frameY + frameHeight - height - borderY;
break
;
}
{
Rect r;
r. left = x;
r. bottom = y;
r. right = x + width;
r. top = y + height;
slavePtr-> self-> set_rect(( Handle) slavePtr, r);
}
}
}
void
Widget_pack_enter( Handle self)
{
Handle master, ptr;
if
( var-> geomInfo. order &&
!hash_fetch( prima_guts.objects, &var-> geomInfo. order,
sizeof
(Handle))) {
var-> geomInfo. order = NULL_HANDLE;
var-> geomInfo. after = 0;
}
if
( var-> geomInfo. in) {
if
( hash_fetch( prima_guts.objects, &var-> geomInfo. in,
sizeof
(Handle)))
var-> geomInfo. in = Widget_check_in( self, var-> geomInfo. in, gtPack);
else
croak(
"%s: bad in"
,
"Prima::Widget::pack"
);
}
else
{
var-> geomInfo. in = NULL_HANDLE;
Widget_check_in( self, var-> owner, gtPack);
}
master = (( var-> geomInfo. in) ? var-> geomInfo. in : var-> owner);
if
( PWidget( master)-> packSlaves) {
ptr = PWidget( master)-> packSlaves;
if
( ptr != var-> geomInfo. order) {
Handle optr = ptr;
Bool inserted =
false
;
while
( ptr) {
if
( ptr == var-> geomInfo. order) {
if
( var-> geomInfo. after) {
var-> geomInfo. next = PWidget( ptr)-> geomInfo. next;
PWidget( ptr)-> geomInfo. next = self;
}
else
{
var-> geomInfo. next = ptr;
PWidget( optr)-> geomInfo. next = self;
}
inserted =
true
;
break
;
}
optr = ptr;
ptr = PWidget( ptr)-> geomInfo. next;
}
if
( !inserted) PWidget( optr)-> geomInfo. next = self;
}
else
{
if
( var-> geomInfo. after) {
var-> geomInfo. next = PWidget( ptr)-> geomInfo. next;
PWidget( ptr)-> geomInfo. next = self;
}
else
{
var-> geomInfo. next = ptr;
PWidget( master)-> packSlaves = self;
}
}
}
else
{
PWidget( master)-> packSlaves = self;
}
}
void
Widget_pack_leave( Handle self)
{
Handle ptr, master;
master = (( var-> geomInfo. in) ? var-> geomInfo. in : var-> owner);
if
( master) {
if
(( ptr = PWidget( master)-> packSlaves) != self) {
if
( ptr) {
while
( PWidget(ptr)-> geomInfo. next) {
if
( PWidget(ptr)-> geomInfo. next == self) {
PWidget(ptr)-> geomInfo. next = var-> geomInfo. next;
break
;
}
ptr = PWidget(ptr)-> geomInfo. next;
}
}
}
else
{
PWidget( master)-> packSlaves = var-> geomInfo. next;
}
}
var-> geomInfo. next = NULL_HANDLE;
}
SV *
Widget_packInfo( Handle self, Bool set, SV * packInfo)
{
if
( !set) {
HV * profile = newHV();
GeomInfo *p = &var-> geomInfo;
switch
( p-> side) {
case
LEFT : pset_c( side,
"top"
);
break
;
case
BOTTOM : pset_c( side,
"bottom"
);
break
;
case
RIGHT : pset_c( side,
"right"
);
break
;
case
TOP : pset_c( side,
"top"
);
break
;
}
if
( p-> fillx) {
pset_c( fill, p-> filly ?
"both"
:
"x"
);
}
else
{
pset_c( fill, p-> filly ?
"y"
:
"none"
);
}
pset_i( expand, p-> expand);
switch
( p-> anchorx) {
case
WEST:
pset_c( anchor,
(( p-> anchory == NORTH) ?
"nw"
: (( p-> anchory == CENTER) ?
"w"
:
"sw"
))
);
break
;
case
CENTER:
pset_c( anchor,
(( p-> anchory == NORTH) ?
"n"
: (( p-> anchory == CENTER) ?
"center"
:
"s"
))
);
break
;
case
EAST:
pset_c( anchor,
(( p-> anchory == NORTH) ?
"ne"
: (( p-> anchory == CENTER) ?
"e"
:
"se"
))
);
break
;
}
pset_H( after, ( p-> order && p-> after) ? p-> order : NULL_HANDLE);
pset_H( before, ( p-> order && !p-> after) ? p-> order : NULL_HANDLE);
pset_H( in, var-> geomInfo. in);
pset_i( ipadx, p-> ipad. x);
pset_i( ipady, p-> ipad. y);
pset_i( padx, p-> pad. x);
pset_i( pady, p-> pad. y);
return
newRV_noinc(( SV *) profile);
}
else
{
dPROFILE;
HV * profile;
Bool reset_zorder =
false
, set_in =
false
;
Handle in = NULL_HANDLE;
if
( !SvOK(packInfo))
return
NULL_SV;
if
( !SvOK(packInfo) || !SvROK(packInfo) || SvTYPE(SvRV(packInfo)) != SVt_PVHV)
croak(
"Widget::packInfo: parameter is not a hash"
);
profile = ( HV*) SvRV( packInfo);
if
( pexist( side)) {
char
* c = pget_c( side);
if
( *c ==
'l'
&& (
strcmp
( c,
"left"
)==0)) var-> geomInfo. side = LEFT;
else
if
( *c ==
'b'
&& (
strcmp
( c,
"bottom"
)==0)) var-> geomInfo. side = BOTTOM;
else
if
( *c ==
'r'
&& (
strcmp
( c,
"right"
)==0)) var-> geomInfo. side = RIGHT;
else
if
( *c ==
't'
&& (
strcmp
( c,
"top"
)==0)) var-> geomInfo. side = TOP;
else
croak(
"%s: invalid 'side'"
,
"Prima::Widget::pack"
);
}
if
( pexist( fill)) {
char
* c = pget_c( fill);
if
((
strcmp
( c,
"x"
) == 0)) {
var-> geomInfo. fillx = 1;
var-> geomInfo. filly = 0;
}
else
if
((
strcmp
( c,
"y"
) == 0)) {
var-> geomInfo. fillx = 0;
var-> geomInfo. filly = 1;
}
else
if
( *c ==
'n'
&& (
strcmp
( c,
"none"
) == 0)) {
var-> geomInfo. fillx =
var-> geomInfo. filly = 0;
}
else
if
( *c ==
'b'
&& (
strcmp
( c,
"both"
) == 0)) {
var-> geomInfo. fillx =
var-> geomInfo. filly = 1;
}
else
croak(
"%s: invalid 'fill'"
,
"Prima::Widget::pack"
);
}
if
( pexist( expand)) {
var-> geomInfo. expand = pget_B( expand);
}
if
( pexist( anchor)) {
char
* c = pget_c( anchor);
if
((
strcmp
( c,
"n"
) == 0)) {
var-> geomInfo. anchorx = CENTER;
var-> geomInfo. anchory = NORTH;
}
else
if
((
strcmp
( c,
"ne"
) == 0)) {
var-> geomInfo. anchorx = EAST;
var-> geomInfo. anchory = NORTH;
}
else
if
((
strcmp
( c,
"e"
) == 0)) {
var-> geomInfo. anchorx = EAST;
var-> geomInfo. anchory = CENTER;
}
else
if
((
strcmp
( c,
"se"
) == 0)) {
var-> geomInfo. anchorx = EAST;
var-> geomInfo. anchory = SOUTH;
}
else
if
((
strcmp
( c,
"s"
) == 0)) {
var-> geomInfo. anchorx = CENTER;
var-> geomInfo. anchory = SOUTH;
}
else
if
((
strcmp
( c,
"sw"
) == 0)) {
var-> geomInfo. anchorx = WEST;
var-> geomInfo. anchory = SOUTH;
}
else
if
((
strcmp
( c,
"w"
) == 0)) {
var-> geomInfo. anchorx = WEST;
var-> geomInfo. anchory = CENTER;
}
else
if
((
strcmp
( c,
"nw"
) == 0)) {
var-> geomInfo. anchorx = WEST;
var-> geomInfo. anchory = NORTH;
}
else
if
( *c ==
'c'
&& (
strcmp
( c,
"center"
) == 0)) {
var-> geomInfo. anchorx = CENTER;
var-> geomInfo. anchory = CENTER;
}
else
croak(
"%s: invalid 'anchor'"
,
"Prima::Widget::pack"
);
}
if
( pexist( ipad)) var-> geomInfo. ipad. x = var-> geomInfo. ipad. y = pget_i( ipad);
if
( pexist( ipadx)) var-> geomInfo. ipad. x = pget_i( ipadx);
if
( pexist( ipady)) var-> geomInfo. ipad. y = pget_i( ipady);
if
( pexist( pad)) var-> geomInfo. pad. x = var-> geomInfo. pad. y = pget_i( pad);
if
( pexist( padx)) var-> geomInfo. pad. x = pget_i( padx);
if
( pexist( pady)) var-> geomInfo. pad. y = pget_i( pady);
if
( pexist( after)) {
SV * sv = pget_sv( after);
if
( SvOK(sv)) {
if
( !( var-> geomInfo. order = gimme_the_mate( sv)))
croak(
"%s: invalid 'after'"
,
"Prima::Widget::pack"
);
var-> geomInfo. after = 1;
if
( pexist( before)) {
sv = pget_sv( before);
if
( SvOK(sv))
croak(
"%s: 'after' and 'before' cannot be present simultaneously"
,
"Prima::Widget::pack"
);
}
}
else
{
var-> geomInfo. order = NULL_HANDLE;
var-> geomInfo. after = 0;
}
reset_zorder =
true
;
}
else
if
( pexist( before)) {
SV * sv = pget_sv( before);
if
( SvOK(sv)) {
if
( !( var-> geomInfo. order = gimme_the_mate( sv)))
croak(
"%s: invalid 'before'"
,
"Prima::Widget::pack"
);
}
else
var-> geomInfo. order = NULL_HANDLE;
var-> geomInfo. after = 0;
reset_zorder =
true
;
}
if
( pexist( in)) {
SV * sv = pget_sv( in);
in = NULL_HANDLE;
if
( SvOK( sv))
in = Widget_check_in( self, gimme_the_mate( sv), gtPlace);
set_in = reset_zorder =
true
;
}
if
( var-> geometry == gtPack) {
if
( reset_zorder)
Widget_pack_leave( self);
}
if
( set_in) var-> geomInfo. in = in;
if
( var-> geometry == gtPack) {
if
( reset_zorder)
Widget_pack_enter( self);
geometry_reset( MASTER, gtPack);
}
}
return
NULL_SV;
}
XS( Widget_get_pack_slaves_FROMPERL)
{
dXSARGS;
Handle self;
if
( items != 1)
croak (
"Invalid usage of Widget.get_pack_slaves"
);
SP -= items;
self = gimme_the_mate( ST( 0));
if
( self == NULL_HANDLE)
croak(
"Illegal object reference passed to Widget.get_pack_slaves"
);
self = var-> packSlaves;
while
( self) {
XPUSHs( sv_2mortal( newSVsv((( PAnyObject) self)-> mate)));
self = var-> geomInfo. next;
}
PUTBACK;
return
;
}
void
Widget_get_pack_slaves ( Handle self) { warn(
"Invalid call of Widget::get_pack_slaves"
); }
void
Widget_get_pack_slaves_REDEFINED( Handle self) { warn(
"Invalid call of Widget::get_pack_slaves"
); }
void
Widget_place_enter( Handle self)
{
Handle master, ptr;
if
( var-> geomInfo. in) {
if
( hash_fetch( prima_guts.objects, &var-> geomInfo. in,
sizeof
(Handle)))
var-> geomInfo. in = Widget_check_in( self, var-> geomInfo. in, gtPlace);
else
croak(
"%s: bad in"
,
"Prima::Widget::place"
);
}
else
{
var-> geomInfo. in = NULL_HANDLE;
Widget_check_in( self, var-> owner, gtPlace);
}
master = (( var-> geomInfo. in) ? var-> geomInfo. in : var-> owner);
if
( PWidget( master)-> placeSlaves) {
if
(( ptr = PWidget( master)-> placeSlaves)) {
while
( PWidget( ptr)-> geomInfo. next)
ptr = PWidget( ptr)-> geomInfo. next;
PWidget( ptr)-> geomInfo. next = self;
}
else
{
var-> geomInfo. next = ptr;
PWidget( master)-> placeSlaves = self;
}
}
else
{
PWidget( master)-> placeSlaves = self;
}
}
void
Widget_place_leave( Handle self)
{
Handle ptr, master;
master = (( var-> geomInfo. in) ? var-> geomInfo. in : var-> owner);
if
( master) {
if
(( ptr = PWidget( master)-> placeSlaves) != self) {
if
( ptr) {
while
( PWidget(ptr)-> geomInfo. next) {
if
( PWidget(ptr)-> geomInfo. next == self) {
PWidget(ptr)-> geomInfo. next = var-> geomInfo. next;
break
;
}
ptr = PWidget(ptr)-> geomInfo. next;
}
}
}
else
{
PWidget( master)-> placeSlaves = var-> geomInfo. next;
}
}
var-> geomInfo. next = NULL_HANDLE;
}
void
Widget_place_slaves( Handle self)
{
PWidget slave, master;
int
x, y, width, height, tmp;
int
masterWidth, masterHeight;
double
x1, y1, x2, y2;
Point size;
if
(!( master = ( PWidget) var-> placeSlaves))
return
;
size = my-> get_size( self);
masterWidth = size. x;
masterHeight = size. y;
for
(
slave = master;
slave != NULL;
slave = ( PWidget) slave-> geomInfo. next
) {
Point sz;
register
GeomInfo* slavePtr = &slave-> geomInfo;
sz = slave-> self-> get_size(( Handle) slave);
x1 = slavePtr->x + (slavePtr->relX*masterWidth);
x = (
int
) (x1 + ((x1 > 0) ? 0.5 : -0.5));
y1 = slavePtr->y + (slavePtr->relY*masterHeight);
y = (
int
) (y1 + ((y1 > 0) ? 0.5 : -0.5));
if
(slavePtr-> use_w || slavePtr-> use_rw) {
width = 0;
if
(slavePtr-> use_w) {
width += slave->geomSize.x;
}
if
(slavePtr-> use_rw) {
x2 = x1 + (slavePtr->relWidth*masterWidth);
tmp = (
int
) (x2 + ((x2 > 0) ? 0.5 : -0.5));
width += tmp - x;
}
}
else
{
width = sz. x;
}
if
(slavePtr-> use_h || slavePtr-> use_rh) {
height = 0;
if
(slavePtr->use_h) {
height += slave->geomSize. y;
}
if
(slavePtr->use_rh) {
y2 = y1 + (slavePtr->relHeight*masterHeight);
tmp = (
int
) (y2 + ((y2 > 0) ? 0.5 : -0.5));
height += tmp - y;
}
}
else
{
height = sz. y;
}
switch
(slavePtr-> anchorx) {
case
WEST:
break
;
case
CENTER:
x -= width/2;
break
;
case
EAST:
x -= width;
break
;
}
switch
(slavePtr-> anchory) {
case
NORTH:
y -= height;
break
;
case
CENTER:
y -= height/2;
break
;
case
SOUTH:
break
;
}
{
Rect r;
r. left = x;
r. bottom = y;
r. right = x + width;
r. top = y + height;
slave-> self-> set_rect(( Handle) slave, r);
}
}
}
SV *
Widget_placeInfo( Handle self, Bool set, SV * placeInfo)
{
if
( !set) {
HV * profile = newHV();
GeomInfo *p = &var-> geomInfo;
switch
( p-> anchorx) {
case
WEST:
pset_c( anchor,
(( p-> anchory == NORTH) ?
"nw"
: (( p-> anchory == CENTER) ?
"w"
:
"sw"
))
);
break
;
case
CENTER:
pset_c( anchor,
(( p-> anchory == NORTH) ?
"n"
: (( p-> anchory == CENTER) ?
"center"
:
"s"
))
);
break
;
case
EAST:
pset_c( anchor,
(( p-> anchory == NORTH) ?
"ne"
: (( p-> anchory == CENTER) ?
"e"
:
"se"
))
);
break
;
}
pset_H( in, var-> geomInfo. in);
if
( p-> use_x) pset_i( x, p-> x);
if
( p-> use_y) pset_i( y, p-> y);
if
( p-> use_w) pset_i( width, var-> geomSize. x);
if
( p-> use_h) pset_i( height, var-> geomSize. y);
if
( p-> use_rx) pset_f( relx, p-> relX);
if
( p-> use_ry) pset_f( rely, p-> relY);
if
( p-> use_rw) pset_f( relwidth, p-> relWidth);
if
( p-> use_rh) pset_f( relheight, p-> relHeight);
return
newRV_noinc(( SV *) profile);
}
else
{
dPROFILE;
HV * profile;
Handle in = NULL_HANDLE;
Bool set_in =
false
;
if
( !SvOK(placeInfo))
return
NULL_SV;
if
( !SvOK(placeInfo) || !SvROK(placeInfo) || SvTYPE(SvRV(placeInfo)) != SVt_PVHV)
croak(
"Widget::placeInfo: parameter is not a hash"
);
profile = ( HV*) SvRV( placeInfo);
if
( pexist( anchor)) {
char
* c = pget_c( anchor);
if
((
strcmp
( c,
"n"
) == 0)) {
var-> geomInfo. anchorx = CENTER;
var-> geomInfo. anchory = NORTH;
}
else
if
((
strcmp
( c,
"ne"
) == 0)) {
var-> geomInfo. anchorx = EAST;
var-> geomInfo. anchory = NORTH;
}
else
if
((
strcmp
( c,
"e"
) == 0)) {
var-> geomInfo. anchorx = EAST;
var-> geomInfo. anchory = CENTER;
}
else
if
((
strcmp
( c,
"se"
) == 0)) {
var-> geomInfo. anchorx = EAST;
var-> geomInfo. anchory = SOUTH;
}
else
if
((
strcmp
( c,
"s"
) == 0)) {
var-> geomInfo. anchorx = CENTER;
var-> geomInfo. anchory = SOUTH;
}
else
if
((
strcmp
( c,
"sw"
) == 0)) {
var-> geomInfo. anchorx = WEST;
var-> geomInfo. anchory = SOUTH;
}
else
if
((
strcmp
( c,
"w"
) == 0)) {
var-> geomInfo. anchorx = WEST;
var-> geomInfo. anchory = CENTER;
}
else
if
((
strcmp
( c,
"nw"
) == 0)) {
var-> geomInfo. anchorx = WEST;
var-> geomInfo. anchory = NORTH;
}
else
if
( *c ==
'c'
&& (
strcmp
( c,
"center"
) == 0)) {
var-> geomInfo. anchorx = CENTER;
var-> geomInfo. anchory = CENTER;
}
else
croak(
"%s: invalid 'anchor'"
,
"Prima::Widget::place"
);
}
if
( pexist( x)) {
SV * sv = pget_sv( x);
if
(( var-> geomInfo. use_x = ( SvOK(sv) ? 1 : 0 )))
var-> geomInfo. x = SvIV( sv);
}
if
( pexist( y)) {
SV * sv = pget_sv( y);
if
(( var-> geomInfo. use_y = ( SvOK(sv) ? 1 : 0 )))
var-> geomInfo. y = SvIV( sv);
}
if
( pexist( width)) {
SV * sv = pget_sv( width);
if
(( var-> geomInfo. use_w = ( SvOK(sv) ? 1 : 0 )))
var-> geomSize. x = SvIV( sv);
}
if
( pexist( height)) {
SV * sv = pget_sv( height);
if
(( var-> geomInfo. use_h = ( SvOK(sv) ? 1 : 0 )))
var-> geomSize. y = SvIV( sv);
}
if
( pexist( relx)) {
SV * sv = pget_sv( relx);
if
(( var-> geomInfo. use_rx = ( SvOK(sv) ? 1 : 0 )))
var-> geomInfo. relX = SvNV( sv);
}
if
( pexist( rely)) {
SV * sv = pget_sv( rely);
if
(( var-> geomInfo. use_ry = ( SvOK(sv) ? 1 : 0 )))
var-> geomInfo. relY = SvNV( sv);
}
if
( pexist( relwidth)) {
SV * sv = pget_sv( relwidth);
if
(( var-> geomInfo. use_rw = ( SvOK(sv) ? 1 : 0 )))
var-> geomInfo. relWidth = SvNV( sv);
}
if
( pexist( relheight)) {
SV * sv = pget_sv( relheight);
if
(( var-> geomInfo. use_rh = ( SvOK(sv) ? 1 : 0 )))
var-> geomInfo. relHeight = SvNV( sv);
}
if
( pexist( in)) {
SV * sv = pget_sv( in);
in = NULL_HANDLE;
if
( SvOK(sv))
in = Widget_check_in( self, gimme_the_mate( sv), gtPlace);
set_in =
true
;
}
if
( var-> geometry == gtPlace) {
if
( set_in)
Widget_place_leave( self);
}
if
( set_in) var-> geomInfo. in = in;
if
( var-> geometry == gtPlace) {
if
( set_in)
Widget_place_enter( self);
geometry_reset( MASTER, gtPlace);
}
}
return
NULL_SV;
}
XS( Widget_get_place_slaves_FROMPERL)
{
dXSARGS;
int
i;
Handle self;
if
( items != 1)
croak (
"Invalid usage of Widget.get_pack_slaves"
);
SP -= items;
self = gimme_the_mate( ST( 0));
if
( self == NULL_HANDLE)
croak(
"Illegal object reference passed to Widget.get_pack_slaves"
);
for
( i = 0; i < var-> widgets. count; i++) {
if
( PWidget( var-> widgets. items[i])-> geometry == gtPlace)
XPUSHs( sv_2mortal( newSVsv((( PAnyObject)(var-> widgets. items[i]))-> mate)));
}
PUTBACK;
return
;
}
void
Widget_get_place_slaves ( Handle self) { warn(
"Invalid call of Widget::get_place_slaves"
); }
void
Widget_get_place_slaves_REDEFINED( Handle self) { warn(
"Invalid call of Widget::get_place_slaves"
); }
#ifdef __cplusplus
}
#endif