2024年4月6日土曜日

WPF用縦書きテキストブロック Tategaki ver.3.0.0

先日、ふとTwitter経由でTategakiの不具合についての報告がありました。前回更新からすでに8年以上経過しているのに、こうやって連絡をいただけるのはとても嬉しいことです。 

(ライブラリをダウンロードしたいだけの人、使い方を見たいだけの人は下のほうのGithubリンクからリポジトリにアクセスしてください)

不具合の経緯

不具合の内容ですが、 TategakiText ver.2系はコントロールをカスタムコントロールで作っており、コントロール内部にGlyphsコントロールを配置することで縦書きを実現していました。これがDocumentViewerコントロールと相性が悪いようで、DocumentViewer上でTategakiText上にマウスオーバーすると例外を吐いて落ちるようでした。

報告してくださった方は、対策案として、ControlではなくContentControlでGlyphsをホスティングするということまで提案してくださっていました。
ここまでいろいろとやってくれる方がいるのに知らんぷりするわけにはいかない…!というわけで、本腰を入れて不具合の解消を始めました。

不具合内容

FixedPageに配置したコントロールでマウスオーバーが発生すると、そのコントロールから親要素を辿ってFixedPageまでの関係を確認するようですが、そこでGlyphs→Borderときて、その次Contorlに行けず(LogicalTreHelper.GetParent(border)がnullとなり)ArgumentNullExceptionが発生しているようでした。

.NETはオープンソースでコードが公開されているので、当該部位を見てみましょう。

// We have no uniform way to do random access for this element.
// This should never happen for S0 conforming document.

(◞‸◟)(◞‸◟)(◞‸◟)(◞‸◟)(◞‸◟)

"S0 confirming document"(S0準拠ドキュメント?)が何を指すかよくわかりませんが、「この分岐に来ることは無いから実装は適当で良いよね、エイヤッ!」で実装されて、nullだった場合の対処とかは深く考えられていなかったコードということですね。

対応方針とやりたかったこと

さて、報告してくださった方は前述の通りContentControlにしたらこの不具合は発生しなくなったと連絡してくれているのですが、Tategakiライブラリが目指すのは「TextBlockの縦書き版」です。
ContentControlはTemplateが使えるという特徴があり、WPFではTextBlockというよりかLabelがそれに該当します。ですので、せっかく提案いただいていて申し訳ないのですが、少しコンセプトからずれてしまうなと思い、別の方法で対処できないか検討することとしました。

そもそも、元祖TextBlockはカスタムコントロールを使っているわけでもGlyphsをラッピングしているわけでもなく、直接FrameworkElementを継承したクラスとして実装されています。従って、現在のTategakiTextの実装方法自体がそもそもコンセプトずれしているということで、直接FrameworkElementを継承することで実装するという方法で進めていくこととしました。
事の発端となった不具合も、呼び出し経路の中でマウスオーバーされたのがGlyphsコントロールかどうかの分岐が入っています。実装を変えれば不具合も解消するでしょう。

実装

FrameworkElementを直接継承して描画処理を行うのはドキュメントが少なく四苦八苦したのですが、それ自体が別記事となるような分量ですので、後ほど別記事として紹介します。

公開

今まではこのブログにファイルを添付する形でソフトを公開していましたが、意外と私の見えないところで使ってくださる方もいて、でも不具合を踏んだけど報告もできずに困っている方も実はいたのではないかと今回の連絡から反省しました。

私がプログラミングを始めたのは、いわゆるVector / 窓の杜時代で、個人が作ったソフトがクローズドソースでそういったホスティングサービスを経由して公開されている時代でした。でも今は違います。オープンソースでコミュニティがいろいろとフィードバックをくれる時代です。
ならばやはりそういうやり方で公開するほうが良いのではないか、ということで、Githubのリポジトリを立ち上げました。

 

これならば不具合があればIssueを立てれるし、バグを直してくれる方がいればPullRequestをくれるはず…!
実を言うとGithubは使うのがこれがほぼ初めてです。初心者ですがよろしくお願いします!!!!!

もちろん従来通りNugetでも公開しております。

Tategaki - Nuget

前回はターゲットが.NET Framework 4.0でしたが、今回から.NET 6にしています。.NET Framework系も必要な方がいればコメント欄か、コードを修正してPullRequestで連絡ください。検討します。

2 件のコメント:

  1. 先日、報告した件、バージョンアップの対応までしていただき有難うございます。
    想像以上に改修されており、驚いてます。私のサンプルは、あまり考えて作っておらず、ControlTemplateを書き換えると問題となるかもしれません。
    .NetFramework4.7 用も追加していただき助かります。

    返信削除
    返信
    1. いえいえ、こちらこそありがとうございました。

      削除