This source file includes following definitions.
- resize_area_corner_size_
- Init
- GetBoundsForClientView
- GetWindowBoundsForClientBounds
- NonClientHitTest
- GetWindowMask
- GetPreferredSize
- Layout
- OnPaint
- GetClassName
- GetMinimumSize
- GetMaximumSize
- ButtonPressed
#include "apps/ui/views/app_window_frame_view.h"
#include "apps/ui/native_app_window.h"
#include "base/strings/utf_string_conversions.h"
#include "extensions/common/draggable_region.h"
#include "grit/theme_resources.h"
#include "grit/ui_strings.h"
#include "third_party/skia/include/core/SkPaint.h"
#include "third_party/skia/include/core/SkRegion.h"
#include "ui/base/hit_test.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/path.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/layout/grid_layout.h"
#include "ui/views/views_delegate.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
#if defined(USE_AURA)
#include "ui/aura/env.h"
#include "ui/aura/window.h"
#endif
namespace {
const int kCaptionHeight = 25;
}
namespace apps {
const char AppWindowFrameView::kViewClassName[] =
"browser/ui/views/extensions/AppWindowFrameView";
AppWindowFrameView::AppWindowFrameView()
: widget_(NULL),
window_(NULL),
close_button_(NULL),
maximize_button_(NULL),
restore_button_(NULL),
minimize_button_(NULL),
resize_inside_bounds_size_(0),
resize_outside_bounds_size_(0),
resize_area_corner_size_(0) {}
AppWindowFrameView::~AppWindowFrameView() {}
void AppWindowFrameView::Init(views::Widget* widget,
NativeAppWindow* window,
bool draw_frame,
const SkColor& frame_color,
int resize_inside_bounds_size,
int resize_outside_bounds_size,
int resize_outside_scale_for_touch,
int resize_area_corner_size) {
widget_ = widget;
window_ = window;
draw_frame_ = draw_frame;
frame_color_ = frame_color;
resize_inside_bounds_size_ = resize_inside_bounds_size;
resize_outside_bounds_size_ = resize_outside_bounds_size;
resize_area_corner_size_ = resize_area_corner_size;
if (draw_frame) {
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
close_button_ = new views::ImageButton(this);
close_button_->SetImage(
views::CustomButton::STATE_NORMAL,
rb.GetNativeImageNamed(IDR_APP_WINDOW_CLOSE).ToImageSkia());
close_button_->SetImage(
views::CustomButton::STATE_HOVERED,
rb.GetNativeImageNamed(IDR_APP_WINDOW_CLOSE_H).ToImageSkia());
close_button_->SetImage(
views::CustomButton::STATE_PRESSED,
rb.GetNativeImageNamed(IDR_APP_WINDOW_CLOSE_P).ToImageSkia());
close_button_->SetAccessibleName(
l10n_util::GetStringUTF16(IDS_APP_ACCNAME_CLOSE));
AddChildView(close_button_);
maximize_button_ = new views::ImageButton(this);
maximize_button_->SetImage(
views::CustomButton::STATE_NORMAL,
rb.GetNativeImageNamed(IDR_APP_WINDOW_MAXIMIZE).ToImageSkia());
maximize_button_->SetImage(
views::CustomButton::STATE_HOVERED,
rb.GetNativeImageNamed(IDR_APP_WINDOW_MAXIMIZE_H).ToImageSkia());
maximize_button_->SetImage(
views::CustomButton::STATE_PRESSED,
rb.GetNativeImageNamed(IDR_APP_WINDOW_MAXIMIZE_P).ToImageSkia());
maximize_button_->SetImage(
views::CustomButton::STATE_DISABLED,
rb.GetNativeImageNamed(IDR_APP_WINDOW_MAXIMIZE_D).ToImageSkia());
maximize_button_->SetAccessibleName(
l10n_util::GetStringUTF16(IDS_APP_ACCNAME_MAXIMIZE));
AddChildView(maximize_button_);
restore_button_ = new views::ImageButton(this);
restore_button_->SetImage(
views::CustomButton::STATE_NORMAL,
rb.GetNativeImageNamed(IDR_APP_WINDOW_RESTORE).ToImageSkia());
restore_button_->SetImage(
views::CustomButton::STATE_HOVERED,
rb.GetNativeImageNamed(IDR_APP_WINDOW_RESTORE_H).ToImageSkia());
restore_button_->SetImage(
views::CustomButton::STATE_PRESSED,
rb.GetNativeImageNamed(IDR_APP_WINDOW_RESTORE_P).ToImageSkia());
restore_button_->SetAccessibleName(
l10n_util::GetStringUTF16(IDS_APP_ACCNAME_RESTORE));
AddChildView(restore_button_);
minimize_button_ = new views::ImageButton(this);
minimize_button_->SetImage(
views::CustomButton::STATE_NORMAL,
rb.GetNativeImageNamed(IDR_APP_WINDOW_MINIMIZE).ToImageSkia());
minimize_button_->SetImage(
views::CustomButton::STATE_HOVERED,
rb.GetNativeImageNamed(IDR_APP_WINDOW_MINIMIZE_H).ToImageSkia());
minimize_button_->SetImage(
views::CustomButton::STATE_PRESSED,
rb.GetNativeImageNamed(IDR_APP_WINDOW_MINIMIZE_P).ToImageSkia());
minimize_button_->SetAccessibleName(
l10n_util::GetStringUTF16(IDS_APP_ACCNAME_MINIMIZE));
AddChildView(minimize_button_);
}
}
gfx::Rect AppWindowFrameView::GetBoundsForClientView() const {
if (!draw_frame_ || widget_->IsFullscreen())
return bounds();
return gfx::Rect(
0, kCaptionHeight, width(), std::max(0, height() - kCaptionHeight));
}
gfx::Rect AppWindowFrameView::GetWindowBoundsForClientBounds(
const gfx::Rect& client_bounds) const {
gfx::Rect window_bounds = client_bounds;
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
gfx::Insets native_frame_insets =
widget_->GetClientAreaBoundsInScreen().InsetsFrom(
widget_->GetWindowBoundsInScreen());
window_bounds.Inset(native_frame_insets);
#endif
if (!draw_frame_) {
if (window_bounds.IsEmpty()) {
window_bounds.set_width(1);
window_bounds.set_height(1);
}
return window_bounds;
}
int closeButtonOffsetX = (kCaptionHeight - close_button_->height()) / 2;
int header_width = close_button_->width() + closeButtonOffsetX * 2;
return gfx::Rect(window_bounds.x(),
window_bounds.y() - kCaptionHeight,
std::max(header_width, window_bounds.width()),
window_bounds.height() + kCaptionHeight);
}
int AppWindowFrameView::NonClientHitTest(const gfx::Point& point) {
if (widget_->IsFullscreen())
return HTCLIENT;
gfx::Rect expanded_bounds = bounds();
if (resize_outside_bounds_size_) {
expanded_bounds.Inset(gfx::Insets(-resize_outside_bounds_size_,
-resize_outside_bounds_size_,
-resize_outside_bounds_size_,
-resize_outside_bounds_size_));
}
if (!expanded_bounds.Contains(point))
return HTNOWHERE;
bool can_ever_resize = widget_->widget_delegate()
? widget_->widget_delegate()->CanResize()
: false;
int resize_border = (widget_->IsMaximized() || widget_->IsFullscreen())
? 0
: resize_inside_bounds_size_;
int frame_component = GetHTComponentForFrame(point,
resize_border,
resize_border,
resize_area_corner_size_,
resize_area_corner_size_,
can_ever_resize);
if (frame_component != HTNOWHERE)
return frame_component;
SkRegion* draggable_region = window_->GetDraggableRegion();
if (draggable_region && draggable_region->contains(point.x(), point.y()))
return HTCAPTION;
int client_component = widget_->client_view()->NonClientHitTest(point);
if (client_component != HTNOWHERE)
return client_component;
if (close_button_ && close_button_->visible() &&
close_button_->GetMirroredBounds().Contains(point)) {
return HTCLOSE;
}
if ((maximize_button_ && maximize_button_->visible() &&
maximize_button_->GetMirroredBounds().Contains(point)) ||
(restore_button_ && restore_button_->visible() &&
restore_button_->GetMirroredBounds().Contains(point))) {
return HTMAXBUTTON;
}
if (minimize_button_ && minimize_button_->visible() &&
minimize_button_->GetMirroredBounds().Contains(point)) {
return HTMINBUTTON;
}
return HTCAPTION;
}
void AppWindowFrameView::GetWindowMask(const gfx::Size& size,
gfx::Path* window_mask) {
}
gfx::Size AppWindowFrameView::GetPreferredSize() {
gfx::Size pref = widget_->client_view()->GetPreferredSize();
gfx::Rect bounds(0, 0, pref.width(), pref.height());
return widget_->non_client_view()
->GetWindowBoundsForClientBounds(bounds)
.size();
}
void AppWindowFrameView::Layout() {
if (!draw_frame_)
return;
gfx::Size close_size = close_button_->GetPreferredSize();
const int kButtonOffsetY = 0;
const int kButtonSpacing = 1;
const int kRightMargin = 3;
close_button_->SetBounds(width() - kRightMargin - close_size.width(),
kButtonOffsetY,
close_size.width(),
close_size.height());
bool can_ever_resize = widget_->widget_delegate()
? widget_->widget_delegate()->CanResize()
: false;
maximize_button_->SetEnabled(can_ever_resize);
gfx::Size maximize_size = maximize_button_->GetPreferredSize();
maximize_button_->SetBounds(
close_button_->x() - kButtonSpacing - maximize_size.width(),
kButtonOffsetY,
maximize_size.width(),
maximize_size.height());
gfx::Size restore_size = restore_button_->GetPreferredSize();
restore_button_->SetBounds(
close_button_->x() - kButtonSpacing - restore_size.width(),
kButtonOffsetY,
restore_size.width(),
restore_size.height());
bool maximized = widget_->IsMaximized();
maximize_button_->SetVisible(!maximized);
restore_button_->SetVisible(maximized);
if (maximized)
maximize_button_->SetState(views::CustomButton::STATE_NORMAL);
else
restore_button_->SetState(views::CustomButton::STATE_NORMAL);
gfx::Size minimize_size = minimize_button_->GetPreferredSize();
minimize_button_->SetState(views::CustomButton::STATE_NORMAL);
minimize_button_->SetBounds(
maximize_button_->x() - kButtonSpacing - minimize_size.width(),
kButtonOffsetY,
minimize_size.width(),
minimize_size.height());
}
void AppWindowFrameView::OnPaint(gfx::Canvas* canvas) {
if (!draw_frame_)
return;
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
if (ShouldPaintAsActive()) {
close_button_->SetImage(
views::CustomButton::STATE_NORMAL,
rb.GetNativeImageNamed(IDR_APP_WINDOW_CLOSE).ToImageSkia());
} else {
close_button_->SetImage(
views::CustomButton::STATE_NORMAL,
rb.GetNativeImageNamed(IDR_APP_WINDOW_CLOSE_U).ToImageSkia());
}
SkPaint paint;
paint.setAntiAlias(false);
paint.setStyle(SkPaint::kFill_Style);
paint.setColor(frame_color_);
gfx::Path path;
path.moveTo(0, 0);
path.lineTo(width(), 0);
path.lineTo(width(), kCaptionHeight);
path.lineTo(0, kCaptionHeight);
path.close();
canvas->DrawPath(path, paint);
}
const char* AppWindowFrameView::GetClassName() const { return kViewClassName; }
gfx::Size AppWindowFrameView::GetMinimumSize() {
gfx::Size min_size = widget_->client_view()->GetMinimumSize();
if (!draw_frame_)
return min_size;
gfx::Rect client_bounds = GetBoundsForClientView();
min_size.Enlarge(0, client_bounds.y());
int closeButtonOffsetX = (kCaptionHeight - close_button_->height()) / 2;
int header_width = close_button_->width() + closeButtonOffsetX * 2;
if (header_width > min_size.width())
min_size.set_width(header_width);
return min_size;
}
gfx::Size AppWindowFrameView::GetMaximumSize() {
gfx::Size max_size = widget_->client_view()->GetMaximumSize();
gfx::Size client_size = GetBoundsForClientView().size();
if (max_size.width())
max_size.Enlarge(width() - client_size.width(), 0);
if (max_size.height())
max_size.Enlarge(0, height() - client_size.height());
return max_size;
}
void AppWindowFrameView::ButtonPressed(views::Button* sender,
const ui::Event& event) {
DCHECK(draw_frame_);
if (sender == close_button_)
widget_->Close();
else if (sender == maximize_button_)
widget_->Maximize();
else if (sender == restore_button_)
widget_->Restore();
else if (sender == minimize_button_)
widget_->Minimize();
}
}