Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / views / app_list / app_list_dialog_container.cc
1 // Copyright 2014 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 "chrome/browser/ui/views/app_list/app_list_dialog_container.h"
6
7 #include "chrome/browser/ui/host_desktop.h"
8 #include "third_party/skia/include/core/SkPaint.h"
9 #include "ui/app_list/app_list_constants.h"
10 #include "ui/base/accelerators/accelerator.h"
11 #include "ui/base/resource/resource_bundle.h"
12 #include "ui/base/ui_base_types.h"
13 #include "ui/events/event_constants.h"
14 #include "ui/events/keycodes/keyboard_codes.h"
15 #include "ui/gfx/canvas.h"
16 #include "ui/resources/grit/ui_resources.h"
17 #include "ui/views/background.h"
18 #include "ui/views/border.h"
19 #include "ui/views/bubble/bubble_border.h"
20 #include "ui/views/bubble/bubble_frame_view.h"
21 #include "ui/views/controls/button/label_button.h"
22 #include "ui/views/layout/fill_layout.h"
23 #include "ui/views/widget/widget.h"
24 #include "ui/views/window/client_view.h"
25 #include "ui/views/window/dialog_delegate.h"
26 #include "ui/views/window/native_frame_view.h"
27 #include "ui/views/window/non_client_view.h"
28
29 namespace {
30
31 // The background for App List dialogs, which appears as a rounded rectangle
32 // with the same border radius and color as the app list contents.
33 class AppListOverlayBackground : public views::Background {
34  public:
35   AppListOverlayBackground() {}
36   ~AppListOverlayBackground() override {}
37
38   // Overridden from views::Background:
39   void Paint(gfx::Canvas* canvas, views::View* view) const override {
40     // The radius of the app list overlay (the dialog's background).
41     // TODO(sashab): Using SupportsShadow() from app_list_view.cc, make this
42     // 1px smaller on platforms that support shadows.
43     const int kAppListOverlayBorderRadius = 3;
44
45     SkPaint paint;
46     paint.setStyle(SkPaint::kFill_Style);
47     paint.setColor(app_list::kContentsBackgroundColor);
48     canvas->DrawRoundRect(
49         view->GetContentsBounds(), kAppListOverlayBorderRadius, paint);
50   }
51
52  private:
53   DISALLOW_COPY_AND_ASSIGN(AppListOverlayBackground);
54 };
55
56 // The contents view for an App List Dialog, which covers the entire app list
57 // and adds a close button.
58 class AppListDialogContainer : public views::DialogDelegateView,
59                                public views::ButtonListener {
60  public:
61   AppListDialogContainer(views::View* dialog_body,
62                          const base::Closure& close_callback)
63       : dialog_body_(dialog_body),
64         close_button_(NULL),
65         close_callback_(close_callback) {
66     set_background(new AppListOverlayBackground());
67     AddChildView(dialog_body_);
68
69     close_button_ = views::BubbleFrameView::CreateCloseButton(this);
70     ui::Accelerator escape(ui::VKEY_ESCAPE, ui::EF_NONE);
71     close_button_->AddAccelerator(escape);
72     AddChildView(close_button_);
73   }
74   ~AppListDialogContainer() override {}
75
76  private:
77   // Overridden from views::View:
78   void Layout() override {
79     // Margin of the close button from the top right-hand corner of the dialog.
80     const int kCloseButtonDialogMargin = 10;
81
82     close_button_->SetPosition(
83         gfx::Point(width() - close_button_->width() - kCloseButtonDialogMargin,
84                    kCloseButtonDialogMargin));
85
86     dialog_body_->SetBoundsRect(GetContentsBounds());
87     views::DialogDelegateView::Layout();
88   }
89   void ViewHierarchyChanged(
90       const ViewHierarchyChangedDetails& details) override {
91     views::DialogDelegateView::ViewHierarchyChanged(details);
92     if (details.is_add && details.child == this)
93       GetFocusManager()->AdvanceFocus(false);
94   }
95
96   // Overridden from views::WidgetDelegate:
97   views::View* GetInitiallyFocusedView() override { return NULL; }
98   ui::ModalType GetModalType() const override { return ui::MODAL_TYPE_WINDOW; }
99   void WindowClosing() override {
100     if (!close_callback_.is_null())
101       close_callback_.Run();
102   }
103   views::ClientView* CreateClientView(views::Widget* widget) override {
104     return new views::ClientView(widget, GetContentsView());
105   }
106   views::NonClientFrameView* CreateNonClientFrameView(
107       views::Widget* widget) override {
108     return new views::NativeFrameView(widget);
109   }
110
111   // Overridden from views::ButtonListener:
112   void ButtonPressed(views::Button* sender, const ui::Event& event) override {
113     if (sender == close_button_) {
114       GetWidget()->Close();
115     } else {
116       NOTREACHED();
117     }
118   }
119
120   views::View* dialog_body_;
121   views::LabelButton* close_button_;
122   const base::Closure close_callback_;
123
124   DISALLOW_COPY_AND_ASSIGN(AppListDialogContainer);
125 };
126
127 // A BubbleFrameView that allows its client view to extend all the way to the
128 // top of the dialog, overlapping the BubbleFrameView's close button. This
129 // allows dialog content to appear closer to the top, in place of a title.
130 class FullSizeBubbleFrameView : public views::BubbleFrameView {
131  public:
132   FullSizeBubbleFrameView() : views::BubbleFrameView(gfx::Insets()) {}
133   ~FullSizeBubbleFrameView() override {}
134
135  private:
136   // Overridden from views::ViewTargeterDelegate:
137   bool DoesIntersectRect(const View* target,
138                          const gfx::Rect& rect) const override {
139     // Make sure click events can still reach the close button, even if the
140     // ClientView overlaps it.
141     if (IsCloseButtonVisible() && GetCloseButtonBounds().Intersects(rect))
142       return true;
143     return views::BubbleFrameView::DoesIntersectRect(target, rect);
144   }
145
146   // Overridden from views::View:
147   gfx::Insets GetInsets() const override { return gfx::Insets(); }
148
149   DISALLOW_COPY_AND_ASSIGN(FullSizeBubbleFrameView);
150 };
151
152 // A container view for a native dialog, which sizes to the given fixed |size|.
153 class NativeDialogContainer : public views::DialogDelegateView {
154  public:
155   NativeDialogContainer(views::View* dialog_body,
156                         const gfx::Size& size,
157                         const base::Closure& close_callback)
158       : size_(size),
159         dialog_body_(dialog_body),
160         close_callback_(close_callback) {
161     SetLayoutManager(new views::FillLayout());
162     AddChildView(dialog_body_);
163   }
164   ~NativeDialogContainer() override {}
165
166  private:
167   // Overridden from views::View:
168   gfx::Size GetPreferredSize() const override { return size_; }
169   void ViewHierarchyChanged(
170       const ViewHierarchyChangedDetails& details) override {
171     views::DialogDelegateView::ViewHierarchyChanged(details);
172     if (details.is_add && details.child == this)
173       GetFocusManager()->AdvanceFocus(false);
174   }
175
176   // Overridden from views::WidgetDelegate:
177   ui::ModalType GetModalType() const override { return ui::MODAL_TYPE_WINDOW; }
178   void WindowClosing() override {
179     if (!close_callback_.is_null())
180       close_callback_.Run();
181   }
182
183   // Overridden from views::DialogDelegate:
184   int GetDialogButtons() const override { return ui::DIALOG_BUTTON_NONE; }
185   views::NonClientFrameView* CreateNonClientFrameView(
186       views::Widget* widget) override {
187     FullSizeBubbleFrameView* frame = new FullSizeBubbleFrameView();
188     scoped_ptr<views::BubbleBorder> border(
189         new views::BubbleBorder(views::BubbleBorder::FLOAT,
190                                 views::BubbleBorder::SMALL_SHADOW,
191                                 SK_ColorRED));
192     border->set_use_theme_background_color(true);
193     frame->SetBubbleBorder(border.Pass());
194     return frame;
195   }
196
197   const gfx::Size size_;
198   views::View* dialog_body_;
199   const base::Closure close_callback_;
200
201   DISALLOW_COPY_AND_ASSIGN(NativeDialogContainer);
202 };
203
204 }  // namespace
205
206 views::DialogDelegateView* CreateAppListContainerForView(
207     views::View* view,
208     const base::Closure& close_callback) {
209   return new AppListDialogContainer(view, close_callback);
210 }
211
212 views::DialogDelegateView* CreateDialogContainerForView(
213     views::View* view,
214     const gfx::Size& size,
215     const base::Closure& close_callback) {
216   return new NativeDialogContainer(view, size, close_callback);
217 }