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/oak/oak_window.h"
6
7#include "base/strings/utf_string_conversions.h"
8#include "grit/ui_resources.h"
9#include "ui/aura/root_window.h"
10#include "ui/aura/window.h"
11#include "ui/base/resource/resource_bundle.h"
12#include "ui/gfx/canvas.h"
13#include "ui/gfx/image/image.h"
14#include "ui/oak/oak.h"
15#include "ui/oak/oak_aura_window_display.h"
16#include "ui/views/controls/table/table_view.h"
17#include "ui/views/controls/tree/tree_view.h"
18#include "ui/views/layout/layout_constants.h"
19#include "ui/views/widget/widget.h"
20
21namespace oak {
22namespace internal {
23namespace {
24const SkColor kBorderColor = SkColorSetRGB(0xCC, 0xCC, 0xCC);
25}  // namespace
26
27// static
28views::Widget* OakWindow::instance = NULL;
29
30////////////////////////////////////////////////////////////////////////////////
31// OakWindow, public:
32
33OakWindow::OakWindow() : tree_container_(NULL) {}
34
35OakWindow::~OakWindow() {
36  // The tree/table need to be destroyed before the model.
37  tree_.reset();
38  details_.reset();
39}
40
41////////////////////////////////////////////////////////////////////////////////
42// OakWindow, views::WidgetDelegateView implementation:
43
44bool OakWindow::CanResize() const {
45  return true;
46}
47
48bool OakWindow::CanMaximize() const {
49  return true;
50}
51
52base::string16 OakWindow::GetWindowTitle() const {
53  return ASCIIToUTF16("Oak");
54}
55
56views::View* OakWindow::GetContentsView() {
57  return this;
58}
59
60gfx::ImageSkia OakWindow::GetWindowIcon() {
61  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
62  return *rb.GetImageNamed(IDR_OAK).ToImageSkia();
63}
64
65bool OakWindow::ShouldShowWindowIcon() const {
66  return true;
67}
68
69void OakWindow::DeleteDelegate() {
70  instance = NULL;
71  delete this;
72}
73
74////////////////////////////////////////////////////////////////////////////////
75// OakWindow, views::View overrides:
76
77void OakWindow::OnPaint(gfx::Canvas* canvas) {
78  canvas->DrawColor(SK_ColorWHITE);
79  canvas->FillRect(separator_rect_, kBorderColor);
80}
81
82void OakWindow::ViewHierarchyChanged(
83    const ViewHierarchyChangedDetails& details) {
84  if (details.is_add && details.child == this)
85    Init();
86}
87
88void OakWindow::Layout() {
89  gfx::Rect content_bounds = GetLocalBounds();
90  content_bounds.Inset(views::kPanelHorizMargin, views::kPanelVertMargin);
91
92  int tree_height =
93      (content_bounds.height() / 2) - views::kUnrelatedControlVerticalSpacing;
94  gfx::Rect tree_bounds = content_bounds;
95  tree_bounds.set_height(tree_height);
96  tree_container_->SetBoundsRect(tree_bounds);
97
98  separator_rect_ = content_bounds;
99  separator_rect_.set_y(
100      tree_bounds.bottom() + views::kRelatedControlVerticalSpacing);
101  separator_rect_.set_height(1);
102
103  gfx::Rect details_bounds = content_bounds;
104  details_bounds.set_y(
105      separator_rect_.bottom() + views::kRelatedControlVerticalSpacing);
106  details_bounds.set_height(content_bounds.bottom() - details_bounds.y());
107  details_container_->SetBoundsRect(details_bounds);
108}
109
110////////////////////////////////////////////////////////////////////////////////
111// OakWindow, views::TreeViewController implementation:
112
113void OakWindow::OnTreeViewSelectionChanged(views::TreeView* tree) {
114  details_model_->SetValue(tree_model_->AsNode(tree->GetSelectedNode())->value);
115}
116
117////////////////////////////////////////////////////////////////////////////////
118// OakWindow, private:
119
120void OakWindow::Init() {
121  tree_model_.reset(
122      GenerateModel(GetWidget()->GetNativeView()->GetRootWindow()));
123  tree_.reset(new views::TreeView);
124  tree_->set_owned_by_client();
125  tree_->SetController(this);
126  tree_->SetModel(tree_model_.get());
127  tree_container_ = tree_->CreateParentIfNecessary();
128  AddChildView(tree_container_);
129
130  details_model_.reset(new OakAuraWindowDisplay);
131  std::vector<ui::TableColumn> columns;
132  columns.push_back(ui::TableColumn());
133  details_.reset(new views::TableView(details_model_.get(),
134                                      columns,
135                                      views::TEXT_ONLY,
136                                      true));
137  details_->set_owned_by_client();
138  details_container_ = details_->CreateParentIfNecessary();
139  details_->SetModel(details_model_.get());
140  AddChildView(details_container_);
141
142  OnTreeViewSelectionChanged(tree_.get());
143}
144
145}  // namespace internal
146
147void ShowOakWindowWithContext(gfx::NativeView context) {
148  if (!internal::OakWindow::instance) {
149    // TODO(erg): Do we want to reuse this window in times with a different
150    // context? For now, this is OK, but if we ever use Oak outside of the ash
151    // shell, we run into crbug.com/165759.
152    internal::OakWindow::instance =
153        views::Widget::CreateWindowWithContextAndBounds(
154            new internal::OakWindow, context, gfx::Rect(10, 10, 500, 500));
155  }
156  internal::OakWindow::instance->Show();
157}
158
159}  // namespace oak
160