2 * Acess GUI (AxWin) Version 2
3 * By John Hodge (thePowersGang)
11 #include <acess/sys.h> // _SysDebug
14 extern void Decorator_RenderWidget(tElement *Element);
15 extern tElement gWM_RootElement;
18 void WM_UpdateMinDims(tElement *Element);
19 void WM_UpdateDimensions(tElement *Element, int Pass);
20 void WM_UpdatePosition(tElement *Element);
21 void WM_RenderWidget(tElement *Element);
26 * \brief Updates the dimensions of an element
27 * \todo What is the \a Pass parameter for
29 * The dimensions of an element are calculated from the parent's
30 * cross dimension (the side at right angles to the alignment) sans some
33 void WM_UpdateDimensions(tElement *Element, int Pass)
40 int fullCross, dynWith;
42 _SysDebug("WM_UpdateDimensions %p'%s'", Element, Element->DebugName);
43 _SysDebug(" -> Flags = 0x%x", Element->Flags);
44 _SysDebug(" ->CachedH = %i, ->PaddingT = %i, ->PaddingB = %i",
45 Element->CachedH, Element->PaddingT, Element->PaddingB
47 _SysDebug(" ->CachedW = %i, ->PaddingL = %i, ->PaddingR = %i",
48 Element->CachedW, Element->PaddingL, Element->PaddingR
52 for( child = Element->FirstChild; child; child = child->NextSibling )
54 if( child->Flags & ELEFLAG_ABSOLUTEPOS )
57 _SysDebug(" > %p'%s' ->FixedWith = %i", child, child->DebugName, child->FixedWith);
58 if( child->FixedWith )
61 fixedSize += child->FixedWith;
64 if( child->FixedCross && maxCross < child->FixedCross )
65 maxCross = child->FixedCross;
66 if( child->MinCross && maxCross < child->MinCross )
67 maxCross = child->MinCross;
71 _SysDebug(" - nChildren = %i, nFixed = %i", Element, nChildren, nFixed);
72 if( nChildren > nFixed ) {
73 if( Element->Flags & ELEFLAG_VERTICAL )
74 dynWith = Element->CachedH - Element->PaddingT
77 dynWith = Element->CachedW - Element->PaddingL
80 if( dynWith < 0 ) return ;
81 dynWith /= nChildren - nFixed;
82 _SysDebug(" - dynWith = %i", dynWith);
85 if( Element->Flags & ELEFLAG_VERTICAL )
86 fullCross = Element->CachedW - Element->PaddingL - Element->PaddingR;
88 fullCross = Element->CachedH - Element->PaddingT - Element->PaddingB;
90 _SysDebug(" - fullCross = %i", Element, fullCross);
92 // Pass 2 - Set sizes and recurse
93 for( child = Element->FirstChild; child; child = child->NextSibling )
97 _SysDebug(" > %p'%s' ->MinCross = %i", child, child->DebugName, child->MinCross);
100 // --- Cross Size ---
101 if( child->FixedCross )
102 cross = child->FixedCross;
104 // TODO: Extra flag so options are (Expand, Equal, Wrap)
105 else if( child->Flags & ELEFLAG_NOEXPAND )
106 cross = child->MinCross;
109 _SysDebug(" > %p'%s' - cross = %i", child, child->DebugName, cross);
110 if( Element->Flags & ELEFLAG_VERTICAL )
111 child->CachedW = cross;
113 child->CachedH = cross;
116 if( child->FixedWith)
117 with = child->FixedWith;
118 else if( child->Flags & ELEFLAG_NOSTRETCH )
119 with = child->MinWith;
122 _SysDebug(" > %p'%s' - with = %i", child, child->DebugName, with);
123 if( Element->Flags & ELEFLAG_VERTICAL )
124 child->CachedH = with;
126 child->CachedW = with;
128 WM_UpdateDimensions(child, Pass);
131 _SysDebug("%p'%s' Done", Element, Element->DebugName);
135 * \brief Updates the position of an element
137 * The parent element sets the positions of its children
139 void WM_UpdatePosition(tElement *Element)
143 static int depth = 0;
144 char indent[depth+1];
146 if( Element->Flags & ELEFLAG_NORENDER ) return ;
148 memset(indent, ' ', depth);
149 indent[depth] = '\0';
152 _SysDebug("%sWM_UpdatePosition %p'%s'{PaddingL:%i, PaddingT:%i}",
153 indent, Element, Element->DebugName, Element->PaddingL, Element->PaddingT);
156 x = Element->CachedX + Element->PaddingL;
157 y = Element->CachedY + Element->PaddingT;
159 _SysDebug("%s- Alignment = %s", indent,
160 (Element->Flags & ELEFLAG_VERTICAL) ? "vertical" : "horizontal");
163 for(child = Element->FirstChild; child; child = child->NextSibling)
165 _SysDebug("%s- x = %i, y = %i", indent, x, y);
170 if( Element->Flags & ELEFLAG_ALIGN_CENTER ) {
171 _SysDebug("%sChild being aligned to center", indent);
172 if(Element->Flags & ELEFLAG_VERTICAL)
173 child->CachedX += Element->CachedW/2 - child->CachedW/2;
175 child->CachedY += Element->CachedH/2 - child->CachedH/2;
177 else if( Element->Flags & ELEFLAG_ALIGN_END) {
178 _SysDebug("%sChild being aligned to end", indent);
179 if(Element->Flags & ELEFLAG_VERTICAL )
180 child->CachedX += Element->CachedW
181 - Element->PaddingL - Element->PaddingR
184 child->CachedY += Element->CachedH
190 _SysDebug("%s> %p'%s' at (%i,%i)", indent, child, child->DebugName,
191 child->CachedX, child->CachedY);
193 // Update child's children positions
194 WM_UpdatePosition(child);
197 if(Element->Flags & ELEFLAG_VERTICAL ) {
198 y += child->CachedH + Element->GapSize;
201 x += child->CachedW + Element->GapSize;
205 _SysDebug("%sElement %p'%s' (%i,%i)",
206 indent, Element, Element->DebugName, Element->CachedX, Element->CachedY
212 * \brief Update the minimum dimensions of the element
213 * \note Called after a child's minimum dimensions have changed
215 void WM_UpdateMinDims(tElement *Element)
221 Element->MinCross = 0;
222 Element->MinWith = 0;
224 for(child = Element->FirstChild; child; child = child->NextSibling)
226 if( Element->Parent &&
227 (Element->Flags & ELEFLAG_VERTICAL) == (Element->Parent->Flags & ELEFLAG_VERTICAL)
230 if(child->FixedCross)
231 Element->MinCross += child->FixedCross;
233 Element->MinCross += child->MinCross;
235 Element->MinWith += child->FixedWith;
237 Element->MinWith += child->MinWith;
241 if(child->FixedCross)
242 Element->MinWith += child->FixedCross;
244 Element->MinWith += child->MinCross;
246 Element->MinCross += child->FixedWith;
248 Element->MinCross += child->MinWith;
253 WM_UpdateMinDims(Element->Parent);
257 void WM_RenderWidget(tElement *Element)
261 if( Element->Flags & ELEFLAG_NORENDER ) return ;
262 if( Element->Flags & ELEFLAG_INVISIBLE ) return ;
264 Decorator_RenderWidget(Element);
266 for(child = Element->FirstChild; child; child = child->NextSibling)
268 WM_RenderWidget(child);
272 void WM_UpdateWindow(tElement *Ele)
274 WM_UpdateDimensions( Ele, 0 );
275 WM_UpdatePosition( Ele );
276 WM_RenderWidget( Ele );
284 for( app = gWM_Applications; app; app = app->Next )
286 for( ele = app->MetaElement.FirstChild; ele; ele = ele->NextSibling ) {
287 if( ele->Flags & ELEFLAG_WINDOW_MAXIMISED ) {
288 ele->CachedX = giWM_MaxAreaX;
289 ele->CachedY = giWM_MaxAreaY;
290 ele->CachedW = giWM_MaxAreaW;
291 ele->CachedH = giWM_MaxAreaH;
293 ele->Flags |= ELEFLAG_NOEXPAND|ELEFLAG_ABSOLUTEPOS|ELEFLAG_FIXEDSIZE;
294 WM_UpdateWindow(ele);
298 gWM_RootElement.CachedX = 0;
299 gWM_RootElement.CachedY = 0;
300 gWM_RootElement.CachedW = giScreenWidth;
301 gWM_RootElement.CachedH = giScreenHeight;
302 gWM_RootElement.Flags |= ELEFLAG_NOEXPAND|ELEFLAG_ABSOLUTEPOS|ELEFLAG_FIXEDSIZE;
304 WM_UpdateWindow( &gWM_RootElement );