Commit 528dd548 authored by rouslan@chromium.org's avatar rouslan@chromium.org

Revert of Use labels to display views tab titles. (https://codereview.chromium.org/323993002/)

Reason for revert:
Appears to have a memory leak. See:

http://build.chromium.org/p/chromium.memory/builders/Linux%20ASan%20LSan%20Tests%20%283%29/builds/3954

Original issue's description:
> Use labels to display views tab titles.
> 
> Add a Label view to Tab for displaying the title.
> Remove Tab::PaintTitle, bounds and font members.
> Remove unnecessary Tab::Get[Title|Icon]Bounds helpers.
> Update the text on Tab::SetData, not during paint.
> Use gfx::DirectionalityMode, remove the Label enum.
> 
> Add gfx::ALIGN_TO_HEAD to gfx::HorizontalAlignment.
> Add Label::GetHorizontalAlignment for ALIGN_TO_HEAD.
> Always flip left/right in Label::SetHorizontalAlignment.
> Have Tab and MessageBoxView use ALIGN_TO_HEAD.
> 
> Update comments and tests, related minor cleanup.
> 
> TODO: Make Label cache RenderText objects.
> TODO: Make RenderText support ALIGN_TO_HEAD.
> 
> BUG=240037
> TEST=No visible Views tab title changes.
> R=sky@chromium.org
> 
> Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=276450

TBR=sky@chromium.org,msw@chromium.org
NOTREECHECKS=true
NOTRY=true
BUG=240037

Review URL: https://codereview.chromium.org/327273005

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@276476 0039d316-1c4b-4281-b951-d872f2087c98
parent 70b9c497
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "ui/gfx/canvas.h" #include "ui/gfx/canvas.h"
#include "ui/gfx/color_analysis.h" #include "ui/gfx/color_analysis.h"
#include "ui/gfx/favicon_size.h" #include "ui/gfx/favicon_size.h"
#include "ui/gfx/font.h"
#include "ui/gfx/image/image_skia_operations.h" #include "ui/gfx/image/image_skia_operations.h"
#include "ui/gfx/path.h" #include "ui/gfx/path.h"
#include "ui/gfx/rect_conversions.h" #include "ui/gfx/rect_conversions.h"
...@@ -42,7 +43,6 @@ ...@@ -42,7 +43,6 @@
#include "ui/gfx/text_elider.h" #include "ui/gfx/text_elider.h"
#include "ui/views/border.h" #include "ui/views/border.h"
#include "ui/views/controls/button/image_button.h" #include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/label.h"
#include "ui/views/rect_based_targeting_utils.h" #include "ui/views/rect_based_targeting_utils.h"
#include "ui/views/widget/tooltip_manager.h" #include "ui/views/widget/tooltip_manager.h"
#include "ui/views/widget/widget.h" #include "ui/views/widget/widget.h"
...@@ -375,6 +375,10 @@ Tab::TabImage Tab::tab_alpha_ = {0}; ...@@ -375,6 +375,10 @@ Tab::TabImage Tab::tab_alpha_ = {0};
Tab::TabImage Tab::tab_active_ = {0}; Tab::TabImage Tab::tab_active_ = {0};
Tab::TabImage Tab::tab_inactive_ = {0}; Tab::TabImage Tab::tab_inactive_ = {0};
// static // static
gfx::Font* Tab::font_ = NULL;
// static
int Tab::font_height_ = 0;
// static
Tab::ImageCache* Tab::image_cache_ = NULL; Tab::ImageCache* Tab::image_cache_ = NULL;
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
...@@ -389,8 +393,6 @@ Tab::Tab(TabController* controller) ...@@ -389,8 +393,6 @@ Tab::Tab(TabController* controller)
immersive_loading_step_(0), immersive_loading_step_(0),
should_display_crashed_favicon_(false), should_display_crashed_favicon_(false),
animating_media_state_(TAB_MEDIA_STATE_NONE), animating_media_state_(TAB_MEDIA_STATE_NONE),
close_button_(NULL),
title_(new views::Label()),
tab_activated_with_last_gesture_begin_(false), tab_activated_with_last_gesture_begin_(false),
hover_controller_(this), hover_controller_(this),
showing_icon_(false), showing_icon_(false),
...@@ -406,10 +408,6 @@ Tab::Tab(TabController* controller) ...@@ -406,10 +408,6 @@ Tab::Tab(TabController* controller)
set_id(VIEW_ID_TAB); set_id(VIEW_ID_TAB);
title_->set_directionality_mode(gfx::DIRECTIONALITY_FROM_TEXT);
title_->SetHorizontalAlignment(gfx::ALIGN_TO_HEAD);
title_->SetElideBehavior(gfx::FADE_TAIL);
// Add the Close Button. // Add the Close Button.
close_button_ = new TabCloseButton(this); close_button_ = new TabCloseButton(this);
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
...@@ -452,16 +450,6 @@ void Tab::SetData(const TabRendererData& data) { ...@@ -452,16 +450,6 @@ void Tab::SetData(const TabRendererData& data) {
TabRendererData old(data_); TabRendererData old(data_);
data_ = data; data_ = data;
base::string16 title = data_.title;
if (title.empty()) {
title = data_.loading ?
l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE) :
CoreTabHelper::GetDefaultTitle();
} else {
Browser::FormatTitleForDisplay(&title);
}
title_->SetText(title);
if (data_.IsCrashed()) { if (data_.IsCrashed()) {
if (!should_display_crashed_favicon_ && !IsPerformingCrashAnimation()) { if (!should_display_crashed_favicon_ && !IsPerformingCrashAnimation()) {
data_.media_state = TAB_MEDIA_STATE_NONE; data_.media_state = TAB_MEDIA_STATE_NONE;
...@@ -698,8 +686,7 @@ void Tab::Layout() { ...@@ -698,8 +686,7 @@ void Tab::Layout() {
// The height of the content of the Tab is the largest of the favicon, // The height of the content of the Tab is the largest of the favicon,
// the title text and the close button graphic. // the title text and the close button graphic.
const int kTabIconSize = gfx::kFaviconSize; const int kTabIconSize = gfx::kFaviconSize;
const int font_height = title_->font_list().GetHeight(); int content_height = std::max(kTabIconSize, font_height_);
int content_height = std::max(kTabIconSize, font_height);
close_button_->SetBorder(views::Border::NullBorder()); close_button_->SetBorder(views::Border::NullBorder());
gfx::Size close_button_size(close_button_->GetPreferredSize()); gfx::Size close_button_size(close_button_->GetPreferredSize());
content_height = std::max(content_height, close_button_size.height()); content_height = std::max(content_height, close_button_size.height());
...@@ -771,15 +758,14 @@ void Tab::Layout() { ...@@ -771,15 +758,14 @@ void Tab::Layout() {
kTitleTextOffsetYAsh : kTitleTextOffsetY; kTitleTextOffsetYAsh : kTitleTextOffsetY;
int title_left = favicon_bounds_.right() + kFaviconTitleSpacing; int title_left = favicon_bounds_.right() + kFaviconTitleSpacing;
int title_top = kTopPadding + title_text_offset + int title_top = kTopPadding + title_text_offset +
(content_height - font_height) / 2; (content_height - font_height_) / 2;
gfx::Rect title_bounds(title_left, title_top, 0, 0);
// Size the Title text to fill the remaining space. // Size the Title text to fill the remaining space.
if (!data().mini || width() >= kMiniTabRendererAsNormalTabWidth) { if (!data().mini || width() >= kMiniTabRendererAsNormalTabWidth) {
// If the user has big fonts, the title will appear rendered too far down // If the user has big fonts, the title will appear rendered too far down
// on the y-axis if we use the regular top padding, so we need to adjust it // on the y-axis if we use the regular top padding, so we need to adjust it
// so that the text appears centered. // so that the text appears centered.
gfx::Size minimum_size = GetMinimumUnselectedSize(); gfx::Size minimum_size = GetMinimumUnselectedSize();
int text_height = title_top + font_height + kBottomPadding; int text_height = title_top + font_height_ + kBottomPadding;
if (text_height > minimum_size.height()) if (text_height > minimum_size.height())
title_top -= (text_height - minimum_size.height()) / 2; title_top -= (text_height - minimum_size.height()) / 2;
...@@ -797,11 +783,19 @@ void Tab::Layout() { ...@@ -797,11 +783,19 @@ void Tab::Layout() {
title_width = lb.width() - title_left; title_width = lb.width() - title_left;
} }
title_width = std::max(title_width, 0); title_width = std::max(title_width, 0);
title_bounds.SetRect(title_left, title_top, title_width, font_height); title_bounds_.SetRect(title_left, title_top, title_width, font_height_);
} else {
title_bounds_.SetRect(title_left, title_top, 0, 0);
} }
title_bounds.set_x(GetMirroredXForRect(title_bounds)); // Certain UI elements within the Tab (the favicon, etc.) are not represented
title_->SetBoundsRect(title_bounds); // as child Views (which is the preferred method). Instead, these UI elements
// are drawn directly on the canvas from within Tab::OnPaint(). The Tab's
// child Views (for example, the Tab's close button which is a views::Button
// instance) are automatically mirrored by the mirroring infrastructure in
// views. The elements Tab draws directly on the canvas need to be manually
// mirrored if the View's layout is right-to-left.
title_bounds_.set_x(GetMirroredXForRect(title_bounds_));
} }
void Tab::OnThemeChanged() { void Tab::OnThemeChanged() {
...@@ -846,7 +840,7 @@ bool Tab::GetTooltipText(const gfx::Point& p, base::string16* tooltip) const { ...@@ -846,7 +840,7 @@ bool Tab::GetTooltipText(const gfx::Point& p, base::string16* tooltip) const {
} }
bool Tab::GetTooltipTextOrigin(const gfx::Point& p, gfx::Point* origin) const { bool Tab::GetTooltipTextOrigin(const gfx::Point& p, gfx::Point* origin) const {
origin->set_x(title_->x() + 10); origin->set_x(title_bounds_.x() + 10);
origin->set_y(-views::TooltipManager::GetTooltipHeight() - 4); origin->set_y(-views::TooltipManager::GetTooltipHeight() - 4);
return true; return true;
} }
...@@ -989,6 +983,14 @@ void Tab::GetAccessibleState(ui::AXViewState* state) { ...@@ -989,6 +983,14 @@ void Tab::GetAccessibleState(ui::AXViewState* state) {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Tab, private // Tab, private
const gfx::Rect& Tab::GetTitleBounds() const {
return title_bounds_;
}
const gfx::Rect& Tab::GetIconBounds() const {
return favicon_bounds_;
}
void Tab::MaybeAdjustLeftForMiniTab(gfx::Rect* bounds) const { void Tab::MaybeAdjustLeftForMiniTab(gfx::Rect* bounds) const {
if (!data().mini || width() >= kMiniTabRendererAsNormalTabWidth) if (!data().mini || width() >= kMiniTabRendererAsNormalTabWidth)
return; return;
...@@ -1026,13 +1028,13 @@ void Tab::PaintTab(gfx::Canvas* canvas) { ...@@ -1026,13 +1028,13 @@ void Tab::PaintTab(gfx::Canvas* canvas) {
PaintTabBackground(canvas); PaintTabBackground(canvas);
const SkColor title_color = GetThemeProvider()->GetColor(IsSelected() ? SkColor title_color = GetThemeProvider()->
ThemeProperties::COLOR_TAB_TEXT : GetColor(IsSelected() ?
ThemeProperties::COLOR_BACKGROUND_TAB_TEXT); ThemeProperties::COLOR_TAB_TEXT :
if (!data().mini || width() > kMiniTabRendererAsNormalTabWidth) { ThemeProperties::COLOR_BACKGROUND_TAB_TEXT);
title_->SetEnabledColor(title_color);
title_->Paint(canvas, views::CullSet()); if (!data().mini || width() > kMiniTabRendererAsNormalTabWidth)
} PaintTitle(canvas, title_color);
if (show_icon) if (show_icon)
PaintIcon(canvas); PaintIcon(canvas);
...@@ -1329,7 +1331,7 @@ void Tab::PaintActiveTabBackground(gfx::Canvas* canvas) { ...@@ -1329,7 +1331,7 @@ void Tab::PaintActiveTabBackground(gfx::Canvas* canvas) {
} }
void Tab::PaintIcon(gfx::Canvas* canvas) { void Tab::PaintIcon(gfx::Canvas* canvas) {
gfx::Rect bounds = favicon_bounds_; gfx::Rect bounds = GetIconBounds();
if (bounds.IsEmpty()) if (bounds.IsEmpty())
return; return;
...@@ -1353,9 +1355,9 @@ void Tab::PaintIcon(gfx::Canvas* canvas) { ...@@ -1353,9 +1355,9 @@ void Tab::PaintIcon(gfx::Canvas* canvas) {
gfx::ImageSkia crashed_favicon(*rb.GetImageSkiaNamed(IDR_SAD_FAVICON)); gfx::ImageSkia crashed_favicon(*rb.GetImageSkiaNamed(IDR_SAD_FAVICON));
bounds.set_y(bounds.y() + favicon_hiding_offset_); bounds.set_y(bounds.y() + favicon_hiding_offset_);
DrawIconCenter(canvas, crashed_favicon, 0, DrawIconCenter(canvas, crashed_favicon, 0,
crashed_favicon.width(), crashed_favicon.width(),
crashed_favicon.height(), crashed_favicon.height(),
bounds, true, SkPaint()); bounds, true, SkPaint());
} else if (!data().favicon.isNull()) { } else if (!data().favicon.isNull()) {
// Paint the normal favicon. // Paint the normal favicon.
DrawIconCenter(canvas, data().favicon, 0, DrawIconCenter(canvas, data().favicon, 0,
...@@ -1387,6 +1389,21 @@ void Tab::PaintMediaIndicator(gfx::Canvas* canvas) { ...@@ -1387,6 +1389,21 @@ void Tab::PaintMediaIndicator(gfx::Canvas* canvas) {
media_indicator_image.height(), true, paint); media_indicator_image.height(), true, paint);
} }
void Tab::PaintTitle(gfx::Canvas* canvas, SkColor title_color) {
// Paint the Title.
base::string16 title = data().title;
if (title.empty()) {
title = data().loading ?
l10n_util::GetStringUTF16(IDS_TAB_LOADING_TITLE) :
CoreTabHelper::GetDefaultTitle();
} else {
Browser::FormatTitleForDisplay(&title);
}
canvas->DrawFadedString(title, gfx::FontList(*font_), title_color,
GetTitleBounds(), 0);
}
void Tab::AdvanceLoadingAnimation(TabRendererData::NetworkState old_state, void Tab::AdvanceLoadingAnimation(TabRendererData::NetworkState old_state,
TabRendererData::NetworkState state) { TabRendererData::NetworkState state) {
static bool initialized = false; static bool initialized = false;
...@@ -1529,11 +1546,12 @@ void Tab::StartMediaIndicatorAnimation() { ...@@ -1529,11 +1546,12 @@ void Tab::StartMediaIndicatorAnimation() {
} }
void Tab::ScheduleIconPaint() { void Tab::ScheduleIconPaint() {
gfx::Rect bounds = favicon_bounds_; gfx::Rect bounds = GetIconBounds();
if (bounds.IsEmpty()) if (bounds.IsEmpty())
return; return;
// Extends the area to the bottom when sad_favicon is animating. // Extends the area to the bottom when sad_favicon is
// animating.
if (IsPerformingCrashAnimation()) if (IsPerformingCrashAnimation())
bounds.set_height(height() - bounds.y()); bounds.set_height(height() - bounds.y());
bounds.set_x(GetMirroredXForRect(bounds)); bounds.set_x(GetMirroredXForRect(bounds));
...@@ -1577,6 +1595,11 @@ void Tab::InitTabResources() { ...@@ -1577,6 +1595,11 @@ void Tab::InitTabResources() {
return; return;
initialized = true; initialized = true;
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
font_ = new gfx::Font(rb.GetFont(ui::ResourceBundle::BaseFont));
font_height_ = font_->GetHeight();
image_cache_ = new ImageCache(); image_cache_ = new ImageCache();
// Load the tab images once now, and maybe again later if the theme changes. // Load the tab images once now, and maybe again later if the theme changes.
......
...@@ -24,12 +24,12 @@ class TabController; ...@@ -24,12 +24,12 @@ class TabController;
namespace gfx { namespace gfx {
class Animation; class Animation;
class AnimationContainer; class AnimationContainer;
class Font;
class LinearAnimation; class LinearAnimation;
class MultiAnimation; class MultiAnimation;
} }
namespace views { namespace views {
class ImageButton; class ImageButton;
class Label;
} }
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
...@@ -185,6 +185,10 @@ class Tab : public gfx::AnimationDelegate, ...@@ -185,6 +185,10 @@ class Tab : public gfx::AnimationDelegate,
// Overridden from ui::EventHandler: // Overridden from ui::EventHandler:
virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
// Returns the bounds of the title and icon.
const gfx::Rect& GetTitleBounds() const;
const gfx::Rect& GetIconBounds() const;
// Invoked from Layout to adjust the position of the favicon or media // Invoked from Layout to adjust the position of the favicon or media
// indicator for mini tabs. // indicator for mini tabs.
void MaybeAdjustLeftForMiniTab(gfx::Rect* bounds) const; void MaybeAdjustLeftForMiniTab(gfx::Rect* bounds) const;
...@@ -208,9 +212,10 @@ class Tab : public gfx::AnimationDelegate, ...@@ -208,9 +212,10 @@ class Tab : public gfx::AnimationDelegate,
int tab_id); int tab_id);
void PaintActiveTabBackground(gfx::Canvas* canvas); void PaintActiveTabBackground(gfx::Canvas* canvas);
// Paints the favicon and media indicator icon, mirrored for RTL if needed. // Paints the favicon, media indicator icon, etc., mirrored for RTL if needed.
void PaintIcon(gfx::Canvas* canvas); void PaintIcon(gfx::Canvas* canvas);
void PaintMediaIndicator(gfx::Canvas* canvas); void PaintMediaIndicator(gfx::Canvas* canvas);
void PaintTitle(gfx::Canvas* canvas, SkColor title_color);
// Invoked if data_.network_state changes, or the network_state is not none. // Invoked if data_.network_state changes, or the network_state is not none.
void AdvanceLoadingAnimation(TabRendererData::NetworkState old_state, void AdvanceLoadingAnimation(TabRendererData::NetworkState old_state,
...@@ -321,7 +326,6 @@ class Tab : public gfx::AnimationDelegate, ...@@ -321,7 +326,6 @@ class Tab : public gfx::AnimationDelegate,
scoped_refptr<gfx::AnimationContainer> animation_container_; scoped_refptr<gfx::AnimationContainer> animation_container_;
views::ImageButton* close_button_; views::ImageButton* close_button_;
views::Label* title_;
bool tab_activated_with_last_gesture_begin_; bool tab_activated_with_last_gesture_begin_;
...@@ -329,6 +333,7 @@ class Tab : public gfx::AnimationDelegate, ...@@ -329,6 +333,7 @@ class Tab : public gfx::AnimationDelegate,
// The bounds of various sections of the display. // The bounds of various sections of the display.
gfx::Rect favicon_bounds_; gfx::Rect favicon_bounds_;
gfx::Rect title_bounds_;
gfx::Rect media_indicator_bounds_; gfx::Rect media_indicator_bounds_;
// The offset used to paint the inactive background image. // The offset used to paint the inactive background image.
...@@ -360,6 +365,9 @@ class Tab : public gfx::AnimationDelegate, ...@@ -360,6 +365,9 @@ class Tab : public gfx::AnimationDelegate,
// The current color of the close button. // The current color of the close button.
SkColor close_button_color_; SkColor close_button_color_;
static gfx::Font* font_;
static int font_height_;
// As the majority of the tabs are inactive, and painting tabs is slowish, // As the majority of the tabs are inactive, and painting tabs is slowish,
// we cache a handful of the inactive tab backgrounds here. // we cache a handful of the inactive tab backgrounds here.
static ImageCache* image_cache_; static ImageCache* image_cache_;
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/models/list_selection_model.h" #include "ui/base/models/list_selection_model.h"
#include "ui/views/controls/button/image_button.h" #include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/label.h"
#include "ui/views/test/views_test_base.h" #include "ui/views/test/views_test_base.h"
#include "ui/views/widget/widget.h" #include "ui/views/widget/widget.h"
...@@ -151,18 +150,16 @@ class TabTest : public views::ViewsTestBase { ...@@ -151,18 +150,16 @@ class TabTest : public views::ViewsTestBase {
const gfx::Rect contents_bounds = tab.GetContentsBounds(); const gfx::Rect contents_bounds = tab.GetContentsBounds();
if (tab.ShouldShowIcon()) { if (tab.ShouldShowIcon()) {
EXPECT_LE(contents_bounds.x(), tab.favicon_bounds_.x()); EXPECT_LE(contents_bounds.x(), tab.favicon_bounds_.x());
if (tab.title_->width() > 0) if (tab.title_bounds_.width() > 0)
EXPECT_LE(tab.favicon_bounds_.right(), tab.title_->x()); EXPECT_LE(tab.favicon_bounds_.right(), tab.title_bounds_.x());
EXPECT_LE(contents_bounds.y(), tab.favicon_bounds_.y()); EXPECT_LE(contents_bounds.y(), tab.favicon_bounds_.y());
EXPECT_LE(tab.favicon_bounds_.bottom(), contents_bounds.bottom()); EXPECT_LE(tab.favicon_bounds_.bottom(), contents_bounds.bottom());
} }
if (tab.ShouldShowIcon() && tab.ShouldShowMediaIndicator()) if (tab.ShouldShowIcon() && tab.ShouldShowMediaIndicator())
EXPECT_LE(tab.favicon_bounds_.right(), tab.media_indicator_bounds_.x()); EXPECT_LE(tab.favicon_bounds_.right(), tab.media_indicator_bounds_.x());
if (tab.ShouldShowMediaIndicator()) { if (tab.ShouldShowMediaIndicator()) {
if (tab.title_->width() > 0) { if (tab.title_bounds_.width() > 0)
EXPECT_LE(tab.title_->bounds().right(), EXPECT_LE(tab.title_bounds_.right(), tab.media_indicator_bounds_.x());
tab.media_indicator_bounds_.x());
}
EXPECT_LE(tab.media_indicator_bounds_.right(), contents_bounds.right()); EXPECT_LE(tab.media_indicator_bounds_.right(), contents_bounds.right());
EXPECT_LE(contents_bounds.y(), tab.media_indicator_bounds_.y()); EXPECT_LE(contents_bounds.y(), tab.media_indicator_bounds_.y());
EXPECT_LE(tab.media_indicator_bounds_.bottom(), contents_bounds.bottom()); EXPECT_LE(tab.media_indicator_bounds_.bottom(), contents_bounds.bottom());
...@@ -177,8 +174,8 @@ class TabTest : public views::ViewsTestBase { ...@@ -177,8 +174,8 @@ class TabTest : public views::ViewsTestBase {
if (tab.ShouldShowCloseBox()) { if (tab.ShouldShowCloseBox()) {
// Note: The title bounds can overlap the left-insets of the close box, // Note: The title bounds can overlap the left-insets of the close box,
// but should otherwise be to the left of the close button. // but should otherwise be to the left of the close button.
if (tab.title_->width() > 0) { if (tab.title_bounds_.width() > 0) {
EXPECT_LE(tab.title_->bounds().right(), EXPECT_LE(tab.title_bounds_.right(),
tab.close_button_->bounds().x() + tab.close_button_->bounds().x() +
tab.close_button_->GetInsets().left()); tab.close_button_->GetInsets().left());
} }
......
...@@ -38,7 +38,7 @@ ValidationMessageBubbleDelegate::ValidationMessageBubbleDelegate( ...@@ -38,7 +38,7 @@ ValidationMessageBubbleDelegate::ValidationMessageBubbleDelegate(
views::Label* label = new views::Label( views::Label* label = new views::Label(
main_text, bundle.GetFontList(ui::ResourceBundle::MediumFont)); main_text, bundle.GetFontList(ui::ResourceBundle::MediumFont));
label->SetHorizontalAlignment(gfx::ALIGN_LEFT); label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
label->set_directionality_mode(gfx::DIRECTIONALITY_FROM_TEXT); label->set_directionality_mode(views::Label::AUTO_DETECT_DIRECTIONALITY);
int text_start_x = kPadding + size.width() + kIconTextMargin; int text_start_x = kPadding + size.width() + kIconTextMargin;
int min_available = kWindowMinWidth - text_start_x - kPadding; int min_available = kWindowMinWidth - text_start_x - kPadding;
int max_available = kWindowMaxWidth - text_start_x - kPadding; int max_available = kWindowMaxWidth - text_start_x - kPadding;
...@@ -50,7 +50,8 @@ ValidationMessageBubbleDelegate::ValidationMessageBubbleDelegate( ...@@ -50,7 +50,8 @@ ValidationMessageBubbleDelegate::ValidationMessageBubbleDelegate(
if (!sub_text.empty()) { if (!sub_text.empty()) {
sub_label = new views::Label(sub_text); sub_label = new views::Label(sub_text);
sub_label->SetHorizontalAlignment(gfx::ALIGN_LEFT); sub_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
sub_label->set_directionality_mode(gfx::DIRECTIONALITY_FROM_TEXT); sub_label->set_directionality_mode(
views::Label::AUTO_DETECT_DIRECTIONALITY);
label_width = std::max(label_width, sub_label->GetPreferredSize().width()); label_width = std::max(label_width, sub_label->GetPreferredSize().width());
sub_label->SetMultiLine(true); sub_label->SetMultiLine(true);
AddChildView(sub_label); AddChildView(sub_label);
......
...@@ -20,7 +20,6 @@ enum HorizontalAlignment { ...@@ -20,7 +20,6 @@ enum HorizontalAlignment {
ALIGN_LEFT = 0, // Align the text's left edge with that of its display area. ALIGN_LEFT = 0, // Align the text's left edge with that of its display area.
ALIGN_CENTER, // Align the text's center with that of its display area. ALIGN_CENTER, // Align the text's center with that of its display area.
ALIGN_RIGHT, // Align the text's right edge with that of its display area. ALIGN_RIGHT, // Align the text's right edge with that of its display area.
ALIGN_TO_HEAD, // Align the text to its first strong character's direction.
}; };
// The directionality modes used to determine the base text direction. // The directionality modes used to determine the base text direction.
......
...@@ -198,11 +198,8 @@ int InnerBoundedLabel::GetTextFlags() { ...@@ -198,11 +198,8 @@ int InnerBoundedLabel::GetTextFlags() {
if (SkColorGetA(background_color()) != 0xFF) if (SkColorGetA(background_color()) != 0xFF)
flags |= gfx::Canvas::NO_SUBPIXEL_RENDERING; flags |= gfx::Canvas::NO_SUBPIXEL_RENDERING;
if (directionality_mode() == gfx::DIRECTIONALITY_FORCE_LTR) { if (directionality_mode() ==
flags |= gfx::Canvas::FORCE_LTR_DIRECTIONALITY; views::Label::AUTO_DETECT_DIRECTIONALITY) {
} else if (directionality_mode() == gfx::DIRECTIONALITY_FORCE_RTL) {
flags |= gfx::Canvas::FORCE_RTL_DIRECTIONALITY;
} else if (directionality_mode() == gfx::DIRECTIONALITY_FROM_TEXT) {
base::i18n::TextDirection direction = base::i18n::TextDirection direction =
base::i18n::GetFirstStrongCharacterDirection(text()); base::i18n::GetFirstStrongCharacterDirection(text());
if (direction == base::i18n::RIGHT_TO_LEFT) if (direction == base::i18n::RIGHT_TO_LEFT)
......
...@@ -128,7 +128,7 @@ void LabelButton::SetElideBehavior(gfx::ElideBehavior elide_behavior) { ...@@ -128,7 +128,7 @@ void LabelButton::SetElideBehavior(gfx::ElideBehavior elide_behavior) {
} }
gfx::HorizontalAlignment LabelButton::GetHorizontalAlignment() const { gfx::HorizontalAlignment LabelButton::GetHorizontalAlignment() const {
return label_->GetHorizontalAlignment(); return label_->horizontal_alignment();
} }
void LabelButton::SetHorizontalAlignment(gfx::HorizontalAlignment alignment) { void LabelButton::SetHorizontalAlignment(gfx::HorizontalAlignment alignment) {
......
...@@ -120,9 +120,11 @@ void Label::ClearEmbellishing() { ...@@ -120,9 +120,11 @@ void Label::ClearEmbellishing() {
} }
void Label::SetHorizontalAlignment(gfx::HorizontalAlignment alignment) { void Label::SetHorizontalAlignment(gfx::HorizontalAlignment alignment) {
// If the UI layout is right-to-left, flip the alignment direction. // If the View's UI layout is right-to-left and directionality_mode_ is
if (base::i18n::IsRTL() && // USE_UI_DIRECTIONALITY, we need to flip the alignment so that the alignment
(alignment == gfx::ALIGN_LEFT || alignment == gfx::ALIGN_RIGHT)) { // settings take into account the text directionality.
if (base::i18n::IsRTL() && (directionality_mode_ == USE_UI_DIRECTIONALITY) &&
(alignment != gfx::ALIGN_CENTER)) {
alignment = (alignment == gfx::ALIGN_LEFT) ? alignment = (alignment == gfx::ALIGN_LEFT) ?
gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT; gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT;
} }
...@@ -132,15 +134,6 @@ void Label::SetHorizontalAlignment(gfx::HorizontalAlignment alignment) { ...@@ -132,15 +134,6 @@ void Label::SetHorizontalAlignment(gfx::HorizontalAlignment alignment) {
} }
} }
gfx::HorizontalAlignment Label::GetHorizontalAlignment() const {
if (horizontal_alignment_ != gfx::ALIGN_TO_HEAD)
return horizontal_alignment_;
const base::i18n::TextDirection dir =
base::i18n::GetFirstStrongCharacterDirection(layout_text());
return dir == base::i18n::RIGHT_TO_LEFT ? gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT;
}
void Label::SetLineHeight(int height) { void Label::SetLineHeight(int height) {
if (height != line_height_) { if (height != line_height_) {
line_height_ = height; line_height_ = height;
...@@ -412,7 +405,7 @@ void Label::Init(const base::string16& text, const gfx::FontList& font_list) { ...@@ -412,7 +405,7 @@ void Label::Init(const base::string16& text, const gfx::FontList& font_list) {
allow_character_break_ = false; allow_character_break_ = false;
elide_behavior_ = gfx::ELIDE_TAIL; elide_behavior_ = gfx::ELIDE_TAIL;
collapse_when_hidden_ = false; collapse_when_hidden_ = false;
directionality_mode_ = gfx::DIRECTIONALITY_FROM_UI; directionality_mode_ = USE_UI_DIRECTIONALITY;
enabled_shadow_color_ = 0; enabled_shadow_color_ = 0;
disabled_shadow_color_ = 0; disabled_shadow_color_ = 0;
shadow_offset_.SetPoint(1, 1); shadow_offset_.SetPoint(1, 1);
...@@ -437,27 +430,33 @@ void Label::RecalculateColors() { ...@@ -437,27 +430,33 @@ void Label::RecalculateColors() {
} }
gfx::Rect Label::GetTextBounds() const { gfx::Rect Label::GetTextBounds() const {
gfx::Rect available(GetAvailableRect()); gfx::Rect available_rect(GetAvailableRect());
gfx::Size text_size(GetTextSize()); gfx::Size text_size(GetTextSize());
text_size.set_width(std::min(available.width(), text_size.width())); text_size.set_width(std::min(available_rect.width(), text_size.width()));
gfx::Point origin(GetInsets().left(), GetInsets().top());
switch (GetHorizontalAlignment()) { gfx::Insets insets = GetInsets();
gfx::Point text_origin(insets.left(), insets.top());
switch (horizontal_alignment_) {
case gfx::ALIGN_LEFT: case gfx::ALIGN_LEFT:
break; break;
case gfx::ALIGN_CENTER: case gfx::ALIGN_CENTER:
// Put any extra margin pixel on the left to match the legacy behavior // We put any extra margin pixel on the left rather than the right. We
// from the use of GetTextExtentPoint32() on Windows. // used to do this because measurement on Windows used
origin.Offset((available.width() + 1 - text_size.width()) / 2, 0); // GetTextExtentPoint32(), which could report a value one too large on the
// right; we now use DrawText(), and who knows if it can also do this.
text_origin.Offset((available_rect.width() + 1 - text_size.width()) / 2,
0);
break; break;
case gfx::ALIGN_RIGHT: case gfx::ALIGN_RIGHT:
origin.set_x(available.right() - text_size.width()); text_origin.set_x(available_rect.right() - text_size.width());
break; break;
default: default:
NOTREACHED(); NOTREACHED();
break; break;
} }
origin.Offset(0, std::max(0, (available.height() - text_size.height())) / 2); text_origin.Offset(0,
return gfx::Rect(origin, text_size); std::max(0, (available_rect.height() - text_size.height())) / 2);
return gfx::Rect(text_origin, text_size);
} }
int Label::ComputeDrawStringFlags() const { int Label::ComputeDrawStringFlags() const {
...@@ -467,11 +466,7 @@ int Label::ComputeDrawStringFlags() const { ...@@ -467,11 +466,7 @@ int Label::ComputeDrawStringFlags() const {
if (SkColorGetA(background_color_) != 0xFF) if (SkColorGetA(background_color_) != 0xFF)
flags |= gfx::Canvas::NO_SUBPIXEL_RENDERING; flags |= gfx::Canvas::NO_SUBPIXEL_RENDERING;
if (directionality_mode_ == gfx::DIRECTIONALITY_FORCE_LTR) { if (directionality_mode_ == AUTO_DETECT_DIRECTIONALITY) {
flags |= gfx::Canvas::FORCE_LTR_DIRECTIONALITY;
} else if (directionality_mode_ == gfx::DIRECTIONALITY_FORCE_RTL) {
flags |= gfx::Canvas::FORCE_RTL_DIRECTIONALITY;
} else if (directionality_mode_ == gfx::DIRECTIONALITY_FROM_TEXT) {
base::i18n::TextDirection direction = base::i18n::TextDirection direction =
base::i18n::GetFirstStrongCharacterDirection(layout_text()); base::i18n::GetFirstStrongCharacterDirection(layout_text());
if (direction == base::i18n::RIGHT_TO_LEFT) if (direction == base::i18n::RIGHT_TO_LEFT)
...@@ -480,7 +475,7 @@ int Label::ComputeDrawStringFlags() const { ...@@ -480,7 +475,7 @@ int Label::ComputeDrawStringFlags() const {
flags |= gfx::Canvas::FORCE_LTR_DIRECTIONALITY; flags |= gfx::Canvas::FORCE_LTR_DIRECTIONALITY;
} }
switch (GetHorizontalAlignment()) { switch (horizontal_alignment_) {
case gfx::ALIGN_LEFT: case gfx::ALIGN_LEFT:
flags |= gfx::Canvas::TEXT_ALIGN_LEFT; flags |= gfx::Canvas::TEXT_ALIGN_LEFT;
break; break;
...@@ -490,9 +485,6 @@ int Label::ComputeDrawStringFlags() const { ...@@ -490,9 +485,6 @@ int Label::ComputeDrawStringFlags() const {
case gfx::ALIGN_RIGHT: case gfx::ALIGN_RIGHT:
flags |= gfx::Canvas::TEXT_ALIGN_RIGHT; flags |= gfx::Canvas::TEXT_ALIGN_RIGHT;
break; break;
default:
NOTREACHED();
break;
} }
if (!is_multi_line_) if (!is_multi_line_)
......
...@@ -18,9 +18,30 @@ ...@@ -18,9 +18,30 @@
namespace views { namespace views {
// A view subclass that can display a string. /////////////////////////////////////////////////////////////////////////////
//
// Label class
//
// A label is a view subclass that can display a string.
//
/////////////////////////////////////////////////////////////////////////////
class VIEWS_EXPORT Label : public View { class VIEWS_EXPORT Label : public View {
public: public:
// The following enum is used to indicate whether using the Chrome UI's
// directionality as the label's directionality, or auto-detecting the label's
// directionality.
//
// If the label text originates from the Chrome UI, we should use the Chrome
// UI's directionality as the label's directionality.
//
// If the text originates from a web page, its directionality is determined
// based on its first character with strong directionality, disregarding what
// directionality the Chrome UI is.
enum DirectionalityMode {
USE_UI_DIRECTIONALITY = 0,
AUTO_DETECT_DIRECTIONALITY
};
// Internal class name. // Internal class name.
static const char kViewClassName[]; static const char kViewClassName[];
...@@ -73,17 +94,28 @@ class VIEWS_EXPORT Label : public View { ...@@ -73,17 +94,28 @@ class VIEWS_EXPORT Label : public View {
// Set the color of a halo on the painted text (use transparent for none). // Set the color of a halo on the painted text (use transparent for none).
void set_halo_color(SkColor halo_color) { halo_color_ = halo_color; } void set_halo_color(SkColor halo_color) { halo_color_ = halo_color; }
// Sets the horizontal alignment; the argument value is mirrored in RTL UI. // Sets horizontal alignment. If the locale is RTL, and the directionality
// mode is USE_UI_DIRECTIONALITY, the alignment is flipped around.
//
// Caveat: for labels originating from a web page, the directionality mode
// should be reset to AUTO_DETECT_DIRECTIONALITY before the horizontal
// alignment is set. Otherwise, the label's alignment specified as a parameter
// will be flipped in RTL locales.
void SetHorizontalAlignment(gfx::HorizontalAlignment alignment); void SetHorizontalAlignment(gfx::HorizontalAlignment alignment);
gfx::HorizontalAlignment GetHorizontalAlignment() const;
// Sets the directionality mode. The default value is DIRECTIONALITY_FROM_UI, gfx::HorizontalAlignment horizontal_alignment() const {
// which should be suitable for most text originating from UI string assets. return horizontal_alignment_;
// Most text originating from web content should use DIRECTIONALITY_FROM_TEXT. }
void set_directionality_mode(gfx::DirectionalityMode mode) {
// Sets the directionality mode. The directionality mode is initialized to
// USE_UI_DIRECTIONALITY when the label is constructed. USE_UI_DIRECTIONALITY
// applies to every label that originates from the Chrome UI. However, if the
// label originates from a web page, its directionality is auto-detected.
void set_directionality_mode(DirectionalityMode mode) {
directionality_mode_ = mode; directionality_mode_ = mode;
} }
gfx::DirectionalityMode directionality_mode() const {
DirectionalityMode directionality_mode() const {
return directionality_mode_; return directionality_mode_;
} }
...@@ -180,7 +212,9 @@ class VIEWS_EXPORT Label : public View { ...@@ -180,7 +212,9 @@ class VIEWS_EXPORT Label : public View {
FRIEND_TEST_ALL_PREFIXES(LabelTest, DrawMultiLineString); FRIEND_TEST_ALL_PREFIXES(LabelTest, DrawMultiLineString);
FRIEND_TEST_ALL_PREFIXES(LabelTest, DrawSingleLineStringInRTL); FRIEND_TEST_ALL_PREFIXES(LabelTest, DrawSingleLineStringInRTL);
FRIEND_TEST_ALL_PREFIXES(LabelTest, DrawMultiLineStringInRTL); FRIEND_TEST_ALL_PREFIXES(LabelTest, DrawMultiLineStringInRTL);
FRIEND_TEST_ALL_PREFIXES(LabelTest, DirectionalityFromText); FRIEND_TEST_ALL_PREFIXES(LabelTest, AutoDetectDirectionality);
// Calls ComputeDrawStringFlags().
FRIEND_TEST_ALL_PREFIXES(LabelTest, DisableSubpixelRendering); FRIEND_TEST_ALL_PREFIXES(LabelTest, DisableSubpixelRendering);
// Sets both |text_| and |layout_text_| to appropriate values, taking // Sets both |text_| and |layout_text_| to appropriate values, taking
...@@ -238,9 +272,10 @@ class VIEWS_EXPORT Label : public View { ...@@ -238,9 +272,10 @@ class VIEWS_EXPORT Label : public View {
base::string16 tooltip_text_; base::string16 tooltip_text_;
// Whether to collapse the label when it's not visible. // Whether to collapse the label when it's not visible.
bool collapse_when_hidden_; bool collapse_when_hidden_;
// Controls whether the directionality is auto-detected based on first strong // The following member variable is used to control whether the
// directionality character or is determined by the application UI's locale. // directionality is auto-detected based on first strong directionality
gfx::DirectionalityMode directionality_mode_; // character or is determined by chrome UI's locale.
DirectionalityMode directionality_mode_;
// Colors for shadow. // Colors for shadow.
SkColor enabled_shadow_color_; SkColor enabled_shadow_color_;
......
...@@ -19,13 +19,6 @@ namespace views { ...@@ -19,13 +19,6 @@ namespace views {
// All text sizing measurements (width and height) should be greater than this. // All text sizing measurements (width and height) should be greater than this.
const int kMinTextDimension = 4; const int kMinTextDimension = 4;
// A test utility function to set the application default text direction.
void SetRTL(bool rtl) {
// Override the current locale/direction.
base::i18n::SetICUDefaultLocale(rtl ? "he" : "en");
EXPECT_EQ(rtl, base::i18n::IsRTL());
}
TEST(LabelTest, FontPropertySymbol) { TEST(LabelTest, FontPropertySymbol) {
Label label; Label label;
std::string font_name("symbol"); std::string font_name("symbol");
...@@ -62,45 +55,38 @@ TEST(LabelTest, ColorProperty) { ...@@ -62,45 +55,38 @@ TEST(LabelTest, ColorProperty) {
} }
TEST(LabelTest, AlignmentProperty) { TEST(LabelTest, AlignmentProperty) {
const bool was_rtl = base::i18n::IsRTL();
Label label; Label label;
for (size_t i = 0; i < 2; ++i) { bool reverse_alignment = base::i18n::IsRTL();
// Toggle the application default text direction (to try each direction).
SetRTL(!base::i18n::IsRTL()); label.SetHorizontalAlignment(gfx::ALIGN_RIGHT);
bool reverse_alignment = base::i18n::IsRTL(); EXPECT_EQ(reverse_alignment ? gfx::ALIGN_LEFT : gfx::ALIGN_RIGHT,
label.horizontal_alignment());
// The alignment should be flipped in RTL UI. label.SetHorizontalAlignment(gfx::ALIGN_LEFT);
label.SetHorizontalAlignment(gfx::ALIGN_RIGHT); EXPECT_EQ(reverse_alignment ? gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT,
EXPECT_EQ(reverse_alignment ? gfx::ALIGN_LEFT : gfx::ALIGN_RIGHT, label.horizontal_alignment());
label.GetHorizontalAlignment()); label.SetHorizontalAlignment(gfx::ALIGN_CENTER);
label.SetHorizontalAlignment(gfx::ALIGN_LEFT); EXPECT_EQ(gfx::ALIGN_CENTER, label.horizontal_alignment());
EXPECT_EQ(reverse_alignment ? gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT,
label.GetHorizontalAlignment()); // The label's alignment should not be flipped if the directionality mode is
label.SetHorizontalAlignment(gfx::ALIGN_CENTER); // AUTO_DETECT_DIRECTIONALITY.
EXPECT_EQ(gfx::ALIGN_CENTER, label.GetHorizontalAlignment()); label.set_directionality_mode(Label::AUTO_DETECT_DIRECTIONALITY);
label.SetHorizontalAlignment(gfx::ALIGN_RIGHT);
for (size_t j = 0; j < 2; ++j) { EXPECT_EQ(gfx::ALIGN_RIGHT, label.horizontal_alignment());
label.SetHorizontalAlignment(gfx::ALIGN_TO_HEAD); label.SetHorizontalAlignment(gfx::ALIGN_LEFT);
const bool rtl = j == 0; EXPECT_EQ(gfx::ALIGN_LEFT, label.horizontal_alignment());
label.SetText(rtl ? base::WideToUTF16(L"\x5d0") : ASCIIToUTF16("A")); label.SetHorizontalAlignment(gfx::ALIGN_CENTER);
EXPECT_EQ(rtl ? gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT, EXPECT_EQ(gfx::ALIGN_CENTER, label.horizontal_alignment());
label.GetHorizontalAlignment());
}
}
EXPECT_EQ(was_rtl, base::i18n::IsRTL());
} }
TEST(LabelTest, DirectionalityModeProperty) { TEST(LabelTest, DirectionalityModeProperty) {
Label label; Label label;
EXPECT_EQ(gfx::DIRECTIONALITY_FROM_UI, label.directionality_mode()); EXPECT_EQ(Label::USE_UI_DIRECTIONALITY, label.directionality_mode());
label.set_directionality_mode(gfx::DIRECTIONALITY_FROM_TEXT); label.set_directionality_mode(Label::AUTO_DETECT_DIRECTIONALITY);
EXPECT_EQ(gfx::DIRECTIONALITY_FROM_TEXT, label.directionality_mode()); EXPECT_EQ(Label::AUTO_DETECT_DIRECTIONALITY, label.directionality_mode());
label.set_directionality_mode(gfx::DIRECTIONALITY_FROM_UI); label.set_directionality_mode(Label::USE_UI_DIRECTIONALITY);
EXPECT_EQ(gfx::DIRECTIONALITY_FROM_UI, label.directionality_mode()); EXPECT_EQ(Label::USE_UI_DIRECTIONALITY, label.directionality_mode());
} }
TEST(LabelTest, MultiLineProperty) { TEST(LabelTest, MultiLineProperty) {
...@@ -331,16 +317,20 @@ TEST(LabelTest, MultiLineSizing) { ...@@ -331,16 +317,20 @@ TEST(LabelTest, MultiLineSizing) {
required_size.width() + border.width()); required_size.width() + border.width());
} }
TEST(LabelTest, DirectionalityFromText) { TEST(LabelTest, AutoDetectDirectionality) {
Label label; Label label;
label.set_directionality_mode(gfx::DIRECTIONALITY_FROM_TEXT); label.set_directionality_mode(Label::AUTO_DETECT_DIRECTIONALITY);
label.SetBounds(0, 0, 1000, 1000);
base::string16 paint_text;
gfx::Rect text_bounds;
int flags = -1;
// Test text starts with RTL character. // Test text starts with RTL character.
label.SetText(base::WideToUTF16(L" \x5d0\x5d1\x5d2 abc")); label.SetText(base::WideToUTF16(L" \x5d0\x5d1\x5d2 abc"));
gfx::Size required_size(label.GetPreferredSize());
gfx::Size extra(22, 8);
label.SetBounds(0, 0, required_size.width() + extra.width(),
required_size.height() + extra.height());
base::string16 paint_text;
gfx::Rect text_bounds;
int flags;
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
EXPECT_EQ(gfx::Canvas::FORCE_RTL_DIRECTIONALITY, EXPECT_EQ(gfx::Canvas::FORCE_RTL_DIRECTIONALITY,
flags & (gfx::Canvas::FORCE_RTL_DIRECTIONALITY | flags & (gfx::Canvas::FORCE_RTL_DIRECTIONALITY |
...@@ -348,6 +338,10 @@ TEST(LabelTest, DirectionalityFromText) { ...@@ -348,6 +338,10 @@ TEST(LabelTest, DirectionalityFromText) {
// Test text starts with LTR character. // Test text starts with LTR character.
label.SetText(base::WideToUTF16(L"ltr \x5d0\x5d1\x5d2 abc")); label.SetText(base::WideToUTF16(L"ltr \x5d0\x5d1\x5d2 abc"));
required_size = label.GetPreferredSize();
label.SetBounds(0, 0, required_size.width() + extra.width(),
required_size.height() + extra.height());
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
EXPECT_EQ(gfx::Canvas::FORCE_LTR_DIRECTIONALITY, EXPECT_EQ(gfx::Canvas::FORCE_LTR_DIRECTIONALITY,
flags & (gfx::Canvas::FORCE_RTL_DIRECTIONALITY | flags & (gfx::Canvas::FORCE_RTL_DIRECTIONALITY |
...@@ -357,8 +351,10 @@ TEST(LabelTest, DirectionalityFromText) { ...@@ -357,8 +351,10 @@ TEST(LabelTest, DirectionalityFromText) {
TEST(LabelTest, DrawSingleLineString) { TEST(LabelTest, DrawSingleLineString) {
Label label; Label label;
label.SetFocusable(false); label.SetFocusable(false);
// Force a directionality to simplify alignment value testing.
label.set_directionality_mode(gfx::DIRECTIONALITY_FORCE_LTR); // Turn off mirroring so that we don't need to figure out if
// align right really means align left.
label.set_directionality_mode(Label::AUTO_DETECT_DIRECTIONALITY);
label.SetText(ASCIIToUTF16("Here's a string with no returns.")); label.SetText(ASCIIToUTF16("Here's a string with no returns."));
gfx::Size required_size(label.GetPreferredSize()); gfx::Size required_size(label.GetPreferredSize());
...@@ -369,7 +365,7 @@ TEST(LabelTest, DrawSingleLineString) { ...@@ -369,7 +365,7 @@ TEST(LabelTest, DrawSingleLineString) {
// Do some basic verifications for all three alignments. // Do some basic verifications for all three alignments.
base::string16 paint_text; base::string16 paint_text;
gfx::Rect text_bounds; gfx::Rect text_bounds;
int flags = -1; int flags;
// Centered text. // Centered text.
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
...@@ -478,14 +474,16 @@ TEST(LabelTest, DrawSingleLineString) { ...@@ -478,14 +474,16 @@ TEST(LabelTest, DrawSingleLineString) {
gfx::Canvas::TEXT_ALIGN_RIGHT)); gfx::Canvas::TEXT_ALIGN_RIGHT));
} }
// Pango needs a max height to elide multiline text; that is not supported here. // On Linux the underlying pango routines require a max height in order to
// ellide multiline text. So until that can be resolved, we set all
// multiline lables to not ellide in Linux only.
TEST(LabelTest, DrawMultiLineString) { TEST(LabelTest, DrawMultiLineString) {
Label label; Label label;
label.SetFocusable(false); label.SetFocusable(false);
// Force a directionality to simplify alignment value testing.
label.set_directionality_mode(gfx::DIRECTIONALITY_FORCE_LTR); // Turn off mirroring so that we don't need to figure out if
// Set a background color to prevent gfx::Canvas::NO_SUBPIXEL_RENDERING flags. // align right really means align left.
label.SetBackgroundColor(SK_ColorWHITE); label.set_directionality_mode(Label::AUTO_DETECT_DIRECTIONALITY);
label.SetText(ASCIIToUTF16("Another string\nwith returns\n\n!")); label.SetText(ASCIIToUTF16("Another string\nwith returns\n\n!"));
label.SetMultiLine(true); label.SetMultiLine(true);
...@@ -498,7 +496,7 @@ TEST(LabelTest, DrawMultiLineString) { ...@@ -498,7 +496,7 @@ TEST(LabelTest, DrawMultiLineString) {
// Do some basic verifications for all three alignments. // Do some basic verifications for all three alignments.
base::string16 paint_text; base::string16 paint_text;
gfx::Rect text_bounds; gfx::Rect text_bounds;
int flags = -1; int flags;
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
EXPECT_EQ(label.text(), paint_text); EXPECT_EQ(label.text(), paint_text);
EXPECT_EQ(extra.width() / 2, text_bounds.x()); EXPECT_EQ(extra.width() / 2, text_bounds.x());
...@@ -511,7 +509,7 @@ TEST(LabelTest, DrawMultiLineString) { ...@@ -511,7 +509,7 @@ TEST(LabelTest, DrawMultiLineString) {
#if !defined(OS_WIN) #if !defined(OS_WIN)
expected_flags |= gfx::Canvas::NO_ELLIPSIS; expected_flags |= gfx::Canvas::NO_ELLIPSIS;
#endif #endif
EXPECT_EQ(expected_flags, expected_flags); EXPECT_EQ(expected_flags, expected_flags & flags);
gfx::Rect center_bounds(text_bounds); gfx::Rect center_bounds(text_bounds);
label.SetHorizontalAlignment(gfx::ALIGN_LEFT); label.SetHorizontalAlignment(gfx::ALIGN_LEFT);
...@@ -529,7 +527,7 @@ TEST(LabelTest, DrawMultiLineString) { ...@@ -529,7 +527,7 @@ TEST(LabelTest, DrawMultiLineString) {
#if !defined(OS_WIN) #if !defined(OS_WIN)
expected_flags |= gfx::Canvas::NO_ELLIPSIS; expected_flags |= gfx::Canvas::NO_ELLIPSIS;
#endif #endif
EXPECT_EQ(expected_flags, expected_flags); EXPECT_EQ(expected_flags, expected_flags & flags);
label.SetHorizontalAlignment(gfx::ALIGN_RIGHT); label.SetHorizontalAlignment(gfx::ALIGN_RIGHT);
paint_text.clear(); paint_text.clear();
...@@ -546,7 +544,7 @@ TEST(LabelTest, DrawMultiLineString) { ...@@ -546,7 +544,7 @@ TEST(LabelTest, DrawMultiLineString) {
#if !defined(OS_WIN) #if !defined(OS_WIN)
expected_flags |= gfx::Canvas::NO_ELLIPSIS; expected_flags |= gfx::Canvas::NO_ELLIPSIS;
#endif #endif
EXPECT_EQ(expected_flags, expected_flags); EXPECT_EQ(expected_flags, expected_flags & flags);
// Test multiline drawing with a border. // Test multiline drawing with a border.
gfx::Insets border(19, 92, 23, 2); gfx::Insets border(19, 92, 23, 2);
...@@ -572,7 +570,7 @@ TEST(LabelTest, DrawMultiLineString) { ...@@ -572,7 +570,7 @@ TEST(LabelTest, DrawMultiLineString) {
#if !defined(OS_WIN) #if !defined(OS_WIN)
expected_flags |= gfx::Canvas::NO_ELLIPSIS; expected_flags |= gfx::Canvas::NO_ELLIPSIS;
#endif #endif
EXPECT_EQ(expected_flags, expected_flags); EXPECT_EQ(expected_flags, expected_flags & flags);
label.SetHorizontalAlignment(gfx::ALIGN_LEFT); label.SetHorizontalAlignment(gfx::ALIGN_LEFT);
paint_text.clear(); paint_text.clear();
...@@ -589,7 +587,7 @@ TEST(LabelTest, DrawMultiLineString) { ...@@ -589,7 +587,7 @@ TEST(LabelTest, DrawMultiLineString) {
#if !defined(OS_WIN) #if !defined(OS_WIN)
expected_flags |= gfx::Canvas::NO_ELLIPSIS; expected_flags |= gfx::Canvas::NO_ELLIPSIS;
#endif #endif
EXPECT_EQ(expected_flags, expected_flags); EXPECT_EQ(expected_flags, expected_flags & flags);
label.SetHorizontalAlignment(gfx::ALIGN_RIGHT); label.SetHorizontalAlignment(gfx::ALIGN_RIGHT);
paint_text.clear(); paint_text.clear();
...@@ -606,7 +604,7 @@ TEST(LabelTest, DrawMultiLineString) { ...@@ -606,7 +604,7 @@ TEST(LabelTest, DrawMultiLineString) {
#if !defined(OS_WIN) #if !defined(OS_WIN)
expected_flags |= gfx::Canvas::NO_ELLIPSIS; expected_flags |= gfx::Canvas::NO_ELLIPSIS;
#endif #endif
EXPECT_EQ(expected_flags, expected_flags); EXPECT_EQ(expected_flags, expected_flags & flags);
} }
TEST(LabelTest, DrawSingleLineStringInRTL) { TEST(LabelTest, DrawSingleLineStringInRTL) {
...@@ -625,7 +623,7 @@ TEST(LabelTest, DrawSingleLineStringInRTL) { ...@@ -625,7 +623,7 @@ TEST(LabelTest, DrawSingleLineStringInRTL) {
// Do some basic verifications for all three alignments. // Do some basic verifications for all three alignments.
base::string16 paint_text; base::string16 paint_text;
gfx::Rect text_bounds; gfx::Rect text_bounds;
int flags = -1; int flags;
// Centered text. // Centered text.
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
...@@ -760,7 +758,7 @@ TEST(LabelTest, DrawMultiLineStringInRTL) { ...@@ -760,7 +758,7 @@ TEST(LabelTest, DrawMultiLineStringInRTL) {
// Do some basic verifications for all three alignments. // Do some basic verifications for all three alignments.
base::string16 paint_text; base::string16 paint_text;
gfx::Rect text_bounds; gfx::Rect text_bounds;
int flags = -1; int flags;
label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags); label.CalculateDrawStringParams(&paint_text, &text_bounds, &flags);
EXPECT_EQ(label.text(), paint_text); EXPECT_EQ(label.text(), paint_text);
EXPECT_EQ(extra.width() / 2, text_bounds.x()); EXPECT_EQ(extra.width() / 2, text_bounds.x());
......
...@@ -177,13 +177,21 @@ void MessageBoxView::Init(const InitParams& params) { ...@@ -177,13 +177,21 @@ void MessageBoxView::Init(const InitParams& params) {
if (params.options & DETECT_DIRECTIONALITY) { if (params.options & DETECT_DIRECTIONALITY) {
std::vector<base::string16> texts; std::vector<base::string16> texts;
SplitStringIntoParagraphs(params.message, &texts); SplitStringIntoParagraphs(params.message, &texts);
// If the text originates from a web page, its alignment is based on its
// first character with strong directionality.
base::i18n::TextDirection message_direction =
base::i18n::GetFirstStrongCharacterDirection(params.message);
gfx::HorizontalAlignment alignment =
(message_direction == base::i18n::RIGHT_TO_LEFT) ?
gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT;
for (size_t i = 0; i < texts.size(); ++i) { for (size_t i = 0; i < texts.size(); ++i) {
Label* message_label = new Label(texts[i]); Label* message_label = new Label(texts[i]);
// Avoid empty multi-line labels, which have a height of 0. // Don't set multi-line to true if the text is empty, else the label will
// have a height of 0.
message_label->SetMultiLine(!texts[i].empty()); message_label->SetMultiLine(!texts[i].empty());
message_label->SetAllowCharacterBreak(true); message_label->SetAllowCharacterBreak(true);
message_label->set_directionality_mode(gfx::DIRECTIONALITY_FROM_TEXT); message_label->set_directionality_mode(Label::AUTO_DETECT_DIRECTIONALITY);
message_label->SetHorizontalAlignment(gfx::ALIGN_TO_HEAD); message_label->SetHorizontalAlignment(alignment);
message_labels_.push_back(message_label); message_labels_.push_back(message_label);
} }
} else { } else {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment