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 20namespace athena { 21namespace { 22 23// The icon size. 24const int kIconSize = 32; 25 26// The distance between the icon and the title when the icon is visible. 27const int kIconTitleSpacing = 10; 28 29// The height of the top border necessary to display the title without the icon. 30const int kDefaultTitleHeight = 25; 31 32// The height of the top border in overview mode. 33const int kOverviewTitleHeight = 55; 34 35// The height of the top border for fullscreen and frameless activities in 36// overview mode. 37const int kOverviewShortTitleHeight = 30; 38 39// The thickness of the left, right and bottom borders in overview mode. 40const int kOverviewBorderThickness = 5; 41 42} // namespace 43 44// static 45const char ActivityFrameView::kViewClassName[] = "ActivityFrameView"; 46 47ActivityFrameView::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 65ActivityFrameView::~ActivityFrameView() { 66 WindowManager::Get()->RemoveObserver(this); 67} 68 69gfx::Rect ActivityFrameView::GetBoundsForClientView() const { 70 gfx::Rect client_bounds = bounds(); 71 client_bounds.Inset(NonClientBorderInsets()); 72 return client_bounds; 73} 74 75gfx::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 82int 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 93void ActivityFrameView::GetWindowMask(const gfx::Size& size, 94 gfx::Path* window_mask) { 95} 96 97void ActivityFrameView::ResetWindowControls() { 98} 99 100void 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 112void ActivityFrameView::UpdateWindowTitle() { 113 if (!view_model_->UsesFrame()) 114 return; 115 title_->SetText(frame_->widget_delegate()->GetWindowTitle()); 116 Layout(); 117} 118 119void ActivityFrameView::SizeConstraintsChanged() { 120} 121 122gfx::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 130const char* ActivityFrameView::GetClassName() const { 131 return kViewClassName; 132} 133 134void 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 162void 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 172void 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 181void 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 190void ActivityFrameView::OnSplitViewModeEnter() { 191} 192 193void ActivityFrameView::OnSplitViewModeExit() { 194} 195 196gfx::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 204int ActivityFrameView::NonClientBorderThickness() const { 205 return in_overview_ ? kOverviewBorderThickness : 0; 206} 207 208int 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