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