Merge branch 'master' of git://github.com/thepowersgang/acess2
[tpg/acess2.git] / Usermode / Applications / axwin3_src / WM / renderers / widget.c
index 7668cbd..fd757af 100644 (file)
 #define DEFAULT_ELETABLE_SIZE  64
 #define BORDER_EVERYTHING      0
 
+// === IMPORTS ===
+extern tWidgetDef      _widget_typedef_ELETYPE_IMAGE;
+extern tWidgetDef      _widget_typedef_ELETYPE_BUTTON;
+extern tWidgetDef      _widget_typedef_ELETYPE_TEXT;
+extern tWidgetDef      _widget_typedef_ELETYPE_TEXTINPUT;
+extern tWidgetDef      _widget_typedef_ELETYPE_SPACER;
+extern tWidgetDef      _widget_typedef_ELETYPE_SUBWIN;
+
 // === PROTOTYPES ===
  int   Renderer_Widget_Init(void);
 tWindow        *Renderer_Widget_Create(int Flags);
@@ -26,10 +34,15 @@ 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, const tWidgetMsg_Create *Msg);
-void   Widget_SetFlags(tWidgetWin *Info, int Len, const tWidgetMsg_SetFlags *Msg);
-void   Widget_SetSize(tWidgetWin *Info, int Len, const tWidgetMsg_SetSize *Msg);
-void   Widget_SetText(tWidgetWin *Info, int Len, const tWidgetMsg_SetText *Msg);
+ int   Widget_IPC_Create(tWindow *Win, size_t Len, const void *Data);
+ int   Widget_IPC_NewWidgetSubwin(tWindow *Win, size_t Len, const void *Data);
+// int Widget_IPC_Delete(tWindow *Win, size_t Len, const void *Data);
+ int   Widget_IPC_SetFocus(tWindow *Win, size_t Len, const void *Data);
+ int   Widget_IPC_SetFlags(tWindow *Win, size_t Len, const void *Data);
+ int   Widget_IPC_SetSize(tWindow *Win, size_t Len, const void *Data);
+ int   Widget_IPC_SetText(tWindow *Win, size_t Len, const void *Data);
+ int   Widget_IPC_GetText(tWindow *Win, size_t Len, const void *Data);
+// int Widget_IPC_SetColour(tWindow *Win, size_t Len, const void *Data);
  int   Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data);
 
 // === GLOBALS ===
@@ -37,21 +50,37 @@ tWMRenderer gRenderer_Widget = {
        .Name = "Widget",
        .CreateWindow = Renderer_Widget_Create,
        .Redraw = Renderer_Widget_Redraw,
-       .HandleMessage = Renderer_Widget_HandleMessage
+       .HandleMessage = Renderer_Widget_HandleMessage,
+       .nIPCHandlers = N_IPC_WIDGET,
+       .IPCHandlers = {
+               [IPC_WIDGET_CREATE] = Widget_IPC_Create,
+               [IPC_WIDGET_CREATESUBWIN] = Widget_IPC_NewWidgetSubwin,
+               [IPC_WIDGET_SETFOCUS] = Widget_IPC_SetFocus,
+               [IPC_WIDGET_SETFLAGS] = Widget_IPC_SetFlags,
+               [IPC_WIDGET_SETSIZE] = Widget_IPC_SetSize,
+               [IPC_WIDGET_SETTEXT] = Widget_IPC_SetText,
+               [IPC_WIDGET_GETTEXT] = Widget_IPC_GetText,
+       }
 };
        
 // --- Element callbacks
