Unverified Commit 24bd28f6 authored by Jonah Williams's avatar Jonah Williams Committed by GitHub

[framework] inline AbstractNode into RenderObject (#103832)

parent 586b15cb
...@@ -1566,9 +1566,7 @@ class _ActionButtonParentDataWidget ...@@ -1566,9 +1566,7 @@ class _ActionButtonParentDataWidget
parentData.isPressed = isPressed; parentData.isPressed = isPressed;
// Force a repaint. // Force a repaint.
final AbstractNode? targetParent = renderObject.parent; renderObject.parent?.markNeedsPaint();
if (targetParent is RenderObject)
targetParent.markNeedsPaint();
} }
} }
......
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
import 'dart:math' as math; import 'dart:math' as math;
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart'; import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
...@@ -1086,9 +1085,9 @@ class TableRowInkWell extends InkResponse { ...@@ -1086,9 +1085,9 @@ class TableRowInkWell extends InkResponse {
RectCallback getRectCallback(RenderBox referenceBox) { RectCallback getRectCallback(RenderBox referenceBox) {
return () { return () {
RenderObject cell = referenceBox; RenderObject cell = referenceBox;
AbstractNode? table = cell.parent; RenderObject? table = cell.parent;
final Matrix4 transform = Matrix4.identity(); final Matrix4 transform = Matrix4.identity();
while (table is RenderObject && table is! RenderTable) { while (table != null && table is! RenderTable) {
table.applyPaintTransform(cell, transform); table.applyPaintTransform(cell, transform);
assert(table == cell.parent); assert(table == cell.parent);
cell = table; cell = table;
......
...@@ -683,7 +683,7 @@ abstract class InkFeature { ...@@ -683,7 +683,7 @@ abstract class InkFeature {
RenderObject node = referenceBox; RenderObject node = referenceBox;
while (node != _controller) { while (node != _controller) {
final RenderObject childNode = node; final RenderObject childNode = node;
node = node.parent! as RenderObject; node = node.parent!;
if (!node.paintsChild(childNode)) { if (!node.paintsChild(childNode)) {
// Some node between the reference box and this would skip painting on // Some node between the reference box and this would skip painting on
// the reference box, so bail out early and avoid unnecessary painting. // the reference box, so bail out early and avoid unnecessary painting.
......
...@@ -2145,7 +2145,7 @@ abstract class RenderBox extends RenderObject { ...@@ -2145,7 +2145,7 @@ abstract class RenderBox extends RenderObject {
assert(!_debugDoingBaseline, 'Please see the documentation for computeDistanceToActualBaseline for the required calling conventions of this method.'); assert(!_debugDoingBaseline, 'Please see the documentation for computeDistanceToActualBaseline for the required calling conventions of this method.');
assert(!debugNeedsLayout); assert(!debugNeedsLayout);
assert(() { assert(() {
final RenderObject? parent = this.parent as RenderObject?; final RenderObject? parent = this.parent;
if (owner!.debugDoingLayout) if (owner!.debugDoingLayout)
return (RenderObject.debugActiveLayout == parent) && parent!.debugDoingThisLayout; return (RenderObject.debugActiveLayout == parent) && parent!.debugDoingThisLayout;
if (owner!.debugDoingPaint) if (owner!.debugDoingPaint)
...@@ -2367,7 +2367,7 @@ abstract class RenderBox extends RenderObject { ...@@ -2367,7 +2367,7 @@ abstract class RenderBox extends RenderObject {
@override @override
void markNeedsLayout() { void markNeedsLayout() {
if (_clearCachedData() && parent is RenderObject) { if (_clearCachedData() && parent != null) {
markParentNeedsLayout(); markParentNeedsLayout();
return; return;
} }
......
...@@ -1039,7 +1039,7 @@ class RenderListWheelViewport ...@@ -1039,7 +1039,7 @@ class RenderListWheelViewport
// `child` will be the last RenderObject before the viewport when walking up from `target`. // `child` will be the last RenderObject before the viewport when walking up from `target`.
RenderObject child = target; RenderObject child = target;
while (child.parent != this) while (child.parent != this)
child = child.parent! as RenderObject; child = child.parent!;
final ListWheelParentData parentData = child.parentData! as ListWheelParentData; final ListWheelParentData parentData = child.parentData! as ListWheelParentData;
final double targetOffset = parentData.offset.dy; // the so-called "centerPosition" final double targetOffset = parentData.offset.dy; // the so-called "centerPosition"
......
...@@ -43,7 +43,7 @@ abstract class RenderAbstractViewport extends RenderObject { ...@@ -43,7 +43,7 @@ abstract class RenderAbstractViewport extends RenderObject {
while (object != null) { while (object != null) {
if (object is RenderAbstractViewport) if (object is RenderAbstractViewport)
return object; return object;
object = object.parent as RenderObject?; object = object.parent;
} }
return null; return null;
} }
...@@ -764,7 +764,7 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix ...@@ -764,7 +764,7 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
RenderBox? pivot; RenderBox? pivot;
bool onlySlivers = target is RenderSliver; // ... between viewport and `target` (`target` included). bool onlySlivers = target is RenderSliver; // ... between viewport and `target` (`target` included).
while (child.parent != this) { while (child.parent != this) {
final RenderObject parent = child.parent! as RenderObject; final RenderObject parent = child.parent!;
assert(parent != null, '$target must be a descendant of $this'); assert(parent != null, '$target must be a descendant of $this');
if (child is RenderBox) { if (child is RenderBox) {
pivot = child; pivot = child;
...@@ -1214,7 +1214,7 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix ...@@ -1214,7 +1214,7 @@ abstract class RenderViewportBase<ParentDataClass extends ContainerParentDataMix
} else { } else {
// `descendant` is between leading and trailing edge and hence already // `descendant` is between leading and trailing edge and hence already
// fully shown on screen. No action necessary. // fully shown on screen. No action necessary.
final Matrix4 transform = descendant.getTransformTo(viewport.parent! as RenderObject); final Matrix4 transform = descendant.getTransformTo(viewport.parent);
return MatrixUtils.transformRect(transform, rect ?? descendant.paintBounds); return MatrixUtils.transformRect(transform, rect ?? descendant.paintBounds);
} }
......
...@@ -2169,8 +2169,8 @@ class LayoutId extends ParentDataWidget<MultiChildLayoutParentData> { ...@@ -2169,8 +2169,8 @@ class LayoutId extends ParentDataWidget<MultiChildLayoutParentData> {
final MultiChildLayoutParentData parentData = renderObject.parentData! as MultiChildLayoutParentData; final MultiChildLayoutParentData parentData = renderObject.parentData! as MultiChildLayoutParentData;
if (parentData.id != id) { if (parentData.id != id) {
parentData.id = id; parentData.id = id;
final AbstractNode? targetParent = renderObject.parent; final RenderObject? targetParent = renderObject.parent;
if (targetParent is RenderObject) if (targetParent != null)
targetParent.markNeedsLayout(); targetParent.markNeedsLayout();
} }
} }
...@@ -4132,8 +4132,8 @@ class Positioned extends ParentDataWidget<StackParentData> { ...@@ -4132,8 +4132,8 @@ class Positioned extends ParentDataWidget<StackParentData> {
} }
if (needsLayout) { if (needsLayout) {
final AbstractNode? targetParent = renderObject.parent; final RenderObject? targetParent = renderObject.parent;
if (targetParent is RenderObject) if (targetParent != null)
targetParent.markNeedsLayout(); targetParent.markNeedsLayout();
} }
} }
...@@ -4992,8 +4992,8 @@ class Flexible extends ParentDataWidget<FlexParentData> { ...@@ -4992,8 +4992,8 @@ class Flexible extends ParentDataWidget<FlexParentData> {
} }
if (needsLayout) { if (needsLayout) {
final AbstractNode? targetParent = renderObject.parent; final RenderObject? targetParent = renderObject.parent;
if (targetParent is RenderObject) if (targetParent != null)
targetParent.markNeedsLayout(); targetParent.markNeedsLayout();
} }
} }
......
...@@ -1747,8 +1747,8 @@ class KeepAlive extends ParentDataWidget<KeepAliveParentDataMixin> { ...@@ -1747,8 +1747,8 @@ class KeepAlive extends ParentDataWidget<KeepAliveParentDataMixin> {
final KeepAliveParentDataMixin parentData = renderObject.parentData! as KeepAliveParentDataMixin; final KeepAliveParentDataMixin parentData = renderObject.parentData! as KeepAliveParentDataMixin;
if (parentData.keepAlive != keepAlive) { if (parentData.keepAlive != keepAlive) {
parentData.keepAlive = keepAlive; parentData.keepAlive = keepAlive;
final AbstractNode? targetParent = renderObject.parent; final RenderObject? targetParent = renderObject.parent;
if (targetParent is RenderObject && !keepAlive) if (targetParent != null && !keepAlive)
targetParent.markNeedsLayout(); // No need to redo layout if it became true. targetParent.markNeedsLayout(); // No need to redo layout if it became true.
} }
} }
......
...@@ -433,8 +433,8 @@ class TableCell extends ParentDataWidget<TableCellParentData> { ...@@ -433,8 +433,8 @@ class TableCell extends ParentDataWidget<TableCellParentData> {
final TableCellParentData parentData = renderObject.parentData! as TableCellParentData; final TableCellParentData parentData = renderObject.parentData! as TableCellParentData;
if (parentData.verticalAlignment != verticalAlignment) { if (parentData.verticalAlignment != verticalAlignment) {
parentData.verticalAlignment = verticalAlignment; parentData.verticalAlignment = verticalAlignment;
final AbstractNode? targetParent = renderObject.parent; final RenderObject? targetParent = renderObject.parent;
if (targetParent is RenderObject) if (targetParent != null)
targetParent.markNeedsLayout(); targetParent.markNeedsLayout();
} }
} }
......
...@@ -552,7 +552,7 @@ class _ScreenshotPaintingContext extends PaintingContext { ...@@ -552,7 +552,7 @@ class _ScreenshotPaintingContext extends PaintingContext {
}) { }) {
RenderObject repaintBoundary = renderObject; RenderObject repaintBoundary = renderObject;
while (repaintBoundary != null && !repaintBoundary.isRepaintBoundary) { while (repaintBoundary != null && !repaintBoundary.isRepaintBoundary) {
repaintBoundary = repaintBoundary.parent! as RenderObject; repaintBoundary = repaintBoundary.parent!;
} }
assert(repaintBoundary != null); assert(repaintBoundary != null);
final _ScreenshotData data = _ScreenshotData(target: renderObject); final _ScreenshotData data = _ScreenshotData(target: renderObject);
...@@ -1510,7 +1510,7 @@ mixin WidgetInspectorService { ...@@ -1510,7 +1510,7 @@ mixin WidgetInspectorService {
final List<RenderObject> chain = <RenderObject>[]; final List<RenderObject> chain = <RenderObject>[];
while (renderObject != null) { while (renderObject != null) {
chain.add(renderObject); chain.add(renderObject);
renderObject = renderObject.parent as RenderObject?; renderObject = renderObject.parent;
} }
return _followDiagnosticableChain(chain.reversed.toList()); return _followDiagnosticableChain(chain.reversed.toList());
} }
...@@ -2565,7 +2565,7 @@ class _RenderInspectorOverlay extends RenderBox { ...@@ -2565,7 +2565,7 @@ class _RenderInspectorOverlay extends RenderBox {
context.addLayer(_InspectorOverlayLayer( context.addLayer(_InspectorOverlayLayer(
overlayRect: Rect.fromLTWH(offset.dx, offset.dy, size.width, size.height), overlayRect: Rect.fromLTWH(offset.dx, offset.dy, size.width, size.height),
selection: selection, selection: selection,
rootRenderObject: parent is RenderObject ? parent! as RenderObject : null, rootRenderObject: parent != null ? parent! : null,
)); ));
} }
} }
...@@ -2841,14 +2841,14 @@ class _InspectorOverlayLayer extends Layer { ...@@ -2841,14 +2841,14 @@ class _InspectorOverlayLayer extends Layer {
/// overlays in the same app (i.e. an storyboard), a selected or candidate /// overlays in the same app (i.e. an storyboard), a selected or candidate
/// render object may not belong to this tree. /// render object may not belong to this tree.
bool _isInInspectorRenderObjectTree(RenderObject child) { bool _isInInspectorRenderObjectTree(RenderObject child) {
RenderObject? current = child.parent as RenderObject?; RenderObject? current = child.parent;
while (current != null) { while (current != null) {
// We found the widget inspector render object. // We found the widget inspector render object.
if (current is RenderStack if (current is RenderStack
&& current.lastChild is _RenderInspectorOverlay) { && current.lastChild is _RenderInspectorOverlay) {
return rootRenderObject == current; return rootRenderObject == current;
} }
current = current.parent as RenderObject?; current = current.parent;
} }
return false; return false;
} }
......
...@@ -1819,5 +1819,5 @@ Future<void> testGestureTap(WidgetTester tester, Finder tooltip) async { ...@@ -1819,5 +1819,5 @@ Future<void> testGestureTap(WidgetTester tester, Finder tooltip) async {
SemanticsNode findDebugSemantics(RenderObject object) { SemanticsNode findDebugSemantics(RenderObject object) {
if (object.debugSemantics != null) if (object.debugSemantics != null)
return object.debugSemantics!; return object.debugSemantics!;
return findDebugSemantics(object.parent! as RenderObject); return findDebugSemantics(object.parent!);
} }
...@@ -1359,5 +1359,5 @@ void main() { ...@@ -1359,5 +1359,5 @@ void main() {
SemanticsNode findDebugSemantics(RenderObject object) { SemanticsNode findDebugSemantics(RenderObject object) {
if (object.debugSemantics != null) if (object.debugSemantics != null)
return object.debugSemantics!; return object.debugSemantics!;
return findDebugSemantics(object.parent! as RenderObject); return findDebugSemantics(object.parent!);
} }
...@@ -118,7 +118,7 @@ void main() { ...@@ -118,7 +118,7 @@ void main() {
expect(parentData!.offset.dy, -(viewHeight / 2.0)); expect(parentData!.offset.dy, -(viewHeight / 2.0));
expect(test.calls, 2); // The layout constraints change will clear the cached data. expect(test.calls, 2); // The layout constraints change will clear the cached data.
final RenderObject parent = test.parent! as RenderObject; final RenderObject parent = test.parent!;
expect(parent.debugNeedsLayout, false); expect(parent.debugNeedsLayout, false);
// Do not forget notify parent dirty after the cached data be cleared by `layout()` // Do not forget notify parent dirty after the cached data be cleared by `layout()`
......
...@@ -935,7 +935,7 @@ void main() { ...@@ -935,7 +935,7 @@ void main() {
editable.painter = null; editable.painter = null;
editable.paintCount = 0; editable.paintCount = 0;
final AbstractNode? parent = editable.parent; final RenderObject? parent = editable.parent;
if (parent is RenderConstrainedBox) if (parent is RenderConstrainedBox)
parent.child = null; parent.child = null;
}); });
......
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter_test/flutter_test.dart';
import 'rendering_tester.dart';
class RealRoot extends AbstractNode {
RealRoot(this.child) {
adoptChild(child);
}
final RenderObject child;
@override
void redepthChildren() {
redepthChild(child);
}
@override
void attach(Object owner) {
super.attach(owner);
child.attach(owner as PipelineOwner);
}
@override
void detach() {
super.detach();
child.detach();
}
@override
PipelineOwner? get owner => super.owner as PipelineOwner?;
void layout() {
child.layout(BoxConstraints.tight(const Size(500.0, 500.0)));
}
}
void main() {
TestRenderingFlutterBinding.ensureInitialized();
test('non-RenderObject roots', () {
RenderPositionedBox child;
final RealRoot root = RealRoot(
child = RenderPositionedBox(
child: RenderSizedBox(const Size(100.0, 100.0)),
),
);
root.attach(PipelineOwner());
child.scheduleInitialLayout();
root.layout();
child.markNeedsLayout();
root.layout();
});
}
...@@ -689,9 +689,9 @@ void main() { ...@@ -689,9 +689,9 @@ void main() {
test('Offstage implements paintsChild correctly', () { test('Offstage implements paintsChild correctly', () {
final RenderBox box = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20)); final RenderBox box = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20));
final RenderBox parent = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20)); final RenderProxyBox parent = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20));
final RenderOffstage offstage = RenderOffstage(offstage: false, child: box); final RenderOffstage offstage = RenderOffstage(offstage: false, child: box);
parent.adoptChild(offstage); parent.child = offstage;
expect(offstage.paintsChild(box), true); expect(offstage.paintsChild(box), true);
...@@ -702,9 +702,9 @@ void main() { ...@@ -702,9 +702,9 @@ void main() {
test('Opacity implements paintsChild correctly', () { test('Opacity implements paintsChild correctly', () {
final RenderBox box = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20)); final RenderBox box = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20));
final RenderBox parent = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20)); final RenderProxyBox parent = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20));
final RenderOpacity opacity = RenderOpacity(child: box); final RenderOpacity opacity = RenderOpacity(child: box);
parent.adoptChild(opacity); parent.child = opacity;
expect(opacity.paintsChild(box), true); expect(opacity.paintsChild(box), true);
...@@ -714,11 +714,11 @@ void main() { ...@@ -714,11 +714,11 @@ void main() {
}); });
test('AnimatedOpacity sets paint matrix to zero when alpha == 0', () { test('AnimatedOpacity sets paint matrix to zero when alpha == 0', () {
final RenderBox box = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20)); final RenderProxyBox box = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20));
final RenderBox parent = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20)); final RenderProxyBox parent = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20));
final AnimationController opacityAnimation = AnimationController(value: 1, vsync: FakeTickerProvider()); final AnimationController opacityAnimation = AnimationController(value: 1, vsync: FakeTickerProvider());
final RenderAnimatedOpacity opacity = RenderAnimatedOpacity(opacity: opacityAnimation, child: box); final RenderAnimatedOpacity opacity = RenderAnimatedOpacity(opacity: opacityAnimation, child: box);
parent.adoptChild(opacity); parent.child = opacity;
// Make it listen to the animation. // Make it listen to the animation.
opacity.attach(PipelineOwner()); opacity.attach(PipelineOwner());
...@@ -732,10 +732,10 @@ void main() { ...@@ -732,10 +732,10 @@ void main() {
test('AnimatedOpacity sets paint matrix to zero when alpha == 0 (sliver)', () { test('AnimatedOpacity sets paint matrix to zero when alpha == 0 (sliver)', () {
final RenderSliver sliver = RenderSliverToBoxAdapter(child: RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20))); final RenderSliver sliver = RenderSliverToBoxAdapter(child: RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20)));
final RenderBox parent = RenderConstrainedBox(additionalConstraints: const BoxConstraints.tightFor(width: 20)); final RenderSliverPadding parent = RenderSliverPadding(padding: const EdgeInsets.all(4));
final AnimationController opacityAnimation = AnimationController(value: 1, vsync: FakeTickerProvider()); final AnimationController opacityAnimation = AnimationController(value: 1, vsync: FakeTickerProvider());
final RenderSliverAnimatedOpacity opacity = RenderSliverAnimatedOpacity(opacity: opacityAnimation, sliver: sliver); final RenderSliverAnimatedOpacity opacity = RenderSliverAnimatedOpacity(opacity: opacityAnimation, sliver: sliver);
parent.adoptChild(opacity); parent.child = opacity;
// Make it listen to the animation. // Make it listen to the animation.
opacity.attach(PipelineOwner()); opacity.attach(PipelineOwner());
......
...@@ -2924,8 +2924,8 @@ Future<void> main() async { ...@@ -2924,8 +2924,8 @@ Future<void> main() async {
final ScrollController controller = ScrollController(); final ScrollController controller = ScrollController();
RenderAnimatedOpacity? findRenderAnimatedOpacity() { RenderAnimatedOpacity? findRenderAnimatedOpacity() {
AbstractNode? parent = tester.renderObject(find.byType(Placeholder)); RenderObject? parent = tester.renderObject(find.byType(Placeholder));
while (parent is RenderObject && parent is! RenderAnimatedOpacity) { while (parent != null && parent is! RenderAnimatedOpacity) {
parent = parent.parent; parent = parent.parent;
} }
return parent is RenderAnimatedOpacity ? parent : null; return parent is RenderAnimatedOpacity ? parent : null;
......
...@@ -308,7 +308,7 @@ mixin CommandHandlerFactory { ...@@ -308,7 +308,7 @@ mixin CommandHandlerFactory {
SemanticsNode? node; SemanticsNode? node;
while (renderObject != null && node == null) { while (renderObject != null && node == null) {
node = renderObject.debugSemantics; node = renderObject.debugSemantics;
renderObject = renderObject.parent as RenderObject?; renderObject = renderObject.parent;
} }
if (node == null) if (node == null)
throw StateError('No semantics data found'); throw StateError('No semantics data found');
......
...@@ -23,7 +23,7 @@ Future<ui.Image> captureImage(Element element) { ...@@ -23,7 +23,7 @@ Future<ui.Image> captureImage(Element element) {
assert(element.renderObject != null); assert(element.renderObject != null);
RenderObject renderObject = element.renderObject!; RenderObject renderObject = element.renderObject!;
while (!renderObject.isRepaintBoundary) { while (!renderObject.isRepaintBoundary) {
renderObject = renderObject.parent! as RenderObject; renderObject = renderObject.parent!;
} }
assert(!renderObject.debugNeedsPaint); assert(!renderObject.debugNeedsPaint);
final OffsetLayer layer = renderObject.debugLayer! as OffsetLayer; final OffsetLayer layer = renderObject.debugLayer! as OffsetLayer;
......
...@@ -82,7 +82,7 @@ RenderObject _findRepaintBoundary(Element element) { ...@@ -82,7 +82,7 @@ RenderObject _findRepaintBoundary(Element element) {
assert(element.renderObject != null); assert(element.renderObject != null);
RenderObject renderObject = element.renderObject!; RenderObject renderObject = element.renderObject!;
while (!renderObject.isRepaintBoundary) { while (!renderObject.isRepaintBoundary) {
renderObject = renderObject.parent! as RenderObject; renderObject = renderObject.parent!;
} }
return renderObject; return renderObject;
} }
......
...@@ -1168,7 +1168,7 @@ abstract class WidgetController { ...@@ -1168,7 +1168,7 @@ abstract class WidgetController {
RenderObject? renderObject = element.findRenderObject(); RenderObject? renderObject = element.findRenderObject();
SemanticsNode? result = renderObject?.debugSemantics; SemanticsNode? result = renderObject?.debugSemantics;
while (renderObject != null && (result == null || result.isMergedIntoParent)) { while (renderObject != null && (result == null || result.isMergedIntoParent)) {
renderObject = renderObject.parent as RenderObject?; renderObject = renderObject.parent;
result = renderObject?.debugSemantics; result = renderObject?.debugSemantics;
} }
if (result == null) if (result == null)
......
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