Skip to content

Commit

Permalink
Add PanelWindow and PanelLayoutManager to ash. (+ win fix)
Browse files Browse the repository at this point in the history
    
This implements a sample implementation of a WidgetDelegateView (PanelWindow) and a LayoutManager to provide an initial out
    
ash_shell must be run with --aura-panels to get the new behavior, since Chrome currently relies on existing behavior for wi

BUG=98330
TEST=Run ash_shell --aura-panels to see a simple panel test implementation. Ensure panels work as expected in Chrome.

Original Review URL: http://codereview.chromium.org/9104027
TBR=dslomov@chromium.org


Review URL: http://codereview.chromium.org/9325051

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@120478 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
stevenjb@chromium.org committed Feb 4, 2012
1 parent 83b583e commit 6b85493
Show file tree
Hide file tree
Showing 11 changed files with 447 additions and 3 deletions.
9 changes: 7 additions & 2 deletions ash/ash.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@
'wm/dialog_frame_view.h',
'wm/image_grid.cc',
'wm/image_grid.h',
'wm/panel_layout_manager.cc',
'wm/panel_layout_manager.h',
'wm/system_modal_container_layout_manager.cc',
'wm/system_modal_container_layout_manager.h',
'wm/system_modal_container_event_filter.cc',
Expand Down Expand Up @@ -227,19 +229,20 @@
'wm/base_layout_manager_unittest.cc',
'wm/compact_layout_manager_unittest.cc',
'wm/image_grid_unittest.cc',
'wm/system_modal_container_layout_manager_unittest.cc',
'wm/panel_layout_manager_unittest.cc',
'wm/power_button_controller_unittest.cc',
'wm/root_window_event_filter_unittest.cc',
'wm/shadow_controller_unittest.cc',
'wm/shelf_layout_manager_unittest.cc',
'wm/system_modal_container_layout_manager_unittest.cc',
'wm/toplevel_layout_manager_unittest.cc',
'wm/toplevel_window_event_filter_unittest.cc',
'wm/video_detector_unittest.cc',
'wm/visibility_controller_unittest.cc',
'wm/window_cycle_controller_unittest.cc',
'wm/window_modality_controller_unittest.cc',
'wm/workspace_controller_unittest.cc',
'wm/workspace/workspace_manager_unittest.cc',
'wm/workspace_controller_unittest.cc',

'<(SHARED_INTERMEDIATE_DIR)/ui/gfx/gfx_resources.rc',
'<(SHARED_INTERMEDIATE_DIR)/ui/ui_resources/ui_resources.rc',
Expand Down Expand Up @@ -293,6 +296,8 @@
'shell/bubble.cc',
'shell/example_factory.h',
'shell/lock_view.cc',
'shell/panel_window.cc',
'shell/panel_window.h',
'shell/shell_main.cc',
'shell/shell_main_parts.cc',
'shell/shell_main_parts.h',
Expand Down
3 changes: 3 additions & 0 deletions ash/ash_switches.cc
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,8 @@ const char kAuraWindowModeManaged[] = "managed";
// Traditional window management with multiple draggable windows.
const char kAuraWindowModeOverlapping[] = "overlapping";

// Use Aura to manage windows of type WINDOW_TYPE_PANEL.
const char kAuraPanelManager[] = "aura-panels";

} // namespace switches
} // namespace ash
1 change: 1 addition & 0 deletions ash/ash_switches.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ ASH_EXPORT extern const char kAuraWindowMode[];
ASH_EXPORT extern const char kAuraWindowModeCompact[];
ASH_EXPORT extern const char kAuraWindowModeManaged[];
ASH_EXPORT extern const char kAuraWindowModeOverlapping[];
ASH_EXPORT extern const char kAuraPanelManager[];

} // namespace switches
} // namespace ash
Expand Down
8 changes: 8 additions & 0 deletions ash/shell.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "ash/wm/compact_layout_manager.h"
#include "ash/wm/compact_status_area_layout_manager.h"
#include "ash/wm/dialog_frame_view.h"
#include "ash/wm/panel_layout_manager.h"
#include "ash/wm/power_button_controller.h"
#include "ash/wm/root_window_event_filter.h"
#include "ash/wm/root_window_layout_manager.h"
Expand Down Expand Up @@ -95,6 +96,13 @@ void CreateSpecialContainers(aura::Window::Windows* containers) {

aura::Window* panel_container = new aura::Window(NULL);
panel_container->set_id(internal::kShellWindowId_PanelContainer);
if (CommandLine::ForCurrentProcess()->
HasSwitch(switches::kAuraPanelManager)) {
panel_container->SetEventFilter(
new ToplevelWindowEventFilter(panel_container));
panel_container->SetLayoutManager(
new internal::PanelLayoutManager(panel_container));
}
containers->push_back(panel_container);

aura::Window* launcher_container = new aura::Window(NULL);
Expand Down
84 changes: 84 additions & 0 deletions ash/shell/panel_window.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/shell/panel_window.h"

#include "ash/wm/toplevel_frame_view.h"
#include "base/utf_string_conversions.h"
#include "ui/aura/window.h"
#include "ui/gfx/canvas.h"
#include "ui/views/widget/widget.h"

namespace {
const int kMinWidth = 100;
const int kMinHeight = 100;
const int kDefaultWidth = 200;
const int kDefaultHeight = 300;
}

namespace ash {

// static
views::Widget* PanelWindow::CreatePanelWindow(const gfx::Rect& rect) {
PanelWindow* panel_window = new PanelWindow("Example Panel Window");
panel_window->params().bounds = rect;
return panel_window->CreateWidget();
}

PanelWindow::PanelWindow(const std::string& name)
: name_(name),
params_(views::Widget::InitParams::TYPE_PANEL) {
params_.delegate = this;
}

PanelWindow::~PanelWindow() {
}

views::Widget* PanelWindow::CreateWidget() {
views::Widget* widget = new views::Widget;

if (params().bounds.width() == 0)
params().bounds.set_width(kDefaultWidth);
if (params().bounds.height() == 0)
params().bounds.set_height(kDefaultHeight);

widget->Init(params());
widget->GetNativeView()->SetName(name_);
widget->Show();

return widget;
}

gfx::Size PanelWindow::GetPreferredSize() {
return gfx::Size(kMinWidth, kMinHeight);
}

void PanelWindow::OnPaint(gfx::Canvas* canvas) {
canvas->FillRect(GetLocalBounds(), SK_ColorGREEN);
}

string16 PanelWindow::GetWindowTitle() const {
return ASCIIToUTF16(name_);
}

views::View* PanelWindow::GetContentsView() {
return this;
}

bool PanelWindow::CanResize() const {
return true;
}

bool PanelWindow::CanMaximize() const {
return false;
}

views::NonClientFrameView* PanelWindow::CreateNonClientFrameView() {
// TODO(stevenjb): Implement a custom frame view for panels.
// For now, use the default frame view (views::CustomFrameView)
// which implements close and resize for us.
return NULL;
}

} // namespace ash
53 changes: 53 additions & 0 deletions ash/shell/panel_window.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef ASH_SHELL_PANEL_WINDOW_H_
#define ASH_SHELL_PANEL_WINDOW_H_
#pragma once

#include "base/basictypes.h"
#include "ui/aura/aura_export.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"

namespace ash {

// Example Class for panel windows (Widget::InitParams::TYPE_PANEL).
// Instances of PanelWindow will get added to the PanelContainer top level
// window which manages the panel layout through PanelLayoutManager.
class PanelWindow : public views::WidgetDelegateView {
public:
explicit PanelWindow(const std::string& name);
virtual ~PanelWindow();

// Creates the widget for the panel window using |params_|.
views::Widget* CreateWidget();

const std::string& name() { return name_; }
views::Widget::InitParams& params() { return params_; }

// Creates a panel window and returns the associated widget.
static views::Widget* CreatePanelWindow(const gfx::Rect& rect);

private:
// Overridden from views::View:
virtual gfx::Size GetPreferredSize() OVERRIDE;
virtual void OnPaint(gfx::Canvas* canvas) OVERRIDE;

// Overridden from views::WidgetDelegate:
virtual string16 GetWindowTitle() const OVERRIDE;
virtual View* GetContentsView() OVERRIDE;
virtual bool CanResize() const OVERRIDE;
virtual bool CanMaximize() const OVERRIDE;
virtual views::NonClientFrameView* CreateNonClientFrameView() OVERRIDE;

std::string name_;
views::Widget::InitParams params_;

DISALLOW_COPY_AND_ASSIGN(PanelWindow);
};

} // namespace ash

#endif // ASH_SHELL_PANEL_WINDOW_H_
13 changes: 12 additions & 1 deletion ash/shell/window_type_launcher.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include "ash/shell_window_ids.h"
#include "ash/shell/example_factory.h"
#include "ash/shell/panel_window.h"
#include "ash/shell/toplevel_window.h"
#include "ash/wm/shadow_types.h"
#include "ash/wm/toplevel_frame_view.h"
Expand Down Expand Up @@ -177,6 +178,8 @@ void InitWindowTypeLauncher() {
WindowTypeLauncher::WindowTypeLauncher()
: ALLOW_THIS_IN_INITIALIZER_LIST(create_button_(
new views::NativeTextButton(this, ASCIIToUTF16("Create Window")))),
ALLOW_THIS_IN_INITIALIZER_LIST(panel_button_(
new views::NativeTextButton(this, ASCIIToUTF16("Create Panel")))),
ALLOW_THIS_IN_INITIALIZER_LIST(create_nonresizable_button_(
new views::NativeTextButton(
this, ASCIIToUTF16("Create Non-Resizable Window")))),
Expand Down Expand Up @@ -204,6 +207,7 @@ WindowTypeLauncher::WindowTypeLauncher()
new views::NativeTextButton(
this, ASCIIToUTF16("Show/Hide a Window")))) {
AddChildView(create_button_);
AddChildView(panel_button_);
AddChildView(create_nonresizable_button_);
AddChildView(bubble_button_);
AddChildView(lock_button_);
Expand Down Expand Up @@ -232,9 +236,14 @@ void WindowTypeLauncher::Layout() {
5, local_bounds.bottom() - create_button_ps.height() - 5,
create_button_ps.width(), create_button_ps.height());

gfx::Size panel_button_ps = panel_button_->GetPreferredSize();
panel_button_->SetBounds(
5, create_button_->y() - panel_button_ps.height() - 5,
panel_button_ps.width(), panel_button_ps.height());

gfx::Size bubble_button_ps = bubble_button_->GetPreferredSize();
bubble_button_->SetBounds(
5, create_button_->y() - bubble_button_ps.height() - 5,
5, panel_button_->y() - bubble_button_ps.height() - 5,
bubble_button_ps.width(), bubble_button_ps.height());

gfx::Size create_nr_button_ps =
Expand Down Expand Up @@ -307,6 +316,8 @@ void WindowTypeLauncher::ButtonPressed(views::Button* sender,
ToplevelWindow::CreateParams params;
params.can_resize = true;
ToplevelWindow::CreateToplevelWindow(params);
} else if (sender == panel_button_) {
PanelWindow::CreatePanelWindow(gfx::Rect());
} else if (sender == create_nonresizable_button_) {
ToplevelWindow::CreateToplevelWindow(ToplevelWindow::CreateParams());
} else if (sender == bubble_button_) {
Expand Down
1 change: 1 addition & 0 deletions ash/shell/window_type_launcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ class WindowTypeLauncher : public views::WidgetDelegateView,
#endif // !defined(OS_MACOSX)

views::NativeTextButton* create_button_;
views::NativeTextButton* panel_button_;
views::NativeTextButton* create_nonresizable_button_;
views::NativeTextButton* bubble_button_;
views::NativeTextButton* lock_button_;
Expand Down
118 changes: 118 additions & 0 deletions ash/wm/panel_layout_manager.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/wm/panel_layout_manager.h"

#include <algorithm>

#include "ash/launcher/launcher.h"
#include "ash/shell.h"
#include "base/auto_reset.h"
#include "ui/aura/root_window.h"
#include "ui/aura/window.h"
#include "ui/gfx/rect.h"
#include "ui/views/widget/widget.h"

namespace {
const int kPanelMarginEdge = 4;
const int kPanelMarginMiddle = 8;
const float kMaxHeightFactor = .80f;
const float kMaxWidthFactor = .50f;
}

namespace ash {
namespace internal {

////////////////////////////////////////////////////////////////////////////////
// PanelLayoutManager public implementation:

PanelLayoutManager::PanelLayoutManager(aura::Window* panel_container)
: panel_container_(panel_container),
in_layout_(false) {
DCHECK(panel_container);
}

PanelLayoutManager::~PanelLayoutManager() {
}

////////////////////////////////////////////////////////////////////////////////
// PanelLayoutManager, aura::LayoutManager implementation:

void PanelLayoutManager::OnWindowResized() {
Relayout();
}

void PanelLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
panel_windows_.push_back(child);
Relayout();
}

void PanelLayoutManager::OnWillRemoveWindowFromLayout(aura::Window* child) {
PanelList::iterator found =
std::find(panel_windows_.begin(), panel_windows_.end(), child);
if (found != panel_windows_.end())
panel_windows_.erase(found);
Relayout();
}

void PanelLayoutManager::OnChildWindowVisibilityChanged(aura::Window* child,
bool visible) {
Relayout();
}

void PanelLayoutManager::SetChildBounds(aura::Window* child,
const gfx::Rect& requested_bounds) {
gfx::Rect bounds(requested_bounds);
const gfx::Rect& max_bounds = panel_container_->GetRootWindow()->bounds();
const int max_width = max_bounds.width() * kMaxWidthFactor;
const int max_height = max_bounds.height() * kMaxHeightFactor;
if (bounds.width() > max_width)
bounds.set_width(max_width);
if (bounds.height() > max_height)
bounds.set_height(max_height);
SetChildBoundsDirect(child, bounds);
Relayout();
}

////////////////////////////////////////////////////////////////////////////////
// PanelLayoutManager private implementation:

// This is a rough outline of a simple panel layout manager.
void PanelLayoutManager::Relayout() {
if (in_layout_)
return;
AutoReset<bool> auto_reset_in_layout(&in_layout_, true);

// Panels are currently laid out just above the launcher (if it exists),
// otherwise at the bottom of the root window.
int right, bottom;
ash::Shell* shell = ash::Shell::GetInstance();
if (shell->launcher() && shell->launcher()->widget()->IsVisible()) {
const gfx::Rect& bounds =
shell->launcher()->widget()->GetWindowScreenBounds();
right = bounds.width() - 1 - kPanelMarginEdge;
bottom = bounds.y() - 1;
} else {
const gfx::Rect& bounds = panel_container_->GetRootWindow()->bounds();
right = bounds.width() - 1 - kPanelMarginEdge;
bottom = bounds.bottom() - 1;
}

// Layout the panel windows right to left.
for (PanelList::iterator iter = panel_windows_.begin();
iter != panel_windows_.end(); ++iter) {
aura::Window* panel_win = *iter;
if (!panel_win->IsVisible())
continue;
int x = right - panel_win->bounds().width();
int y = bottom - panel_win->bounds().height();
gfx::Rect bounds(x, y,
panel_win->bounds().width(), panel_win->bounds().height());
SetChildBoundsDirect(panel_win, bounds);
right = x - kPanelMarginMiddle;
}
}

} // namespace internal
} // namespace ash
Loading

0 comments on commit 6b85493

Please sign in to comment.