DIR := Apps/AxWin/1.0
BIN := AxWinWM
OBJ := main.o helpers.o commandline.o video.o input.o video_text.o
-OBJ += messages.o interface.o wm.o decorator.o
+OBJ += messages.o interface.o wm.o decorator.o render.o
OBJ += image.o
LDFLAGS += -limage_sif -luri -lnet
--- /dev/null
+/*
+ * Acess GUI (AxWin) Version 2
+ * By John Hodge (thePowersGang)
+ *
+ * Rendering code
+ */
+#include "common.h"
+#include <stdlib.h>
+#include <string.h>
+#include "wm.h"
+#include <acess/sys.h> // _SysDebug
+
+// === IMPORTS ===
+extern void Decorator_RenderWidget(tElement *Element);
+extern tElement gWM_RootElement;
+
+// === PROTOTYPES ===
+void WM_UpdateMinDims(tElement *Element);
+void WM_UpdateDimensions(tElement *Element, int Pass);
+void WM_UpdatePosition(tElement *Element);
+void WM_RenderWidget(tElement *Element);
+void WM_Update(void);
+
+// === CODE ===
+/**
+ * \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
+ * padding.
+ */
+void WM_UpdateDimensions(tElement *Element, int Pass)
+{
+ tElement *child;
+ int nChildren = 0;
+ int nFixed = 0;
+ int maxCross = 0;
+ int fixedSize = 0;
+ int fullCross, dynWith;
+
+ _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(" ->CachedW = %i, ->PaddingL = %i, ->PaddingR = %i",
+ Element->CachedW, Element->PaddingL, Element->PaddingR
+ );
+
+ // Pass 1
+ for( child = Element->FirstChild; child; child = child->NextSibling )
+ {
+ if( child->Flags & ELEFLAG_ABSOLUTEPOS )
+ continue ;
+
+ _SysDebug(" > %p'%s' ->FixedWith = %i", child, child->DebugName, child->FixedWith);
+ if( child->FixedWith )
+ {
+ nFixed ++;
+ fixedSize += child->FixedWith;
+ }
+
+ if( child->FixedCross && maxCross < child->FixedCross )
+ maxCross = child->FixedCross;
+ if( child->MinCross && maxCross < child->MinCross )
+ maxCross = child->MinCross;
+ nChildren ++;
+ }
+
+ _SysDebug(" - nChildren = %i, nFixed = %i", Element, nChildren, nFixed);
+ if( nChildren > nFixed ) {
+ if( Element->Flags & ELEFLAG_VERTICAL )
+ dynWith = Element->CachedH - Element->PaddingT
+ - Element->PaddingB;
+ else
+ dynWith = Element->CachedW - Element->PaddingL
+ - Element->PaddingR;
+ dynWith -= fixedSize;
+ if( dynWith < 0 ) return ;
+ dynWith /= nChildren - nFixed;
+ _SysDebug(" - dynWith = %i", dynWith);
+ }
+
+ if( Element->Flags & ELEFLAG_VERTICAL )
+ fullCross = Element->CachedW - Element->PaddingL - Element->PaddingR;
+ else
+ fullCross = Element->CachedH - Element->PaddingT - Element->PaddingB;
+
+ _SysDebug(" - fullCross = %i", Element, fullCross);
+
+ // Pass 2 - Set sizes and recurse
+ for( child = Element->FirstChild; child; child = child->NextSibling )
+ {
+ int cross, with;
+
+ _SysDebug(" > %p'%s' ->MinCross = %i", child, child->DebugName, child->MinCross);
+
+
+ // --- Cross Size ---
+ if( child->FixedCross )
+ cross = child->FixedCross;
+ // Expand to fill?
+ // TODO: Extra flag so options are (Expand, Equal, Wrap)
+ else if( child->Flags & ELEFLAG_NOEXPAND )
+ cross = child->MinCross;
+ else
+ cross = fullCross;
+ _SysDebug(" > %p'%s' - cross = %i", child, child->DebugName, cross);
+ if( Element->Flags & ELEFLAG_VERTICAL )
+ child->CachedW = cross;
+ else
+ child->CachedH = cross;
+
+ // --- With Size ---
+ if( child->FixedWith)
+ with = child->FixedWith;
+ else if( child->Flags & ELEFLAG_NOSTRETCH )
+ with = child->MinWith;
+ else
+ with = dynWith;
+ _SysDebug(" > %p'%s' - with = %i", child, child->DebugName, with);
+ if( Element->Flags & ELEFLAG_VERTICAL )
+ child->CachedH = with;
+ else
+ child->CachedW = with;
+
+ WM_UpdateDimensions(child, Pass);
+ }
+
+ _SysDebug("%p'%s' Done", Element, Element->DebugName);
+}
+
+/**
+ * \brief Updates the position of an element
+ *
+ * The parent element sets the positions of its children
+ */
+void WM_UpdatePosition(tElement *Element)
+{
+ tElement *child;
+ int x, y;
+ static int depth = 0;
+ char indent[depth+1];
+
+ if( Element->Flags & ELEFLAG_NORENDER ) return ;
+
+ 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 ) {
+ _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) {
+ _SysDebug("%sChild being aligned to end", indent);
+ if(Element->Flags & ELEFLAG_VERTICAL )
+ child->CachedX += Element->CachedW
+ - Element->PaddingL - Element->PaddingR
+ - child->CachedW;
+ else
+ 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);
+
+ // Increment
+ if(Element->Flags & ELEFLAG_VERTICAL ) {
+ y += child->CachedH + Element->GapSize;
+ }
+ else {
+ x += child->CachedW + Element->GapSize;
+ }
+ }
+
+ _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
+ */
+void WM_UpdateMinDims(tElement *Element)
+{
+ tElement *child;
+
+ if(!Element) return;
+
+ Element->MinCross = 0;
+ Element->MinWith = 0;
+
+ for(child = Element->FirstChild; child; child = child->NextSibling)
+ {
+ if( Element->Parent &&
+ (Element->Flags & ELEFLAG_VERTICAL) == (Element->Parent->Flags & ELEFLAG_VERTICAL)
+ )
+ {
+ if(child->FixedCross)
+ Element->MinCross += child->FixedCross;
+ else
+ Element->MinCross += child->MinCross;
+ if(child->FixedWith)
+ Element->MinWith += child->FixedWith;
+ else
+ Element->MinWith += child->MinWith;
+ }
+ else
+ {
+ if(child->FixedCross)
+ Element->MinWith += child->FixedCross;
+ else
+ Element->MinWith += child->MinCross;
+ if(child->FixedWith)
+ Element->MinCross += child->FixedWith;
+ else
+ Element->MinCross += child->MinWith;
+ }
+ }
+
+ // Recurse upwards
+ WM_UpdateMinDims(Element->Parent);
+}
+/**
+ * \}
+ */
+
+// --- Render ---
+void WM_RenderWidget(tElement *Element)
+{
+ tElement *child;
+
+ if( Element->Flags & ELEFLAG_NORENDER ) return ;
+ if( Element->Flags & ELEFLAG_INVISIBLE ) return ;
+
+ Decorator_RenderWidget(Element);
+
+ for(child = Element->FirstChild; child; child = child->NextSibling)
+ {
+ WM_RenderWidget(child);
+ }
+}
+
+void WM_Update(void)
+{
+ gWM_RootElement.CachedX = 0; gWM_RootElement.CachedY = 0;
+ gWM_RootElement.CachedW = giScreenWidth;
+ gWM_RootElement.CachedH = giScreenHeight;
+ gWM_RootElement.Flags |= ELEFLAG_NOEXPAND|ELEFLAG_ABSOLUTEPOS|ELEFLAG_FIXEDSIZE;
+
+ WM_UpdateDimensions( &gWM_RootElement, 0 );
+ WM_UpdatePosition( &gWM_RootElement );
+ WM_RenderWidget( &gWM_RootElement );
+
+ Video_Update();
+}
#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 ===
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_UpdateDimensions(tElement *Element, int Pass);
-void WM_UpdatePosition(tElement *Element);
-void WM_RenderWidget(tElement *Element);
-void WM_Update(void);
// === GLOBALS ===
// - TODO: Handle windows by having multiple root elements
void (*UpdateSize)(tElement *This);
void (*UpdateText)(tElement *This);
} gaWM_WidgetTypes[MAX_ELETYPES] = {
- {NULL, NULL, NULL, NULL}, // NULL
- {NULL, NULL, NULL, NULL} // Box
+ {NULL, NULL, NULL, NULL, NULL}, // NULL
+ {NULL, NULL, NULL, NULL, NULL}, // Window
+ {NULL, NULL, NULL, NULL, NULL} // Box
};
const int ciWM_NumWidgetTypes = sizeof(gaWM_WidgetTypes)/sizeof(gaWM_WidgetTypes[0]);
memcpy(ret->Ident, Ident, IdentLen);
ret->SendMessage = Cb;
+ ret->MaxElementIndex = DEFAULT_ELEMENTS_PER_APP;
+ ret->EleIndex = calloc( 1, ret->MaxElementIndex * sizeof(*ret->EleIndex) );
+
ret->Next = gWM_Applications;
gWM_Applications = ret;
}
/**
- * \brief
+ * \brief Delete an element
*/
void AxWin_DeleteElement(tElement *Element)
{
if( Element->Type < ciWM_NumWidgetTypes && gaWM_WidgetTypes[Element->Type].Delete )
gaWM_WidgetTypes[Element->Type].Delete(Element);
+ if(Element->Owner)
+ Element->Owner->EleIndex[ Element->ApplicationID ] = NULL;
+
+ Element->Type = 0;
+ Element->Owner = 0;
+ Element->Flags = 0;
+
free(Element);
}
return ;
}
+/**
+ * \brief Set the fixed lenghthways size of an element
+ */
void AxWin_SetSize(tElement *Element, int Size)
{
if(!Element) return ;
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
- * padding.
- */
-void WM_UpdateDimensions(tElement *Element, int Pass)
-{
- tElement *child;
- int nChildren = 0;
- int nFixed = 0;
- int maxCross = 0;
- int fixedSize = 0;
- int fullCross, dynWith;
-
- _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(" ->CachedW = %i, ->PaddingL = %i, ->PaddingR = %i",
- Element->CachedW, Element->PaddingL, Element->PaddingR
- );
-
- // Pass 1
- for( child = Element->FirstChild; child; child = child->NextSibling )
- {
- if( child->Flags & ELEFLAG_ABSOLUTEPOS )
- continue ;
-
- _SysDebug(" > %p'%s' ->FixedWith = %i", child, child->DebugName, child->FixedWith);
- if( child->FixedWith )
- {
- nFixed ++;
- fixedSize += child->FixedWith;
- }
-
- if( child->FixedCross && maxCross < child->FixedCross )
- maxCross = child->FixedCross;
- if( child->MinCross && maxCross < child->MinCross )
- maxCross = child->MinCross;
- nChildren ++;
- }
-
- _SysDebug(" - nChildren = %i, nFixed = %i", Element, nChildren, nFixed);
- if( nChildren > nFixed ) {
- if( Element->Flags & ELEFLAG_VERTICAL )
- dynWith = Element->CachedH - Element->PaddingT
- - Element->PaddingB;
- else
- dynWith = Element->CachedW - Element->PaddingL
- - Element->PaddingR;
- dynWith -= fixedSize;
- if( dynWith < 0 ) return ;
- dynWith /= nChildren - nFixed;
- _SysDebug(" - dynWith = %i", dynWith);
- }
-
- if( Element->Flags & ELEFLAG_VERTICAL )
- fullCross = Element->CachedW - Element->PaddingL - Element->PaddingR;
- else
- fullCross = Element->CachedH - Element->PaddingT - Element->PaddingB;
-
- _SysDebug(" - fullCross = %i", Element, fullCross);
-
- // Pass 2 - Set sizes and recurse
- for( child = Element->FirstChild; child; child = child->NextSibling )
- {
- int cross, with;
-
- _SysDebug(" > %p'%s' ->MinCross = %i", child, child->DebugName, child->MinCross);
-
-
- // --- Cross Size ---
- if( child->FixedCross )
- cross = child->FixedCross;
- // Expand to fill?
- // TODO: Extra flag so options are (Expand, Equal, Wrap)
- else if( child->Flags & ELEFLAG_NOEXPAND )
- cross = child->MinCross;
- else
- cross = fullCross;
- _SysDebug(" > %p'%s' - cross = %i", child, child->DebugName, cross);
- if( Element->Flags & ELEFLAG_VERTICAL )
- child->CachedW = cross;
- else
- child->CachedH = cross;
-
- // --- With Size ---
- if( child->FixedWith)
- with = child->FixedWith;
- else if( child->Flags & ELEFLAG_NOSTRETCH )
- with = child->MinWith;
- else
- with = dynWith;
- _SysDebug(" > %p'%s' - with = %i", child, child->DebugName, with);
- if( Element->Flags & ELEFLAG_VERTICAL )
- child->CachedH = with;
- else
- child->CachedW = with;
-
- WM_UpdateDimensions(child, Pass);
- }
-
- _SysDebug("%p'%s' Done", Element, Element->DebugName);
-}
-
-/**
- * \brief Updates the position of an element
- *
- * The parent element sets the positions of its children
- */
-void WM_UpdatePosition(tElement *Element)
-{
- tElement *child;
- int x, y;
- static int depth = 0;
- char indent[depth+1];
-
- if( Element->Flags & ELEFLAG_NORENDER ) return ;
-
- 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 ) {
- _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) {
- _SysDebug("%sChild being aligned to end", indent);
- if(Element->Flags & ELEFLAG_VERTICAL )
- child->CachedX += Element->CachedW
- - Element->PaddingL - Element->PaddingR
- - child->CachedW;
- else
- 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);
-
- // Increment
- if(Element->Flags & ELEFLAG_VERTICAL ) {
- y += child->CachedH + Element->GapSize;
- }
- else {
- x += child->CachedW + Element->GapSize;
- }
- }
-
- _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
- */
-void WM_UpdateMinDims(tElement *Element)
-{
- tElement *child;
-
- if(!Element) return;
-
- Element->MinCross = 0;
- Element->MinWith = 0;
-
- for(child = Element->FirstChild; child; child = child->NextSibling)
- {
- if( Element->Parent &&
- (Element->Flags & ELEFLAG_VERTICAL) == (Element->Parent->Flags & ELEFLAG_VERTICAL)
- )
- {
- if(child->FixedCross)
- Element->MinCross += child->FixedCross;
- else
- Element->MinCross += child->MinCross;
- if(child->FixedWith)
- Element->MinWith += child->FixedWith;
- else
- Element->MinWith += child->MinWith;
- }
- else
- {
- if(child->FixedCross)
- Element->MinWith += child->FixedCross;
- else
- Element->MinWith += child->MinCross;
- if(child->FixedWith)
- Element->MinCross += child->FixedWith;
- else
- Element->MinCross += child->MinWith;
- }
- }
-
- // Recurse upwards
- WM_UpdateMinDims(Element->Parent);
-}
-/**
- * \}
- */
-
-// --- Render ---
-void WM_RenderWidget(tElement *Element)
-{
- tElement *child;
-
- if( Element->Flags & ELEFLAG_NORENDER ) return ;
- if( Element->Flags & ELEFLAG_INVISIBLE ) return ;
-
- Decorator_RenderWidget(Element);
-
- for(child = Element->FirstChild; child; child = child->NextSibling)
- {
- WM_RenderWidget(child);
- }
-}
-
-void WM_Update(void)
-{
- gWM_RootElement.CachedX = 0; gWM_RootElement.CachedY = 0;
- gWM_RootElement.CachedW = giScreenWidth;
- gWM_RootElement.CachedH = giScreenHeight;
- gWM_RootElement.Flags |= ELEFLAG_NOEXPAND|ELEFLAG_ABSOLUTEPOS|ELEFLAG_FIXEDSIZE;
-
- WM_UpdateDimensions( &gWM_RootElement, 0 );
- WM_UpdatePosition( &gWM_RootElement );
- WM_RenderWidget( &gWM_RootElement );
-
- Video_Update();
-}
#include <axwin2/axwin.h>
#include "common.h"
+/**
+ * \brief Number of elements that can be owned by each application)
+ */
+// TODO: Fine tune these values
+#define MAX_ELEMENTS_PER_APP 1024
+#define DEFAULT_ELEMENTS_PER_APP 128
+
typedef struct sAxWin_Element tElement;
-typedef struct sTab tTab;
typedef struct sApplication tApplication;
struct sAxWin_Element
{
- int Type;
+ enum eElementTypes Type;
+ // Element Tree
tElement *Parent;
tElement *FirstChild;
tElement *LastChild;
tElement *NextSibling;
+
+ // Application
+ tApplication *Owner; //!< Owning application
+ uint16_t ApplicationID; //!< Index into sApplication::EleIndex
// User modifiable attributes
short PaddingL, PaddingR;
uint32_t Flags;
- short FixedWith; // Fixed Long Size attribute (height)
- short FixedCross; // Fixed Cross Size attribute (width)
+ short FixedWith; //!< Fixed Long Size attribute (height)
+ short FixedCross; //!< Fixed Cross Size attribute (width)
char *Text;
// -- Attributes maitained by the element code
// Not touched by the user
- short MinWith; // Minimum long size
- short MinCross; // Minimum cross size
- void *Data;
+ short MinWith; //!< Minimum long size
+ short MinCross; //!< Minimum cross size
+ void *Data; //!< Per-type data
// -- Render Cache
short CachedX, CachedY;
{
tApplication *Next;
- void *Ident;
+ void *Ident; //!< Client Identifier
tMessages_Handle_Callback *SendMessage;
- char *Name;
- tElement MetaElement;
-
+ char *Name; //!< Application name
+
+ int MaxElementIndex; //!< Number of entries in \a EleIndex
+ tElement **EleIndex; //!< Array of pointers to elements owned by this application
+
+ tElement MetaElement; //!< Windows child off this
};
+// === FUNCTIONS ===
+
+// --- Render
+extern void WM_UpdateMinDims(tElement *Element);
+extern void WM_UpdateDimensions(tElement *Element, int Pass);
+extern void WM_UpdatePosition(tElement *Element);
+extern void WM_RenderWidget(tElement *Element);
+extern void WM_Update(void);
+
#endif
req.Size = 1 + (len+1)/4;
strcpy(req.Data, Name);
- msg = AxWin_int_SendAndWait(MSG_SREQ_ADDTAB, &req);
+ msg = AxWin_int_SendAndWait(MSG_SRSP_RETURN, &req);
ret = ((tAxWin_RetMsg*)msg->Data)->Bool;
free(msg);
tAxWin_Element *ret;
int len = strlen(Title);
- req.ID = MSG_SREQ_ADDTAB;
+ req.ID = MSG_SREQ_ADDWIN;
req.Size = 1 + (len+1)/4;
strcpy(req.Data, Title);
{
ELETYPE_NONE,
- ELETYPE_WINDOW,
+ ELETYPE_WINDOW, //!< Window root element
ELETYPE_BOX, //!< Content box (invisible in itself)
ELETYPE_TABBAR, //!< Tab Bar