-tWidgetDef     *gaWM_WidgetTypes[NUM_ELETYPES];
+tWidgetDef     *gaWM_WidgetTypes[NUM_ELETYPES] = {
+       [ELETYPE_IMAGE]     = &_widget_typedef_ELETYPE_IMAGE,
+       [ELETYPE_BUTTON]    = &_widget_typedef_ELETYPE_BUTTON,
+       [ELETYPE_TEXT]      = &_widget_typedef_ELETYPE_TEXT,
+       [ELETYPE_TEXTINPUT] = &_widget_typedef_ELETYPE_TEXTINPUT,
+       [ELETYPE_SPACER]    = &_widget_typedef_ELETYPE_SPACER,
+       [ELETYPE_SUBWIN]    = &_widget_typedef_ELETYPE_SUBWIN,
+       };
 const int      ciWM_NumWidgetTypes = sizeof(gaWM_WidgetTypes)/sizeof(gaWM_WidgetTypes[0]);
 tWidgetDef     gWidget_NullWidgetDef;
 
 // === CODE ===
 int Renderer_Widget_Init(void)
 {
-        int    i;
        WM_RegisterRenderer(&gRenderer_Widget); 
 
-       for(i = 0; i < ciWM_NumWidgetTypes; i ++)
+       for(int i = 0; i < ciWM_NumWidgetTypes; i ++)
        {
                if(gaWM_WidgetTypes[i] != NULL) continue;
                
@@ -79,6 +108,7 @@ void Widget_int_SetTypeDef(int Type, tWidgetDef *Ptr)
        }
        
        gaWM_WidgetTypes[Type] = Ptr;
+       _SysDebug("Registered widget type %i '%s'", Type, Ptr->Name);
 }
 
 tWindow        *Renderer_Widget_Create(int Flags)
@@ -87,7 +117,7 @@ tWindow      *Renderer_Widget_Create(int Flags)
        tWidgetWin      *info;
         int    eletable_size = DEFAULT_ELETABLE_SIZE;
 
-       _SysDebug("Renderer_Widget_Create: (Flags = 0x%x)", Flags);
+       //_SysDebug("Renderer_Widget_Create: (Flags = 0x%x)", Flags);
 
        // TODO: Use `Flags` as default element count?
        // - Actaully, it's taken by the root ele flags
@@ -214,14 +244,14 @@ void Widget_UpdateDimensions(tElement *Element)
        else
                fullCross = Element->CachedH - Element->PaddingT - Element->PaddingB;
 
-       _SysDebug("%i (p=%i) - WxH=%ix%i",
-               Element->ID, (Element->Parent ? Element->Parent->ID : -1),
-               Element->CachedW, Element->CachedH
-               );
-       _SysDebug("  %s dynWith = %i, fullCross = %i",
-               (Element->Flags & ELEFLAG_VERTICAL ? "Vert" : "Horiz"),
-               dynWith, fullCross
-               );
+       //_SysDebug("%i (p=%i) - WxH=%ix%i",
+       //      Element->ID, (Element->Parent ? Element->Parent->ID : -1),
+       //      Element->CachedW, Element->CachedH
+       //      );
+       //_SysDebug("  %s dynWith = %i, fullCross = %i",
+       //      (Element->Flags & ELEFLAG_VERTICAL ? "Vert" : "Horiz"),
+       //      dynWith, fullCross
+       //      );
        
        // Pass 2 - Set sizes and recurse
        for( child = Element->FirstChild; child; child = child->NextSibling )
@@ -234,7 +264,7 @@ void Widget_UpdateDimensions(tElement *Element)
                if( child->Flags & ELEFLAG_ABSOLUTEPOS )        continue ;
                
                // --- Width ---
-               if( child->Flags & ELEFLAG_NOEXPAND )
+               if( child->Flags & (bVertical ? ELEFLAG_NOEXPAND : ELEFLAG_NOSTRETCH) )
                        w = child->MinW;
                else if( bVertical )
                        w = child->FixedCross ? child->FixedCross : fullCross;
@@ -242,7 +272,7 @@ void Widget_UpdateDimensions(tElement *Element)
                        w = child->FixedWith ? child->FixedWith : dynWith;
        
                // --- Height ---
-               if( child->Flags & ELEFLAG_NOSTRETCH )
+               if( child->Flags & (bVertical ? ELEFLAG_NOSTRETCH : ELEFLAG_NOEXPAND) )
                        h = child->MinH;
                else if( bVertical )
                        h = child->FixedWith ? child->FixedWith : dynWith;
