2 * Acess GUI (AxWin) Version 2
3 * By John Hodge (thePowersGang)
5 * Window Manager and Widget Control
13 extern void Decorator_RenderWidget(tElement *Element);
16 tElement *WM_CreateElement(tElement *Parent, int Type, int Flags);
17 void WM_UpdateMinDims(tElement *Element);
18 void WM_SetFlags(tElement *Element, int Flags);
19 void WM_SetSize(tElement *Element, int Size);
20 void WM_SetText(tElement *Element, char *Text);
21 void WM_UpdateDimensions(tElement *Element, int Pass);
22 void WM_UpdatePosition(tElement *Element);
23 void WM_RenderWidget(tElement *Element);
27 tElement gWM_RootElement;
29 void (*Init)(tElement *This);
30 void (*UpdateFlags)(tElement *This);
31 void (*UpdateSize)(tElement *This);
32 void (*UpdateText)(tElement *This);
33 } gaWM_WidgetTypes[MAX_ELETYPES] = {
34 {NULL, NULL, NULL, NULL}, // NULL
35 {NULL, NULL, NULL, NULL} // Box
39 // --- Widget Creation and Control ---
40 tElement *WM_CreateElement(tElement *Parent, int Type, int Flags)
44 ret = calloc(sizeof(tElement), 1);
49 if(Parent == NULL) Parent = &gWM_RootElement;
53 // Append to parent's list
54 ret->NextSibling = Parent->LastChild;
55 Parent->LastChild = ret;
56 if(!Parent->FirstChild) Parent->FirstChild = ret;
63 if( gaWM_WidgetTypes[Type].Init )
64 gaWM_WidgetTypes[Type].Init(ret);
66 WM_UpdateMinDims(ret->Parent);
72 * \brief Alter an element's flags
74 void WM_SetFlags(tElement *Element, int Flags)
76 // Permissions are handled in the message handler
78 gWM_RootElement.Flags = Flags;
82 Element->Flags = Flags;
86 void WM_SetSize(tElement *Element, int Size)
89 Element->FixedWith = Size;
94 * \brief Set the text field of an element
95 * \note Used for the image path on ELETYPE_IMAGE
97 void WM_SetText(tElement *Element, char *Text)
100 if(Element->Text) free(Element->Text);
101 Element->Text = strdup(Text);
103 switch(Element->Type)
106 if(Element->Data) free(Element->Data);
107 Element->Data = Image_Load( Element->Text );
109 Element->Flags &= ~ELEFLAG_FIXEDSIZE;
113 //Element->Flags |= ELEFLAG_FIXEDSIZE;
114 Element->CachedW = ((tImage*)Element->Data)->Width;
115 Element->CachedH = ((tImage*)Element->Data)->Height;
117 if(Element->Parent && Element->Parent->Flags & ELEFLAG_VERTICAL) {
118 Element->MinCross = ((tImage*)Element->Data)->Width;
119 Element->MinWith = ((tImage*)Element->Data)->Height;
122 Element->MinWith = ((tImage*)Element->Data)->Width;
123 Element->MinCross = ((tImage*)Element->Data)->Height;
131 // --- Pre-Rendering ---
133 * \name Pre-Rendering
134 * \brief Updates the element positions and sizes
138 * \brief Updates the dimensions of an element
140 * The dimensions of an element are calculated from the parent's
141 * cross dimension (the side at right angles to the alignment) sans some
144 void WM_UpdateDimensions(tElement *Element, int Pass)
151 int fullCross, dynWith;
153 _SysDebug("%p -> Flags = 0x%x", Element, Element->Flags);
154 _SysDebug("%p ->CachedH = %i, ->PaddingT = %i, ->PaddingB = %i",
155 Element, Element->CachedH, Element->PaddingT, Element->PaddingB
157 _SysDebug("%p ->CachedW = %i, ->PaddingL = %i, ->PaddingR = %i",
158 Element, Element->CachedW, Element->PaddingL, Element->PaddingR
162 for( child = Element->FirstChild; child; child = child->NextSibling )
164 if( child->Flags & ELEFLAG_ABSOLUTEPOS )
167 _SysDebug("%p,%p ->FixedWith = %i", Element, child, child->FixedWith);
168 if( child->FixedWith )
171 fixedSize += child->FixedWith;
174 if( child->FixedCross && maxCross < child->FixedCross )
175 maxCross = child->FixedCross;
176 if( child->MinCross && maxCross < child->MinCross )
177 maxCross = child->MinCross;
181 _SysDebug("%p - nChildren = %i, nFixed = %i", Element, nChildren, nFixed);
182 if( nChildren > nFixed ) {
183 if( Element->Flags & ELEFLAG_VERTICAL )
184 dynWith = Element->CachedH - Element->PaddingT
187 dynWith = Element->CachedW - Element->PaddingL
189 dynWith -= fixedSize;
190 if( dynWith < 0 ) return ;
191 dynWith /= nChildren - nFixed;
192 _SysDebug("%p - dynWith = %i", Element, dynWith);
195 if( Element->Flags & ELEFLAG_VERTICAL )
196 fullCross = Element->CachedW - Element->PaddingL - Element->PaddingR;
198 fullCross = Element->CachedH - Element->PaddingT - Element->PaddingB;
200 _SysDebug("%p - fullCross = %i", Element, fullCross);
202 // Pass 2 - Set sizes and recurse
203 for( child = Element->FirstChild; child; child = child->NextSibling )
207 _SysDebug("%p,%p ->MinCross = %i", Element, child, child->MinCross);
210 // --- Cross Size ---
211 if( child->FixedCross )
212 cross = child->FixedCross;
214 // TODO: Extra flag so options are (Expand, Equal, Wrap)
215 else if( child->Flags & ELEFLAG_NOEXPAND )
216 cross = child->MinCross;
219 _SysDebug("%p,%p - cross = %i", Element, child, cross);
220 if( Element->Flags & ELEFLAG_VERTICAL )
221 child->CachedW = cross;
223 child->CachedH = cross;
226 if( child->FixedWith)
227 with = child->FixedWith;
228 else if( child->Flags & ELEFLAG_NOSTRETCH )
229 with = child->MinWith;
232 _SysDebug("%p,%p - with = %i", Element, child, with);
233 if( Element->Flags & ELEFLAG_VERTICAL )
234 child->CachedH = with;
236 child->CachedW = with;
238 WM_UpdateDimensions(child, 0);
243 * \brief Updates the position of an element
245 * The parent element sets the positions of its children
247 void WM_UpdatePosition(tElement *Element)
252 if( Element->Flags & ELEFLAG_NORENDER ) return ;
254 _SysDebug("Element=%p{PaddingL:%i, PaddingT:%i}",
255 Element, Element->PaddingL, Element->PaddingT);
258 x = Element->CachedX + Element->PaddingL;
259 y = Element->CachedY + Element->PaddingT;
262 for(child = Element->FirstChild; child; child = child->NextSibling)
268 if( Element->Flags & ELEFLAG_ALIGN_CENTER ) {
269 if(Element->Flags & ELEFLAG_VERTICAL )
270 child->CachedX += Element->CachedW/2 - child->CachedW/2;
272 child->CachedY += Element->CachedH/2 - child->CachedH/2;
274 else if( Element->Flags & ELEFLAG_ALIGN_END ) {
275 if(Element->Flags & ELEFLAG_VERTICAL )
276 child->CachedX += Element->CachedW - child->CachedW;
278 child->CachedY += Element->CachedH - child->CachedH;
281 // Update child's children positions
282 WM_UpdatePosition(child);
285 if(Element->Flags & ELEFLAG_VERTICAL ) {
286 y += child->CachedH + Element->GapSize;
289 x += child->CachedW + Element->GapSize;
293 _SysDebug("Element %p (%i,%i)",
294 Element, Element->CachedX, Element->CachedY
299 * \brief Update the minimum dimensions of the element
300 * \note Called after a child's minimum dimensions have changed
302 void WM_UpdateMinDims(tElement *Element)
308 Element->MinCross = 0;
309 Element->MinWith = 0;
311 for(child = Element->FirstChild; child; child = child->NextSibling)
313 if( Element->Parent &&
314 (Element->Flags & ELEFLAG_VERTICAL) == (Element->Parent->Flags & ELEFLAG_VERTICAL)
317 if(child->FixedCross)
318 Element->MinCross += child->FixedCross;
320 Element->MinCross += child->MinCross;
322 Element->MinWith += child->FixedWith;
324 Element->MinWith += child->MinWith;
328 if(child->FixedCross)
329 Element->MinWith += child->FixedCross;
331 Element->MinWith += child->MinCross;
333 Element->MinCross += child->FixedWith;
335 Element->MinCross += child->MinWith;
340 WM_UpdateMinDims(Element->Parent);
347 void WM_RenderWidget(tElement *Element)
351 if( Element->Flags & ELEFLAG_NORENDER ) return ;
352 if( Element->Flags & ELEFLAG_INVISIBLE ) return ;
354 Decorator_RenderWidget(Element);
356 for(child = Element->FirstChild; child; child = child->NextSibling)
358 WM_RenderWidget(child);
364 gWM_RootElement.CachedX = 0; gWM_RootElement.CachedY = 0;
365 gWM_RootElement.CachedW = giScreenWidth;
366 gWM_RootElement.CachedH = giScreenHeight;
367 gWM_RootElement.Flags |= ELEFLAG_NOEXPAND|ELEFLAG_ABSOLUTEPOS|ELEFLAG_FIXEDSIZE;
369 WM_UpdateDimensions( &gWM_RootElement, 0 );
370 WM_UpdatePosition( &gWM_RootElement );
371 WM_RenderWidget( &gWM_RootElement );