甘いものが無性に欲しくなって

即席のドーナツを作ってみた.小麦粉+ベーキングパウダを水で溶いて熱した油の中にポトンと落としただけ.速攻3分でできあがり.ただし,画像をアップロードするのに2日掛かった.

ドーナッツ

重婚クラスタ循環は多重カードが発生する原因だが,循環に関係するクラスタに属するすべてのノードが関わっているという訳ではない.むしろ,循環を解消するためにパージされた婚姻グラフの枝,つまり結婚当事者ノードに関わりがある.循環の発生している重婚クラスタに属するノードにはCARDLINK::samecycle属性が付与されているが,それを代替するものとして,breakup属性を導入し,循環を解消するために削除された婚姻枝の結婚枠とその当事者ノード付与するようにした.{samemcycle} ⊃ {breakaup}でbreakup属性の方がより範囲が狭い.つまり,焦点深度が深い.CARDLINK::samecycleは廃止した.

TOPOLOGY::BuildSameGeneMarriageGraphのステージ【13】重婚グラフの循環が止まるまで枝を除去するの段では,「重婚クラスタ循環が存在するとき,親子枝の親ノードの配偶者の配偶者関係を切断」していたが,ターゲットを「親子枝の子ノード」に切り替えてみた.サンプルの源氏物語全系譜7.ZELでは,この親子枝は光源氏→夕霧に該当し,これまでは親の光源氏をクラスタから切断するという処理になっていたところを,子ノードの夕霧で切断するという操作に切り替えた.この結果,多重カードは現行の7から5まで削減することができた.修正前の多重カードは以下の7点だが,▲マークの付いた,源典侍と真木柱は修正後の版では多重になることを免れている.

  1. @5紫の上(若紫)[5]
  2. @57女三宮[4]
  3. @100源典侍[4] ▲
  4. @101朧月夜[4]
  5. @103空蝉[4]
  6. @104藤壷の宮[4]
  7. @144真木柱[6] ▲

これで見る限り,修正後の版の方が高品質であるように思われるが,親ノードと子ノードのどちらを切断する方が有利かはケースバイケースであり,本来ならその優劣を計量して決定すべきところだが,多重カードの出現数はコンテキストに依存して決定されるため,この時点では確定することができない.実際,「子ノードで切断」する方式の場合,削除される枝数は以下のようにむしろ増加している.下記▲は「親ノードで切断」には含まれない循環/削除枝.

  1. 削除枝:直系血族配偶者 MARGBOX #8260:#8612 光源氏(0)+#17138 紫の上(若紫)(1)→#8663 明石中宮(0)
  2. 循環枝:【2】⇒【2】 【CARDLINK:#1095 @8夕霧[0]】⇒【CARDLINK:#1032 @1光源氏[0]】
  3. 削除枝:重婚配偶者 MARGBOX #6916:#17276 落葉の宮(1)+#9938 柏木(0)→ ▲
  4. 循環枝:【2】⇒【2】 【CARDLINK:#1032 @1光源氏[0]】⇒【CARDLINK:#1041 @2桐壷院[0]】▲
  5. 削除枝:重婚配偶者 MARGBOX #8548:#17672 柏木(1)+#17686 女三宮(2)→#17700 薫(2)
  6. 削除枝:重婚配偶者 MARGBOX #7252:#10601 伊予介(0)+#18368 空蝉(2)→
  7. 削除枝:重婚配偶者 MARGBOX #7076:#9887 致仕太政大臣(0)+#17571 夕顔(1)→#17585 玉鬘(1)
  8. 削除枝:重婚配偶者 MARGBOX #7092:#9887 致仕太政大臣(0)+#17600 源典侍(2)→
  9. 削除枝:重婚配偶者 MARGBOX #7380:#9309 朱雀院(0)+#17339 朧月夜(1)→
  10. 削除枝:重婚配偶者 MARGBOX #8292:#8629 桐壷院(0)+#17389 藤壷の宮(1)→#17403 冷泉院(3)

直系血族婚はあらかじめ除去されているので循環枝に含まれていないが,それを含めれば,修正前の方式では循環を解消するために2箇所の切断が必要であり,修正後の方式では切断は3箇所に増加,パージされる婚姻関係(削除枝)は前者が7であるのに対し,後者では8に増加している(しかし,多重カード数は後者の方が少ない).

HasPhysicalConnectionで系列優先実ノードの絶対世代番号と物理世代番号の一致を求めるように修正した.HasPhysicalConnectionはDoesMajorTribePathExistとaddTribeTreeGraphから呼び出されている.DoesMajorTribePathExistはIsConnectedとSetMinorTribe,TribePrimaryCandidateで使われている.addTribeTreeGraphはEstablishMajorTribeChainから実行される.この修正により,源氏物語全系譜7.ZEL #1 光源氏で起きていた「絶対世代番号と物理世代番号の不一致」は解消した.

多重カードは5枚.多分これは最少多重カードになっていると思う.ZT BASICではグラフ検証系を使えないため,9件の多重カードが残る.最近の修正をフィックスしておこう.

  1. CARDLINK:samecycleを廃止する@20210315 12箇所
  2. MAXREPEATCOUNTを廃止する@20210315 8箇所
  3. MakingLookUpは系統並び替えで一度だけ実行する@20210227 廃止 10箇所
  4. TESTABSOLUTEGENERATION 3箇所
  5. 仮修正 2箇所,OBSOLETE 1箇所

Version 2.2.0.029 Release 2021-03-17を所内リリースした.⇒ダメだ.多重カードが7に戻ってしまった.修正フィックス前の版でも同じ.⇒ZELKOVA 2021-03-15-2まで戻れば復活する.WinMergeでファイルを比較してみたが有意差は見つからなかった.この版とZELKOVA 2021-03-16の相違点はグラフ関係の関数を移動していることと「MAXREPEATCOUNTを廃止する」修正がまだ入っていないくらいだ.その他TribeRelocation.cppには細かい差異があるが,一瞥しただけでは致命的なものは見つからなかった.

ともかく,この版に戻って出直すしかない.まず,この版で「CARDLINK:samecycleを廃止する@20210315」と「重婚クラスタ循環を子ノード側で切断する@20210315」をフィックスしておこう.⇒後者はSPECIFICATIONとして温存しておいた方がよい.この版でリリース版を起こしておくことにする.その前にZT BASICで動作することを確認しておこう.⇒OKだ.改めて,「MAXREPEATCOUNTを廃止する」を入れておこう.

重婚クラスタ検定論理の修正

TOPOLOGY::BuildSameGeneMarriageGraphを修正して,ステージ【3】婚姻関係にある2つの人名を連結する枝をグラフに追加するの段で「直系血族婚関係を重婚クラスタグラフからあらかじめ排除する」ようにした.また,重婚クラスタ循環が存在するとき,親子枝の親ノードPの配偶者の配偶者関係を切断する処理で,配偶者Aの配偶者Bとの関係が配偶者Bの唯一の結婚の場合には切断しないように修正した.

これはこの切断によって配偶者Bが孤立してしまうことを防止するためである.この関係を切断しなくても,クラスタの世代分割には支障はない.配偶者Bは配偶者Aとともに親ノードPのクラスタに移籍するようになるからだ.これで,少なくとも大臣(葵)系列と蔵人の少将 (夕顔)系列で発生していた,「絶対世代番号と物理世代番号の不一致」は解消したが,まだ複数の「絶対世代番号不一致」が残っている.

image

この中には,先帝系列,※6系列,※7系列,按察の大納言(若紫)系列が含まれているが,問題は系列優先ノードとその他のノードとの位置関係にある.このブロックの中心は先帝系列でその優先ノードの紫の上(若紫)が光源氏との直系血族婚関係にあるため多重出現していることが関係しているのではないか?だとすれば,どうすればよいか?

