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