Usermode/AxWin3 - Cleaning up bugs, adding image loading and text printing
[tpg/acess2.git] / Usermode / Applications / axwin3_src / WM / renderer_widget.c
index 505c5e3..92972d6 100644 (file)
@@ -11,6 +11,7 @@
 #include <string.h>
 #include <wm_messages.h>
 #include <stdlib.h>
+#include "include/image.h"
 
 #define DEFAULT_ELETABLE_SIZE  64
 
  int   Renderer_Widget_Init(void);
 tWindow        *Renderer_Widget_Create(int Flags);
 void   Renderer_Widget_Redraw(tWindow *Window);
+
 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);
+// --- Messages
 tElement       *Widget_GetElementById(tWidgetWin *Info, uint32_t ID);
 void   Widget_NewWidget(tWidgetWin *Info, size_t Len, tWidgetMsg_Create *Msg);
+void   Widget_SetFlags(tWidgetWin *Info, int Len, tWidgetMsg_SetFlags *Msg);
+void   Widget_SetSize(tWidgetWin *Info, int Len, tWidgetMsg_SetSize *Msg);
+void   Widget_SetText(tWidgetWin *Info, int Len, tWidgetMsg_SetText *Msg);
+ int   Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, void *Data);
+// --- Type helpers
+void   Widget_TextBox_UpdateText(tElement *Element, const char *Text);
+void   Widget_Image_UpdateText(tElement *Element, const char *Text);
 
 // === GLOBALS ===
 tWMRenderer    gRenderer_Widget = {
@@ -32,6 +41,22 @@ tWMRenderer  gRenderer_Widget = {
        .Redraw = Renderer_Widget_Redraw,
        .HandleMessage = Renderer_Widget_HandleMessage
 };
+       
+// --- Element type flags
+struct {
+       void    (*Init)(tElement *Ele);
+       void    (*Delete)(tElement *Ele);
+       void    (*UpdateFlags)(tElement *Ele);
+       void    (*UpdateSize)(tElement *Ele);
+       void    (*UpdateText)(tElement *Ele, const char *Text); // This should update Ele->Text
+}      gaWM_WidgetTypes[NUM_ELETYPES] = {
+       {NULL, NULL, NULL, NULL, NULL}, // NULL
+       {NULL, NULL, NULL, NULL, NULL}, // Box
+       {NULL, NULL, NULL, NULL, Widget_TextBox_UpdateText},    // Text
+       {NULL, NULL, NULL, NULL, Widget_Image_UpdateText},      // Image
+       {NULL, NULL, NULL, NULL, NULL}  // Button
+};
+const int      ciWM_NumWidgetTypes = sizeof(gaWM_WidgetTypes)/sizeof(gaWM_WidgetTypes[0]);
 
 // === CODE ===
 int Renderer_Widget_Init(void)
@@ -47,13 +72,19 @@ tWindow     *Renderer_Widget_Create(int Flags)
        tWidgetWin      *info;
         int    eletable_size = DEFAULT_ELETABLE_SIZE;
 
+       _SysDebug("Renderer_Widget_Create: (Flags = 0x%x)", Flags);
+
        // TODO: Use `Flags` as default element count?
+       // - Actaully, it's taken by the root ele flags
+       // - Use the upper bits?
 
        ret = WM_CreateWindowStruct( sizeof(tWidgetWin) + sizeof(tElement*)*eletable_size );
        info = ret->RendererInfo;
        
        info->TableSize = eletable_size;
+       info->RootElement.ID = -1;
        info->RootElement.BackgroundColour = 0xCCCCCC;
+       info->RootElement.Flags = Flags;
        
        return ret;
 }
@@ -110,6 +141,11 @@ void Widget_UpdateDimensions(tElement *Element)
                        nFixed ++;
                        fixedSize += child->FixedWith;
                }
+               else if( child->Flags & ELEFLAG_NOSTRETCH )
+               {
+                       nFixed ++;
+                       fixedSize += child->MinWith;
+               }
                
                if( child->FixedCross && maxCross < child->FixedCross )
                        maxCross = child->FixedCross;
@@ -117,7 +153,7 @@ void Widget_UpdateDimensions(tElement *Element)
                        maxCross = child->MinCross;
                nChildren ++;
        }
-       
+
        // Get the dynamic with size from the unused space in the element
        if( nChildren > nFixed ) {
                if( Element->Flags & ELEFLAG_VERTICAL )
@@ -129,6 +165,9 @@ void Widget_UpdateDimensions(tElement *Element)
                dynWith /= nChildren - nFixed;
        }
        
+       _SysDebug("%i - nChildren = %i, nFixed = %i, dynWith = %i, fixedSize = %i",
+               Element->ID, nChildren, nFixed, dynWith, fixedSize);
+
        // Get the cross size
        if( Element->Flags & ELEFLAG_VERTICAL )
                fullCross = Element->CachedW - Element->PaddingL - Element->PaddingR;
@@ -154,13 +193,16 @@ void Widget_UpdateDimensions(tElement *Element)
                        cross = fullCross;
                
                // --- With Size ---
-               if( child->FixedWith)
+               if( child->FixedWith )
                        with = child->FixedWith;
                else if( child->Flags & ELEFLAG_NOSTRETCH )
                        with = child->MinWith;
                else
                        with = dynWith;
-               
+       
+
+               if(with < child->MinWith)       with = child->MinWith;
+               if(cross < child->MinCross)     cross = child->MinCross;
                
                // Update the dimensions if they have changed
                if( Element->Flags & ELEFLAG_VERTICAL ) {
@@ -196,6 +238,9 @@ void Widget_UpdatePosition(tElement *Element)
         int    x, y;
        
        if( Element->Flags & ELEFLAG_NORENDER ) return ;
+
+       _SysDebug("Widget_UpdatePosition: (Element=%p(%i Type=%i Flags=0x%x))",
+               Element, Element->ID, Element->Type, Element->Flags);
        
        // Initialise
        x = Element->CachedX + Element->PaddingL;
@@ -226,6 +271,8 @@ void Widget_UpdatePosition(tElement *Element)
                                        - Element->PaddingT - Element->PaddingB;
                }
 
+               _SysDebug(" Widget_UpdatePosition[%i]: newX = %i, newY = %i", Element->ID, newX, newY);
+
                // Check for changes, and don't update if there was no change
                if( newX != child->CachedX || newY != child->CachedY )
                {
@@ -245,14 +292,58 @@ void Widget_UpdatePosition(tElement *Element)
        }
 }
 
+/**
+ * \brief Update the minimum dimensions of the element
+ * \note Called after a child's minimum dimensions have changed
+ */
+void Widget_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
+       Widget_UpdateMinDims(Element->Parent);
+}
+
 
 // --- Helpers ---
 tElement *Widget_GetElementById(tWidgetWin *Info, uint32_t ID)
 {
        tElement        *ele;
 
-       if(ID == -1)
-               return &Info->RootElement;
+       if( ID == -1 )  return &Info->RootElement;
        
        if( ID < Info->TableSize )      return Info->ElementTable[ID];
 
@@ -273,6 +364,9 @@ void Widget_NewWidget(tWidgetWin *Info, size_t Len, tWidgetMsg_Create *Msg)
        if( strnlen(Msg->DebugName, max_debugname_len) == max_debugname_len )
                return ;
        
+       _SysDebug("Widget_NewWidget (%i %i Type %i Flags 0x%x)",
+               Msg->Parent, Msg->NewID, Msg->Type, Msg->Flags);
+       
        // Create
        parent = Widget_GetElementById(Info, Msg->Parent);
        if(!parent)
@@ -295,13 +389,16 @@ void Widget_NewWidget(tWidgetWin *Info, size_t Len, tWidgetMsg_Create *Msg)
        new->PaddingB = 2;
        new->PaddingL = 2;
        new->PaddingR = 2;
+       new->CachedX = -1;
+       
+       if( new->Type < ciWM_NumWidgetTypes && gaWM_WidgetTypes[new->Type].Init )
+               gaWM_WidgetTypes[new->Type].Init(new);
        
        // 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
@@ -313,6 +410,26 @@ void Widget_NewWidget(tWidgetWin *Info, size_t Len, tWidgetMsg_Create *Msg)
                else
                        Info->ElementTable[new->ID % Info->TableSize] = new;
        }
