Skip to content

Commit

Permalink
Implemented MongolTextAlign
Browse files Browse the repository at this point in the history
  • Loading branch information
suragch committed Mar 13, 2021
1 parent 215adb2 commit 93c3df7
Show file tree
Hide file tree
Showing 21 changed files with 184 additions and 54 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## [1.1.0] - 2021.3.13

- Implemented MongolTextAlign (supports top, center, bottom, justify)
- Known issue: Spaces after words are included in the measurements so MongolTextAlign.bottom aligns the space to the bottom and not the text itself.

## [1.0.0] - 2021.3.6

- Null safe
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,5 @@ This are not part of `mongol` library yet, but you can see an example of how to
- Improve keyboard
- Various other text based widgets
- Support `WidgetSpan`.
- Add missing tests (currently commented out)
- Add missing tests (currently commented out)
- For MongolTextAlign.bottom don't count final space in line height
83 changes: 73 additions & 10 deletions example/lib/demos/text_demo.dart
Original file line number Diff line number Diff line change
@@ -1,22 +1,85 @@
import 'package:flutter/material.dart';
import 'package:mongol/mongol.dart';

class TextDemo extends StatelessWidget {
class TextDemo extends StatefulWidget {
@override
_TextDemoState createState() => _TextDemoState();
}

class _TextDemoState extends State<TextDemo> {
var _alignment = MongolTextAlign.top;

void _updateAlignment(MongolTextAlign alignment) {
setState(() {
_alignment = alignment;
});
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Padding(
padding: const EdgeInsets.all(20.0),
child: Center(
child: Container(
color: Colors.blue[100],
child: MongolText(
text,
style: TextStyle(fontSize: 30),
body: Stack(
children: [
Column(
children: [
Button(
title: 'top',
onPressed: () => _updateAlignment(MongolTextAlign.top),
),
Button(
title: 'center',
onPressed: () => _updateAlignment(MongolTextAlign.center),
),
Button(
title: 'bottom',
onPressed: () => _updateAlignment(MongolTextAlign.bottom),
),
Button(
title: 'justify',
onPressed: () => _updateAlignment(MongolTextAlign.justify),
),
],
),
Padding(
padding: const EdgeInsets.all(20.0),
child: Center(
child: Container(
color: Colors.blue[100],
child: MongolText(
text,
style: TextStyle(fontSize: 30),
textAlign: _alignment,
),
),
),
),
),
],
),
);
}
}

class Button extends StatelessWidget {
const Button({
Key? key,
required this.title,
required this.onPressed,
}) : super(key: key);

final String title;
final VoidCallback onPressed;

@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(4.0),
child: MaterialButton(
minWidth: 100,
elevation: 8,
color: Colors.blue,
child: Text(title),
onPressed: onPressed,
),
);
}
Expand Down
2 changes: 1 addition & 1 deletion example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ packages:
path: ".."
relative: true
source: path
version: "1.0.0"
version: "1.1.0"
path:
dependency: transitive
description:
Expand Down
1 change: 1 addition & 0 deletions lib/mongol.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ library mongol;

export 'package:mongol/src/text/mongol_text.dart';
export 'package:mongol/src/text/mongol_rich_text.dart';
export 'package:mongol/src/base/mongol_text_align.dart';
export 'package:mongol/src/dialog/mongol_alert_dialog.dart';
export 'package:mongol/src/editing/mongol_text_field.dart';
export 'package:mongol/src/editing/alignment.dart';
Expand Down
65 changes: 51 additions & 14 deletions lib/src/base/mongol_paragraph.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import 'dart:ui' as ui;
import 'package:flutter/painting.dart';
import 'package:characters/characters.dart';

import 'mongol_text_align.dart';

/// A paragraph of vertical Mongolian layout text.
///
/// This class is a replacement for the Paragraph class. Since Paragraph hands
Expand All @@ -33,12 +35,14 @@ class MongolParagraph {
this._text,
this._maxLines,
this._ellipsis,
this._textAlign,
);

final String _text;
final List<_TextRun> _runs;
final int? _maxLines;
final _TextRun? _ellipsis;
final MongolTextAlign _textAlign;

double? _width;
double? _height;
Expand Down Expand Up @@ -295,26 +299,55 @@ class MongolParagraph {
final dy = -line.bounds.height;
canvas.translate(0, dy);

// draw each run in the current line
canvas.save();
final startIndex = line.textRunStart;
final endIndex = line.textRunEnd - 1;
// draw line
final isLastLine = i == _lines.length - 1;
for (var j = startIndex; j <= endIndex; j++) {
if (shouldDrawEllipsis && isLastLine && j == endIndex) {
if (maxIntrinsicHeight + _ellipsis!.height < height) {
final run = _runs[j];
run.draw(canvas, Offset(0, 0));
canvas.translate(run.width, 0);
}
_ellipsis!.draw(canvas, Offset(0, 0));
} else {
_drawEachRunInCurrentLine(canvas, line, shouldDrawEllipsis, isLastLine);
}

canvas.restore();
}

void _drawEachRunInCurrentLine(
Canvas canvas, _LineInfo line, bool shouldDrawEllipsis, bool isLastLine) {
canvas.save();

var runSpacing = 0.0;
switch (_textAlign) {
case MongolTextAlign.top:
break;
case MongolTextAlign.center:
final offset = (_height! - line.bounds.width) / 2;
canvas.translate(offset, 0);
break;
case MongolTextAlign.bottom:
final offset = _height! - line.bounds.width;
canvas.translate(offset, 0);
break;
case MongolTextAlign.justify:
if (isLastLine) break;
final extraSpace = _height! - line.bounds.width;
final runsInLine = line.textRunEnd - line.textRunStart;
if (runsInLine <= 1) break;
runSpacing = extraSpace / (runsInLine - 1);
break;
}

final startIndex = line.textRunStart;
final endIndex = line.textRunEnd - 1;
for (var j = startIndex; j <= endIndex; j++) {
if (shouldDrawEllipsis && isLastLine && j == endIndex) {
if (maxIntrinsicHeight + _ellipsis!.height < height) {
final run = _runs[j];
run.draw(canvas, Offset(0, 0));
canvas.translate(run.width, 0);
}
_ellipsis!.draw(canvas, Offset(0, 0));
} else {
final run = _runs[j];
run.draw(canvas, Offset(0, 0));
canvas.translate(run.width, 0);
}
canvas.restore();
canvas.translate(runSpacing, 0);
}

canvas.restore();
Expand Down Expand Up @@ -602,15 +635,18 @@ class MongolParagraphConstraints {
class MongolParagraphBuilder {
MongolParagraphBuilder(
ui.ParagraphStyle style, {
MongolTextAlign textAlign = MongolTextAlign.top,
double textScaleFactor = 1.0,
int? maxLines,
String? ellipsis,
}) : _paragraphStyle = style,
_textAlign = textAlign,
_textScaleFactor = textScaleFactor,
_maxLines = maxLines,
_ellipsis = ellipsis;

ui.ParagraphStyle? _paragraphStyle;
final MongolTextAlign _textAlign;
final double _textScaleFactor;
final int? _maxLines;
final String? _ellipsis;
Expand Down Expand Up @@ -706,6 +742,7 @@ class MongolParagraphBuilder {
_plainText.toString(),
_maxLines,
_ellipsisRun(style),
_textAlign,
);
}

Expand Down
27 changes: 27 additions & 0 deletions lib/src/base/mongol_text_align.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2014 The Flutter Authors.
// Copyright 2021 Suragch.
// All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/// Whether and how to align text vertically.
///
/// This is only used at the MongolTextPainter level and above. Below that the
/// more primitive [TextAlign] enum is used and top is mapped to left and
/// bottom is mapped to right.
enum MongolTextAlign {
/// Align the text on the top edge of the container.
top,

/// Align the text on the bottom edge of the container.
bottom,

/// Align the text in the center of the container.
center,

/// Stretch lines of text that end with a soft line break to fill the height
/// of the container.
///
/// Lines that end with hard line breaks are aligned towards the [top] edge.
justify,
}
25 changes: 3 additions & 22 deletions lib/src/base/mongol_text_painter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import 'dart:ui' as ui show ParagraphStyle;
import 'package:flutter/widgets.dart';
import 'package:mongol/src/base/mongol_paragraph.dart';

import 'mongol_text_align.dart';

// The default font size if none is specified. This should be kept in
// sync with the default values in text_style.dart, as well as the
// defaults set in the engine (eg, LibTxt's text_style.h, paragraph_style.h).
Expand All @@ -31,28 +33,6 @@ class _CaretMetrics {
final double? fullWidth;
}

/// Whether and how to align text vertically.
///
/// This is only used at the MongolTextPainter level and above. Below that the
/// more primitive [TextAlign] enum is used and top is mapped to left and
/// bottom is mapped to right.
enum MongolTextAlign {
/// Align the text on the top edge of the container.
top,

/// Align the text on the bottom edge of the container.
bottom,

/// Align the text in the center of the container.
center,

/// Stretch lines of text that end with a soft line break to fill the height
/// of the container.
///
/// Lines that end with hard line breaks are aligned towards the [top] edge.
justify,
}

/// A convenience method for converting MongolTextAlign to TextAlign
TextAlign mapMongolToHorizontalTextAlign(MongolTextAlign textAlign) {
switch (textAlign) {
Expand Down Expand Up @@ -383,6 +363,7 @@ class MongolTextPainter {
if (_paragraph == null) {
final builder = MongolParagraphBuilder(
_createParagraphStyle(),
textAlign: _textAlign,
textScaleFactor: _textScaleFactor,
maxLines: _maxLines,
ellipsis: _ellipsis,
Expand Down
1 change: 1 addition & 0 deletions lib/src/editing/mongol_editable_text.dart
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import 'package:flutter/rendering.dart';
import 'package:flutter/scheduler.dart' show SchedulerBinding;
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart' hide EditableText, EditableTextState;
import 'package:mongol/src/base/mongol_text_align.dart';

import 'package:mongol/src/editing/mongol_render_editable.dart';
import 'package:mongol/src/base/mongol_text_painter.dart';
Expand Down
2 changes: 1 addition & 1 deletion lib/src/editing/mongol_input_decorator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ import 'package:flutter/material.dart'
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';

import '../base/mongol_text_align.dart';
import '../text/mongol_text.dart';
import '../base/mongol_text_painter.dart';
import 'alignment.dart';
import 'input_border.dart';

Expand Down
1 change: 1 addition & 0 deletions lib/src/editing/mongol_render_editable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'package:mongol/src/base/mongol_text_align.dart';
import 'package:mongol/src/base/mongol_text_painter.dart';

const double _kCaretGap = 1.0; // pixels
Expand Down
1 change: 1 addition & 0 deletions lib/src/editing/mongol_text_field.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import 'package:flutter/material.dart'
MaterialStateProperty,
MaterialStateMouseCursor,
MaterialState;
import 'package:mongol/src/base/mongol_text_align.dart';

import 'alignment.dart';
import 'mongol_editable_text.dart';
Expand Down
1 change: 1 addition & 0 deletions lib/src/text/mongol_render_paragraph.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'dart:ui' as ui show Gradient, Shader;
import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:mongol/src/base/mongol_text_align.dart';

import '../base/mongol_text_painter.dart';

Expand Down
2 changes: 1 addition & 1 deletion lib/src/text/mongol_rich_text.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';

import 'mongol_render_paragraph.dart';
import '../base/mongol_text_painter.dart';
import '../base/mongol_text_align.dart';

/// A string of rich text in vertical Mongolian layout.
///
Expand Down
1 change: 1 addition & 0 deletions lib/src/text/mongol_text.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:flutter/widgets.dart';

import 'mongol_rich_text.dart';
import '../base/mongol_text_painter.dart';
import '../base/mongol_text_align.dart';

/// A run of vertical text with a single style.
///
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: mongol
description: Flutter widget package for displaying and editing vertical Mongolian text.
version: 1.0.0
version: 1.1.0
homepage: https://github.com/suragch/mongol

environment:
Expand Down
Loading

0 comments on commit 93c3df7

Please sign in to comment.