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;
93 void WM_SetText(tElement *Element, char *Text)
96 if(Element->Text) free(Element->Text);
97 Element->Text = strdup(Text);
102 if(Element->Data) free(Element->Data);
103 Element->Data = Image_Load( Element->Text );
105 Element->Flags &= ~ELEFLAG_FIXEDSIZE;
109 //Element->Flags |= ELEFLAG_FIXEDSIZE;
110 Element->CachedW = ((tImage*)Element->Data)->Width;
111 Element->CachedH = ((tImage*)Element->Data)->Height;
113 if(Element->Parent && Element->Parent->Flags & ELEFLAG_VERTICAL) {
114 Element->MinCross = ((tImage*)Element->Data)->Width;
115 Element->MinWith = ((tImage*)Element->Data)->Height;
118 Element->MinWith = ((tImage*)Element->Data)->Width;
119 Element->MinCross = ((tImage*)Element->Data)->Height;
127 // --- Pre-Rendering ---
129 * \brief Updates the dimensions of an element
131 * The dimensions of an element are calculated from the parent's
132 * cross dimension (the side at right angles to the alignment) sans some
135 void WM_UpdateDimensions(tElement *Element, int Pass)
142 int fullCross, dynWith;
144 _SysDebug("%p -> Flags = 0x%x", Element, Element->Flags);
145 _SysDebug("%p ->CachedH = %i, ->PaddingT = %i, ->PaddingB = %i",
146 Element, Element->CachedH, Element->PaddingT, Element->PaddingB
148 _SysDebug("%p ->CachedW = %i, ->PaddingL = %i, ->PaddingR = %i",
149 Element, Element->CachedW, Element->PaddingL, Element->PaddingR
153 for( child = Element->FirstChild; child; child = child->NextSibling )
155 if( child->Flags & ELEFLAG_ABSOLUTEPOS )
158 _SysDebug("%p,%p ->FixedWith = %i", Element, child, child->FixedWith);
159 if( child->FixedWith )
162 fixedSize += child->FixedWith;
165 if( child->FixedCross && maxCross < child->FixedCross )
166 maxCross = child->FixedCross;
167 if( child->MinCross && maxCross < child->MinCross )
168 maxCross = child->MinCross;
172 _SysDebug("%p - nChildren = %i, nFixed = %i", Element, nChildren, nFixed);
173 if( nChildren > nFixed ) {
174 if( Element->Flags & ELEFLAG_VERTICAL )
175 dynWith = Element->CachedH - Element->PaddingT
178 dynWith = Element->CachedW - Element->PaddingL
180 dynWith -= fixedSize;
181 if( dynWith < 0 ) return ;
182 dynWith /= nChildren - nFixed;
183 _SysDebug("%p - dynWith = %i", Element, dynWith);
186 if( Element->Flags & ELEFLAG_VERTICAL )
187 fullCross = Element->CachedW - Element->PaddingL - Element->PaddingR;
189 fullCross = Element->CachedH - Element->PaddingT - Element->PaddingB;
191 _SysDebug("%p - fullCross = %i", Element, fullCross);
193 // Pass 2 - Set sizes and recurse
194 for( child = Element->FirstChild; child; child = child->NextSibling )
198 _SysDebug("%p,%p ->MinCross = %i", Element, child, child->MinCross);
201 // --- Cross Size ---
202 if( child->FixedCross )
203 cross = child->FixedCross;
205 // TODO: Extra flag so options are (Expand, Equal, Wrap)
206 else if( child->Flags & ELEFLAG_NOEXPAND )
207 cross = child->MinCross;
210 _SysDebug("%p,%p - cross = %i", Element, child, cross);
211 if( Element->Flags & ELEFLAG_VERTICAL )
212 child->CachedW = cross;
214 child->CachedH = cross;
217 if( child->FixedWith)
218 with = child->FixedWith;
219 else if( child->Flags & ELEFLAG_NOSTRETCH )
220 with = child->MinWith;
223 _SysDebug("%p,%p - with = %i", Element, child, with);
224 if( Element->Flags & ELEFLAG_VERTICAL )
225 child->CachedH = with;
227 child->CachedW = with;
229 WM_UpdateDimensions(child, 0);
234 * \brief Updates the position of an element
236 * The parent element sets the positions of its children
238 void WM_UpdatePosition(tElement *Element)
243 if( Element->Flags & ELEFLAG_NORENDER ) return ;
245 _SysDebug("Element=%p{PaddingL:%i, PaddingT:%i}",
246 Element, Element->PaddingL, Element->PaddingT);
249 x = Element->CachedX + Element->PaddingL;
250 y = Element->CachedY + Element->PaddingT;
253 for(child = Element->FirstChild; child; child = child->NextSibling)
259 if( Element->Flags & ELEFLAG_ALIGN_CENTER ) {
260 if(Element->Flags & ELEFLAG_VERTICAL )
261 child->CachedX += Element->CachedW/2 - child->CachedW/2;
263 child->CachedY += Element->CachedH/2 - child->CachedH/2;
265 else if( Element->Flags & ELEFLAG_ALIGN_END ) {
266 if(Element->Flags & ELEFLAG_VERTICAL )
267 child->CachedX += Element->CachedW - child->CachedW;
269 child->CachedY += Element->CachedH - child->CachedH;
272 // Update child's children positions
273 WM_UpdatePosition(child);
276 if(Element->Flags & ELEFLAG_VERTICAL ) {
277 y += child->CachedH + Element->GapSize;
280 x += child->CachedW + Element->GapSize;
284 _SysDebug("Element %p (%i,%i)",
285 Element, Element->CachedX, Element->CachedY
291 * \brief Update the minimum dimensions of the element
292 * \note Called after a child's minimum dimensions have changed
294 void WM_UpdateMinDims(tElement *Element)
300 Element->MinCross = 0;
301 Element->MinWith = 0;
303 for(child = Element->FirstChild; child; child = child->NextSibling)
305 if( Element->Parent &&
306 (Element->Flags & ELEFLAG_VERTICAL) == (Element->Parent->Flags & ELEFLAG_VERTICAL)
309 if(child->FixedCross)
310 Element->MinCross += child->FixedCross;
312 Element->MinCross += child->MinCross;
314 Element->MinWith += child->FixedWith;
316 Element->MinWith += child->MinWith;
320 if(child->FixedCross)
321 Element->MinWith += child->FixedCross;
323 Element->MinWith += child->MinCross;
325 Element->MinCross += child->FixedWith;
327 Element->MinCross += child->MinWith;
332 WM_UpdateMinDims(Element->Parent);
336 void WM_RenderWidget(tElement *Element)
340 if( Element->Flags & ELEFLAG_NORENDER ) return ;
341 if( Element->Flags & ELEFLAG_INVISIBLE ) return ;
343 Decorator_RenderWidget(Element);
345 for(child = Element->FirstChild; child; child = child->NextSibling)
347 WM_RenderWidget(child);
353 gWM_RootElement.CachedX = 0; gWM_RootElement.CachedY = 0;
354 gWM_RootElement.CachedW = giScreenWidth;
355 gWM_RootElement.CachedH = giScreenHeight;
356 gWM_RootElement.Flags |= ELEFLAG_NOEXPAND|ELEFLAG_ABSOLUTEPOS|ELEFLAG_FIXEDSIZE;
358 WM_UpdateDimensions( &gWM_RootElement, 0 );
359 WM_UpdatePosition( &gWM_RootElement );
360 WM_RenderWidget( &gWM_RootElement );