系列優先ノードでsamecycle属性を持っているノードが14点,breakup属性を持っているノードが4点ある.samecycleは循環の発生している重婚クラスタに属するノードで,breakupは循環を解消するために削除された婚姻枝の当事者ノードだ.breakupノードは一般にsamecycleノードでもあるが,紫の上(若紫)は上記修正により,重婚クラスタ検定に入る前に直系血族婚関係で除去されているため,breakup属性しか持っていない.breakup属性を持つ優先仮ノードには以下がある.

  1. TRIBEBOX #15205 先祖=#8765 一院(0)[1] 優先=#8612 光源氏(0) 始系列
  2. TRIBEBOX #15349 先祖=#10533 先帝(0)[4] 優先=#50277 紫の上(若紫)(3)→#17138 紫の上(若紫)(1)
  3. TRIBEBOX #15593 先祖=#10516 衛門督(箒木)(0)[15] 優先=#18334 空蝉(1)→#10346 空蝉(0)
  4. TRIBEBOX #16087 先祖=#10414 三位中将(0)[28] 優先=#18734 夕顔(2)→#8612 光源氏(0)

このグラフのクラスタ図を見てみよう.

image

※6系列と※7系列が中務宮と同じ世代まで下がっているところが特徴的だ.※3と並ぶ※2系列は実際の出力では左端に移動しているが,高さは変わらない.実際の系図出力は下図のようになっている.

image

系図全体の世代高さは同じ9世代だが,クラスタ図には冗長なところが存在しない.どこでこの差異が発生しているのかを突き止めなくてはならない.紫の上のカードは2つ出ている.紫の上(0)は葵の上の直下の子ども枠内で絶対世代番号と物理世代番号は一致している.紫の上(1)はその一つ上の世代,光源氏の結婚枠内で絶対世代番号5に対し,物理世代番号は4になっている.

クラスタ図上には人名カードの重複は存在しないから,クラスタ図上では絶対世代番号5の位置にあり,他の場所から参照される場合もその位置で参照されているはずだ.先帝系列の優先ノードを紫の上と決定したときの選択に誤りがあるのではないだろうか?つまり,クラスタ上で決定した位置に配置されるべきノードを選択すべきだったのではないだろうか?⇒少なくとも系列優先実ノードの絶対世代番号≠物理世代番号であることが決定因であることは間違いなさそうだ.

クラスタ図を用いて絶対世代番号を決定した後の処理

重婚クラスタ検定でクラスタ図を用いて絶対世代番号を決定した後の処理を見直す必要がある.ここでは2つのことを実施している.①絶対世代番号を用いて各描画要素の配置を決定すること,②系列間の参照関係を確立し,物理的なコネクションを確保すること.①は主にTRIBELIST::ShiftDirectAbsoluteとAdjustTribeGenerationによって実行され,②はTOPOLOGY::EstablishMajorTribeChainが担当する.

①の状態を検査するためにTREEVIEW::TestAbsoluteGenerationを復活させた.系列参照関係はすでにMAKEUPTREEフェーズで基本的には確立しているが,物理的なコネクションを構成するためにTRIBEBOX::TribeGhostNameとBetweenTwoWomenが発動される.また,これらの処理によって描画要素の垂直位置関係に矛盾を解決するためにCheckTribeVerticalPositionが用いられる.

重婚クラスタ循環がない図面ではこれらの道具立てで十分処理できるのだが,問題は源氏のように重婚クラスタが無数に存在するような図面の場合だ.このような図面に多重カードが発生することは避けられないが,それを極小化するためには,絶対世代番号を用いた配置とそれからの逸脱をコントロールする必要がある.どうすればよいか?

まず,重婚クラスタグラフからハッセ図を生成するときに除去された削除枝(結婚)を追跡できるようにしておこう.一度バックアップに戻って出直すことにする.

カード巡回パネルの仕様を変更

カード巡回パネルの仕様を変更して,巡回対象テーブルを検索テーブルから選択テーブルに変えることにする.⇒改修した.また,左右カーソルキーでカード巡回パネルのスピンボタンを代用できるようにした.左右カーソルキーでカード巡回パネルが出ていない場合でも,選択されたカード領域を巡回することができる.これは結構便利かもしれない.

▲部分図で選択カード0のとき,全体図に戻って選択カード1となり,一覧表では選択状態になっているが,系図画面では選択が落ちている.⇒再現できない.

源氏物語全系譜7.ZEL全体図#1 光源氏で「先祖ノード絶対世代番号不一致」が以下で発生している.

  1. #10533 先帝(0)
  2. #10618 大臣(葵)
  3. #10992 ※6(0)
  4. #11349 按察の大納言(若紫)
  5. #11536 ※7(0)

AFTERMARGSAMEGENEフェーズでShiftDirectAbsoluteとAdjustTribeGenerationを実行した直後には世代不一致は起きていない.その後に実行される①CheckTribeVerticalPosition,②TribeGhostName,③BetweenTwoWomenのうち,①は世代調整のために不可欠なので温存し,②と③はメインループに入ってから遅延しょりすることにした.また,リトライではAFTERMARGSAMEGENEの入口まで戻って,ShiftDirectAbsoluteとAdjustTribeGenerationを再実行するようにした.これで#10618 大臣(葵)を除くすべての「先祖ノード絶対世代番号不一致」が解消した.

大臣(葵)の世代不一致は六条御息所の重婚に起因するもので,配偶者である前春宮と光源氏が異世代とならざるを得ないことから不可避と認定される.

image

このサンプルでは多重が9件発生しているが,除去された循環枝数9と一致している.この中には本人ポジションを持たない不可避多重カード6件が含まれる.これはほぼ「究極の多重カード最小図面」と呼んで差し支えないのではないかと思う.

▲上記サンプルで※3系列と先帝系列で「主系列の付け替え」が反復発生している.※3系列では優先ノードが#17897 桐壷の更衣(1)⇔#17865 明石の上(1)で行ったり来たりになっている.先帝系列では,#17963 真木柱(2)と#17949 髭黒(1)の間で往復運動している.どちらも主系列は一院系列で結果的には主系列には変更はない.この切り替えはEstablishMajorTribeChainで起きている.

Windows 10 バージョン 2004のインストールに失敗した

PCがやけに重くなっている感じがしたので,Windows 10 バージョン 2004のインストールを試みた.ダウンロードにも相当な時間が掛かったが何とか完了し,インストールに入ったが遅々として進まないので寝てしまった.朝起きたら「更新したプログラムを構成しています 25%」の状態で足踏みしている.30分放置してもまったく進まないので電源を落として再起動した.ネットでチェックすると,バージョン 2004のインストールには相当問題があるようだ.

image

再起動すると「コンピュータに対する変更を元に戻しています」の画面になったが,そのあとは通常通り使えるようになった.OSのバージョンは1909に戻っている.「更新を7日間一時停止」しておくのが一番無難かもしれない.最近の修正をフィックスしておこう.

  1. SIMPLENODEのdownwardとupwardを廃止@20210303 2箇所
  2. 選択はカードの有効無効と無関係@20210305 4箇所
  3. クラスタ検定に結婚を持たない終端ノードを含める@20210306 1箇所
  4. 主選択カードの仕様変更@20210307 2箇所
  5. カード選択とカード移動を切り離す20210306 7箇所
  6. 仮修正 2箇所,暫定修正 6箇所,#if 0 8箇所,

