2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
24 CGUILabel::CGUILabel(float posX, float posY, float width, float height, const CLabelInfo& labelInfo, CGUILabel::OVER_FLOW overflow)
26 , m_textLayout(labelInfo.font, overflow == OVER_FLOW_WRAP, height)
27 , m_scrolling(overflow == OVER_FLOW_SCROLL)
28 , m_overflowType(overflow)
30 , m_scrollInfo(50, 0, labelInfo.scrollSpeed, labelInfo.scrollSuffix)
32 , m_maxRect(posX, posY, posX + width, posY + height)
38 CGUILabel::~CGUILabel(void)
42 bool CGUILabel::SetScrolling(bool scrolling)
44 bool changed = m_scrolling != scrolling;
46 m_scrolling = scrolling;
53 bool CGUILabel::SetOverflow(OVER_FLOW overflow)
55 bool changed = m_overflowType != overflow;
57 m_overflowType = overflow;
62 bool CGUILabel::SetColor(CGUILabel::COLOR color)
64 bool changed = m_color != color;
71 color_t CGUILabel::GetColor() const
76 return m_label.selectedColor;
78 return m_label.disabledColor;
80 return m_label.focusedColor ? m_label.focusedColor : m_label.textColor;
82 return m_label.invalidColor ? m_label.invalidColor : m_label.textColor;
86 return m_label.textColor;
89 bool CGUILabel::Process(unsigned int currentTime)
91 // TODO Add the correct processing
93 bool overFlows = (m_renderRect.Width() + 0.5f < m_textLayout.GetTextWidth()); // 0.5f to deal with floating point rounding issues
94 bool renderSolid = (m_color == COLOR_DISABLED);
96 if (overFlows && m_scrolling && !renderSolid)
97 return m_textLayout.UpdateScrollinfo(m_scrollInfo);
102 void CGUILabel::Render()
104 color_t color = GetColor();
105 bool renderSolid = (m_color == COLOR_DISABLED);
106 bool overFlows = (m_renderRect.Width() + 0.5f < m_textLayout.GetTextWidth()); // 0.5f to deal with floating point rounding issues
107 if (overFlows && m_scrolling && !renderSolid)
108 m_textLayout.RenderScrolling(m_renderRect.x1, m_renderRect.y1, m_label.angle, color, m_label.shadowColor, 0, m_renderRect.Width(), m_scrollInfo);
111 float posX = m_renderRect.x1;
112 float posY = m_renderRect.y1;
115 { // hack for right and centered multiline text, as GUITextLayout::Render() treats posX as the right hand
116 // or center edge of the text (see GUIFontTTF::DrawTextInternal), and this has already been taken care of
117 // in UpdateRenderRect(), but we wish to still pass the horizontal alignment info through (so that multiline text
118 // is aligned correctly), so we must undo the UpdateRenderRect() changes for horizontal alignment.
119 if (m_label.align & XBFONT_RIGHT)
120 posX += m_renderRect.Width();
121 else if (m_label.align & XBFONT_CENTER_X)
122 posX += m_renderRect.Width() * 0.5f;
123 if (m_label.align & XBFONT_CENTER_Y) // need to pass a centered Y so that <angle> will rotate around the correct point.
124 posY += m_renderRect.Height() * 0.5f;
125 align = m_label.align;
128 align |= XBFONT_TRUNCATED;
129 m_textLayout.Render(posX, posY, m_label.angle, color, m_label.shadowColor, align, m_overflowType == OVER_FLOW_CLIP ? m_textLayout.GetTextWidth() : m_renderRect.Width(), renderSolid);
133 void CGUILabel::SetInvalid()
138 bool CGUILabel::UpdateColors()
140 return m_label.UpdateColors();
143 bool CGUILabel::SetMaxRect(float x, float y, float w, float h)
145 CRect oldRect = m_maxRect;
147 m_maxRect.SetRect(x, y, x + w, y + h);
150 return oldRect != m_maxRect;
153 bool CGUILabel::SetAlign(uint32_t align)
155 bool changed = m_label.align != align;
157 m_label.align = align;
163 bool CGUILabel::SetStyledText(const vecText &text, const vecColors &colors)
165 m_textLayout.UpdateStyled(text, colors, m_maxRect.Width());
170 bool CGUILabel::SetText(const CStdString &label)
172 if (m_textLayout.Update(label, m_maxRect.Width(), m_invalid))
173 { // needed an update - reset scrolling and update our text layout
174 m_scrollInfo.Reset();
183 bool CGUILabel::SetTextW(const CStdStringW &label)
185 if (m_textLayout.UpdateW(label, m_maxRect.Width(), m_invalid))
187 m_scrollInfo.Reset();
196 void CGUILabel::UpdateRenderRect()
198 // recalculate our text layout
200 m_textLayout.GetTextExtent(width, height);
201 width = std::min(width, GetMaxWidth());
202 if (m_label.align & XBFONT_CENTER_Y)
203 m_renderRect.y1 = m_maxRect.y1 + (m_maxRect.Height() - height) * 0.5f;
205 m_renderRect.y1 = m_maxRect.y1 + m_label.offsetY;
206 if (m_label.align & XBFONT_RIGHT)
207 m_renderRect.x1 = m_maxRect.x2 - width - m_label.offsetX;
208 else if (m_label.align & XBFONT_CENTER_X)
209 m_renderRect.x1 = m_maxRect.x1 + (m_maxRect.Width() - width) * 0.5f;
211 m_renderRect.x1 = m_maxRect.x1 + m_label.offsetX;
212 m_renderRect.x2 = m_renderRect.x1 + width;
213 m_renderRect.y2 = m_renderRect.y1 + height;
216 float CGUILabel::GetMaxWidth() const
218 if (m_label.width) return m_label.width;
219 return m_maxRect.Width() - 2*m_label.offsetX;
222 bool CGUILabel::CheckAndCorrectOverlap(CGUILabel &label1, CGUILabel &label2)
224 CRect rect(label1.m_renderRect);
225 if (rect.Intersect(label2.m_renderRect).IsEmpty())
226 return false; // nothing to do (though it could potentially encroach on the min_space requirement)
228 // overlap vertically and horizontally - check alignment
229 CGUILabel &left = label1.m_renderRect.x1 <= label2.m_renderRect.x1 ? label1 : label2;
230 CGUILabel &right = label1.m_renderRect.x1 <= label2.m_renderRect.x1 ? label2 : label1;
231 if ((left.m_label.align & 3) == 0 && right.m_label.align & XBFONT_RIGHT)
233 static const float min_space = 10;
234 float chopPoint = (left.m_maxRect.x1 + left.GetMaxWidth() + right.m_maxRect.x2 - right.GetMaxWidth()) * 0.5f;
235 // [1 [2...[2 1].|..........1] 2]
236 // [1 [2.....[2 | 1]..1] 2]
237 // [1 [2..........|.[2 1]..1] 2]
238 if (right.m_renderRect.x1 > chopPoint)
239 chopPoint = right.m_renderRect.x1 - min_space;
240 else if (left.m_renderRect.x2 < chopPoint)
241 chopPoint = left.m_renderRect.x2 + min_space;
242 left.m_renderRect.x2 = chopPoint - min_space;
243 right.m_renderRect.x1 = chopPoint + min_space;