Usermode/AxWin3 - Added keysyms (symlink to kernel version)
[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 extern tApplication     *gWM_Applications;
17 extern int      giWM_MaxAreaX;
18 extern int      giWM_MaxAreaY;
19 extern int      giWM_MaxAreaW;
20 extern int      giWM_MaxAreaH;
21
22 // === PROTOTYPES ===
23 void    WM_UpdateMinDims(tElement *Element);
24 void    WM_UpdateDimensions(tElement *Element, int Pass);
25 void    WM_UpdatePosition(tElement *Element);
26 void    WM_RenderWidget(tElement *Element);
27 void    WM_Update(void);
28
29 // === CODE ===
30 /**
31  * \brief Updates the dimensions of an element
32  * \todo What is the \a Pass parameter for
33  * 
34  * The dimensions of an element are calculated from the parent's
35  * cross dimension (the side at right angles to the alignment) sans some
36  * padding.
37  */
38 void WM_UpdateDimensions(tElement *Element, int Pass)
39 {
40         tElement        *child;
41          int    nChildren = 0;
42          int    nFixed = 0;
43          int    maxCross = 0;
44          int    fixedSize = 0;
45          int    fullCross, dynWith;
46         
47         _SysDebug("WM_UpdateDimensions %p'%s'", Element, Element->DebugName);
48         _SysDebug(" -> Flags = 0x%x", Element->Flags);
49         _SysDebug(" ->CachedH = %i, ->PaddingT = %i, ->PaddingB = %i",
50                 Element->CachedH, Element->PaddingT, Element->PaddingB
51                 );
52         _SysDebug(" ->CachedW = %i, ->PaddingL = %i, ->PaddingR = %i",
53                 Element->CachedW, Element->PaddingL, Element->PaddingR
54                 );
55         
56         // Pass 1
57         for( child = Element->FirstChild; child; child = child->NextSibling )
58         {
59                 if( child->Flags & ELEFLAG_ABSOLUTEPOS )
60                         continue ;
61                 
62                 _SysDebug(" > %p'%s' ->FixedWith = %i", child, child->DebugName, child->FixedWith);
63                 if( child->FixedWith )
64                 {
65                         nFixed ++;
66                         fixedSize += child->FixedWith;
67                 }
68                 
69                 if( child->FixedCross && maxCross < child->FixedCross )
70                         maxCross = child->FixedCross;
71                 if( child->MinCross && maxCross < child->MinCross )
72                         maxCross = child->MinCross;
73                 nChildren ++;
74         }
75         
76         _SysDebug(" - nChildren = %i, nFixed = %i", Element, nChildren, nFixed);
77         if( nChildren > nFixed ) {
78                 if( Element->Flags & ELEFLAG_VERTICAL )
79                         dynWith = Element->CachedH - Element->PaddingT
80                                 - Element->PaddingB;
81                 else
82                         dynWith = Element->CachedW - Element->PaddingL
83                                 - Element->PaddingR;
84                 dynWith -= fixedSize;
85                 if( dynWith < 0 )       return ;
86                 dynWith /= nChildren - nFixed;
87                 _SysDebug(" - dynWith = %i", dynWith);
88         }
89         
90         if( Element->Flags & ELEFLAG_VERTICAL )
91                 fullCross = Element->CachedW - Element->PaddingL - Element->PaddingR;
92         else
93                 fullCross = Element->CachedH - Element->PaddingT - Element->PaddingB;
94         
95         _SysDebug(" - fullCross = %i", Element, fullCross);
96         
97         // Pass 2 - Set sizes and recurse
98         for( child = Element->FirstChild; child; child = child->NextSibling )
99         {
100                  int    cross, with;
101                 
102                 _SysDebug(" > %p'%s' ->MinCross = %i", child, child->DebugName, child->MinCross);
103
104                 
105                 // --- Cross Size ---
106                 if( child->FixedCross )
107                         cross = child->FixedCross;
108                 // Expand to fill?
109                 // TODO: Extra flag so options are (Expand, Equal, Wrap)
110                 else if( child->Flags & ELEFLAG_NOEXPAND )
111                         cross = child->MinCross;
112                 else
113                         cross = fullCross;
114                 _SysDebug(" > %p'%s' - cross = %i", child, child->DebugName, cross);
115                 if( Element->Flags & ELEFLAG_VERTICAL )
116                         child->CachedW = cross;
117                 else
118                         child->CachedH = cross;
119                 
120                 // --- With Size ---
121                 if( child->FixedWith)
122                         with = child->FixedWith;
123                 else if( child->Flags & ELEFLAG_NOSTRETCH )
124                         with = child->MinWith;
125                 else
126                         with = dynWith;
127                 _SysDebug(" > %p'%s' - with = %i", child, child->DebugName, with);
128                 if( Element->Flags & ELEFLAG_VERTICAL )
129                         child->CachedH = with;
130                 else
131                         child->CachedW = with;
132                 
133                 WM_UpdateDimensions(child, Pass);
134         }
135         
136         _SysDebug("%p'%s' Done", Element, Element->DebugName);
137 }
138
139 /**
140  * \brief Updates the position of an element
141  * 
142  * The parent element sets the positions of its children
143  */
144 void WM_UpdatePosition(tElement *Element)
145 {
146         tElement        *child;
147          int    x, y;
148         static int      depth = 0;
149         char    indent[depth+1];
150         
151         if( Element->Flags & ELEFLAG_NORENDER ) return ;
152         
153         memset(indent, ' ', depth);
154         indent[depth] = '\0';
155         depth ++;
156         
157         _SysDebug("%sWM_UpdatePosition %p'%s'{PaddingL:%i, PaddingT:%i}",
158                 indent, Element, Element->DebugName, Element->PaddingL, Element->PaddingT);
159         
160         // Initialise
161         x = Element->CachedX + Element->PaddingL;
162         y = Element->CachedY + Element->PaddingT;
163         
164         _SysDebug("%s- Alignment = %s", indent,
165                 (Element->Flags & ELEFLAG_VERTICAL) ? "vertical" : "horizontal");
166
167         // Update each child
168         for(child = Element->FirstChild; child; child = child->NextSibling)
169         {
170                 _SysDebug("%s- x = %i, y = %i", indent, x, y);
171                 child->CachedX = x;
172                 child->CachedY = y;
173                 
174                 // Set Alignment
175                 if( Element->Flags & ELEFLAG_ALIGN_CENTER ) {
176                         _SysDebug("%sChild being aligned to center", indent);
177                         if(Element->Flags & ELEFLAG_VERTICAL)
178                                 child->CachedX += Element->CachedW/2 - child->CachedW/2;
179                         else
180                                 child->CachedY += Element->CachedH/2 - child->CachedH/2;
181                 }
182                 else if( Element->Flags & ELEFLAG_ALIGN_END) {
183                         _SysDebug("%sChild being aligned to end", indent);
184                         if(Element->Flags & ELEFLAG_VERTICAL )
185                                 child->CachedX += Element->CachedW
186                                         - Element->PaddingL - Element->PaddingR
187                                         - child->CachedW;
188                         else
189                                 child->CachedY += Element->CachedH
190                                         - Element->PaddingT
191                                         - Element->PaddingB
192                                         - child->CachedH;
193                 }
194                 
195                 _SysDebug("%s> %p'%s' at (%i,%i)", indent, child, child->DebugName,
196                         child->CachedX, child->CachedY);
197         
198                 // Update child's children positions
199                 WM_UpdatePosition(child);
200                 
201                 // Increment
202                 if(Element->Flags & ELEFLAG_VERTICAL ) {
203                         y += child->CachedH + Element->GapSize;
204                 }
205                 else {
206                         x += child->CachedW + Element->GapSize;
207                 }
208         }
209         
210         _SysDebug("%sElement %p'%s' (%i,%i)",
211                 indent, Element, Element->DebugName, Element->CachedX, Element->CachedY
212                 );
213         depth --;
214 }
215
216 /**
217  * \brief Update the minimum dimensions of the element
218  * \note Called after a child's minimum dimensions have changed
219  */
220 void WM_UpdateMinDims(tElement *Element)
221 {
222         tElement        *child;
223         
224         if(!Element)    return;
225         
226         Element->MinCross = 0;
227         Element->MinWith = 0;
228         
229         for(child = Element->FirstChild; child; child = child->NextSibling)
230         {
231                 if( Element->Parent &&
232                         (Element->Flags & ELEFLAG_VERTICAL) == (Element->Parent->Flags & ELEFLAG_VERTICAL)
233                         )
234                 {
235                         if(child->FixedCross)
236                                 Element->MinCross += child->FixedCross;
237                         else
238                                 Element->MinCross += child->MinCross;
239                         if(child->FixedWith)
240                                 Element->MinWith += child->FixedWith;
241                         else
242                                 Element->MinWith += child->MinWith;
243                 }
244                 else
245                 {
246                         if(child->FixedCross)
247                                 Element->MinWith += child->FixedCross;
248                         else
249                                 Element->MinWith += child->MinCross;
250                         if(child->FixedWith)
251                                 Element->MinCross += child->FixedWith;
252                         else
253                                 Element->MinCross += child->MinWith;
254                 }
255         }
256         
257         // Recurse upwards
258         WM_UpdateMinDims(Element->Parent);
259 }
260
261 // --- Render ---
262 void WM_RenderWidget(tElement *Element)
263 {
264         tElement        *child;
265         
266         if( Element->Flags & ELEFLAG_NORENDER ) return ;
267         if( Element->Flags & ELEFLAG_INVISIBLE )        return ;
268         
269         Decorator_RenderWidget(Element);
270         
271         for(child = Element->FirstChild; child; child = child->NextSibling)
272         {
273                 WM_RenderWidget(child);
274         }
275 }
276
277 void WM_UpdateWindow(tElement *Ele)
278 {       
279         WM_UpdateDimensions( Ele, 0 );
280         WM_UpdatePosition( Ele );
281         WM_RenderWidget( Ele );
282 }
283
284 void WM_Update(void)
285 {
286         tApplication    *app;
287         tElement        *ele;
288         
289         for( app = gWM_Applications; app; app = app->Next )
290         {
291                 for( ele = app->MetaElement.FirstChild; ele; ele = ele->NextSibling ) {
292                         if( ele->Flags & ELEFLAG_WINDOW_MAXIMISED ) {
293                                 ele->CachedX = giWM_MaxAreaX;
294                                 ele->CachedY = giWM_MaxAreaY;
295                                 ele->CachedW = giWM_MaxAreaW;
296                                 ele->CachedH = giWM_MaxAreaH;
297                         }
298                         ele->Flags |= ELEFLAG_NOEXPAND|ELEFLAG_ABSOLUTEPOS|ELEFLAG_FIXEDSIZE;
299                         WM_UpdateWindow(ele);
300                 }
301         }
302         
303         gWM_RootElement.CachedX = 0;
304         gWM_RootElement.CachedY = 0;
305         gWM_RootElement.CachedW = giScreenWidth;
306         gWM_RootElement.CachedH = giScreenHeight;
307         gWM_RootElement.Flags |= ELEFLAG_NOEXPAND|ELEFLAG_ABSOLUTEPOS|ELEFLAG_FIXEDSIZE;
308         
309         WM_UpdateWindow( &gWM_RootElement );
310         
311         Video_Update();
312 }

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