Commit bc021eeb authored by pkotwicz's avatar pkotwicz Committed by Commit bot

Make activities have a thick border when in overview mode part 1

BUG=401559
TEST=Manual, see bug
TBR=sadrul, oshima (TBR for DEPS additions)
NOTRY=true

Review URL: https://codereview.chromium.org/518673007

Cr-Commit-Position: refs/heads/master@{#293620}
parent 4a530823
include_rules = [
"+athena/screen",
"+athena/screen/public",
"+athena/wm/public",
"+third_party/skia/include",
"+ui/aura",
"+ui/base",
"+ui/gfx",
"+ui/views",
]
......@@ -4,64 +4,97 @@
#include "athena/activity/activity_frame_view.h"
#include <algorithm>
#include <vector>
#include "athena/activity/public/activity_view_model.h"
#include "athena/wm/public/window_manager.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/hit_test.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/window/client_view.h"
namespace athena {
namespace {
// The icon size.
const int kIconSize = 32;
// The distance between the icon and the title when the icon is visible.
const int kIconTitleSpacing = 5;
// The height of the top border necessary to display the title without the icon.
const int kDefaultTitleHeight = 25;
////////////////////////////////////////////////////////////////////////////////
// FrameViewAthena, public:
// The height of the top border in overview mode.
const int kOverviewTitleHeight = 55;
// The height of the top border for fullscreen and frameless activities in
// overview mode.
const int kOverviewShortTitleHeight = 30;
// The thickness of the left, right and bottom borders in overview mode.
const int kOverviewBorderThickness = 5;
} // namespace
// static
const char ActivityFrameView::kViewClassName[] = "ActivityFrameView";
ActivityFrameView::ActivityFrameView(views::Widget* frame,
ActivityViewModel* view_model)
: frame_(frame), view_model_(view_model), title_(new views::Label) {
title_->SetHorizontalAlignment(gfx::ALIGN_CENTER);
: frame_(frame),
view_model_(view_model),
title_(new views::Label),
icon_(new views::ImageView),
in_overview_(false) {
title_->SetEnabledColor(SkColorSetA(SK_ColorBLACK, 0xe5));
title_->SetBorder(views::Border::CreateSolidSidedBorder(0, 0, 1, 0,
SkColorSetA(SK_ColorGRAY, 0x7f)));
SkBitmap bitmap;
bitmap.allocN32Pixels(kIconSize, kIconSize);
bitmap.eraseARGB(255, 0, 255, 0);
icon_->SetImage(gfx::ImageSkia::CreateFrom1xBitmap(bitmap));
AddChildView(title_);
AddChildView(icon_);
SkColor bgcolor = view_model_->GetRepresentativeColor();
set_background(views::Background::CreateSolidBackground(bgcolor));
UpdateWindowTitle();
WindowManager::GetInstance()->AddObserver(this);
}
ActivityFrameView::~ActivityFrameView() {
WindowManager::GetInstance()->RemoveObserver(this);
}
////////////////////////////////////////////////////////////////////////////////
// ActivityFrameView, views::NonClientFrameView overrides:
gfx::Rect ActivityFrameView::GetBoundsForClientView() const {
gfx::Rect client_bounds = bounds();
if (view_model_->UsesFrame())
client_bounds.Inset(0, NonClientTopBorderHeight(), 0, 0);
client_bounds.Inset(NonClientBorderInsets());
return client_bounds;
}
gfx::Rect ActivityFrameView::GetWindowBoundsForClientBounds(
const gfx::Rect& client_bounds) const {
gfx::Rect window_bounds = client_bounds;
if (view_model_->UsesFrame())
window_bounds.Inset(0, -NonClientTopBorderHeight(), 0, 0);
window_bounds.Inset(-NonClientBorderInsets());
return window_bounds;
}
int ActivityFrameView::NonClientHitTest(const gfx::Point& point) {
if (frame_->IsFullscreen())
return 0;
if (title_->bounds().Contains(point))
return HTCAPTION;
return 0;
if (!bounds().Contains(point))
return HTNOWHERE;
int client_hit_test = frame_->client_view()->NonClientHitTest(point);
if (client_hit_test != HTNOWHERE)
return client_hit_test;
int window_hit_test =
GetHTComponentForFrame(point, 0, NonClientBorderThickness(), 0, 0, false);
return (window_hit_test == HTNOWHERE) ? HTCAPTION : client_hit_test;
}
void ActivityFrameView::GetWindowMask(const gfx::Size& size,
......@@ -85,11 +118,9 @@ void ActivityFrameView::UpdateWindowTitle() {
if (!view_model_->UsesFrame())
return;
title_->SetText(frame_->widget_delegate()->GetWindowTitle());
Layout();
}
////////////////////////////////////////////////////////////////////////////////
// ActivityFrameView, views::View overrides:
gfx::Size ActivityFrameView::GetPreferredSize() const {
gfx::Size pref = frame_->client_view()->GetPreferredSize();
gfx::Rect bounds(0, 0, pref.width(), pref.height());
......@@ -103,15 +134,83 @@ const char* ActivityFrameView::GetClassName() const {
}
void ActivityFrameView::Layout() {
title_->SetBounds(0, 0, width(), NonClientTopBorderHeight());
if (frame_->IsFullscreen() || !view_model_->UsesFrame()) {
title_->SetVisible(false);
icon_->SetVisible(false);
return;
}
title_->SetVisible(true);
icon_->SetVisible(in_overview_);
gfx::Size preferred_title_size = title_->GetPreferredSize();
int top_height = NonClientTopBorderHeight();
int title_x = 0;
if (in_overview_) {
int edge = (top_height - kIconSize) / 2;
icon_->SetBounds(edge, edge, kIconSize, kIconSize);
title_x = icon_->bounds().right() + kIconTitleSpacing;
} else {
title_x = (width() - preferred_title_size.width()) / 2;
}
title_->SetBounds(title_x,
(top_height - preferred_title_size.height()) / 2,
preferred_title_size.width(),
preferred_title_size.height());
}
////////////////////////////////////////////////////////////////////////////////
// ActivityFrameView, private:
void ActivityFrameView::OnPaintBackground(gfx::Canvas* canvas) {
View::OnPaintBackground(canvas);
// Paint a border around the client view.
gfx::Rect border_bounds = GetLocalBounds();
border_bounds.Inset(NonClientBorderInsets());
border_bounds.Inset(-1, -1, 0, 0);
canvas->DrawRect(border_bounds, SkColorSetA(SK_ColorGRAY, 0x7f));
}
void ActivityFrameView::OnOverviewModeEnter() {
view_model_->PrepareContentsForOverview();
in_overview_ = true;
InvalidateLayout();
frame_->client_view()->InvalidateLayout();
frame_->GetRootView()->Layout();
SchedulePaint();
}
void ActivityFrameView::OnOverviewModeExit() {
in_overview_ = false;
InvalidateLayout();
frame_->client_view()->InvalidateLayout();
frame_->GetRootView()->Layout();
SchedulePaint();
view_model_->ResetContentsView();
}
void ActivityFrameView::OnSplitViewModeEnter() {
}
void ActivityFrameView::OnSplitViewModeExit() {
}
gfx::Insets ActivityFrameView::NonClientBorderInsets() const {
int border_thickness = NonClientBorderThickness();
return gfx::Insets(NonClientTopBorderHeight(),
border_thickness,
border_thickness,
border_thickness);
}
int ActivityFrameView::NonClientBorderThickness() const {
return in_overview_ ? kOverviewBorderThickness : 0;
}
int ActivityFrameView::NonClientTopBorderHeight() const {
const int kDefaultTitleHeight = 25;
return frame_->IsFullscreen() ? 0 : kDefaultTitleHeight;
if (frame_->IsFullscreen() || !view_model_->UsesFrame())
return in_overview_ ? kOverviewShortTitleHeight : 0;
return in_overview_ ? kOverviewTitleHeight : kDefaultTitleHeight;
}
} // namespace ash
} // namespace athena
......@@ -5,10 +5,13 @@
#ifndef ATHENA_ACTIVITY_ACTIVITY_FRAME_VIEW_H_
#define ATHENA_ACTIVITY_ACTIVITY_FRAME_VIEW_H_
#include "athena/wm/public/window_manager_observer.h"
#include "base/memory/scoped_ptr.h"
#include "ui/gfx/insets.h"
#include "ui/views/window/non_client_view.h"
namespace views {
class ImageView;
class Label;
class Widget;
}
......@@ -18,7 +21,8 @@ namespace athena {
class ActivityViewModel;
// A NonClientFrameView used for activity.
class ActivityFrameView : public views::NonClientFrameView {
class ActivityFrameView : public views::NonClientFrameView,
public WindowManagerObserver {
public:
// Internal class name.
static const char kViewClassName[];
......@@ -26,7 +30,7 @@ class ActivityFrameView : public views::NonClientFrameView {
ActivityFrameView(views::Widget* frame, ActivityViewModel* view_model);
virtual ~ActivityFrameView();
// views::NonClientFrameView overrides:
// views::NonClientFrameView:
virtual gfx::Rect GetBoundsForClientView() const OVERRIDE;
virtual gfx::Rect GetWindowBoundsForClientBounds(
const gfx::Rect& client_bounds) const OVERRIDE;
......@@ -37,18 +41,31 @@ class ActivityFrameView : public views::NonClientFrameView {
virtual void UpdateWindowIcon() OVERRIDE;
virtual void UpdateWindowTitle() OVERRIDE;
// views::View overrides:
// views::View:
virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual const char* GetClassName() const OVERRIDE;
virtual void Layout() OVERRIDE;
virtual void OnPaintBackground(gfx::Canvas* canvas) OVERRIDE;
private:
// WindowManagerObserver:
virtual void OnOverviewModeEnter() OVERRIDE;
virtual void OnOverviewModeExit() OVERRIDE;
virtual void OnSplitViewModeEnter() OVERRIDE;
virtual void OnSplitViewModeExit() OVERRIDE;
gfx::Insets NonClientBorderInsets() const;
int NonClientBorderThickness() const;
int NonClientTopBorderHeight() const;
// Not owned.
views::Widget* frame_;
ActivityViewModel* view_model_;
views::Label* title_;
views::ImageView* icon_;
// Whether overview mode is active.
bool in_overview_;
DISALLOW_COPY_AND_ASSIGN(ActivityFrameView);
};
......
......@@ -57,6 +57,12 @@ class ATHENA_EXPORT ActivityViewModel {
// GetRepresentativeColor() should be used to clear the preview area.
// Note: We intentionally do not use a layer / view for this.
virtual gfx::ImageSkia GetOverviewModeImage() = 0;
// Prepares the contents view for overview.
virtual void PrepareContentsForOverview() = 0;
// Undoes any changes done by PrepareContentsForOverview().
virtual void ResetContentsView() = 0;
};
} // namespace athena
......
......@@ -140,6 +140,17 @@ gfx::ImageSkia AppActivity::GetOverviewModeImage() {
return overview_mode_image_;
}
void AppActivity::PrepareContentsForOverview() {
// Turn on fast resizing to avoid re-laying out the web contents when
// entering / exiting overview mode.
web_view_->SetFastResize(true);
}
void AppActivity::ResetContentsView() {
web_view_->SetFastResize(false);
web_view_->Layout();
}
AppActivity::~AppActivity() {
// If this activity is registered, we unregister it now.
if (app_activity_registry_)
......
......@@ -45,6 +45,8 @@ class AppActivity : public Activity,
virtual views::View* GetContentsView() OVERRIDE;
virtual void CreateOverviewModeImage() OVERRIDE;
virtual gfx::ImageSkia GetOverviewModeImage() OVERRIDE;
virtual void PrepareContentsForOverview() OVERRIDE;
virtual void ResetContentsView() OVERRIDE;
protected:
virtual ~AppActivity();
......
......@@ -90,4 +90,10 @@ gfx::ImageSkia AppActivityProxy::GetOverviewModeImage() {
return image_;
}
void AppActivityProxy::PrepareContentsForOverview() {
}
void AppActivityProxy::ResetContentsView() {
}
} // namespace athena
......@@ -45,6 +45,8 @@ class AppActivityProxy : public Activity,
virtual views::View* GetContentsView() OVERRIDE;
virtual void CreateOverviewModeImage() OVERRIDE;
virtual gfx::ImageSkia GetOverviewModeImage() OVERRIDE;
virtual void PrepareContentsForOverview() OVERRIDE;
virtual void ResetContentsView() OVERRIDE;
private:
// The creator of this object which needs to be informed if the object gets
......
......@@ -465,6 +465,17 @@ gfx::ImageSkia WebActivity::GetOverviewModeImage() {
return overview_mode_image_;
}
void WebActivity::PrepareContentsForOverview() {
// Turn on fast resizing to avoid re-laying out the web contents when
// entering / exiting overview mode.
web_view_->SetFastResize(true);
}
void WebActivity::ResetContentsView() {
web_view_->SetFastResize(false);
web_view_->Layout();
}
void WebActivity::TitleWasSet(content::NavigationEntry* entry,
bool explicit_set) {
ActivityManager::Get()->UpdateActivity(this);
......
......@@ -53,6 +53,8 @@ class WebActivity : public Activity,
virtual views::View* GetContentsView() OVERRIDE;
virtual void CreateOverviewModeImage() OVERRIDE;
virtual gfx::ImageSkia GetOverviewModeImage() OVERRIDE;
virtual void PrepareContentsForOverview() OVERRIDE;
virtual void ResetContentsView() OVERRIDE;
// content::WebContentsObserver:
virtual void TitleWasSet(content::NavigationEntry* entry,
......
......@@ -55,6 +55,8 @@ class TestActivity : public Activity,
virtual views::View* GetContentsView() OVERRIDE { return view_; }
virtual void CreateOverviewModeImage() OVERRIDE {}
virtual gfx::ImageSkia GetOverviewModeImage() OVERRIDE { return image_; }
virtual void PrepareContentsForOverview() OVERRIDE {}
virtual void ResetContentsView() OVERRIDE {}
private:
// The presentation values.
......
......@@ -80,5 +80,11 @@ gfx::ImageSkia SampleActivity::GetOverviewModeImage() {
return gfx::ImageSkia();
}
void SampleActivity::PrepareContentsForOverview() {
}
void SampleActivity::ResetContentsView() {
}
} // namespace test
} // namespace athena
......@@ -38,6 +38,8 @@ class SampleActivity : public Activity,
virtual views::View* GetContentsView() OVERRIDE;
virtual void CreateOverviewModeImage() OVERRIDE;
virtual gfx::ImageSkia GetOverviewModeImage() OVERRIDE;
virtual void PrepareContentsForOverview() OVERRIDE;
virtual void ResetContentsView() OVERRIDE;
SkColor color_;
SkColor contents_color_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment