OLD | NEW |
| (Empty) |
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 "athena/activity/activity_frame_view.h" | |
6 | |
7 #include "athena/activity/public/activity_view_model.h" | |
8 #include "athena/wm/public/window_manager.h" | |
9 #include "ui/base/hit_test.h" | |
10 #include "ui/gfx/canvas.h" | |
11 #include "ui/gfx/image/image_skia.h" | |
12 #include "ui/views/background.h" | |
13 #include "ui/views/controls/image_view.h" | |
14 #include "ui/views/controls/label.h" | |
15 #include "ui/views/view.h" | |
16 #include "ui/views/widget/widget.h" | |
17 #include "ui/views/widget/widget_delegate.h" | |
18 #include "ui/views/window/client_view.h" | |
19 | |
20 namespace athena { | |
21 namespace { | |
22 | |
23 // The icon size. | |
24 const int kIconSize = 32; | |
25 | |
26 // The distance between the icon and the title when the icon is visible. | |
27 const int kIconTitleSpacing = 10; | |
28 | |
29 // The height of the top border necessary to display the title without the icon. | |
30 const int kDefaultTitleHeight = 25; | |
31 | |
32 // The height of the top border in overview mode. | |
33 const int kOverviewTitleHeight = 55; | |
34 | |
35 // The height of the top border for fullscreen and frameless activities in | |
36 // overview mode. | |
37 const int kOverviewShortTitleHeight = 30; | |
38 | |
39 // The thickness of the left, right and bottom borders in overview mode. | |
40 const int kOverviewBorderThickness = 5; | |
41 | |
42 } // namespace | |
43 | |
44 // static | |
45 const char ActivityFrameView::kViewClassName[] = "ActivityFrameView"; | |
46 | |
47 ActivityFrameView::ActivityFrameView(views::Widget* frame, | |
48 ActivityViewModel* view_model) | |
49 : frame_(frame), | |
50 view_model_(view_model), | |
51 title_(new views::Label), | |
52 icon_(new views::ImageView), | |
53 in_overview_(false) { | |
54 title_->SetEnabledColor(SkColorSetA(SK_ColorBLACK, 0xe5)); | |
55 | |
56 AddChildView(title_); | |
57 AddChildView(icon_); | |
58 | |
59 UpdateWindowTitle(); | |
60 UpdateWindowIcon(); | |
61 | |
62 view_model_->SetActivityView(this); | |
63 | |
64 WindowManager::Get()->AddObserver(this); | |
65 } | |
66 | |
67 ActivityFrameView::~ActivityFrameView() { | |
68 WindowManager::Get()->RemoveObserver(this); | |
69 | |
70 // |view_model_| is already destroyed at this time. So do not attempt to reset | |
71 // the activity-view by calling SetActivityView(nullptr); | |
72 // http://crbug.com/427113 | |
73 } | |
74 | |
75 gfx::Rect ActivityFrameView::GetBoundsForClientView() const { | |
76 gfx::Rect client_bounds = bounds(); | |
77 client_bounds.Inset(NonClientBorderInsets()); | |
78 return client_bounds; | |
79 } | |
80 | |
81 gfx::Rect ActivityFrameView::GetWindowBoundsForClientBounds( | |
82 const gfx::Rect& client_bounds) const { | |
83 gfx::Rect window_bounds = client_bounds; | |
84 window_bounds.Inset(-NonClientBorderInsets()); | |
85 return window_bounds; | |
86 } | |
87 | |
88 int ActivityFrameView::NonClientHitTest(const gfx::Point& point) { | |
89 if (!bounds().Contains(point)) | |
90 return HTNOWHERE; | |
91 int client_hit_test = frame_->client_view()->NonClientHitTest(point); | |
92 if (client_hit_test != HTNOWHERE) | |
93 return client_hit_test; | |
94 int window_hit_test = | |
95 GetHTComponentForFrame(point, 0, NonClientBorderThickness(), 0, 0, false); | |
96 return (window_hit_test == HTNOWHERE) ? HTCAPTION : client_hit_test; | |
97 } | |
98 | |
99 void ActivityFrameView::GetWindowMask(const gfx::Size& size, | |
100 gfx::Path* window_mask) { | |
101 } | |
102 | |
103 void ActivityFrameView::ResetWindowControls() { | |
104 } | |
105 | |
106 void ActivityFrameView::UpdateWindowIcon() { | |
107 // The activity has a frame in overview mode regardless of the value of | |
108 // ActivityViewModel::UsesFrame(). | |
109 SkColor bgcolor = view_model_->GetRepresentativeColor(); | |
110 set_background(views::Background::CreateSolidBackground(bgcolor)); | |
111 title_->SetBackgroundColor(bgcolor); | |
112 | |
113 if (view_model_->UsesFrame()) | |
114 icon_->SetImage(view_model_->GetIcon()); | |
115 SchedulePaint(); | |
116 } | |
117 | |
118 void ActivityFrameView::UpdateWindowTitle() { | |
119 if (!view_model_->UsesFrame()) | |
120 return; | |
121 title_->SetText(frame_->widget_delegate()->GetWindowTitle()); | |
122 Layout(); | |
123 } | |
124 | |
125 void ActivityFrameView::SizeConstraintsChanged() { | |
126 } | |
127 | |
128 gfx::Size ActivityFrameView::GetPreferredSize() const { | |
129 gfx::Size pref = frame_->client_view()->GetPreferredSize(); | |
130 gfx::Rect bounds(0, 0, pref.width(), pref.height()); | |
131 return frame_->non_client_view() | |
132 ->GetWindowBoundsForClientBounds(bounds) | |
133 .size(); | |
134 } | |
135 | |
136 const char* ActivityFrameView::GetClassName() const { | |
137 return kViewClassName; | |
138 } | |
139 | |
140 void ActivityFrameView::Layout() { | |
141 if (frame_->IsFullscreen() || !view_model_->UsesFrame()) { | |
142 title_->SetVisible(false); | |
143 icon_->SetVisible(false); | |
144 return; | |
145 } | |
146 | |
147 title_->SetVisible(true); | |
148 icon_->SetVisible(in_overview_); | |
149 | |
150 gfx::Size preferred_title_size = title_->GetPreferredSize(); | |
151 int top_height = NonClientTopBorderHeight(); | |
152 int title_x = 0; | |
153 if (in_overview_) { | |
154 int edge = (top_height - kIconSize) / 2; | |
155 icon_->SetBounds(edge, edge, kIconSize, kIconSize); | |
156 | |
157 title_x = icon_->bounds().right() + kIconTitleSpacing; | |
158 } else { | |
159 title_x = (width() - preferred_title_size.width()) / 2; | |
160 } | |
161 | |
162 title_->SetBounds(title_x, | |
163 (top_height - preferred_title_size.height()) / 2, | |
164 preferred_title_size.width(), | |
165 preferred_title_size.height()); | |
166 } | |
167 | |
168 void ActivityFrameView::OnPaintBackground(gfx::Canvas* canvas) { | |
169 View::OnPaintBackground(canvas); | |
170 | |
171 // Paint a border around the client view. | |
172 gfx::Rect border_bounds = GetLocalBounds(); | |
173 border_bounds.Inset(NonClientBorderInsets()); | |
174 border_bounds.Inset(-1, -1, 0, 0); | |
175 canvas->DrawRect(border_bounds, SkColorSetA(SK_ColorGRAY, 0x7f)); | |
176 } | |
177 | |
178 void ActivityFrameView::UpdateTitle() { | |
179 UpdateWindowTitle(); | |
180 } | |
181 | |
182 void ActivityFrameView::UpdateIcon() { | |
183 UpdateWindowIcon(); | |
184 } | |
185 | |
186 void ActivityFrameView::UpdateRepresentativeColor() { | |
187 UpdateWindowTitle(); | |
188 } | |
189 | |
190 void ActivityFrameView::OnOverviewModeEnter() { | |
191 view_model_->PrepareContentsForOverview(); | |
192 in_overview_ = true; | |
193 InvalidateLayout(); | |
194 frame_->client_view()->InvalidateLayout(); | |
195 frame_->GetRootView()->Layout(); | |
196 SchedulePaint(); | |
197 } | |
198 | |
199 void ActivityFrameView::OnOverviewModeExit() { | |
200 in_overview_ = false; | |
201 InvalidateLayout(); | |
202 frame_->client_view()->InvalidateLayout(); | |
203 frame_->GetRootView()->Layout(); | |
204 SchedulePaint(); | |
205 view_model_->ResetContentsView(); | |
206 } | |
207 | |
208 void ActivityFrameView::OnSplitViewModeEnter() { | |
209 } | |
210 | |
211 void ActivityFrameView::OnSplitViewModeExit() { | |
212 } | |
213 | |
214 gfx::Insets ActivityFrameView::NonClientBorderInsets() const { | |
215 int border_thickness = NonClientBorderThickness(); | |
216 return gfx::Insets(NonClientTopBorderHeight(), | |
217 border_thickness, | |
218 border_thickness, | |
219 border_thickness); | |
220 } | |
221 | |
222 int ActivityFrameView::NonClientBorderThickness() const { | |
223 return in_overview_ ? kOverviewBorderThickness : 0; | |
224 } | |
225 | |
226 int ActivityFrameView::NonClientTopBorderHeight() const { | |
227 if (frame_->IsFullscreen() || !view_model_->UsesFrame()) | |
228 return in_overview_ ? kOverviewShortTitleHeight : 0; | |
229 return in_overview_ ? kOverviewTitleHeight : kDefaultTitleHeight; | |
230 } | |
231 | |
232 } // namespace athena | |
OLD | NEW |