Rockbox Utility: make the window icon also include a larger one.
[maemo-rb.git] / utils / themeeditor / graphics / rbviewport.cpp
blobfea1055935b6a09d079a9acddbf37cd186268adc
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2010 Robert Bieber
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include <QPainter>
23 #include <QPainterPath>
24 #include <QGraphicsSceneMouseEvent>
25 #include <QTransform>
27 #include <QDebug>
29 #include <cmath>
31 #include "rbviewport.h"
32 #include "rbscreen.h"
33 #include "rbrenderinfo.h"
34 #include "parsetreemodel.h"
35 #include "tag_table.h"
36 #include "skin_parser.h"
37 #include "skindocument.h"
39 /* Pixels/second of text scrolling */
40 const double RBViewport::scrollRate = 30;
42 RBViewport::RBViewport(skin_element* node, const RBRenderInfo& info,
43 ParseTreeNode* pNode)
44 : RBMovable(info.screen()), foreground(info.screen()->foreground()),
45 background(info.screen()->background()), textOffset(0,0),
46 screen(info.screen()), textAlign(Left), showStatusBar(false),
47 statusBarTexture(":/render/statusbar.png"),
48 leftGraphic(0), centerGraphic(0), rightGraphic(0), scrollTime(0),
49 node(pNode), doc(info.document())
52 if(!node->tag)
54 /* Default viewport takes up the entire screen */
55 size = QRectF(0, 0, info.screen()->getWidth(),
56 info.screen()->getHeight());
57 customUI = false;
58 font = screen->getFont(1);
60 screen->setDefault(this);
62 if(screen->getCustomUI())
64 RBViewport* cui = screen->getCustomUI();
65 size = cui->boundingRect();
66 setPos(cui->pos());
70 /* Making sure the default viewport can't be graphically manipulated */
71 setFlag(ItemIsSelectable, false);
72 setFlag(ItemIsMovable, false);
74 if(info.model()->rowCount(QModelIndex()) > 1)
76 /* If there is more than one viewport in the document */
77 textOffset.setX(-1);
79 else
81 setVisible(true);
84 else
86 QString ident;
87 int x,y,w,h;
88 /* Rendering one of the other types of viewport */
89 switch(node->tag->name[1])
91 case '\0':
92 customUI = false;
93 baseParam= 0;
94 break;
96 case 'l':
97 /* A preloaded viewport definition */
98 ident = node->params[0].data.text;
99 customUI = false;
100 if(!screen->viewPortDisplayed(ident))
101 hide();
102 info.screen()->loadViewport(ident, this);
103 baseParam= 1;
104 break;
106 case 'i':
107 /* Custom UI Viewport */
108 customUI = true;
109 baseParam= 1;
110 if(node->params[0].type == skin_tag_parameter::DEFAULT)
112 setVisible(true);
114 else
116 hide();
117 info.screen()->loadViewport(ident, this);
119 break;
121 /* Now we grab the info common to all viewports */
122 int param = baseParam;
123 x = node->params[param++].data.number;
124 if(x < 0)
125 x = info.screen()->boundingRect().right() + x;
126 y = node->params[param++].data.number;
127 if(y < 0)
128 y = info.screen()->boundingRect().bottom() + y;
130 if(node->params[param].type == skin_tag_parameter::DEFAULT)
131 w = info.screen()->getWidth() - x;
132 else
133 w = node->params[param].data.number;
134 if(w < 0)
135 w = info.screen()->getWidth() + w - x;
137 if(node->params[++param].type == skin_tag_parameter::DEFAULT)
138 h = info.screen()->getHeight() - y;
139 else
140 h = node->params[param].data.number;
141 if(h < 0)
142 h = info.screen()->getHeight() + h - y;
144 /* Adjusting to screen coordinates if necessary */
145 if(screen->parentItem() != 0)
147 x -= screen->parentItem()->pos().x();
148 y -= screen->parentItem()->pos().y();
151 if(node->params[++param].type == skin_tag_parameter::DEFAULT)
152 font = screen->getFont(1);
153 else
154 font = screen->getFont(node->params[param].data.number);
156 setPos(x, y);
157 size = QRectF(0, 0, w, h);
160 debug = info.device()->data("showviewports").toBool();
161 lineHeight = font->lineHeight();
163 if(info.screen()->isRtlMirrored() && info.device()->data("rtl").toBool())
165 /* Mirroring the viewport */
166 double x = screen->boundingRect().width() - 2 * pos().x();
167 QTransform t;
168 t.translate(x, 0);
169 t.scale(-1, 1);
170 setTransform(t);
173 if(customUI)
174 screen->setCustomUI(this);
177 RBViewport::~RBViewport()
181 QPainterPath RBViewport::shape() const
183 QPainterPath retval;
184 retval.addRect(size);
185 return retval;
188 void RBViewport::paint(QPainter *painter,
189 const QStyleOptionGraphicsItem *option, QWidget *widget)
191 if(!screen->hasBackdrop() && background != screen->background())
193 painter->fillRect(size, QBrush(background));
196 painter->setBrush(Qt::NoBrush);
197 painter->setPen(customUI ? Qt::blue : Qt::red);
198 if(debug)
199 painter->drawRect(size);
201 if(showStatusBar)
202 painter->fillRect(QRectF(0, 0, size.width(), 8), statusBarTexture);
204 RBMovable::paint(painter, option, widget);
207 void RBViewport::newLine()
209 if(textOffset.x() < 0)
210 return;
212 if(leftText != "")
213 alignLeft();
215 if(centerText != "")
216 alignCenter();
218 if(rightText != "")
219 alignRight();
221 textOffset.setY(textOffset.y() + lineHeight);
222 textOffset.setX(0);
223 textAlign = Left;
225 leftText.clear();
226 rightText.clear();
227 centerText.clear();
229 leftGraphic = 0;
230 centerGraphic = 0;
231 rightGraphic = 0;
233 scrollTime = 0;
236 void RBViewport::write(QString text)
238 if(textOffset.x() < 0)
239 return;
241 Alignment align = textAlign;
243 if(align == Left)
245 leftText.append(text);
247 else if(align == Center)
249 centerText.append(text);
251 else if(align == Right)
253 rightText.append(text);
257 void RBViewport::showPlaylist(const RBRenderInfo &info, int start,
258 ParseTreeNode* lines)
261 int song = start + info.device()->data("pp").toInt();
262 int numSongs = info.device()->data("pe").toInt();
264 while(song <= numSongs && textOffset.y() + lineHeight < size.height())
266 lines->render(info, this);
267 newLine();
268 song++;
272 void RBViewport::makeFullScreen()
274 size = screen->boundingRect();
275 setPos(screen->pos());
278 void RBViewport::saveGeometry()
280 QRectF bounds = boundingRect();
281 QPointF origin = pos();
283 node->modParam(static_cast<int>(origin.x()), baseParam);
284 node->modParam(static_cast<int>(origin.y()), baseParam + 1);
285 node->modParam(static_cast<int>(bounds.width()), baseParam + 2);
286 node->modParam(static_cast<int>(bounds.height()), baseParam + 3);
289 void RBViewport::alignLeft()
291 int y = textOffset.y();
293 if(leftGraphic)
294 delete leftGraphic;
296 leftGraphic = font->renderText(leftText, foreground, size.width(), this);
297 leftGraphic->setPos(0, y);
299 /* Setting scroll position if necessary */
300 int difference = leftGraphic->realWidth()
301 - leftGraphic->boundingRect().width();
302 if(difference > 0)
304 /* Subtracting out complete cycles */
305 double totalTime = 2 * difference / scrollRate;
306 scrollTime -= totalTime * std::floor(scrollTime / totalTime);
308 /* Calculating the offset */
309 if(scrollTime < static_cast<double>(difference) / scrollRate)
311 leftGraphic->setOffset(scrollRate * scrollTime);
313 else
315 scrollTime -= static_cast<double>(difference) / scrollRate;
316 leftGraphic->setOffset(difference - scrollRate * scrollTime);
321 void RBViewport::alignCenter()
323 int y = textOffset.y();
324 int x = 0;
326 if(centerGraphic)
327 delete centerGraphic;
329 centerGraphic = font->renderText(centerText, foreground, size.width(),
330 this);
332 if(centerGraphic->boundingRect().width() < size.width())
334 x = size.width() - centerGraphic->boundingRect().width();
335 x /= 2;
337 else
339 x = 0;
342 centerGraphic->setPos(x, y);
344 /* Setting scroll position if necessary */
345 int difference = centerGraphic->realWidth()
346 - centerGraphic->boundingRect().width();
347 if(difference > 0)
349 /* Subtracting out complete cycles */
350 double totalTime = 2 * difference / scrollRate;
351 scrollTime -= totalTime * std::floor(scrollTime / totalTime);
353 /* Calculating the offset */
354 if(scrollTime < static_cast<double>(difference) / scrollRate)
356 centerGraphic->setOffset(scrollRate * scrollTime);
358 else
360 scrollTime -= static_cast<double>(difference) / scrollRate;
361 centerGraphic->setOffset(difference - scrollRate * scrollTime);
367 void RBViewport::alignRight()
369 int y = textOffset.y();
370 int x = 0;
372 if(rightGraphic)
373 delete rightGraphic;
375 rightGraphic = font->renderText(rightText, foreground, size.width(), this);
377 if(rightGraphic->boundingRect().width() < size.width())
378 x = size.width() - rightGraphic->boundingRect().width();
379 else
380 x = 0;
382 rightGraphic->setPos(x, y);
384 /* Setting scroll position if necessary */
385 int difference = rightGraphic->realWidth()
386 - rightGraphic->boundingRect().width();
387 if(difference > 0)
389 /* Subtracting out complete cycles */
390 double totalTime = 2 * difference / scrollRate;
391 scrollTime -= totalTime * std::floor(scrollTime / totalTime);
393 /* Calculating the offset */
394 if(scrollTime < static_cast<double>(difference) / scrollRate)
396 rightGraphic->setOffset(scrollRate * scrollTime);
398 else
400 scrollTime -= static_cast<double>(difference) / scrollRate;
401 rightGraphic->setOffset(difference - scrollRate * scrollTime);