Update the widget animation callback to use widgetReposition as opposed to setting the position directly.
git-svn-id: svn+ssh://svn.gna.org/svn/warzone/trunk@5932 4a71c877-e1ca-e34f-864e-861f7616d084master
parent
906f766b8a
commit
04e2f5f82b
|
@ -240,10 +240,16 @@ static bool widgetAnimationTimerCallback(widget *self, const event *evt,
|
|||
switch (i)
|
||||
{
|
||||
case ANI_TYPE_TRANSLATE:
|
||||
// Update the widgets position
|
||||
self->offset = widgetAnimationInterpolateTranslate(self, k1,
|
||||
k2, time);
|
||||
{
|
||||
// Get the new position
|
||||
point pos = widgetAnimationInterpolateTranslate(self, k1,
|
||||
k2, time);
|
||||
|
||||
// Set the new position
|
||||
widgetReposition(self, pos.x, pos.y);
|
||||
|
||||
break;
|
||||
}
|
||||
case ANI_TYPE_ROTATE:
|
||||
// Update the widgets rotation
|
||||
self->rotate = widgetAnimationInterpolateRotate(self, k1,
|
||||
|
|
|
@ -44,6 +44,7 @@ static void windowInitVtbl(window *self)
|
|||
vtbl.widgetVtbl.addChild = windowAddChildImpl;
|
||||
vtbl.widgetVtbl.doLayout = windowDoLayoutImpl;
|
||||
vtbl.widgetVtbl.doDraw = windowDoDrawImpl;
|
||||
vtbl.widgetVtbl.resize = windowResizeImpl;
|
||||
|
||||
vtbl.widgetVtbl.getMinSize = windowGetMinSizeImpl;
|
||||
vtbl.widgetVtbl.getMaxSize = windowGetMaxSizeImpl;
|
||||
|
@ -77,6 +78,11 @@ void windowInit(window *self, const char *id, int w, int h)
|
|||
|
||||
// Set our size to (w,h)
|
||||
widgetResize(WIDGET(self), w, h);
|
||||
|
||||
// Default anchor state is static (as opposed to dynamic)
|
||||
self->anchorState = ANCHOR_STATIC;
|
||||
self->anchorWindow = NULL;
|
||||
self->anchorRepositionId = self->anchorResizeId = -1;
|
||||
}
|
||||
|
||||
void windowDestroyImpl(widget *self)
|
||||
|
@ -240,9 +246,36 @@ void windowRepositionFromScreen(window *self, hAlign hAlign, int xOffset,
|
|||
widgetReposition(WIDGET(self), x, y);
|
||||
}
|
||||
|
||||
void windowRepositionFromAnchor(window *self, const window *anchor,
|
||||
hAlign hAlign, int xOffset,
|
||||
vAlign vAlign, int yOffset)
|
||||
void windowSetAnchorState(window *self, anchorState state)
|
||||
{
|
||||
// If the anchor is being disabled, remove any active event handlers
|
||||
if (state == ANCHOR_STATIC && self->anchorWindow)
|
||||
{
|
||||
widget *anchorWidget = WIDGET(self->anchorWindow);
|
||||
|
||||
// Remove the reposition event handler
|
||||
if (widgetIsEventHandler(anchorWidget, self->anchorRepositionId))
|
||||
{
|
||||
widgetRemoveEventHandler(anchorWidget, self->anchorRepositionId);
|
||||
}
|
||||
|
||||
// Remove the resize event handler
|
||||
if (widgetIsEventHandler(anchorWidget, self->anchorResizeId))
|
||||
{
|
||||
widgetRemoveEventHandler(anchorWidget, self->anchorResizeId);
|
||||
}
|
||||
|
||||
// We no longer have an anchor window
|
||||
self->anchorWindow = NULL;
|
||||
}
|
||||
|
||||
// Update the state
|
||||
self->anchorState = state;
|
||||
}
|
||||
|
||||
static void windowDoRepositionFromAnchor(window *self, const window *anchor,
|
||||
hAlign hAlign, int xOffset,
|
||||
vAlign vAlign, int yOffset)
|
||||
{
|
||||
int x = 0, y = 0;
|
||||
size anchorSize = WIDGET(anchor)->size;
|
||||
|
@ -285,3 +318,109 @@ void windowRepositionFromAnchor(window *self, const window *anchor,
|
|||
// Reposition
|
||||
widgetReposition(WIDGET(self), x, y);
|
||||
}
|
||||
|
||||
void windowResizeImpl(widget *self, int w, int h)
|
||||
{
|
||||
window *windowSelf = WINDOW(self);
|
||||
|
||||
// Call our parents resize method
|
||||
widgetResizeImpl(self, w, h);
|
||||
|
||||
// If dynamic anchoring is enabled, reposition ourself
|
||||
if (windowSelf->anchorState == ANCHOR_DYNAMIC && windowSelf->anchorWindow)
|
||||
{
|
||||
windowDoRepositionFromAnchor(windowSelf, windowSelf->anchorWindow,
|
||||
windowSelf->anchorHAlign,
|
||||
windowSelf->anchorXOffset,
|
||||
windowSelf->anchorVAlign,
|
||||
windowSelf->anchorYOffset);
|
||||
}
|
||||
}
|
||||
|
||||
static bool windowAnchorCallback(widget *self, const event *evt, int handlerId,
|
||||
void *userData)
|
||||
{
|
||||
// The window to be repositioned is stored in userData
|
||||
window *anchoredWindow = WINDOW(userData);
|
||||
|
||||
// We should only be called to respond to resize and reposition eventd
|
||||
assert(evt->type == EVT_REPOSITION || evt->type == EVT_RESIZE);
|
||||
|
||||
// Call windowDoRepositionFromAnchor to update the position
|
||||
windowDoRepositionFromAnchor(anchoredWindow, WINDOW(self),
|
||||
anchoredWindow->anchorHAlign,
|
||||
anchoredWindow->anchorXOffset,
|
||||
anchoredWindow->anchorVAlign,
|
||||
anchoredWindow->anchorYOffset);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool windowAnchorDestroyCallback(widget *self, const event *evt,
|
||||
int handlerId, void *userData)
|
||||
{
|
||||
// The window that installed us is in userData
|
||||
window *anchoredWindow = WINDOW(userData);
|
||||
|
||||
// Make sure the event is a destruct event
|
||||
assert(evt->type == EVT_DESTRUCT);
|
||||
|
||||
// We are being removed and therefore are no longer anchored
|
||||
anchoredWindow->anchorWindow = NULL;
|
||||
anchoredWindow->anchorRepositionId = anchoredWindow->anchorResizeId = -1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void windowRepositionFromAnchor(window *self, const window *anchor,
|
||||
hAlign hAlign, int xOffset,
|
||||
vAlign vAlign, int yOffset)
|
||||
{
|
||||
// If dynamic anchors are enabled, set up dynamic anchoring
|
||||
if (self->anchorState == ANCHOR_DYNAMIC)
|
||||
{
|
||||
// Get the current anchor (so that we may remove the event handlers)
|
||||
widget *anchorWidget = WIDGET(self->anchorWindow);
|
||||
|
||||
if (anchorWidget)
|
||||
{
|
||||
// Remove any current event handlers we've installed
|
||||
if (widgetIsEventHandler(anchorWidget, self->anchorRepositionId))
|
||||
{
|
||||
widgetRemoveEventHandler(anchorWidget, self->anchorRepositionId);
|
||||
}
|
||||
if (widgetIsEventHandler(anchorWidget, self->anchorResizeId))
|
||||
{
|
||||
widgetRemoveEventHandler(anchorWidget, self->anchorResizeId);
|
||||
}
|
||||
}
|
||||
|
||||
// Save the window/alignment/offsets
|
||||
self->anchorWindow = self;
|
||||
self->anchorHAlign = hAlign;
|
||||
self->anchorXOffset = xOffset;
|
||||
|
||||
self->anchorVAlign = vAlign;
|
||||
self->anchorYOffset = yOffset;
|
||||
|
||||
/*
|
||||
* Install the event handlers, which are required to track changes to
|
||||
* the size and position of the anchor window.
|
||||
*
|
||||
* Here we make the assumption that the event handlers when removed,
|
||||
* will be done so in pairs (and therefore only need to install a single
|
||||
* destructor). The same callback is used for both resize and reposition
|
||||
* events.
|
||||
*/
|
||||
self->anchorRepositionId = widgetAddEventHandler(WIDGET(anchor), EVT_REPOSITION,
|
||||
windowAnchorCallback,
|
||||
NULL, self);
|
||||
self->anchorResizeId = widgetAddEventHandler(WIDGET(anchor), EVT_RESIZE,
|
||||
windowAnchorCallback,
|
||||
windowAnchorDestroyCallback,
|
||||
self);
|
||||
}
|
||||
|
||||
// Reposition the window
|
||||
windowDoRepositionFromAnchor(self, anchor, hAlign, xOffset, vAlign, yOffset);
|
||||
}
|
||||
|
|
|
@ -29,6 +29,18 @@
|
|||
typedef struct _window window;
|
||||
typedef struct _windowVtbl windowVtbl;
|
||||
|
||||
/**
|
||||
* The possible ways in which windowRepositionFromAnchor can act
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/// The window does not track changes in the anchor windows
|
||||
ANCHOR_STATIC,
|
||||
|
||||
/// The window tracks and updates to changes in the anchor window
|
||||
ANCHOR_DYNAMIC
|
||||
} anchorState;
|
||||
|
||||
struct _windowVtbl
|
||||
{
|
||||
widgetVtbl widgetVtbl;
|
||||
|
@ -47,6 +59,42 @@ struct _window
|
|||
* Our vtable
|
||||
*/
|
||||
windowVtbl *vtbl;
|
||||
|
||||
/**
|
||||
* Current anchor state
|
||||
*/
|
||||
anchorState anchorState;
|
||||
|
||||
/**
|
||||
* Anchor window
|
||||
*/
|
||||
window *anchorWindow;
|
||||
|
||||
/**
|
||||
* Anchor horizontal alignment
|
||||
*/
|
||||
hAlign anchorHAlign;
|
||||
|
||||
/**
|
||||
* Anchor horizontal offset
|
||||
*/
|
||||
int anchorXOffset;
|
||||
|
||||
/**
|
||||
* Anchor vertical alignment
|
||||
*/
|
||||
vAlign anchorVAlign;
|
||||
|
||||
/**
|
||||
* Anchor vertical offset
|
||||
*/
|
||||
int anchorYOffset;
|
||||
|
||||
/**
|
||||
* Event handler IDs for anchor events
|
||||
*/
|
||||
int anchorRepositionId;
|
||||
int anchorResizeId;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -68,6 +116,7 @@ void windowDestroyImpl(widget *self);
|
|||
bool windowDoLayoutImpl(widget *self);
|
||||
void windowDoDrawImpl(widget *self);
|
||||
bool windowAddChildImpl(widget *self, widget *child);
|
||||
void windowResizeImpl(widget *self, int w, int h);
|
||||
size windowGetMinSizeImpl(widget *self);
|
||||
size windowGetMaxSizeImpl(widget *self);
|
||||
|
||||
|
@ -130,6 +179,23 @@ void windowSetScreenSize(int w, int h);
|
|||
void windowRepositionFromScreen(window *self, hAlign hAlign, int xOffset,
|
||||
vAlign vAlign, int yOffset);
|
||||
|
||||
/**
|
||||
* Sets the behaviour of windowRepositionFromAchor (with the default being
|
||||
* ANCHOR_STATIC) to state. If the state is the same as the current anchor state
|
||||
* then this method is a no-op.
|
||||
*
|
||||
* It is important to note that:
|
||||
* - setting the state to ANCHOR_STATIC will break the current anchor (if any);
|
||||
* - a state of ANCHOR_DYNAMIC will only take effect after the next call to
|
||||
* windowRepositionFromAnchor;
|
||||
* - calling widgetReposition with an anchor state of ANCHOR_DYNAMIC will cause
|
||||
* strange behaviour - the anchor should be set to ANCHOR_STATIC first.
|
||||
*
|
||||
* @param self The window to set the anchor state for.
|
||||
* @param state The new state to set the anchor behaviour to.
|
||||
*/
|
||||
void windowSetAnchorState(window *self, anchorState state);
|
||||
|
||||
/**
|
||||
* Positions the window relative to the position of another window, anchor.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue