getTypesetContextMenus function
- required EditableTextState editableTextState,
- List<
StyleTypeEnum> ? styleTypes,
Generates a list of ContextMenuButtonItems for text editing actions.
This method builds context menu items that apply various text styling
options to the selected text within a TextField. The styles are
determined by the styleTypes list provided. If no styles are specified,
then all available text styles are included by default.
The method leverages the EditableTextState's textEditingValue to
customize the text styling and updates the state accordingly.
Parameters:
editableTextState: The state of the editable text field. It is used to apply the style changes to the current text.styleTypes: An optional list ofStyleTypeEnumthat specifies which styles should be present in the context menu. If not provided, all styles are included.
Returns:
A list of ContextMenuButtonItem where each item represents a button in the context menu for styling the selected text in the associated text field.
Usage Examples:
// Within a [TextField], using the default constructor
TextField(
contextMenuBuilder: (context, editableTextState) {
return AdaptiveTextSelectionToolbar.buttonItems(
anchors: editableTextState.contextMenuAnchors,
buttonItems: getTypesetContextMenus(editableTextState: editableTextState),
);
},
);
Context Menu Item Actions:
When a context menu item is selected,
it applies a specific style to the text.
For instance, selecting 'Bold' wraps the selected text with boldChar.
Similarly, 'Italic', 'Strikethrough', 'Monospace', 'Underline', and 'Link'
apply their respective styles as per the definitions in TypesetReserved.
// Applying a single style, for example, Bold
var buttonItems = getTypesetContextMenus(
editableTextState: editableTextState,
styleTypes: [StyleTypeEnum.bold],
);
buttonItems.firstWhere((item) => item.label == 'Bold').onPressed();
// This will embolden the selected text.
Implementation
List<ContextMenuButtonItem> getTypesetContextMenus({
required EditableTextState editableTextState,
List<StyleTypeEnum>? styleTypes,
}) {
final buttonItems = <ContextMenuButtonItem>[];
final value = editableTextState.textEditingValue;
final selectionText = value.selection.textInside(value.text);
if (selectionText.isEmpty) {
return buttonItems;
}
// If no specific styles are provided, add all available styles
if (styleTypes == null || styleTypes.isEmpty) {
styleTypes = StyleTypeEnum.values.toList();
}
//if text is already styled, return
for (final char in TypesetReserved.all) {
if (selectionText.startsWith(char) && selectionText.endsWith(char)) {
return buttonItems;
}
}
// Helper to escape reserved chars with broken bar
String escapeReservedChars(String originalText) {
final escapedText = originalText.split('').map((char) {
if (TypesetReserved.all.contains(char)) {
// Prepend the escape literal before the reserved char
return '${TypesetReserved.escapeLiteral}$char';
}
return char;
}).join();
return escapedText;
}
void applyTextStyle(String char) {
final text = escapeReservedChars(value.selection.textInside(value.text));
final newText = value.text.replaceRange(
value.selection.start,
value.selection.end,
'$char$text$char',
);
editableTextState.updateEditingValue(
value.copyWith(
text: newText,
selection: TextSelection.collapsed(
offset: value.selection.start + char.length * 2 + text.length,
),
),
);
}
void applyLinkStyle() {
final text = escapeReservedChars(value.selection.textInside(value.text));
final newText = value.text.replaceRange(
value.selection.start,
value.selection.end,
'${TypesetReserved.linkChar}$text${TypesetReserved.linkSplitChar}https://$text${TypesetReserved.linkChar}',
);
editableTextState.updateEditingValue(
value.copyWith(
text: newText,
selection: TextSelection.collapsed(
offset: value.selection.start +
text.length +
TypesetReserved.linkChar.length * 2 +
TypesetReserved.linkSplitChar.length,
),
),
);
}
// Adding buttons based on the provided style types
if (styleTypes.contains(StyleTypeEnum.bold)) {
buttonItems.add(
ContextMenuButtonItem(
label: StyleTypeEnum.bold.styleTypeEnumValue,
onPressed: () => applyTextStyle(TypesetReserved.boldChar),
),
);
}
if (styleTypes.contains(StyleTypeEnum.italic)) {
buttonItems.add(
ContextMenuButtonItem(
label: StyleTypeEnum.italic.styleTypeEnumValue,
onPressed: () => applyTextStyle(TypesetReserved.italicChar),
),
);
}
if (styleTypes.contains(StyleTypeEnum.strikethrough)) {
buttonItems.add(
ContextMenuButtonItem(
label: StyleTypeEnum.strikethrough.styleTypeEnumValue,
onPressed: () => applyTextStyle(TypesetReserved.strikethroughChar),
),
);
}
if (styleTypes.contains(StyleTypeEnum.monospace)) {
buttonItems.add(
ContextMenuButtonItem(
label: StyleTypeEnum.monospace.styleTypeEnumValue,
onPressed: () => applyTextStyle(TypesetReserved.monospaceChar),
),
);
}
if (styleTypes.contains(StyleTypeEnum.underline)) {
buttonItems.add(
ContextMenuButtonItem(
label: StyleTypeEnum.underline.styleTypeEnumValue,
onPressed: () => applyTextStyle(TypesetReserved.underlineChar),
),
);
}
if (styleTypes.contains(StyleTypeEnum.link)) {
buttonItems.add(
ContextMenuButtonItem(
label: StyleTypeEnum.link.styleTypeEnumValue,
onPressed: applyLinkStyle,
),
);
}
return buttonItems;
}