Usermode/AxWin3 - Implementing more of the widget code
[tpg/acess2.git] / Usermode / Applications / axwin3_src / WM / renderer_widget.c
index fa284e8..505c5e3 100644 (file)
@@ -9,65 +9,25 @@
 #include <wm_renderer.h>
 #include <renderer_widget.h>
 #include <string.h>
+#include <wm_messages.h>
+#include <stdlib.h>
 
-// === TYPES ===
-typedef struct sWidgetWin      tWidgetWin;
-typedef struct sAxWin_Element  tElement;
-
-// === STRUCTURES ===
-struct sAxWin_Element
-{
-       enum eElementTypes      Type;
-
-       uint32_t        ID;     //!< Application provided ID number
-       tElement        *ListNext;      //!< Next element in bucket
-       
-       // Element Tree
-       tElement        *Parent;
-       tElement        *FirstChild;
-       tElement        *LastChild;
-       tElement        *NextSibling;
-       
-       // User modifiable attributes   
-       short   PaddingL, PaddingR;
-       short   PaddingT, PaddingB;
-       short   GapSize;
-       
-       uint32_t        Flags;
-       
-       short   FixedWith;      //!< Fixed lengthways 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;  //!< Per-type data
-       
-       // -- Render Cache
-       short   CachedX, CachedY;
-       short   CachedW, CachedH;
-       
-       char    DebugName[];
-};
-struct sWidgetWin
-{
-       tElement        RootElement;
-       
-        int    TableSize;      //!< Number of entries, anything over will wrap
-       tElement        *ElementTable[];        //!< Hash table essentially
-};
+#define DEFAULT_ELETABLE_SIZE  64
 
 // === PROTOTYPES ===
-tWindow        *Renderer_Widget_Create(int Width, int Height, int Flags);
+ int   Renderer_Widget_Init(void);
+tWindow        *Renderer_Widget_Create(int Flags);
 void   Renderer_Widget_Redraw(tWindow *Window);
-int    Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, void *Data);
+void   Widget_RenderWidget(tWindow *Window, tElement *Element);
+ int   Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, void *Data);
+void   Widget_UpdateDimensions(tElement *Element);
+void   Widget_UpdatePosition(tElement *Element);
+tElement       *Widget_GetElementById(tWidgetWin *Info, uint32_t ID);
+void   Widget_NewWidget(tWidgetWin *Info, size_t Len, tWidgetMsg_Create *Msg);
 
 // === GLOBALS ===
 tWMRenderer    gRenderer_Widget = {
-       .Name = "Classful",
+       .Name = "Widget",
        .CreateWindow = Renderer_Widget_Create,
        .Redraw = Renderer_Widget_Redraw,
        .HandleMessage = Renderer_Widget_HandleMessage
@@ -81,18 +41,51 @@ int Renderer_Widget_Init(void)
        return 0;
 }
 
-tWindow        *Renderer_Widget_Create(int Width, int Height, int Flags)
+tWindow        *Renderer_Widget_Create(int Flags)
 {
-       // TODO: Add info
-       return WM_CreateWindowStruct( sizeof(tWidgetWin) );
+       tWindow *ret;
+       tWidgetWin      *info;
+        int    eletable_size = DEFAULT_ELETABLE_SIZE;
+
+       // TODO: Use `Flags` as default element count?
+
+       ret = WM_CreateWindowStruct( sizeof(tWidgetWin) + sizeof(tElement*)*eletable_size );
+       info = ret->RendererInfo;
+       
+       info->TableSize = eletable_size;
+       info->RootElement.BackgroundColour = 0xCCCCCC;
+       
+       return ret;
 }
 
 void Renderer_Widget_Redraw(tWindow *Window)
 {
+       tWidgetWin      *info = Window->RendererInfo;
+       WM_Render_FillRect(Window, 0, 0, 0xFFF, 0xFFF, info->RootElement.BackgroundColour);
+
+       Widget_UpdateDimensions(&info->RootElement);
+       Widget_UpdatePosition(&info->RootElement);
+
+       Widget_RenderWidget(Window, &info->RootElement);
 }
 
 // --- Render / Resize ---
-void _UpdateDimensions(tElement *Ele)
+void Widget_RenderWidget(tWindow *Window, tElement *Element)
+{
+       tElement        *child;
+       
+       if( Element->Flags & ELEFLAG_NORENDER ) return ;
+       if( Element->Flags & ELEFLAG_INVISIBLE )        return ;
+       
+       Widget_Decorator_RenderWidget(Window, Element);
+       
+       for(child = Element->FirstChild; child; child = child->NextSibling)
+       {
+               Widget_RenderWidget(Window, child);
+       }
+}
+
+void Widget_UpdateDimensions(tElement *Element)
 {
        tElement        *child;
         int    nChildren = 0;
@@ -189,12 +182,15 @@ void _UpdateDimensions(tElement *Ele)
                child->CachedX = -1;
        
                // Recurse down so the child elements can be updated    
-               _UpdateDimensions(child);
+               Widget_UpdateDimensions(child);
        }
        
 }
 
