diff --git a/src/Abstract/Entity/Browser/Container/Page/Content/Markup.php b/src/Abstract/Entity/Browser/Container/Page/Content/Markup.php index 8a2d9a67..7b2a5fc7 100644 --- a/src/Abstract/Entity/Browser/Container/Page/Content/Markup.php +++ b/src/Abstract/Entity/Browser/Container/Page/Content/Markup.php @@ -18,11 +18,7 @@ abstract class Markup // Dependencies public Content $content; - // Defaults - public const WRAP = 140; - // Extras - protected int $_wrap = self::WRAP; protected ?string $_source = null; public function __construct( @@ -113,11 +109,18 @@ abstract class Markup return false; } - // Require custom wordwrap implementation on widget resize - abstract protected function _onSizeAllocate( + // Custom wordwrap on widget resize + protected function _onSizeAllocate( GtkLabel $label, GdkEvent $event - ): bool; + ): bool + { + $this->set( // @TODO Gtk::timeout_add + $this->_source + ); + + return false; + } // Require custom layout implementation abstract public function set( @@ -125,61 +128,6 @@ abstract class Markup ): void; // Tools - protected function _line( - int $offset - ): ?string - { - if (is_null($this->_source)) - { - return null; - } - - $start = strrpos( - substr( - $this->_source, - 0, - $offset - ), - PHP_EOL - ) + 1; - - $end = strpos( - $this->_source, - PHP_EOL, - $offset - ); - - if ($end === false) - { - $end = strlen( - $this->_source - ); - } - - return substr( - $this->_source, - $start, - $end - $start - ); - } - - protected function _wrap( - string $source - ): string - { - if ($wrap = $this->_wrap ? $this->_wrap : $this::WRAP) - { - return wordwrap( - $source, - $wrap, - PHP_EOL, - false - ); - } - - throw new Exception; - } - protected function _url( string $link ): ?string diff --git a/src/Abstract/Model/Gtk/Pango/Markup.php b/src/Abstract/Model/Gtk/Pango/Markup.php index bdc1e505..8db38c65 100644 --- a/src/Abstract/Model/Gtk/Pango/Markup.php +++ b/src/Abstract/Model/Gtk/Pango/Markup.php @@ -4,6 +4,9 @@ declare(strict_types=1); namespace Yggverse\Yoda\Abstract\Model\Gtk\Pango; +use \PangoLayout; +use \GtkDrawingArea; + class Markup implements \Yggverse\Yoda\Interface\Model\Gtk\Pango\Markup { public static function code( @@ -99,11 +102,15 @@ class Markup implements \Yggverse\Yoda\Interface\Model\Gtk\Pango\Markup } public static function text( - string $value + string $value, + int $width = self::WRAP_WIDTH ): string { return htmlspecialchars( - $value + self::_wrap( + $value, + $width + ) ); } @@ -131,4 +138,62 @@ class Markup implements \Yggverse\Yoda\Interface\Model\Gtk\Pango\Markup throw new Exception; } + + public static function width( + string $markup + ): ?int + { + $layout = new PangoLayout( + (new GtkDrawingArea)->create_pango_context() + ); + + $layout->set_markup( + $markup, + mb_strlen( + $markup, + 'UTF-8' + ) + ); + + if ($size = $layout->get_pixel_size()) + { + return $size['width']; + } + + return null; + } + + protected static function _wrap( + string $string, + int $width = self::WRAP_WIDTH, + int $line = 1 + ): string + { + $words = []; + + foreach (explode(' ', $string) as $word) + { + if (isset($words[$line]) && Markup::width(implode(' ', $words[$line])) > $width) + { + $line++; + } + + $words[$line][] = $word; + } + + $lines = []; + + foreach ($words as $values) + { + $lines[] = implode( + ' ', + $values + ); + } + + return implode( + PHP_EOL, + $lines + ); + } } \ No newline at end of file diff --git a/src/Entity/Browser/Container/Page/Content/Gemtext.php b/src/Entity/Browser/Container/Page/Content/Gemtext.php index 676de88e..bec3abea 100644 --- a/src/Entity/Browser/Container/Page/Content/Gemtext.php +++ b/src/Entity/Browser/Container/Page/Content/Gemtext.php @@ -180,7 +180,8 @@ class Gemtext extends \Yggverse\Yoda\Abstract\Entity\Browser\Container\Page\Cont else { $line[] = Markup::text( - $entity->getData() + $entity->getData(), + $this->content->page->gtk->get_allocated_width() ); } diff --git a/src/Interface/Model/Gtk/Pango/Markup.php b/src/Interface/Model/Gtk/Pango/Markup.php index 0be4e478..dbcb9d14 100644 --- a/src/Interface/Model/Gtk/Pango/Markup.php +++ b/src/Interface/Model/Gtk/Pango/Markup.php @@ -12,6 +12,8 @@ interface Markup { public const TAG_CODE = 'tt'; + public const WRAP_WIDTH = 140; + public static function code( string $value ): string; @@ -54,4 +56,8 @@ interface Markup string $const, bool $close ): string; + + public static function width( + string $markup + ): ?int; } \ No newline at end of file