*/
#include "common.h"
#include <stdlib.h>
-#include <strings.h>
+#include <string.h>
#include "wm.h"
+#include <acess/sys.h> // _SysDebug
// === IMPORTS ===
extern void Decorator_RenderWidget(tElement *Element);
+extern void Video_GetTextDims(tFont *Font, const char *Text, int *W, int *H);
// === PROTOTYPES ===
-tElement *WM_CreateElement(tElement *Parent, int Type, int Flags);
+tElement *AxWin_CreateElement(tElement *Parent, int Type, int Flags, const char *DebugName);
+void AxWin_DeleteElement(tElement *Element);
+void AxWin_SetFlags(tElement *Element, int Flags);
+void AxWin_SetSize(tElement *Element, int Size);
+void AxWin_SetText(tElement *Element, const char *Text);
void WM_UpdateMinDims(tElement *Element);
-void WM_SetFlags(tElement *Element, int Flags);
-void WM_SetSize(tElement *Element, int Size);
-void WM_SetText(tElement *Element, char *Text);
void WM_UpdateDimensions(tElement *Element, int Pass);
void WM_UpdatePosition(tElement *Element);
void WM_RenderWidget(tElement *Element);
void WM_Update(void);
// === GLOBALS ===
-tElement gWM_RootElement;
+// - TODO: Handle windows by having multiple root elements
+tElement gWM_RootElement = {
+ .DebugName = "ROOT"
+};
+
+tApplication *gWM_Applications;
+
+// --- Element type flags
struct {
void (*Init)(tElement *This);
void (*UpdateFlags)(tElement *This);
// === CODE ===
// --- Widget Creation and Control ---
-tElement *WM_CreateElement(tElement *Parent, int Type, int Flags)
+tAxWin_Element *AxWin_CreateElement(tElement *Parent, int Type, int Flags, const char *DebugName)
{
tElement *ret;
+ const char *dbgName = DebugName ? DebugName : "";
- ret = calloc(sizeof(tElement), 1);
+ ret = calloc(sizeof(tElement)+strlen(dbgName)+1, 1);
if(!ret) return NULL;
// Prepare
ret->Type = Type;
+ strcpy(ret->DebugName, dbgName);
if(Parent == NULL) Parent = &gWM_RootElement;
ret->Parent = Parent;
ret->Flags = Flags;
// Append to parent's list
- ret->NextSibling = Parent->LastChild;
+ if(Parent->LastChild)
+ Parent->LastChild->NextSibling = ret;
Parent->LastChild = ret;
if(!Parent->FirstChild) Parent->FirstChild = ret;
return ret;
}
+/**
+ * \brief
+ */
+void AxWin_DeleteElement(tElement *Element)
+{
+ // TODO: Implement AxWin_DeleteElement
+ free(Element);
+}
+
/**
* \brief Alter an element's flags
*/
-void WM_SetFlags(tElement *Element, int Flags)
+void AxWin_SetFlags(tElement *Element, int Flags)
{
// Permissions are handled in the message handler
if(!Element) {
return ;
}
-void WM_SetSize(tElement *Element, int Size)
+void AxWin_SetSize(tElement *Element, int Size)
{
if(!Element) return ;
Element->FixedWith = Size;
return ;
}
-void WM_SetText(tElement *Element, char *Text)
+/**
+ * \brief Set the text field of an element
+ * \note Used for the image path on ELETYPE_IMAGE
+ */
+void AxWin_SetText(tElement *Element, const char *Text)
{
if(!Element) return ;
if(Element->Text) free(Element->Text);
Element->MinCross = ((tImage*)Element->Data)->Height;
}
break;
+
+ case ELETYPE_TEXT:
+ {
+ int w=0, h=0;
+ Video_GetTextDims(NULL, Element->Text, &w, &h);
+ if(Element->Parent && Element->Parent->Flags & ELEFLAG_VERTICAL) {
+ Element->MinCross = w;
+ Element->MinWith = h;
+ }
+ else {
+ Element->MinWith = w;
+ Element->MinCross = h;
+ }
+ }
+ break;
+ default: // Any other, no special case
+ break ;
}
return ;
}
// --- Pre-Rendering ---
+/**
+ * \name Pre-Rendering
+ * \brief Updates the element positions and sizes
+ * \{
+ */
/**
* \brief Updates the dimensions of an element
+ * \todo What is the \a Pass parameter for
*
* The dimensions of an element are calculated from the parent's
* cross dimension (the side at right angles to the alignment) sans some
int fixedSize = 0;
int fullCross, dynWith;
- _SysDebug("%p -> Flags = 0x%x", Element, Element->Flags);
- _SysDebug("%p ->CachedH = %i, ->PaddingT = %i, ->PaddingB = %i",
- Element, Element->CachedH, Element->PaddingT, Element->PaddingB
+ _SysDebug("WM_UpdateDimensions %p'%s'", Element, Element->DebugName);
+ _SysDebug(" -> Flags = 0x%x", Element->Flags);
+ _SysDebug(" ->CachedH = %i, ->PaddingT = %i, ->PaddingB = %i",
+ Element->CachedH, Element->PaddingT, Element->PaddingB
);
- _SysDebug("%p ->CachedW = %i, ->PaddingL = %i, ->PaddingR = %i",
- Element, Element->CachedW, Element->PaddingL, Element->PaddingR
+ _SysDebug(" ->CachedW = %i, ->PaddingL = %i, ->PaddingR = %i",
+ Element->CachedW, Element->PaddingL, Element->PaddingR
);
// Pass 1
if( child->Flags & ELEFLAG_ABSOLUTEPOS )
continue ;
- _SysDebug("%p,%p ->FixedWith = %i", Element, child, child->FixedWith);
+ _SysDebug(" > %p'%s' ->FixedWith = %i", child, child->DebugName, child->FixedWith);
if( child->FixedWith )
{
nFixed ++;
nChildren ++;
}
- _SysDebug("%p - nChildren = %i, nFixed = %i", Element, nChildren, nFixed);
+ _SysDebug(" - nChildren = %i, nFixed = %i", Element, nChildren, nFixed);
if( nChildren > nFixed ) {
if( Element->Flags & ELEFLAG_VERTICAL )
dynWith = Element->CachedH - Element->PaddingT
dynWith -= fixedSize;
if( dynWith < 0 ) return ;
dynWith /= nChildren - nFixed;
- _SysDebug("%p - dynWith = %i", Element, dynWith);
+ _SysDebug(" - dynWith = %i", dynWith);
}
if( Element->Flags & ELEFLAG_VERTICAL )
else
fullCross = Element->CachedH - Element->PaddingT - Element->PaddingB;
- _SysDebug("%p - fullCross = %i", Element, fullCross);
+ _SysDebug(" - fullCross = %i", Element, fullCross);
// Pass 2 - Set sizes and recurse
for( child = Element->FirstChild; child; child = child->NextSibling )
{
int cross, with;
- _SysDebug("%p,%p ->MinCross = %i", Element, child, child->MinCross);
+ _SysDebug(" > %p'%s' ->MinCross = %i", child, child->DebugName, child->MinCross);
// --- Cross Size ---
cross = child->MinCross;
else
cross = fullCross;
- _SysDebug("%p,%p - cross = %i", Element, child, cross);
+ _SysDebug(" > %p'%s' - cross = %i", child, child->DebugName, cross);
if( Element->Flags & ELEFLAG_VERTICAL )
child->CachedW = cross;
else
with = child->MinWith;
else
with = dynWith;
- _SysDebug("%p,%p - with = %i", Element, child, with);
+ _SysDebug(" > %p'%s' - with = %i", child, child->DebugName, with);
if( Element->Flags & ELEFLAG_VERTICAL )
child->CachedH = with;
else
child->CachedW = with;
- WM_UpdateDimensions(child, 0);
+ WM_UpdateDimensions(child, Pass);
}
+
+ _SysDebug("%p'%s' Done", Element, Element->DebugName);
}
/**
{
tElement *child;
int x, y;
+ static int depth = 0;
+ char indent[depth+1];
if( Element->Flags & ELEFLAG_NORENDER ) return ;
- _SysDebug("Element=%p{PaddingL:%i, PaddingT:%i}",
- Element, Element->PaddingL, Element->PaddingT);
+ memset(indent, ' ', depth);
+ indent[depth] = '\0';
+ depth ++;
+
+ _SysDebug("%sWM_UpdatePosition %p'%s'{PaddingL:%i, PaddingT:%i}",
+ indent, Element, Element->DebugName, Element->PaddingL, Element->PaddingT);
// Initialise
x = Element->CachedX + Element->PaddingL;
y = Element->CachedY + Element->PaddingT;
+ _SysDebug("%s- Alignment = %s", indent,
+ (Element->Flags & ELEFLAG_VERTICAL) ? "vertical" : "horizontal");
+
// Update each child
for(child = Element->FirstChild; child; child = child->NextSibling)
{
+ _SysDebug("%s- x = %i, y = %i", indent, x, y);
child->CachedX = x;
child->CachedY = y;
// Set Alignment
if( Element->Flags & ELEFLAG_ALIGN_CENTER ) {
- if(Element->Flags & ELEFLAG_VERTICAL )
+ _SysDebug("%sChild being aligned to center", indent);
+ if(Element->Flags & ELEFLAG_VERTICAL)
child->CachedX += Element->CachedW/2 - child->CachedW/2;
else
child->CachedY += Element->CachedH/2 - child->CachedH/2;
}
- else if( Element->Flags & ELEFLAG_ALIGN_END ) {
+ else if( Element->Flags & ELEFLAG_ALIGN_END) {
+ _SysDebug("%sChild being aligned to end", indent);
if(Element->Flags & ELEFLAG_VERTICAL )
- child->CachedX += Element->CachedW - child->CachedW;
+ child->CachedX += Element->CachedW
+ - Element->PaddingL - Element->PaddingR
+ - child->CachedW;
else
- child->CachedY += Element->CachedH - child->CachedH;
+ child->CachedY += Element->CachedH
+ - Element->PaddingT
+ - Element->PaddingB
+ - child->CachedH;
}
+ _SysDebug("%s> %p'%s' at (%i,%i)", indent, child, child->DebugName,
+ child->CachedX, child->CachedY);
+
// Update child's children positions
WM_UpdatePosition(child);
}
}
- _SysDebug("Element %p (%i,%i)",
- Element, Element->CachedX, Element->CachedY
+ _SysDebug("%sElement %p'%s' (%i,%i)",
+ indent, Element, Element->DebugName, Element->CachedX, Element->CachedY
);
+ depth --;
}
-
/**
* \brief Update the minimum dimensions of the element
* \note Called after a child's minimum dimensions have changed
// Recurse upwards
WM_UpdateMinDims(Element->Parent);
}
+/**
+ * \}
+ */
// --- Render ---
void WM_RenderWidget(tElement *Element)