AxWin2 - Minor commenting change
[tpg/acess2.git] / Usermode / Applications / axwin2_src / WM / render.c
1 /*
2  * Acess GUI (AxWin) Version 2
3  * By John Hodge (thePowersGang)
4  * 
5  * Rendering code
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     Decorator_RenderWidget(tElement *Element);
15 extern tElement gWM_RootElement;
16
17 // === PROTOTYPES ===
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);
22 void    WM_Update(void);
23
24 // === CODE ===
25 /**
26  * \brief Updates the dimensions of an element
27  * \todo What is the \a Pass parameter for
28  * 
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
31  * padding.
32  */
33 void WM_UpdateDimensions(tElement *Element, int Pass)
34 {
35         tElement        *child;
36          int    nChildren = 0;
37          int    nFixed = 0;
38          int    maxCross = 0;
39          int    fixedSize = 0;
40          int    fullCross, dynWith;
41         
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
46                 );
47         _SysDebug(" ->CachedW = %i, ->PaddingL = %i, ->PaddingR = %i",
48                 Element->CachedW, Element->PaddingL, Element->PaddingR
49                 );
50         
51         // Pass 1
52         for( child = Element->FirstChild; child; child = child->NextSibling )
53         {
54                 if( child->Flags & ELEFLAG_ABSOLUTEPOS )
55                         continue ;
56                 
57                 _SysDebug(" > %p'%s' ->FixedWith = %i", child, child->DebugName, child->FixedWith);
58                 if( child->FixedWith )
59                 {
60                         nFixed ++;
61                         fixedSize += child->FixedWith;
62                 }
63                 
64                 if( child->FixedCross && maxCross < child->FixedCross )
65                         maxCross = child->FixedCross;
66                 if( child->MinCross && maxCross < child->MinCross )
67                         maxCross = child->MinCross;
68                 nChildren ++;
69         }
70         
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
75                                 - Element->PaddingB;
76                 else
77                         dynWith = Element->CachedW - Element->PaddingL
78                                 - Element->PaddingR;
79                 dynWith -= fixedSize;
80                 if( dynWith < 0 )       return ;
81                 dynWith /= nChildren - nFixed;
82                 _SysDebug(" - dynWith = %i", dynWith);
83         }
84         
85         if( Element->Flags & ELEFLAG_VERTICAL )
86                 fullCross = Element->CachedW - Element->PaddingL - Element->PaddingR;
87         else
88                 fullCross = Element->CachedH - Element->PaddingT - Element->PaddingB;
89         
90         _SysDebug(" - fullCross = %i", Element, fullCross);
91         
92         // Pass 2 - Set sizes and recurse
93         for( child = Element->FirstChild; child; child = child->NextSibling )
94         {
95                  int    cross, with;
96                 
97                 _SysDebug(" > %p'%s' ->MinCross = %i", child, child->DebugName, child->MinCross);
98
99                 
100                 // --- Cross Size ---
101                 if( child->FixedCross )
102                         cross = child->FixedCross;
103                 // Expand to fill?
104                 // TODO: Extra flag so options are (Expand, Equal, Wrap)
105                 else if( child->Flags & ELEFLAG_NOEXPAND )
106                         cross = child->MinCross;
107                 else
108                         cross = fullCross;
109                 _SysDebug(" > %p'%s' - cross = %i", child, child->DebugName, cross);
110                 if( Element->Flags & ELEFLAG_VERTICAL )
111                         child->CachedW = cross;
112                 else
113                         child->CachedH = cross;
114                 
115                 // --- With Size ---
116                 if( child->FixedWith)
117                         with = child->FixedWith;
118                 else if( child->Flags & ELEFLAG_NOSTRETCH )
119                         with = child->MinWith;
120                 else
121                         with = dynWith;
122                 _SysDebug(" > %p'%s' - with = %i", child, child->DebugName, with);
123                 if( Element->Flags & ELEFLAG_VERTICAL )
124                         child->CachedH = with;
125                 else
126                         child->CachedW = with;
127                 
128                 WM_UpdateDimensions(child, Pass);
129         }
130         
131         _SysDebug("%p'%s' Done", Element, Element->DebugName);
132 }
133
134 /**
135  * \brief Updates the position of an element
136  * 
137  * The parent element sets the positions of its children
138  */
139 void WM_UpdatePosition(tElement *Element)
140 {
141         tElement        *child;
142          int    x, y;
143         static int      depth = 0;
144         char    indent[depth+1];
145         
146         if( Element->Flags & ELEFLAG_NORENDER ) return ;
147         
148         memset(indent, ' ', depth);
149         indent[depth] = '\0';
150         depth ++;
151         
152         _SysDebug("%sWM_UpdatePosition %p'%s'{PaddingL:%i, PaddingT:%i}",
153                 indent, Element, Element->DebugName, Element->PaddingL, Element->PaddingT);
154         
155         // Initialise
156         x = Element->CachedX + Element->PaddingL;
157         y = Element->CachedY + Element->PaddingT;
158         
159         _SysDebug("%s- Alignment = %s", indent,
160                 (Element->Flags & ELEFLAG_VERTICAL) ? "vertical" : "horizontal");
161
162         // Update each child
163         for(child = Element->FirstChild; child; child = child->NextSibling)
164         {
165                 _SysDebug("%s- x = %i, y = %i", indent, x, y);
166                 child->CachedX = x;
167                 child->CachedY = y;
168                 
169                 // Set Alignment
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;
174                         else
175                                 child->CachedY += Element->CachedH/2 - child->CachedH/2;
176                 }
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
182                                         - child->CachedW;
183                         else
184                                 child->CachedY += Element->CachedH
185                                         - Element->PaddingT
186                                         - Element->PaddingB
187                                         - child->CachedH;
188                 }
189                 
190                 _SysDebug("%s> %p'%s' at (%i,%i)", indent, child, child->DebugName,
191                         child->CachedX, child->CachedY);
192         
193                 // Update child's children positions
194                 WM_UpdatePosition(child);
195                 
196                 // Increment
197                 if(Element->Flags & ELEFLAG_VERTICAL ) {
198                         y += child->CachedH + Element->GapSize;
199                 }
200                 else {
201                         x += child->CachedW + Element->GapSize;
202                 }
203         }
204         
205         _SysDebug("%sElement %p'%s' (%i,%i)",
206                 indent, Element, Element->DebugName, Element->CachedX, Element->CachedY
207                 );
208         depth --;
209 }
210
211 /**
212  * \brief Update the minimum dimensions of the element
213  * \note Called after a child's minimum dimensions have changed
214  */
215 void WM_UpdateMinDims(tElement *Element)
216 {
217         tElement        *child;
218         
219         if(!Element)    return;
220         
221         Element->MinCross = 0;
222         Element->MinWith = 0;
223         
224         for(child = Element->FirstChild; child; child = child->NextSibling)
225         {
226                 if( Element->Parent &&
227                         (Element->Flags & ELEFLAG_VERTICAL) == (Element->Parent->Flags & ELEFLAG_VERTICAL)
228                         )
229                 {
230                         if(child->FixedCross)
231                                 Element->MinCross += child->FixedCross;
232                         else
233                                 Element->MinCross += child->MinCross;
234                         if(child->FixedWith)
235                                 Element->MinWith += child->FixedWith;
236                         else
237                                 Element->MinWith += child->MinWith;
238                 }
239                 else
240                 {
241                         if(child->FixedCross)
242                                 Element->MinWith += child->FixedCross;
243                         else
244                                 Element->MinWith += child->MinCross;
245                         if(child->FixedWith)
246                                 Element->MinCross += child->FixedWith;
247                         else
248                                 Element->MinCross += child->MinWith;
249                 }
250         }
251         
252         // Recurse upwards
253         WM_UpdateMinDims(Element->Parent);
254 }
255
256 // --- Render ---
257 void WM_RenderWidget(tElement *Element)
258 {
259         tElement        *child;
260         
261         if( Element->Flags & ELEFLAG_NORENDER ) return ;
262         if( Element->Flags & ELEFLAG_INVISIBLE )        return ;
263         
264         Decorator_RenderWidget(Element);
265         
266         for(child = Element->FirstChild; child; child = child->NextSibling)
267         {
268                 WM_RenderWidget(child);
269         }
270 }
271
272 void WM_Update(void)
273 {
274         gWM_RootElement.CachedX = 0;    gWM_RootElement.CachedY = 0;
275         gWM_RootElement.CachedW = giScreenWidth;
276         gWM_RootElement.CachedH = giScreenHeight;
277         gWM_RootElement.Flags |= ELEFLAG_NOEXPAND|ELEFLAG_ABSOLUTEPOS|ELEFLAG_FIXEDSIZE;
278         
279         WM_UpdateDimensions( &gWM_RootElement, 0 );
280         WM_UpdatePosition( &gWM_RootElement );
281         WM_RenderWidget( &gWM_RootElement );
282         
283         Video_Update();
284 }

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