add flexlayout

This commit is contained in:
Jeremy Rose
2022-09-14 20:27:39 -07:00
parent 46cbe4feee
commit 2d4f131fe5
7 changed files with 163 additions and 24 deletions

View File

@@ -12,6 +12,7 @@
#include "shell/common/gin_helper/dictionary.h"
#include "shell/common/gin_helper/object_template_builder.h"
#include "shell/common/node_includes.h"
#include "ui/views/layout/flex_layout.h"
#include "ui/views/layout/layout_manager_base.h"
#include <limits>
@@ -55,6 +56,63 @@ struct Converter<views::ProposedLayout> {
}
};
template <>
struct Converter<views::LayoutOrientation> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
views::LayoutOrientation* out) {
std::string orientation = base::ToLowerASCII(gin::V8ToString(isolate, val));
if (orientation == "horizontal") {
*out = views::LayoutOrientation::kHorizontal;
} else if (orientation == "vertical") {
*out = views::LayoutOrientation::kVertical;
} else {
return false;
}
return true;
}
};
template <>
struct Converter<views::LayoutAlignment> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
views::LayoutAlignment* out) {
std::string orientation = base::ToLowerASCII(gin::V8ToString(isolate, val));
if (orientation == "start") {
*out = views::LayoutAlignment::kStart;
} else if (orientation == "center") {
*out = views::LayoutAlignment::kCenter;
} else if (orientation == "end") {
*out = views::LayoutAlignment::kEnd;
} else if (orientation == "stretch") {
*out = views::LayoutAlignment::kStretch;
} else if (orientation == "baseline") {
*out = views::LayoutAlignment::kBaseline;
} else {
return false;
}
return true;
}
};
template <>
struct Converter<views::FlexAllocationOrder> {
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
views::FlexAllocationOrder* out) {
std::string orientation = base::ToLowerASCII(gin::V8ToString(isolate, val));
if (orientation == "normal") {
*out = views::FlexAllocationOrder::kNormal;
} else if (orientation == "reverse") {
*out = views::FlexAllocationOrder::kReverse;
} else {
return false;
}
return true;
}
};
template <>
struct Converter<views::SizeBound> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
@@ -79,29 +137,24 @@ struct Converter<views::SizeBounds> {
namespace electron::api {
using LayoutCallback = base::RepeatingCallback<views::ProposedLayout(
const views::SizeBounds& size_bounds)>;
class JSLayoutManager : public views::LayoutManagerBase {
public:
JSLayoutManager(v8::Isolate* isolate, v8::Local<v8::Object> js_side)
: js_side_(isolate, js_side) {}
JSLayoutManager(LayoutCallback layout_callback)
: layout_callback_(std::move(layout_callback)) {}
~JSLayoutManager() override {}
views::ProposedLayout CalculateProposedLayout(
const views::SizeBounds& size_bounds) const override {
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
v8::HandleScope handle_scope(isolate);
gin_helper::Dictionary dict(isolate, js_side_.Get(isolate));
base::RepeatingCallback<views::ProposedLayout(
const views::SizeBounds& size_bounds)>
calculate_proposed_layout;
if (dict.Get("calculateProposedLayout", &calculate_proposed_layout)) {
views::ProposedLayout pl = calculate_proposed_layout.Run(size_bounds);
return pl;
}
return views::ProposedLayout();
return layout_callback_.Run(size_bounds);
}
private:
v8::Global<v8::Object> js_side_;
LayoutCallback layout_callback_;
};
View::View(views::View* view) : view_(view) {
@@ -132,8 +185,51 @@ void View::SetBounds(const gfx::Rect& bounds) {
view()->SetBoundsRect(bounds);
}
void View::SetLayoutManager(v8::Isolate* isolate, v8::Local<v8::Object> value) {
view_->SetLayoutManager(std::make_unique<JSLayoutManager>(isolate, value));
gfx::Rect View::GetBounds() {
return view()->bounds();
}
void View::SetLayout(v8::Isolate* isolate, v8::Local<v8::Object> value) {
gin_helper::Dictionary dict(isolate, value);
LayoutCallback calculate_proposed_layout;
if (dict.Get("calculateProposedLayout", &calculate_proposed_layout)) {
view_->SetLayoutManager(std::make_unique<JSLayoutManager>(
std::move(calculate_proposed_layout)));
} else {
auto* layout =
view_->SetLayoutManager(std::make_unique<views::FlexLayout>());
views::LayoutOrientation orientation;
if (dict.Get("orientation", &orientation))
layout->SetOrientation(orientation);
views::LayoutAlignment main_axis_alignment;
if (dict.Get("mainAxisAlignment", &main_axis_alignment))
layout->SetMainAxisAlignment(main_axis_alignment);
views::LayoutAlignment cross_axis_alignment;
if (dict.Get("crossAxisAlignment", &cross_axis_alignment))
layout->SetCrossAxisAlignment(cross_axis_alignment);
gfx::Insets interior_margin;
if (dict.Get("interiorMargin", &interior_margin))
layout->SetInteriorMargin(interior_margin);
int minimum_cross_axis_size;
if (dict.Get("minimumCrossAxisSize", &minimum_cross_axis_size))
layout->SetMinimumCrossAxisSize(minimum_cross_axis_size);
bool collapse_margins;
if (dict.Has("collapseMargins") &&
dict.Get("collapseMargins", &collapse_margins))
layout->SetCollapseMargins(collapse_margins);
bool include_host_insets_in_layout;
if (dict.Has("includeHostInsetsInLayout") &&
dict.Get("includeHostInsetsInLayout", &include_host_insets_in_layout))
layout->SetIncludeHostInsetsInLayout(include_host_insets_in_layout);
bool ignore_default_main_axis_margins;
if (dict.Has("ignoreDefaultMainAxisMargins") &&
dict.Get("ignoreDefaultMainAxisMargins",
&ignore_default_main_axis_margins))
layout->SetIgnoreDefaultMainAxisMargins(ignore_default_main_axis_margins);
views::FlexAllocationOrder flex_allocation_order;
if (dict.Get("flexAllocationOrder", &flex_allocation_order))
layout->SetFlexAllocationOrder(flex_allocation_order);
}
}
std::vector<v8::Local<v8::Value>> View::GetChildren() {
@@ -188,7 +284,8 @@ void View::BuildPrototype(v8::Isolate* isolate,
.SetMethod("addChildViewAt", &View::AddChildViewAt)
.SetProperty("children", &View::GetChildren)
.SetMethod("setBounds", &View::SetBounds)
.SetMethod("setLayoutManager", &View::SetLayoutManager);
.SetMethod("getBounds", &View::GetBounds)
.SetMethod("setLayout", &View::SetLayout);
#endif
}

View File

@@ -31,7 +31,8 @@ class View : public gin_helper::Wrappable<View> {
void AddChildViewAt(gin::Handle<View> child, size_t index);
void SetBounds(const gfx::Rect& bounds);
void SetLayoutManager(v8::Isolate* isolate, v8::Local<v8::Object> value);
gfx::Rect GetBounds();
void SetLayout(v8::Isolate* isolate, v8::Local<v8::Object> value);
std::vector<v8::Local<v8::Value>> GetChildren();
#endif

View File

@@ -14,6 +14,8 @@
#include "shell/common/gin_helper/dictionary.h"
#include "shell/common/gin_helper/object_template_builder.h"
#include "shell/common/node_includes.h"
#include "ui/views/layout/flex_layout_types.h"
#include "ui/views/view_class_properties.h"
#if BUILDFLAG(IS_MAC)
#include "shell/browser/ui/cocoa/delayed_native_view_host.h"
@@ -38,6 +40,10 @@ WebContentsView::WebContentsView(v8::Isolate* isolate,
// managed by InspectableWebContents.
set_delete_view(false);
#endif
view()->SetProperty(
views::kFlexBehaviorKey,
views::FlexSpecification(views::MinimumFlexSizeRule::kScaleToMinimum,
views::MaximumFlexSizeRule::kUnbounded));
Observe(web_contents->web_contents());
}

View File

@@ -21,7 +21,6 @@ class RootViewMac : public views::View {
RootViewMac& operator=(const RootViewMac&) = delete;
// views::View:
void Layout() override;
gfx::Size GetMinimumSize() const override;
gfx::Size GetMaximumSize() const override;

View File

@@ -5,22 +5,17 @@
#include "shell/browser/ui/cocoa/root_view_mac.h"
#include "shell/browser/native_window.h"
#include "ui/views/layout/fill_layout.h"
namespace electron {
RootViewMac::RootViewMac(NativeWindow* window) : window_(window) {
set_owned_by_client();
SetLayoutManager(std::make_unique<views::FillLayout>());
}
RootViewMac::~RootViewMac() = default;
void RootViewMac::Layout() {
if (!window_->content_view()) // Not ready yet.
return;
window_->content_view()->SetBoundsRect(gfx::Rect(gfx::Point(), size()));
}
gfx::Size RootViewMac::GetMinimumSize() const {
return window_->GetMinimumSize();
}

View File

@@ -4,9 +4,11 @@
#include "shell/common/gin_converters/gfx_converter.h"
#include "gin/data_object_builder.h"
#include "shell/common/gin_helper/dictionary.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/rect.h"
@@ -107,6 +109,35 @@ bool Converter<gfx::Rect>::FromV8(v8::Isolate* isolate,
return true;
}
v8::Local<v8::Value> Converter<gfx::Insets>::ToV8(v8::Isolate* isolate,
const gfx::Insets& val) {
return gin::DataObjectBuilder(isolate)
.Set("top", val.top())
.Set("left", val.left())
.Set("bottom", val.bottom())
.Set("right", val.right())
.Build();
}
bool Converter<gfx::Insets>::FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
gfx::Insets* out) {
gin::Dictionary dict(isolate);
if (!gin::ConvertFromV8(isolate, val, &dict))
return false;
double top, left, right, bottom;
if (!dict.Get("top", &top))
return false;
if (!dict.Get("left", &left))
return false;
if (!dict.Get("bottom", &bottom))
return false;
if (!dict.Get("right", &right))
return false;
*out = gfx::Insets::TLBR(top, left, bottom, right);
return true;
}
template <>
struct Converter<display::Display::AccelerometerSupport> {
static v8::Local<v8::Value> ToV8(

View File

@@ -16,6 +16,7 @@ class Point;
class PointF;
class Size;
class Rect;
class Insets;
enum class ResizeEdge;
} // namespace gfx
@@ -54,6 +55,15 @@ struct Converter<gfx::Rect> {
gfx::Rect* out);
};
template <>
struct Converter<gfx::Insets> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
const gfx::Insets& val);
static bool FromV8(v8::Isolate* isolate,
v8::Local<v8::Value> val,
gfx::Insets* out);
};
template <>
struct Converter<display::Display> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,