Add Custom Style Attribute builder

pull/350/head
ritheshSalyan 4 years ago
parent d59fbf1d90
commit 7374eee0a2
  1. 2
      .vscode/launch.json
  2. 15
      app/lib/generated_plugin_registrant.dart
  3. 1
      app/windows/flutter/ephemeral/.plugin_symlinks/url_launcher_windows
  4. 5
      lib/src/models/documents/attribute.dart
  5. 3
      lib/src/models/documents/style.dart
  6. 3
      lib/src/widgets/delegate.dart
  7. 15
      lib/src/widgets/editor.dart
  8. 5
      lib/src/widgets/raw_editor.dart
  9. 5
      lib/src/widgets/simple_viewer.dart
  10. 3
      lib/src/widgets/text_block.dart
  11. 17
      lib/src/widgets/text_line.dart

@ -8,7 +8,7 @@
"name": "flutter-quill",
"request": "launch",
"type": "dart",
"program": "app/lib/main.dart"
"program": "example/lib/main.dart"
},
]

@ -0,0 +1,15 @@
//
// Generated file. Do not edit.
//
// ignore_for_file: lines_longer_than_80_chars
import 'package:url_launcher_web/url_launcher_web.dart';
import 'package:flutter_web_plugins/flutter_web_plugins.dart';
// ignore: public_member_api_docs
void registerPlugins(Registrar registrar) {
UrlLauncherPlugin.registerWith(registrar);
registrar.registerMessageHandler();
}

@ -0,0 +1 @@
C:/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-0.0.1+3/

