12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/panels/stacked_panel_collection.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <algorithm>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/auto_reset.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h"
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/panels/detached_panel_collection.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/panels/display_settings_provider.h"
13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/ui/panels/native_panel_stack_window.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/panels/panel.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/panels/panel_constants.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/panels/panel_manager.h"
17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)StackedPanelCollection::StackedPanelCollection(PanelManager* panel_manager)
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : PanelCollection(PanelCollection::STACKED),
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      panel_manager_(panel_manager),
22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      primary_stack_window_(NULL),
23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      secondary_stack_window_(NULL),
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      minimizing_all_(false) {
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)StackedPanelCollection::~StackedPanelCollection() {
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(panels_.empty());
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(most_recently_active_panels_.empty());
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StackedPanelCollection::OnDisplayChanged() {
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (panels_.empty())
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect enclosing_bounds = GetEnclosingBounds();
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect work_area = panel_manager_->display_settings_provider()->
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetWorkAreaMatching(enclosing_bounds);
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If the height of the whole stack is bigger than the height of the new work
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // area, try to reduce the stack height by collapsing panels. In rare case,
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // all panels are collapsed and there is still not enough space. We simply
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // let the stack go beyond the work area limit.
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (enclosing_bounds.height() > work_area.height()) {
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int needed_space = enclosing_bounds.height() - work_area.height();
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MinimizePanelsForSpace(needed_space);
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect top_bounds = top_panel()->GetBounds();
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int common_width = top_bounds.width();
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (common_width > work_area.width())
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    common_width = work_area.width();
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int common_x = top_bounds.x();
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (common_x + common_width > work_area.right())
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    common_x = work_area.right() - common_width;
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (common_x < work_area.x())
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    common_x = work_area.x();
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int total_height = bottom_panel()->GetBounds().bottom() - top_bounds.y();
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int start_y = top_bounds.y();
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (start_y + total_height > work_area.bottom())
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    start_y = work_area.bottom() - total_height;
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (start_y < work_area.y())
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    start_y = work_area.y();
66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RefreshLayoutWithTopPanelStartingAt(
68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      gfx::Point(common_x, start_y), common_width);
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StackedPanelCollection::RefreshLayout() {
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (panels_.empty())
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Rect top_bounds = top_panel()->GetBounds();
75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  RefreshLayoutWithTopPanelStartingAt(top_bounds.origin(), top_bounds.width());
76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void StackedPanelCollection::RefreshLayoutWithTopPanelStartingAt(
79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const gfx::Point& start_position, int common_width) {
80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (panels_.empty())
81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // If only one panel is left in the stack, we only need to check if it should
84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // be moved to |start_y| position.
85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (panels_.size() == 1) {
86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Panel* panel = panels_.front();
87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    gfx::Rect bounds = panel->GetBounds();
88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (bounds.origin() != start_position) {
89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      bounds.set_origin(start_position);
90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      panel->SetPanelBounds(bounds);
91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // We do not update bounds for affected panels one by one. Instead, all
96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // changes are bundled and performed synchronously.
97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  primary_stack_window_->BeginBatchUpdatePanelBounds(true);
98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (secondary_stack_window_)
99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    secondary_stack_window_->BeginBatchUpdatePanelBounds(true);
100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int y = start_position.y();
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int common_x = start_position.x();
103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (Panels::const_iterator iter = panels_.begin();
104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       iter != panels_.end(); ++iter) {
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Panel* panel = *iter;
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The visibility of minimize button might need to be updated due to that
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // top panel might change when a panel is being added or removed from
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // the stack.
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    panel->UpdateMinimizeRestoreButtonVisibility();
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Don't update the stacked panel that is in preview mode.
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gfx::Rect bounds = panel->GetBounds();
114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (panel->in_preview_mode()) {
115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      y += bounds.height();
116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      continue;
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Update the restored size.
120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    gfx::Size full_size = panel->full_size();
121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    full_size.set_width(common_width);
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    panel->set_full_size(full_size);
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Recompute the bounds.
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bounds.SetRect(
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        common_x,
127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        y,
128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        common_width,
129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        panel->expansion_state() == Panel::EXPANDED ?
130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)            panel->full_size().height() : panel->TitleOnlyHeight());
131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    GetStackWindowForPanel(panel)->AddPanelBoundsForBatchUpdate(panel, bounds);
133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    y += bounds.height();
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  primary_stack_window_->EndBatchUpdatePanelBounds();
138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (secondary_stack_window_)
139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    secondary_stack_window_->EndBatchUpdatePanelBounds();
140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::string16 StackedPanelCollection::GetTitle() const {
143c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (panels_.empty())
144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return base::string16();
145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Panel* panel = panels_.front();
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const extensions::Extension* extension = panel->GetExtension();
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return base::UTF8ToUTF16(extension && !extension->name().empty() ?
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      extension->name() : panel->app_name());
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
152d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)gfx::Image StackedPanelCollection::GetIcon() const {
153d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (panels_.empty())
154d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    return gfx::Image();
155d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  return panels_.front()->app_icon();
156d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)}
157d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void StackedPanelCollection::PanelBoundsBatchUpdateCompleted() {
159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!secondary_stack_window_ || panels_.empty())
160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (top_panel()->in_preview_mode() != bottom_panel()->in_preview_mode() ||
163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      primary_stack_window_->IsAnimatingPanelBounds() ||
164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      secondary_stack_window_->IsAnimatingPanelBounds())
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return;
166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Move all panels from secondary stack window to primary stack window.
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  primary_stack_window_->MergeWith(secondary_stack_window_);
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  secondary_stack_window_->Close();
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  secondary_stack_window_ = NULL;
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Rect StackedPanelCollection::GetEnclosingBounds() const {
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect enclosing_bounds = top_panel()->GetBounds();
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  enclosing_bounds.set_height(
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bottom_panel()->GetBounds().bottom() - enclosing_bounds.y());
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return enclosing_bounds;
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int StackedPanelCollection::MinimizePanelsForSpace(int needed_space) {
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int available_space = GetCurrentAvailableBottomSpace();
182a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
183a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Only the most recently active panel might be active.
184a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  Panel* active_panel = NULL;
185a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (!most_recently_active_panels_.empty()) {
186a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    Panel* most_recently_active_panel = most_recently_active_panels_.front();
187a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (most_recently_active_panel->IsActive())
188a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      active_panel = most_recently_active_panel;
189a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
190a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (Panels::const_reverse_iterator iter =
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           most_recently_active_panels_.rbegin();
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != most_recently_active_panels_.rend() &&
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           available_space < needed_space;
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++iter) {
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Panel* current_panel = *iter;
197a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (current_panel != active_panel && !IsPanelMinimized(current_panel)) {
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      available_space +=
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          current_panel->GetBounds().height() - panel::kTitlebarHeight;
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MinimizePanel(current_panel);
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return available_space;
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StackedPanelCollection::AddPanel(Panel* panel,
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      PositioningMask positioning_mask) {
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_NE(this, panel->collection());
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  panel->set_collection(this);
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Panel* adjacent_panel = NULL;
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (positioning_mask & PanelCollection::TOP_POSITION) {
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    adjacent_panel = top_panel();
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    panels_.push_front(panel);
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // To fit the new panel within the working area, collapse unfocused panels
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // in the least recent active order until there is enough space.
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (positioning_mask & PanelCollection::COLLAPSE_TO_FIT) {
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int needed_space = panel->GetBounds().height();
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      int available_space = MinimizePanelsForSpace(needed_space);
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK(available_space >= needed_space);
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    adjacent_panel = bottom_panel();
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    panels_.push_back(panel);
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (panel->IsActive())
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    most_recently_active_panels_.push_front(panel);
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    most_recently_active_panels_.push_back(panel);
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (adjacent_panel)
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UpdatePanelCornerStyle(adjacent_panel);
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The secondary stack window should be used when one of the following occurs:
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // 1) Some panels but not all panels are being dragged. This is because
237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //    those panels being dragged might not be fully aligned with other panels
238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //    not being dragged.
239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // 2) The newly added panel is not fully aligned with the existing panel, in
240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  //    terms of both x and width.
241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  NativePanelStackWindow* stack_window;
242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (top_panel()->in_preview_mode() == bottom_panel()->in_preview_mode() &&
243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      top_panel()->GetBounds().x() == bottom_panel()->GetBounds().x() &&
244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      top_panel()->GetBounds().width() == bottom_panel()->GetBounds().width()) {
245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!primary_stack_window_)
246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      primary_stack_window_ = NativePanelStackWindow::Create(this);
247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    stack_window = primary_stack_window_;
248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  } else {
249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!secondary_stack_window_)
250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      secondary_stack_window_ = NativePanelStackWindow::Create(this);
251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    stack_window = secondary_stack_window_;
252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  stack_window->AddPanel(panel);
254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if ((positioning_mask & NO_LAYOUT_REFRESH) == 0)
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RefreshLayout();
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StackedPanelCollection::RemovePanel(Panel* panel, RemovalReason reason) {
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool is_top = panel == top_panel();
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool is_bottom = panel == bottom_panel();
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If the top panel is being closed, all panels below it should move up. To
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // do this, the top y position of top panel needs to be tracked first.
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool top_panel_closed = false;
266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Point top_origin;
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  int top_width = 0;
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (reason == PanelCollection::PANEL_CLOSED && is_top) {
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    top_panel_closed = true;
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    top_origin = panel->GetBounds().origin();
271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    top_width = panel->GetBounds().width();
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  panel->set_collection(NULL);
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  panels_.remove(panel);
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  most_recently_active_panels_.remove(panel);
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (is_top) {
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Panel* new_top_panel = top_panel();
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (new_top_panel)
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UpdatePanelCornerStyle(new_top_panel);
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (is_bottom) {
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Panel* new_bottom_panel = bottom_panel();
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (new_bottom_panel)
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UpdatePanelCornerStyle(new_bottom_panel);
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If an active panel is being closed, try to focus the next recently active
2893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // panel in the stack that is not minimized.
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (reason == PanelCollection::PANEL_CLOSED &&
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      panel->IsActive() &&
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      !most_recently_active_panels_.empty()) {
2933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    for (Panels::const_iterator iter = most_recently_active_panels_.begin();
2943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)       iter != most_recently_active_panels_.end(); ++iter) {
2953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      Panel* other_panel = *iter;
2963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      if (!IsPanelMinimized(other_panel)) {
2973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        other_panel->Activate();
2983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        break;
2993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      }
3003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // If the top panel is closed, move up all other panels to stay at the same
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // y position as the top panel being closed.
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (top_panel_closed)
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RefreshLayoutWithTopPanelStartingAt(top_origin, top_width);
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  else if (reason == PanelCollection::PANEL_CLOSED)
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RefreshLayout();
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Remove the panel from the corresponding stack window.
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  GetStackWindowForPanel(panel)->RemovePanel(panel);
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Close the secondary stack window if no panel is is shown inside it.
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Note that we do not need to do this for primary stack window since the
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // whole stack will be gone when only one panel is left.
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (secondary_stack_window_ && secondary_stack_window_->IsEmpty()) {
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    secondary_stack_window_->Close();
318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    secondary_stack_window_ = NULL;
319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StackedPanelCollection::CloseAll() {
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Make a copy as closing panels can modify the iterator.
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Panels panels_copy = panels_;
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (Panels::const_iterator iter = panels_copy.begin();
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != panels_copy.end(); ++iter)
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    (*iter)->Close();
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (primary_stack_window_) {
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    primary_stack_window_->Close();
332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    primary_stack_window_ = NULL;
333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (secondary_stack_window_) {
335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    secondary_stack_window_->Close();
336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    secondary_stack_window_ = NULL;
337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StackedPanelCollection::OnPanelAttentionStateChanged(Panel* panel) {
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if ((panel->attention_mode() & Panel::USE_SYSTEM_ATTENTION) != 0)
342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    primary_stack_window_->DrawSystemAttention(panel->IsDrawingAttention());
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StackedPanelCollection::OnPanelTitlebarClicked(
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Panel* panel, panel::ClickModifier modifier) {
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool expanded = panel->expansion_state() == Panel::EXPANDED;
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (modifier == panel::APPLY_TO_ALL) {
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (expanded)
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MinimizeAll();
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RestoreAll(panel);
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (expanded)
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MinimizePanel(panel);
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RestorePanel(panel);
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StackedPanelCollection::ResizePanelWindow(
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Panel* panel,
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Size& preferred_window_size) {
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StackedPanelCollection::ActivatePanel(Panel* panel) {
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Make sure the panel is expanded when activated so the user input
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // does not go into a collapsed window.
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (panel->IsMinimized())
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    panel->SetExpansionState(Panel::EXPANDED);
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StackedPanelCollection::MinimizePanel(Panel* panel) {
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  panel->SetExpansionState(Panel::TITLE_ONLY);
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StackedPanelCollection::RestorePanel(Panel* panel) {
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ensure that the panel could fit within the work area after it is expanded.
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // First, try to collapse the unfocused panel in the least recent active
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // order in order to get enough space.
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int needed_space = panel->full_size().height() - panel->TitleOnlyHeight();
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int available_space = MinimizePanelsForSpace(needed_space);
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If there is still not enough space, try to move up the stack.
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int space_beyond_available = needed_space - available_space;
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (space_beyond_available > 0) {
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int top_available_space = GetCurrentAvailableTopSpace();
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int move_delta = (space_beyond_available > top_available_space) ?
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        top_available_space : space_beyond_available;
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (Panels::const_iterator iter = panels_.begin();
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         iter != panels_.end(); iter++) {
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Panel* current_panel = *iter;
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      gfx::Rect bounds = current_panel->GetBounds();
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bounds.set_y(bounds.y() - move_delta);
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      current_panel->SetPanelBounds(bounds);
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    available_space += move_delta;
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If there is still not enough space, shrink the restored height to make it
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // fit at the last resort. Note that the restored height cannot be shrunk less
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // than the minimum panel height. If this is the case, we will just let it
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // expand beyond the screen boundary.
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  space_beyond_available = needed_space - available_space;
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (space_beyond_available > 0) {
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    gfx::Size full_size = panel->full_size();
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int reduced_height = full_size.height() - space_beyond_available;
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (reduced_height < panel::kPanelMinHeight)
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      reduced_height = panel::kPanelMinHeight;
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    full_size.set_height(reduced_height);
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    panel->set_full_size(full_size);
4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  panel->SetExpansionState(Panel::EXPANDED);
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StackedPanelCollection::MinimizeAll() {
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Set minimizing_all_ to prevent deactivation of each panel when it
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // is minimized. See comments in OnPanelExpansionStateChanged.
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::AutoReset<bool> pin(&minimizing_all_, true);
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Panel* minimized_active_panel = NULL;
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (Panels::const_iterator iter = panels_.begin();
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != panels_.end(); ++iter) {
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if ((*iter)->IsActive())
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      minimized_active_panel = *iter;
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MinimizePanel(*iter);
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // When a single panel is minimized, it is deactivated to ensure that
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // a minimized panel does not have focus. However, when minimizing all,
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the deactivation is only done once after all panels are minimized,
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // rather than per minimized panel, both for efficiency and to avoid
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // temporary activations of random not-yet-minimized panels.
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (minimized_active_panel) {
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    minimized_active_panel->Deactivate();
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Layout will be refreshed in response to (de)activation notification.
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StackedPanelCollection::RestoreAll(Panel* panel_clicked) {
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Expand the panel being clicked first. This is to make sure at least one
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // panel that is clicked by the user will be expanded.
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RestorePanel(panel_clicked);
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Try to expand all other panels starting from the most recently active
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // panel.
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (Panels::const_iterator iter = most_recently_active_panels_.begin();
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != most_recently_active_panels_.end(); ++iter) {
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If the stack already extends to both top and bottom of the work area,
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // stop now since we cannot fit any more expanded panels.
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (GetCurrentAvailableTopSpace() == 0 &&
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GetCurrentAvailableBottomSpace() == 0) {
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Panel* panel = *iter;
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (panel != panel_clicked)
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RestorePanel(panel);
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StackedPanelCollection::OnMinimizeButtonClicked(
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Panel* panel, panel::ClickModifier modifier) {
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The minimize button is only present in the top panel.
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(top_panel(), panel);
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
467c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  primary_stack_window_->Minimize();
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StackedPanelCollection::OnRestoreButtonClicked(
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Panel* panel, panel::ClickModifier modifier) {
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NOTREACHED();
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool StackedPanelCollection::CanShowMinimizeButton(const Panel* panel) const {
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Only the top panel in the stack shows the minimize button.
477a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return PanelManager::CanUseSystemMinimize() && panel == top_panel();
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool StackedPanelCollection::CanShowRestoreButton(const Panel* panel) const {
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool StackedPanelCollection::IsPanelMinimized(const Panel* panel) const {
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return panel->expansion_state() != Panel::EXPANDED;
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
48890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool StackedPanelCollection::UsesAlwaysOnTopPanels() const {
48990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return false;
49090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
49190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StackedPanelCollection::SavePanelPlacement(Panel* panel) {
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!saved_panel_placement_.panel);
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  saved_panel_placement_.panel = panel;
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (top_panel() != panel)
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    saved_panel_placement_.top_panel = top_panel();
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    saved_panel_placement_.position = panel->GetBounds().origin();
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  saved_panel_placement_.top_panel = top_panel() != panel ? top_panel() : NULL;
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StackedPanelCollection::RestorePanelToSavedPlacement() {
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(saved_panel_placement_.panel);
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (saved_panel_placement_.top_panel) {
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Restore the top panel if it has been moved out of the stack. This could
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // happen when there're 2 panels in the stack and the bottom panel is being
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // dragged out of the stack and thus cause both panels become detached.
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (saved_panel_placement_.top_panel->stack() != this) {
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DCHECK_EQ(PanelCollection::DETACHED,
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                saved_panel_placement_.top_panel->collection()->type());
514c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      panel_manager_->MovePanelToCollection(
515c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          saved_panel_placement_.top_panel,
516c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          this,
517c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)          static_cast<PanelCollection::PositioningMask>(
518c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              PanelCollection::TOP_POSITION |
519c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)              PanelCollection::NO_LAYOUT_REFRESH));
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RefreshLayout();
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Restore the position when the top panel is being dragged.
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_EQ(top_panel(), saved_panel_placement_.panel);
525c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    RefreshLayoutWithTopPanelStartingAt(saved_panel_placement_.position,
526c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                        top_panel()->GetBounds().width());
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DiscardSavedPanelPlacement();
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StackedPanelCollection::DiscardSavedPanelPlacement() {
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(saved_panel_placement_.panel);
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  saved_panel_placement_.panel = NULL;
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  saved_panel_placement_.top_panel = NULL;
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)panel::Resizability StackedPanelCollection::GetPanelResizability(
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const Panel* panel) const {
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The panel in the stack can be resized by the following rules:
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // * If collapsed, it can only be resized by its left or right edge.
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // * Otherwise, it can be resized by its left or right edge plus:
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //   % top edge and corners, if it is at the top;
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //   % bottom edge, if it is not at the bottom.
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //   % bottom edge and corners, if it is at the bottom.
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  panel::Resizability resizability = static_cast<panel::Resizability>(
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      panel::RESIZABLE_LEFT | panel::RESIZABLE_RIGHT);
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (panel->IsMinimized())
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return resizability;
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (panel == top_panel()) {
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    resizability = static_cast<panel::Resizability>(resizability |
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        panel::RESIZABLE_TOP | panel::RESIZABLE_TOP_LEFT |
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        panel::RESIZABLE_TOP_RIGHT);
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (panel == bottom_panel()) {
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    resizability = static_cast<panel::Resizability>(resizability |
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        panel::RESIZABLE_BOTTOM | panel::RESIZABLE_BOTTOM_LEFT |
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        panel::RESIZABLE_BOTTOM_RIGHT);
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    resizability = static_cast<panel::Resizability>(resizability |
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        panel::RESIZABLE_BOTTOM);
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return resizability;
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StackedPanelCollection::OnPanelResizedByMouse(
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Panel* resized_panel, const gfx::Rect& new_bounds) {
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  resized_panel->set_full_size(new_bounds.size());
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
570c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!secondary_stack_window_);
571c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  primary_stack_window_->BeginBatchUpdatePanelBounds(false);
572c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The delta x and width can be computed from the difference between
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the panel being resized and any other panel.
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Panel* other_panel = resized_panel == top_panel() ? bottom_panel()
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                    : top_panel();
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect other_bounds = other_panel->GetBounds();
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int delta_x = new_bounds.x() - other_bounds.x();
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int delta_width = new_bounds.width() - other_bounds.width();
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect previous_bounds;
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool resized_panel_found = false;
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool panel_below_resized_panel_updated = false;
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (Panels::const_iterator iter = panels_.begin();
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != panels_.end(); iter++) {
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Panel* panel = *iter;
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (panel == resized_panel) {
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // |new_bounds| should be used since the panel bounds have not been
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // updated yet.
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      previous_bounds = new_bounds;
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      resized_panel_found = true;
592c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      primary_stack_window_->AddPanelBoundsForBatchUpdate(panel, new_bounds);
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      continue;
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
596c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    gfx::Rect bounds = panel->GetBounds();
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bounds.set_x(bounds.x() + delta_x);
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bounds.set_width(bounds.width() + delta_width);
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If the panel below the panel being resized is expanded, update its
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // height to offset the height change of the panel being resized.
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // For example, the stack has P1 and P2 (from top to bottom). P1's height
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // is 100 and P2's height is 120. If P1's bottom increases by 10, P2's
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // height needs to shrink by 10.
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (resized_panel_found) {
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!panel_below_resized_panel_updated && !panel->IsMinimized()) {
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        int old_bottom = bounds.bottom();
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        bounds.set_y(previous_bounds.bottom());
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        bounds.set_height(old_bottom - bounds.y());
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      } else {
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        bounds.set_y(previous_bounds.bottom());
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      panel_below_resized_panel_updated = true;
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!panel->IsMinimized())
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      panel->set_full_size(bounds.size());
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
619c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    primary_stack_window_->AddPanelBoundsForBatchUpdate(panel, bounds);
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    previous_bounds = bounds;
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
623c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  primary_stack_window_->EndBatchUpdatePanelBounds();
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool StackedPanelCollection::HasPanel(Panel* panel) const {
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return std::find(panels_.begin(), panels_.end(), panel) != panels_.end();
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StackedPanelCollection::UpdatePanelOnCollectionChange(Panel* panel) {
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  panel->set_attention_mode(
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<Panel::AttentionMode>(Panel::USE_PANEL_ATTENTION |
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        Panel::USE_SYSTEM_ATTENTION));
634c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  panel->ShowShadow(false);
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  panel->UpdateMinimizeRestoreButtonVisibility();
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdatePanelCornerStyle(panel);
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StackedPanelCollection::OnPanelExpansionStateChanged(Panel* panel) {
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_NE(Panel::MINIMIZED, panel->expansion_state());
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Ensure minimized panel does not get the focus. If minimizing all,
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the active panel will be deactivated once when all panels are minimized
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // rather than per minimized panel.
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (panel->expansion_state() != Panel::EXPANDED && !minimizing_all_ &&
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      panel->IsActive()) {
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    panel->Deactivate();
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
650c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // The bounds change per expansion state will be done in RefreshLayout.
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  RefreshLayout();
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StackedPanelCollection::OnPanelActiveStateChanged(Panel* panel) {
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!panel->IsActive())
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
658a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Move the panel to the front if not yet.
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Panels::iterator iter = std::find(most_recently_active_panels_.begin(),
6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      most_recently_active_panels_.end(), panel);
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(iter != most_recently_active_panels_.end());
662a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (iter != most_recently_active_panels_.begin()) {
663a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    most_recently_active_panels_.erase(iter);
664a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    most_recently_active_panels_.push_front(panel);
665a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
667a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  GetStackWindowForPanel(panel)->OnPanelActivated(panel);
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
670c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)gfx::Rect StackedPanelCollection::GetInitialPanelBounds(
671c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      const gfx::Rect& requested_bounds) const {
672c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK(!panels_.empty());
673c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  gfx::Rect bottom_panel_bounds = bottom_panel()->GetBounds();
674c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return gfx::Rect(bottom_panel_bounds.x(),
675c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   bottom_panel_bounds.bottom(),
676c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   bottom_panel_bounds.width(),
677c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   requested_bounds.height());
678c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
679c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Panel* StackedPanelCollection::GetPanelAbove(Panel* panel) const {
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(panel);
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (panels_.size() < 2)
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Panels::const_iterator iter = panels_.begin();
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Panel* above_panel = *iter;
6872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (; iter != panels_.end(); ++iter) {
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (*iter == panel)
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return above_panel;
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    above_panel = *iter;
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return NULL;
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Panel* StackedPanelCollection::GetPanelBelow(Panel* panel) const {
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(panel);
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (panels_.size() < 2)
6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Panels::const_iterator iter =
7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::find(panels_.begin(), panels_.end(), panel);
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (iter == panels_.end())
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ++iter;
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return iter == panels_.end() ? NULL : *iter;
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StackedPanelCollection::MoveAllDraggingPanelsInstantly(
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Vector2d& delta_origin) {
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (Panels::const_iterator iter = panels_.begin();
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != panels_.end(); iter++) {
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Panel* panel = *iter;
713c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (panel->in_preview_mode()) {
714c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetStackWindowForPanel(panel)->MovePanelsBy(delta_origin);
715c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return;
716c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
720c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool StackedPanelCollection::IsMinimized() const {
721c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return primary_stack_window_->IsMinimized();
722c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
723c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
724c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool StackedPanelCollection::IsAnimatingPanelBounds(Panel* panel) const {
725c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return GetStackWindowForPanel(panel)->IsAnimatingPanelBounds();
726c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
727c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void StackedPanelCollection::UpdatePanelCornerStyle(Panel* panel) {
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  panel::CornerStyle corner_style;
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool at_top = panel == top_panel();
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool at_bottom = panel == bottom_panel();
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (at_top && at_bottom)
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    corner_style = panel::ALL_ROUNDED;
7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else if (at_top)
7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    corner_style = panel::TOP_ROUNDED;
7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else if (at_bottom)
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    corner_style = panel::BOTTOM_ROUNDED;
7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    corner_style = panel::NOT_ROUNDED;
7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  panel->SetWindowCornerStyle(corner_style);
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::Rect StackedPanelCollection::GetWorkArea() const {
7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (panels_.empty())
7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return panel_manager_->display_settings_provider()->GetPrimaryWorkArea();
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return panel_manager_->display_settings_provider()->GetWorkAreaMatching(
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetEnclosingBounds());
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int StackedPanelCollection::GetCurrentAvailableTopSpace() const {
7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect work_area = GetWorkArea();
7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (panels_.empty())
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return work_area.height();
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int available_space = top_panel()->GetBounds().y() - work_area.y();
7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (available_space < 0)
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    available_space = 0;
7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return available_space;
7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int StackedPanelCollection::GetCurrentAvailableBottomSpace() const {
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect work_area = GetWorkArea();
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (panels_.empty())
7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return work_area.height();
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int available_space = work_area.bottom() -
7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bottom_panel()->GetBounds().bottom();
7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (available_space < 0)
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    available_space = 0;
7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return available_space;
7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int StackedPanelCollection::GetMaximiumAvailableBottomSpace() const {
7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect work_area = GetWorkArea();
7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (panels_.empty())
7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return work_area.height();
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int bottom = top_panel()->GetBounds().y();
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (Panels::const_iterator iter = panels_.begin();
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       iter != panels_.end(); iter++) {
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Panel* panel = *iter;
782a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    // Only the most recently active panel might be active.
783a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    if (iter == panels_.begin() && panel->IsActive())
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bottom += panel->GetBounds().height();
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bottom += panel::kTitlebarHeight;
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int available_space = work_area.bottom() - bottom;
7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (available_space < 0)
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    available_space = 0;
7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return available_space;
7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
793c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
794c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)NativePanelStackWindow* StackedPanelCollection::GetStackWindowForPanel(
795c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Panel* panel) const {
796c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return secondary_stack_window_ && secondary_stack_window_->HasPanel(panel) ?
797c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      secondary_stack_window_ : primary_stack_window_;
798c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
799