Skip to content

Commit

Permalink
Merge pull request #1 from kekland/indentation
Browse files Browse the repository at this point in the history
Indentation
  • Loading branch information
kekland authored Jun 9, 2020
2 parents 1c2322c + 2c53abe commit fb6cf5f
Show file tree
Hide file tree
Showing 11 changed files with 174 additions and 28 deletions.
51 changes: 50 additions & 1 deletion packages/notus/lib/src/document/attributes.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// for details. 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:collection/collection.dart';
import 'package:notus/notus.dart';
import 'package:quiver_hashcode/hashcode.dart';

/// Scope of a style attribute, defines context in which an attribute can be
Expand Down Expand Up @@ -74,8 +75,10 @@ class NotusAttribute<T> implements NotusAttributeBuilder<T> {
static final Map<String, NotusAttributeBuilder> _registry = {
NotusAttribute.bold.key: NotusAttribute.bold,
NotusAttribute.italic.key: NotusAttribute.italic,
NotusAttribute.strikethrough.key: NotusAttribute.strikethrough,
NotusAttribute.link.key: NotusAttribute.link,
NotusAttribute.heading.key: NotusAttribute.heading,
NotusAttribute.indentation.key: NotusAttribute.indentation,
NotusAttribute.block.key: NotusAttribute.block,
NotusAttribute.embed.key: NotusAttribute.embed,
};
Expand All @@ -88,6 +91,9 @@ class NotusAttribute<T> implements NotusAttributeBuilder<T> {
/// Italic style attribute.
static const italic = _ItalicAttribute();

// Strikethrough style attribute
static const strikethrough = _StrikethroughAttribute();

/// Link style attribute.
// ignore: const_eval_throws_exception
static const link = LinkAttributeBuilder._();
Expand All @@ -107,6 +113,18 @@ class NotusAttribute<T> implements NotusAttributeBuilder<T> {
/// Alias for [NotusAttribute.heading.level3].
static NotusAttribute<int> get h3 => heading.level3;

/// Indentation attribute
static const indentation = IndentationAttributeBuilder._();

/// Alias for [NotusAttribute.indentation.indent]
static NotusAttribute<int> indent(int level) => indentation.indent(level);

/// Alias for [NotusAttribute.indentation.indentMore]
static NotusAttribute<int> get indentMore => indentation.indentMore;

/// Alias for [NotusAttribute.indentation.indentLess]
static NotusAttribute<int> get indentLess => indentation.indentLess;

/// Block attribute
// ignore: const_eval_throws_exception
static const block = BlockAttributeBuilder._();
Expand Down Expand Up @@ -200,7 +218,8 @@ class NotusStyle {

final Map<String, NotusAttribute> _data;

static NotusStyle fromJson(Map<String, dynamic> data) {
static NotusStyle fromJson(
Map<String, dynamic> data, ) {
if (data == null) return NotusStyle();

final result = data.map((String key, dynamic value) {
Expand Down Expand Up @@ -332,6 +351,12 @@ class _ItalicAttribute extends NotusAttribute<bool> {
const _ItalicAttribute() : super._('i', NotusAttributeScope.inline, true);
}

/// Applies strikethrough style to a text segment.
class _StrikethroughAttribute extends NotusAttribute<bool> {
const _StrikethroughAttribute()
: super._('s', NotusAttributeScope.inline, true);
}

/// Builder for link attribute values.
///
/// There is no need to use this class directly, consider using
Expand Down Expand Up @@ -364,6 +389,30 @@ class HeadingAttributeBuilder extends NotusAttributeBuilder<int> {
NotusAttribute<int> get level3 => NotusAttribute<int>._(key, scope, 3);
}

/// Builder for indentation attribute.
///
/// There is no need to use this class directly, consider using
/// [NotusAttribute.indentation] instead.
class IndentationAttributeBuilder extends NotusAttributeBuilder<int> {
static const _kIndent = 'indent';
static const kIndentMore = -1;
static const kIndentLess = -2;
const IndentationAttributeBuilder._()
: super._(_kIndent, NotusAttributeScope.line);

/// Indent the current line with this level
NotusAttribute<int> indent(int level) =>
NotusAttribute<int>._(key, scope, level);

/// Increment the current indentation level
NotusAttribute<int> get indentMore =>
NotusAttribute<int>._(key, scope, kIndentMore);

/// Decrement the current indentation level
NotusAttribute<int> get indentLess =>
NotusAttribute<int>._(key, scope, kIndentLess);
}

/// Builder for block attribute styles (number/bullet lists, code and quote).
///
/// There is no need to use this class directly, consider using
Expand Down
1 change: 1 addition & 0 deletions packages/zefyr/example/android/gradle.properties
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
org.gradle.jvmargs=-Xmx1536M
android.enableR8=true
11 changes: 6 additions & 5 deletions packages/zefyr/example/ios/Flutter/flutter_export_environment.sh
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
#!/bin/sh
# This is a generated file; do not edit or check into version control.
export "FLUTTER_ROOT=/Users/mountain/Documents/development/flutter"
export "FLUTTER_APPLICATION_PATH=/Users/mountain/Documents/code/zefyr/packages/zefyr/example"
export "FLUTTER_TARGET=lib/main.dart"
export "FLUTTER_ROOT=C:\Sdk\flutter"
export "FLUTTER_APPLICATION_PATH=D:\Projects\zefyr\packages\zefyr\example"
export "FLUTTER_TARGET=lib\main.dart"
export "FLUTTER_BUILD_DIR=build"
export "SYMROOT=${SOURCE_ROOT}/../build/ios"
export "FLUTTER_FRAMEWORK_DIR=/Users/mountain/Documents/development/flutter/bin/cache/artifacts/engine/ios"
export "SYMROOT=${SOURCE_ROOT}/../build\ios"
export "OTHER_LDFLAGS=$(inherited) -framework Flutter"
export "FLUTTER_FRAMEWORK_DIR=C:\Sdk\flutter\bin\cache\artifacts\engine\ios"
export "FLUTTER_BUILD_NAME=1.0.0"
export "FLUTTER_BUILD_NUMBER=1"
9 changes: 9 additions & 0 deletions packages/zefyr/lib/src/widgets/__theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class ZefyrTheme extends InheritedWidget {
class ZefyrThemeData {
final TextStyle boldStyle;
final TextStyle italicStyle;
final TextStyle strikethroughStyle;
final TextStyle linkStyle;
final StyleTheme paragraphTheme;
final HeadingTheme headingTheme;
Expand All @@ -76,12 +77,16 @@ class ZefyrThemeData {
const padding = EdgeInsets.symmetric(vertical: 8.0);
final boldStyle = TextStyle(fontWeight: FontWeight.bold);
final italicStyle = TextStyle(fontStyle: FontStyle.italic);
final strikethroughStyle =
TextStyle(decoration: TextDecoration.lineThrough);

final linkStyle = TextStyle(
color: themeData.accentColor, decoration: TextDecoration.underline);

return ZefyrThemeData(
boldStyle: boldStyle,
italicStyle: italicStyle,
strikethroughStyle: strikethroughStyle,
linkStyle: linkStyle,
paragraphTheme: StyleTheme(textStyle: paragraphStyle, padding: padding),
headingTheme: HeadingTheme.fallback(context),
Expand All @@ -96,6 +101,7 @@ class ZefyrThemeData {
const ZefyrThemeData({
this.boldStyle,
this.italicStyle,
this.strikethroughStyle,
this.linkStyle,
this.paragraphTheme,
this.headingTheme,
Expand All @@ -110,6 +116,7 @@ class ZefyrThemeData {
TextStyle textStyle,
TextStyle boldStyle,
TextStyle italicStyle,
TextStyle strikethroughStyle,
TextStyle linkStyle,
StyleTheme paragraphTheme,
HeadingTheme headingTheme,
Expand All @@ -123,6 +130,7 @@ class ZefyrThemeData {
boldStyle: boldStyle ?? this.boldStyle,
italicStyle: italicStyle ?? this.italicStyle,
linkStyle: linkStyle ?? this.linkStyle,
strikethroughStyle: strikethroughStyle ?? this.strikethroughStyle,
paragraphTheme: paragraphTheme ?? this.paragraphTheme,
headingTheme: headingTheme ?? this.headingTheme,
blockTheme: blockTheme ?? this.blockTheme,
Expand All @@ -137,6 +145,7 @@ class ZefyrThemeData {
return copyWith(
boldStyle: other.boldStyle,
italicStyle: other.italicStyle,
strikethroughStyle: other.strikethroughStyle,
linkStyle: other.linkStyle,
paragraphTheme: other.paragraphTheme,
headingTheme: other.headingTheme,
Expand Down
3 changes: 3 additions & 0 deletions packages/zefyr/lib/src/widgets/common.dart
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ class _ZefyrLineState extends State<ZefyrLine> {
if (style.containsSame(NotusAttribute.italic)) {
result = result.merge(theme.attributeTheme.italic);
}
if (style.containsSame(NotusAttribute.strikethrough)) {
result = result.merge(theme.attributeTheme.strikethrough);
}
if (style.contains(NotusAttribute.link)) {
result = result.merge(theme.attributeTheme.link);
}
Expand Down
27 changes: 23 additions & 4 deletions packages/zefyr/lib/src/widgets/controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'dart:math' as math;

import 'package:flutter/widgets.dart';
import 'package:notus/notus.dart';
import 'package:notus/notus.dart';
import 'package:quill_delta/quill_delta.dart';
import 'package:zefyr/util.dart';

Expand Down Expand Up @@ -168,7 +169,8 @@ class ZefyrController extends ChangeNotifier {

if (length == 0 &&
(attribute.key == NotusAttribute.bold.key ||
attribute.key == NotusAttribute.italic.key)) {
attribute.key == NotusAttribute.italic.key ||
attribute.key == NotusAttribute.strikethrough.key)) {
// Add the attribute to our toggledStyle. It will be used later upon insertion.
_toggledStyles = toggledStyles.put(attribute);
}
Expand All @@ -188,9 +190,26 @@ class ZefyrController extends ChangeNotifier {

/// Formats current selection with [attribute].
void formatSelection(NotusAttribute attribute) {
int index = _selection.start;
int length = _selection.end - index;
formatText(index, length, attribute);
final index = _selection.start;
final length = _selection.end - index;
var attr = attribute;

if (attr.key == NotusAttribute.indentation.key) {
final currentStyle = getSelectionStyle();
var level = currentStyle.get(NotusAttribute.indentation)?.value ?? 0;

if (attr.value == IndentationAttributeBuilder.kIndentLess) {
if (level > 0) level -= 1;
} else if (attr.value == IndentationAttributeBuilder.kIndentMore) {
level += 1;
} else {
level = attr.value;
}

attr = NotusAttribute.indent(level);
}

formatText(index, length, attr);
}

/// Returns style of specified text range.
Expand Down
39 changes: 24 additions & 15 deletions packages/zefyr/lib/src/widgets/editable_text.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:notus/notus.dart';
import 'package:zefyr/src/widgets/indent.dart';

import 'code.dart';
import 'common.dart';
Expand Down Expand Up @@ -238,27 +239,35 @@ class _ZefyrEditableTextState extends State<ZefyrEditableText>

Widget _defaultChildBuilder(BuildContext context, Node node) {
if (node is LineNode) {
Widget child;
if (node.hasEmbed) {
return ZefyrLine(node: node);
child = ZefyrLine(node: node);
} else if (node.style.contains(NotusAttribute.heading)) {
return ZefyrHeading(node: node);
child = ZefyrHeading(node: node);
} else {
child = ZefyrParagraph(node: node);
}
return ZefyrParagraph(node: node);
}

final BlockNode block = node;
final blockStyle = block.style.get(NotusAttribute.block);
if (blockStyle == NotusAttribute.block.code) {
return ZefyrCode(node: block);
} else if (blockStyle == NotusAttribute.block.bulletList) {
return ZefyrList(node: block);
} else if (blockStyle == NotusAttribute.block.numberList) {
return ZefyrList(node: block);
} else if (blockStyle == NotusAttribute.block.quote) {
return ZefyrQuote(node: block);
return ZefyrIndent(
child: child,
node: node,
);
} else {
final BlockNode block = node;
final blockStyle = block.style.get(NotusAttribute.block);

if (blockStyle == NotusAttribute.block.code) {
return ZefyrCode(node: block);
} else if (blockStyle == NotusAttribute.block.bulletList) {
return ZefyrList(node: block);
} else if (blockStyle == NotusAttribute.block.numberList) {
return ZefyrList(node: block);
} else if (blockStyle == NotusAttribute.block.quote) {
return ZefyrQuote(node: block);
}
}

throw UnimplementedError('Block format $blockStyle.');
throw UnimplementedError('This format is not defined.');
}

void _updateSubscriptions([ZefyrEditableText oldWidget]) {
Expand Down
20 changes: 20 additions & 0 deletions packages/zefyr/lib/src/widgets/indent.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import 'package:flutter/widgets.dart';
import 'package:zefyr/zefyr.dart';

class ZefyrIndent extends StatelessWidget {
final LineNode node;
final Widget child;

const ZefyrIndent({Key key, this.node, this.child}) : super(key: key);

@override
Widget build(BuildContext context) {
final indentLevel =
node.style.get<int>(NotusAttribute.indentation)?.value ?? 0;

return Padding(
padding: EdgeInsets.only(left: indentLevel * 16.0),
child: child,
);
}
}
10 changes: 7 additions & 3 deletions packages/zefyr/lib/src/widgets/list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
import 'package:notus/notus.dart';

import 'common.dart';
import 'indent.dart';
import 'paragraph.dart';
import 'theme.dart';

Expand Down Expand Up @@ -86,9 +87,12 @@ class ZefyrListItem extends StatelessWidget {
bullet = Padding(padding: padding, child: bullet);
}

return Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[bullet, Expanded(child: content)],
return ZefyrIndent(
node: node,
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[bullet, Expanded(child: content)],
),
);
}
}
Loading

0 comments on commit fb6cf5f

Please sign in to comment.