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 WindowManager::Get()->AddObserver(this); 63 } 64 65 ActivityFrameView::~ActivityFrameView() { 66 WindowManager::Get()->RemoveObserver(this); 67 } 68 69 gfx::Rect ActivityFrameView::GetBoundsForClientView() const { 70 gfx::Rect client_bounds = bounds(); 71 client_bounds.Inset(NonClientBorderInsets()); 72 return client_bounds; 73 } 74 75 gfx::Rect ActivityFrameView::GetWindowBoundsForClientBounds( 76 const gfx::Rect& client_bounds) const { 77 gfx::Rect window_bounds = client_bounds; 78 window_bounds.Inset(-NonClientBorderInsets()); 79 return window_bounds; 80 } 81 82 int ActivityFrameView::NonClientHitTest(const gfx::Point& point) { 83 if (!bounds().Contains(point)) 84 return HTNOWHERE; 85 int client_hit_test = frame_->client_view()->NonClientHitTest(point); 86 if (client_hit_test != HTNOWHERE) 87 return client_hit_test; 88 int window_hit_test = 89 GetHTComponentForFrame(point, 0, NonClientBorderThickness(), 0, 0, false); 90 return (window_hit_test == HTNOWHERE) ? HTCAPTION : client_hit_test; 91 } 92 93 void ActivityFrameView::GetWindowMask(const gfx::Size& size, 94 gfx::Path* window_mask) { 95 } 96 97 void ActivityFrameView::ResetWindowControls() { 98 } 99 100 void ActivityFrameView::UpdateWindowIcon() { 101 // The activity has a frame in overview mode regardless of the value of 102 // ActivityViewModel::UsesFrame(). 103 SkColor bgcolor = view_model_->GetRepresentativeColor(); 104 set_background(views::Background::CreateSolidBackground(bgcolor)); 105 title_->SetBackgroundColor(bgcolor); 106 107 if (view_model_->UsesFrame()) 108 icon_->SetImage(view_model_->GetIcon()); 109 SchedulePaint(); 110 } 111 112 void ActivityFrameView::UpdateWindowTitle() { 113 if (!view_model_->UsesFrame()) 114 return; 115 title_->SetText(frame_->widget_delegate()->GetWindowTitle()); 116 Layout(); 117 } 118 119 void ActivityFrameView::SizeConstraintsChanged() { 120 } 121 122 gfx::Size ActivityFrameView::GetPreferredSize() const { 123 gfx::Size pref = frame_->client_view()->GetPreferredSize(); 124 gfx::Rect bounds(0, 0, pref.width(), pref.height()); 125 return frame_->non_client_view() 126 ->GetWindowBoundsForClientBounds(bounds) 127 .size(); 128 } 129 130 const char* ActivityFrameView::GetClassName() const { 131 return kViewClassName; 132 } 133 134 void ActivityFrameView::Layout() { 135 if (frame_->IsFullscreen() || !view_model_->UsesFrame()) { 136 title_->SetVisible(false); 137 icon_->SetVisible(false); 138 return; 139 } 140 141 title_->SetVisible(true); 142 icon_->SetVisible(in_overview_); 143 144 gfx::Size preferred_title_size = title_->GetPreferredSize(); 145 int top_height = NonClientTopBorderHeight(); 146 int title_x = 0; 147 if (in_overview_) { 148 int edge = (top_height - kIconSize) / 2; 149 icon_->SetBounds(edge, edge, kIconSize, kIconSize); 150 151 title_x = icon_->bounds().right() + kIconTitleSpacing; 152 } else { 153 title_x = (width() - preferred_title_size.width()) / 2; 154 } 155 156 title_->SetBounds(title_x, 157 (top_height - preferred_title_size.height()) / 2, 158 preferred_title_size.width(), 159 preferred_title_size.height()); 160 } 161 162 void ActivityFrameView::OnPaintBackground(gfx::Canvas* canvas) { 163 View::OnPaintBackground(canvas); 164 165 // Paint a border around the client view. 166 gfx::Rect border_bounds = GetLocalBounds(); 167 border_bounds.Inset(NonClientBorderInsets()); 168 border_bounds.Inset(-1, -1, 0, 0); 169 canvas->DrawRect(border_bounds, SkColorSetA(SK_ColorGRAY, 0x7f)); 170 } 171 172 void ActivityFrameView::OnOverviewModeEnter() { 173 view_model_->PrepareContentsForOverview(); 174 in_overview_ = true; 175 InvalidateLayout(); 176 frame_->client_view()->InvalidateLayout(); 177 frame_->GetRootView()->Layout(); 178 SchedulePaint(); 179 } 180 181 void ActivityFrameView::OnOverviewModeExit() { 182 in_overview_ = false; 183 InvalidateLayout(); 184 frame_->client_view()->InvalidateLayout(); 185 frame_->GetRootView()->Layout(); 186 SchedulePaint(); 187 view_model_->ResetContentsView(); 188 } 189 190 void ActivityFrameView::OnSplitViewModeEnter() { 191 } 192 193 void ActivityFrameView::OnSplitViewModeExit() { 194 } 195 196 gfx::Insets ActivityFrameView::NonClientBorderInsets() const { 197 int border_thickness = NonClientBorderThickness(); 198 return gfx::Insets(NonClientTopBorderHeight(), 199 border_thickness, 200 border_thickness, 201 border_thickness); 202 } 203 204 int ActivityFrameView::NonClientBorderThickness() const { 205 return in_overview_ ? kOverviewBorderThickness : 0; 206 } 207 208 int ActivityFrameView::NonClientTopBorderHeight() const { 209 if (frame_->IsFullscreen() || !view_model_->UsesFrame()) 210 return in_overview_ ? kOverviewShortTitleHeight : 0; 211 return in_overview_ ? kOverviewTitleHeight : kDefaultTitleHeight; 212 } 213 214 } // namespace athena 215