Usermode/Build - Updates to build system for crtbegin/crtend
[tpg/acess2.git] / Usermode / Applications / axwin3_src / WM / renderer_widget.c
index 92972d6..c4799e9 100644 (file)
@@ -31,8 +31,10 @@ 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_DispText_UpdateText(tElement *Element, const char *Text);
 void   Widget_Image_UpdateText(tElement *Element, const char *Text);
+ int   Widget_Button_MouseButton(tElement *Element, int X, int Y, int Button, int bPress);
+void   Widget_TextInput_Init(tElement *Element);
 
 // === GLOBALS ===
 tWMRenderer    gRenderer_Widget = {
@@ -42,19 +44,36 @@ tWMRenderer gRenderer_Widget = {
        .HandleMessage = Renderer_Widget_HandleMessage
 };
        
-// --- Element type flags
+// --- Element callbacks
 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
+
+       /**
+        * \name Input handlers
+        * \note Returns boolean unhandled
+        * \{
+        */     
+        int    (*MouseButton)(tElement *Ele, int X, int Y, int Button, int bPressed);
+        int    (*MouseMove)(tElement *Ele, int X, int Y);
+        int    (*KeyDown)(tElement *Ele, int KeySym, int Character);
+        int    (*KeyUp)(tElement *Ele, int KeySym);
+        int    (*KeyFire)(tElement *Ele, int KeySym, int Character);
+       /**
+        * \}
+        */
 }      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
+       {0},    // NULL
+       {0},    // Box
+       {.UpdateText = Widget_DispText_UpdateText},     // Text
+       {.UpdateText = Widget_Image_UpdateText},        // Image
+       {.MouseButton = Widget_Button_MouseButton},     // Button
+       {0},    // Spacer
+       {.Init = Widget_TextInput_Init},        // Text Box (Single Line)
 };
 const int      ciWM_NumWidgetTypes = sizeof(gaWM_WidgetTypes)/sizeof(gaWM_WidgetTypes[0]);
 
@@ -82,6 +101,7 @@ tWindow      *Renderer_Widget_Create(int Flags)
        info = ret->RendererInfo;
        
        info->TableSize = eletable_size;
+       info->RootElement.Window = ret;
        info->RootElement.ID = -1;
        info->RootElement.BackgroundColour = 0xCCCCCC;
        info->RootElement.Flags = Flags;
@@ -165,8 +185,8 @@ void Widget_UpdateDimensions(tElement *Element)
                dynWith /= nChildren - nFixed;
        }
        
-       _SysDebug("%i - nChildren = %i, nFixed = %i, dynWith = %i, fixedSize = %i",
-               Element->ID, nChildren, nFixed, dynWith, fixedSize);
+//     _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 )
@@ -239,8 +259,8 @@ void Widget_UpdatePosition(tElement *Element)
        
        if( Element->Flags & ELEFLAG_NORENDER ) return ;
 
-       _SysDebug("Widget_UpdatePosition: (Element=%p(%i Type=%i Flags=0x%x))",
-               Element, Element->ID, Element->Type, Element->Flags);
+//     _SysDebug("Widget_UpdatePosition: (Element=%p(%i Type=%i Flags=0x%x))",
+//             Element, Element->ID, Element->Type, Element->Flags);
        
        // Initialise
        x = Element->CachedX + Element->PaddingL;
@@ -271,7 +291,7 @@ void Widget_UpdatePosition(tElement *Element)
                                        - Element->PaddingT - Element->PaddingB;
                }
 
-               _SysDebug(" Widget_UpdatePosition[%i]: newX = %i, newY = %i", Element->ID, newX, newY);
+//             _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 )
@@ -337,6 +357,27 @@ void Widget_UpdateMinDims(tElement *Element)
        Widget_UpdateMinDims(Element->Parent);
 }
 
+tElement *Widget_GetElementByPos(tWidgetWin *Info, int X, int Y)
+{
+       tElement        *ret, *next, *ele;
+       
+       next = &Info->RootElement;
+       while(next)
+       {
+               ret = next;
+               next = NULL;
+               for(ele = ret->FirstChild; ele; ele = ele->NextSibling)
+               {
+                       if(ele->Flags & ELEFLAG_NORENDER)       continue;
+                       if(X < ele->CachedX)    continue;
+                       if(Y < ele->CachedY)    continue;
+                       if(X >= ele->CachedX + ele->CachedW)    continue;
+                       if(Y >= ele->CachedY + ele->CachedH)    continue;
+                       next = ele;
+               }
+       }
+       return ret;
+}
 
 // --- Helpers ---
 tElement *Widget_GetElementById(tWidgetWin *Info, uint32_t ID)
@@ -381,6 +422,7 @@ void Widget_NewWidget(tWidgetWin *Info, size_t Len, tWidgetMsg_Create *Msg)
 
        // Create new element
        new = calloc(sizeof(tElement), 1);
+       new->Window = parent->Window;
        new->ID = Msg->NewID;
        new->Type = Msg->Type;
        new->Parent = parent;
@@ -480,6 +522,51 @@ int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, void *Data)
 
                info->RootElement.CachedW = msg->W;             
                info->RootElement.CachedH = msg->H;
+               
+               // TODO: Update dimensions of all child elements?
+               
+               return 0; }
+
+       case WNDMSG_MOUSEMOVE: {
+               _SysDebug("TODO: Support widget mouse move events");
+               return 0; }
+
+       case WNDMSG_MOUSEBTN: {
+               struct sWndMsg_MouseButton      *msg = Data;
+               tWidgetMsg_MouseBtn     client_msg;
+               tElement        *ele;
+                int    x, y;
+                int    rv;
+               
+               if(Len < sizeof(*msg))  return -1;
+
+               x = msg->X; y = msg->Y;
+               client_msg.Button = msg->Button;
+               client_msg.bPressed = msg->bPressed;
+
+               ele = Widget_GetElementByPos(info, x, y);
+               // Send event to all elements from `ele` upwards
+               for( ; ele; ele = ele->Parent )
+               {
+                       if(ele->Type < ciWM_NumWidgetTypes && gaWM_WidgetTypes[ele->Type].MouseButton)
+                       {
+                               rv = gaWM_WidgetTypes[ele->Type].MouseButton(
+                                       ele,
+                                       x - ele->CachedX, y - ele->CachedY,
+                                       msg->Button, msg->bPressed
+                                       );
+                               // Allow a type to trap the input from going any higher
+                               if(rv == 0)     break;
+                       }
+                       else
+                       {
+                               // Pass to user
+                               client_msg.X = x - ele->CachedX;
+                               client_msg.Y = y - ele->CachedY;
+                               client_msg.WidgetID = ele->ID;
+                               WM_SendMessage(Target, Target, MSG_WIDGET_MOUSEBTN, sizeof(client_msg), &client_msg);
+                       }
+               }
                return 0; }
 
        // New Widget
@@ -512,8 +599,15 @@ int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, void *Data)
        }
 }
 
+void Widget_Fire(tElement *Element)
+{
+       tWidgetMsg_Fire msg;
+       msg.WidgetID = Element->ID;
+       WM_SendMessage(Element->Window, Element->Window, MSG_WIDGET_FIRE, sizeof(msg), &msg);
+}
+
 // --- Type Helpers
-void Widget_TextBox_UpdateText(tElement *Element, const char *Text)
+void Widget_DispText_UpdateText(tElement *Element, const char *Text)
 {
         int    w=0, h=0;
 
@@ -559,3 +653,28 @@ void Widget_Image_UpdateText(tElement *Element, const char *Text)
        // NOTE: Doesn't update Element->Text because it's useless
 }
 
+int Widget_Button_MouseButton(tElement *Element, int X, int Y, int Button, int bPress)
+{
+       _SysDebug("Ele %i - Button %i %s",
+               Element->ID, Button,
+               (bPress ? "pressed" : "released")
+               );
+       if(!bPress)     Widget_Fire(Element);
+       return 0;       // Handled
+}
+
+void Widget_TextInput_Init(tElement *Element)
+{
+        int    h;
+
+       // TODO: Select font correctly  
+       WM_Render_GetTextDims(NULL, "jJ", NULL, &h);
+       
+       if( Element->Parent && (Element->Parent->Flags & ELEFLAG_VERTICAL) )
+               Element->MinWith = h;
+       else
+               Element->MinCross = h;
+
+       // No need to explicitly update parent min dims, as the AddElement routine does that    
+}
+

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