Exemplo n.º 1
0
        public override Widget build(BuildContext context)
        {
            FocusScope.of(context).reparentIfNeeded(this.widget.focusNode);

            DefaultTextStyle defaultTextStyle   = DefaultTextStyle.of(context);
            TextStyle        effectiveTextStyle = this.widget.style;

            if (this.widget.style == null || this.widget.style.inherit)
            {
                effectiveTextStyle = defaultTextStyle.style.merge(this.widget.style);
            }

            Widget child = new WealthyText(
                key: this._richTextKey,
                textAlign: this.widget.textAlign ?? defaultTextStyle.textAlign ?? TextAlign.left,
                softWrap: this.widget.softWrap ?? defaultTextStyle.softWrap,
                overflow: this.widget.overflow ?? defaultTextStyle.overflow,
                textScaleFactor: this.widget.textScaleFactor ?? MediaQuery.textScaleFactorOf(context),
                maxLines: this.widget.maxLines ?? defaultTextStyle.maxLines,
                textSpanList: this.widget.textSpanList,
                style: effectiveTextStyle,
                onSelectionChanged: () => {
                if (this._hasFocus)
                {
                    return;
                }

                FocusScope.of(this.context).requestFocus(this.widget.focusNode);
            },
                selectionColor: this.widget.selectionColor ?? Colors.blue);

            return(new IgnorePointer(
                       ignoring: false,
                       child: new RichTextSelectionGestureDetector(
                           onTapDown: this._handleTapDown,
                           onSingleTapUp: this._handleSingleTapUp,
                           onSingleTapCancel: this._handleSingleTapCancel,
                           onSingleLongTapStart: this._handleLongPress,
                           onDragSelectionStart: this._handleDragSelectionStart,
                           onDragSelectionUpdate: this._handleDragSelectionUpdate,
                           behavior: HitTestBehavior.translucent,
                           child: child
                           )
                       ));
        }
        public override Widget build(BuildContext context)
        {
            WidgetsD.debugCheckHasDirectionality(context);

            switch (Directionality.of(context))
            {
            case TextDirection.ltr:
                keys = widget.children.Keys.ToList();
                break;

            case TextDirection.rtl:
                widget.children.Keys.ToList().Reverse();
                keys = widget.children.Keys.ToList();
                break;
            }
            List <Listenable> results = new List <Listenable>();

            results.AddRange(_highlightControllers.Values);
            results.AddRange(_pressControllers.Values);
            return(new AnimatedBuilder(
                       animation: ListenableUtils.merge(results),
                       builder: (BuildContext context1, Widget child1) => {
                List <Widget> children = new List <Widget>();
                foreach (T currentKey in keys)
                {
                    TextStyle textStyle = DefaultTextStyle.of(context1).style.copyWith(
                        fontWeight: _highlightTween.evaluate(_highlightControllers[currentKey])
                        );

                    Widget child = new DefaultTextStyle(
                        style: textStyle,
                        child:
                        new Opacity(
                            opacity: _pressTween.evaluate(_pressControllers[currentKey]),
                            child: new MetaData(
                                behavior: HitTestBehavior.opaque,
                                child: new Center(child: widget.children[currentKey])
                                )
                            )
                        );

                    children.Add(child);
                }

                int selectedIndex = widget.groupValue.Equals(default) ? 0 : keys.IndexOf(widget.groupValue);
Exemplo n.º 3
0
        public override Widget build(BuildContext context)
        {
            float textScaleFactor = MediaQuery.textScaleFactorOf(context);

            return(new Container(
                       constraints: new BoxConstraints(minHeight: GalleryOptionUtils._kItemHeight *textScaleFactor),
                       padding: GalleryOptionUtils._kItemPadding,
                       alignment: AlignmentDirectional.centerStart,
                       child: new DefaultTextStyle(
                           style: DefaultTextStyle.of(context).style,
                           maxLines: 2,
                           overflow: TextOverflow.fade,
                           child: new IconTheme(
                               data: Theme.of(context).primaryIconTheme,
                               child: this.child
                               )
                           )
                       ));
        }
Exemplo n.º 4
0
        public override Widget build(BuildContext context)
        {
            var defaultTextStyle   = DefaultTextStyle.of(context);
            var effectiveTextStyle = style;

            if (style == null || style.inherit)
            {
                effectiveTextStyle = defaultTextStyle.style.merge(style);
            }

            if (MediaQuery.boldTextOverride(context))
            {
                effectiveTextStyle = effectiveTextStyle.merge(new TextStyle(fontWeight: FontWeight.w700));
            }

            var textSpan = new TextSpan(
                "",
                style: effectiveTextStyle,
                children: _textSpanList
                );

            textSpan.children.ForEach(child =>
            {
                if (child is ImageSpan imageSpan)
                {
                    imageSpan.UpdateImageConfiguration(context);
                }
            });

            var result = new WealthyTextWrapper(
                textAlign: textAlign ?? defaultTextStyle.textAlign ?? TextAlign.left,
                softWrap: softWrap ?? defaultTextStyle.softWrap,
                overflow: overflow ?? defaultTextStyle.overflow,
                textScaleFactor: textScaleFactor ?? MediaQuery.textScaleFactorOf(context),
                maxLines: maxLines ?? defaultTextStyle.maxLines,
                text: textSpan,
                onSelectionChanged: _onSelectionChanged,
                selectionColor: _selectionColor
                );

            return(result);
        }
Exemplo n.º 5
0
        public override Widget build(BuildContext context)
        {
            float?width = this.shrinkToFit ? (float?)null : MediaQuery.of(context).size.width;

            return(new Container(
                       padding: this.padding,
                       color: this.backgroundColor,
                       width: width,
                       child: DefaultTextStyle.merge(
                           style: this.defaultTextStyle ?? DefaultTextStyle.of(context).style,
                           child: (this.useRichText)
                        ? (Widget) new HtmlRichTextParser(
                               shrinkToFit: this.shrinkToFit,
                               onLinkTap: this.onLinkTap,
                               renderNewlines: this.renderNewlines,
                               customEdgeInsets: this.customEdgeInsets,
                               customTextStyle: this.customTextStyle,
                               customTextAlign: this.customTextAlign,
                               html: this.data,
                               onImageError: this.onImageError,
                               linkStyle: this.linkStyle,
                               imageProperties: this.imageProperties,
                               onImageTap: this.onImageTap,
                               showImages: this.showImages
                               )
                        : new HtmlOldParser(
                               width: width,
                               onLinkTap: this.onLinkTap,
                               renderNewlines: this.renderNewlines,
                               customRender: this.customRender,
                               html: this.data,
                               blockSpacing: this.blockSpacing,
                               onImageError: this.onImageError,
                               linkStyle: this.linkStyle,
                               showImages: this.showImages
                               )
                           )
                       ));
        }
Exemplo n.º 6
0
        public override Widget build(BuildContext context)
        {
            base.build(context);
            D.assert(() => { return(_controller._textSpan.visitChildren((InlineSpan span) => span is TextSpan)); },
                     () => "SelectableText only supports TextSpan; Other type of InlineSpan is not allowed");
            D.assert(WidgetsD.debugCheckHasMediaQuery(context));
            D.assert(WidgetsD.debugCheckHasDirectionality(context));
            D.assert(
                !(widget.style != null && widget.style.inherit == false &&
                  (widget.style.fontSize == null || widget.style.textBaseline == null)),
                () => "inherit false style must supply fontSize and textBaseline"
                );

            ThemeData themeData = Theme.of(context);
            FocusNode focusNode = _effectiveFocusNode;

            TextSelectionControls textSelectionControls;
            bool   paintCursorAboveText;
            bool   cursorOpacityAnimates;
            Offset cursorOffset = Offset.zero;
            Color  cursorColor  = widget.cursorColor;
            Radius cursorRadius = widget.cursorRadius;

            switch (themeData.platform)
            {
            case RuntimePlatform.IPhonePlayer:
            case RuntimePlatform.OSXEditor:
            case RuntimePlatform.OSXPlayer:
                forcePressEnabled     = true;
                textSelectionControls = CupertinoTextFieldUtils.cupertinoTextSelectionControls;
                paintCursorAboveText  = true;
                cursorOpacityAnimates = true;
                cursorColor           = cursorColor ?? CupertinoTheme.of(context).primaryColor;
                cursorRadius          = cursorRadius ?? Radius.circular(2.0f);
                cursorOffset          =
                    new Offset(SelectableTextUtils.iOSHorizontalOffset / MediaQuery.of(context).devicePixelRatio,
                               0);
                break;

            default:
                forcePressEnabled     = false;
                textSelectionControls = _MaterialTextSelectionControls.materialTextSelectionControls;
                paintCursorAboveText  = false;
                cursorOpacityAnimates = false;
                cursorColor           = cursorColor ?? themeData.cursorColor;
                break;
            }

            DefaultTextStyle defaultTextStyle   = DefaultTextStyle.of(context);
            TextStyle        effectiveTextStyle = widget.style;

            if (widget.style == null || widget.style.inherit)
            {
                effectiveTextStyle = defaultTextStyle.style.merge(widget.style);
            }
            if (MediaQuery.boldTextOverride(context))
            {
                effectiveTextStyle = effectiveTextStyle.merge(new TextStyle(fontWeight: FontWeight.bold));
            }

            Widget child = new RepaintBoundary(
                child: new EditableText(
                    key: editableTextKey,
                    style: effectiveTextStyle,
                    readOnly: true,
                    textWidthBasis: widget.textWidthBasis ?? defaultTextStyle.textWidthBasis,
                    showSelectionHandles: _showSelectionHandles,
                    showCursor: widget.showCursor,
                    controller: _controller,
                    focusNode: focusNode,
                    strutStyle: widget.strutStyle ?? new StrutStyle(),
                    textAlign: widget.textAlign ?? defaultTextStyle.textAlign ?? TextAlign.start,
                    textDirection: widget.textDirection,
                    textScaleFactor: widget.textScaleFactor,
                    autofocus: widget.autofocus,
                    forceLine: false,
                    toolbarOptions: widget.toolbarOptions,
                    minLines: widget.minLines,
                    maxLines: widget.maxLines ?? defaultTextStyle.maxLines,
                    selectionColor: themeData.textSelectionColor,
                    selectionControls: widget.selectionEnabled ? textSelectionControls : null,
                    onSelectionChanged: _handleSelectionChanged,
                    onSelectionHandleTapped: _handleSelectionHandleTapped,
                    rendererIgnoresPointer: true,
                    cursorWidth: widget.cursorWidth,
                    cursorRadius: cursorRadius,
                    cursorColor: cursorColor,
                    cursorOpacityAnimates: cursorOpacityAnimates,
                    cursorOffset: cursorOffset,
                    paintCursorAboveText: paintCursorAboveText,
                    backgroundCursorColor: CupertinoColors.inactiveGray,
                    enableInteractiveSelection: widget.enableInteractiveSelection,
                    dragStartBehavior: widget.dragStartBehavior,
                    scrollPhysics: widget.scrollPhysics
                    )
                );

            return(_selectionGestureDetectorBuilder.buildGestureDetector(
                       behavior: HitTestBehavior.translucent,
                       child: child
                       ));
        }
Exemplo n.º 7
0
        public override Widget build(BuildContext context)
        {
            List <Widget> _gestureChildren  = new List <Widget>();
            List <Color>  _backgroundColors = new List <Color>();
            int           index             = 0;
            int           selectedIndex     = 0;
            int           pressedIndex      = 0;

            foreach (T currentKey in widget.children.Keys)
            {
                selectedIndex = (widget.groupValue.Equals(currentKey)) ? index : selectedIndex;
                pressedIndex  = (_pressedKey.Equals(currentKey)) ? index : pressedIndex;
                TextStyle textStyle = DefaultTextStyle.of(context).style.copyWith(
                    color: getTextColor(index, currentKey)
                    );
                IconThemeData iconTheme = new IconThemeData(
                    color: getTextColor(index, currentKey)
                    );

                Widget child = new Center(
                    child: widget.children[currentKey]
                    );

                child = new GestureDetector(
                    onTapDown: (TapDownDetails _event) => {
                    _onTapDown(currentKey);
                },
                    onTapCancel: _onTapCancel,
                    onTap: () => {
                    _onTap(currentKey);
                },
                    child: new IconTheme(
                        data: iconTheme,
                        child: new DefaultTextStyle(
                            style: textStyle,
                            child: child
                            )
                        )
                    );

                _backgroundColors.Add(getBackgroundColor(index, currentKey));
                _gestureChildren.Add(child);
                index += 1;
            }

            Widget box = new _SegmentedControlRenderWidget <T>(
                children: _gestureChildren,
                selectedIndex: selectedIndex,
                pressedIndex: pressedIndex,
                backgroundColors: _backgroundColors,
                borderColor: _borderColor
                );

            return(new Padding(
                       padding: widget.padding ?? CupertinoSegmentedControlsUtils._kHorizontalItemPadding,
                       child: new UnconstrainedBox(
                           constrainedAxis: Axis.horizontal,
                           child: box
                           )
                       ));
        }
Exemplo n.º 8
0
        Widget _parseNode(HtmlNode node)
        {
            if (this.customRender != null)
            {
                Widget customWidget = this.customRender(node, this._parseNodeList(node.ChildNodes));
                if (customWidget != null)
                {
                    return(customWidget);
                }
            }

            if (node.NodeType is HtmlNodeType.Element)
            {
                if (!_supportedElements.Contains(node.Name))
                {
                    return(new Container());
                }

                switch (node.Name)
                {
                case "a":
                    return(new GestureDetector(
                               child: DefaultTextStyle.merge(
                                   child: new Wrap(
                                       children: this._parseNodeList(node.ChildNodes)
                                       ),
                                   style: this.linkStyle
                                   ),
                               onTap: () => {
                        if (node.Attributes.Contains("href") && this.onLinkTap != null)
                        {
                            string url = node.Attributes["href"].Value;
                            this.onLinkTap(url);
                        }
                    }));

                case "abbr":
                    return(DefaultTextStyle.merge(
                               child: new Wrap(
                                   children: this._parseNodeList(node.ChildNodes)
                                   ),
                               style: new TextStyle(
                                   decoration: TextDecoration.underline,
                                   decorationStyle: TextDecorationStyle.solid
                                   )
                               ));

                case "acronym":
                    return(DefaultTextStyle.merge(
                               child: new Wrap(
                                   children: this._parseNodeList(node.ChildNodes)
                                   ),
                               style: new TextStyle(
                                   decoration: TextDecoration.underline,
                                   decorationStyle: TextDecorationStyle.solid
                                   )
                               ));

                case "address":
                    return(DefaultTextStyle.merge(
                               child: new Wrap(
                                   children: this._parseNodeList(node.ChildNodes)
                                   ),
                               style: new TextStyle(
                                   fontStyle: FontStyle.italic
                                   )
                               ));

                case "article":
                    return(new Container(
                               width: this.width,
                               child: new Wrap(
                                   crossAxisAlignment: WrapCrossAlignment.center,
                                   children: this._parseNodeList(node.ChildNodes)
                                   )
                               ));

                case "aside":
                    return(new Container(
                               width: this.width,
                               child: new Wrap(
                                   crossAxisAlignment: WrapCrossAlignment.center,
                                   children: this._parseNodeList(node.ChildNodes)
                                   )
                               ));

                case "b":
                    return(DefaultTextStyle.merge(
                               child: new Wrap(
                                   children: this._parseNodeList(node.ChildNodes)
                                   ),
                               style: new TextStyle(
                                   fontWeight: FontWeight.bold
                                   )
                               ));

                case "bdi":
                    return(new Wrap(
                               children: this._parseNodeList(node.ChildNodes)
                               ));

                case "bdo":
                    if (node.Attributes["dir"] != null)
                    {
                        return(new Directionality(
                                   child: new Wrap(
                                       children: this._parseNodeList(node.ChildNodes)
                                       ),
                                   textDirection: node.Attributes["dir"].Value == "rtl"
                                    ? TextDirection.rtl
                                    : TextDirection.ltr
                                   ));
                    }

                    //Direction attribute is required, just render the text normally now.
                    return(new Wrap(
                               children: this._parseNodeList(node.ChildNodes)
                               ));

                case "big":
                    return(DefaultTextStyle.merge(
                               child: new Wrap(
                                   children: this._parseNodeList(node.ChildNodes)
                                   ),
                               style: new TextStyle(
                                   fontSize: 20.0f
                                   )
                               ));

                case "blockquote":
                    return(new Padding(
                               padding:
                               EdgeInsets.fromLTRB(40.0f, this.blockSpacing, 40.0f, this.blockSpacing),
                               child: new Container(
                                   width: this.width,
                                   child: new Wrap(
                                       crossAxisAlignment: WrapCrossAlignment.center,
                                       children: this._parseNodeList(node.ChildNodes)
                                       )
                                   )
                               ));

                case "body":
                    return(new Container(
                               width: this.width,
                               child: new Wrap(
                                   crossAxisAlignment: WrapCrossAlignment.center,
                                   children: this._parseNodeList(node.ChildNodes)
                                   )
                               ));

                case "br":
                    if (this._isNotFirstBreakTag(node))
                    {
                        return(new Container(width: this.width, height: this.blockSpacing));
                    }

                    return(new Container(width: this.width));

                case "caption":
                    return(new Container(
                               width: this.width,
                               child: new Wrap(
                                   crossAxisAlignment: WrapCrossAlignment.center,
                                   alignment: WrapAlignment.center,
                                   children: this._parseNodeList(node.ChildNodes)
                                   )
                               ));

                case "center":
                    return(new Container(
                               width: this.width,
                               child: new Wrap(
                                   crossAxisAlignment: WrapCrossAlignment.center,
                                   children: this._parseNodeList(node.ChildNodes),
                                   alignment: WrapAlignment.center
                                   )));

                case "cite":
                    return(DefaultTextStyle.merge(
                               child: new Wrap(
                                   children: this._parseNodeList(node.ChildNodes)
                                   ),
                               style: new TextStyle(
                                   fontStyle: FontStyle.italic
                                   )
                               ));

                case "code":
                    return(DefaultTextStyle.merge(
                               child: new Wrap(
                                   children: this._parseNodeList(node.ChildNodes)
                                   ),
                               style: new TextStyle(
                                   fontFamily: "monospace"
                                   )
                               ));

                case "data":
                    return(new Wrap(
                               children: this._parseNodeList(node.ChildNodes)
                               ));

                case "dd":
                    return(new Padding(
                               padding: EdgeInsets.only(left: 40.0f),
                               child: new Container(
                                   width: this.width,
                                   child: new Wrap(
                                       crossAxisAlignment: WrapCrossAlignment.center,
                                       children: this._parseNodeList(node.ChildNodes)
                                       )
                                   )));

                case "del":
                    return(DefaultTextStyle.merge(
                               child: new Wrap(
                                   children: this._parseNodeList(node.ChildNodes)
                                   ),
                               style: new TextStyle(
                                   decoration: TextDecoration.lineThrough
                                   )
                               ));

                case "dfn":
                    return(DefaultTextStyle.merge(
                               child: new Wrap(
                                   children: this._parseNodeList(node.ChildNodes)
                                   ),
                               style: new TextStyle(
                                   fontStyle: FontStyle.italic
                                   )
                               ));

                case "div":
                    return(new Container(
                               width: this.width,
                               child: new Wrap(
                                   crossAxisAlignment: WrapCrossAlignment.center,
                                   children: this._parseNodeList(node.ChildNodes)
                                   )
                               ));

                case "dl":
                    return(new Padding(
                               padding: EdgeInsets.only(top: this.blockSpacing, bottom: this.blockSpacing),
                               child: new Column(
                                   children: this._parseNodeList(node.ChildNodes),
                                   crossAxisAlignment: CrossAxisAlignment.start
                                   )));

                case "dt":
                    return(new Wrap(
                               children: this._parseNodeList(node.ChildNodes)
                               ));

                case "em":
                    return(DefaultTextStyle.merge(
                               child: new Wrap(
                                   children: this._parseNodeList(node.ChildNodes)
                                   ),
                               style: new TextStyle(
                                   fontStyle: FontStyle.italic
                                   )
                               ));

                case "figcaption":
                    return(new Wrap(
                               children: this._parseNodeList(node.ChildNodes)
                               ));

                case "figure":
                    return(new Padding(
                               padding:
                               EdgeInsets.fromLTRB(40.0f, this.blockSpacing, 40.0f, this.blockSpacing),
                               child: new Column(
                                   children: this._parseNodeList(node.ChildNodes),
                                   crossAxisAlignment: CrossAxisAlignment.center
                                   )));

                case "font":
                    return(new Wrap(
                               children: this._parseNodeList(node.ChildNodes)
                               ));

                case "footer":
                    return(new Container(
                               width: this.width,
                               child: new Wrap(
                                   crossAxisAlignment: WrapCrossAlignment.center,
                                   children: this._parseNodeList(node.ChildNodes)
                                   )
                               ));

                case "h1":
                    return(DefaultTextStyle.merge(
                               child: new Container(
                                   width: this.width,
                                   child: new Wrap(
                                       crossAxisAlignment: WrapCrossAlignment.center,
                                       children: this._parseNodeList(node.ChildNodes)
                                       )
                                   ),
                               style: new TextStyle(
                                   fontSize: 28.0f,
                                   fontWeight: FontWeight.bold
                                   )
                               ));

                case "h2":
                    return(DefaultTextStyle.merge(
                               child: new Container(
                                   width: this.width,
                                   child: new Wrap(
                                       crossAxisAlignment: WrapCrossAlignment.center,
                                       children: this._parseNodeList(node.ChildNodes)
                                       )
                                   ),
                               style: new TextStyle(
                                   fontSize: 21.0f,
                                   fontWeight: FontWeight.bold
                                   )
                               ));

                case "h3":
                    return(DefaultTextStyle.merge(
                               child: new Container(
                                   width: this.width,
                                   child: new Wrap(
                                       crossAxisAlignment: WrapCrossAlignment.center,
                                       children: this._parseNodeList(node.ChildNodes)
                                       )
                                   ),
                               style: new TextStyle(
                                   fontSize: 16.0f,
                                   fontWeight: FontWeight.bold
                                   )
                               ));

                case "h4":
                    return(DefaultTextStyle.merge(
                               child: new Container(
                                   width: this.width,
                                   child: new Wrap(
                                       crossAxisAlignment: WrapCrossAlignment.center,
                                       children: this._parseNodeList(node.ChildNodes)
                                       )
                                   ),
                               style: new TextStyle(
                                   fontSize: 14.0f,
                                   fontWeight: FontWeight.bold
                                   )
                               ));

                case "h5":
                    return(DefaultTextStyle.merge(
                               child: new Container(
                                   width: this.width,
                                   child: new Wrap(
                                       crossAxisAlignment: WrapCrossAlignment.center,
                                       children: this._parseNodeList(node.ChildNodes)
                                       )
                                   ),
                               style: new TextStyle(
                                   fontSize: 12.0f,
                                   fontWeight: FontWeight.bold
                                   )
                               ));

                case "h6":
                    return(DefaultTextStyle.merge(
                               child: new Container(
                                   width: this.width,
                                   child: new Wrap(
                                       crossAxisAlignment: WrapCrossAlignment.center,
                                       children: this._parseNodeList(node.ChildNodes)
                                       )
                                   ),
                               style: new TextStyle(
                                   fontSize: 10.0f,
                                   fontWeight: FontWeight.bold
                                   )
                               ));

                case "header":
                    return(new Container(
                               width: this.width,
                               child: new Wrap(
                                   crossAxisAlignment: WrapCrossAlignment.center,
                                   children: this._parseNodeList(node.ChildNodes)
                                   )
                               ));

                case "hr":
                    return(new Padding(
                               padding: EdgeInsets.only(top: 7.0f, bottom: 7.0f),
                               child: new Divider(height: 1.0f, color: Colors.black38)
                               ));

                case "i":
                    return(DefaultTextStyle.merge(
                               child: new Wrap(
                                   children: this._parseNodeList(node.ChildNodes)
                                   ),
                               style: new TextStyle(
                                   fontStyle: FontStyle.italic
                                   )
                               ));

                case "img":
                    return(new Builder(
                               builder: (BuildContext context) => {
                        if (this.showImages)
                        {
                            if (node.Attributes["src"] != null)
                            {
                                if (node.Attributes["src"].Value.StartsWith("data:image") &&
                                    node.Attributes["src"].Value.Contains("base64,"))
                                {
                                    return Image.memory(Convert.FromBase64String(
                                                            node.Attributes["src"].Value.Split(new string[] { "base64," },
                                                                                               StringSplitOptions.None)[1].Trim()));
                                }

                                return Image.network(node.Attributes["src"].Value);
                            }
                            else if (node.Attributes["alt"] != null)
                            {
                                //Temp fix for https://github.com/flutter/flutter/issues/736
                                if (node.Attributes["alt"].Value.EndsWith(" "))
                                {
                                    return new Container(
                                        padding: EdgeInsets.only(right: 2.0f),
                                        child: new Text(node.Attributes["alt"].Value));
                                }
                                else
                                {
                                    return new Text(node.Attributes["alt"].Value);
                                }
                            }
                        }

                        return new Container();
                    }
                               ));

                case "ins":
                    return(DefaultTextStyle.merge(
                               child: new Wrap(
                                   children: this._parseNodeList(node.ChildNodes)
                                   ),
                               style: new TextStyle(
                                   decoration: TextDecoration.underline
                                   )
                               ));

                case "kbd":
                    return(DefaultTextStyle.merge(
                               child: new Wrap(
                                   children: this._parseNodeList(node.ChildNodes)
                                   ),
                               style: new TextStyle(
                                   fontFamily: "monospace"
                                   )
                               ));

                case "li":
                    string     type        = node.ParentNode.Name; // Parent type; usually ol or ul
                    EdgeInsets markPadding = EdgeInsets.symmetric(horizontal: 4.0f);
                    Widget     mark;
                    switch (type)
                    {
                    case "ul":
                        mark = new Container(child: new Text("•"), padding: markPadding);
                        break;

                    case "ol":
                        int index = node.ParentNode.ChildNodes.IndexOf(node) + 1;
                        mark = new Container(child: new Text($"{index}."), padding: markPadding);
                        break;

                    default:         //Fallback to middle dot
                        mark = new Container(width: 0.0f, height: 0.0f);
                        break;
                    }

                    return(new Container(
                               width: this.width,
                               child: new Wrap(
                                   crossAxisAlignment: WrapCrossAlignment.center,
                                   children: new List <Widget> {
                        mark,
                        new Wrap(
                            crossAxisAlignment: WrapCrossAlignment.center,
                            children: this._parseNodeList(node.ChildNodes))
                    }
                                   )
                               ));

                case "main":
                    return(new Container(
                               width: this.width,
                               child: new Wrap(
                                   crossAxisAlignment: WrapCrossAlignment.center,
                                   children: this._parseNodeList(node.ChildNodes)
                                   )
                               ));

                case "mark":
                    return(DefaultTextStyle.merge(
                               child: new Wrap(
                                   children: this._parseNodeList(node.ChildNodes)
                                   ),
                               style: new TextStyle(
                                   color: Colors.black,
                                   background: this._getPaint(Colors.yellow)
                                   )
                               ));

                case "nav":
                    return(new Container(
                               width: this.width,
                               child: new Wrap(
                                   crossAxisAlignment: WrapCrossAlignment.center,
                                   children: this._parseNodeList(node.ChildNodes)
                                   )
                               ));

                case "noscript":
                    return(new Container(
                               width: this.width,
                               child: new Wrap(
                                   crossAxisAlignment: WrapCrossAlignment.center,
                                   alignment: WrapAlignment.start,
                                   children: this._parseNodeList(node.ChildNodes)
                                   )
                               ));

                case "ol":
                    return(new Column(
                               children: this._parseNodeList(node.ChildNodes),
                               crossAxisAlignment: CrossAxisAlignment.start
                               ));

                case "p":
                    return(new Padding(
                               padding: EdgeInsets.only(top: this.blockSpacing, bottom: this.blockSpacing),
                               child: new Container(
                                   width: this.width,
                                   child: new Wrap(
                                       crossAxisAlignment: WrapCrossAlignment.center,
                                       alignment: WrapAlignment.start,
                                       children: this._parseNodeList(node.ChildNodes)
                                       )
                                   )
                               ));

                case "pre":
                    return(new Padding(
                               padding: EdgeInsets.all(this.blockSpacing),
                               child: DefaultTextStyle.merge(
                                   child: new Text(node.InnerHtml),
                                   style: new TextStyle(
                                       fontFamily: "monospace"
                                       )
                                   )
                               ));

                case "q":
                    List <Widget> children = new List <Widget>();
                    children.Add(new Text("\""));
                    children.AddRange(this._parseNodeList(node.ChildNodes));
                    children.Add(new Text("\""));
                    return(DefaultTextStyle.merge(
                               child: new Wrap(
                                   children: children
                                   ),
                               style: new TextStyle(
                                   fontStyle: FontStyle.italic
                                   )
                               ));

                case "rp":
                    return(new Wrap(
                               children: this._parseNodeList(node.ChildNodes)
                               ));

                case "rt":
                    return(new Wrap(
                               children: this._parseNodeList(node.ChildNodes)
                               ));

                case "ruby":
                    return(new Wrap(
                               children: this._parseNodeList(node.ChildNodes)
                               ));

                case "s":
                    return(DefaultTextStyle.merge(
                               child: new Wrap(
                                   children: this._parseNodeList(node.ChildNodes)
                                   ),
                               style: new TextStyle(
                                   decoration: TextDecoration.lineThrough
                                   )
                               ));

                case "samp":
                    return(DefaultTextStyle.merge(
                               child: new Wrap(
                                   children: this._parseNodeList(node.ChildNodes)
                                   ),
                               style: new TextStyle(
                                   fontFamily: "monospace"
                                   )
                               ));

                case "section":
                    return(new Container(
                               width: this.width,
                               child: new Wrap(
                                   crossAxisAlignment: WrapCrossAlignment.center,
                                   children: this._parseNodeList(node.ChildNodes)
                                   )
                               ));

                case "small":
                    return(DefaultTextStyle.merge(
                               child: new Wrap(
                                   children: this._parseNodeList(node.ChildNodes)
                                   ),
                               style: new TextStyle(
                                   fontSize: 10.0f
                                   )
                               ));

                case "span":
                    return(new Wrap(
                               children: this._parseNodeList(node.ChildNodes)
                               ));

                case "strike":
                    return(DefaultTextStyle.merge(
                               child: new Wrap(
                                   children: this._parseNodeList(node.ChildNodes)
                                   ),
                               style: new TextStyle(
                                   decoration: TextDecoration.lineThrough
                                   )
                               ));

                case "strong":
                    return(DefaultTextStyle.merge(
                               child: new Wrap(
                                   children: this._parseNodeList(node.ChildNodes)
                                   ),
                               style: new TextStyle(
                                   fontWeight: FontWeight.bold
                                   )
                               ));

                case "sub":
                case "sup":
                    //Use builder to capture the parent font to inherit the font styles
                    return(new Builder(builder: (BuildContext context) => {
                        DefaultTextStyle parent = DefaultTextStyle.of(context);
                        TextStyle parentStyle = parent.style;

                        var painter = new TextPainter(
                            text: new TextSpan(
                                text: node.InnerText,
                                style: parentStyle
                                ),
                            textDirection: TextDirection.ltr);
                        painter.layout();
                        //print(painter.size);

                        //Get the height from the default text
                        var height = painter.size.height *
                                     1.35f;     //compute a higher height for the text to increase the offset of the Positioned text

                        painter = new TextPainter(
                            text: new TextSpan(
                                text: node.InnerText,
                                style: parentStyle.merge(new TextStyle(
                                                             fontSize:
                                                             parentStyle.fontSize * RichTextParserUtils.OFFSET_TAGS_FONT_SIZE_FACTOR))
                                ),
                            textDirection: TextDirection.ltr);
                        painter.layout();
                        //print(painter.size);

                        //Get the width from the reduced/positioned text
                        var width = painter.size.width;

                        //print("Width: $width, Height: $height");

                        return DefaultTextStyle.merge(
                            child: new Wrap(
                                crossAxisAlignment: WrapCrossAlignment.center,
                                children: new List <Widget> {
                            new Stack(
                                fit: StackFit.loose,
                                children: new List <Widget> {
                                //The Stack needs a non-positioned object for the next widget to respect the space so we create
                                //a sized box to fill the required space
                                new SizedBox(
                                    width: width,
                                    height: height
                                    ),
                                DefaultTextStyle.merge(
                                    child: new Positioned(
                                        child: new Wrap(children: this._parseNodeList(node.ChildNodes)),
                                        bottom: node.Name == "sub" ? 0 : (int?)null,
                                        top: node.Name == "sub" ? (int?)null : 0
                                        ),
                                    style: new TextStyle(
                                        fontSize: parentStyle.fontSize *
                                        RichTextParserUtils.OFFSET_TAGS_FONT_SIZE_FACTOR)
                                    )
                            }
                                )
                        }
                                )
                            );
                    }));

                case "table":
                    return(new Column(
                               children: this._parseNodeList(node.ChildNodes),
                               crossAxisAlignment: CrossAxisAlignment.start
                               ));

                case "tbody":
                    return(new Column(
                               children: this._parseNodeList(node.ChildNodes),
                               crossAxisAlignment: CrossAxisAlignment.start
                               ));

                case "td":
                    int colspan = 1;
                    if (node.Attributes["colspan"] != null)
                    {
                        int.TryParse(node.Attributes["colspan"].Value, out colspan);
                    }

                    return(new Expanded(
                               flex: colspan,
                               child: new Wrap(
                                   crossAxisAlignment: WrapCrossAlignment.center,
                                   children: this._parseNodeList(node.ChildNodes)
                                   )
                               ));

                case "template":
                    //Not usually displayed in HTML
                    return(new Container());

                case "tfoot":
                    return(new Column(
                               children: this._parseNodeList(node.ChildNodes),
                               crossAxisAlignment: CrossAxisAlignment.start
                               ));

                case "th":
                    int _colspan = 1;
                    if (node.Attributes["colspan"] != null)
                    {
                        int.TryParse(node.Attributes["colspan"].Value, out _colspan);
                    }

                    return(DefaultTextStyle.merge(
                               child: new Expanded(
                                   flex: _colspan,
                                   child: new Wrap(
                                       crossAxisAlignment: WrapCrossAlignment.center,
                                       alignment: WrapAlignment.center,
                                       children: this._parseNodeList(node.ChildNodes)
                                       )
                                   ),
                               style: new TextStyle(
                                   fontWeight: FontWeight.bold
                                   )
                               ));

                case "thead":
                    return(new Column(
                               children: this._parseNodeList(node.ChildNodes),
                               crossAxisAlignment: CrossAxisAlignment.start
                               ));

                case "time":
                    return(new Wrap(
                               children: this._parseNodeList(node.ChildNodes)
                               ));

                case "tr":
                    return(new Row(
                               children: this._parseNodeList(node.ChildNodes),
                               crossAxisAlignment: CrossAxisAlignment.center
                               ));

                case "tt":
                    return(DefaultTextStyle.merge(
                               child: new Wrap(
                                   children: this._parseNodeList(node.ChildNodes)
                                   ),
                               style: new TextStyle(
                                   fontFamily: "monospace"
                                   )
                               ));

                case "u":
                    return(DefaultTextStyle.merge(
                               child: new Wrap(
                                   children: this._parseNodeList(node.ChildNodes)
                                   ),
                               style: new TextStyle(
                                   decoration: TextDecoration.underline
                                   )
                               ));

                case "ul":
                    return(new Column(
                               children: this._parseNodeList(node.ChildNodes),
                               crossAxisAlignment: CrossAxisAlignment.start
                               ));

                case "var":
                    return(DefaultTextStyle.merge(
                               child: new Wrap(
                                   children: this._parseNodeList(node.ChildNodes)
                                   ),
                               style: new TextStyle(
                                   fontStyle: FontStyle.italic
                                   )
                               ));
                }
            }
            else if (node.NodeType is HtmlNodeType.Text)
            {
                //We don't need to worry about rendering extra whitespace
                if (node.InnerText.Trim() == "" && node.InnerText.IndexOf(" ") == -1)
                {
                    return(new Wrap());
                }

                if (node.InnerText.Trim() == "" && node.InnerText.IndexOf(" ") != -1)
                {
                    (node as HtmlTextNode).Text = " ";
                }

                string finalText = this.trimStringHtml(node.InnerText);
                //Temp fix for https://github.com/flutter/flutter/issues/736
                if (finalText.EndsWith(" "))
                {
                    return(new Container(
                               padding: EdgeInsets.only(right: 2.0f), child: new Text(finalText)));
                }
                else
                {
                    return(new Text(finalText));
                }
            }

            return(new Wrap());
        }