Usermode/AxWin3 - Adding pop-up menu support (via a new window type)
authorJohn Hodge <[email protected]>
Thu, 10 Nov 2011 01:23:13 +0000 (09:23 +0800)
committerJohn Hodge <[email protected]>
Thu, 10 Nov 2011 01:23:13 +0000 (09:23 +0800)
Usermode/Applications/axwin3_src/Interface/main.c
Usermode/Applications/axwin3_src/WM/renderer_menu.c [new file with mode: 0644]
Usermode/Applications/axwin3_src/include/menu_messages.h [new file with mode: 0644]
Usermode/Applications/axwin3_src/libaxwin3.so_src/Makefile
Usermode/Applications/axwin3_src/libaxwin3.so_src/r_menu.c [new file with mode: 0644]
Usermode/Applications/axwin3_src/libaxwin3.so_src/r_widget.c
Usermode/include/axwin3/menu.h [new file with mode: 0644]

index 990489e..0065686 100644 (file)
@@ -9,14 +9,17 @@
 #include <stdlib.h>
 #include <axwin3/axwin.h>
 #include <axwin3/widget.h>
+#include <axwin3/menu.h>
 
 #define SIDEBAR_WIDTH  36
 
 // === PROTOTYPES ===
 void   create_sidebar(void);
+void   create_mainmenu(void);
 
 // === GLOBALS ===
 tHWND  gSidebar;
+tHWND  gSystemMenu;
 tAxWin3_Widget *gSidebarRoot;
  int   giScreenWidth;
  int   giScreenHeight;
@@ -25,6 +28,7 @@ tAxWin3_Widget        *gSidebarRoot;
 int systembutton_fire(tAxWin3_Widget *Widget)
 {
        _SysDebug("SystemButton pressed");
+       AxWin3_Menu_ShowAt(gSystemMenu, SIDEBAR_WIDTH, 0);
        return 0;
 }
 
@@ -34,6 +38,7 @@ int main(int argc, char *argv[])
        AxWin3_Connect(NULL);
        
        create_sidebar();
+       create_mainmenu();
        
        // Idle loop
        AxWin3_MainLoop();
@@ -82,7 +87,22 @@ void create_sidebar(void)
        
 }
 
+void mainmenu_app_textedit(void *unused)
+{
+       _SysDebug("TODO: Launch text editor");
+}
+
+void mainmenu_run_dialog(void *unused)
+{
+       _SysDebug("TODO: Show run dialog");
+}
+
 void create_mainmenu(void)
 {
+       gSystemMenu = AxWin3_Menu_Create(gSidebar);
+       
+       AxWin3_Menu_AddItem(gSystemMenu, "Text &Editor\tWin+E", mainmenu_app_textedit, NULL, 0, NULL);
+       AxWin3_Menu_AddItem(gSystemMenu, NULL, NULL, NULL, 0, NULL);
+       AxWin3_Menu_AddItem(gSystemMenu, "Run\tWin+R", mainmenu_run_dialog, NULL, 0, NULL);
 }
 
