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