Commit 502e56bf authored by Oriol Brufau's avatar Oriol Brufau Committed by Commit Bot

[css-logical] Implement flow-relative values for 'float', 'clear' and 'resize' properties

They are implemented behind the CSSLogical runtime flag.

Intent to Implement:
https://groups.google.com/a/chromium.org/forum/#!msg/blink-dev/48OwfwZrbvI/A1XZFGkzAwAJ

Spec: https://drafts.csswg.org/css-logical/#directional-keywords

BUG=850004

TEST=external/wpt/css/css-logical/logical-values-float-clear.html
TEST=external/wpt/css/css-logical/logical-values-resize.html

The tests still have some failures because sideways writing modes have
not been implemented yet (http://crbug.com/680331).

Change-Id: Ieede2703368a44f3ce9996e917857226795ebaea
Reviewed-on: https://chromium-review.googlesource.com/1163667Reviewed-by: default avatarAnders Ruud <andruud@chromium.org>
Reviewed-by: default avatarYoav Weiss <yoav@yoav.ws>
Commit-Queue: Oriol Brufau <obrufau@igalia.com>
Cr-Commit-Position: refs/heads/master@{#581904}
parent 2abccfab
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
<div id="log"></div> <div id="log"></div>
<script src="./resources/test-box-properties.js"></script> <script type="module">
<script> import {runTests, createBoxPropertyGroup} from "./resources/test-box-properties.js";
runTests(createBoxPropertyGroup("border-*-color", {type: "color"})); runTests(createBoxPropertyGroup("border-*-color", {type: "color"}));
</script> </script>
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
<div id="log"></div> <div id="log"></div>
<script src="./resources/test-box-properties.js"></script> <script type="module">
<script> import {runTests, createBoxPropertyGroup} from "./resources/test-box-properties.js";
runTests(createBoxPropertyGroup("border-*", {type: ["length", "border-style", "color"]})); runTests(createBoxPropertyGroup("border-*", {type: ["length", "border-style", "color"]}));
</script> </script>
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
<div id="log"></div> <div id="log"></div>
<script src="./resources/test-box-properties.js"></script> <script type="module">
<script> import {runTests, createBoxPropertyGroup} from "./resources/test-box-properties.js";
runTests(createBoxPropertyGroup("border-*-style", {type: "border-style"})); runTests(createBoxPropertyGroup("border-*-style", {type: "border-style"}));
</script> </script>
...@@ -9,8 +9,8 @@ ...@@ -9,8 +9,8 @@
<div id="log"></div> <div id="log"></div>
<script src="./resources/test-box-properties.js"></script> <script type="module">
<script> import {runTests, createBoxPropertyGroup} from "./resources/test-box-properties.js";
runTests(createBoxPropertyGroup("border-*-width", { runTests(createBoxPropertyGroup("border-*-width", {
type: "length", type: "length",
prerequisites: {"border-*-style": "solid"}, prerequisites: {"border-*-style": "solid"},
......
...@@ -9,8 +9,8 @@ ...@@ -9,8 +9,8 @@
<div id="log"></div> <div id="log"></div>
<script src="./resources/test-box-properties.js"></script> <script type="module">
<script> import {runTests, createBoxPropertyGroup} from "./resources/test-box-properties.js";
runTests(createBoxPropertyGroup("inset-*", { runTests(createBoxPropertyGroup("inset-*", {
type: "length", type: "length",
prerequisites: {"position": "relative"}, prerequisites: {"position": "relative"},
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
<div id="log"></div> <div id="log"></div>
<script src="./resources/test-box-properties.js"></script> <script type="module">
<script> import {runTests, createBoxPropertyGroup} from "./resources/test-box-properties.js";
runTests(createBoxPropertyGroup("margin-*", {type: "length"})); runTests(createBoxPropertyGroup("margin-*", {type: "length"}));
</script> </script>
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
<div id="log"></div> <div id="log"></div>
<script src="./resources/test-box-properties.js"></script> <script type="module">
<script> import {runTests, createBoxPropertyGroup} from "./resources/test-box-properties.js";
runTests(createBoxPropertyGroup("padding-*", {type: "length"})); runTests(createBoxPropertyGroup("padding-*", {type: "length"}));
</script> </script>
...@@ -9,8 +9,8 @@ ...@@ -9,8 +9,8 @@
<div id="log"></div> <div id="log"></div>
<script src="./resources/test-box-properties.js"></script> <script type="module">
<script> import {runTests, createSizingPropertyGroup} from "./resources/test-box-properties.js";
runTests(createSizingPropertyGroup("")); runTests(createSizingPropertyGroup(""));
runTests(createSizingPropertyGroup("max-")); runTests(createSizingPropertyGroup("max-"));
runTests(createSizingPropertyGroup("min-")); runTests(createSizingPropertyGroup("min-"));
......
<!DOCTYPE html>
<meta charset="utf-8" />
<title>CSS Logical Values: Flow-Relative Values for the 'float' and 'clear' Properties</title>
<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com" />
<link rel="help" href="https://drafts.csswg.org/css-logical/#float-clear">
<meta name="assert" content="This test checks the flow-relative values for 'float' and 'clear' in different writing modes." />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="log"></div>
<script type="module">
import {runTests} from "./resources/test-logical-values.js";
const values = ["inline-start", "inline-end"];
runTests("clear", values);
runTests("float", values);
</script>
This is a testharness.js-based test.
PASS Test that 'resize: block' is supported.
PASS Test 'resize: block' with 'writing-mode: horizontal-tb; direction: ltr; '.
PASS Test 'resize: block' with 'writing-mode: horizontal-tb; direction: rtl; '.
PASS Test 'resize: block' with 'writing-mode: vertical-rl; direction: rtl; '.
FAIL Test 'resize: block' with 'writing-mode: sideways-rl; direction: rtl; '. assert_equals: computed value, resize expected "horizontal" but got "vertical"
PASS Test 'resize: block' with 'writing-mode: vertical-rl; direction: ltr; '.
FAIL Test 'resize: block' with 'writing-mode: sideways-rl; direction: ltr; '. assert_equals: computed value, resize expected "horizontal" but got "vertical"
PASS Test 'resize: block' with 'writing-mode: vertical-lr; direction: rtl; '.
FAIL Test 'resize: block' with 'writing-mode: sideways-lr; direction: ltr; '. assert_equals: computed value, resize expected "horizontal" but got "vertical"
PASS Test 'resize: block' with 'writing-mode: vertical-lr; direction: ltr; '.
FAIL Test 'resize: block' with 'writing-mode: sideways-lr; direction: rtl; '. assert_equals: computed value, resize expected "horizontal" but got "vertical"
PASS Test that 'resize: inline' is supported.
PASS Test 'resize: inline' with 'writing-mode: horizontal-tb; direction: ltr; '.
PASS Test 'resize: inline' with 'writing-mode: horizontal-tb; direction: rtl; '.
PASS Test 'resize: inline' with 'writing-mode: vertical-rl; direction: rtl; '.
FAIL Test 'resize: inline' with 'writing-mode: sideways-rl; direction: rtl; '. assert_equals: computed value, resize expected "vertical" but got "horizontal"
PASS Test 'resize: inline' with 'writing-mode: vertical-rl; direction: ltr; '.
FAIL Test 'resize: inline' with 'writing-mode: sideways-rl; direction: ltr; '. assert_equals: computed value, resize expected "vertical" but got "horizontal"
PASS Test 'resize: inline' with 'writing-mode: vertical-lr; direction: rtl; '.
FAIL Test 'resize: inline' with 'writing-mode: sideways-lr; direction: ltr; '. assert_equals: computed value, resize expected "vertical" but got "horizontal"
PASS Test 'resize: inline' with 'writing-mode: vertical-lr; direction: ltr; '.
FAIL Test 'resize: inline' with 'writing-mode: sideways-lr; direction: rtl; '. assert_equals: computed value, resize expected "vertical" but got "horizontal"
Harness: the test ran to completion.
<!DOCTYPE html>
<meta charset="utf-8" />
<title>CSS Logical Values: Flow-Relative Values for the 'resize' Property</title>
<link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com" />
<link rel="help" href="https://drafts.csswg.org/css-logical/#resize">
<meta name="assert" content="This test checks the flow-relative values for 'resize' in different writing modes." />
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<div id="log"></div>
<script type="module">
import {runTests} from "./resources/test-logical-values.js";
runTests("resize", ["block", "inline"]);
</script>
import {
testElement,
writingModes,
testCSSValues,
testComputedValues,
makeDeclaration
} from "./test-shared.js";
/**
* Tests flow-relative values for a CSS property in different writing modes.
*
* @param {string} property
* The CSS property to be tested.
* @param {string[]} values
* An array with the flow-relative values to be tested.
*/
export function runTests(property, values) {
for (const value of values) {
test(function() {
const {style} = testElement;
style.cssText = "";
style.setProperty(property, value);
testCSSValues("logical values in inline style", style, [[property, value]]);
}, `Test that '${property}: ${value}' is supported.`);
const camelCase = value.replace(/-(.)/g, (match, $1) => $1.toUpperCase());
for (const writingMode of writingModes) {
for (const style of writingMode.styles) {
const writingModeDecl = makeDeclaration(style);
test(function() {
const physicalSide = writingMode[camelCase];
let expected;
if (physicalSide === writingMode.lineLeft) {
expected = "left";
} else if (physicalSide === writingMode.lineRight) {
expected = "right";
} else {
expected = physicalSide;
}
testComputedValues(`computed value`,
`.test { ${writingModeDecl} }`,
[[property, expected]]);
}, `Test '${property}: ${value}' with '${writingModeDecl}'.`);
}
}
}
}
const sheet = document.head.appendChild(document.createElement("style"));
// Specify size for outer <div> to avoid unconstrained-size warnings
// when writing-mode of the inner test <div> is vertical-*
const wrapper = document.body.appendChild(document.createElement("div"));
wrapper.style.cssText = "width:100px; height: 100px;";
export const testElement = wrapper.appendChild(document.createElement("div"));
testElement.id = testElement.className = "test";
// Six unique overall writing modes for property-mapping purposes.
export const writingModes = [
{
styles: [
{"writing-mode": "horizontal-tb", "direction": "ltr"},
],
blockStart: "top", blockEnd: "bottom", inlineStart: "left", inlineEnd: "right",
over: "top", under: "bottom", lineLeft: "left", lineRight: "right",
block: "vertical", inline: "horizontal" },
{
styles: [
{"writing-mode": "horizontal-tb", "direction": "rtl"},
],
blockStart: "top", blockEnd: "bottom", inlineStart: "right", inlineEnd: "left",
over: "top", under: "bottom", lineLeft: "left", lineRight: "right",
block: "vertical", inline: "horizontal" },
{
styles: [
{"writing-mode": "vertical-rl", "direction": "rtl"},
{"writing-mode": "sideways-rl", "direction": "rtl"},
],
blockStart: "right", blockEnd: "left", inlineStart: "bottom", inlineEnd: "top",
over: "right", under: "left", lineLeft: "top", lineRight: "bottom",
block: "horizontal", inline: "vertical" },
{
styles: [
{"writing-mode": "vertical-rl", "direction": "ltr"},
{"writing-mode": "sideways-rl", "direction": "ltr"},
],
blockStart: "right", blockEnd: "left", inlineStart: "top", inlineEnd: "bottom",
over: "right", under: "left", lineLeft: "top", lineRight: "bottom",
block: "horizontal", inline: "vertical" },
{
styles: [
{"writing-mode": "vertical-lr", "direction": "rtl"},
],
blockStart: "left", blockEnd: "right", inlineStart: "bottom", inlineEnd: "top",
over: "right", under: "left", lineLeft: "top", lineRight: "bottom",
block: "horizontal", inline: "vertical" },
{
styles: [
{"writing-mode": "sideways-lr", "direction": "ltr"},
],
blockStart: "left", blockEnd: "right", inlineStart: "bottom", inlineEnd: "top",
over: "left", under: "right", lineLeft: "bottom", lineRight: "top",
block: "horizontal", inline: "vertical" },
{
styles: [
{"writing-mode": "vertical-lr", "direction": "ltr"},
],
blockStart: "left", blockEnd: "right", inlineStart: "top", inlineEnd: "bottom",
over: "right", under: "left", lineLeft: "top", lineRight: "bottom",
block: "horizontal", inline: "vertical" },
{
styles: [
{"writing-mode": "sideways-lr", "direction": "rtl"},
],
blockStart: "left", blockEnd: "right", inlineStart: "top", inlineEnd: "bottom",
over: "left", under: "right", lineLeft: "bottom", lineRight: "top",
block: "horizontal", inline: "vertical" },
];
export function testCSSValues(testName, style, expectedValues) {
for (const [property, value] of expectedValues) {
assert_equals(style.getPropertyValue(property), value, `${testName}, ${property}`);
}
}
export function testComputedValues(testName, rules, expectedValues) {
sheet.textContent = rules;
const cs = getComputedStyle(testElement);
testCSSValues(testName, cs, expectedValues);
sheet.textContent = "";
}
export function makeDeclaration(object = {}, replacement = "*") {
let decl = "";
for (const [property, value] of Object.entries(object)) {
decl += `${property.replace("*", replacement)}: ${value}; `;
}
return decl;
}
...@@ -79,6 +79,30 @@ el.style.setProperty('text-underline-position', 'right under') ...@@ -79,6 +79,30 @@ el.style.setProperty('text-underline-position', 'right under')
el.style.getPropertyValue('text-underline-position') is el.style.getPropertyValue('text-underline-position') is
getComputedStyle(el).getPropertyValue('text-underline-position') is auto getComputedStyle(el).getPropertyValue('text-underline-position') is auto
el.style.setProperty('clear', 'inline-start')
el.style.getPropertyValue('clear') is
getComputedStyle(el).getPropertyValue('clear') is none
el.style.setProperty('clear', 'inline-end')
el.style.getPropertyValue('clear') is
getComputedStyle(el).getPropertyValue('clear') is none
el.style.setProperty('float', 'inline-start')
el.style.getPropertyValue('float') is
getComputedStyle(el).getPropertyValue('float') is none
el.style.setProperty('float', 'inline-end')
el.style.getPropertyValue('float') is
getComputedStyle(el).getPropertyValue('float') is none
el.style.setProperty('resize', 'block')
el.style.getPropertyValue('resize') is
getComputedStyle(el).getPropertyValue('resize') is none
el.style.setProperty('resize', 'inline')
el.style.getPropertyValue('resize') is
getComputedStyle(el).getPropertyValue('resize') is none
PASS successfullyParsed is true PASS successfullyParsed is true
TEST COMPLETE TEST COMPLETE
......
...@@ -79,6 +79,30 @@ el.style.setProperty('text-underline-position', 'right under') ...@@ -79,6 +79,30 @@ el.style.setProperty('text-underline-position', 'right under')
el.style.getPropertyValue('text-underline-position') is under right el.style.getPropertyValue('text-underline-position') is under right
getComputedStyle(el).getPropertyValue('text-underline-position') is under right getComputedStyle(el).getPropertyValue('text-underline-position') is under right
el.style.setProperty('clear', 'inline-start')
el.style.getPropertyValue('clear') is inline-start
getComputedStyle(el).getPropertyValue('clear') is left
el.style.setProperty('clear', 'inline-end')
el.style.getPropertyValue('clear') is inline-end
getComputedStyle(el).getPropertyValue('clear') is right
el.style.setProperty('float', 'inline-start')
el.style.getPropertyValue('float') is inline-start
getComputedStyle(el).getPropertyValue('float') is left
el.style.setProperty('float', 'inline-end')
el.style.getPropertyValue('float') is inline-end
getComputedStyle(el).getPropertyValue('float') is right
el.style.setProperty('resize', 'block')
el.style.getPropertyValue('resize') is block
getComputedStyle(el).getPropertyValue('resize') is vertical
el.style.setProperty('resize', 'inline')
el.style.getPropertyValue('resize') is inline
getComputedStyle(el).getPropertyValue('resize') is horizontal
PASS successfullyParsed is true PASS successfullyParsed is true
TEST COMPLETE TEST COMPLETE
......
...@@ -43,6 +43,13 @@ var properties = [ ...@@ -43,6 +43,13 @@ var properties = [
['text-underline-position', 'right'], ['text-underline-position', 'right'],
['text-underline-position', 'under left'], ['text-underline-position', 'under left'],
['text-underline-position', 'right under'], ['text-underline-position', 'right under'],
['clear', 'inline-start'],
['clear', 'inline-end'],
['float', 'inline-start'],
['float', 'inline-end'],
['resize', 'block'],
['resize', 'inline'],
]; ];
properties.forEach(function(args) { properties.forEach(function(args) {
......
...@@ -1393,6 +1393,7 @@ ...@@ -1393,6 +1393,7 @@
keywords: ["none", "left", "right", "both"], keywords: ["none", "left", "right", "both"],
typedom_types: ["Keyword"], typedom_types: ["Keyword"],
default_value: "none", default_value: "none",
style_builder_custom_functions: ["value"],
}, },
{ {
name: "clip", name: "clip",
...@@ -1691,6 +1692,7 @@ ...@@ -1691,6 +1692,7 @@
default_value: "none", default_value: "none",
name_for_methods: "Floating", name_for_methods: "Floating",
type_name: "EFloat", type_name: "EFloat",
style_builder_custom_functions: ["value"],
}, },
{ {
name: "flood-color", name: "flood-color",
......
...@@ -265,6 +265,8 @@ ...@@ -265,6 +265,8 @@
"-webkit-auto", "-webkit-auto",
"left", "left",
"right", "right",
"inline-start",
"inline-end",
"center", "center",
"justify", "justify",
"-webkit-left", "-webkit-left",
......
...@@ -583,7 +583,10 @@ bool CSSParserFastPaths::IsValidKeywordPropertyAndValue( ...@@ -583,7 +583,10 @@ bool CSSParserFastPaths::IsValidKeywordPropertyAndValue(
return value_id == CSSValueTop || value_id == CSSValueBottom; return value_id == CSSValueTop || value_id == CSSValueBottom;
case CSSPropertyClear: case CSSPropertyClear:
return value_id == CSSValueNone || value_id == CSSValueLeft || return value_id == CSSValueNone || value_id == CSSValueLeft ||
value_id == CSSValueRight || value_id == CSSValueBoth; value_id == CSSValueRight || value_id == CSSValueBoth ||
(RuntimeEnabledFeatures::CSSLogicalEnabled() &&
(value_id == CSSValueInlineStart ||
value_id == CSSValueInlineEnd));
case CSSPropertyClipRule: case CSSPropertyClipRule:
case CSSPropertyFillRule: case CSSPropertyFillRule:
return value_id == CSSValueNonzero || value_id == CSSValueEvenodd; return value_id == CSSValueNonzero || value_id == CSSValueEvenodd;
...@@ -611,6 +614,9 @@ bool CSSParserFastPaths::IsValidKeywordPropertyAndValue( ...@@ -611,6 +614,9 @@ bool CSSParserFastPaths::IsValidKeywordPropertyAndValue(
return value_id == CSSValueShow || value_id == CSSValueHide; return value_id == CSSValueShow || value_id == CSSValueHide;
case CSSPropertyFloat: case CSSPropertyFloat:
return value_id == CSSValueLeft || value_id == CSSValueRight || return value_id == CSSValueLeft || value_id == CSSValueRight ||
(RuntimeEnabledFeatures::CSSLogicalEnabled() &&
(value_id == CSSValueInlineStart ||
value_id == CSSValueInlineEnd)) ||
value_id == CSSValueNone; value_id == CSSValueNone;
case CSSPropertyImageRendering: case CSSPropertyImageRendering:
return value_id == CSSValueAuto || return value_id == CSSValueAuto ||
...@@ -668,6 +674,8 @@ bool CSSParserFastPaths::IsValidKeywordPropertyAndValue( ...@@ -668,6 +674,8 @@ bool CSSParserFastPaths::IsValidKeywordPropertyAndValue(
case CSSPropertyResize: case CSSPropertyResize:
return value_id == CSSValueNone || value_id == CSSValueBoth || return value_id == CSSValueNone || value_id == CSSValueBoth ||
value_id == CSSValueHorizontal || value_id == CSSValueVertical || value_id == CSSValueHorizontal || value_id == CSSValueVertical ||
(RuntimeEnabledFeatures::CSSLogicalEnabled() &&
(value_id == CSSValueBlock || value_id == CSSValueInline)) ||
value_id == CSSValueAuto; value_id == CSSValueAuto;
case CSSPropertyScrollBehavior: case CSSPropertyScrollBehavior:
DCHECK(RuntimeEnabledFeatures::CSSOMSmoothScrollEnabled()); DCHECK(RuntimeEnabledFeatures::CSSOMSmoothScrollEnabled());
......
...@@ -16,5 +16,27 @@ const CSSValue* Clear::CSSValueFromComputedStyleInternal( ...@@ -16,5 +16,27 @@ const CSSValue* Clear::CSSValueFromComputedStyleInternal(
return CSSIdentifierValue::Create(style.Clear()); return CSSIdentifierValue::Create(style.Clear());
} }
void Clear::ApplyValue(StyleResolverState& state, const CSSValue& value) const {
const CSSIdentifierValue& identifier_value = ToCSSIdentifierValue(value);
EClear c;
CSSValueID id = identifier_value.GetValueID();
switch (id) {
case CSSValueInlineStart:
case CSSValueInlineEnd:
if ((id == CSSValueInlineStart) ==
(state.Style()->Direction() == TextDirection::kLtr)) {
c = EClear::kLeft;
} else {
c = EClear::kRight;
}
break;
default:
c = identifier_value.ConvertTo<EClear>();
break;
}
state.Style()->SetClear(c);
}
} // namespace CSSLonghand } // namespace CSSLonghand
} // namespace blink } // namespace blink
...@@ -20,5 +20,27 @@ const CSSValue* Float::CSSValueFromComputedStyleInternal( ...@@ -20,5 +20,27 @@ const CSSValue* Float::CSSValueFromComputedStyleInternal(
return CSSIdentifierValue::Create(style.Floating()); return CSSIdentifierValue::Create(style.Floating());
} }
void Float::ApplyValue(StyleResolverState& state, const CSSValue& value) const {
const CSSIdentifierValue& identifier_value = ToCSSIdentifierValue(value);
EFloat f;
CSSValueID id = identifier_value.GetValueID();
switch (id) {
case CSSValueInlineStart:
case CSSValueInlineEnd:
if ((id == CSSValueInlineStart) ==
(state.Style()->Direction() == TextDirection::kLtr)) {
f = EFloat::kLeft;
} else {
f = EFloat::kRight;
}
break;
default:
f = identifier_value.ConvertTo<EFloat>();
break;
}
state.Style()->SetFloating(f);
}
} // namespace CSSLonghand } // namespace CSSLonghand
} // namespace blink } // namespace blink
...@@ -25,14 +25,27 @@ void Resize::ApplyValue(StyleResolverState& state, ...@@ -25,14 +25,27 @@ void Resize::ApplyValue(StyleResolverState& state,
const CSSIdentifierValue& identifier_value = ToCSSIdentifierValue(value); const CSSIdentifierValue& identifier_value = ToCSSIdentifierValue(value);
EResize r = EResize::kNone; EResize r = EResize::kNone;
if (identifier_value.GetValueID() == CSSValueAuto) { CSSValueID id = identifier_value.GetValueID();
if (Settings* settings = state.GetDocument().GetSettings()) { switch (id) {
r = settings->GetTextAreasAreResizable() ? EResize::kBoth case CSSValueAuto:
: EResize::kNone; if (Settings* settings = state.GetDocument().GetSettings()) {
} r = settings->GetTextAreasAreResizable() ? EResize::kBoth
UseCounter::Count(state.GetDocument(), WebFeature::kCSSResizeAuto); : EResize::kNone;
} else { }
r = identifier_value.ConvertTo<EResize>(); UseCounter::Count(state.GetDocument(), WebFeature::kCSSResizeAuto);
break;
case CSSValueBlock:
case CSSValueInline:
if ((id == CSSValueBlock) ==
IsHorizontalWritingMode(state.Style()->GetWritingMode())) {
r = EResize::kVertical;
} else {
r = EResize::kHorizontal;
}
break;
default:
r = identifier_value.ConvertTo<EResize>();
break;
} }
state.Style()->SetResize(r); state.Style()->SetResize(r);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment