summaryrefslogtreecommitdiffstats
path: root/ash/wm/panel_layout_manager.cc
blob: 0031829f45844b71f92d66c38e9f25e4e884cf2a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/wm/panel_layout_manager.h"

#include <algorithm>

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

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

namespace ash {
namespace internal {

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

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

PanelLayoutManager::~PanelLayoutManager() {
}

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

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

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

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

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

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

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

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

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

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

}  // namespace internal
}  // namespace ash