Home | History | Annotate | Download | only in examples
      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