This source file includes following definitions.
- GetViewsWithAssociatedWindow
- GetOrderOfViewsWithLayers
- StartObserving
- StopObserving
- OnWindowPropertyChanged
- OnWindowDestroying
- association_observer_
- ReorderChildWindows
- OnWindowAdded
- OnWillRemoveWindow
- OnWindowDestroying
#include "ui/views/widget/window_reorderer.h"
#include <map>
#include <vector>
#include "ui/aura/window.h"
#include "ui/views/view.h"
#include "ui/views/view_constants_aura.h"
namespace views {
namespace {
void GetViewsWithAssociatedWindow(
const aura::Window& parent_window,
std::map<views::View*, aura::Window*>* hosted_windows) {
const std::vector<aura::Window*>& child_windows = parent_window.children();
for (size_t i = 0; i < child_windows.size(); ++i) {
aura::Window* child = child_windows[i];
View* host_view = child->GetProperty(kHostViewKey);
if (host_view)
(*hosted_windows)[host_view] = child;
}
}
void GetOrderOfViewsWithLayers(
views::View* view,
ui::Layer* parent_layer,
const std::map<views::View*, aura::Window*>& hosts,
std::vector<views::View*>* order) {
DCHECK(view);
DCHECK(parent_layer);
DCHECK(order);
if (view->layer() && view->layer()->parent() == parent_layer) {
order->push_back(view);
} else if (hosts.find(view) != hosts.end()) {
order->push_back(view);
}
for (int i = 0; i < view->child_count(); ++i)
GetOrderOfViewsWithLayers(view->child_at(i), parent_layer, hosts, order);
}
}
class WindowReorderer::AssociationObserver : public aura::WindowObserver {
public:
explicit AssociationObserver(WindowReorderer* reorderer);
virtual ~AssociationObserver();
void StartObserving(aura::Window* window);
void StopObserving(aura::Window* window);
private:
virtual void OnWindowPropertyChanged(aura::Window* window,
const void* key,
intptr_t old) OVERRIDE;
virtual void OnWindowDestroying(aura::Window* window) OVERRIDE;
WindowReorderer* reorderer_;
std::set<aura::Window*> windows_;
DISALLOW_COPY_AND_ASSIGN(AssociationObserver);
};
WindowReorderer::AssociationObserver::AssociationObserver(
WindowReorderer* reorderer)
: reorderer_(reorderer) {
}
WindowReorderer::AssociationObserver::~AssociationObserver() {
while (!windows_.empty())
StopObserving(*windows_.begin());
}
void WindowReorderer::AssociationObserver::StartObserving(
aura::Window* window) {
windows_.insert(window);
window->AddObserver(this);
}
void WindowReorderer::AssociationObserver::StopObserving(
aura::Window* window) {
windows_.erase(window);
window->RemoveObserver(this);
}
void WindowReorderer::AssociationObserver::OnWindowPropertyChanged(
aura::Window* window,
const void* key,
intptr_t old) {
if (key == kHostViewKey)
reorderer_->ReorderChildWindows();
}
void WindowReorderer::AssociationObserver::OnWindowDestroying(
aura::Window* window) {
windows_.erase(window);
window->RemoveObserver(this);
}
WindowReorderer::WindowReorderer(aura::Window* parent_window,
View* root_view)
: parent_window_(parent_window),
root_view_(root_view),
association_observer_(new AssociationObserver(this)) {
parent_window_->AddObserver(this);
const std::vector<aura::Window*>& windows = parent_window_->children();
for (size_t i = 0; i < windows.size(); ++i)
association_observer_->StartObserving(windows[i]);
ReorderChildWindows();
}
WindowReorderer::~WindowReorderer() {
if (parent_window_) {
parent_window_->RemoveObserver(this);
}
}
void WindowReorderer::ReorderChildWindows() {
if (!parent_window_)
return;
std::map<View*, aura::Window*> hosted_windows;
GetViewsWithAssociatedWindow(*parent_window_, &hosted_windows);
if (hosted_windows.empty()) {
return;
}
std::vector<View*> view_with_layer_order;
GetOrderOfViewsWithLayers(root_view_, parent_window_->layer(), hosted_windows,
&view_with_layer_order);
for (std::vector<View*>::reverse_iterator it = view_with_layer_order.rbegin();
it != view_with_layer_order.rend(); ++it) {
View* view = *it;
ui::Layer* layer = view->layer();
aura::Window* window = NULL;
std::map<View*, aura::Window*>::iterator hosted_window_it =
hosted_windows.find(view);
if (hosted_window_it != hosted_windows.end()) {
window = hosted_window_it->second;
layer = window->layer();
}
DCHECK(layer);
if (window)
parent_window_->StackChildAtBottom(window);
parent_window_->layer()->StackAtBottom(layer);
}
}
void WindowReorderer::OnWindowAdded(aura::Window* new_window) {
association_observer_->StartObserving(new_window);
ReorderChildWindows();
}
void WindowReorderer::OnWillRemoveWindow(aura::Window* window) {
association_observer_->StopObserving(window);
}
void WindowReorderer::OnWindowDestroying(aura::Window* window) {
parent_window_->RemoveObserver(this);
parent_window_ = NULL;
association_observer_.reset();
}
}