blob: 351ca08255bae26cc208c98f1c23f5a79a19acd8 [file] [log] [blame]
// Copyright 2017 The Fuchsia 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 "peridot/lib/fidl/view_host.h"
#include <lib/fxl/logging.h>
#include <lib/fxl/macros.h>
namespace modular {
struct ViewHost::ViewData {
explicit ViewData(scenic::Session* session) : host_node(session) {}
scenic::EntityNode host_node;
};
ViewHost::ViewHost(scenic::ViewContext view_context)
: V1BaseView(std::move(view_context), "ViewHost"),
container_node_(session()) {
parent_node().AddChild(container_node_);
}
ViewHost::~ViewHost() = default;
void ViewHost::ConnectView(zx::eventpair view_holder_token) {
const uint32_t child_key = next_child_key_++;
auto view_data = std::make_unique<ViewData>(session());
zx::eventpair host_import_token;
view_data->host_node.ExportAsRequest(&host_import_token);
container_node_.AddChild(view_data->host_node);
views_.emplace(child_key, std::move(view_data));
GetViewContainer()->AddChild2(child_key, std::move(view_holder_token),
std::move(host_import_token));
UpdateScene();
}
void ViewHost::ConnectView(
fidl::InterfaceHandle<fuchsia::ui::viewsv1token::ViewOwner> view_owner) {
ConnectView(zx::eventpair(view_owner.TakeChannel().release()));
}
void ViewHost::OnPropertiesChanged(
fuchsia::ui::viewsv1::ViewProperties /*old_properties*/) {
UpdateScene();
}
void ViewHost::OnChildUnavailable(uint32_t child_key) {
FXL_LOG(ERROR) << "View died unexpectedly: child_key=" << child_key;
auto it = views_.find(child_key);
FXL_DCHECK(it != views_.end());
it->second->host_node.Detach();
views_.erase(it);
GetViewContainer()->RemoveChild2(child_key, zx::eventpair());
UpdateScene();
}
void ViewHost::UpdateScene() {
if (!properties().view_layout || views_.empty()) {
return;
}
// Layout all children in a row.
uint32_t index = 0;
uint32_t space = logical_size().width;
uint32_t base = space / views_.size();
uint32_t excess = space % views_.size();
uint32_t offset = 0;
for (auto it = views_.begin(); it != views_.end(); ++it, ++index) {
ViewData* view_data = it->second.get();
// Distribute any excess width among the leading children.
uint32_t extent = base;
if (excess) {
extent++;
excess--;
}
fuchsia::math::RectF layout_bounds;
layout_bounds.x = offset;
layout_bounds.y = 0;
layout_bounds.width = extent;
layout_bounds.height = logical_size().height;
offset += extent;
auto view_properties = fuchsia::ui::viewsv1::ViewProperties::New();
view_properties->view_layout = fuchsia::ui::viewsv1::ViewLayout::New();
view_properties->view_layout->size = fuchsia::math::SizeF();
view_properties->view_layout->size.width = layout_bounds.width;
view_properties->view_layout->size.height = layout_bounds.height;
view_properties->view_layout->inset = fuchsia::math::InsetF();
GetViewContainer()->SetChildProperties(it->first,
std::move(view_properties));
view_data->host_node.SetTranslation(layout_bounds.x, layout_bounds.y, 0u);
}
InvalidateScene();
}
} // namespace modular