カード履歴ボタンではセンタリングしなくてもよいのではないか?現参照カードにはHOMEキーでいつでもジャンプできる.⇒だとすれば,カード履歴で単選択に戻るのではなく,選択領域を維持したまま現参照カードだけ切り替えるという仕様の方が筋が通るのではないか?⇒カード履歴ではJumpNewCardSingleで単選択に落としている.カード履歴でカード画面のタブが切り替わるのもよくない.⇒カード履歴では意図的にタブを復元している.JUMPTBLには以下の記録が格納されている.

  1. refn As Integer ‘現参照カード(基準ノード)参照番号
  2. tabn As Integer ‘カード画面タブ番号
  3. page As Integer ‘結婚ページ番号
  4. oyap As Integer ‘父母ページ番号
  5. entry As Integer ‘部分図エントリ番号
  6. previewmode As Short ‘プレビューモード
  7. keizuparm As mKeizuParm ‘系図描画パラメータ

つまり,可能な限りそのときの状態を復元させるという意図がある.一種のUNDOのような効果を狙っていたものと思われる.少しやり過ぎではないかという感もある… カード移動によって無闇にタブが切り替わらない方がよいという場合もあると思うのだが… タブの切り替え,結婚ページ,父母ページの切り替えなどは一時停止してしばらく運用してみることにする.これで,上下矢印キー,カード画面のスピンボタン,カード履歴ボタンの動作は現参照カードを移動するだけというシンプルなものになった.これでよいのではないかと思う.

逆に,矢印キー,スピンボタン,履歴ボタンが押されたときはカード巡回パネルは閉じた方がよいと思う.現行では履歴ボタンでは閉じるようになっているが,スピンボタンは巡回パネルのスピンボタンの動作になっている.また,矢印キーではやや意味不明の動作になる.⇒矢印キーでは巡回パネルを閉じるようにした.カード画面のスピンボタンが巡回パネルの動作になるというのも少し分かりづらいところはあるが,弊害はあまりないと思われるので現行のままとする.

系図画面の空白部をクリックして無選択にならない.⇒表示が更新されていない.mGetSelectListでは0を返している.UpdateSelectionは実行されている.⇒処理の重複を回避するために削り過ぎてしまった.UpdateSelectionの中でClearSelectionを実行することは必須だ.

選択→センタリングという動作そのものはよいと思うが,少し動作し過ぎの感じがする.カードが見えている場合はそこまでやらなくてよい.⇒CallCenteringMoveでは,*selectchangeがオンの場合はカードがフレーム内のときはジャンプしないようになっている.ただし,ACTION_HOMEKEYではつねに現参照カードにジャンプする.⇒CZelkovaCtrl3::CenteringCardの動作をACTION_CENTERに戻した.動作的にはこれでよいと思う.ただし,一覧表上で拡張選択(複数選択)した場合には現参照カードが見えるようにすべきだ.

呼び出し側ではそのような動作になっているが,ActionCenteringには引数で参照番号を渡していないため,どこかで齟齬が起きている.⇒TREEVIEW::CallCenteringMoveで*selectchangeが入っていないため,「中央点不動ズーム」の動作になっている.⇒タイミングが合っていない.センタリングはCardGridView_CurrentCellChangedで実行されるが,selectchangeに値が入るのはDataGridView_MouseUpでSelectionProcが実行されたときだ.この順序関係を変えることはできないので,ACTION_CENTERの場合は,selectchangeを無視してセンタリングを実行するようにするしかない.⇒修正した.これで完全に現参照カードを追尾できるようになった.

源氏物語全系譜6.1.ZEL 全体図#1 光源氏で一覧表で複数選択→親族図に切り替えで被参照カウントの残留が発生した.NAMEBOX:Dispose→ RetrieveGhost→ DeleteLongTailで発生している.MARGBOX[24]からの参照だ.MARGBOXsANCHORスロットでanchor2という変数だ.「アンカー参照の控え,アンカー付け替え時の参照削除用:人名枠への単純参照」というコメントが付いている.NAMEBOXにはNAMEsDUMMYというスロットがあり,dummyboxという名前が付いている.この障害は選択操作と無関係に発生する.

NAMEBOX::Disposeでcheckをオンにすると,これまで停止していなかったところで止まるようになる.⇒checkで停止するようになっていた.紛らわしいので廃止しておこう.

dummyboxはすでに空になっているが,現物は残っている.dummyboxは参照ではなく接続なので,おそらくフロート状態になっているのだろう.障害が起きているのはNAMEBOX #96515 中姫君(4)で,ダミー枠はMARGBOX #96525だ.⇒いや,読み損なっていた.障害ノードはNAMEBOX #86655 中姫君(3)で,dummyboxは活きているので簡単に参照解除できる.⇒解決.

同上の操作でNAMEBOX::getDrawSizeの「親族範囲外カード」エラーが複数出ている.LINEAGEの値は7でZELKOVATREEのとき,カードのkindredが10>7であるためだ.10というのはSTRANGERSなので明らかに「親族範囲外カード」であるように思われる.ただし,これはTREEVIEW::EraseTreeViewで起きているので,検査対象とはなならない.少なくともCHAOTICSTATE以下では無視してよいだろう.

同上サンプルの親族図の系図画面上で複数選択→ 部分図に遷移しようとしてMARGBOX::MostLeftで停止した.(ML && ML->group() != group())というエラーだ.結婚枠とその中の人名枠の所属系列が異なるというエラーだ.選択操作とは無関係に発生する.この障害もやはり,EraseTreeViewで発生している.上記と同様無視でよいだろう.

いい感じになってきた.選択操作に関してはほぼ満点と言ってよい.

検索ボックスでテキストを全選択して削除でカード削除になるのはまずい.⇒これはおそらくDELキーがカード削除コマンドになっているためではないかと思われる.このため,キーイベントが発生する前にコマンドが実行されてしまっている.KeyDownSubではCtrl+DELでカード編集:カード削除となっていて,「@2017-09-09 修飾なしの削除キーでカード削除を実行する × 弊害がある」としているのだが… ⇒まず,カード削除コマンドのショートカットをCtrl+DELに変えてみよう.

検索ボックスでDELキーを押すと,MDIForm_KeyDown→ KeyDownSubを通るようになるが,該当項目がないのでパスしてテキストのクリアが実行される.また,系図画面にフォーカスがあるときには,ZView_KeyDownが起動され,ここでは「修飾なしの削除キーでカード削除 」が実行される.これでよいのではないだろうか?カード画面上のテキストボックスでも普通にDELキーが使える.

検索ボックスで検索条件不一致で検索テキストが削除されるというのはあまりよい仕様ではない.また,テキストがクリアされた後,カーソルがボックスの中央というのも違和感がある.⇒検索入力ボックスのAlignmentはLeftになっている.このAlignmentはテキストボックス内の位置ではなく,ボックス全体がツールバーの中で右寄せか左寄せかという設定になっている.MDIParent.Designer.vbで「Me.検索入力ボックス.TextAlign=System.Drawing.ContentAlignment.MiddleLeft」としてみたが,変化しない.というか,不一致でテキストがクリアされると見ていたが,違うようだ.

「マッチするカードはありません」のパネルを閉じてもテキストボックスには残っている.ただし,ボックス内にカーソルを置くと突然消えて,カーソルがボックスの中央に表示された状態になる.しかし,カーソルを移動すると消えていた文字がまた復活する.検索入力ボックスのイベントハンドラは「検索入力ボックス_TextChanged」だけだ.ボックス内にカーソルを置いただけではこのイベントは発生しない.⇒よくわからないが,ここではこういうものだとしておこう.