+
+       Widget_UpdateMinDims(parent);
+}
+
+void Widget_SetFlags(tWidgetWin *Info, int Len, tWidgetMsg_SetFlags *Msg)
+{
+       tElement        *ele;
+       
+       if( Len < sizeof(tWidgetMsg_SetFlags) )
+               return ;
+
+       _SysDebug("Widget_SetFlags: (%i 0x%x 0x%x)", Msg->WidgetID, Msg->Value, Msg->Mask);
+       
+       ele = Widget_GetElementById(Info, Msg->WidgetID);
+       if(!ele)        return;
+
+       Msg->Value &= Msg->Mask;
+       
+       ele->Flags &= ~Msg->Mask;
+       ele->Flags |= Msg->Value;
 }
 
 void Widget_SetSize(tWidgetWin *Info, int Len, tWidgetMsg_SetSize *Msg)
@@ -330,7 +447,26 @@ void Widget_SetSize(tWidgetWin *Info, int Len, tWidgetMsg_SetSize *Msg)
 
 void Widget_SetText(tWidgetWin *Info, int Len, tWidgetMsg_SetText *Msg)
 {
+       tElement        *ele;
        
+       if( Len < sizeof(tWidgetMsg_SetText) + 1 )
+               return ;
+       if( Msg->Text[Len - sizeof(tWidgetMsg_SetText) - 1] != '\0' )
+               return ;
+
+       ele = Widget_GetElementById(Info, Msg->WidgetID);
+       if(!ele)        return ;
+
+
+       if( ele->Type < ciWM_NumWidgetTypes && gaWM_WidgetTypes[ele->Type].UpdateText )
+       {
+               gaWM_WidgetTypes[ele->Type].UpdateText( ele, Msg->Text );
+       }
+//     else
+//     {
+//             if(ele->Text)   free(ele->Text);
+//             ele->Text = strdup(Msg->Text);
+//     }
 }
 
 int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, void *Data)
@@ -350,11 +486,21 @@ int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, void *Data)
        case MSG_WIDGET_CREATE:
                Widget_NewWidget(info, Len, Data);
                return 0;
+
+       case MSG_WIDGET_DELETE:
+               _SysDebug("TODO: Implement MSG_WIDGET_DELETE");
+               return 0;
+
+       // Set Flags
+       case MSG_WIDGET_SETFLAGS:
+               Widget_SetFlags(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);
@@ -366,3 +512,50 @@ int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, void *Data)
        }
 }
 
+// --- Type Helpers
+void Widget_TextBox_UpdateText(tElement *Element, const char *Text)
+{
+        int    w=0, h=0;
+
+       if(Element->Text)       free(Element->Text);
+       Element->Text = strdup(Text);
+
+       WM_Render_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;
+       }
+
+       Widget_UpdateMinDims(Element->Parent);
+}
+
+void Widget_Image_UpdateText(tElement *Element, const char *Text)
+{
+       if(Element->Data)       free(Element->Data);
+       Element->Data = Image_Load( Text );
+       if(!Element->Data) {
+//             Element->Flags &= ~ELEFLAG_FIXEDSIZE;
+               return ;
+       }
+       
+       Element->CachedW = ((tImage*)Element->Data)->Width;
+       Element->CachedH = ((tImage*)Element->Data)->Height;
+       
+       if(Element->Parent && (Element->Parent->Flags & ELEFLAG_VERTICAL) ) {
+               Element->MinCross = ((tImage*)Element->Data)->Width;
+               Element->MinWith = ((tImage*)Element->Data)->Height;
+       }
+       else {
+               Element->MinWith = ((tImage*)Element->Data)->Width;
+               Element->MinCross = ((tImage*)Element->Data)->Height;
+       }
+
+       Widget_UpdateMinDims(Element->Parent);
+       
+       // NOTE: Doesn't update Element->Text because it's useless
+}
+

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