// Copyright 2014 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 "mojo/services/view_manager/server_view.h"
#include "mojo/services/view_manager/server_view_delegate.h"
namespace mojo {
namespace service {
ServerView::ServerView(ServerViewDelegate* delegate, const ViewId& id)
: delegate_(delegate), id_(id), parent_(NULL), visible_(true) {
DCHECK(delegate); // Must provide a delegate.
}
ServerView::~ServerView() {
while (!children_.empty())
children_.front()->parent()->Remove(children_.front());
if (parent_)
parent_->Remove(this);
delegate_->OnViewDestroyed(this);
}
void ServerView::Add(ServerView* child) {
// We assume validation checks happened already.
DCHECK(child);
DCHECK(child != this);
DCHECK(!child->Contains(this));
if (child->parent() == this) {
if (children_.size() == 1)
return; // Already in the right position.
Reorder(child, children_.back(), ORDER_DIRECTION_ABOVE);
return;
}
const ServerView* old_parent = child->parent();
child->delegate_->OnWillChangeViewHierarchy(child, this, old_parent);
if (child->parent())
child->parent()->RemoveImpl(child);
child->parent_ = this;
children_.push_back(child);
child->delegate_->OnViewHierarchyChanged(child, this, old_parent);
}
void ServerView::Remove(ServerView* child) {
// We assume validation checks happened else where.
DCHECK(child);
DCHECK(child != this);
DCHECK(child->parent() == this);
child->delegate_->OnWillChangeViewHierarchy(child, NULL, this);
RemoveImpl(child);
child->delegate_->OnViewHierarchyChanged(child, NULL, this);
}
void ServerView::Reorder(ServerView* child,
ServerView* relative,
OrderDirection direction) {
// We assume validation checks happened else where.
DCHECK(child);
DCHECK(child->parent() == this);
DCHECK_GT(children_.size(), 1u);
children_.erase(std::find(children_.begin(), children_.end(), child));
Views::iterator i = std::find(children_.begin(), children_.end(), relative);
if (direction == ORDER_DIRECTION_ABOVE) {
DCHECK(i != children_.end());
children_.insert(++i, child);
} else if (direction == ORDER_DIRECTION_BELOW) {
DCHECK(i != children_.end());
children_.insert(i, child);
}
}
void ServerView::SetBounds(const gfx::Rect& bounds) {
if (bounds_ == bounds)
return;
const gfx::Rect old_bounds = bounds_;
bounds_ = bounds;
delegate_->OnViewBoundsChanged(this, old_bounds, bounds);
}
const ServerView* ServerView::GetRoot() const {
const ServerView* view = this;
while (view && view->parent())
view = view->parent();
return view;
}
std::vector<const ServerView*> ServerView::GetChildren() const {
std::vector<const ServerView*> children;
children.reserve(children_.size());
for (size_t i = 0; i < children_.size(); ++i)
children.push_back(children_[i]);
return children;
}
std::vector<ServerView*> ServerView::GetChildren() {
// TODO(sky): rename to children() and fix return type.
return children_;
}
bool ServerView::Contains(const ServerView* view) const {
for (const ServerView* parent = view; parent; parent = parent->parent_) {
if (parent == this)
return true;
}
return false;
}
void ServerView::SetVisible(bool value) {
if (visible_ == value)
return;
delegate_->OnWillChangeViewVisibility(this);
visible_ = value;
}
bool ServerView::IsDrawn(const ServerView* root) const {
if (!root->visible_)
return false;
const ServerView* view = this;
while (view && view != root && view->visible_)
view = view->parent_;
return view == root;
}
void ServerView::SetSurfaceId(cc::SurfaceId surface_id) {
surface_id_ = surface_id;
delegate_->OnViewSurfaceIdChanged(this);
}
void ServerView::RemoveImpl(ServerView* view) {
view->parent_ = NULL;
children_.erase(std::find(children_.begin(), children_.end(), view));
}
} // namespace service
} // namespace mojo