検索ボックスの右にある虫メガネは選択領域があるときには,巡回パネルの右スピンボタンと同じ動作になっていて,カードを巡回するようになっているが,インジケータ行が変化していない.⇒SearchBoxSearchにUpdateSelectionを追加してインジケータ行も連動するようになったが,動作的にはかなり問題がある.選択領域と検索領域を混用するというのはやはりまずいのではないか?

検索領域は検索結果の巡回にのみ使用するように限定すべきだと思う.確かに選択領域を巡回できる手段があるというのも悪いアイディアではないが,混乱の元になる.検索結果は新たな検索が実施されるまでは温存され,いつでもカード巡回パネルないし検索ボタンで巡回できるというのはよいと思う.従って,選択領域を検索領域にコピーするという操作は基本的に不要ないし有害であると思われる.

選択領域→ 検索領域のコピーはmGetSearchListで実施している.この関数をmGetSearchListから呼び出すというのはとりあえず停止しよう.また,検索結果を選択領域に組み込むというのも廃止すべきだろう.いや,検索領域を選択領域に落とすというのは結構有用性があるのではないか?だとすれば,検索結果をストレートに選択領域に転換するというのが一番わかり易いと思う.

ただし,次検索で巡回するのは検索領域であり,選択領域ではないから,たとえば検索解除しても次検索は可能ということになる.検索領域から選択領域へのコピーはMakeSearchSelectionで実施している.この関数ではSendSelectionで選択領域を送っているので,系図画面には反映されているが,一覧表が更新されていない.⇒MakeSearchSelectionでUpdateSelectionを実行するようにした.

F3を押すと巡回パネルが閉じてしまうが,開いたままでよいのではないか?⇒KeyDownSubで閉じている.F3キーの場合は開けたままとしてみよう.

検索条件をキープされているはずだが,入っていない.SearchStringは検索文字列リストに追加しているだけだ.CopySearchConditionがMakeSearchSelectionから呼び出されているが,これはZ.SCの内容を検索パネルのパラメータにコピーするものだ.検索ボックスではZ.SCを使っていないのではないか?QuickSearchでは事後にZ.SCを構成しているが,MakeSearchSelection実行後なので間に合わない.⇒先行してZ.SCを構成するようにした.

クィック検索では姓名を1文字列としているが,姓と名前に分離する必要がある.スペースを区切り文字としてSplitで分割するようにした.

キーワード「大納言」で検索し,結果を新規部分図として部分図に切り替えようとして,TOPOLOGY::BuildSameGeneMarriageGraphで停止した.多重グラフ2の枝リストが空になっている.しかし,これはすべてのノードが孤立ノードの場合なら,あり得ることだ.ダンプだけで停止しないようにした.

カード一覧表をクリック→カード選択でカード画面が変化しない

カード一覧表をクリック→カード選択でカード画面が変化しない.矢印キー,カード画面のスピンボタンでは変化する.系図画面上のクリック→カード選択でも変化する.一覧表の最左セル(インジケータ列)のクリックなら変化する.⇒CardGridView_CurrentCellChangedでCardBox.GetNewCardを実行するように修正.CurrentCellChangedではマウスアップイベントとの重複動作を避けるためにSelectionProcないしSendSelectionを実行しないように修正している.

今後は,カード画面上に表示されるカードを現参照カードと呼ぶことにする.現参照カードは三図面(全体図・親族図・部分図)共通でカード選択操作によって指定されるが,↑↓キーないし,カード画面上のスピンボタン(カード番号の差左右に配置)を操作することで選択状態に変化を与えずに移動することができる.つまり,現参照カードと選択カードは独立の状態として管理される.現参照カードは一覧表の最左列をクリックするか,ないし人名カードのカード番号欄にカード番号を記入→ENTERで直接変更することもできる.

カード一覧表の最左列のクリックで現参照カードを切り替えたとき,一覧画面上のカラー表示行が更新されない.⇒CardGridView_CurrentCellChangedでインジケータ移動を処理しているブロックでChangeRowColorを実行するようにした.

一覧表の表示範囲が系図画面上のカードのとき,系図画面上に現参照カードが存在しない場合には,インジケータは消えていなくてはならないのにそうなっていない.人名カード上のスピンボタンでカード移動した場合にはそのような動作になる.カード履歴で移動した場合も一手遅れてそのような状態になる.

図面種別を切り替えたときには現参照カードがレコードに含まれているか否かをチェックしなくてはならない.また,含まれていた場合にも行が変化している可能性がある.以前はKindredMapSubの中でGetNewTableを実行していたが,現行では「図面種別変更では必ず系統並び替えが実行されるのでここでは不要」としているため,この関数内では検査ができない.同様のことは一覧表の表示範囲を切り替えたときにも起こり得るので,GetNewTableの中で検査した方がよい.

GetNewTableではUpdateSelectionを実行しているので,この中で検査できるのではないか?⇒一番確実なのはUpdateIndicatorでチェックすることだろう.いや,UpdateIndicatorの中から実行されるSetCurrentCellでは現参照用カードのレコードが存在しない場合にはインジケータをリセットしているのだが… UpdateSelectionに渡している引数が悪い.BuildNewTableの戻り値を使っているが,間違いだ.

現参照番号を渡すようにした.カード履歴で移動のときには,Z.SelectedRefnumをUpdateSelectionに渡している.SelectedRefnumは検索などのときにも使用される作業変数なので,適切ではない.Currefnumを使うべきだろう.⇒大体整理されたのではないかと思う.

親族呼称図.ZELの全体図で基準ノードの#46 義父(舅)→婿を削除しようとして,NAMEBOX::Disposeで停止した.その後,系統並び替えで多重グラフ2の節点リストが空で停止した.SIMPLEGRAPH:GetHasseDiagramで「基準ノードが空」エラーが起きる.基準ノード以外のカードの削除では特に問題は発生しない.多重グラフ1の連結成分リストには含まれている.

15  #7743 k COMPLIST 7743 {2}[0]<15> <15>CARDLINK:#629 @48妻の祖父→孫娘の婿[0] <15>CARDLINK:#638 @49妻の祖母→孫娘の婿[0]

ただし,このクラスタは親子関係を持っていないため,多重グラフ2には算入されていない.⇒多重グラフ2は親子関係による枝グラフとして生成されているが,親子関係を持っていないノードもグラフに含める必要がある.⇒最初に多重グラフ1の連結成分リストを転記して多重グラフ2の節点リストを構成しておくようにした.これでどんな多系統図でも扱えるようになったのではないか?

image

「カード削除」によって系列優先ノードが削除されることは普通に起こり得るので,OnDeleteCard中はNAMEBOX::Disposeで停止しないとしておくことにする.

同上サンプルの部分図基準ノード=#45 妻→夫の基準ノードを削除した後の動作が悪い.UNDOで戻ったとき系図画面で現参照カードの枠が消えている.他のカードをクリックするとその枠が逆に表示される.⇒UNDOを実行したとき,画面を更新する前に枠を削除していないのだろう.UNDOを実行したときには必ず系統並び替えが実行されるので,その時点でフラグをリセットする必要がある.

いや,それはやっている.どこかで余分な動作が入っているのではないか?⇒TREEVIEW::DrawControlでは冒頭で選択枠を非表示とし,出口で選択枠を再表示しているが,dispselectしか見ていなかった.DispSelectBoxは選択枠と現参照カード枠の両方を処理しているので,dispprimeを見る必要がある.⇒動作するようになった.

一覧画面上で選択操作した場合には,従来のように現参照カードにジャンプできるようにした方がよい.これまではCardBox.GetNewCardでセンタリングするようになっていたのだが,インジケータなどによる移動でもGetNewCardになるので,センタリングする場合としない場合を切り分けなくてはならない.可能だろうか?

