- add sources.
[platform/framework/web/crosswalk.git] / src / ui / app_list / views / app_list_view.cc
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/app_list/views/app_list_view.h"
6
7 #include "base/callback.h"
8 #include "base/command_line.h"
9 #include "base/strings/string_util.h"
10 #include "ui/app_list/app_list_constants.h"
11 #include "ui/app_list/app_list_model.h"
12 #include "ui/app_list/app_list_view_delegate.h"
13 #include "ui/app_list/pagination_model.h"
14 #include "ui/app_list/signin_delegate.h"
15 #include "ui/app_list/views/app_list_background.h"
16 #include "ui/app_list/views/app_list_main_view.h"
17 #include "ui/app_list/views/search_box_view.h"
18 #include "ui/app_list/views/signin_view.h"
19 #include "ui/base/ui_base_switches.h"
20 #include "ui/gfx/image/image_skia.h"
21 #include "ui/gfx/insets.h"
22 #include "ui/gfx/path.h"
23 #include "ui/gfx/skia_util.h"
24 #include "ui/views/bubble/bubble_frame_view.h"
25 #include "ui/views/controls/textfield/textfield.h"
26 #include "ui/views/layout/fill_layout.h"
27 #include "ui/views/widget/widget.h"
28
29 #if defined(USE_AURA)
30 #include "ui/aura/window.h"
31 #include "ui/aura/root_window.h"
32 #if defined(OS_WIN)
33 #include "ui/base/win/shell.h"
34 #endif
35 #if !defined(OS_CHROMEOS)
36 #include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
37 #endif
38 #endif  // defined(USE_AURA)
39
40 namespace app_list {
41
42 namespace {
43
44 base::Closure g_next_paint_callback;
45
46 // The distance between the arrow tip and edge of the anchor view.
47 const int kArrowOffset = 10;
48
49 }  // namespace
50
51 ////////////////////////////////////////////////////////////////////////////////
52 // AppListView:
53
54 AppListView::AppListView(AppListViewDelegate* delegate)
55     : model_(new AppListModel),
56       delegate_(delegate),
57       app_list_main_view_(NULL),
58       signin_view_(NULL) {
59   if (delegate_)
60     delegate_->InitModel(model_.get());
61   model_->AddObserver(this);
62 }
63
64 AppListView::~AppListView() {
65   model_->RemoveObserver(this);
66   // Models are going away, ensure their references are cleared.
67   RemoveAllChildViews(true);
68 }
69
70 void AppListView::InitAsBubbleAttachedToAnchor(
71     gfx::NativeView parent,
72     PaginationModel* pagination_model,
73     views::View* anchor,
74     const gfx::Vector2d& anchor_offset,
75     views::BubbleBorder::Arrow arrow,
76     bool border_accepts_events) {
77   SetAnchorView(anchor);
78   InitAsBubbleInternal(
79       parent, pagination_model, arrow, border_accepts_events, anchor_offset);
80 }
81
82 void AppListView::InitAsBubbleAtFixedLocation(
83     gfx::NativeView parent,
84     PaginationModel* pagination_model,
85     const gfx::Point& anchor_point_in_screen,
86     views::BubbleBorder::Arrow arrow,
87     bool border_accepts_events) {
88   SetAnchorView(NULL);
89   set_anchor_rect(gfx::Rect(anchor_point_in_screen, gfx::Size()));
90   InitAsBubbleInternal(
91       parent, pagination_model, arrow, border_accepts_events, gfx::Vector2d());
92 }
93
94 void AppListView::SetBubbleArrow(views::BubbleBorder::Arrow arrow) {
95   GetBubbleFrameView()->bubble_border()->set_arrow(arrow);
96   SizeToContents();  // Recalcuates with new border.
97   GetBubbleFrameView()->SchedulePaint();
98 }
99
100 void AppListView::SetAnchorPoint(const gfx::Point& anchor_point) {
101   set_anchor_rect(gfx::Rect(anchor_point, gfx::Size()));
102   SizeToContents();  // Repositions view relative to the anchor.
103 }
104
105 void AppListView::SetDragAndDropHostOfCurrentAppList(
106     ApplicationDragAndDropHost* drag_and_drop_host) {
107   app_list_main_view_->SetDragAndDropHostOfCurrentAppList(drag_and_drop_host);
108 }
109
110 void AppListView::ShowWhenReady() {
111   app_list_main_view_->ShowAppListWhenReady();
112 }
113
114 void AppListView::Close() {
115   app_list_main_view_->Close();
116   if (delegate_)
117     delegate_->Dismiss();
118   else
119     GetWidget()->Close();
120 }
121
122 void AppListView::UpdateBounds() {
123   SizeToContents();
124 }
125
126 gfx::Size AppListView::GetPreferredSize() {
127   return app_list_main_view_->GetPreferredSize();
128 }
129
130 void AppListView::Paint(gfx::Canvas* canvas) {
131   views::BubbleDelegateView::Paint(canvas);
132   if (!g_next_paint_callback.is_null()) {
133     g_next_paint_callback.Run();
134     g_next_paint_callback.Reset();
135   }
136 }
137
138 bool AppListView::ShouldHandleSystemCommands() const {
139   return true;
140 }
141
142 void AppListView::Prerender() {
143   app_list_main_view_->Prerender();
144 }
145
146 void AppListView::OnSigninStatusChanged() {
147   signin_view_->SetVisible(!model_->signed_in());
148   app_list_main_view_->SetVisible(model_->signed_in());
149   app_list_main_view_->search_box_view()->InvalidateMenu();
150 }
151
152 void AppListView::SetProfileByPath(const base::FilePath& profile_path) {
153   delegate_->SetProfileByPath(profile_path);
154 }
155
156 void AppListView::AddObserver(Observer* observer) {
157   observers_.AddObserver(observer);
158 }
159
160 void AppListView::RemoveObserver(Observer* observer) {
161   observers_.RemoveObserver(observer);
162 }
163
164 // static
165 void AppListView::SetNextPaintCallback(const base::Closure& callback) {
166   g_next_paint_callback = callback;
167 }
168
169 #if defined(OS_WIN)
170 HWND AppListView::GetHWND() const {
171 #if defined(USE_AURA)
172   gfx::NativeWindow window =
173       GetWidget()->GetTopLevelWidget()->GetNativeWindow();
174   return window->GetDispatcher()->GetAcceleratedWidget();
175 #else
176   return GetWidget()->GetTopLevelWidget()->GetNativeWindow();
177 #endif
178 }
179 #endif
180
181 void AppListView::InitAsBubbleInternal(gfx::NativeView parent,
182                                        PaginationModel* pagination_model,
183                                        views::BubbleBorder::Arrow arrow,
184                                        bool border_accepts_events,
185                                        const gfx::Vector2d& anchor_offset) {
186   app_list_main_view_ = new AppListMainView(delegate_.get(),
187                                             model_.get(),
188                                             pagination_model,
189                                             parent);
190   AddChildView(app_list_main_view_);
191 #if defined(USE_AURA)
192   app_list_main_view_->SetPaintToLayer(true);
193   app_list_main_view_->SetFillsBoundsOpaquely(false);
194   app_list_main_view_->layer()->SetMasksToBounds(true);
195 #endif
196
197   signin_view_ = new SigninView(
198       delegate_ ? delegate_->GetSigninDelegate()
199                 : NULL,
200       app_list_main_view_->GetPreferredSize().width());
201   AddChildView(signin_view_);
202
203   OnSigninStatusChanged();
204   set_color(kContentsBackgroundColor);
205   set_margins(gfx::Insets());
206   set_move_with_anchor(true);
207   set_parent_window(parent);
208   set_close_on_deactivate(false);
209   set_close_on_esc(false);
210   set_anchor_view_insets(gfx::Insets(kArrowOffset + anchor_offset.y(),
211                                      kArrowOffset + anchor_offset.x(),
212                                      kArrowOffset - anchor_offset.y(),
213                                      kArrowOffset - anchor_offset.x()));
214   set_border_accepts_events(border_accepts_events);
215   set_shadow(views::BubbleBorder::BIG_SHADOW);
216 #if defined(USE_AURA) && defined(OS_WIN)
217   if (!ui::win::IsAeroGlassEnabled() ||
218       CommandLine::ForCurrentProcess()->HasSwitch(
219           switches::kDisableDwmComposition)) {
220     set_shadow(views::BubbleBorder::NO_SHADOW_OPAQUE_BORDER);
221   }
222 #endif
223   views::BubbleDelegateView::CreateBubble(this);
224   SetBubbleArrow(arrow);
225
226 #if defined(USE_AURA)
227   GetWidget()->GetNativeWindow()->layer()->SetMasksToBounds(true);
228   GetBubbleFrameView()->set_background(new AppListBackground(
229       GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius(),
230       app_list_main_view_));
231   set_background(NULL);
232 #else
233   set_background(new AppListBackground(
234       GetBubbleFrameView()->bubble_border()->GetBorderCornerRadius(),
235       app_list_main_view_));
236
237   // On non-aura the bubble has two widgets, and it's possible for the border
238   // to be shown independently in odd situations. Explicitly hide the bubble
239   // widget to ensure that any WM_WINDOWPOSCHANGED messages triggered by the
240   // window manager do not have the SWP_SHOWWINDOW flag set which would cause
241   // the border to be shown. See http://crbug.com/231687 .
242   GetWidget()->Hide();
243 #endif
244 }
245
246 void AppListView::OnBeforeBubbleWidgetInit(
247     views::Widget::InitParams* params,
248     views::Widget* widget) const {
249 #if defined(USE_AURA) && !defined(OS_CHROMEOS)
250   if (delegate_ && delegate_->ForceNativeDesktop())
251     params->native_widget = new views::DesktopNativeWidgetAura(widget);
252 #endif
253 }
254
255 views::View* AppListView::GetInitiallyFocusedView() {
256   return app_list_main_view_->search_box_view()->search_box();
257 }
258
259 gfx::ImageSkia AppListView::GetWindowIcon() {
260   if (delegate_)
261     return delegate_->GetWindowIcon();
262
263   return gfx::ImageSkia();
264 }
265
266 bool AppListView::WidgetHasHitTestMask() const {
267   return true;
268 }
269
270 void AppListView::GetWidgetHitTestMask(gfx::Path* mask) const {
271   DCHECK(mask);
272   mask->addRect(gfx::RectToSkRect(
273       GetBubbleFrameView()->GetContentsBounds()));
274 }
275
276 bool AppListView::AcceleratorPressed(const ui::Accelerator& accelerator) {
277   // The accelerator is added by BubbleDelegateView.
278   if (accelerator.key_code() == ui::VKEY_ESCAPE) {
279     if (app_list_main_view_->search_box_view()->HasSearch()) {
280       app_list_main_view_->search_box_view()->ClearSearch();
281     } else {
282       GetWidget()->Deactivate();
283       Close();
284     }
285     return true;
286   }
287
288   return false;
289 }
290
291 void AppListView::Layout() {
292   const gfx::Rect contents_bounds = GetContentsBounds();
293   app_list_main_view_->SetBoundsRect(contents_bounds);
294   signin_view_->SetBoundsRect(contents_bounds);
295 }
296
297 void AppListView::OnWidgetDestroying(views::Widget* widget) {
298   BubbleDelegateView::OnWidgetDestroying(widget);
299   if (delegate_ && widget == GetWidget())
300     delegate_->ViewClosing();
301 }
302
303 void AppListView::OnWidgetActivationChanged(views::Widget* widget,
304                                             bool active) {
305   // Do not called inherited function as the bubble delegate auto close
306   // functionality is not used.
307   if (widget == GetWidget())
308     FOR_EACH_OBSERVER(Observer, observers_,
309                       OnActivationChanged(widget, active));
310 }
311
312 void AppListView::OnWidgetVisibilityChanged(views::Widget* widget,
313                                             bool visible) {
314   BubbleDelegateView::OnWidgetVisibilityChanged(widget, visible);
315
316   if (widget != GetWidget())
317     return;
318
319   // We clear the search when hiding so the next time the app list appears it is
320   // not showing search results.
321   if (!visible)
322     app_list_main_view_->search_box_view()->ClearSearch();
323
324   // Whether we need to signin or not may have changed since last time we were
325   // shown.
326   Layout();
327 }
328
329 void AppListView::OnAppListModelSigninStatusChanged() {
330   OnSigninStatusChanged();
331 }
332
333 void AppListView::OnAppListModelUsersChanged() {
334   OnSigninStatusChanged();
335 }
336
337 }  // namespace app_list