cb4fd27ea2228467722dcb601b2d0dc2e197beb9
[tpg/acess2.git] / Usermode / Applications / axwin2_src / WM / wm.c
1 /*
2  * Acess GUI (AxWin) Version 2
3  * By John Hodge (thePowersGang)
4  * 
5  * Window Manager and Widget Control
6  */
7 #include "common.h"
8 #include <stdlib.h>
9 #include <string.h>
10 #include "wm.h"
11 #include <acess/sys.h>  // _SysDebug
12
13 // === IMPORTS ===
14 extern void     Video_GetTextDims(tFont *Font, const char *Text, int *W, int *H);
15
16 // === PROTOTYPES ===
17 tElement        *AxWin_CreateElement(tElement *Parent, int Type, int Flags, const char *DebugName);
18 void    AxWin_DeleteElement(tElement *Element);
19 void    AxWin_SetFlags(tElement *Element, int Flags);
20 void    AxWin_SetSize(tElement *Element, int Size);
21 void    AxWin_SetText(tElement *Element, const char *Text);
22
23 // === GLOBALS ===
24 // - TODO: Handle windows by having multiple root elements
25 tElement        gWM_RootElement = {
26         .DebugName = "ROOT"
27 };
28
29 tApplication    *gWM_Applications;
30
31 // --- Element type flags
32 struct {
33         void    (*Init)(tElement *This);
34         void    (*Delete)(tElement *This);
35         void    (*UpdateFlags)(tElement *This);
36         void    (*UpdateSize)(tElement *This);
37         void    (*UpdateText)(tElement *This);
38 }       gaWM_WidgetTypes[MAX_ELETYPES] = {
39         {NULL, NULL, NULL, NULL, NULL}, // NULL
40         {NULL, NULL, NULL, NULL, NULL}, // Window
41         {NULL, NULL, NULL, NULL, NULL}  // Box
42 };
43 const int       ciWM_NumWidgetTypes = sizeof(gaWM_WidgetTypes)/sizeof(gaWM_WidgetTypes[0]);
44
45 // === CODE ===
46 tApplication *AxWin_RegisterClient(int IdentLen, void *Ident, tMessages_Handle_Callback *Cb, const char *Name)
47 {
48         tApplication    *ret = calloc( 1, sizeof(tApplication) + 1 + strlen(Name) + 1 + IdentLen );
49         
50         ret->Name = &ret->MetaElement.DebugName[1];
51         strcpy(ret->Name, Name);
52         ret->Ident = ret->Name + strlen(Name) + 1;
53         memcpy(ret->Ident, Ident, IdentLen);
54         ret->SendMessage = Cb;
55
56         ret->MaxElementIndex = DEFAULT_ELEMENTS_PER_APP;
57         ret->EleIndex = calloc( 1, ret->MaxElementIndex * sizeof(*ret->EleIndex) );
58
59         ret->Next = gWM_Applications;
60         gWM_Applications = ret;
61
62         // TODO: Inform listeners of the new application
63
64         return ret;
65 }
66
67 void AxWin_DeregisterClient(tApplication *App)
68 {
69         tElement        *win, *next;
70         // TODO: Implement DeregisterClient
71
72         for( win = App->MetaElement.FirstChild; win; win = next )
73         {
74                 next = win->NextSibling;
75                 AxWin_DeleteElement(win);
76         }
77
78         // TODO: Inform listeners of deleted application
79         // TODO: Remove from list
80         free(App);
81 }
82
83 tElement *AxWin_CreateWindow(tApplication *App, const char *Name)
84 {
85         tElement        *ret;
86
87         // TODO: Implement _CreateTab
88         
89         ret = AxWin_CreateElement(&App->MetaElement, ELETYPE_WINDOW, 0, NULL);
90         ret->Text = strdup(Name);
91         return ret;
92 }
93
94 // --- Widget Creation and Control ---
95 tAxWin_Element *AxWin_CreateElement(tElement *Parent, int Type, int Flags, const char *DebugName)
96 {
97         tElement        *ret;
98         const char      *dbgName = DebugName ? DebugName : "";
99         
100         ret = calloc(sizeof(tElement)+strlen(dbgName)+1, 1);
101         if(!ret)        return NULL;
102         
103         // Prepare
104         ret->Type = Type;
105         strcpy(ret->DebugName, dbgName);
106         if(Parent == NULL)      Parent = &gWM_RootElement;
107         ret->Parent = Parent;
108         ret->Flags = Flags;
109         
110         // Append to parent's list
111         if(Parent->LastChild)
112                 Parent->LastChild->NextSibling = ret;
113         Parent->LastChild = ret;
114         if(!Parent->FirstChild) Parent->FirstChild = ret;
115         
116         ret->PaddingL = 2;
117         ret->PaddingR = 2;
118         ret->PaddingT = 2;
119         ret->PaddingB = 2;
120         
121         if( Type < ciWM_NumWidgetTypes && gaWM_WidgetTypes[Type].Init )
122                 gaWM_WidgetTypes[Type].Init(ret);
123         
124         WM_UpdateMinDims(ret->Parent);
125         
126         return ret;
127 }
128
129 /**
130  * \brief Delete an element
131  */
132 void AxWin_DeleteElement(tElement *Element)
133 {
134         tElement        *child, *next;
135         
136         for(child = Element->FirstChild; child; child = next)
137         {
138                 next = child->NextSibling;
139                 AxWin_DeleteElement(child);
140         }
141
142         // TODO: Implement AxWin_DeleteElement
143         // TODO: Clean up related data.
144         if( Element->Type < ciWM_NumWidgetTypes && gaWM_WidgetTypes[Element->Type].Delete )
145                 gaWM_WidgetTypes[Element->Type].Delete(Element);
146
147         if(Element->Owner)
148                 Element->Owner->EleIndex[ Element->ApplicationID ] = NULL;
149
150         Element->Type = 0;
151         Element->Owner = 0;
152         Element->Flags = 0;
153
154         free(Element);
155 }
156
157 /**
158  * \brief Alter an element's flags 
159  */
160 void AxWin_SetFlags(tElement *Element, int Flags)
161 {
162         // Permissions are handled in the message handler
163         if(!Element) {
164                 gWM_RootElement.Flags = Flags;
165                 return ;
166         }
167         
168         Element->Flags = Flags;
169         return ;
170 }
171
172 /**
173  * \brief Set the fixed lenghthways size of an element
174  */
175 void AxWin_SetSize(tElement *Element, int Size)
176 {
177         if(!Element)    return ;
178         Element->FixedWith = Size;
179         return ;
180 }
181
182 /**
183  * \brief Set the text field of an element
184  * \note Used for the image path on ELETYPE_IMAGE
185  */
186 void AxWin_SetText(tElement *Element, const char *Text)
187 {
188         if(!Element)    return ;
189         if(Element->Text)       free(Element->Text);
190         Element->Text = strdup(Text);
191         
192         switch(Element->Type)
193         {
194         case ELETYPE_IMAGE:
195                 if(Element->Data)       free(Element->Data);
196                 Element->Data = Image_Load( Element->Text );
197                 if(!Element->Data) {
198                         Element->Flags &= ~ELEFLAG_FIXEDSIZE;
199                         return ;
200                 }
201                 
202                 //Element->Flags |= ELEFLAG_FIXEDSIZE;
203                 Element->CachedW = ((tImage*)Element->Data)->Width;
204                 Element->CachedH = ((tImage*)Element->Data)->Height;
205                 
206                 if(Element->Parent && Element->Parent->Flags & ELEFLAG_VERTICAL) {
207                         Element->MinCross = ((tImage*)Element->Data)->Width;
208                         Element->MinWith = ((tImage*)Element->Data)->Height;
209                 }
210                 else {
211                         Element->MinWith = ((tImage*)Element->Data)->Width;
212                         Element->MinCross = ((tImage*)Element->Data)->Height;
213                 }
214                 break;
215         
216         case ELETYPE_TEXT:
217                 {
218                  int    w=0, h=0;
219                 Video_GetTextDims(NULL, Element->Text, &w, &h);
220                 if(Element->Parent && Element->Parent->Flags & ELEFLAG_VERTICAL) {
221                         Element->MinCross = w;
222                         Element->MinWith = h;
223                 }
224                 else {
225                         Element->MinWith = w;
226                         Element->MinCross = h;
227                 }
228                 }
229                 break;
230         default:        // Any other, no special case
231                 break ; 
232         }
233         
234         return ;
235 }

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