DataGridView_MouseUpではSelectionProc()を呼び出しているが,これもどちらの場合も含んでいる.矢印キーによる移動とカード画面のスピンボタンによる移動ではSpinUpDownを呼び出している.この関数の中でもGetNewCardを使っているので,GetNewCardの外でセンタリングするようにすればよいのではないか?

以前はSelectionProcの中でCenteringCardSubを実行していたのだが… CardGridView_CurrentCellChangedの中ではインジケータ列のクリックとそうでない場合の2箇所でGetNewCardを実行している.インジケータ列のクリックでない場合にはセンタリングを実行するようにした.

HOMEキーも予定したような動作になっている.これで選択操作と現参照カードの操作はほぼ完全に整理が付いたのではないかと思う.これと類似した機能として,検索時のカード巡回とカード巡回パネルによる選択領域のカード巡回がある.チェックしておこう.

一覧表とカード画面は巡回パネルと同期しているが,系図画面のジャンプが止まっている.この操作ではGetNewCardは呼び出されていない.代わりにMakeNewCardを実行している.SetSelectCardで「カード巡回パネルのカードを更新」しているが,この中でCenteringCardSubを実行している.なぜ利かないのだろう?

一覧表でカード選択→ カード巡回パネルで「巡回の対象となる(複数の)カードがありません」のエラーが出る.このエラーはZ.SearchCountの場合に発生する.カード巡回の対象はZ.DeleteTableではなく,Z.SearchTableなので,それを転記する必要がある.TakeSearchSelectionでそれをやっているが,現在のところ止めてある.MakeSearchSelectionというその逆関数もある.

mZelkova::mGetSearchListはTakeSearchSelectionと同等のことを実施している.Zelkova1_NodeClickではmZelkova::mGetSelectListから選択カードリストを取得して,mGetSearchListで検索リストに転記している.mGetSelectListの中でつねにmGetSearchListを実行する必要はないと考えられるので,停止しておこう.その代わり,カード巡回_ClickでZ.mGetSearchListを実行するようにしてみた.

これでカード巡回はできるようになったが,スピンボタンの押下で一覧表の選択が落ちてしまった.これはおかしい.⇒SetSelectCardでUpdateSelectionを実行していたところ,「カード巡回では選択領域を変化させない」という理由でUpdateIndicatorに変えたためだ.UpdateSelectionを単独で実行すると単選択になってしまう.

CZelkovaCtrl3::CenteringCardでは引数にカード参照番号が入っているが,実際の動作ではまったく参照されていない.実際には選択カードリストを見ているため,予定したような動作にならないので,ActionCenteringの引数をACTION_CENTERからACTION_HOMEKEYに変更した.CallCenteringMoveではACTION_HOMEKEYのときは現参照カードにジャンプするようになっているので,この方が実情と整合する.

カード巡回パネルが出ているときに選択状態を変えてもテーブルが更新されない.また,一覧表で選択操作を行うとカード巡回パネルが閉じてしまう.⇒上記ではmGetSelectListの中でmGetSearchListを実行しないとしているが,修正を戻して実行するようにした.また,一覧表上の選択操作でもカード巡回パネルを閉じないようにした.

インジケータ列のクリックで選択が落ちる場合がある.⇒特定のカードで落ちているような感じもする.なぜか,#15 五宮で落ちる.かなり不思議だ.⇒以下の条件が成立してCardGridView_CurrentCellChangedから離脱している.

EditRowIndex = CardGridView.CurrentCell.RowIndex

EditRowIndexが14になっている.EditTableFlagを見ていないためだ.

▲カードと連動をオフにするとカード切り替えがオンになるが,パネルを開いたときにカードと連動オフの場合はカード切り替えはオフになったまま.また,カード切り替えボタンを押してもカード画面の内容は更新されず,パネルを閉じて終了してしまう.

▲源氏物語全系譜6.1.ZELの全体図 #1 光源氏でカード番号でソートしようとして,非参照カウントの残留が発生した.EraseTreeViewからNAMEBOX::Dispose→ RetrieveGhostで起きている.なにかの拍子にカード番号の昇順ソートが掛かってしまった.しかも,その前に選択反転のようなことも起きている.

一覧表のインジケータを選択と独立に操作

終端ノードないし孤立ノードを選択して系統並び替えを実行すると,SIMPLEGRAPH::GetHasseDiagramで「基準ノードが空」というエラーが出ていたので,BuildSameGeneMarriageGraphのステージ【4】で「複数の親を持つ終端カードを節点とする自己ループを追加する」としていたところを,「結婚を持たない終端カードを節点とする自己ループを追加する」のように変更した.これにより,すべての有効なカードが重婚クラスタグラフに含まれるようになった.

これで選択操作と図面操作が切り離され,選択状態は図面をどう改変しても変化しないようになったが,厳密に言うとまだそれが残っているところがある.一覧画面とカード画面上でカード移動を実行すると選択は単選択状態に戻ってしまう.現行では①一覧画面・カード画面上でのカードの移動,②系図画面上でのセンタリング,③カード画面に表示されるカードは完全に連動している.選択状態を維持したままカード移動を実行するとしたら,どんな仕様になるのか?考えてみよう.

  1. 一覧画面上のインジケータが移動する
  2. カード画面に表示される主選択カードが変化する
  3. 系図画面はカードの移動によっては変化しない
  4. 系図画面で主選択カードにジャンプするにはHOMEキーを押す

ということになるのではないだろうか?カード検索を実行したときに表示される「カード巡回」パネルはやや上と類似した動作になっている.ただし,検索結果に含まれるカードはすべて選択状態になっているので,①選択されたカードを巡回する,②系図画面ではセンタリングが実行されるという相違点があるが,考え方としては近いものがある.上のような仕様が実装されることになれば,カード巡回パネルの操作でも系図画面は変化しないということになるのではないだろうか?この方が操作的には軽くなり,より使い易くなるのではないかと思う.

一番の問題点は項目1の「一覧画面上のインジケータが移動する」,つまり選択とインジケータの操作を完全に分離可能かどうか?という点にある.まず,この点を確認しておこう.⇒難しいかもしれない.一覧表のクリックとUP/DOWNキーの押下は同じイベントで処理されている.いや,先にキーイベントが発生しているから,切り分けることはできるのではないか?⇒可能だ.その前に,カード移動したときセンタリングしないようにしたときの操作性がどのように変化するかを見ておこう.

センタリングしないというのでよいのではないか?実際,部分図や親族図でカードが画面上に存在しない場合などもある.つまり,カード移動では系図画面は変化しないというのでよいと思う.ただし,カード画面と一覧画面はつねに連動するものとする.

もう一つ問題がある.仮に選択状態を変化させずにカード移動ができるようになったとしても,すべてのカードを巡回しないとそのカードに到達できないのではほとんど意味がない.カード画面ではカード番号を入力→ENTERでそのカードにジャンプできるが,それと同等のことが一覧画面でもできなくてはならない.一覧表の最左列つまり,インジケータが表示されている列のセルをクリックするとそこにジャンプできるようにすることは可能だろうか?

▲カード編集:カード巡回で「巡回の対象となるカードがありません」の表示が出る.一覧画面で複数カードを選択しているのだが…

▲プレビュー画面でズーム倍率を100%に切り替えたら,Zelkova1_MoveControlでAutoPosition.X < 0 Or AutoPosition.Y < 0というエラーが起きた.また,ズーム倍率25%でウィンドウ枠をドラッグしたら何重にも線が重なって画面が壊れた.ここでズームーボタンを押したら,倍率が595%になった.