@@ -274,7 +304,6 @@ void Widget_UpdateDimensions(tElement *Element)
  */
 void Widget_UpdatePosition(tElement *Element)
 {
-       tElement        *child;
         int    x, y;
        
        if( Element->Flags & ELEFLAG_NORENDER ) return ;
@@ -291,7 +320,7 @@ void Widget_UpdatePosition(tElement *Element)
        y = Element->CachedY + Element->PaddingT;
        
        // Update each child
-       for(child = Element->FirstChild; child; child = child->NextSibling)
+       for(tElement *child = Element->FirstChild; child; child = child->NextSibling)
        {
                 int    newX, newY;
                // Ignore elements that will not be rendered
@@ -342,7 +371,6 @@ void Widget_UpdatePosition(tElement *Element)
  */
 void Widget_UpdateMinDims(tElement *Element)
 {
-       tElement        *child;
         int    minW, minH;
         int    nChildren;
        
@@ -352,7 +380,7 @@ void Widget_UpdateMinDims(tElement *Element)
        minH = 0;
        nChildren = 0;
        
-       for(child = Element->FirstChild; child; child = child->NextSibling)
+       for( tElement *child = Element->FirstChild; child; child = child->NextSibling )
        {
                 int    cross;
                
@@ -389,14 +417,13 @@ void Widget_UpdateMinDims(tElement *Element)
 
 tElement *Widget_GetElementByPos(tWidgetWin *Info, int X, int Y)
 {
-       tElement        *ret, *next, *ele;
-       
-       next = &Info->RootElement;
-       do
-       {
+       tElement *ret;
+       tElement *next = &Info->RootElement;
+       // Scan down tree
+       do {
                ret = next;
                next = NULL;
-               for(ele = ret->FirstChild; ele; ele = ele->NextSibling)
+               for(tElement *ele = ret->FirstChild; ele; ele = ele->NextSibling)
                {
                        if(ele->Flags & ELEFLAG_NORENDER)       continue;
                        if(X < ele->CachedX)    continue;
@@ -423,17 +450,74 @@ tElement *Widget_GetElementById(tWidgetWin *Info, uint32_t ID)
        return ele;
 }
 
+tElement *Widget_int_Create(tWidgetWin *Info, tElement *Parent, int ID, int Type, int Flags)
+{
+       if( Widget_GetElementById(Info, ID) )
+               return NULL;
+       if( Type >= NUM_ELETYPES ) {
+               return NULL;
+       }
+       
+       _SysDebug("Widget Create #%i '%s' 0x%x",
+               ID, gaWM_WidgetTypes[Type]->Name, Flags);
+
+       // Create new element
+       tElement *new = calloc(sizeof(tElement), 1);
+       new->Window = Parent->Window;
+       new->ID = ID;
+       new->Type = Type;
+       new->Parent = Parent;
+       new->Flags = Flags;
+       new->PaddingT = 2;
+       new->PaddingB = 2;
+       new->PaddingL = 2;
+       new->PaddingR = 2;
+       new->CachedX = -1;
+
+       if( gaWM_WidgetTypes[Type]->Init )
+               gaWM_WidgetTypes[Type]->Init(new);
+       
+       // Add to parent's list
+       if(Parent->LastChild)
+               Parent->LastChild->NextSibling = new;
+       else
+               Parent->FirstChild = new;
+       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;
+       }
+       
+       return new;
+}
+
+void Widget_SetFocus(tWidgetWin *Info, tElement *Ele)
+{
+       // TODO: Callbacks
+
+       Info->FocusedElement = Ele;
+}
+
+
 // --- Message Handlers ---
-void Widget_NewWidget(tWidgetWin *Info, size_t Len, const tWidgetMsg_Create *Msg)
+int Widget_IPC_Create(tWindow *Win, size_t Len, const void *Data)
 {
-       const int       max_debugname_len = Len - sizeof(tWidgetMsg_Create);
-       tElement        *parent, *new;
+       tWidgetWin      *Info = Win->RendererInfo;
+       const tWidgetIPC_Create *Msg = Data;
+       const int       max_debugname_len = Len - sizeof(*Msg);
+       tElement        *parent;
 
        // Sanity check
        if( Len < sizeof(*Msg) )
-               return ;
+               return -1;
        if( strnlen(Msg->DebugName, max_debugname_len) == max_debugname_len )
-               return ;
+               return -1;
        
        _SysDebug("Widget_NewWidget (%i %i Type %i Flags 0x%x)",
                Msg->Parent, Msg->NewID, Msg->Type, Msg->Flags);
@@ -441,7 +525,7 @@ void Widget_NewWidget(tWidgetWin *Info, size_t Len, const tWidgetMsg_Create *Msg
        if(Msg->Type >= ciWM_NumWidgetTypes)
        {
                _SysDebug("Widget_NewWidget - Bad widget type %i", Msg->Type);
-               return ;
+               return 1;
        }
 
        // Create
@@ -449,100 +533,113 @@ void Widget_NewWidget(tWidgetWin *Info, size_t Len, const tWidgetMsg_Create *Msg
        if(!parent)
        {
                _SysDebug("Widget_NewWidget - Bad parent ID %i", Msg->Parent);
-               return ;
+               return 1;
        }
 
-       // Check if the ID is already in use
-       if( Widget_GetElementById(Info, Msg->NewID) )
-               return ;
+       Widget_int_Create(Info, parent, Msg->NewID, Msg->Type, Msg->Flags);
 
-       // Create new element
-       new = calloc(sizeof(tElement), 1);
-       new->Window = parent->Window;
-       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;
-       new->CachedX = -1;
-       
-       if( 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;
-       parent->LastChild = new;
+       Widget_UpdateMinDims(parent);
+       return 0;
+}
 
-       // 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;
-       }
+int Widget_IPC_NewWidgetSubwin(tWindow *Win, size_t Len, const void *Data)
+{
+       tWidgetWin      *Info = Win->RendererInfo;
+       const tWidgetIPC_CreateSubWin   *Msg = Data;
+       const int       max_debugname_len = Len - sizeof(*Msg);
+       tElement        *parent, *new;
 
+       // Sanity check
+       if( Len < sizeof(*Msg) )
+               return -1;
+       if( strnlen(Msg->DebugName, max_debugname_len) == max_debugname_len )
+               return -1;
+
+       _SysDebug("Widget_NewWidgetSubwin(%i %i  Type %i Flags 0x%x Subwin %i)",
+               Msg->Parent, Msg->NewID, Msg->Type, Msg->Flags, Msg->WindowHandle);
+       
+       parent = Widget_GetElementById(Info, Msg->Parent);
+       if(!parent)     return 1;
+       if( Widget_GetElementById(Info, Msg->NewID) )   return 1;
+       
+       new = Widget_int_Create(Info, parent, Msg->NewID, Msg->Type, Msg->Flags);
+       new->Data = WM_GetWindowByID(parent->Window, Msg->WindowHandle);
        Widget_UpdateMinDims(parent);
+       return 0;
 }
 
-void Widget_SetFocus(tWidgetWin *Info, tElement *Ele)
+// TODO: Widget_IPC_Delete
+
+int Widget_IPC_SetFocus(tWindow *Win, size_t Len, const void *Data)
 {
-       // TODO: Callbacks
+       tWidgetWin      *info = Win->RendererInfo;
+       tElement        *ele;
+       const tWidgetIPC_SetFocus       *msg = Data;
+       if(Len < sizeof(*msg))  return -1;
 
-       Info->FocusedElement = Ele;
+       _SysDebug("Widget_SetFocus(%i)", msg->WidgetID);
+       
+       ele = Widget_GetElementById(info, msg->WidgetID);
+       Widget_SetFocus(info, ele);
+       return 0;
 }
 
-void Widget_SetFlags(tWidgetWin *Info, int Len, const tWidgetMsg_SetFlags *Msg)
+int Widget_IPC_SetFlags(tWindow *Win, size_t Len, const void *Data)
 {
+       tWidgetWin *Info = Win->RendererInfo;
+       const tWidgetIPC_SetFlags       *Msg = Data;
        tElement        *ele;
        
        if( Len < sizeof(*Msg) )
-               return ;
+               return -1;
 
        _SysDebug("Widget_SetFlags: (%i 0x%x 0x%x)", Msg->WidgetID, Msg->Value, Msg->Mask);
        
        ele = Widget_GetElementById(Info, Msg->WidgetID);
-       if(!ele)        return;
+       if(!ele)        return 1;
 
        ele->Flags &= ~Msg->Mask;
        ele->Flags |= Msg->Value & Msg->Mask;
+       
+       return 0;
 }
 
-void Widget_SetSize(tWidgetWin *Info, int Len, const tWidgetMsg_SetSize *Msg)
+int Widget_IPC_SetSize(tWindow *Win, size_t Len, const void *Data)
 {
+       tWidgetWin      *Info = Win->RendererInfo;
+       const tWidgetIPC_SetSize        *Msg = Data;
        tElement        *ele;
        
        if( Len < sizeof(*Msg) )
-               return ;
+               return -1;
+
+       _SysDebug("Widget_SetSize(%i, %i)", Msg->WidgetID, Msg->Value);
        
        ele = Widget_GetElementById(Info, Msg->WidgetID);
-       if(!ele)        return ;
+       if(!ele)        return 1;
        
        ele->FixedWith = Msg->Value;
+       return 0;
 }
 
-void Widget_SetText(tWidgetWin *Info, int Len, const tWidgetMsg_SetText *Msg)
+int Widget_IPC_SetText(tWindow *Win, size_t Len, const void *Data)
 {
+       tWidgetWin      *Info = Win->RendererInfo;
+       const tWidgetIPC_SetText        *Msg = Data;
        tElement        *ele;
        
        if( Len < sizeof(*Msg) + 1 )
-               return ;
+               return -1;
        if( Msg->Text[Len - sizeof(*Msg) - 1] != '\0' )
-               return ;
+               return -1;
 
+       _SysDebug("Widget_SetText(%i, '%.30s')", Msg->WidgetID, Msg->Text);
        ele = Widget_GetElementById(Info, Msg->WidgetID);
-       if(!ele)        return ;
-
+       if(!ele)        return 1;
 
        if( gaWM_WidgetTypes[ele->Type]->UpdateText )
        {
+               _SysDebug(" - calling handler");
                gaWM_WidgetTypes[ele->Type]->UpdateText( ele, Msg->Text );
        }
 //     else
@@ -550,6 +647,35 @@ void Widget_SetText(tWidgetWin *Info, int Len, const tWidgetMsg_SetText *Msg)
 //             if(ele->Text)   free(ele->Text);
 //             ele->Text = strdup(Msg->Text);
 //     }
+       return 0;
+}
+
+int Widget_IPC_GetText(tWindow *Win, size_t Len, const void *Data)
+{
+       tWidgetWin      *Info = Win->RendererInfo;
+       const tWidgetIPC_SetText        *Msg = Data;
+       if( Len < sizeof(*Msg) )
+               return -1;
+       
+       const char      *text = NULL;
+       tElement *ele = Widget_GetElementById(Info, Msg->WidgetID);
+       if(ele)
+               text = ele->Text;
+       
+       char    buf[sizeof(tWidgetIPC_SetText) + strlen(text?text:"") + 1];
+       tWidgetIPC_SetText      *omsg = (void*)buf;
+       
+       if( text ) {
+               omsg->WidgetID = Msg->WidgetID;
+               strcpy(omsg->Text, text);
+       }
+       else {
+               omsg->WidgetID = -1;
+               omsg->Text[0] = 0;
+       }
+       
+       WM_SendIPCReply(Win, IPC_WIDGET_GETTEXT, sizeof(buf), buf);
+       return 0;
 }
 
 int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data)
@@ -657,41 +783,6 @@ int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, const void
                }
                return 0; }
 
-       // New Widget
-       case MSG_WIDGET_CREATE:
-               Widget_NewWidget(info, Len, Data);
-               return 0;
-
-       // Delete a widget
-       case MSG_WIDGET_DELETE:
-               _SysDebug("TODO: Implement MSG_WIDGET_DELETE");
-               return 0;
-
-       // Set focused widget
-       case MSG_WIDGET_SETFOCUS: {
-               tElement        *ele;
-               const tWidgetMsg_SetFocus       *msg = Data;
-               if(Len < sizeof(*msg))  return -1;
-               
-               ele = Widget_GetElementById(info, msg->WidgetID);
-               Widget_SetFocus(info, ele);
-               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);
-               return 0;
-       
        // 
        default:
                return 1;       // Unhandled, pass to user
@@ -702,6 +793,7 @@ void Widget_Fire(tElement *Element)
 {
        tWidgetMsg_Fire msg;
        msg.WidgetID = Element->ID;
+       _SysDebug("Widget_Fire: Fire on %p %i", Element->Window, Element->ID);
        WM_SendMessage(Element->Window, Element->Window, MSG_WIDGET_FIRE, sizeof(msg), &msg);
 }
 

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