@ -165,9 +165,10 @@ class Attribute<T> {
Map<String, dynamic> toJson() => <String, dynamic>{key: value};
static Attribute fromKeyValue(String key, dynamic value) {
static Attribute? fromKeyValue(String key, dynamic value) {
if (!_registry.containsKey(key)) {
throw ArgumentError.value(key, 'key "$key" not found.');
return null;
// throw ArgumentError.value(key, 'key "$key" not found.');
}
final origin = _registry[key]!;
final attribute = clone(origin, value);

@ -18,7 +18,8 @@ class Style {
final result = attributes.map((key, dynamic value) {
final attr = Attribute.fromKeyValue(key, value);
return MapEntry<String, Attribute>(key, attr);
// ignore: lines_longer_than_80_chars
return MapEntry<String, Attribute>(key, attr??Attribute(key, AttributeScope.INLINE, value));
});
return Style.attr(result);
}

@ -2,6 +2,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import '../../models/documents/attribute.dart';
import '../models/documents/nodes/leaf.dart';
import 'editor.dart';
@ -9,7 +10,7 @@ import 'text_selection.dart';
typedef EmbedBuilder = Widget Function(
BuildContext context, Embed node, bool readOnly);
typedef StyleBuilder = TextStyle Function(Attribute<dynamic> attribute);
abstract class EditorTextSelectionGestureDetectorBuilderDelegate {
GlobalKey<EditorState> getEditableTextKey();

@ -144,7 +144,7 @@ String _standardizeImageUrl(String url) {
}
bool _isMobile() => io.Platform.isAndroid || io.Platform.isIOS;
TextStyle _defaultStyleBuilder(_)=>const TextStyle();
Widget _defaultEmbedBuilder(
BuildContext context, leaf.Embed node, bool readOnly) {
assert(!kIsWeb, 'Please provide EmbedBuilder for Web');
@ -225,8 +225,8 @@ Widget _defaultEmbedBuilder(
}
class QuillEditor extends StatefulWidget {
const QuillEditor(
{required this.controller,
const QuillEditor({
required this.controller,
required this.focusNode,
required this.scrollController,
required this.scrollable,
@ -251,7 +251,9 @@ class QuillEditor extends StatefulWidget {
this.onSingleLongTapStart,
this.onSingleLongTapMoveUpdate,
this.onSingleLongTapEnd,
this.embedBuilder = _defaultEmbedBuilder});
this.embedBuilder = _defaultEmbedBuilder,
this.styleBuilder = _defaultStyleBuilder,
});
factory QuillEditor.basic({
required QuillController controller,
@ -310,6 +312,7 @@ class QuillEditor extends StatefulWidget {
onSingleLongTapEnd;
final EmbedBuilder embedBuilder;
final StyleBuilder styleBuilder;
@override
_QuillEditorState createState() => _QuillEditorState();
@ -413,7 +416,9 @@ class _QuillEditorState extends State<QuillEditor>
widget.keyboardAppearance,
widget.enableInteractiveSelection,
widget.scrollPhysics,
widget.embedBuilder),
widget.embedBuilder,
widget.styleBuilder,
),
);
}

@ -57,6 +57,7 @@ class RawEditor extends StatefulWidget {
this.enableInteractiveSelection,
this.scrollPhysics,
this.embedBuilder,
this.styleBuilder,
) : assert(maxHeight == null || maxHeight > 0, 'maxHeight cannot be null'),
assert(minHeight == null || minHeight >= 0, 'minHeight cannot be null'),
assert(maxHeight == null || minHeight == null || maxHeight >= minHeight,
@ -89,7 +90,7 @@ class RawEditor extends StatefulWidget {
final bool enableInteractiveSelection;
final ScrollPhysics? scrollPhysics;
final EmbedBuilder embedBuilder;
final StyleBuilder styleBuilder;
@override
State<StatefulWidget> createState() => RawEditorState();
}
@ -244,6 +245,7 @@ class RawEditorState extends EditorState
? const EdgeInsets.all(16)
: null,
widget.embedBuilder,
widget.styleBuilder,
_cursorCont,
indentLevelCounts,
_handleCheckboxTap,
@ -262,6 +264,7 @@ class RawEditorState extends EditorState
line: node,
textDirection: _textDirection,
embedBuilder: widget.embedBuilder,
styleBuilder: widget.styleBuilder,
styles: _styles!,
readOnly: widget.readOnly,
);

@ -37,6 +37,7 @@ class QuillSimpleViewer extends StatefulWidget {
this.padding = EdgeInsets.zero,
this.embedBuilder,
Key? key,
this.styleBuilder,
}) : assert(truncate ||
((truncateScale == null) &&
(truncateAlignment == null) &&
@ -54,6 +55,7 @@ class QuillSimpleViewer extends StatefulWidget {
final double scrollBottomInset;
final EdgeInsetsGeometry padding;
final EmbedBuilder? embedBuilder;
final StyleBuilder? styleBuilder;
final bool readOnly;
@override
@ -100,6 +102,7 @@ class _QuillSimpleViewerState extends State<QuillSimpleViewer>
}
EmbedBuilder get embedBuilder => widget.embedBuilder ?? _defaultEmbedBuilder;
StyleBuilder get styleBuilder => widget.styleBuilder ??(a)=>const TextStyle();
Widget _defaultEmbedBuilder(
BuildContext context, leaf.Embed node, bool readOnly) {
@ -218,6 +221,7 @@ class _QuillSimpleViewerState extends State<QuillSimpleViewer>
? const EdgeInsets.all(16)
: null,
embedBuilder,
styleBuilder,
_cursorCont,
indentLevelCounts,
_handleCheckboxTap,
@ -247,6 +251,7 @@ class _QuillSimpleViewerState extends State<QuillSimpleViewer>
line: node,
textDirection: _textDirection,
embedBuilder: embedBuilder,
styleBuilder: styleBuilder,
styles: _styles,
readOnly: widget.readOnly,
);

@ -59,6 +59,7 @@ class EditableTextBlock extends StatelessWidget {
this.hasFocus,
this.contentPadding,
this.embedBuilder,
this.styleBuilder,
this.cursorCont,
this.indentLevelCounts,
this.onCheckboxTap,
@ -76,6 +77,7 @@ class EditableTextBlock extends StatelessWidget {
final bool hasFocus;
final EdgeInsets? contentPadding;
final EmbedBuilder embedBuilder;
final StyleBuilder styleBuilder;
final CursorCont cursorCont;
final Map<int, int> indentLevelCounts;
final Function(int, bool) onCheckboxTap;
@ -123,6 +125,7 @@ class EditableTextBlock extends StatelessWidget {
line: line,
textDirection: textDirection,
embedBuilder: embedBuilder,
styleBuilder: styleBuilder,
styles: styles!,
readOnly: readOnly,
),

@ -24,6 +24,7 @@ class TextLine extends StatelessWidget {
const TextLine({
required this.line,
required this.embedBuilder,
required this.styleBuilder,
required this.styles,
required this.readOnly,
this.textDirection,
@ -35,7 +36,7 @@ class TextLine extends StatelessWidget {
final EmbedBuilder embedBuilder;
final DefaultStyles styles;
final bool readOnly;
final StyleBuilder? styleBuilder;
@override
Widget build(BuildContext context) {
assert(debugCheckHasMediaQuery(context));
@ -150,6 +151,20 @@ class TextLine extends StatelessWidget {
textStyle = textStyle.merge(toMerge);
if (styleBuilder != null) {
line.style.attributes.keys.forEach((key) {
final attribute =
Attribute.fromKeyValue(key, line.style.attributes[key]);
if (attribute != null) {
///
///Unkown Attribute
///
final call = styleBuilder?.call(attribute);
textStyle = textStyle.merge(call);
}
});
}
return textStyle;
}

Loading…
Cancel
Save