親族図:直系血族図をカード一覧表:すべてのカードに切り替えて全点で62のところが,124点に増えてしまった.TREEVIEW:CheckSelectListでカウント不一致のエラーが出ている.選択カード数は1でselectflagのカウントはゼロ.

BuildNewTableでは,テーブルを一旦空にした後,再構築しているが,このとき,行の追加によりCurrentCellChangedイベントが発生→ CurrentCell.ColumnIndex = 0→最左列のクリックと誤認してGetNewCardを実行→ MakeNewCard→ 参照番号がゼロであるため,GetNewTable(True)で新しいテーブルが追加されるという動作になっている.⇒CardGridView_CurrentCellChangedでテーブル構築中は無動作で抜けるようにした.

基準ノードの行はシアン色で表示されているが,この行を含む複数行を選択した後,他の行をクリックすると,色が落ちてしまう.⇒しかし,起こる場合と起こらない場合がある.どうも行の並びと関係があるような気がする.⇒背景色設定を共通ルーチン化することで漏れを排除するようにした.⇒解決.

▲親族図と全体図で系統並び替えの基準ノードを共有しているように思われる.これらは独立ということになっていたのではないか?部分図の基準ノードは独立しているようだが… 確かにこの仕様はバランスが悪いような気もするが,実用的にはその方が適切である場合もあり得る.全体図でカードAを基準ノードにしているときに,親族図に移動する目的は,Aの親族図が見たいという場合が多いのではないか?このとき,まったく別のカードの親族図が出ていたとすると混乱する可能性がある.

しかし,現行では系統並び替えによっても選択領域は変化しないから,カードAが選択されていれば,そのまま系統並び替えを実行すればよいということになるのではないか?部分図のように親族図も独立の基準ノードを持つとした方が,仕様的には筋が通っていると思う.また,今回の「選択領域と提示カードの分離」という方向性にも合致している.

ただし,これを実装するにはファイルのフォーマットの変更が必要となるので,右から左という訳にはゆかない.同種の課題として,全体図・親族図・部分図で独立の環境パラメータ(親族種別など)を持つという懸案もある.これも保存ファイルのフォーマットに関わるので,もしやるとすれば同時に実現した方がよい.

この件は一時保留としてもう少し片付けることにしよう.一覧表のインジケータ行とカード画面に表示される提示カード(仮称)は完全に同期するようになったが,ここまで来ると系図画面にも出さないという訳にはゆかなくなる.提示カードは従来仕様の「主選択カード」に類似しているが,選択領域に含まれていないというところが大きな違いだ.

現行では主選択カードの取り出しには2つの方法がある.①系図画面で左ボタンアップ→TREEVIEW::LButtonUpで取得,②カード画面に人名カードを表示する際に,Z.mSetPrimarySelectionでカードの参照番号を送付.どちらの場合も最終的には人名カードが更新されるので,mSetPrimarySelectionがあれば間に合いそうだ.取得した値は,TREEVIEW::selectedcardとselectednameに格納されるので,とりあえず,それを流用することにしよう.

▲主点カードはカード画面上に表示されているカードと一致しなくてはならない.従って,一覧表の表示範囲が系図画面上のカードのとき,系図画面上にそのカードが存在しない場合には,インジケータは消えていなくてはならないのにそうなっていない.人名カード上のスピンボタンでカード移動した場合にはそのような動作になっている.カード履歴で移動した場合でも,一手遅れてそのような状態になっている.

▲親族呼称図.ZELの直系血族図で基準ノードの#46 義父(舅)→婿を削除しようとして,NAMEBOX::Disposeで停止した.その後,系統並び替えで多重グラフ2の節点リストが空で停止した.全体図でも類似の障害が発生する.このケースではSIMPLEGRAPH::GetHasseDiagramで「基準ノードが空」エラーが起きる.基準ノード以外のカードの削除では特に問題は発生しない.

系統並び替えを実行しても選択が落ちない

カード選択はユーザの主体的な行動であり,システム側からユーザに押し付けるものではない.カード選択操作の場面は,①系図画面上の選択,②一覧画面上での選択,③カード画面での移動,④編集コマンドによる選択がある.③ではつねに単選択になるが,それ以外は一般に複数カードの選択が可能だ.①で系図画面上のカードをクリックないし拡張選択した場合はOCXが選択/解除されたカードないし領域をDLL側に通知する.DLL側ではそれに従い,selectcardlist->tableを更新する.

②の場合,アプリ側ではZ.DeleteTableに選択領域を設定して,GCに送り,GCではそれをDLLに伝達する.DLL側ではDeleteTableの内容をTREEVIEW::selectcardlist->tableに転記する.④には全選択/選択反転がある.全選択では「有効なカード」がすべて選択され,選択の反転では「有効なカード」ー「選択されたカード」が選択状態になる.「有効なカード」とは一覧表表示範囲:系図画面上のカードに相当する.カードテーブル上のカード(CARDLINK)はselectcardlist->tableと同期するためのフラグselectflagを持っている.DLL側でselectcardlistの更新を行っている関数には以下がある.

  1. TREEVIEW::putSelectList ←CallPutSelectList
  2. TREEVIEW::selectAll ←CallSelectAll
  3. TREEVIEW::hitSelectNode ←TREEVIEW::LButtonUp
  4. TREEVIEW::selectNode ←TREEVIEW::LButtonUp
  5. TREEVIEW::getSelectList ←CallGetSelectList
  6. TOPOLOGY::RebuildCardList ←UNDOSYSTEM::UndoProcess,UNDOSYSTEM::CommandEnd

getSelectListはputSelectList の逆関数でアプリ側にselectcardlistの内容を返す関数だが,その前にカードテーブルをスキャンしてselectflagオンのカードをselectcardlist->tableに収集してから送付している.RebuildCardList はUNDOシステムで用いられる関数でカードのselectflagからselectcardlist->tableを復元している.系図画面で拡張選択したときの動作を見てみよう.初回だけは系図画面と一覧画面が同期していたが,後が続かない.なぜか?

LbuttonUpからselectcardlistを更新するところまでは問題ない.その後,Zelkova1_NodeClickが起動され,mZelkova::mGetSelectListを呼び出してZ.DeleteTableを更新している.Z.DeleteCountの値も正しい.一覧表の更新はUpdateSelectionで実行している.どうもどこかで選択が落とされている.ただし,Z.DeleteTableの中身は変化していない.

UpdateSelectionの中で落とされている.UpdateIndicatorで単選択に戻されている.動作不良の元凶はUpdateIndicatorだ.インジケータと呼んでいるのは,一覧表の最左列に表示される右矢印を意味している.選択操作に関連するが,インジケータの操作で単選択になってしまうというのはおかしい.UpdateIndicatorを実行しなければ,系図画面と一覧画面の選択状態は完全に同期している.

UpdateIndicatorから呼ばれるSetCurrentCellで単選択に落ちている.「現在のセルを変更すると DataGridView 選択範囲が変更される場合があります」ということのようだ.設定で回避できるのだろうか?現在の設定は以下のようになっている.

.SelectionMode = DataGridViewSelectionMode.FullRowSelect ‘つねに行全体を選択
.MultiSelect = True             ‘複数行の選択を許す
.AllowUserToDeleteRows = False
.EditMode = DataGridViewEditMode.EditOnKeystrokeOrF2

Selection Modes in the Windows Forms DataGridView Control によれば,「Note that changing the value of the CurrentCell property does not alter the current selection」となっているのだが…

