1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef UI_VIEWS_CONTROLS_LABEL_H_ 6 #define UI_VIEWS_CONTROLS_LABEL_H_ 7 8 #include <string> 9 #include <vector> 10 11 #include "base/compiler_specific.h" 12 #include "base/gtest_prod_util.h" 13 #include "base/strings/string16.h" 14 #include "third_party/skia/include/core/SkColor.h" 15 #include "ui/gfx/font.h" 16 #include "ui/gfx/text_constants.h" 17 #include "ui/views/view.h" 18 19 namespace views { 20 21 ///////////////////////////////////////////////////////////////////////////// 22 // 23 // Label class 24 // 25 // A label is a view subclass that can display a string. 26 // 27 ///////////////////////////////////////////////////////////////////////////// 28 class VIEWS_EXPORT Label : public View { 29 public: 30 // Internal class name. 31 static const char kViewClassName[]; 32 33 // The following enum is used to indicate whether using the Chrome UI's 34 // directionality as the label's directionality, or auto-detecting the label's 35 // directionality. 36 // 37 // If the label text originates from the Chrome UI, we should use the Chrome 38 // UI's directionality as the label's directionality. 39 // 40 // If the text originates from a web page, its directionality is determined 41 // based on its first character with strong directionality, disregarding what 42 // directionality the Chrome UI is. 43 enum DirectionalityMode { 44 USE_UI_DIRECTIONALITY = 0, 45 AUTO_DETECT_DIRECTIONALITY 46 }; 47 48 enum ElideBehavior { 49 NO_ELIDE, // Do not elide the label text; truncate as needed. 50 ELIDE_IN_MIDDLE, // Add ellipsis in the middle of the string as needed. 51 ELIDE_AT_END, // Add ellipsis at the end of the string as needed. 52 ELIDE_AS_EMAIL, // Elide while retaining username/domain chars as needed. 53 }; 54 55 Label(); 56 explicit Label(const string16& text); 57 Label(const string16& text, const gfx::Font& font); 58 virtual ~Label(); 59 60 // Get or set the font used by this label. 61 const gfx::Font& font() const { return font_; } 62 virtual void SetFont(const gfx::Font& font); 63 64 // Get or set the label text. 65 const string16& text() const { return text_; } 66 void SetText(const string16& text); 67 68 // Enables or disables auto-color-readability (enabled by default). If this 69 // is enabled, then calls to set any foreground or background color will 70 // trigger an automatic mapper that uses color_utils::GetReadableColor() to 71 // ensure that the foreground colors are readable over the background color. 72 void SetAutoColorReadabilityEnabled(bool enabled); 73 74 // Sets the color. This will automatically force the color to be readable 75 // over the current background color. 76 virtual void SetEnabledColor(SkColor color); 77 void SetDisabledColor(SkColor color); 78 79 SkColor enabled_color() const { return actual_enabled_color_; } 80 81 // Sets the background color. This won't be explicitly drawn, but the label 82 // will force the text color to be readable over it. 83 void SetBackgroundColor(SkColor color); 84 SkColor background_color() const { return background_color_; } 85 86 // Enables a drop shadow underneath the text. 87 void SetShadowColors(SkColor enabled_color, SkColor disabled_color); 88 89 // Sets the drop shadow's offset from the text. 90 void SetShadowOffset(int x, int y); 91 92 // Disables shadows. 93 void ClearEmbellishing(); 94 95 // Sets horizontal alignment. If the locale is RTL, and the directionality 96 // mode is USE_UI_DIRECTIONALITY, the alignment is flipped around. 97 // 98 // Caveat: for labels originating from a web page, the directionality mode 99 // should be reset to AUTO_DETECT_DIRECTIONALITY before the horizontal 100 // alignment is set. Otherwise, the label's alignment specified as a parameter 101 // will be flipped in RTL locales. 102 void SetHorizontalAlignment(gfx::HorizontalAlignment alignment); 103 104 gfx::HorizontalAlignment horizontal_alignment() const { 105 return horizontal_alignment_; 106 } 107 108 // Sets the directionality mode. The directionality mode is initialized to 109 // USE_UI_DIRECTIONALITY when the label is constructed. USE_UI_DIRECTIONALITY 110 // applies to every label that originates from the Chrome UI. However, if the 111 // label originates from a web page, its directionality is auto-detected. 112 void set_directionality_mode(DirectionalityMode mode) { 113 directionality_mode_ = mode; 114 } 115 116 DirectionalityMode directionality_mode() const { 117 return directionality_mode_; 118 } 119 120 // Get or set the distance in pixels between baselines of multi-line text. 121 // Default is 0, indicating the distance between lines should be the standard 122 // one for the label's text, font, and platform. 123 int line_height() const { return line_height_; } 124 void SetLineHeight(int height); 125 126 // Get or set if the label text can wrap on multiple lines; default is false. 127 bool is_multi_line() const { return is_multi_line_; } 128 void SetMultiLine(bool multi_line); 129 130 // Sets whether the label text can be split on words. 131 // Default is false. This only works when is_multi_line is true. 132 void SetAllowCharacterBreak(bool allow_character_break); 133 134 // Sets whether the label text should be elided in the middle or end (if 135 // necessary). The default is to elide at the end. 136 // NOTE: Eliding in the middle is not supported for multi-line strings. 137 void SetElideBehavior(ElideBehavior elide_behavior); 138 139 // Sets the tooltip text. Default behavior for a label (single-line) is to 140 // show the full text if it is wider than its bounds. Calling this overrides 141 // the default behavior and lets you set a custom tooltip. To revert to 142 // default behavior, call this with an empty string. 143 void SetTooltipText(const string16& tooltip_text); 144 145 // Resizes the label so its width is set to the width of the longest line and 146 // its height deduced accordingly. 147 // This is only intended for multi-line labels and is useful when the label's 148 // text contains several lines separated with \n. 149 // |max_width| is the maximum width that will be used (longer lines will be 150 // wrapped). If 0, no maximum width is enforced. 151 void SizeToFit(int max_width); 152 153 // Gets/sets the flag to determine whether the label should be collapsed when 154 // it's hidden (not visible). If this flag is true, the label will return a 155 // preferred size of (0, 0) when it's not visible. 156 void set_collapse_when_hidden(bool value) { collapse_when_hidden_ = value; } 157 bool collapse_when_hidden() const { return collapse_when_hidden_; } 158 159 void SetHasFocusBorder(bool has_focus_border); 160 161 // Overridden from View: 162 virtual gfx::Insets GetInsets() const OVERRIDE; 163 virtual int GetBaseline() const OVERRIDE; 164 // Overridden to compute the size required to display this label. 165 virtual gfx::Size GetPreferredSize() OVERRIDE; 166 // Returns the height necessary to display this label with the provided width. 167 // This method is used to layout multi-line labels. It is equivalent to 168 // GetPreferredSize().height() if the receiver is not multi-line. 169 virtual int GetHeightForWidth(int w) OVERRIDE; 170 virtual const char* GetClassName() const OVERRIDE; 171 virtual View* GetTooltipHandlerForPoint(const gfx::Point& point) OVERRIDE; 172 virtual bool HitTestRect(const gfx::Rect& rect) const OVERRIDE; 173 virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE; 174 // Gets the tooltip text for labels that are wider than their bounds, except 175 // when the label is multiline, in which case it just returns false (no 176 // tooltip). If a custom tooltip has been specified with SetTooltipText() 177 // it is returned instead. 178 virtual bool GetTooltipText(const gfx::Point& p, 179 string16* tooltip) const OVERRIDE; 180 181 protected: 182 // Called by Paint to paint the text. Override this to change how 183 // text is painted. 184 virtual void PaintText(gfx::Canvas* canvas, 185 const string16& text, 186 const gfx::Rect& text_bounds, 187 int flags); 188 189 virtual gfx::Size GetTextSize() const; 190 191 SkColor disabled_color() const { return actual_disabled_color_; } 192 193 // Overridden from View: 194 // Overridden to dirty our text bounds if we're multi-line. 195 virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE; 196 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE; 197 virtual void OnNativeThemeChanged(const ui::NativeTheme* theme) OVERRIDE; 198 199 private: 200 // These tests call CalculateDrawStringParams in order to verify the 201 // calculations done for drawing text. 202 FRIEND_TEST_ALL_PREFIXES(LabelTest, DrawSingleLineString); 203 FRIEND_TEST_ALL_PREFIXES(LabelTest, DrawMultiLineString); 204 FRIEND_TEST_ALL_PREFIXES(LabelTest, DrawSingleLineStringInRTL); 205 FRIEND_TEST_ALL_PREFIXES(LabelTest, DrawMultiLineStringInRTL); 206 FRIEND_TEST_ALL_PREFIXES(LabelTest, AutoDetectDirectionality); 207 208 // Calls ComputeDrawStringFlags(). 209 FRIEND_TEST_ALL_PREFIXES(LabelTest, DisableSubpixelRendering); 210 211 static gfx::Font GetDefaultFont(); 212 213 void Init(const string16& text, const gfx::Font& font); 214 215 void RecalculateColors(); 216 217 // Returns where the text is drawn, in the receivers coordinate system. 218 gfx::Rect GetTextBounds() const; 219 220 int ComputeDrawStringFlags() const; 221 222 gfx::Rect GetAvailableRect() const; 223 224 // Returns parameters to be used for the DrawString call. 225 void CalculateDrawStringParams(string16* paint_text, 226 gfx::Rect* text_bounds, 227 int* flags) const; 228 229 // Updates any colors that have not been explicitly set from the theme. 230 void UpdateColorsFromTheme(const ui::NativeTheme* theme); 231 232 // Resets |cached_heights_| and |cached_heights_cursor_| and mark 233 // |text_size_valid_| as false. 234 void ResetCachedSize(); 235 236 bool ShouldShowDefaultTooltip() const; 237 238 string16 text_; 239 gfx::Font font_; 240 SkColor requested_enabled_color_; 241 SkColor actual_enabled_color_; 242 SkColor requested_disabled_color_; 243 SkColor actual_disabled_color_; 244 SkColor background_color_; 245 246 // Set to true once the corresponding setter is invoked. 247 bool enabled_color_set_; 248 bool disabled_color_set_; 249 bool background_color_set_; 250 251 bool auto_color_readability_; 252 mutable gfx::Size text_size_; 253 mutable bool text_size_valid_; 254 int line_height_; 255 bool is_multi_line_; 256 bool allow_character_break_; 257 ElideBehavior elide_behavior_; 258 gfx::HorizontalAlignment horizontal_alignment_; 259 string16 tooltip_text_; 260 // Whether to collapse the label when it's not visible. 261 bool collapse_when_hidden_; 262 // The following member variable is used to control whether the 263 // directionality is auto-detected based on first strong directionality 264 // character or is determined by chrome UI's locale. 265 DirectionalityMode directionality_mode_; 266 // When embedded in a larger control that is focusable, setting this flag 267 // allows this view to reserve space for a focus border that it otherwise 268 // might not have because it is not itself focusable. 269 bool has_focus_border_; 270 271 // Colors for shadow. 272 SkColor enabled_shadow_color_; 273 SkColor disabled_shadow_color_; 274 275 // Space between text and shadow. 276 gfx::Point shadow_offset_; 277 278 // Should a shadow be drawn behind the text? 279 bool has_shadow_; 280 281 // The cached heights to avoid recalculation in GetHeightForWidth(). 282 std::vector<gfx::Size> cached_heights_; 283 int cached_heights_cursor_; 284 285 DISALLOW_COPY_AND_ASSIGN(Label); 286 }; 287 288 } // namespace views 289 290 #endif // UI_VIEWS_CONTROLS_LABEL_H_ 291