Usermode/AxWin3 - Adding pop-up menu support (via a new window type)
[tpg/acess2.git] / Usermode / Applications / axwin3_src / WM / renderer_menu.c
1 /*
2  * Acess2 Window Manager v3
3  * - By John Hodge (thePowersGang)
4  *
5  * render_menu.c
6  * - Pop-up menu window class/renderer
7  */
8 #include <common.h>
9 #include <menu_messages.h>
10
11 // === STRUCTURES ===
12 typedef struct sMenuItem
13 {
14         // Settings
15         char    *Label;
16         char    *Shortcut;
17          int    KeyOffset;
18          int    Flags;
19         
20         // Cached values
21          int    LabelWidth;     
22          int    ShortcutWidth;
23          int    UnderlineX;
24          int    UnderlineW;
25
26         char    Data[];
27 } tMenuItem;
28
29 typedef struct sMenuWindowInfo
30 {
31          int    MaxLabelWidth;
32          int    MinLabelWidth;
33         
34          int    MaxItems;
35          int    nItems;
36         tMenuItem       *Items[];
37 } tMenuWindowInfo;
38
39 // === GLOBALS ===
40 tWMRenderer     gRenderer_Menu = {
41         .Name = "Menu",
42         .CreateWindow = Renderer_Menu_Create,
43         .Redraw = Renderer_Menu_Redraw,
44         .HandleMessage = Renderer_Menu_HandleMessage
45 };
46
47 // === CODE ===
48 void Renderer_Menu_Init(void)
49 {
50         WM_RegisterRenderer(&gRenderer_Menu);
51 }
52
53 tWindow *Renderer_Menu_Create(int Argument)
54 {
55         tWindow *ret;
56         tMenuWindowInfo *info;
57
58         if(Argument < 5)        Argument = 5;
59         if(Argument > 200)      Argument = 200; 
60
61         ret = WM_CreateWindowStruct(sizeof(*info) + Argument*sizeof(info->Items[0]));
62         info = ret->RendererInfo;
63         info->MaxItems = Argument;
64         
65         return ret;
66 }
67
68 void Renderer_Menu_Redraw(tWindow *Window)
69 {
70         // TODO: Implement Renderer_Menu_Redraw
71         
72         // - Resize window to contain all items
73
74         // - Move the window such that it is on screen
75         //  > Make sure to catch if the menu can't fit fully onscreen
76
77         // - Render each item
78 }
79
80 int Renderer_Menu_HandleMessage(tWindow *Window, int Msg, int Length, void *Data)
81 {
82         switch(Msg)
83         {
84         case MSG_MENU_ADDITEM: {
85                 tMenuMsg_AddItem        *req = Data;
86                 tMenuItem       *item;
87                 if(Length < sizeof(*req) + 1)   return -1;
88                 if(req->Label[Length-sizeof(*req)] != '\0')     return -1;
89                 
90                 if(info->Items[req->ID])        break;
91                 item = malloc(sizeof(tMenuItem)+strlen(req->Label));
92                 info->Items[req->ID] = item;
93                 
94                 if(req->Label[0] == '\0')
95                 {
96                         // Spacer
97                         item->Label = NULL;
98                 }
99                 else
100                 {
101                         // Actual item
102                         char    *dest = item->Data;
103                         char    *src = req->Label;
104                          int    ofs = 0;
105                         // - Main label
106                         item->KeyOffset = -1;
107                         item->Label = dest;
108                         for(ofs = 0; *src && *src != '\t'; ofs ++)
109                         {
110                                 if(*src == '&') {
111                                         *dest = '\0';
112                                         item->KeyOffset = ofs;
113                                         src ++;
114                                 }
115                                 else {
116                                         *dest++ = *src++;
117                                 }
118                         }
119                         *dest = '\0';
120                         // - Key combo / Shortcut
121                         if(*src)
122                         {
123                                 src ++;
124                                 item->Shortcut = dest;
125                                 strcpy(item->Shortcut, src);
126                         }
127                         else
128                         {
129                                 item->Shortcut = NULL;
130                         }
131                         
132                         // Get dimensions
133                         // - Underline (hotkey)
134                         if(item->KeyOffset == -1)
135                         {
136                                 item->UnderlineX = 0;
137                                 item->UnderlineW = 0;
138                         }
139                         else
140                         {
141                                 char    tmp = item->Label[item->KeyOffset];
142                                 item->Label[item->KeyOffset] = '\0';
143                                 WM_Render_GetTextDims(NULL, item->Label, &item->UnderlineX, NULL);
144                                 item->Label[item->KeyOffset] = tmp;
145                                 tmp = item->Label[item->KeyOffset+1];
146                                 item->Label[item->KeyOffset+1] = '\0';
147                                 WM_Render_GetTextDims(NULL, item->Label+item->KeyOffset, &item->UnderlineW, NULL);
148                                 item->Label[item->KeyOffset+1] = tmp;
149                         }
150                         // - Labels
151                         WM_Render_GetTextDims(NULL, item->Label, &item->LabelWidth, NULL);
152                         if(item->Shortcut)
153                                 WM_Render_GetTextDims(NULL, item->Shortcut, &item->ShortcutWidth, NULL);
154                         else
155                                 item->ShortcutWidth = 0;
156                 }
157         
158                 break; }
159         
160         // Only message to pass to client
161         case MSG_MENU_SELECT:
162                 return 1;
163         }
164         return 0;
165 }
166

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