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#include "ui/views/examples/text_example.h"
6
7#include "base/strings/utf_string_conversions.h"
8#include "ui/gfx/canvas.h"
9#include "ui/gfx/font_list.h"
10#include "ui/views/border.h"
11#include "ui/views/controls/button/checkbox.h"
12#include "ui/views/controls/combobox/combobox.h"
13#include "ui/views/controls/label.h"
14#include "ui/views/examples/example_combobox_model.h"
15#include "ui/views/layout/grid_layout.h"
16#include "ui/views/view.h"
17
18namespace views {
19namespace examples {
20
21namespace {
22
23// Number of columns in the view layout.
24const int kNumColumns = 10;
25
26const char kShortText[] = "The quick brown fox jumps over the lazy dog.";
27const char kLongText[] =
28    "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod "
29    "tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim "
30    "veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea "
31    "commodo consequat.\nDuis aute irure dolor in reprehenderit in voluptate "
32    "velit esse cillum dolore eu fugiat nulla pariatur.\n\nExcepteur sint "
33    "occaecat cupidatat non proident, sunt in culpa qui officia deserunt "
34    "mollit anim id est laborum.";
35const char kAmpersandText[] =
36    "The quick && &brown fo&x jumps over the lazy dog.";
37const wchar_t kRightToLeftText[] =
38    L"\x5e9\x5dc\x5d5\x5dd \x5d4\x5e2\x5d5\x5dc\x5dd! "
39    L"\x5e9\x5dc\x5d5\x5dd \x5d4\x5e2\x5d5\x5dc\x5dd! "
40    L"\x5e9\x5dc\x5d5\x5dd \x5d4\x5e2\x5d5\x5dc\x5dd! "
41    L"\x5e9\x5dc\x5d5\x5dd \x5d4\x5e2\x5d5\x5dc\x5dd! "
42    L"\x5e9\x5dc\x5d5\x5dd \x5d4\x5e2\x5d5\x5dc\x5dd! "
43    L"\x5e9\x5dc\x5d5\x5dd \x5d4\x5e2\x5d5\x5dc\x5dd! "
44    L"\x5e9\x5dc\x5d5\x5dd \x5d4\x5e2\x5d5\x5dc\x5dd! "
45    L"\x5e9\x5dc\x5d5\x5dd \x5d4\x5e2\x5d5\x5dc\x5dd!";
46
47const char* kTextExamples[] = { "Short", "Long", "Ampersands", "RTL Hebrew", };
48const char* kElideBehaviors[] = { "Elide", "No Elide", "Fade", };
49const char* kPrefixOptions[] = { "Default", "Show", "Hide", };
50const char* kHorizontalAligments[] = { "Default", "Left", "Center", "Right", };
51
52// Toggles bit |flag| on |flags| based on state of |checkbox|.
53void SetFlagFromCheckbox(Checkbox* checkbox, int* flags, int flag) {
54  if (checkbox->checked())
55    *flags |= flag;
56  else
57    *flags &= ~flag;
58}
59
60}  // namespace
61
62// TextExample's content view, which draws stylized string.
63class TextExample::TextExampleView : public View {
64 public:
65  TextExampleView()
66    : text_(base::ASCIIToUTF16(kShortText)),
67      flags_(0),
68      halo_(false),
69      elide_(gfx::NO_ELIDE) {
70  }
71
72  virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE {
73    View::OnPaint(canvas);
74    const gfx::Rect bounds = GetContentsBounds();
75    const SkColor color = SK_ColorDKGRAY;
76    if (elide_ == gfx::FADE_TAIL) {
77      canvas->DrawFadedString(text_, font_list_, color, bounds, flags_);
78    } else if (halo_) {
79      canvas->DrawStringRectWithHalo(text_, font_list_, color, SK_ColorYELLOW,
80                                     bounds, flags_);
81    } else {
82      canvas->DrawStringRectWithFlags(text_, font_list_, color, bounds, flags_);
83    }
84  }
85
86  int flags() const { return flags_; }
87  void set_flags(int flags) { flags_ = flags; }
88  void set_text(const base::string16& text) { text_ = text; }
89  void set_halo(bool halo) { halo_ = halo; }
90  void set_elide(gfx::ElideBehavior elide) { elide_ = elide; }
91
92  int GetStyle() const { return font_list_.GetFontStyle(); }
93  void SetStyle(int style) { font_list_ = font_list_.DeriveWithStyle(style); }
94
95 private:
96  // The font used for drawing the text.
97  gfx::FontList font_list_;
98
99  // The text to draw.
100  base::string16 text_;
101
102  // Text flags for passing to |DrawStringRect()|.
103  int flags_;
104
105  // A flag to draw a halo around the text.
106  bool halo_;
107
108  // The eliding, fading, or truncating behavior.
109  gfx::ElideBehavior elide_;
110
111  DISALLOW_COPY_AND_ASSIGN(TextExampleView);
112};
113
114TextExample::TextExample() : ExampleBase("Text Styles") {}
115
116TextExample::~TextExample() {
117  // Remove the views first as some reference combobox models.
118  container()->RemoveAllChildViews(true);
119}
120
121Checkbox* TextExample::AddCheckbox(GridLayout* layout, const char* name) {
122  Checkbox* checkbox = new Checkbox(base::ASCIIToUTF16(name));
123  checkbox->set_listener(this);
124  layout->AddView(checkbox);
125  return checkbox;
126}
127
128Combobox* TextExample::AddCombobox(GridLayout* layout,
129                                   const char* name,
130                                   const char** strings,
131                                   int count) {
132  layout->StartRow(0, 0);
133  layout->AddView(new Label(base::ASCIIToUTF16(name)));
134  ExampleComboboxModel* model = new ExampleComboboxModel(strings, count);
135  example_combobox_model_.push_back(model);
136  Combobox* combobox = new Combobox(model);
137  combobox->SetSelectedIndex(0);
138  combobox->set_listener(this);
139  layout->AddView(combobox, kNumColumns - 1, 1);
140  return combobox;
141}
142
143void TextExample::CreateExampleView(View* container) {
144  text_view_ = new TextExampleView;
145  text_view_->SetBorder(Border::CreateSolidBorder(1, SK_ColorGRAY));
146  GridLayout* layout = new GridLayout(container);
147  container->SetLayoutManager(layout);
148  layout->AddPaddingRow(0, 8);
149
150  ColumnSet* column_set = layout->AddColumnSet(0);
151  column_set->AddPaddingColumn(0, 8);
152  column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL,
153                        0.1f, GridLayout::USE_PREF, 0, 0);
154  for (int i = 0; i < kNumColumns - 1; i++)
155    column_set->AddColumn(GridLayout::FILL, GridLayout::FILL,
156                          0.1f, GridLayout::USE_PREF, 0, 0);
157  column_set->AddPaddingColumn(0, 8);
158
159  h_align_cb_ = AddCombobox(layout, "H-Align", kHorizontalAligments,
160                            arraysize(kHorizontalAligments));
161  eliding_cb_ = AddCombobox(layout, "Eliding", kElideBehaviors,
162                            arraysize(kElideBehaviors));
163  prefix_cb_ = AddCombobox(layout, "Prefix", kPrefixOptions,
164                           arraysize(kPrefixOptions));
165  text_cb_ = AddCombobox(layout, "Example Text", kTextExamples,
166                         arraysize(kTextExamples));
167
168  layout->StartRow(0, 0);
169  multiline_checkbox_ = AddCheckbox(layout, "Multiline");
170  break_checkbox_ = AddCheckbox(layout, "Character Break");
171  halo_checkbox_ = AddCheckbox(layout, "Halo");
172  bold_checkbox_ = AddCheckbox(layout, "Bold");
173  italic_checkbox_ = AddCheckbox(layout, "Italic");
174  underline_checkbox_ = AddCheckbox(layout, "Underline");
175
176  layout->AddPaddingRow(0, 20);
177  column_set = layout->AddColumnSet(1);
178  column_set->AddPaddingColumn(0, 16);
179  column_set->AddColumn(GridLayout::FILL, GridLayout::FILL,
180                        1, GridLayout::USE_PREF, 0, 0);
181  column_set->AddPaddingColumn(0, 16);
182  layout->StartRow(1, 1);
183  layout->AddView(text_view_);
184  layout->AddPaddingRow(0, 8);
185}
186
187void TextExample::ButtonPressed(Button* button, const ui::Event& event) {
188  int flags = text_view_->flags();
189  int style = text_view_->GetStyle();
190  SetFlagFromCheckbox(multiline_checkbox_, &flags, gfx::Canvas::MULTI_LINE);
191  SetFlagFromCheckbox(break_checkbox_, &flags, gfx::Canvas::CHARACTER_BREAK);
192  SetFlagFromCheckbox(bold_checkbox_, &style, gfx::Font::BOLD);
193  SetFlagFromCheckbox(italic_checkbox_, &style, gfx::Font::ITALIC);
194  SetFlagFromCheckbox(underline_checkbox_, &style, gfx::Font::UNDERLINE);
195  text_view_->set_halo(halo_checkbox_->checked());
196  text_view_->set_flags(flags);
197  text_view_->SetStyle(style);
198  text_view_->SchedulePaint();
199}
200
201void TextExample::OnPerformAction(Combobox* combobox) {
202  int flags = text_view_->flags();
203  if (combobox == h_align_cb_) {
204    flags &= ~(gfx::Canvas::TEXT_ALIGN_LEFT |
205               gfx::Canvas::TEXT_ALIGN_CENTER |
206               gfx::Canvas::TEXT_ALIGN_RIGHT);
207    switch (combobox->selected_index()) {
208      case 0:
209        break;
210      case 1:
211        flags |= gfx::Canvas::TEXT_ALIGN_LEFT;
212        break;
213      case 2:
214        flags |= gfx::Canvas::TEXT_ALIGN_CENTER;
215        break;
216      case 3:
217        flags |= gfx::Canvas::TEXT_ALIGN_RIGHT;
218        break;
219    }
220  } else if (combobox == text_cb_) {
221    switch (combobox->selected_index()) {
222      case 0:
223        text_view_->set_text(base::ASCIIToUTF16(kShortText));
224        break;
225      case 1:
226        text_view_->set_text(base::ASCIIToUTF16(kLongText));
227        break;
228      case 2:
229        text_view_->set_text(base::ASCIIToUTF16(kAmpersandText));
230        break;
231      case 3:
232        text_view_->set_text(base::WideToUTF16(kRightToLeftText));
233        break;
234    }
235  } else if (combobox == eliding_cb_) {
236    switch (combobox->selected_index()) {
237      case 0:
238        text_view_->set_elide(gfx::ELIDE_TAIL);
239        break;
240      case 1:
241        text_view_->set_elide(gfx::NO_ELIDE);
242        break;
243      case 2:
244        text_view_->set_elide(gfx::FADE_TAIL);
245        break;
246    }
247  } else if (combobox == prefix_cb_) {
248    flags &= ~(gfx::Canvas::SHOW_PREFIX | gfx::Canvas::HIDE_PREFIX);
249    switch (combobox->selected_index()) {
250      case 0:
251        break;
252      case 1:
253        flags |= gfx::Canvas::SHOW_PREFIX;
254        break;
255      case 2:
256        flags |= gfx::Canvas::HIDE_PREFIX;
257        break;
258    }
259  }
260  text_view_->set_flags(flags);
261  text_view_->SchedulePaint();
262}
263
264}  // namespace examples
265}  // namespace views
266