}
gaWM_WidgetTypes[Type] = Ptr;
- _SysDebug("Registered type %i to %p", Type, Ptr);
}
tWindow *Renderer_Widget_Create(int Flags)
info = ret->RendererInfo;
info->TableSize = eletable_size;
+ info->FocusedElement = &info->RootElement;
info->RootElement.Window = ret;
info->RootElement.ID = -1;
info->RootElement.BackgroundColour = 0xCCCCCC;
tElement *ret, *next, *ele;
next = &Info->RootElement;
- while(next)
+ do
{
ret = next;
next = NULL;
if(Y >= ele->CachedY + ele->CachedH) continue;
next = ele;
}
- }
+ } while(next);
return ret;
}
return ele;
}
+tElement *Widget_int_Create(tWidgetWin *Info, tElement *Parent, int ID, int Type, int Flags)
+{
+ if( Widget_GetElementById(Info, ID) )
+ return NULL;
+
+ // 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;
+}
+
// --- Message Handlers ---
void Widget_NewWidget(tWidgetWin *Info, size_t Len, const tWidgetMsg_Create *Msg)
{
const int max_debugname_len = Len - sizeof(tWidgetMsg_Create);
- tElement *parent, *new;
+ tElement *parent;
// Sanity check
if( Len < sizeof(*Msg) )
return ;
}
- // 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;
+ Widget_UpdateMinDims(parent);
+}
+
+void Widget_NewWidgetSubwin(tWidgetWin *Info, size_t Len, const tWidgetMsg_CreateSubWin *Msg)
+{
+ const int max_debugname_len = Len - sizeof(tWidgetMsg_CreateSubWin);
+ tElement *parent, *new;
+
+ // Sanity check
+ if( Len < sizeof(*Msg) )
+ return ;
+ if( strnlen(Msg->DebugName, max_debugname_len) == max_debugname_len )
+ return ;
- if( gaWM_WidgetTypes[new->Type]->Init )
- gaWM_WidgetTypes[new->Type]->Init(new);
+ parent = Widget_GetElementById(Info, Msg->Parent);
+ if(!parent) return;
+ if( Widget_GetElementById(Info, Msg->NewID) ) return ;
- // Add to parent's list
- if(parent->LastChild)
- parent->LastChild->NextSibling = new;
- else
- parent->FirstChild = new;
- parent->LastChild = new;
+ new = Widget_int_Create(Info, parent, Msg->NewID, Msg->Type, Msg->Flags);
+ new->Data = WM_GetWindowByID(parent->Window, Msg->WindowHandle);
+ Widget_UpdateMinDims(parent);
+}
- // 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_SetFocus(tWidgetWin *Info, tElement *Ele)
+{
+ // TODO: Callbacks
- Widget_UpdateMinDims(parent);
+ Info->FocusedElement = Ele;
}
void Widget_SetFlags(tWidgetWin *Info, int Len, const tWidgetMsg_SetFlags *Msg)
// }
}
+int Widget_GetText(tWidgetWin *Info, int Len, const tWidgetMsg_SetText *Msg)
+{
+ if( Len < sizeof(*Msg) )
+ return 0;
+ if( Len > sizeof(*Msg) )
+ return 1; // Pass to user
+
+ const char *text = NULL;
+ tElement *ele = Widget_GetElementById(Info, Msg->WidgetID);
+ if(ele)
+ text = ele->Text;
+
+ char buf[sizeof(tWidgetMsg_SetText) + strlen(text?text:"") + 1];
+ tWidgetMsg_SetText *omsg = (void*)buf;
+
+ if( text ) {
+ omsg->WidgetID = Msg->WidgetID;
+ strcpy(omsg->Text, text);
+ }
+ else {
+ omsg->WidgetID = -1;
+ omsg->Text[0] = 0;
+ }
+
+ WM_SendMessage(Info->RootElement.Window, Info->RootElement.Window, MSG_WIDGET_GETTEXT, sizeof(buf), buf);
+ return 0;
+}
+
int Renderer_Widget_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data)
{
tWidgetWin *info = Target->RendererInfo;
+ tElement *ele;
switch(Msg)
{
case WNDMSG_RESIZE: {
case WNDMSG_MOUSEBTN: {
const struct sWndMsg_MouseButton *msg = Data;
tWidgetMsg_MouseBtn client_msg;
- tElement *ele;
int x, y;
int rv;
client_msg.bPressed = msg->bPressed;
ele = Widget_GetElementByPos(info, x, y);
+ Widget_SetFocus(info, ele);
// Send event to all elements from `ele` upwards
for( ; ele; ele = ele->Parent )
{
}
return 0; }
+ case WNDMSG_KEYDOWN: {
+ const struct sWndMsg_KeyAction *msg = Data;
+ if(Len < sizeof(*msg)) return -1;
+
+ if(!info->FocusedElement) return 0;
+ ele = info->FocusedElement;
+
+ if(gaWM_WidgetTypes[ele->Type]->KeyDown)
+ gaWM_WidgetTypes[ele->Type]->KeyDown(ele, msg->KeySym, msg->UCS32);
+ else
+ {
+ // TODO: Pass to user
+ }
+
+ return 0; }
+
+ case WNDMSG_KEYFIRE: {
+ const struct sWndMsg_KeyAction *msg = Data;
+ if(Len < sizeof(*msg)) return -1;
+
+ if(!info->FocusedElement) return 0;
+ ele = info->FocusedElement;
+
+ if(gaWM_WidgetTypes[ele->Type]->KeyFire)
+ gaWM_WidgetTypes[ele->Type]->KeyFire(ele, msg->KeySym, msg->UCS32);
+ else
+ {
+ // TODO: Pass the buck
+ }
+ return 0; }
+
+ case WNDMSG_KEYUP: {
+ const struct sWndMsg_KeyAction *msg = Data;
+ if(Len < sizeof(*msg)) return -1;
+
+ if(!info->FocusedElement) return 0;
+ ele = info->FocusedElement;
+
+ if(gaWM_WidgetTypes[ele->Type]->KeyUp)
+ gaWM_WidgetTypes[ele->Type]->KeyUp(ele, msg->KeySym);
+ else
+ {
+ // TODO: Pass the buck
+ }
+ return 0; }
+
// New Widget
case MSG_WIDGET_CREATE:
Widget_NewWidget(info, Len, Data);
return 0;
+ case MSG_WIDGET_CREATESUBWIN:
+ Widget_NewWidgetSubwin(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);
case MSG_WIDGET_SETTEXT:
Widget_SetText(info, Len, Data);
return 0;
+ case MSG_WIDGET_GETTEXT:
+ return Widget_GetText(info, Len, Data);
//
default: