diff --git a/lib/betawidget/vector.c b/lib/betawidget/vector.c index d6839c825..89f62dea9 100644 --- a/lib/betawidget/vector.c +++ b/lib/betawidget/vector.c @@ -102,4 +102,3 @@ int vectorSize(vector *v) { return v->head; } - diff --git a/lib/betawidget/widget.c b/lib/betawidget/widget.c index ba936d94a..fe349394d 100644 --- a/lib/betawidget/widget.c +++ b/lib/betawidget/widget.c @@ -34,6 +34,13 @@ static void widgetInitVtbl(widget *self) vtbl.enable = widgetEnableImpl; vtbl.disable = widgetDisableImpl; + vtbl.getMinSize = widgetGetMinSizeImpl; + vtbl.getMaxSize = widgetGetMaxSizeImpl; + + vtbl.setAlign = widgetSetAlignImpl; + + vtbl.doLayout = NULL; + vtbl.doDraw = NULL; vtbl.destroy = widgetDestroyImpl; @@ -108,7 +115,7 @@ static void widgetDrawChildren(widget *self, cairo_t *cr) // Draw our children for (i = 0; i < vectorSize(self->children); i++) { - widget *child = WIDGET(vectorAt(self->children, i)); + widget *child = vectorAt(self->children, i); cairo_matrix_t current; // Translate such that (0,0) is the location of the widget @@ -200,12 +207,25 @@ bool widgetAddChildImpl(widget *self, widget *child) // Add the widget vectorAdd(self->children, child); - // FIXME: We need to do some arbitration - - // Set ourself as its parent - child->parent = self; - - return true; + // Re-layout ourself + if (widgetDoLayout(self)) + { + // Set ourself as its parent + child->parent = self; + + return true; + } + // Not enough space to fit the widget + else + { + // Remove child + widgetRemoveChild(self, child); + + // Restore the layout + widgetDoLayout(self); + + return false; + } } /* @@ -294,7 +314,7 @@ void widgetEnableImpl(widget *self) // Enable all of our children for (i = 0; i < vectorSize(self->children); i++) { - widgetEnable(WIDGET(vectorAt(self->children, i))); + widgetEnable(vectorAt(self->children, i)); } } @@ -380,6 +400,26 @@ void widgetBlurImpl(widget *self) widgetFireCallbacks(self, &evt); } +point widgetGetMinSizeImpl(widget *self) +{ + return self->minSize; +} + +point widgetGetMaxSizeImpl(widget *self) +{ + return self->maxSize; +} + +void widgetSetAlignImpl(widget *self, vAlign v, hAlign h) +{ + self->vAlignment = v; + self->hAlignment = h; + + // Re-align our children + // TODO: We should check the return value here + widgetDoLayout(self); +} + widget *widgetGetCurrentlyFocused(widget *self) { int i; @@ -495,11 +535,35 @@ void widgetBlur(widget *self) WIDGET_GET_VTBL(self)->blur(self); } +point widgetGetMinSize(widget *self) +{ + return WIDGET_GET_VTBL(self)->getMinSize(self); +} + +point widgetGetMaxSize(widget *self) +{ + return WIDGET_GET_VTBL(self)->getMaxSize(self); +} + +void widgetSetAlign(widget *self, vAlign v, hAlign h) +{ + WIDGET_GET_VTBL(self)->setAlign(self, v, h); +} + void widgetDoDraw(widget *self, cairo_t *cr) { + WIDGET_CHECK_METHOD(self, doDraw); + WIDGET_GET_VTBL(self)->doDraw(self, cr); } +bool widgetDoLayout(widget *self) +{ + WIDGET_CHECK_METHOD(self, doLayout); + + return WIDGET_GET_VTBL(self)->doLayout(self); +} + bool widgetHandleEvent(widget *self, event *evt) { return WIDGET_GET_VTBL(self)->handleEvent(self, evt); diff --git a/lib/betawidget/widget.h b/lib/betawidget/widget.h index 8f01b0330..35c2400f5 100644 --- a/lib/betawidget/widget.h +++ b/lib/betawidget/widget.h @@ -1,6 +1,9 @@ #ifndef WIDGET_H_ #define WIDGET_H_ +// TODO: Make this cross platform (MSVC) +#include + #include #include "vector.h" @@ -25,6 +28,9 @@ typedef bool (*callback) (widget *widget, event *evt, void *userData); typedef struct _eventTableEntry eventTableEntry; +typedef enum _hAlign hAlign; +typedef enum _vAlign vAlign; + /* * The valid event types */ @@ -140,7 +146,27 @@ struct _eventTableEntry }; /* - * The widget classes virtual method table. + * The possible horizontal sides a child can be aligned to + */ +enum _hAlign +{ + LEFT, + CENTRE, + RIGHT +}; + +/* + * The possible vertical sides a child can be aligned to + */ +enum _vAlign +{ + TOP, + MIDDLE, + BOTTOM +}; + +/* + * The widget classes virtual method table */ struct _widgetVtbl { @@ -160,7 +186,13 @@ struct _widgetVtbl void (*enable) (widget *self); void (*disable) (widget *self); + point (*getMinSize) (widget *self); + point (*getMaxSize) (widget *self); + + void (*setAlign) (widget *self, vAlign v, hAlign h); + void (*doDraw) (widget *self, cairo_t *cr); + bool (*doLayout) (widget *self); void (*destroy) (widget *self); }; @@ -190,6 +222,22 @@ struct _widget */ widget *parent; + /* + * The minimum size the widget can be + */ + point minSize; + + /* + * The maximum size the widget can be + */ + point maxSize; + + /* + * Child alignment + */ + vAlign vAlignment; + hAlign hAlignment; + //-------------------------------------- // Public members //-------------------------------------- @@ -203,7 +251,7 @@ struct _widget * Arbitary user-defined data */ void *pUserData; - int userData; + int32_t userData; /* * The offset of the widget relative to its parent @@ -236,6 +284,7 @@ struct _widget */ #define WIDGET(self) ((widget *) (self)) #define WIDGET_GET_VTBL(self) ((WIDGET(self))->vtbl) +#define WIDGET_CHECK_METHOD(self, method) (assert(WIDGET_GET_VTBL(self)->method)) /* * Protected methods @@ -252,6 +301,10 @@ void widgetEnableImpl(widget *self); void widgetDisableImpl(widget *self); void widgetFocusImpl(widget *self); void widgetBlurImpl(widget *self); +point widgetGetMinSizeImpl(widget *self); +point widgetGetMaxSizeImpl(widget *self); +void widgetSetAlignImpl(widget *self, vAlign v, hAlign h); +void widgetDoAlignImpl(widget *self); bool widgetHandleEventImpl(widget *instance, event *evt); @@ -297,8 +350,8 @@ widget *windgetGetRoot(widget *self); /** * Attempts to add child as a child widget of self. The exact location of the - * widget (as well as its dimensions) are decided during an arbitration process - * between the self and the child. + * widget (as well as its dimensions) are decided based off of the min & max + * sizes of the child. * * @param self The widget to add the child widget to. * @param child The widget to be added. @@ -399,7 +452,7 @@ widget *widgetGetCurrentlyFocused(widget *self); void widgetFocus(widget *self); /** -c * Blurs the current widget (removes keyboard focus from it). Before self is + * Blurs the current widget (removes keyboard focus from it). Before self is * blurred any child widget with focus is blurred first. Finally the EVT_BLUR * event handlers for self are fired. * @@ -407,6 +460,33 @@ c * Blurs the current widget (removes keyboard focus from it). Before self is */ void widgetBlur(widget *self); +/** + * Returns the minimum size that the widget can be. + * + * @param self The widget to return the miniumum size of. + * @return The miniumum (x,y) size of the widget. + */ +point widgetGetMinSize(widget *self); + +/** + * Returns the maxiumum size that the widget can be. A value of -1 for either + * the x or y co-ordinate means that there is no maximum size. + * + * @param self The widget to return the maximum size of. + * @return The maximum (x,y) size of the widget. + */ +point widgetGetMaxSize(widget *self); + +/** + * Sets the alignment of child widgets of self. This is used when the maximum + * size of the child widgets is less than that of the size of self. + * + * @param self The widget to set the alignment of. + * @param v The vertical alignment of the widget (TOP, MIDDLE, BOTTOM). + * @param h The horizontal alignment of the widget (LEFT, CENTRE, RIGHT). + */ +void widgetSetAlign(widget *self, vAlign v, hAlign h); + /** * TODO */ @@ -426,6 +506,11 @@ bool widgetHandleEvent(widget *self, event *evt); */ void widgetDoDraw(widget *self, cairo_t *cr); +/** + * + */ +bool widgetDoLayout(widget *self); + /** * Fires all of the event handlers registered for evt->type on the widger self. * @@ -435,4 +520,3 @@ void widgetDoDraw(widget *self, cairo_t *cr); bool widgetFireCallbacks(widget *self, event *evt); #endif /*WIDGET_H_*/ -