1 // Copyright 2016 The Chromium Embedded Framework Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be found
3 // in the LICENSE file.
4
5 #ifndef CEF_LIBCEF_BROWSER_VIEWS_PANEL_IMPL_H_
6 #define CEF_LIBCEF_BROWSER_VIEWS_PANEL_IMPL_H_
7 #pragma once
8
9 #include "include/views/cef_fill_layout.h"
10 #include "include/views/cef_layout.h"
11 #include "include/views/cef_panel.h"
12 #include "include/views/cef_window.h"
13
14 #include "libcef/browser/views/box_layout_impl.h"
15 #include "libcef/browser/views/fill_layout_impl.h"
16 #include "libcef/browser/views/layout_util.h"
17 #include "libcef/browser/views/view_impl.h"
18
19 #include "base/logging.h"
20
21 // Helpers for template boiler-plate.
22 #define CEF_PANEL_IMPL_T CEF_VIEW_IMPL_T
23 #define CEF_PANEL_IMPL_A CEF_VIEW_IMPL_A
24 #define CEF_PANEL_IMPL_D CefPanelImpl<CEF_PANEL_IMPL_A>
25
26 // Template for implementing CefPanel-derived classes. See comments in
27 // view_impl.h for a usage overview.
28 CEF_PANEL_IMPL_T class CefPanelImpl : public CEF_VIEW_IMPL_D {
29 public:
30 using ParentClass = CEF_VIEW_IMPL_D;
31
32 // CefPanel methods. When adding new As*() methods make sure to update
33 // CefViewAdapter::GetFor() in view_adapter.cc.
AsWindow()34 CefRefPtr<CefWindow> AsWindow() override { return nullptr; }
35 CefRefPtr<CefFillLayout> SetToFillLayout() override;
36 CefRefPtr<CefBoxLayout> SetToBoxLayout(
37 const CefBoxLayoutSettings& settings) override;
38 CefRefPtr<CefLayout> GetLayout() override;
39 void Layout() override;
40 void AddChildView(CefRefPtr<CefView> view) override;
41 void AddChildViewAt(CefRefPtr<CefView> view, int index) override;
42 void ReorderChildView(CefRefPtr<CefView> view, int index) override;
43 void RemoveChildView(CefRefPtr<CefView> view) override;
44 void RemoveAllChildViews() override;
45 size_t GetChildViewCount() override;
46 CefRefPtr<CefView> GetChildViewAt(int index) override;
47
48 // CefView methods:
AsPanel()49 CefRefPtr<CefPanel> AsPanel() override { return this; }
50
51 // CefViewAdapter methods:
GetDebugInfo(base::DictionaryValue * info,bool include_children)52 void GetDebugInfo(base::DictionaryValue* info,
53 bool include_children) override {
54 ParentClass::GetDebugInfo(info, include_children);
55 if (include_children) {
56 const size_t count = ParentClass::content_view()->children().size();
57 if (count > 0U) {
58 std::unique_ptr<base::ListValue> children(new base::ListValue());
59
60 for (size_t i = 0U; i < count; ++i) {
61 views::View* view = ParentClass::content_view()->children()[i];
62 CefViewAdapter* adapter = CefViewAdapter::GetFor(view);
63 if (adapter) {
64 std::unique_ptr<base::DictionaryValue> child_info(
65 new base::DictionaryValue());
66 adapter->GetDebugInfo(child_info.get(), include_children);
67 children->Append(std::move(child_info));
68 }
69 }
70
71 info->Set("children", std::move(children));
72 }
73 }
74 }
75
76 protected:
77 // Create a new implementation object.
78 // Always call Initialize() after creation.
79 // |delegate| may be nullptr.
CefPanelImpl(CefRefPtr<CefViewDelegateClass> delegate)80 explicit CefPanelImpl(CefRefPtr<CefViewDelegateClass> delegate)
81 : ParentClass(delegate) {}
82
Initialize()83 void Initialize() override {
84 ParentClass::Initialize();
85
86 // Create the default layout object.
87 SetToFillLayout();
88 }
89 };
90
SetToFillLayout()91 CEF_PANEL_IMPL_T CefRefPtr<CefFillLayout> CEF_PANEL_IMPL_D::SetToFillLayout() {
92 CEF_REQUIRE_VALID_RETURN(nullptr);
93 return CefFillLayoutImpl::Create(ParentClass::content_view());
94 }
95
SetToBoxLayout(const CefBoxLayoutSettings & settings)96 CEF_PANEL_IMPL_T CefRefPtr<CefBoxLayout> CEF_PANEL_IMPL_D::SetToBoxLayout(
97 const CefBoxLayoutSettings& settings) {
98 CEF_REQUIRE_VALID_RETURN(nullptr);
99 return CefBoxLayoutImpl::Create(settings, ParentClass::content_view());
100 }
101
GetLayout()102 CEF_PANEL_IMPL_T CefRefPtr<CefLayout> CEF_PANEL_IMPL_D::GetLayout() {
103 CEF_REQUIRE_VALID_RETURN(nullptr);
104 return layout_util::GetFor(ParentClass::content_view());
105 }
106
Layout()107 CEF_PANEL_IMPL_T void CEF_PANEL_IMPL_D::Layout() {
108 CEF_REQUIRE_VALID_RETURN_VOID();
109 return ParentClass::root_view()->Layout();
110 }
111
AddChildView(CefRefPtr<CefView> view)112 CEF_PANEL_IMPL_T void CEF_PANEL_IMPL_D::AddChildView(CefRefPtr<CefView> view) {
113 CEF_REQUIRE_VALID_RETURN_VOID();
114 DCHECK(view.get());
115 DCHECK(view->IsValid());
116 if (!view.get() || !view->IsValid())
117 return;
118
119 auto* view_ptr = view->IsAttached()
120 ? view_util::GetFor(view)
121 : view_util::PassOwnership(view).release();
122 DCHECK(view_ptr);
123 ParentClass::content_view()->AddChildView(view_ptr);
124 }
125
AddChildViewAt(CefRefPtr<CefView> view,int index)126 CEF_PANEL_IMPL_T void CEF_PANEL_IMPL_D::AddChildViewAt(CefRefPtr<CefView> view,
127 int index) {
128 CEF_REQUIRE_VALID_RETURN_VOID();
129 DCHECK(view.get());
130 DCHECK(view->IsValid());
131 DCHECK_GE(index, 0);
132 DCHECK_LE(static_cast<unsigned int>(index),
133 ParentClass::content_view()->children().size());
134 if (!view.get() || !view->IsValid() || index < 0 ||
135 (static_cast<unsigned int>(index) >
136 ParentClass::content_view()->children().size())) {
137 return;
138 }
139
140 auto* view_ptr = view->IsAttached()
141 ? view_util::GetFor(view)
142 : view_util::PassOwnership(view).release();
143 DCHECK(view_ptr);
144 ParentClass::content_view()->AddChildViewAt(view_ptr, index);
145 }
146
ReorderChildView(CefRefPtr<CefView> view,int index)147 CEF_PANEL_IMPL_T void CEF_PANEL_IMPL_D::ReorderChildView(
148 CefRefPtr<CefView> view,
149 int index) {
150 CEF_REQUIRE_VALID_RETURN_VOID();
151 DCHECK(view.get());
152 DCHECK(view->IsValid());
153 DCHECK(view->IsAttached());
154 if (!view.get() || !view->IsValid() || !view->IsAttached())
155 return;
156
157 views::View* view_ptr = view_util::GetFor(view);
158 DCHECK(view_ptr);
159 DCHECK_EQ(view_ptr->parent(), ParentClass::content_view());
160 if (!view_ptr || view_ptr->parent() != ParentClass::content_view())
161 return;
162
163 ParentClass::content_view()->ReorderChildView(view_ptr, index);
164 }
165
RemoveChildView(CefRefPtr<CefView> view)166 CEF_PANEL_IMPL_T void CEF_PANEL_IMPL_D::RemoveChildView(
167 CefRefPtr<CefView> view) {
168 CEF_REQUIRE_VALID_RETURN_VOID();
169 DCHECK(view.get());
170 DCHECK(view->IsValid());
171 DCHECK(view->IsAttached());
172 if (!view.get() || !view->IsValid() || !view->IsAttached())
173 return;
174
175 views::View* view_ptr = view_util::GetFor(view);
176 DCHECK(view_ptr);
177 DCHECK_EQ(view_ptr->parent(), ParentClass::content_view());
178 if (!view_ptr || view_ptr->parent() != ParentClass::content_view())
179 return;
180
181 ParentClass::content_view()->RemoveChildView(view_ptr);
182 view_util::ResumeOwnership(view);
183 }
184
RemoveAllChildViews()185 CEF_PANEL_IMPL_T void CEF_PANEL_IMPL_D::RemoveAllChildViews() {
186 CEF_REQUIRE_VALID_RETURN_VOID();
187 while (!ParentClass::content_view()->children().empty()) {
188 CefRefPtr<CefView> view = view_util::GetFor(
189 ParentClass::content_view()->children().front(), false);
190 RemoveChildView(view);
191 }
192 }
193
GetChildViewCount()194 CEF_PANEL_IMPL_T size_t CEF_PANEL_IMPL_D::GetChildViewCount() {
195 CEF_REQUIRE_VALID_RETURN(0U);
196 return ParentClass::content_view()->children().size();
197 }
198
GetChildViewAt(int index)199 CEF_PANEL_IMPL_T CefRefPtr<CefView> CEF_PANEL_IMPL_D::GetChildViewAt(
200 int index) {
201 CEF_REQUIRE_VALID_RETURN(nullptr);
202 DCHECK_GE(index, 0);
203 DCHECK_LT(static_cast<unsigned int>(index),
204 ParentClass::content_view()->children().size());
205 if (index < 0 || (static_cast<unsigned int>(index) >=
206 ParentClass::content_view()->children().size()))
207 return nullptr;
208
209 CefRefPtr<CefView> view =
210 view_util::GetFor(ParentClass::content_view()->children()[index], false);
211 DCHECK(view);
212 return view;
213 }
214
215 #endif // CEF_LIBCEF_BROWSER_VIEWS_PANEL_IMPL_H_
216