diff --git a/Usermode/Applications/axwin3_src/WM/renderer_menu.c b/Usermode/Applications/axwin3_src/WM/renderer_menu.c
new file mode 100644 (file)
index 0000000..bf8b845
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * Acess2 Window Manager v3
+ * - By John Hodge (thePowersGang)
+ *
+ * render_menu.c
+ * - Pop-up menu window class/renderer
+ */
+#include <common.h>
+#include <menu_messages.h>
+
+// === STRUCTURES ===
+typedef struct sMenuItem
+{
+       // Settings
+       char    *Label;
+       char    *Shortcut;
+        int    KeyOffset;
+        int    Flags;
+       
+       // Cached values
+        int    LabelWidth;     
+        int    ShortcutWidth;
+        int    UnderlineX;
+        int    UnderlineW;
+
+       char    Data[];
+} tMenuItem;
+
+typedef struct sMenuWindowInfo
+{
+        int    MaxLabelWidth;
+        int    MinLabelWidth;
+       
+        int    MaxItems;
+        int    nItems;
+       tMenuItem       *Items[];
+} tMenuWindowInfo;
+
+// === GLOBALS ===
+tWMRenderer    gRenderer_Menu = {
+       .Name = "Menu",
+       .CreateWindow = Renderer_Menu_Create,
+       .Redraw = Renderer_Menu_Redraw,
+       .HandleMessage = Renderer_Menu_HandleMessage
+};
+
+// === CODE ===
+void Renderer_Menu_Init(void)
+{
+       WM_RegisterRenderer(&gRenderer_Menu);
+}
+
+tWindow        *Renderer_Menu_Create(int Argument)
+{
+       tWindow *ret;
+       tMenuWindowInfo *info;
+
+       if(Argument < 5)        Argument = 5;
+       if(Argument > 200)      Argument = 200; 
+
+       ret = WM_CreateWindowStruct(sizeof(*info) + Argument*sizeof(info->Items[0]));
+       info = ret->RendererInfo;
+       info->MaxItems = Argument;
+       
+       return ret;
+}
+
+void Renderer_Menu_Redraw(tWindow *Window)
+{
+       // TODO: Implement Renderer_Menu_Redraw
+       
+       // - Resize window to contain all items
+
+       // - Move the window such that it is on screen
+       //  > Make sure to catch if the menu can't fit fully onscreen
+
+       // - Render each item
+}
+
+int Renderer_Menu_HandleMessage(tWindow *Window, int Msg, int Length, void *Data)
+{
+       switch(Msg)
+       {
+       case MSG_MENU_ADDITEM: {
+               tMenuMsg_AddItem        *req = Data;
+               tMenuItem       *item;
+               if(Length < sizeof(*req) + 1)   return -1;
+               if(req->Label[Length-sizeof(*req)] != '\0')     return -1;
+               
+               if(info->Items[req->ID])        break;
+               item = malloc(sizeof(tMenuItem)+strlen(req->Label));
+               info->Items[req->ID] = item;
+               
+               if(req->Label[0] == '\0')
+               {
+                       // Spacer
+                       item->Label = NULL;
+               }
+               else
+               {
+                       // Actual item
+                       char    *dest = item->Data;
+                       char    *src = req->Label;
+                        int    ofs = 0;
+                       // - Main label
+                       item->KeyOffset = -1;
+                       item->Label = dest;
+                       for(ofs = 0; *src && *src != '\t'; ofs ++)
+                       {
+                               if(*src == '&') {
+                                       *dest = '\0';
+                                       item->KeyOffset = ofs;
+                                       src ++;
+                               }
+                               else {
+                                       *dest++ = *src++;
+                               }
+                       }
+                       *dest = '\0';
+                       // - Key combo / Shortcut
+                       if(*src)
+                       {
+                               src ++;
+                               item->Shortcut = dest;
+                               strcpy(item->Shortcut, src);
+                       }
+                       else
+                       {
+                               item->Shortcut = NULL;
+                       }
+                       
+                       // Get dimensions
+                       // - Underline (hotkey)
+                       if(item->KeyOffset == -1)
+                       {
+                               item->UnderlineX = 0;
+                               item->UnderlineW = 0;
+                       }
+                       else
+                       {
+                               char    tmp = item->Label[item->KeyOffset];
+                               item->Label[item->KeyOffset] = '\0';
+                               WM_Render_GetTextDims(NULL, item->Label, &item->UnderlineX, NULL);
+                               item->Label[item->KeyOffset] = tmp;
+                               tmp = item->Label[item->KeyOffset+1];
+                               item->Label[item->KeyOffset+1] = '\0';
+                               WM_Render_GetTextDims(NULL, item->Label+item->KeyOffset, &item->UnderlineW, NULL);
+                               item->Label[item->KeyOffset+1] = tmp;
+                       }
+                       // - Labels
+                       WM_Render_GetTextDims(NULL, item->Label, &item->LabelWidth, NULL);
+                       if(item->Shortcut)
+                               WM_Render_GetTextDims(NULL, item->Shortcut, &item->ShortcutWidth, NULL);
+                       else
+                               item->ShortcutWidth = 0;
+               }
+       
+               break; }
+       
+       // Only message to pass to client
+       case MSG_MENU_SELECT:
+               return 1;
+       }
+       return 0;
+}
+
diff --git a/Usermode/Applications/axwin3_src/include/menu_messages.h b/Usermode/Applications/axwin3_src/include/menu_messages.h
new file mode 100644 (file)
index 0000000..04dcd2d
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * Acess2 Window Manager v3
+ * - By John Hodge (thePowersGang)
+ *
+ * menu_messages.h
+ * - AxWin3 Menu IPC Messages
+ */
+#ifndef _MENU_MESSAGES_H_
+#define _MENU_MESSAGES_H_
+
+#include "ipcmessages.h"
+
+enum eMenuMessages
+{
+       MSG_MENU_ADDITEM = 0x1000,
+       MSG_MENU_SETFLAGS,
+       
+       MSG_MENU_SELECT
+};
+
+typedef struct
+{
+       uint16_t        ID;
+       uint16_t        Flags;
+       uint32_t        SubMenuID;
+       char    Label[];
+} tMenuMsg_AddItem;
+
+typedef struct
+{
+       uint16_t        ID;
+       uint16_t        Value;
+       uint16_t        Mask;
+} tMenuMsg_SetFlags;
+
+typedef struct
+{
+       uint16_t        ID;
+} tMenuMsg_Select;
+
+#endif
+
index b874291..3d37b5b 100644 (file)
@@ -7,7 +7,7 @@ CPPFLAGS += -I ../include/
 CFLAGS   += -Wall
 LDFLAGS  += -lc -soname libaxwin3.so
 
