]> git.vomp.tv Git - vompclient.git/blob - boxx.cc
*** empty log message ***
[vompclient.git] / boxx.cc
1 /*
2     Copyright 2007 Chris Tallon
3
4     This file is part of VOMP.
5
6     VOMP is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     VOMP is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with VOMP; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19 */
20
21 #include "boxx.h"
22 #include "bitmap.h"
23 #include "log.h"
24
25 char Boxx::numBoxxes = 0;
26
27 Boxx::Boxx()
28 {
29   // I want a parent box or a surface.
30   parent = NULL;
31   surface = NULL;
32
33   area.x = 0;
34   area.y = 0;
35   area.w = 0;
36   area.h = 0;
37
38   paraVSpace = 6; // default gap for drawPara
39
40   backgroundColourSet = false;
41   visible = true;
42
43   numBoxxes++;
44   Log::getInstance()->log("Boxx", Log::DEBUG, "Construct, now %u", numBoxxes);
45 }
46
47 Boxx::~Boxx()
48 {
49   if (surface) delete surface;
50   numBoxxes--;
51   Log::getInstance()->log("Boxx", Log::DEBUG, "Destruct, now %u", numBoxxes);
52 }
53
54 void Boxx::draw()
55 {
56   //Log::getInstance()->log("Boxx", Log::DEBUG, "Draw this %p surface %p", this, surface);
57   if (backgroundColourSet) fillColour(backgroundColour);
58
59   Boxx* currentBoxx;
60   vector<Boxx*>::iterator j;
61   for (j = children.begin(); j != children.end(); j++)
62   {
63     currentBoxx = *j;
64     if (currentBoxx->getVisible()) currentBoxx->draw();
65   }  
66 }
67
68 void Boxx::setSize(UINT w, UINT h)
69 {
70   area.w = w;
71   area.h = h;
72 }
73
74 void Boxx::setPosition(UINT x, UINT y)
75 {
76   area.x = x;
77   area.y = y;
78 }
79
80 void Boxx::createBuffer()
81 {
82   surface = new Surface_TYPE();
83   surface->create(area.w, area.h);
84 }
85
86 void Boxx::add(Boxx* newChild)
87 {
88   newChild->setParent(this);
89   children.push_back(newChild);
90 }
91
92 void Boxx::remove(Boxx* oldChild)
93 {
94   for(vector<Boxx*>::iterator i = children.begin(); i != children.end(); i++)
95   {
96     if (*i == oldChild)
97     {
98       children.erase(i);
99       return;
100     }
101   }
102   Log::getInstance()->log("Boxx", Log::ERR, "Remove child box called, child %p not found", oldChild);
103 }
104
105 void Boxx::setParent(Boxx* newParent)
106 {
107   parent = newParent;
108 }
109
110 void Boxx::setBackgroundColour(const Colour& Tcolour)
111 {
112   backgroundColour = Tcolour;
113   backgroundColourSet = true;
114 }
115
116 void Boxx::setVisible(bool isVisible)
117 {
118   visible = isVisible;
119 }
120
121 bool Boxx::getVisible()
122 {
123   return visible;
124 }
125
126 void Boxx::setGap(UINT gap)
127 {
128   paraVSpace = gap;
129 }
130
131 void Boxx::blt(Region& r)
132 {
133   /* surface update to screen needs:
134   source x distance into this surface
135   source y distance into this surface
136   width of update
137   height of update
138   destination x on screen
139   destination y on screen
140   */
141
142   if (parent) abort(); // if (parent) then this is a child boxx. It can not blt.
143
144   // this shouldn't be here
145   r.x -= area.x;
146   r.y -= area.y;
147
148   surface->updateToScreen(r.x, r.y, r.w, r.h, area.x + r.x, area.y + r.y);
149   
150 }
151
152 int Boxx::getScreenX()
153 {
154   if (parent) return area.x + parent->getScreenX();
155   return area.x;
156 }
157
158 int Boxx::getScreenY()
159 {
160   if (parent) return area.y + parent->getScreenY();
161   return area.y;
162 }
163
164 int Boxx::getRootBoxOffsetX()  // convert this to be getX and silently do the parent/not thing? same for Y below?
165 {
166   if (parent) return area.x + parent->getRootBoxOffsetX();
167   return 0;
168 }
169
170 int Boxx::getRootBoxOffsetY()
171 {
172   if (parent) return area.y + parent->getRootBoxOffsetY();
173   return 0;
174 }
175
176 int Boxx::getX()
177 {
178   return area.x;
179 }
180
181 int Boxx::getY()
182 {
183   return area.y;
184 }
185
186 int Boxx::getX2()
187 {
188   return area.x + area.w;
189 }
190
191 int Boxx::getY2()
192 {
193   return area.y + area.h;
194 }
195
196 UINT Boxx::getWidth()
197 {
198   return area.w;
199 }
200
201 UINT Boxx::getHeight()
202 {
203   return area.h;
204 }
205
206 // FIXME Clean up the code to use just one of the following
207
208 Region* Boxx::getRegion()
209 {
210   return &area;
211 }
212
213 Region Boxx::getRegionR()
214 {
215   return area;
216 }
217
218 void Boxx::getRootBoxRegion(Region* r)
219 {
220   // Returns a region that describes the position of this box on the box with the surface
221   // To be used for boxstack->update calls
222
223   r->x = getRootBoxOffsetX();
224   r->y = getRootBoxOffsetY();
225   r->w = area.w;
226   r->h = area.h;  
227 }
228
229 // Level 1 drawing functions
230
231 void Boxx::fillColour(const Colour& colour)
232 {
233   rectangle(0, 0, area.w, area.h, colour);
234 }
235
236 void Boxx::drawPara(const char* text, int x, int y, const Colour& colour)
237 {
238   char line[256];
239   int lineHeight = surface->getFontHeight() + paraVSpace;
240
241   int lineWidth;
242   int thisCharWidth;
243   int textPos;
244   int linePos;
245   int ypos;
246   int printLine;
247
248   textPos = 0;
249   ypos = y;
250
251   while(1)
252   {
253     linePos = 0;
254     lineWidth = 0;
255     while(1)
256     {
257       printLine = 0;
258
259       if (text[textPos] == '\0') break;
260
261       if (text[textPos] == '\n')
262       {
263         textPos++; // ignore the \n
264         printLine = 1;
265         break;
266       }
267
268       thisCharWidth = surface->getCharWidth(text[textPos]);
269       if ((lineWidth + thisCharWidth) > (int)(area.w - (2 * paraMargin)))
270       {
271         // this character would break the right margin
272         if (text[textPos] == ' ')
273         {
274           // this char is a space, ignore and break
275           textPos++;
276           break;
277         }
278         else
279         {
280           // Need to go back to the last space in the line
281           while ((text[textPos] != ' ') && (linePos >= 0))
282           {
283             textPos--;
284             linePos--;
285           }
286           // Now take the space we just found
287           textPos++;
288           break;
289         }
290       }
291       line[linePos++] = text[textPos];
292       lineWidth += thisCharWidth;
293       textPos++;
294     }
295
296 //    line[linePos++] = '\0';
297     if (linePos>=0) line[linePos++] = '\0'; //Here is the change
298
299     if (printLine || (linePos > 1)) // if some text was put in line
300     {
301       drawText(line, x, ypos, colour);
302       ypos += lineHeight;
303       if (ypos > (int)(area.h - lineHeight)) break;
304     }
305     else
306     {
307       break;
308     }
309   }
310 }
311
312 void Boxx::rectangle(Region& region, const Colour& colour)
313 {
314   rectangle(region.x, region.y, region.w, region.h, colour);
315 }
316
317 // Level 0 drawing functions
318
319 void Boxx::rectangle(UINT x, UINT y, UINT w, UINT h, const Colour& colour)
320 {
321   if (parent) parent->rectangle(area.x + x, area.y + y, w, h, colour);
322   else surface->fillblt(x, y, w, h, colour.rgba());
323 }
324
325 void Boxx::drawText(const char* text, int x, int y, const Colour& colour)
326 {
327   if (parent) parent->drawText(text, area.x + x, area.y + y, colour);
328   else surface->drawText(text, x, y, colour.rgba());
329 }
330
331 void Boxx::drawText(const char* text, int x, int y, int width, const Colour& colour)
332 {
333   if (parent) parent->drawText(text, area.x + x, area.y + y, width, colour);
334   else surface->drawText(text, x, y, width, colour.rgba());
335 }
336
337 void Boxx::drawTextRJ(const char* text, int x, int y, const Colour& colour)
338 {
339   if (parent) parent->drawTextRJ(text, area.x + x, area.y + y, colour);
340   else surface->drawTextRJ(text, x, y, colour.rgba());
341 }
342
343 void Boxx::drawTextCentre(const char* text, int x, int y, const Colour& colour)
344 {
345   if (parent) parent->drawTextCentre(text, area.x + x, area.y + y, colour);
346   else surface->drawTextCentre(text, x, y, colour.rgba());
347 }
348
349 void Boxx::drawPixelAlpha(UINT x, UINT y, const Colour& colour,bool fastdraw)
350 {
351   if (parent) parent->drawPixelAlpha(area.x + x, area.y + y, colour,fastdraw);
352   else
353   {
354     int c = (  (colour.alpha << 24 )
355              | (colour.red    << 16)
356              | (colour.green  <<  8)
357              | (colour.blue        ) );
358
359     surface->drawPixel(x, y, c,fastdraw);
360   }
361 }
362
363 void Boxx::drawPixel(UINT x, UINT y, const Colour& colour, bool fastdraw)
364 {
365   if (parent) parent->drawPixel(area.x + x, area.y + y, colour,fastdraw);
366   else
367   {
368     int c = (  (0xFF000000         )
369              | (colour.red    << 16)
370              | (colour.green  <<  8)
371              | (colour.blue        ) );
372
373     surface->drawPixel(x, y, c,fastdraw);
374   }
375 }
376 void Boxx::drawBitmap(UINT x, UINT y, const Bitmap& bm)
377 {
378   if (parent) parent->drawBitmap(area.x + x, area.y + y, bm);
379   else surface->drawBitmap(x, y, bm);
380 }
381
382 void Boxx::startFastDraw()
383 {
384     if (parent) parent->startFastDraw();
385     else
386     {
387         surface->startFastDraw();
388     }
389 }
390
391 void Boxx::endFastDraw()
392 {
393     if (parent) parent->endFastDraw();
394     else
395     {
396         surface->endFastDraw();
397     }
398 }
399  
400
401 int Boxx::charWidth(char c)
402 {
403   if (parent) return parent->charWidth(c);
404   else return surface->getCharWidth(c);
405 }
406
407 Surface * Boxx::getSurface() {
408   if (parent) return parent->getSurface();
409   return surface;
410 }
411