Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- `decoration` property in `DefaultTextBlockStyle` for the `header` attribute to customize headers with borders, background colors, and other styles using `BoxDecoration` [#2429](https://github.com/singerdmx/flutter-quill/pull/2429).

## [11.0.0-dev.19] - 2025-01-10

### Added
Expand Down
22 changes: 21 additions & 1 deletion example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import 'dart:io' as io show Directory, File;

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_quill/flutter_quill.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_quill/flutter_quill.dart';
import 'package:flutter_quill_example/quill_delta_sample.dart';
import 'package:flutter_quill_extensions/flutter_quill_extensions.dart';
import 'package:path/path.dart' as path;
Expand Down Expand Up @@ -146,6 +146,26 @@ class _HomePageState extends State<HomePage> {
config: QuillEditorConfig(
placeholder: 'Start writing your notes...',
padding: const EdgeInsets.all(16),
customStyles: DefaultStyles(
h2: DefaultTextBlockStyle(
DefaultTextStyle.of(context).style.copyWith(
fontSize: 30,
color: DefaultTextStyle.of(context).style.color,
letterSpacing: -0.8,
height: 1.067,
fontWeight: FontWeight.bold,
decoration: TextDecoration.none,
),
HorizontalSpacing(8, 8),
const VerticalSpacing(8, 8),
VerticalSpacing.zero,
BoxDecoration(
border: Border.all(
width: 3,
color: Colors.blue,
),
)),
),
embedBuilders: [
...FlutterQuillEmbeds.editorBuilders(
imageEmbedConfig: QuillEditorImageEmbedConfig(
Expand Down
32 changes: 29 additions & 3 deletions lib/src/editor/raw_editor/raw_editor_state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,8 @@ class QuillRawEditorState extends EditorState
prevNodeOl = attrs[Attribute.list.key] == Attribute.ol;
final nodeTextDirection = getDirectionOfNode(node, _textDirection);
if (node is Line) {
final editableTextLine = _getEditableTextLineFromNode(node, context);
final editableTextLine =
_getEditableTextLineFromNode(node, context, attrs);
result.add(Directionality(
textDirection: nodeTextDirection, child: editableTextLine));
} else if (node is Block) {
Expand Down Expand Up @@ -645,7 +646,7 @@ class QuillRawEditorState extends EditorState
}

EditableTextLine _getEditableTextLineFromNode(
Line node, BuildContext context) {
Line node, BuildContext context, Map<String, Attribute<dynamic>> attrs) {
final textLine = TextLine(
line: node,
textDirection: _textDirection,
Expand Down Expand Up @@ -673,7 +674,8 @@ class QuillRawEditorState extends EditorState
_hasFocus,
MediaQuery.devicePixelRatioOf(context),
_cursorCont,
_styles!.inlineCode!);
_styles!.inlineCode!,
_getDecoration(node, _styles, attrs));
return editableTextLine;
}

Expand Down Expand Up @@ -777,6 +779,30 @@ class QuillRawEditorState extends EditorState
return VerticalSpacing.zero;
}

BoxDecoration? _getDecoration(Node node, DefaultStyles? defaultStyles,
Map<String, Attribute<dynamic>> attrs) {
if (attrs.containsKey(Attribute.header.key)) {
final level = attrs[Attribute.header.key]!.value;
switch (level) {
case 1:
return defaultStyles!.h1!.decoration;
case 2:
return defaultStyles!.h2!.decoration;
case 3:
return defaultStyles!.h3!.decoration;
case 4:
return defaultStyles!.h4!.decoration;
case 5:
return defaultStyles!.h5!.decoration;
case 6:
return defaultStyles!.h6!.decoration;
default:
throw ArgumentError('Invalid level $level');
}
}
return null;
}

void _didChangeTextEditingValueListener() {
_didChangeTextEditingValue(controller.ignoreFocusOnTextChange);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/src/editor/widgets/text/text_block.dart
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ class EditableTextBlock extends StatelessWidget {
MediaQuery.devicePixelRatioOf(context),
cursorCont,
styles!.inlineCode!,
);
null);
final nodeTextDirection = getDirectionOfNode(line, textDirection);
children.add(
Directionality(
Expand Down
25 changes: 23 additions & 2 deletions lib/src/editor/widgets/text/text_line.dart
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,7 @@ class EditableTextLine extends RenderObjectWidget {
this.devicePixelRatio,
this.cursorCont,
this.inlineCodeStyle,
this.decoration,
{super.key});

final Line line;
Expand All @@ -701,6 +702,7 @@ class EditableTextLine extends RenderObjectWidget {
final double devicePixelRatio;
final CursorCont cursorCont;
final InlineCodeStyle inlineCodeStyle;
final BoxDecoration? decoration;

@override
RenderObjectElement createElement() {
Expand All @@ -719,7 +721,8 @@ class EditableTextLine extends RenderObjectWidget {
_getPadding(),
color,
cursorCont,
inlineCodeStyle);
inlineCodeStyle,
decoration);
}

@override
Expand All @@ -735,7 +738,8 @@ class EditableTextLine extends RenderObjectWidget {
..hasFocus = hasFocus
..setDevicePixelRatio(devicePixelRatio)
..setCursorCont(cursorCont)
..setInlineCodeStyle(inlineCodeStyle);
..setInlineCodeStyle(inlineCodeStyle)
..setDecoration(decoration);
}

EdgeInsetsGeometry _getPadding() {
Expand All @@ -762,6 +766,7 @@ class RenderEditableTextLine extends RenderEditableBox {
this.color,
this.cursorCont,
this.inlineCodeStyle,
this.decoration,
);

RenderBox? _leading;
Expand All @@ -780,6 +785,7 @@ class RenderEditableTextLine extends RenderEditableBox {
List<TextBox>? _selectedRects;
late Rect _caretPrototype;
InlineCodeStyle inlineCodeStyle;
BoxDecoration? decoration;
final Map<TextLineSlot, RenderBox> children = <TextLineSlot, RenderBox>{};

Iterable<RenderBox> get _children sync* {
Expand Down Expand Up @@ -895,6 +901,12 @@ class RenderEditableTextLine extends RenderEditableBox {
markNeedsLayout();
}

void setDecoration(BoxDecoration? newDecoration) {
if (decoration == newDecoration) return;
decoration = newDecoration;
markNeedsPaint();
}

// Start selection implementation

bool containsTextSelection() {
Expand Down Expand Up @@ -1289,6 +1301,15 @@ class RenderEditableTextLine extends RenderEditableBox {
}
}

if (decoration != null) {
final paintRect = offset & size;
decoration!.createBoxPainter().paint(
context.canvas,
paintRect.topLeft,
ImageConfiguration(size: paintRect.size),
);
}

if (_body != null) {
final parentData = _body!.parentData as BoxParentData;
final effectiveOffset = offset + parentData.offset;
Expand Down