1 /** @file widgets/labelwidget.h 2 * 3 * @authors Copyright (c) 2013-2017 Jaakko Keränen <jaakko.keranen@iki.fi> 4 * 5 * @par License 6 * LGPL: http://www.gnu.org/licenses/lgpl.html 7 * 8 * <small>This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU Lesser General Public License as published by 10 * the Free Software Foundation; either version 3 of the License, or (at your 11 * option) any later version. This program is distributed in the hope that it 12 * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty 13 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 14 * General Public License for more details. You should have received a copy of 15 * the GNU Lesser General Public License along with this program; if not, see: 16 * http://www.gnu.org/licenses</small> 17 */ 18 19 #ifndef LIBAPPFW_LABELWIDGET_H 20 #define LIBAPPFW_LABELWIDGET_H 21 22 #include "../ui/defs.h" 23 #include "../GuiWidget" 24 #include "../ProceduralImage" 25 #include "../ui/Data" 26 27 namespace de { 28 29 class GLUniform; 30 class GridLayout; 31 class Image; 32 33 /** 34 * Widget showing a label text and/or image. 35 * 36 * LabelWidget offers several parameters for controlling the layout of the text 37 * and image components. The widget is also able to independently determine its 38 * size to exactly fit its contents (according to the LabelWidget::SizePolicy). 39 * 40 * The alignment parameters are applied as follows: 41 * 42 * - LabelWidget::setAlignment() defines where the content of the widget is 43 * aligned as a group, once the relative positions of the image and the text 44 * have been determined. 45 * 46 * - LabelWidget::setTextAlignment() defines where the text will be positioned 47 * in relation to the image. For instance, if the text alignment is AlignRight, 48 * the text will be placed on the right side of the image. If there is no 49 * image, this has no effect. 50 * 51 * - LabelWidget::setImageAlignment() defines how the image is aligned in 52 * relation to text when both are visible. For instance, if text is aligned to 53 * AlignRight (appearing on the right side of the image), then an image 54 * alignment of AlignTop would align the top of the image with the top of the 55 * text. AlignBottom would align the bottom of the image with the bottom of the 56 * text. This value must be on the perpendicular axis when compared to text 57 * alignment (otherwise it has no effect). 58 * 59 * - LabelWidget::setTextLineAlignment() defines the alignment of each individual 60 * wrapped line of text within the text block. 61 * 62 * Additionally, LabelWidget::setImageFit() defines how the image will be 63 * scaled inside the area reserved for the image. 64 * 65 * LabelWidget is an Asset because the preparation of text for drawing occurs 66 * asynchronously, and meanwhile the content size of the text is (0,0). 67 * Observing the asset state allows others to determine when the label is ready 68 * to be drawn/laid out with the final dimensions. 69 * 70 * @ingroup guiWidgets 71 */ 72 class LIBAPPFW_PUBLIC LabelWidget : public GuiWidget, public IAssetGroup 73 { 74 public: 75 LabelWidget(String const &name = String()); 76 77 AssetGroup &assets() override; 78 79 void setText(String const &text); 80 void setImage(Image const &image); 81 82 /** 83 * Sets the image drawn in the label. Procedural images can generate any 84 * geometry on the fly, so the image can be fully animated. 85 * 86 * @param procImage Procedural image. LabelWidget takes ownership. 87 */ 88 void setImage(ProceduralImage *procImage); 89 90 /** 91 * Sets the image drawn in the label using a procedural image from the UI style. 92 * 93 * @param id Image ID. 94 * @param heightFromFont Optionally overrides the image size using the height of 95 * this font. Default is to use the image's own size. 96 */ 97 void setStyleImage(DotPath const &id, String const &heightFromFont = ""); 98 99 ProceduralImage *image() const; 100 101 /** 102 * Sets an overlay image that gets drawn over the label contents. 103 * 104 * @param overlayProcImage Procedural image. LabelWidget takes ownership. 105 * @param alignment Alignment for the overlaid image. 106 */ 107 void setOverlayImage(ProceduralImage *overlayProcImage, 108 ui::Alignment const &alignment = ui::AlignCenter); 109 110 String text() const; 111 112 /** 113 * Returns the actual size of the text in pixels. 114 */ 115 Vector2ui textSize() const; 116 117 Rule const &contentWidth() const; 118 Rule const &contentHeight() const; 119 120 enum FillMode { 121 FillWithImage, 122 FillWithText 123 }; 124 125 void setFillMode(FillMode fillMode); 126 127 /** 128 * Sets the gap between the text and image. Defaults to "label.gap". 129 * 130 * @param styleRuleId Id of a rule in the style. 131 */ 132 void setTextGap(DotPath const &styleRuleId); 133 134 DotPath const &textGap() const; 135 136 enum TextShadow { 137 NoShadow, 138 RectangleShadow 139 }; 140 141 void setTextShadow(TextShadow shadow, DotPath const &shadowColor = "label.shadow"); 142 143 enum AlignmentMode { 144 AlignByCombination, 145 AlignOnlyByImage, 146 AlignOnlyByText 147 }; 148 149 /** 150 * Sets the alignment of the entire contents of the widget inside its 151 * rectangle. 152 * 153 * @param align Alignment for all content. 154 * @param alignMode Mode of alignment (by combo/text/image). 155 */ 156 void setAlignment(ui::Alignment const &align, 157 AlignmentMode alignMode = AlignByCombination); 158 159 void setTextAlignment(ui::Alignment const &textAlign); 160 161 ui::Alignment textAlignment() const; 162 163 void setTextLineAlignment(ui::Alignment const &textLineAlign); 164 165 void setTextModulationColorf(Vector4f const &colorf); 166 167 Vector4f textModulationColorf() const; 168 169 /** 170 * Sets the maximum width used for text. By default, the maximum width is determined 171 * automatically based on the layout of the label content. 172 * 173 * @param pixels Maximum width of text, or 0 to determine automatically. 174 */ 175 void setMaximumTextWidth(int pixels); 176 177 void setMaximumTextWidth(Rule const &pixels); 178 179 void setMinimumHeight(Rule const &minHeight); 180 181 /** 182 * Sets an alternative style for text. By default, the rich text styling comes 183 * from Style. 184 * 185 * @param richStyle Rich text styling. 186 */ 187 void setTextStyle(Font::RichFormat::IStyle const *richStyle); 188 189 /** 190 * Sets the alignment of the image when there is both an image 191 * and a text in the label. 192 * 193 * @param imageAlign Alignment for the image. 194 */ 195 void setImageAlignment(ui::Alignment const &imageAlign); 196 197 void setImageFit(ui::ContentFit const &fit); 198 199 /** 200 * The image's actual size will be overridden by this size. 201 * @param size Image size. 202 */ 203 void setOverrideImageSize(const Rule &width, const Rule &height); 204 setOverrideImageSize(const ISizeRule & size)205 void setOverrideImageSize(const ISizeRule &size) 206 { 207 setOverrideImageSize(size.width(), size.height()); 208 } 209 setOverrideImageSize(const Rule & widthAndHeight)210 void setOverrideImageSize(const Rule &widthAndHeight) 211 { 212 setOverrideImageSize(widthAndHeight, widthAndHeight); 213 } 214 215 RulePair overrideImageSize() const; 216 217 void setImageScale(float scaleFactor); 218 219 void setImageColor(Vector4f const &imageColor); 220 221 bool hasImage() const; 222 223 /** 224 * Sets the policy for the widget to adjust its own width and/or height. By default, 225 * labels do not adjust their own size. 226 * - ui::Fixed means that the content uses its own size and the widget needs to be 227 * sized by the user. 228 * - ui::Filled means content is expanded to fill the entire contents of the widget 229 * area, but the widget still needs to be sized by the user. 230 * - ui::Expand means the widget resizes itself to the size of the content. 231 * 232 * @param horizontal Horizontal sizing policy. 233 * @param vertical Vertical sizing policy. 234 */ setSizePolicy(ui::SizePolicy horizontal,ui::SizePolicy vertical)235 void setSizePolicy(ui::SizePolicy horizontal, ui::SizePolicy vertical) { 236 setWidthPolicy(horizontal); 237 setHeightPolicy(vertical); 238 } 239 240 void setWidthPolicy(ui::SizePolicy policy); 241 void setHeightPolicy(ui::SizePolicy policy); 242 243 enum AppearanceAnimation { 244 AppearInstantly, 245 AppearGrowHorizontally, 246 AppearGrowVertically 247 }; 248 249 /** 250 * Sets the way the label's content affects its size. 251 * 252 * @param method Method of appearance: 253 * - AppearInstantly: The size is unaffected by the content's state. 254 * This is the default. 255 * - AppearGrowHorizontally: The widget's width is initially zero, but when the 256 * content is ready for drawing, the width will animate 257 * to the appropriate width in the specified time span. 258 * - AppearGrowVertically: The widget's height is initially zero, but when the 259 * content is ready for drawing, the height will animate 260 * to the appropriate height in the specified time span. 261 * @param span Animation time span for the appearance. 262 */ 263 void setAppearanceAnimation(AppearanceAnimation method, TimeSpan const &span = 0.0); 264 265 // Events. 266 void update() override; 267 void drawContent() override; 268 269 struct ContentLayout { 270 Rectanglef image; 271 Rectanglei text; 272 }; 273 274 void contentLayout(ContentLayout &layout); 275 276 public: 277 static LabelWidget *newWithText(const String &text, GuiWidget *parent = nullptr); 278 static LabelWidget *appendSeparatorWithText(const String &text, GuiWidget *parent = nullptr, 279 GridLayout *appendToGrid = nullptr); 280 281 protected: 282 void glInit() override; 283 void glDeinit() override; 284 void glMakeGeometry(GuiVertexBuilder &verts) override; 285 void updateStyle() override; 286 287 /** 288 * Called before drawing to update the model-view-projection matrix. 289 * Derived classes may override this to set a custom matrix for the label. 290 * @return @c true, if a customized matrix was set. 291 */ 292 virtual bool updateModelViewProjection(Matrix4f &mvp); 293 294 private: 295 DENG2_PRIVATE(d) 296 }; 297 298 } // namespace de 299 300 #endif // LIBAPPFW_LABELWIDGET_H 301