1 // Copyright 2013 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 #include "ui/views/examples/multiline_example.h" 6 7 #include "base/strings/utf_string_conversions.h" 8 #include "ui/events/event.h" 9 #include "ui/gfx/render_text.h" 10 #include "ui/views/background.h" 11 #include "ui/views/border.h" 12 #include "ui/views/controls/button/checkbox.h" 13 #include "ui/views/controls/label.h" 14 #include "ui/views/controls/textfield/textfield.h" 15 #include "ui/views/layout/grid_layout.h" 16 #include "ui/views/view.h" 17 18 using base::ASCIIToUTF16; 19 20 namespace views { 21 namespace examples { 22 23 namespace { 24 25 gfx::Range ClampRange(gfx::Range range, size_t max) { 26 range.set_start(std::min(range.start(), max)); 27 range.set_end(std::min(range.end(), max)); 28 return range; 29 } 30 31 // A Label with a clamped preferred width to demonstrate wrapping. 32 class PreferredSizeLabel : public Label { 33 public: 34 PreferredSizeLabel() : Label() {} 35 virtual ~PreferredSizeLabel() {} 36 37 // Label: 38 virtual gfx::Size GetPreferredSize() const OVERRIDE { 39 return gfx::Size(50, Label::GetPreferredSize().height()); 40 } 41 42 private: 43 DISALLOW_COPY_AND_ASSIGN(PreferredSizeLabel); 44 }; 45 46 } // namespace 47 48 // A simple View that hosts a RenderText object. 49 class MultilineExample::RenderTextView : public View { 50 public: 51 RenderTextView() : render_text_(gfx::RenderText::CreateInstance()) { 52 render_text_->SetHorizontalAlignment(gfx::ALIGN_CENTER); 53 render_text_->SetColor(SK_ColorBLACK); 54 render_text_->SetMultiline(true); 55 SetBorder(Border::CreateSolidBorder(2, SK_ColorGRAY)); 56 } 57 58 virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE { 59 View::OnPaint(canvas); 60 render_text_->Draw(canvas); 61 } 62 63 virtual gfx::Size GetPreferredSize() const OVERRIDE { 64 // Turn off multiline mode to get the single-line text size, which is the 65 // preferred size for this view. 66 render_text_->SetMultiline(false); 67 gfx::Size size(render_text_->GetContentWidth(), 68 render_text_->GetStringSize().height()); 69 size.Enlarge(GetInsets().width(), GetInsets().height()); 70 render_text_->SetMultiline(true); 71 return size; 72 } 73 74 virtual int GetHeightForWidth(int w) const OVERRIDE { 75 // TODO(ckocagil): Why does this happen? 76 if (w == 0) 77 return View::GetHeightForWidth(w); 78 const gfx::Rect old_rect = render_text_->display_rect(); 79 gfx::Rect rect = old_rect; 80 rect.set_width(w - GetInsets().width()); 81 render_text_->SetDisplayRect(rect); 82 int height = render_text_->GetStringSize().height() + GetInsets().height(); 83 render_text_->SetDisplayRect(old_rect); 84 return height; 85 } 86 87 void SetText(const base::string16& new_contents) { 88 // Color and style the text inside |test_range| to test colors and styles. 89 const size_t range_max = new_contents.length(); 90 gfx::Range color_range = ClampRange(gfx::Range(1, 21), range_max); 91 gfx::Range bold_range = ClampRange(gfx::Range(4, 10), range_max); 92 gfx::Range italic_range = ClampRange(gfx::Range(7, 13), range_max); 93 94 render_text_->SetText(new_contents); 95 render_text_->SetColor(SK_ColorBLACK); 96 render_text_->ApplyColor(0xFFFF0000, color_range); 97 render_text_->SetStyle(gfx::DIAGONAL_STRIKE, false); 98 render_text_->ApplyStyle(gfx::DIAGONAL_STRIKE, true, color_range); 99 render_text_->SetStyle(gfx::UNDERLINE, false); 100 render_text_->ApplyStyle(gfx::UNDERLINE, true, color_range); 101 render_text_->ApplyStyle(gfx::BOLD, true, bold_range); 102 render_text_->ApplyStyle(gfx::ITALIC, true, italic_range); 103 InvalidateLayout(); 104 } 105 106 private: 107 virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE { 108 gfx::Rect bounds = GetLocalBounds(); 109 bounds.Inset(GetInsets()); 110 render_text_->SetDisplayRect(bounds); 111 } 112 113 scoped_ptr<gfx::RenderText> render_text_; 114 115 DISALLOW_COPY_AND_ASSIGN(RenderTextView); 116 }; 117 118 MultilineExample::MultilineExample() 119 : ExampleBase("Multiline RenderText"), 120 render_text_view_(NULL), 121 label_(NULL), 122 textfield_(NULL), 123 label_checkbox_(NULL) { 124 } 125 126 MultilineExample::~MultilineExample() { 127 } 128 129 void MultilineExample::CreateExampleView(View* container) { 130 const base::string16 kTestString = base::WideToUTF16(L"qwerty" 131 L"\x627\x644\x631\x626\x64A\x633\x64A\x629" 132 L"asdfgh"); 133 134 render_text_view_ = new RenderTextView(); 135 render_text_view_->SetText(kTestString); 136 137 label_ = new PreferredSizeLabel(); 138 label_->SetText(kTestString); 139 label_->SetMultiLine(true); 140 label_->SetBorder(Border::CreateSolidBorder(2, SK_ColorCYAN)); 141 142 label_checkbox_ = new Checkbox(ASCIIToUTF16("views::Label:")); 143 label_checkbox_->SetChecked(true); 144 label_checkbox_->set_listener(this); 145 label_checkbox_->set_request_focus_on_press(false); 146 147 textfield_ = new Textfield(); 148 textfield_->set_controller(this); 149 textfield_->SetText(kTestString); 150 151 GridLayout* layout = new GridLayout(container); 152 container->SetLayoutManager(layout); 153 154 ColumnSet* column_set = layout->AddColumnSet(0); 155 column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 156 0.0f, GridLayout::USE_PREF, 0, 0); 157 column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 158 1.0f, GridLayout::FIXED, 0, 0); 159 160 layout->StartRow(0, 0); 161 layout->AddView(new Label(ASCIIToUTF16("gfx::RenderText:"))); 162 layout->AddView(render_text_view_); 163 164 layout->StartRow(0, 0); 165 layout->AddView(label_checkbox_); 166 layout->AddView(label_); 167 168 layout->StartRow(0, 0); 169 layout->AddView(new Label(ASCIIToUTF16("Sample Text:"))); 170 layout->AddView(textfield_); 171 } 172 173 void MultilineExample::ContentsChanged(Textfield* sender, 174 const base::string16& new_contents) { 175 render_text_view_->SetText(new_contents); 176 if (label_checkbox_->checked()) 177 label_->SetText(new_contents); 178 container()->Layout(); 179 container()->SchedulePaint(); 180 } 181 182 void MultilineExample::ButtonPressed(Button* sender, const ui::Event& event) { 183 DCHECK_EQ(sender, label_checkbox_); 184 label_->SetText(label_checkbox_->checked() ? textfield_->text() : 185 base::string16()); 186 container()->Layout(); 187 container()->SchedulePaint(); 188 } 189 190 } // namespace examples 191 } // namespace views 192