This source file includes following definitions.
- refresh_action_factory_
- OnDisplayChanged
- AddPanel
- GetDefaultPositionForPanel
- StartingRightPosition
- GetRightMostAvailablePosition
- RemovePanel
- SavePanelPlacement
- RestorePanelToSavedPlacement
- DiscardSavedPanelPlacement
- GetPanelResizability
- OnPanelResizedByMouse
- OnPanelExpansionStateChanged
- AdjustPanelBoundsPerExpansionState
- OnPanelAttentionStateChanged
- OnPanelTitlebarClicked
- ActivatePanel
- MinimizePanel
- RestorePanel
- MinimizeAll
- RestoreAll
- OnMinimizeButtonClicked
- OnRestoreButtonClicked
- CanShowMinimizeButton
- CanShowRestoreButton
- IsPanelMinimized
- UsesAlwaysOnTopPanels
- UpdateMinimizedPanelCount
- ResizePanelWindow
- ShouldBringUpTitlebars
- BringUpOrDownTitlebars
- DelayedBringUpOrDownTitlebarsCheck
- DoBringUpOrDownTitlebars
- GetBottomPositionForExpansionState
- OnMouseMove
- OnAutoHidingDesktopBarVisibilityChanged
- OnAutoHidingDesktopBarThicknessChanged
- RefreshLayout
- WidthToDisplayPanelInCollection
- CloseAll
- UpdatePanelOnCollectionChange
- ScheduleLayoutRefresh
- OnPanelActiveStateChanged
- GetInitialPanelBounds
- HasPanel
#include "chrome/browser/ui/panels/docked_panel_collection.h"
#include <math.h>
#include <algorithm>
#include <vector>
#include "base/auto_reset.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/ui/panels/panel_drag_controller.h"
#include "chrome/browser/ui/panels/panel_manager.h"
#include "chrome/browser/ui/panels/panel_mouse_watcher.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"
namespace {
const int kPanelCollectionLeftMargin = 6;
const int kPanelCollectionRightMargin = 24;
const int kMaxDelayWaitForBottomBarVisibilityChangeMs = 1000;
#if defined(TOOLKIT_GTK)
const int kDelayBeforeCollapsingFromTitleOnlyStateMs = 2000;
#else
const int kDelayBeforeCollapsingFromTitleOnlyStateMs = 0;
#endif
const int kRefreshLayoutAfterActivePanelChangeDelayMs = 600;
const int kNumPanelsToAnimateSimultaneously = 3;
}
DockedPanelCollection::DockedPanelCollection(PanelManager* panel_manager)
: PanelCollection(PanelCollection::DOCKED),
panel_manager_(panel_manager),
minimized_panel_count_(0),
are_titlebars_up_(false),
minimizing_all_(false),
delayed_titlebar_action_(NO_ACTION),
titlebar_action_factory_(this),
refresh_action_factory_(this) {
panel_manager_->display_settings_provider()->AddDesktopBarObserver(this);
OnDisplayChanged();
}
DockedPanelCollection::~DockedPanelCollection() {
DCHECK(panels_.empty());
DCHECK_EQ(0, minimized_panel_count_);
panel_manager_->display_settings_provider()->RemoveDesktopBarObserver(this);
}
void DockedPanelCollection::OnDisplayChanged() {
work_area_ =
panel_manager_->display_settings_provider()->GetPrimaryWorkArea();
work_area_.set_x(work_area_.x() + kPanelCollectionLeftMargin);
work_area_.set_width(work_area_.width() -
kPanelCollectionLeftMargin - kPanelCollectionRightMargin);
if (panels_.empty())
return;
for (Panels::const_iterator iter = panels_.begin();
iter != panels_.end(); ++iter) {
(*iter)->LimitSizeToWorkArea(work_area_);
}
RefreshLayout();
}
void DockedPanelCollection::AddPanel(Panel* panel,
PositioningMask positioning_mask) {
DCHECK_EQ(Panel::EXPANDED, panel->expansion_state());
DCHECK(panel->initialized());
DCHECK_NE(this, panel->collection());
panel->set_collection(this);
bool default_position = (positioning_mask & KNOWN_POSITION) == 0;
bool update_bounds = (positioning_mask & DO_NOT_UPDATE_BOUNDS) == 0;
if (default_position) {
gfx::Size full_size = panel->full_size();
gfx::Point pt = GetDefaultPositionForPanel(full_size);
panel->SetPanelBounds(gfx::Rect(pt, full_size));
panels_.push_back(panel);
} else {
DCHECK(update_bounds);
int x = panel->GetBounds().x();
Panels::iterator iter = panels_.begin();
for (; iter != panels_.end(); ++iter)
if (x > (*iter)->GetBounds().x())
break;
panels_.insert(iter, panel);
}
if (update_bounds) {
if ((positioning_mask & DELAY_LAYOUT_REFRESH) != 0)
ScheduleLayoutRefresh();
else
RefreshLayout();
}
}
gfx::Point DockedPanelCollection::GetDefaultPositionForPanel(
const gfx::Size& full_size) const {
int x = 0;
if (!panels_.empty() &&
panels_.back()->GetBounds().x() < work_area_.x()) {
Panels::const_reverse_iterator iter = panels_.rbegin();
for (; iter != panels_.rend(); ++iter) {
if ((*iter)->GetBounds().x() >= work_area_.x()) {
x = (*iter)->GetBounds().x();
break;
}
}
DCHECK(x > work_area_.x());
} else {
x = std::max(GetRightMostAvailablePosition() - full_size.width(),
work_area_.x());
}
return gfx::Point(x, work_area_.bottom() - full_size.height());
}
int DockedPanelCollection::StartingRightPosition() const {
return work_area_.right();
}
int DockedPanelCollection::GetRightMostAvailablePosition() const {
return panels_.empty() ? StartingRightPosition() :
(panels_.back()->GetBounds().x() - kPanelsHorizontalSpacing);
}
void DockedPanelCollection::RemovePanel(Panel* panel, RemovalReason reason) {
DCHECK_EQ(this, panel->collection());
panel->set_collection(NULL);
DCHECK(!panels_.empty());
if (panels_.back() == panel) {
panels_.pop_back();
if (saved_panel_placement_.panel &&
saved_panel_placement_.left_panel == panel)
saved_panel_placement_.left_panel = NULL;
} else {
Panels::iterator iter = find(panels_.begin(), panels_.end(), panel);
DCHECK(iter != panels_.end());
iter = panels_.erase(iter);
if (saved_panel_placement_.panel &&
saved_panel_placement_.left_panel == panel)
saved_panel_placement_.left_panel = *iter;
}
if (panel->expansion_state() != Panel::EXPANDED)
UpdateMinimizedPanelCount();
RefreshLayout();
}
void DockedPanelCollection::SavePanelPlacement(Panel* panel) {
DCHECK(!saved_panel_placement_.panel);
saved_panel_placement_.panel = panel;
Panels::iterator iter = find(panels_.begin(), panels_.end(), panel);
DCHECK(iter != panels_.end());
++iter;
saved_panel_placement_.left_panel = (iter == panels_.end()) ? NULL : *iter;
}
void DockedPanelCollection::RestorePanelToSavedPlacement() {
DCHECK(saved_panel_placement_.panel);
Panel* panel = saved_panel_placement_.panel;
Panels::iterator iter = std::find(panels_.begin(), panels_.end(), panel);
DCHECK(iter != panels_.end());
Panels::iterator next_iter = iter;
next_iter++;
Panel* next_panel = (next_iter == panels_.end()) ? NULL : *iter;
if (next_panel != saved_panel_placement_.left_panel) {
panels_.erase(iter);
if (saved_panel_placement_.left_panel) {
Panels::iterator iter_to_insert_before = std::find(panels_.begin(),
panels_.end(), saved_panel_placement_.left_panel);
DCHECK(iter_to_insert_before != panels_.end());
panels_.insert(iter_to_insert_before, panel);
} else {
panels_.push_back(panel);
}
}
RefreshLayout();
DiscardSavedPanelPlacement();
}
void DockedPanelCollection::DiscardSavedPanelPlacement() {
DCHECK(saved_panel_placement_.panel);
saved_panel_placement_.panel = NULL;
saved_panel_placement_.left_panel = NULL;
}
panel::Resizability DockedPanelCollection::GetPanelResizability(
const Panel* panel) const {
return (panel->expansion_state() == Panel::EXPANDED) ?
panel::RESIZABLE_EXCEPT_BOTTOM : panel::NOT_RESIZABLE;
}
void DockedPanelCollection::OnPanelResizedByMouse(Panel* panel,
const gfx::Rect& new_bounds) {
DCHECK_EQ(this, panel->collection());
panel->set_full_size(new_bounds.size());
}
void DockedPanelCollection::OnPanelExpansionStateChanged(Panel* panel) {
gfx::Rect panel_bounds = panel->GetBounds();
AdjustPanelBoundsPerExpansionState(panel, &panel_bounds);
panel->SetPanelBounds(panel_bounds);
UpdateMinimizedPanelCount();
if (panel->expansion_state() != Panel::EXPANDED && !minimizing_all_ &&
panel->IsActive()) {
panel->Deactivate();
}
}
void DockedPanelCollection::AdjustPanelBoundsPerExpansionState(Panel* panel,
gfx::Rect* bounds) {
Panel::ExpansionState expansion_state = panel->expansion_state();
switch (expansion_state) {
case Panel::EXPANDED:
bounds->set_height(panel->full_size().height());
break;
case Panel::TITLE_ONLY:
bounds->set_height(panel->TitleOnlyHeight());
break;
case Panel::MINIMIZED:
bounds->set_height(panel::kMinimizedPanelHeight);
break;
default:
NOTREACHED();
break;
}
int bottom = GetBottomPositionForExpansionState(expansion_state);
bounds->set_y(bottom - bounds->height());
}
void DockedPanelCollection::OnPanelAttentionStateChanged(Panel* panel) {
DCHECK_EQ(this, panel->collection());
Panel::ExpansionState state = panel->expansion_state();
if (panel->IsDrawingAttention()) {
if (state == Panel::MINIMIZED)
panel->SetExpansionState(Panel::TITLE_ONLY);
return;
}
if (state != Panel::TITLE_ONLY || are_titlebars_up_)
return;
if (panel_manager_->drag_controller()->dragging_panel() == panel)
return;
const gfx::Point mouse_position =
panel_manager_->mouse_watcher()->GetMousePosition();
gfx::Rect bounds = panel->GetBounds();
if (bounds.x() <= mouse_position.x() &&
mouse_position.x() <= bounds.right() &&
mouse_position.y() >= bounds.y())
return;
panel->SetExpansionState(Panel::MINIMIZED);
}
void DockedPanelCollection::OnPanelTitlebarClicked(Panel* panel,
panel::ClickModifier modifier) {
DCHECK_EQ(this, panel->collection());
if (!IsPanelMinimized(panel))
return;
if (modifier == panel::APPLY_TO_ALL)
RestoreAll();
else
RestorePanel(panel);
}
void DockedPanelCollection::ActivatePanel(Panel* panel) {
DCHECK_EQ(this, panel->collection());
panel->SetExpansionState(Panel::EXPANDED);
}
void DockedPanelCollection::MinimizePanel(Panel* panel) {
DCHECK_EQ(this, panel->collection());
if (panel->expansion_state() != Panel::EXPANDED)
return;
panel->SetExpansionState(panel->IsDrawingAttention() ?
Panel::TITLE_ONLY : Panel::MINIMIZED);
}
void DockedPanelCollection::RestorePanel(Panel* panel) {
DCHECK_EQ(this, panel->collection());
panel->SetExpansionState(Panel::EXPANDED);
}
void DockedPanelCollection::MinimizeAll() {
base::AutoReset<bool> pin(&minimizing_all_, true);
Panel* minimized_active_panel = NULL;
for (Panels::const_iterator iter = panels_.begin();
iter != panels_.end(); ++iter) {
if ((*iter)->IsActive())
minimized_active_panel = *iter;
MinimizePanel(*iter);
}
if (minimized_active_panel) {
minimized_active_panel->Deactivate();
}
}
void DockedPanelCollection::RestoreAll() {
for (Panels::const_iterator iter = panels_.begin();
iter != panels_.end(); ++iter) {
RestorePanel(*iter);
}
}
void DockedPanelCollection::OnMinimizeButtonClicked(
Panel* panel, panel::ClickModifier modifier) {
if (modifier == panel::APPLY_TO_ALL)
MinimizeAll();
else
MinimizePanel(panel);
}
void DockedPanelCollection::OnRestoreButtonClicked(
Panel* panel, panel::ClickModifier modifier) {
if (modifier == panel::APPLY_TO_ALL)
RestoreAll();
else
RestorePanel(panel);
}
bool DockedPanelCollection::CanShowMinimizeButton(const Panel* panel) const {
return !IsPanelMinimized(panel);
}
bool DockedPanelCollection::CanShowRestoreButton(const Panel* panel) const {
return IsPanelMinimized(panel);
}
bool DockedPanelCollection::IsPanelMinimized(const Panel* panel) const {
return panel->expansion_state() != Panel::EXPANDED;
}
bool DockedPanelCollection::UsesAlwaysOnTopPanels() const {
return true;
}
void DockedPanelCollection::UpdateMinimizedPanelCount() {
int prev_minimized_panel_count = minimized_panel_count_;
minimized_panel_count_ = 0;
for (Panels::const_iterator panel_iter = panels_.begin();
panel_iter != panels_.end(); ++panel_iter) {
if ((*panel_iter)->expansion_state() != Panel::EXPANDED)
minimized_panel_count_++;
}
if (prev_minimized_panel_count == 0 && minimized_panel_count_ > 0)
panel_manager_->mouse_watcher()->AddObserver(this);
else if (prev_minimized_panel_count > 0 && minimized_panel_count_ == 0)
panel_manager_->mouse_watcher()->RemoveObserver(this);
DCHECK_LE(minimized_panel_count_, num_panels());
}
void DockedPanelCollection::ResizePanelWindow(
Panel* panel,
const gfx::Size& preferred_window_size) {
DCHECK_EQ(this, panel->collection());
gfx::Size new_size(preferred_window_size.width(),
preferred_window_size.height());
new_size = panel->ClampSize(new_size);
if (new_size == panel->full_size())
return;
panel->set_full_size(new_size);
RefreshLayout();
}
bool DockedPanelCollection::ShouldBringUpTitlebars(int mouse_x,
int mouse_y) const {
DisplaySettingsProvider* provider =
panel_manager_->display_settings_provider();
if (provider->IsAutoHidingDesktopBarEnabled(
DisplaySettingsProvider::DESKTOP_BAR_ALIGNED_BOTTOM) &&
provider->GetDesktopBarVisibility(
DisplaySettingsProvider::DESKTOP_BAR_ALIGNED_BOTTOM) ==
DisplaySettingsProvider::DESKTOP_BAR_VISIBLE) {
int bottom_bar_bottom = work_area_.bottom();
int bottom_bar_y = bottom_bar_bottom - provider->GetDesktopBarThickness(
DisplaySettingsProvider::DESKTOP_BAR_ALIGNED_BOTTOM);
if (bottom_bar_y <= mouse_y && mouse_y <= bottom_bar_bottom)
return true;
}
Panel* dragging_panel = panel_manager_->drag_controller()->dragging_panel();
if (dragging_panel &&
dragging_panel->collection()->type() != PanelCollection::DOCKED)
dragging_panel = NULL;
for (Panels::const_iterator iter = panels_.begin();
iter != panels_.end(); ++iter) {
Panel* panel = *iter;
Panel::ExpansionState state = panel->expansion_state();
if (state == Panel::EXPANDED)
continue;
if (state == Panel::TITLE_ONLY && panel == dragging_panel)
return true;
if (panel->IsDrawingAttention())
continue;
gfx::Rect bounds = panel->GetBounds();
if (bounds.x() <= mouse_x && mouse_x <= bounds.right() &&
mouse_y >= bounds.y())
return true;
}
return false;
}
void DockedPanelCollection::BringUpOrDownTitlebars(bool bring_up) {
if (are_titlebars_up_ == bring_up)
return;
are_titlebars_up_ = bring_up;
int task_delay_ms = 0;
DisplaySettingsProvider* provider =
panel_manager_->display_settings_provider();
if (provider->IsAutoHidingDesktopBarEnabled(
DisplaySettingsProvider::DESKTOP_BAR_ALIGNED_BOTTOM)) {
DisplaySettingsProvider::DesktopBarVisibility visibility =
provider->GetDesktopBarVisibility(
DisplaySettingsProvider::DESKTOP_BAR_ALIGNED_BOTTOM);
if (visibility !=
(bring_up ? DisplaySettingsProvider::DESKTOP_BAR_VISIBLE
: DisplaySettingsProvider::DESKTOP_BAR_HIDDEN)) {
task_delay_ms = kMaxDelayWaitForBottomBarVisibilityChangeMs;
}
}
DCHECK(task_delay_ms == 0 ||
kDelayBeforeCollapsingFromTitleOnlyStateMs == 0);
if (!bring_up && task_delay_ms == 0) {
task_delay_ms = kDelayBeforeCollapsingFromTitleOnlyStateMs;
}
delayed_titlebar_action_ = bring_up ? BRING_UP : BRING_DOWN;
titlebar_action_factory_.InvalidateWeakPtrs();
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&DockedPanelCollection::DelayedBringUpOrDownTitlebarsCheck,
titlebar_action_factory_.GetWeakPtr()),
base::TimeDelta::FromMilliseconds(
PanelManager::AdjustTimeInterval(task_delay_ms)));
}
void DockedPanelCollection::DelayedBringUpOrDownTitlebarsCheck() {
if (delayed_titlebar_action_ == NO_ACTION)
return;
bool need_to_bring_up_titlebars = (delayed_titlebar_action_ == BRING_UP);
delayed_titlebar_action_ = NO_ACTION;
if (are_titlebars_up_ != need_to_bring_up_titlebars)
return;
DoBringUpOrDownTitlebars(need_to_bring_up_titlebars);
}
void DockedPanelCollection::DoBringUpOrDownTitlebars(bool bring_up) {
for (Panels::const_iterator iter = panels_.begin();
iter != panels_.end(); ++iter) {
Panel* panel = *iter;
if (panel->IsDrawingAttention())
continue;
if (bring_up) {
if (panel->expansion_state() == Panel::MINIMIZED)
panel->SetExpansionState(Panel::TITLE_ONLY);
} else {
if (panel->expansion_state() == Panel::TITLE_ONLY)
panel->SetExpansionState(Panel::MINIMIZED);
}
}
}
int DockedPanelCollection::GetBottomPositionForExpansionState(
Panel::ExpansionState expansion_state) const {
int bottom = work_area_.bottom();
DisplaySettingsProvider* provider =
panel_manager_->display_settings_provider();
if (expansion_state == Panel::TITLE_ONLY &&
provider->IsAutoHidingDesktopBarEnabled(
DisplaySettingsProvider::DESKTOP_BAR_ALIGNED_BOTTOM)) {
bottom -= provider->GetDesktopBarThickness(
DisplaySettingsProvider::DESKTOP_BAR_ALIGNED_BOTTOM);
}
return bottom;
}
void DockedPanelCollection::OnMouseMove(const gfx::Point& mouse_position) {
bool bring_up_titlebars = ShouldBringUpTitlebars(mouse_position.x(),
mouse_position.y());
BringUpOrDownTitlebars(bring_up_titlebars);
}
void DockedPanelCollection::OnAutoHidingDesktopBarVisibilityChanged(
DisplaySettingsProvider::DesktopBarAlignment alignment,
DisplaySettingsProvider::DesktopBarVisibility visibility) {
if (delayed_titlebar_action_ == NO_ACTION)
return;
DisplaySettingsProvider::DesktopBarVisibility expected_visibility =
delayed_titlebar_action_ == BRING_UP
? DisplaySettingsProvider::DESKTOP_BAR_VISIBLE
: DisplaySettingsProvider::DESKTOP_BAR_HIDDEN;
if (visibility != expected_visibility)
return;
DoBringUpOrDownTitlebars(delayed_titlebar_action_ == BRING_UP);
delayed_titlebar_action_ = NO_ACTION;
}
void DockedPanelCollection::OnAutoHidingDesktopBarThicknessChanged(
DisplaySettingsProvider::DesktopBarAlignment alignment, int thickness) {
RefreshLayout();
}
void DockedPanelCollection::RefreshLayout() {
int total_active_width = 0;
int total_inactive_width = 0;
for (Panels::const_iterator panel_iter = panels_.begin();
panel_iter != panels_.end(); ++panel_iter) {
Panel* panel = *panel_iter;
if (panel->IsActive())
total_active_width += panel->full_size().width();
else
total_inactive_width += panel->full_size().width();
}
double display_width_for_inactive_panels =
work_area_.width() - total_active_width -
kPanelsHorizontalSpacing * panels_.size();
double overflow_squeeze_factor = (total_inactive_width > 0) ?
std::min(display_width_for_inactive_panels / total_inactive_width, 1.0) :
1.0;
typedef std::pair<Panel*, gfx::Rect> PanelBoundsInfo;
std::vector<PanelBoundsInfo> moving_right;
std::queue<PanelBoundsInfo> moving_left;
int rightmost_position = StartingRightPosition();
for (Panels::const_iterator panel_iter = panels_.begin();
panel_iter != panels_.end(); ++panel_iter) {
Panel* panel = *panel_iter;
gfx::Rect old_bounds = panel->GetBounds();
gfx::Rect new_bounds = old_bounds;
AdjustPanelBoundsPerExpansionState(panel, &new_bounds);
new_bounds.set_width(
WidthToDisplayPanelInCollection(panel->IsActive(),
overflow_squeeze_factor,
panel->full_size().width()));
int x = rightmost_position - new_bounds.width();
new_bounds.set_x(x);
if (x < old_bounds.x() ||
(x == old_bounds.x() && new_bounds.width() <= old_bounds.width()))
moving_left.push(std::make_pair(panel, new_bounds));
else
moving_right.push_back(std::make_pair(panel, new_bounds));
rightmost_position = x - kPanelsHorizontalSpacing;
}
int num_animated = 0;
bool going_right = true;
while (!moving_right.empty() || !moving_left.empty()) {
PanelBoundsInfo bounds_info;
going_right = !going_right;
bool take_panel_on_right =
(going_right && !moving_right.empty()) ||
moving_left.empty();
if (take_panel_on_right) {
bounds_info = moving_right.back();
moving_right.pop_back();
} else {
bounds_info = moving_left.front();
moving_left.pop();
}
Panel* panel = bounds_info.first;
gfx::Rect bounds = bounds_info.second;
if (!panel->in_preview_mode() && bounds != panel->GetBounds()) {
if (num_animated < kNumPanelsToAnimateSimultaneously) {
panel->SetPanelBounds(bounds);
++num_animated;
} else {
panel->SetPanelBoundsInstantly(bounds);
}
}
}
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_PANEL_COLLECTION_UPDATED,
content::Source<PanelCollection>(this),
content::NotificationService::NoDetails());
}
int DockedPanelCollection::WidthToDisplayPanelInCollection(
bool is_for_active_panel, double squeeze_factor, int full_width) const {
return is_for_active_panel ? full_width :
std::max(panel::kPanelMinWidth,
static_cast<int>(floor(full_width * squeeze_factor)));
}
void DockedPanelCollection::CloseAll() {
Panels panels_copy = panels_;
for (Panels::reverse_iterator iter = panels_copy.rbegin();
iter != panels_copy.rend(); ++iter)
(*iter)->Close();
}
void DockedPanelCollection::UpdatePanelOnCollectionChange(Panel* panel) {
panel->set_attention_mode(Panel::USE_PANEL_ATTENTION);
panel->ShowShadow(true);
panel->UpdateMinimizeRestoreButtonVisibility();
panel->SetWindowCornerStyle(panel::TOP_ROUNDED);
}
void DockedPanelCollection::ScheduleLayoutRefresh() {
refresh_action_factory_.InvalidateWeakPtrs();
base::MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&DockedPanelCollection::RefreshLayout,
refresh_action_factory_.GetWeakPtr()),
base::TimeDelta::FromMilliseconds(PanelManager::AdjustTimeInterval(
kRefreshLayoutAfterActivePanelChangeDelayMs)));
}
void DockedPanelCollection::OnPanelActiveStateChanged(Panel* panel) {
ScheduleLayoutRefresh();
}
gfx::Rect DockedPanelCollection::GetInitialPanelBounds(
const gfx::Rect& requested_bounds) const {
gfx::Rect initial_bounds = requested_bounds;
initial_bounds.set_origin(
GetDefaultPositionForPanel(requested_bounds.size()));
return initial_bounds;
}
bool DockedPanelCollection::HasPanel(Panel* panel) const {
return find(panels_.begin(), panels_.end(), panel) != panels_.end();
}