00001 #include <iostream>
00002 using namespace std;
00003
00004 #include <qfontmetrics.h>
00005
00006 #include "mythuitype.h"
00007 #include "mythimage.h"
00008 #include "mythpainter.h"
00009 #include "mythmainwindow.h"
00010 #include "mythfontproperties.h"
00011
00012 #include "mythcontext.h"
00013
00014 MythUIType::MythUIType(QObject *parent, const char *name)
00015 : QObject(parent, name)
00016 {
00017 m_Visible = true;
00018 m_CanHaveFocus = m_HasFocus = false;
00019 m_Area = QRect(0, 0, 0, 0);
00020 m_NeedsRedraw = false;
00021 m_Alpha = 255;
00022 m_AlphaChangeMode = m_AlphaChange = m_AlphaMin = 0;
00023 m_AlphaMax = 255;
00024 m_Moving = false;
00025 m_XYDestination = QPoint(0, 0);
00026 m_XYSpeed = QPoint(0, 0);
00027
00028 m_Parent = NULL;
00029 if (parent)
00030 {
00031 m_Parent = dynamic_cast<MythUIType *>(parent);
00032 if (m_Parent)
00033 m_Parent->AddChild(this);
00034 }
00035
00036 m_DirtyRegion = QRegion(QRect(0, 0, 0, 0));
00037
00038 m_Fonts = new FontMap();
00039 }
00040
00041 MythUIType::~MythUIType()
00042 {
00043 delete m_Fonts;
00044 }
00045
00046 void MythUIType::AddChild(MythUIType *child)
00047 {
00048 if (!child)
00049 {
00050 return;
00051 }
00052
00053 m_ChildrenList.push_back(child);
00054 }
00055
00056 MythUIType *MythUIType::GetChild(const char *name, const char *inherits)
00057 {
00058 QObject *ret = child(name, inherits);
00059 if (ret)
00060 return dynamic_cast<MythUIType *>(ret);
00061 return NULL;
00062 }
00063
00064 QValueVector<MythUIType *> *MythUIType::GetAllChildren(void)
00065 {
00066 return &m_ChildrenList;
00067 }
00068
00069 void MythUIType::DeleteAllChildren(void)
00070 {
00071 QValueVector<MythUIType*>::iterator it;
00072 for (it = m_ChildrenList.begin(); it != m_ChildrenList.end(); ++it)
00073 {
00074 (*it)->deleteLater();
00075 }
00076
00077 m_ChildrenList.clear();
00078 }
00079
00087 MythUIType *MythUIType::GetChildAt(const QPoint &p)
00088 {
00089 if (GetArea().contains(p))
00090 {
00091
00092
00093 if (CanTakeFocus() && IsVisible())
00094 return this;
00095
00096 if (m_ChildrenList.isEmpty())
00097 return NULL;
00098
00099
00100 QValueVector<MythUIType*>::iterator it;
00101 for (it = m_ChildrenList.end()-1; it != m_ChildrenList.begin()-1; it--)
00102 {
00103 MythUIType *child = (*it)->GetChildAt(p - GetArea().topLeft());
00104 if (child != NULL)
00105 {
00106 return child;
00107 }
00108 }
00109 }
00110 return NULL;
00111 }
00112
00113 bool MythUIType::NeedsRedraw(void)
00114 {
00115 return m_NeedsRedraw;
00116 }
00117
00118 void MythUIType::SetRedraw(void)
00119 {
00120 if (m_Area.width() == 0 || m_Area.height() == 0)
00121 return;
00122
00123 m_NeedsRedraw = true;
00124
00125 if (m_DirtyRegion.isEmpty())
00126 m_DirtyRegion = QRegion(m_Area);
00127 else
00128 m_DirtyRegion = m_DirtyRegion.unite(QRegion(m_Area));
00129
00130 if (m_Parent)
00131 m_Parent->SetChildNeedsRedraw(this);
00132 }
00133
00134 void MythUIType::SetChildNeedsRedraw(MythUIType *child)
00135 {
00136 QRegion childRegion = child->GetDirtyArea();
00137 if (childRegion.isEmpty())
00138 return;
00139
00140 childRegion.translate(m_Area.x(), m_Area.y());
00141
00142 m_NeedsRedraw = true;
00143
00144 if (m_DirtyRegion.isEmpty())
00145 m_DirtyRegion = childRegion;
00146 else
00147 m_DirtyRegion = m_DirtyRegion.unite(childRegion);
00148
00149 if (m_Parent)
00150 m_Parent->SetChildNeedsRedraw(this);
00151 }
00152
00153 bool MythUIType::CanTakeFocus(void)
00154 {
00155 return m_CanHaveFocus;
00156 }
00157
00158 void MythUIType::SetCanTakeFocus(bool set)
00159 {
00160 m_CanHaveFocus = set;
00161 }
00162
00163 void MythUIType::HandleMovementPulse(void)
00164 {
00165 if (!GetMythPainter()->SupportsAnimation())
00166 return;
00167
00168 if (!m_Moving)
00169 return;
00170
00171 QPoint curXY = m_Area.topLeft();
00172 m_DirtyRegion = m_Area;
00173
00174 int xdir = m_XYDestination.x() - curXY.x();
00175 int ydir = m_XYDestination.y() - curXY.y();
00176
00177 curXY.setX(curXY.x() + m_XYSpeed.x());
00178 curXY.setY(curXY.y() + m_XYSpeed.y());
00179
00180 if ((xdir > 0 && curXY.x() >= m_XYDestination.x()) ||
00181 (xdir < 0 && curXY.x() <= m_XYDestination.x()) ||
00182 (xdir == 0))
00183 {
00184 m_XYSpeed.setX(0);
00185 }
00186
00187 if ((ydir > 0 && curXY.y() >= m_XYDestination.y()) ||
00188 (ydir <= 0 && curXY.y() <= m_XYDestination.y()) ||
00189 (ydir == 0))
00190 {
00191 m_XYSpeed.setY(0);
00192 }
00193
00194 SetRedraw();
00195
00196 if (m_XYSpeed.x() == 0 && m_XYSpeed.y() == 0)
00197 {
00198 m_Moving = false;
00199 emit FinishedMoving();
00200 }
00201
00202 m_Area.moveTopLeft(curXY);
00203 }
00204
00205 void MythUIType::HandleAlphaPulse(void)
00206 {
00207 if (!GetMythPainter()->SupportsAlpha())
00208 return;
00209
00210 if (m_AlphaChangeMode == 0)
00211 return;
00212
00213 m_Alpha += m_AlphaChange;
00214 if (m_Alpha > 255)
00215 m_Alpha = 255;
00216 if (m_Alpha < 0)
00217 m_Alpha = 0;
00218
00219 if (m_Alpha >= m_AlphaMax || m_Alpha <= m_AlphaMin)
00220 {
00221 if (m_AlphaChangeMode == 2)
00222 {
00223 m_AlphaChange *= -1;
00224 }
00225 else
00226 {
00227 m_AlphaChangeMode = 0;
00228 m_AlphaChange = 0;
00229 }
00230 }
00231
00232 SetRedraw();
00233 }
00234
00235 void MythUIType::Pulse(void)
00236 {
00237 HandleMovementPulse();
00238 HandleAlphaPulse();
00239
00240 QValueVector<MythUIType *>::Iterator it;
00241 for (it = m_ChildrenList.begin(); it != m_ChildrenList.end(); ++it)
00242 (*it)->Pulse();
00243 }
00244
00245 int MythUIType::CalcAlpha(int alphamod)
00246 {
00247 return (int)(m_Alpha * (alphamod / 255.0));
00248 }
00249
00250 void MythUIType::DrawSelf(MythPainter *, int, int, int, QRect)
00251 {
00252 }
00253
00254 void MythUIType::Draw(MythPainter *p, int xoffset, int yoffset, int alphaMod,
00255 QRect clipRect)
00256 {
00257 m_NeedsRedraw = false;
00258 m_DirtyRegion = QRegion(QRect(0, 0, 0, 0));
00259
00260 if (!m_Visible)
00261 return;
00262
00263 QRect realArea = m_Area;
00264 realArea.moveBy(xoffset, yoffset);
00265
00266 if (!realArea.intersects(clipRect))
00267 return;
00268
00269 DrawSelf(p, xoffset, yoffset, alphaMod, clipRect);
00270
00271 QValueVector<MythUIType *>::Iterator it;
00272 for (it = m_ChildrenList.begin(); it != m_ChildrenList.end(); ++it)
00273 {
00274 (*it)->Draw(p, xoffset + m_Area.x(), yoffset + m_Area.y(),
00275 CalcAlpha(alphaMod), clipRect);
00276 }
00277 }
00278
00279 void MythUIType::SetPosition(int x, int y)
00280 {
00281 SetPosition(QPoint(x, y));
00282 }
00283
00284 void MythUIType::SetPosition(const QPoint &pos)
00285 {
00286 if (m_Area.topLeft() == pos)
00287 return;
00288
00289 m_DirtyRegion = m_Area;
00290
00291 m_Area.moveTopLeft(pos);
00292 SetRedraw();
00293 }
00294
00295 void MythUIType::SetArea(const QRect &rect)
00296 {
00297 if (rect == m_Area)
00298 return;
00299
00300 m_DirtyRegion = m_Area;
00301
00302 m_Area = rect;
00303 SetRedraw();
00304 }
00305
00306 QRect MythUIType::GetArea(void) const
00307 {
00308 return m_Area;
00309 }
00310
00311 QRegion MythUIType::GetDirtyArea(void) const
00312 {
00313 return m_DirtyRegion;
00314 }
00315
00316 QString MythUIType::cutDown(const QString &data, QFont *font,
00317 bool multiline, int overload_width,
00318 int overload_height)
00319 {
00320 int length = data.length();
00321 if (length == 0)
00322 return data;
00323
00324 int maxwidth = m_Area.width();
00325 if (overload_width != -1)
00326 maxwidth = overload_width;
00327 int maxheight = m_Area.height();
00328 if (overload_height != -1)
00329 maxheight = overload_height;
00330
00331 int justification = Qt::AlignLeft | Qt::WordBreak;
00332 QFontMetrics fm(*font);
00333
00334 int margin = length - 1;
00335 int index = 0;
00336 int diff = 0;
00337
00338 while (margin > 0)
00339 {
00340 if (multiline)
00341 diff = maxheight - fm.boundingRect(0, 0, maxwidth, maxheight,
00342 justification, data,
00343 index + margin).height();
00344 else
00345 diff = maxwidth - fm.width(data, index + margin);
00346 if (diff >= 0)
00347 index += margin;
00348
00349 margin /= 2;
00350
00351 if (index + margin >= length - 1)
00352 margin = (length - 1) - index;
00353 }
00354
00355 if (index < length - 1)
00356 {
00357 QString tmpStr(data);
00358 tmpStr.truncate(index);
00359 if (index >= 3)
00360 tmpStr.replace(index - 3, 3, "...");
00361 return tmpStr;
00362 }
00363
00364 return data;
00365
00366 }
00367
00368 bool MythUIType::IsVisible(void)
00369 {
00370 return m_Visible;
00371 }
00372
00373 void MythUIType::MoveTo(QPoint destXY, QPoint speedXY)
00374 {
00375 if (!GetMythPainter()->SupportsAnimation())
00376 return;
00377
00378 if (destXY.x() == m_Area.x() && destXY.y() == m_Area.y())
00379 return;
00380
00381 m_Moving = true;
00382
00383 m_XYDestination = destXY;
00384 m_XYSpeed = speedXY;
00385 }
00386
00387 void MythUIType::AdjustAlpha(int mode, int alphachange, int minalpha,
00388 int maxalpha)
00389 {
00390 if (!GetMythPainter()->SupportsAlpha())
00391 return;
00392
00393 m_AlphaChangeMode = mode;
00394 m_AlphaChange = alphachange;
00395 m_AlphaMin = minalpha;
00396 m_AlphaMax = maxalpha;
00397
00398 if (m_Alpha > m_AlphaMax)
00399 m_Alpha = m_AlphaMax;
00400 if (m_Alpha < m_AlphaMin)
00401 m_Alpha = m_AlphaMin;
00402 }
00403
00404 void MythUIType::SetAlpha(int newalpha)
00405 {
00406 m_Alpha = newalpha;
00407 SetRedraw();
00408 }
00409
00410 int MythUIType::GetAlpha(void)
00411 {
00412 return m_Alpha;
00413 }
00414
00415 bool MythUIType::keyPressEvent(QKeyEvent *)
00416 {
00417 return false;
00418 }
00419
00420 void MythUIType::customEvent(QCustomEvent *)
00421 {
00422 return;
00423 }
00424
00425 void MythUIType::gestureEvent(MythUIType *origtype, MythGestureEvent *ge)
00426 {
00427 if (m_Parent)
00428 m_Parent->gestureEvent(origtype, ge);
00429 }
00430
00431 void MythUIType::LoseFocus(void)
00432 {
00433 if (!m_CanHaveFocus || !m_HasFocus)
00434 return;
00435
00436 emit LosingFocus();
00437 m_HasFocus = false;
00438 Refresh();
00439 }
00440
00441 bool MythUIType::TakeFocus(void)
00442 {
00443 if (!m_CanHaveFocus || m_HasFocus)
00444 return false;
00445
00446 m_HasFocus = true;
00447 Refresh();
00448 emit TakingFocus();
00449 return true;
00450 }
00451
00452 void MythUIType::Activate(void)
00453 {
00454 }
00455
00456 void MythUIType::Refresh(void)
00457 {
00458 SetRedraw();
00459 }
00460
00461 void MythUIType::SetVisible(bool visible)
00462 {
00463 if (visible != m_Visible)
00464 {
00465 m_Visible = visible;
00466 SetRedraw();
00467 }
00468 }
00469
00470 void MythUIType::Hide(void)
00471 {
00472 m_Visible = false;
00473 SetRedraw();
00474 emit Hiding();
00475 }
00476
00477 void MythUIType::Show(void)
00478 {
00479 m_Visible = true;
00480 SetRedraw();
00481 emit Showing();
00482 }
00483
00484 void MythUIType::AddFocusableChildrenToList(QPtrList<MythUIType> &focusList)
00485 {
00486 if (m_CanHaveFocus)
00487 focusList.append(this);
00488
00489 QValueVector<MythUIType *>::Iterator it;
00490 for (it = m_ChildrenList.begin(); it != m_ChildrenList.end(); ++it)
00491 (*it)->AddFocusableChildrenToList(focusList);
00492 }
00493
00494 QFont MythUIType::CreateQFont(const QString &face, int pointSize,
00495 int weight, bool italic)
00496 {
00497 return GetMythMainWindow()->CreateQFont(face, pointSize, weight, italic);
00498 }
00499
00500 QRect MythUIType::NormRect(const QRect &rect)
00501 {
00502 return GetMythMainWindow()->NormRect(rect);
00503 }
00504
00505 QPoint MythUIType::NormPoint(const QPoint &point)
00506 {
00507 return GetMythMainWindow()->NormPoint(point);
00508 }
00509
00510 int MythUIType::NormX(const int x)
00511 {
00512 return GetMythMainWindow()->NormX(x);
00513 }
00514
00515 int MythUIType::NormY(const int y)
00516 {
00517 return GetMythMainWindow()->NormY(y);
00518 }
00519
00520 void MythUIType::CopyFrom(MythUIType *base)
00521 {
00522 m_Visible = base->m_Visible;
00523 m_CanHaveFocus = base->m_CanHaveFocus;
00524
00525 m_Area = base->m_Area;
00526 m_Alpha = base->m_Alpha;
00527 m_AlphaChangeMode = base->m_AlphaChangeMode;
00528 m_AlphaChange = base->m_AlphaChange;
00529 m_AlphaMin = base->m_AlphaMin;
00530 m_AlphaMax = base->m_AlphaMax;
00531
00532 m_Moving = base->m_Moving;
00533 m_XYDestination = base->m_XYDestination;
00534 m_XYSpeed = base->m_XYSpeed;
00535
00536 QValueVector<MythUIType *>::Iterator it;
00537 for (it = base->m_ChildrenList.begin(); it != base->m_ChildrenList.end();
00538 ++it)
00539 {
00540 (*it)->CreateCopy(this);
00541 }
00542 }
00543
00544 void MythUIType::CreateCopy(MythUIType *)
00545 {
00546 VERBOSE(VB_IMPORTANT, "Copy called on base type?");
00547 }
00548
00549
00550 bool MythUIType::ParseElement(QDomElement &element)
00551 {
00552 if (element.tagName() == "position")
00553 SetPosition(parsePoint(element));
00554 else if (element.tagName() == "alpha")
00555 {
00556 m_Alpha = getFirstText(element).toInt();
00557 m_AlphaChangeMode = 0;
00558 }
00559 else if (element.tagName() == "alphapulse")
00560 {
00561 m_AlphaChangeMode = 2;
00562 m_AlphaMin = element.attribute("min", "0").toInt();
00563 m_AlphaMax = element.attribute("max", "255").toInt();
00564 m_AlphaChange = element.attribute("change", "5").toInt();
00565 }
00566 else
00567 return false;
00568
00569 return true;
00570 }
00571
00572 void MythUIType::Finalize(void)
00573 {
00574 }
00575
00576 MythFontProperties *MythUIType::GetFont(const QString &text)
00577 {
00578 MythFontProperties *ret = m_Fonts->GetFont(text);
00579 if (!ret && m_Parent)
00580 return m_Parent->GetFont(text);
00581
00582 return ret;
00583 }
00584
00585 bool MythUIType::AddFont(const QString &text, MythFontProperties *fontProp)
00586 {
00587 return m_Fonts->AddFont(text, fontProp);
00588 }
00589