UpdateSelectionでは以前は選択領域設定の前にUpdateIndicatorを実行していたのだが,「引数のカード参照番号が選択されていない場合がある@20180830」という理由で現在の位置に移動している.しかし,これでは完全に誤動作してしまうので,修正前の状態に戻すことにする.選択されていない参照番号を指定した場合には余分なカードが選択された状態になり,整合が取れなくなる可能性がある.CurrentCellを非選択にできるかどうかを調べてみよう.

問題なさそうだ.これで要求を満足する動作になった.複数選択動作でまだ一つだけ不十分な点がある.一覧表でインジケータの出ている行と,カード画面に表示されているカード,および系図画面で濃紺で表示されているカードは連動しているが,系図画面上で選択を落とす操作をしたときに濃紺で表示される「主選択カード」が消えてしまう場合がある.一覧表で操作した場合には問題ないように見える.

部分図で複数選択を実行して,getSelectListでCheckSelectListのエラーが起きた.getSelectListではカードテーブルからselectcardlistを作り直している.CheckSelectListでは有効カードのみをカウントしている.getSelectListでも同様処理するようにしてエラーは解消したが,有効でないカードの選択フラグはむしろ積極的に落とす必要がある.今度はTREEVIEW::hitSelectNodeで同様エラーが出た.

上記の修正は間違っている.「選択領域はカードの有効・無効とは無関係」というのがゼルコバの木の仕様だ.ただし,全選択と選択反転は有効カードのみが対象となる.⇒対処した.

図面種別を切り替えると系図画面が無選択状態になってしまう.系図画面の切り替えでは一度選択領域をリセットして,再描画する必要がある.系統並び替えの冒頭で実行されるTREEVIEW::InitTreeViewでsetSelcount(0)が実行されている.図面種別の切り替えでは必ず系統並び替えが必要になるから,ここでリセットされたのでは対処しようがない.GCに問い合わせできれば取得可能だが,上りインタフェースは存在しない.⇒InitTreeViewではsetSelcount(0)を実行しない代わりに,COUPLING::EraseFamilyTreeでリセットするようにした.

▲系統並び替えを実行して,GetHasseDiagramで「基準ノードが空」エラーが発生する.seedはFAMILYTREE::BaseLinkを含む成分リストで多重グラフ2の節点リストで探しているのだが… 通常の手順では発生しない.複数カードを選択し,そのうちの一つをCtrl+クリックで選択解除→ Ctrl+クリックで再選択してから系統並び替えで発生する.その後は図面種別の切り替えなどでも同じ事象が起きるようになる.

グラフをダンプしてみたが,確かに入っていない.ただし,これは上のような「手順」の問題ではなく,クラスタ図自体の問題だ.つまり,現行では終端ノードは世代番号の確定に関係がないという理由で省かれている.これは確かにまずいのではないだろうか?

描画領域サイズオーバーの問題が片付いた

VAIO2に(一昨日)仕掛けてあった渋沢一族の完全木テストの結果がダンプされていたので記録しておこう.所要時間1時間57分となっているが,時計の針は少なくとも一周しているので26時間掛かっている.

包括テストI 完全木テストを完了しました.
ご協力ありがとうございました.

C:\Users\babalabo\Desktop\渋沢一族8.ZEL
サンプル点数: 829 経過時間:01:56:51 検定図面数: 7461面
計算時間:12.52 秒/面 99.81 ms/点 延べ点数: 935925点

描画領域サイズオーバーの問題が片付いた.かなりあちこち調整する必要があった.主な点を挙げてみると,

  1. ZoomListTool_SelectedIndexChanged SendKeys.Send(“{ENTER}”)を廃止し,SendKeys.Send(“{BACKSPACE}”)を実行する
  2. MDIForm_KeyDown Keys.EnterではSetZoomRateを実行し,Keys.BackではResetZoomRateを実行する
  3. SetZoomRate Zelkova1.ZoomSetを引数ZOOM_RESETで呼び出す
  4. ResetZoomRate Zelkova1.ZoomSetを引数ZOOM_NOMSGで呼び出す
  5. CZelkovaCtrl3::ZoomSet CtrlZoomSetの戻り値がERR_ZOOMOVERRANGEのときはActionCenteringを実行する
  6. CtrlZoomSet 引数がZOOM_RESETのときは,TreeView->OVERSIZEをリセット,ZOOM_NOMSGでは保持してZoomSetを実行する
  7. TREEVIEW::CheckDispSizeOver OVERSIZEがオンのときは,「この図面は~以上には拡大できません」の表示を抑制する
  8. TREEVIEW::LimitSizeOver 描画領域サイズオーバーが発生した場合には,OVERSIZEをオンにする
  9. TREEVIEW::Zoom OVERSIZEならERR_ZOOMOVERRANGEを返す
  10. TREEVIEW::ZoomIn,ZoomOut ZoomSetを呼び出す前にOVERSIZEをリセットする

要点は,①エラーコードERR_ZOOMOVERRANGEがアプリ側まで伝達されるように経路を整備(渡せないところではTREEVIEW::OVERSIZEを使う),②警告パネルが重複表示されるのを抑制,③ズーム倍率リストのテキスト変更でリターンキーが押された場合,④ズーム倍率リストのインデックスが変更された場合の動作を(外形的に)統一する.⑤エラーが発生した場合にズームタイマーを確実に止めるなど.コンボボックスのSelectedIndexChangedイベントをキャンセルできないという不都合に対処するために,キーイベントを送ってイベントハンドラで遅延処理するという仕掛けを作り込んだのは2017年頃のようだ.デバッグモードではこの操作が止めてあったため気付かなかった.

系図画面ないし一覧画面上での選択動作にいろいろと不具合がある.選択操作と部分図操作は切っても切れない関係があるので,正しく動いてくれないと甚だ都合が悪い.特に一覧画面上の動作が悪い.まず,最初に一覧画面上に表示されているレコード数をチェックできるようにしておこう.⇒ModeNameChangeの末尾で以下を実行するようにした.

CardTable.Text = TitleName + “ 《” + ModeName + “》” + “ ” + Str(CardTable.CardGridView.Rows.Count) + “点”

これでほとんどカバーできるようだ.数字も合っている.選択されているカードの数も出しておこう.CardGridView_SelectionChangedでModeNameChangeを実行するようにして同期が取れるようになった.

一覧画面上での選択操作は系図画面上の選択されたカードと同期している.また,カード画面に表示される主選択カードも同期している.問題は,系図画面上での操作が一覧画面に反映しないという点だ.カードが1点だけの場合は一覧画面にも反映される.また,選択解除も同期しているが,複数選択になるとまったくダメだ.

しかし,「まったくダメ」という訳でもない.入る場合と入らない場合がある.しかし,ほとんど入るという場合がない.親族図で複数選択して部分図に移動すると一覧画面でも複数選択になる場合がある.ただし,このとき部分図は無選択状態になっている.また,何かの拍子で選択が反転して「訳が分からない状態」になる場合もある.⇒渋沢一族ではサンプルが大き過ぎる.親族呼称図を使うことにしよう.

▲系図画面設定の動作がおかしい.結婚マークを表示する→ 人名枠線を表示するとして結婚点が下枠の高さに表示されてしまう.⇒ただし,この事象は再現しない.また,結婚マークを表示するをオン・オフしても画面に反映されない.

GetHasseDiagramの論理を見直し

岩崎彌次郎系列を選択して部分図に切り替えようとして,SIMPLEGRAPH:GetHasseDiagramで停止した.この関数を呼び出すときの引数seedが空になっている.⇒SIMPLENODE::AddOyakoEdaで枝が生成されていない.⇒「系列分解図の場合は始系列のみ処理する@20171125」となっている.これはかなりまずい.クラスタ図は婚姻と親子関係だけで構成されるので,「系列」は無関係のはずだ.

