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/examples_window.h"
6
7#include <algorithm>
8#include <string>
9
10#include "base/memory/scoped_vector.h"
11#include "base/strings/utf_string_conversions.h"
12#include "ui/base/models/combobox_model.h"
13#include "ui/base/ui_base_paths.h"
14#include "ui/views/background.h"
15#include "ui/views/controls/combobox/combobox.h"
16#include "ui/views/controls/label.h"
17#include "ui/views/examples/bubble_example.h"
18#include "ui/views/examples/button_example.h"
19#include "ui/views/examples/checkbox_example.h"
20#include "ui/views/examples/combobox_example.h"
21#include "ui/views/examples/double_split_view_example.h"
22#include "ui/views/examples/label_example.h"
23#include "ui/views/examples/link_example.h"
24#include "ui/views/examples/menu_example.h"
25#include "ui/views/examples/message_box_example.h"
26#include "ui/views/examples/multiline_example.h"
27#include "ui/views/examples/progress_bar_example.h"
28#include "ui/views/examples/radio_button_example.h"
29#include "ui/views/examples/scroll_view_example.h"
30#include "ui/views/examples/single_split_view_example.h"
31#include "ui/views/examples/slider_example.h"
32#include "ui/views/examples/tabbed_pane_example.h"
33#include "ui/views/examples/table_example.h"
34#include "ui/views/examples/text_example.h"
35#include "ui/views/examples/textfield_example.h"
36#include "ui/views/examples/throbber_example.h"
37#include "ui/views/examples/tree_view_example.h"
38#include "ui/views/examples/widget_example.h"
39#include "ui/views/layout/fill_layout.h"
40#include "ui/views/layout/grid_layout.h"
41#include "ui/views/widget/widget.h"
42#include "ui/views/widget/widget_delegate.h"
43
44namespace views {
45namespace examples {
46
47typedef scoped_ptr<ScopedVector<ExampleBase> > ScopedExamples;
48
49namespace {
50
51// Creates the default set of examples. Caller owns the result.
52ScopedExamples CreateExamples() {
53  ScopedExamples examples(new ScopedVector<ExampleBase>);
54  examples->push_back(new BubbleExample);
55  examples->push_back(new ButtonExample);
56  examples->push_back(new CheckboxExample);
57  examples->push_back(new ComboboxExample);
58  examples->push_back(new DoubleSplitViewExample);
59  examples->push_back(new LabelExample);
60  examples->push_back(new LinkExample);
61  examples->push_back(new MenuExample);
62  examples->push_back(new MessageBoxExample);
63  examples->push_back(new MultilineExample);
64  examples->push_back(new ProgressBarExample);
65  examples->push_back(new RadioButtonExample);
66  examples->push_back(new ScrollViewExample);
67  examples->push_back(new SingleSplitViewExample);
68  examples->push_back(new SliderExample);
69  examples->push_back(new TabbedPaneExample);
70  examples->push_back(new TableExample);
71  examples->push_back(new TextExample);
72  examples->push_back(new TextfieldExample);
73  examples->push_back(new ThrobberExample);
74  examples->push_back(new TreeViewExample);
75  examples->push_back(new WidgetExample);
76  return examples.Pass();
77}
78
79struct ExampleTitleCompare {
80  bool operator() (ExampleBase* a, ExampleBase* b) {
81    return a->example_title() < b->example_title();
82  }
83};
84
85ScopedExamples GetExamplesToShow(ScopedExamples extra) {
86  ScopedExamples examples(CreateExamples());
87  if (extra.get()) {
88    examples->insert(examples->end(), extra->begin(), extra->end());
89    extra->weak_clear();
90  }
91  std::sort(examples->begin(), examples->end(), ExampleTitleCompare());
92  return examples.Pass();
93}
94
95}  // namespace
96
97// Model for the examples that are being added via AddExample().
98class ComboboxModelExampleList : public ui::ComboboxModel {
99 public:
100  ComboboxModelExampleList() {}
101  virtual ~ComboboxModelExampleList() {}
102
103  void SetExamples(ScopedExamples examples) {
104    example_list_.swap(*examples);
105  }
106
107  // ui::ComboboxModel:
108  virtual int GetItemCount() const OVERRIDE { return example_list_.size(); }
109  virtual base::string16 GetItemAt(int index) OVERRIDE {
110    return base::UTF8ToUTF16(example_list_[index]->example_title());
111  }
112
113  View* GetItemViewAt(int index) {
114    return example_list_[index]->example_view();
115  }
116
117 private:
118  ScopedVector<ExampleBase> example_list_;
119
120  DISALLOW_COPY_AND_ASSIGN(ComboboxModelExampleList);
121};
122
123class ExamplesWindowContents : public WidgetDelegateView,
124                               public ComboboxListener {
125 public:
126  ExamplesWindowContents(Operation operation, ScopedExamples examples)
127      : combobox_(new Combobox(&combobox_model_)),
128        example_shown_(new View),
129        status_label_(new Label),
130        operation_(operation) {
131    instance_ = this;
132    combobox_->set_listener(this);
133    combobox_model_.SetExamples(examples.Pass());
134    combobox_->ModelChanged();
135
136    set_background(Background::CreateStandardPanelBackground());
137    GridLayout* layout = new GridLayout(this);
138    SetLayoutManager(layout);
139    ColumnSet* column_set = layout->AddColumnSet(0);
140    column_set->AddPaddingColumn(0, 5);
141    column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
142                          GridLayout::USE_PREF, 0, 0);
143    column_set->AddPaddingColumn(0, 5);
144    layout->AddPaddingRow(0, 5);
145    layout->StartRow(0 /* no expand */, 0);
146    layout->AddView(combobox_);
147
148    if (combobox_model_.GetItemCount() > 0) {
149      layout->StartRow(1, 0);
150      example_shown_->SetLayoutManager(new FillLayout());
151      example_shown_->AddChildView(combobox_model_.GetItemViewAt(0));
152      layout->AddView(example_shown_);
153    }
154
155    layout->StartRow(0 /* no expand */, 0);
156    layout->AddView(status_label_);
157    layout->AddPaddingRow(0, 5);
158  }
159
160  virtual ~ExamplesWindowContents() {
161    // Delete |combobox_| first as it references |combobox_model_|.
162    delete combobox_;
163    combobox_ = NULL;
164  }
165
166  // Prints a message in the status area, at the bottom of the window.
167  void SetStatus(const std::string& status) {
168    status_label_->SetText(base::UTF8ToUTF16(status));
169  }
170
171  static ExamplesWindowContents* instance() { return instance_; }
172
173 private:
174  // WidgetDelegateView:
175  virtual bool CanResize() const OVERRIDE { return true; }
176  virtual bool CanMaximize() const OVERRIDE { return true; }
177  virtual bool CanMinimize() const OVERRIDE { return true; }
178  virtual base::string16 GetWindowTitle() const OVERRIDE {
179    return base::ASCIIToUTF16("Views Examples");
180  }
181  virtual View* GetContentsView() OVERRIDE { return this; }
182  virtual void WindowClosing() OVERRIDE {
183    instance_ = NULL;
184    if (operation_ == QUIT_ON_CLOSE)
185      base::MessageLoopForUI::current()->Quit();
186  }
187
188  // ComboboxListener:
189  virtual void OnPerformAction(Combobox* combobox) OVERRIDE {
190    DCHECK_EQ(combobox, combobox_);
191    DCHECK(combobox->selected_index() < combobox_model_.GetItemCount());
192    example_shown_->RemoveAllChildViews(false);
193    example_shown_->AddChildView(combobox_model_.GetItemViewAt(
194        combobox->selected_index()));
195    example_shown_->RequestFocus();
196    SetStatus(std::string());
197    Layout();
198  }
199
200  static ExamplesWindowContents* instance_;
201  ComboboxModelExampleList combobox_model_;
202  Combobox* combobox_;
203  View* example_shown_;
204  Label* status_label_;
205  const Operation operation_;
206
207  DISALLOW_COPY_AND_ASSIGN(ExamplesWindowContents);
208};
209
210// static
211ExamplesWindowContents* ExamplesWindowContents::instance_ = NULL;
212
213void ShowExamplesWindow(Operation operation,
214                        gfx::NativeWindow window_context,
215                        ScopedExamples extra_examples) {
216  if (ExamplesWindowContents::instance()) {
217    ExamplesWindowContents::instance()->GetWidget()->Activate();
218  } else {
219    ScopedExamples examples(GetExamplesToShow(extra_examples.Pass()));
220    Widget* widget = new Widget;
221    Widget::InitParams params;
222    params.delegate = new ExamplesWindowContents(operation, examples.Pass());
223    params.context = window_context;
224    params.bounds = gfx::Rect(0, 0, 850, 300);
225    widget->Init(params);
226    widget->Show();
227  }
228}
229
230void LogStatus(const std::string& string) {
231  ExamplesWindowContents::instance()->SetStatus(string);
232}
233
234}  // namespace examples
235}  // namespace views
236