-void _UpdatePosition(tElement *Element)
+/**
+ * \brief Update the position of child elements
+ */
+void Widget_UpdatePosition(tElement *Element)
 {
        tElement        *child;
         int    x, y;
@@ -236,7 +232,7 @@ void _UpdatePosition(tElement *Element)
                        child->CachedX = newX;
                        child->CachedY = newY;
                        // Update child's children positions
-                       WM_UpdatePosition(child);
+                       Widget_UpdatePosition(child);
                }
                
                // Increment
@@ -251,28 +247,25 @@ void _UpdatePosition(tElement *Element)
 
 
 // --- Helpers ---
-tElement *_GetElementById(tWidgetWin *Info, uint32_t ID)
+tElement *Widget_GetElementById(tWidgetWin *Info, uint32_t ID)
 {
        tElement        *ele;
-        int    num;
+
+       if(ID == -1)
+               return &Info->RootElement;
        
        if( ID < Info->TableSize )      return Info->ElementTable[ID];
 
-       while( ID >= Info->TableSize ) {
-               num ++;
-               ID -= Info->TableSize;
-       }
-
-       ele = Info->ElementTable[num];
-       while(num-- && ele)     ele = ele->ListNext;
+       ele = Info->ElementTable[ID % Info->TableSize];
+       while(ele && ele->ID != ID)     ele = ele->ListNext;
        return ele;
 }
 
 // --- Message Handlers ---
-void _NewWidget(tWidgetWin *Info, size_t Len, tWidgetMsg_Create *Msg)
+void Widget_NewWidget(tWidgetWin *Info, size_t Len, tWidgetMsg_Create *Msg)
 {
        const int       max_debugname_len = Len - sizeof(tWidgetMsg_Create);
-       tElement        *parent;        
+       tElement        *parent, *new;
 
        // Sanity check
        if( Len < sizeof(tWidgetMsg_Create) )
@@ -281,7 +274,62 @@ void _NewWidget(tWidgetWin *Info, size_t Len, tWidgetMsg_Create *Msg)
                return ;
        
        // Create
-       parent = _GetElementById(Info, Msg->Parent);
+       parent = Widget_GetElementById(Info, Msg->Parent);
+       if(!parent)
+       {
+               _SysDebug("Widget_NewWidget - Bad parent ID %i", Msg->Parent);
+               return ;
+       }
+
+       // Check if the ID is already in use
+       if( Widget_GetElementById(Info, Msg->NewID) )
+               return ;
+
+       // Create new element
+       new = calloc(sizeof(tElement), 1);
+       new->ID = Msg->NewID;
+       new->Type = Msg->Type;
+       new->Parent = parent;
+       new->Flags = Msg->Flags;
+       new->PaddingT = 2;
+       new->PaddingB = 2;
+       new->PaddingL = 2;
+       new->PaddingR = 2;
+       
+       // Add to parent's list
+       if(parent->LastChild)
+               parent->LastChild->NextSibling = new;
+       else
+               parent->FirstChild = new;
+       new->NextSibling = parent->LastChild;
+       parent->LastChild = new;
+
+       // Add to info
+       {
+               tElement        *ele, *prev = NULL;
+               for(ele = Info->ElementTable[new->ID % Info->TableSize]; ele; prev = ele, ele = ele->ListNext);
+               if(prev)
+                       prev->ListNext = new;
+               else
+                       Info->ElementTable[new->ID % Info->TableSize] = new;
+       }
+}
+
+void Widget_SetSize(tWidgetWin *Info, int Len, tWidgetMsg_SetSize *Msg)
+{
+       tElement        *ele;
+       
+       if( Len < sizeof(tWidgetMsg_SetSize) )
+               return ;
+       
+       ele = Widget_GetElementById(Info, Msg->WidgetID);
+       if(!ele)        return ;
+       
+       ele->FixedWith = Msg->Value;
+}
+
+void Widget_SetText(tWidgetWin *Info, int Len, tWidgetMsg_SetText *Msg)
+{
        
 }
 
@@ -290,14 +338,31 @@ int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, void *Data)
        tWidgetWin      *info = Target->RendererInfo;
        switch(Msg)
        {
+       case WNDMSG_RESIZE: {
+               struct sWndMsg_Resize   *msg = Data;
+               if(Len < sizeof(*msg))  return -1;              
+
+               info->RootElement.CachedW = msg->W;             
+               info->RootElement.CachedH = msg->H;
+               return 0; }
+
+       // New Widget
        case MSG_WIDGET_CREATE:
-               _NewWidget(info, Len, Data);
+               Widget_NewWidget(info, Len, Data);
+               return 0;
+       
+       // Set length
+       case MSG_WIDGET_SETSIZE:
+               Widget_SetSize(info, Len, Data);
+               return 0;
+       // Set text
+       case MSG_WIDGET_SETTEXT:
+               Widget_SetText(info, Len, Data);
                return 0;
+       
+       // 
        default:
-               return 1;       // Unhandled
+               return 1;       // Unhandled, pass to user
        }
 }
 
-
-
-

UCC git Repository :: git.ucc.asn.au