getAllLayouts method
Retrieves and processes information about the widgets in the current Flutter widget tree and returns a list of layout data structures.
These layout data structures contain information about the position, size, and other properties of the widgets in the tree.
Returns: A list of layout data structures. Each layout data structure is a map.
Implementation
Future<List<Map<String, dynamic>>> getAllLayouts() async {
final List<Map<String, dynamic>> layouts = [];
final List<dynamic> pathList = WidgetPath.entryList();
final int pathCount = pathList.length;
bool hasGestures = false;
if (createRootLayout) {
layouts.add(createRootLayoutControl());
}
for (dynamic entry in pathList) {
final MapEntry<int, dynamic> widgetEntry =
entry as MapEntry<int, dynamic>;
final int key = widgetEntry.key;
final WidgetPath wp = widgetEntry.value as WidgetPath;
final BuildContext? context = wp.context;
if (context == null) {
tlLogger.w('Context null for path (removed): ${wp.path}');
WidgetPath.removePath(key);
continue;
}
final String contextString = context.toString();
if (contextString.startsWith('State') &&
contextString.endsWith('(DEFUNCT)(no widget)')) {
tlLogger
.v("Deleting obsolete path item: $key, context: $contextString");
WidgetPath.removePath(key);
continue;
}
final Widget widget = context.widget;
final Map<String, dynamic> args = wp.parameters;
final String? type = args['type'] ?? '';
final String? subType = args['subType'] ?? '';
wp.usedInLayout = true;
if (type != null && type.compareTo("GestureDetector") == 0) {
hasGestures = true;
} else if (subType != null) {
final String path = wp.widgetPath();
final dynamic getData = args['data'];
Map<String, dynamic>? aStyle;
Map<String, dynamic>? font;
Map<String, dynamic>? image;
String? text;
Map<String, dynamic>? accessibility = args['accessibility'];
bool? maskingEnabled = await getMaskingEnabled();
bool masked = maskingEnabled! &&
(maskIds!.contains(path) || maskIds!.contains(wp.widgetDigest()));
if (subType.compareTo("ImageView") == 0) {
image = await getData(widget);
if (image == null) {
tlLogger.v("Image is empty!");
continue;
}
tlLogger.v('Image is available: ${widget.runtimeType.toString()}');
} else if (subType.compareTo("TextView") == 0) {
text = getData(widget) ?? '';
final TextStyle style = args['style'] ?? TextStyle();
final TextAlign align = args['align'] ?? TextAlign.left;
if (maskingEnabled && !masked && maskValuePatterns != null) {
for (final String pattern in maskValuePatterns!) {
if (text!.contains(RegExp(pattern))) {
masked = true;
tlLogger.v(
'Masking matched content with RE: $pattern, text: $text');
break;
}
}
}
if (masked) {
try {
text = await maskText(text!);
} on TealeafException catch (te) {
tlLogger.v('Unable to mask text. ${te.getMsg}');
}
tlLogger.v(
"Text Layout masked text: $text, Widget: ${widget.runtimeType.toString()}, "
"Digest for MASKING: ${wp.widgetDigest()}");
} else {
tlLogger.v(
"Text Layout text: $text, Widget: ${widget.runtimeType.toString()}");
}
font = {
'family': style.fontFamily,
'size': style.fontSize.toString(),
'bold': (FontWeight.values.indexOf(style.fontWeight!) >
FontWeight.values.indexOf(FontWeight.normal))
.toString(),
'italic': (style.fontStyle == FontStyle.italic).toString()
};
double top = 0, bottom = 0, left = 0, right = 0;
if (wp.parent!.widget is Padding) {
final Padding padding = wp.parent!.widget as Padding;
if (padding.padding is EdgeInsets) {
final EdgeInsets eig = padding.padding as EdgeInsets;
top = eig.top;
bottom = eig.bottom;
left = eig.left;
right = eig.right;
}
}
if (subType.compareTo("TextField") == 0) {
var textField = widget as TextField;
var controller = textField.controller;
controller?.addListener(() { });
}
aStyle = {
'textColor': (style.color!.value & 0xFFFFFF).toString(),
'textAlphaColor': (style.color?.alpha ?? 0).toString(),
'textAlphaBGColor': (style.backgroundColor?.alpha ?? 0).toString(),
'textAlign': align.toString().split('.').last,
'paddingBottom': bottom.toInt().toString(),
'paddingTop': top.toInt().toString(),
'paddingLeft': left.toInt().toString(),
'paddingRight': right.toInt().toString(),
'hidden': (style.color!.opacity == 1.0).toString(),
'colorPrimary': (style.foreground?.color ?? 0).toString(),
'colorPrimaryDark': 0.toString(), // TBD: Dark theme??
'colorAccent': (style.decorationColor?.value ?? 0)
.toString(), // TBD: are this the same??
};
}
final RenderBox box = context.findRenderObject() as RenderBox;
final Offset position = box.localToGlobal(Offset.zero);
if (image != null) {
tlLogger.v("Adding image to layouts....");
}
tlLogger.v(
'--> Layout Flutter -- x: ${position.dx}, y: ${position.dy}, width: ${box.size.width.toInt()}, text: $text');
layouts.add(<String, dynamic>{
'id': path,
'cssId': wp.widgetDigest(),
'idType': (-4).toString(),
'tlType': (image != null)
? 'image'
: (text != null && text.contains('\n') ? 'textArea' : 'label'),
'type': type,
'subType': subType,
'position': <String, String>{
'x': position.dx.toInt().toString(),
'y': position.dy.toInt().toString(),
'width': box.size.width.toInt().toString(),
'height': box.size.height.toInt().toString(),
},
'zIndex': "501",
'currState': <String, dynamic>{
'text': text,
'placeHolder': "", // TBD??
'font': font
},
if (image != null) 'image': image,
if (aStyle != null) 'style': aStyle,
if (accessibility != null) 'accessibility': accessibility,
'originalId': path.replaceAll("/", ""),
'masked': '$masked'
});
}
}
layoutParametersForGestures =
hasGestures ? List.unmodifiable(layouts) : null;
tlLogger.v(
"WigetPath cache size, before: $pathCount, after: ${WidgetPath.size}, # of layouts: ${layouts.length}");
return layouts;
}