-OBJ = main.o msg.o wm.o r_widget.o
+OBJ = main.o msg.o wm.o r_widget.o r_menu.o
 BIN = libaxwin3.so
 
 include ../../../Libraries/Makefile.tpl
diff --git a/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_menu.c b/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_menu.c
new file mode 100644 (file)
index 0000000..e7bd2bf
--- /dev/null
@@ -0,0 +1,112 @@
+/*
+ * AxWin3 Interface Library
+ * - By John Hodge (thePowersGang)
+ *
+ * r_menu.c
+ * - Menu renderer interface
+ */
+#include <stdlib.h>
+#include <axwin3/axwin.h>
+#include <axwin3/menu.h>
+#include <menu_messages.h>
+#include "include/internal.h"
+#include "include/ipc.h"
+#include <string.h>
+
+// === TYPES ===
+typedef struct sMenuWindowInfo tMenuWindowInfo;
+
+struct sAxWin3_MenuItem
+{
+       tHWND   Window;
+        int    ID;
+       tAxWin3_Menu_Callback   Callback;
+       void    *CbPtr;
+       tHWND   SubMenu;
+};
+
+struct sMenuWindowInfo
+{
+        int    nItems;
+       tAxWin3_MenuItem        *Items;
+};
+
+// === CODE ===
+int AxWin3_Menu_int_Callback(tHWND Window, int Message, int Length, void *Data)
+{
+       tMenuWindowInfo *info = AxWin3_int_GetDataPtr(Window);
+       switch(Message)
+       {
+       case MSG_MENU_SELECT: {
+               tMenuMsg_Select *msg = Data;
+               tAxWin3_MenuItem        *item;
+               if(Length < sizeof(tMenuMsg_Select))    return -1;
+               if(msg->ID >= info->nItems)     return -1;
+               item = &info->Items[msg->ID];
+               if(item->Callback)      item->Callback(item->CbPtr);
+               return 0; }
+       }
+       return 1;
+}
+
+tHWND AxWin3_Menu_Create(tHWND Parent)
+{
+       tHWND   ret;
+       tMenuWindowInfo *info;
+       
+       ret = AxWin3_CreateWindow(Parent, "Menu", 0, sizeof(*info), AxWin3_Menu_int_Callback);
+       if(!ret)        return ret;
+       
+       info = AxWin3_int_GetDataPtr(ret);
+       info->nItems = 0;
+       info->Items = NULL;
+       
+       return ret;
+}
+
+void AxWin3_Menu_ShowAt(tHWND Menu, int X, int Y)
+{
+       AxWin3_MoveWindow(Menu, X, Y);
+       AxWin3_ShowWindow(Menu, 1);
+}
+
+tAxWin3_MenuItem *AxWin3_Menu_AddItem(
+       tHWND Menu, const char *Label,
+       tAxWin3_Menu_Callback Cb, void *Ptr,
+       int Flags, tHWND SubMenu
+       )
+{
+       tMenuWindowInfo *info;
+       tAxWin3_MenuItem        *ret;
+       
+       info = AxWin3_int_GetDataPtr(Menu);
+       
+       info->nItems ++;
+       info->Items = realloc(info->Items, sizeof(*info->Items)*info->nItems);
+       if(!info->Items) {
+               _SysDebug("ERROR: Realloc Failed");
+               return NULL;
+       }
+       
+       ret = &info->Items[info->nItems-1];
+       ret->ID = info->nItems - 1;
+       ret->Window = Menu;
+       ret->Callback = Cb;
+       ret->CbPtr = Ptr;
+       ret->SubMenu = SubMenu; 
+
+       {
+               tAxWin_IPCMessage       *msg;
+               tMenuMsg_AddItem        *req;
+               msg = AxWin3_int_AllocateIPCMessage(Menu, MSG_MENU_ADDITEM, 0, sizeof(*req)+strlen(Label));
+               req = (void*)msg->Data;
+               req->ID = ret->ID;
+               req->Flags = Flags;
+               req->SubMenuID = AxWin3_int_GetWindowID(SubMenu);
+               strcpy(req->Label, Label);
+               AxWin3_int_SendIPCMessage(msg);
+               free(msg);
+       }
+       
+       return ret;
+}
index 43eef70..17dd16e 100644 (file)
@@ -2,8 +2,8 @@
  * AxWin3 Interface Library
  * - By John Hodge (thePowersGang)
  *
- * main.c
- * - Entrypoint and setup
+ * r_widget.c
+ * - Widget window type interface
  */
 #include <axwin3/axwin.h>
 #include <axwin3/widget.h>
diff --git a/Usermode/include/axwin3/menu.h b/Usermode/include/axwin3/menu.h
new file mode 100644 (file)
index 0000000..323bf30
--- /dev/null
@@ -0,0 +1,26 @@
+/*
+ * Acess2 GUI Version 3 (AxWin3)
+ * - By John Hodge (thePowersGang)
+ *
+ * menu.h
+ * - Menu window type
+ */
+#ifndef _AXWIN3_MENU_H_
+#define _AXWIN3_MENU_H_
+
+typedef void   (*tAxWin3_Menu_Callback)(void *Ptr);
+typedef struct sAxWin3_MenuItem        tAxWin3_MenuItem;
+
+extern tHWND   AxWin3_Menu_Create(tHWND Parent);
+extern void    AxWin3_Menu_ShowAt(tHWND Menu, int X, int Y);
+
+extern tAxWin3_MenuItem        *AxWin3_Menu_AddItem(
+               tHWND Menu, const char *Label,
+               tAxWin3_Menu_Callback Cb, void *Ptr,
+               int Flags, tHWND SubMenu
+               );
+extern tAxWin3_MenuItem        *AxWin3_Menu_GetItem(tHWND Menu, int Index);
+extern void    AxWin3_Menu_SetFlags(tAxWin3_MenuItem *Item, int Flags, int Mask);
+
+#endif
+

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