いや,そういう訳にもゆかない.確定世代番号を得ることがクラスタ図の目的だが,系列間の結婚によってそれが歪められてしまう.かなり厄介な話になってきた.系列分解図の場合は重婚クラスタ検定はパスするというのが現実的であるような気がするが,この問題は棚上げして,部分図の場合はつねに系列分解図オフとすることで逃げることにしよう.

渋沢一族が5つのブロックに分解している事情を解明する手がかりとして,岡部長景の傍系親族図と渋沢栄一の傍系親族図の接点となっている尾高豊作@22の傍系親族図を取ってみた.246人を収容するかなり大きな親族図だ.尾高豊作は尾高 惇忠(藍香)の子どもの尾高次郎と大内ふみの間の子で,尾高家は渋沢一族の中でも渋沢家に次ぐ大きな氏族だ.尾高豊作の配偶者の岡部豊子は岡部長景とは異母兄弟に当たる.

尾高豊作の娘尾高泰子からすると,岡部長発は直系血族,岡部長景は傍系血族に当たるから現行アルゴリズムでもトレース可能なはずなのだが… クラスタ図の枝は親子関係だが,婚姻関係は1個の節点(クラスタ)として集約されているので,尾高豊作→ 岡部長景のパスが検出できないということは考え辛い.SIMPLEGRAPH::GetHasseDiagramの論理を見直してみよう.

確かに,現行では到達できないパスが発生するのは避けられないように思われる.現行アルゴリズムは以下のようなフローになっている.

  1. 起点から上流/下流検定を実施する
  2. すべての先祖ノードから下流検定を実施する
  3. すべての末裔ノードから上流検定を実施する

この論理では傍系に到達できない可能性がある.書き直してみよう.先祖ノードからの下流検定と末裔ノードからの上流検定を一体化して,下流検定→ 上流検定→ 下流検定を反復する必要がある.⇒解決した.

MARGBOX::CheckMargBoxChangedで@20渋沢市郎右衛門の先祖リンク不良が反復発生するのはなぜか?⇒該当する結婚枠が複数存在するためだ.⇒ダンプを抑制した.

現行では重婚クラスタ検定の入口で多重カードをカウントし,多重カードゼロの場合は重婚クラスタ図を生成しないようになっているが,つねに生成するようにすべきではないか?⇒多重カードゼロのサンプルは比較的単純なものが多いのでクラスタ検定を実施してもそれほど負荷が掛かる訳ではないのでやった方がよいと思う.やらなくても弊害はほとんどないとは思われるが,やっておいた方が安全だ.

画面サイズオーバーの問題が出ているので調べておこう.

系列分解図で栄一の系列を選択→新規部分図で部分図に切り替えようとして,TREEVIEW:CheckDispSizeOverのエラーになった.系列分解図でズーム倍率46%のとき,尾高磯五郎系列のカードを拡張選択して部分図:新規部分図で「現在の選択範囲を部分図に設定」した後,「部分図モードに切り替えますか?」→「はい」を押して,TREEVIEW:Zoom→ SetOuterFrameでエラーが発生する.OuterFrameには系図外枠が入っているが,幅が上限の32000を超えている.

しかし,選択された部分図の領域はそれほど大きなものではないので,全体図の領域と間違えているものと思われる.「部分図に設定」しただけでは描画領域は確保されず,部分図モードに切り替えて系統並び替えが実行されて初めて部分図の領域が確定するので,ZoomSetが掛かるタイミングが早過ぎる.ズーム倍率は描画に先立って切り替えておく必要があるが,適用される領域が間違っている(まだ計算されていない).

TREEVIEW::CheckDispSizeOverはGetTitlePositionから呼び出されているが,GetTitlePositionの呼び元は2つある.①CallGetTitlePositionと②SetOuterFrameだ.前者はという外部関数から呼び出されているが,後者はLButtonUp, SetDispParm, SetTitleBox, UpdateDiagram, Zoomなどいろいろなところから呼び出されている.

TREEVIEW::ZoomSetにはapplyという引数があって,Zoomを実行するか否かを選択できるようになっている.これをオフにして呼び出せばよいのではないか?TREEVIEW::ZoomSetは,CtrlZoomSet, MakeLeastWindow, ZoomIn, ZoomOutから呼び出されている.今の場合は,CtrlZoomSetからの呼び出しだが,この関数ではモードがZOOM_RESETとZOOM_KINDREDの場合にのみ,ZoomSetを呼び出している.ZOOM_KINDREDは今の場合のような「図面種別の切り替えに伴うズーム倍率の変更」だからapplyオフでよい.ZOOM_RESETはVBのSetZoomRateで呼び出されるケースだが,これもオフでよいのではないかと思う.⇒これでこの問題は一応片付いたのではないかと思う.

しかし,今度はTRIBELIST::ShiftDirectAbsoluteでエラーが出るようになってしまった.先祖ノードのシフトを実行して,確定世代番号と人名枠の物理世代番号の不一致が起きている.下図は尾高磯五郎系列の「一部」を部分図としたもので,4系統に分離している.

image

関係の一部がカットされたために系列がバラバラになるのはやむを得ないというより,当然だが,出力がかなりおかしい.それぞれ独立系統なので先祖ノードが物理世代ゼロに配置されるのは当然だが,下流系との間にギャップが出来てしまっている.各カードに表示された確定世代番号を見ると,画面上の垂直位置と一致しているので,確定世代番号に従っていると言える.カード数は全76点だ.

GetHasseDiagramで距離数を確定世代番号に変換するところで失敗しているのだろう.系統ごとに基準点が異なるので一括して処理したのでは正しい値にならない.どうすればよいか?SIMPLEGRAPH:GetHasseDiagramの中で系統ごとに処理が閉じるようにしなくてはならないだろう.この修正は結構クリティカルなので,一度バックアップを取って最近の修正をフィックスしてから着手することにしよう.

  1. RetrieveGhostではCHAOTICSTATEまではノーマル処理する@20210301 1件
  2. CHAOTICSTATEまではつねにノーマル処理する@20210302 12箇所
  3. NOMULTICARDを廃止する@20210303 12箇所
  4. 仮修正 1箇所,暫定 2箇所,#if 0 4箇所

SIMPLENODEにはすでに使われなくなったdownwardとupwardという2つの変数があるのでこれらを廃止して,代わりにstrain(系統)という変数を導入することにする.⇒実装した.動作している.

image

渋沢一族の系列分解図は横幅が上限を超えてしまうため,「92.2%以上には拡大できない」が,その動作があまりよくない.ズーム倍率リストで100%以上を指定しても拡大されないが,警告も出ない上,画面が崩れる場合がある.倍率表示は100%,200%などになっている.ズームトグルボタンで100%に戻そうとすると初めてメッセージが出て92%に自動調整されるが,画面は左端に移動してしまう.ズームインボタンで拡大しようとしたときの動作はトグルボタンの場合と同じだ.⇒ズームリストツールを操作したときのコマンドが,ZOOM_RESETだ.

しかし,ズームトグルの場合のように自動調整は実行されず,メッセージも出ない.ざっと見た限りではトグルとリストツールで動作には差異がないように見える.どちらもTREEVIEW::Zoomを呼び出しているだけだ.VB側の動作もZView.Zelkova1.ZoomSetを実行した後,UpdateZoomRateしているだけだ.どこかで書き戻されているようだ.⇒これは結構難しい.ズーム倍率リストのSelectedIndexChangedイベントの中でテキストを書き換えても上書きされてしまう.ComboBoxではe.Cancelのような方法が使えない.