// Copyright 2016 The Chromium Embedded Framework Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be found // in the LICENSE file. #ifndef CEF_LIBCEF_BROWSER_VIEWS_PANEL_IMPL_H_ #define CEF_LIBCEF_BROWSER_VIEWS_PANEL_IMPL_H_ #pragma once #include "include/views/cef_fill_layout.h" #include "include/views/cef_layout.h" #include "include/views/cef_panel.h" #include "include/views/cef_window.h" #include "libcef/browser/views/box_layout_impl.h" #include "libcef/browser/views/fill_layout_impl.h" #include "libcef/browser/views/layout_util.h" #include "libcef/browser/views/view_impl.h" #include "base/logging.h" // Helpers for template boiler-plate. #define CEF_PANEL_IMPL_T CEF_VIEW_IMPL_T #define CEF_PANEL_IMPL_A CEF_VIEW_IMPL_A #define CEF_PANEL_IMPL_D CefPanelImpl<CEF_PANEL_IMPL_A> // Template for implementing CefPanel-derived classes. See comments in // view_impl.h for a usage overview. CEF_PANEL_IMPL_T class CefPanelImpl : public CEF_VIEW_IMPL_D { public: typedef CEF_VIEW_IMPL_D ParentClass; // CefPanel methods. When adding new As*() methods make sure to update // CefViewAdapter::GetFor() in view_adapter.cc. CefRefPtr<CefWindow> AsWindow() override { return nullptr; } CefRefPtr<CefFillLayout> SetToFillLayout() override; CefRefPtr<CefBoxLayout> SetToBoxLayout( const CefBoxLayoutSettings& settings) override; CefRefPtr<CefLayout> GetLayout() override; void Layout() override; void AddChildView(CefRefPtr<CefView> view) override; void AddChildViewAt(CefRefPtr<CefView> view, int index) override; void ReorderChildView(CefRefPtr<CefView> view, int index) override; void RemoveChildView(CefRefPtr<CefView> view) override; void RemoveAllChildViews() override; size_t GetChildViewCount() override; CefRefPtr<CefView> GetChildViewAt(int index) override; // CefView methods: CefRefPtr<CefPanel> AsPanel() override { return this; } // CefViewAdapter methods: void GetDebugInfo(base::DictionaryValue* info, bool include_children) override { ParentClass::GetDebugInfo(info, include_children); if (include_children) { const size_t count = ParentClass::content_view()->child_count(); if (count > 0U) { std::unique_ptr<base::ListValue> children(new base::ListValue()); for (size_t i = 0U; i < count; ++i) { views::View* view = ParentClass::content_view()->child_at(i); CefViewAdapter* adapter = CefViewAdapter::GetFor(view); if (adapter) { std::unique_ptr<base::DictionaryValue> child_info( new base::DictionaryValue()); adapter->GetDebugInfo(child_info.get(), include_children); children->Append(std::move(child_info)); } } info->Set("children", std::move(children)); } } } protected: // Create a new implementation object. // Always call Initialize() after creation. // |delegate| may be nullptr. explicit CefPanelImpl(CefRefPtr<CefViewDelegateClass> delegate) : ParentClass(delegate) { } void Initialize() override { ParentClass::Initialize(); // Create the default layout object. SetToFillLayout(); } }; CEF_PANEL_IMPL_T CefRefPtr<CefFillLayout> CEF_PANEL_IMPL_D::SetToFillLayout() { CEF_REQUIRE_VALID_RETURN(nullptr); return CefFillLayoutImpl::Create(ParentClass::content_view()); } CEF_PANEL_IMPL_T CefRefPtr<CefBoxLayout> CEF_PANEL_IMPL_D::SetToBoxLayout( const CefBoxLayoutSettings& settings) { CEF_REQUIRE_VALID_RETURN(nullptr); return CefBoxLayoutImpl::Create(settings, ParentClass::content_view()); } CEF_PANEL_IMPL_T CefRefPtr<CefLayout> CEF_PANEL_IMPL_D::GetLayout() { CEF_REQUIRE_VALID_RETURN(nullptr); return layout_util::GetFor(ParentClass::content_view()); } CEF_PANEL_IMPL_T void CEF_PANEL_IMPL_D::Layout() { CEF_REQUIRE_VALID_RETURN_VOID(); return ParentClass::root_view()->Layout(); } CEF_PANEL_IMPL_T void CEF_PANEL_IMPL_D::AddChildView( CefRefPtr<CefView> view) { CEF_REQUIRE_VALID_RETURN_VOID(); DCHECK(view.get()); DCHECK(view->IsValid()); DCHECK(!view->IsAttached()); if (!view.get() || !view->IsValid() || view->IsAttached()) return; std::unique_ptr<views::View> view_ptr = view_util::PassOwnership(view); ParentClass::content_view()->AddChildView(view_ptr.release()); } CEF_PANEL_IMPL_T void CEF_PANEL_IMPL_D::AddChildViewAt( CefRefPtr<CefView> view, int index) { CEF_REQUIRE_VALID_RETURN_VOID(); DCHECK(view.get()); DCHECK(view->IsValid()); DCHECK(!view->IsAttached()); DCHECK_GE(index, 0); DCHECK_LE(index, ParentClass::content_view()->child_count()); if (!view.get() || !view->IsValid() || view->IsAttached() || index < 0 || index > ParentClass::content_view()->child_count()) { return; } std::unique_ptr<views::View> view_ptr = view_util::PassOwnership(view); ParentClass::content_view()->AddChildViewAt(view_ptr.release(), index); } CEF_PANEL_IMPL_T void CEF_PANEL_IMPL_D::ReorderChildView( CefRefPtr<CefView> view, int index) { CEF_REQUIRE_VALID_RETURN_VOID(); DCHECK(view.get()); DCHECK(view->IsValid()); DCHECK(view->IsAttached()); if (!view.get() || !view->IsValid() || !view->IsAttached()) return; views::View* view_ptr = view_util::GetFor(view); DCHECK(view_ptr); DCHECK_EQ(view_ptr->parent(), ParentClass::content_view()); if (!view_ptr || view_ptr->parent() != ParentClass::content_view()) return; ParentClass::content_view()->ReorderChildView(view_ptr, index); } CEF_PANEL_IMPL_T void CEF_PANEL_IMPL_D::RemoveChildView( CefRefPtr<CefView> view) { CEF_REQUIRE_VALID_RETURN_VOID(); DCHECK(view.get()); DCHECK(view->IsValid()); DCHECK(view->IsAttached()); if (!view.get() || !view->IsValid() || !view->IsAttached()) return; views::View* view_ptr = view_util::GetFor(view); DCHECK(view_ptr); DCHECK_EQ(view_ptr->parent(), ParentClass::content_view()); if (!view_ptr || view_ptr->parent() != ParentClass::content_view()) return; ParentClass::content_view()->RemoveChildView(view_ptr); view_util::ResumeOwnership(view); } CEF_PANEL_IMPL_T void CEF_PANEL_IMPL_D::RemoveAllChildViews() { CEF_REQUIRE_VALID_RETURN_VOID(); while (ParentClass::content_view()->has_children()) { CefRefPtr<CefView> view = view_util::GetFor(ParentClass::content_view()->child_at(0), false); RemoveChildView(view); } } CEF_PANEL_IMPL_T size_t CEF_PANEL_IMPL_D::GetChildViewCount() { CEF_REQUIRE_VALID_RETURN(0U); return ParentClass::content_view()->child_count(); } CEF_PANEL_IMPL_T CefRefPtr<CefView> CEF_PANEL_IMPL_D::GetChildViewAt( int index) { CEF_REQUIRE_VALID_RETURN(nullptr); DCHECK_GE(index, 0); DCHECK_LT(index, ParentClass::content_view()->child_count()); if (index < 0 || index >= ParentClass::content_view()->child_count()) return nullptr; CefRefPtr<CefView> view = view_util::GetFor(ParentClass::content_view()->child_at(index), false); DCHECK(view); return view; } #endif // CEF_LIBCEF_BROWSER_VIEWS_PANEL_IMPL_H_