Tcl/Tk」カテゴリーアーカイブ

TkTableのバインディングを修正した

TkTableはdllで配布されていますが、ヘルプに説明のあるデフォルトのバインディングはlib/Tktable2.9/tkTable.tclに書かれているようです。
このファイルは特にデモアプリなどで使われているわけではなく、単にカスタマイズする人のために内部の実装を見えるようにしたものだと思われます。

TkTableはオプションで-selectmode extendedを指定することでドラッグによる範囲選択ができるようになるのですが、セル領域とタイトルセル領域にまたがってドラッグした場合、選択領域がばらばらになってしまうという問題がありました。

最新の2.10に添付されたtkTable.tclも全く変わってなかったので、修正してみました。ただ、過去の選択部分だけをクリアするような処理を、全域クリアに変えてしまったので、パフォーマンス的には問題ありの可能性もあります。ためしに3000行×50列とかでやってみたところでは全く問題ありませんでした。
 

--- C:/Tcl/lib/Tktable2.9/tkTable.tcl	Tue Aug 25 20:01:59 2009
+++ C:/devel/tcl/tktable/tkTable.tcl	Fri Aug 28 18:59:51 2009
@@ -433,26 +433,54 @@
 	    if {[catch {$w index anchor}]} { return }
 	    scan $Priv(tablePrev) %d,%d r c
 	    scan $el %d,%d elr elc
-	    if {[$w tag includes title $el]} {
-		if {$r < [$w cget -titlerows]+[$w cget -roworigin]} {
-		    ## We're in a column header
-		    if {$c < [$w cget -titlecols]+[$w cget -colorigin]} {
-			## We're in the topleft title area
-			$w selection clear anchor end
-		    } else {
-			$w selection clear anchor [$w index end row],$c
-		    }
-		    $w selection set anchor [$w index end row],$elc
-		} else {
-		    ## We're in a row header
-		    $w selection clear anchor $r,[$w index end col]
-		    $w selection set anchor $elr,[$w index end col]
+
+	    set titlerowend [expr {[$w cget -titlerows]+[$w cget -roworigin]}]
+		set titlecolend [expr {[$w cget -titlecols]+[$w cget -colorigin]}]
+	    if {$r != $elr} {
+			if {$r < $titlerowend} {
+				if {$elr >= $titlerowend && $r >= $titlerowend} {
+					set elr $r; # turn aside while selecting title row area
+				}
+			} else {
+				if {$elr < $titlerowend && $r < $titlerowend && $elc >= $titlecolend} {
+					set elr $r; # turn aside while selecting non-title row area
+				}
+			}
 		}
+		if {$c != $elc} {
+		    if {$c < $titlecolend} {
+				if {$elc >= $titlecolend && $c >= $titlecolend} {
+					set elc $c; # turn aside while selecting title col area
+				}
+			} else {
+				if {$elc < $titlecolend && $c < $titlecolend && $elr >= $titlerowend} {
+					set elc $c; # turn aside while selecting non-title col area
+				}
+			}
+		}
+		$w selection clear all
+	    if {[$w tag includes title $r,$c]} {
+			if {$r < $titlerowend} {
+			    if {$c < $titlecolend} {
+					## We're in the topleft title area
+					if {$elc >= $titlecolend} {
+					    $w selection set anchor [$w index end row],$elc
+					} else {
+					    $w selection set anchor $elr,[$w index end col]
+					}
+			    } else {
+				    ## We're in a column header
+				    $w selection set anchor [$w index end row],$elc
+			    }
+			} else {
+			    ## We're in a row header
+			    $w selection set anchor $elr,[$w index end col]
+			}
+		    set Priv(tablePrev) $elr,$elc
 	    } else {
-		$w selection clear anchor $Priv(tablePrev)
-		$w selection set anchor $el
+			$w selection set anchor $el
+		    set Priv(tablePrev) $r,$c
 	    }
-	    set Priv(tablePrev) $el
 	}
     }
 }

Tcl/TkからC#へ

大学でC++に挫折して、プログラマはあきらめていた私はサークルのホームページでPerl/CGIを使ったのをきっかけに再びプログラミングに手を染めることになりました。

それでも仕事で使えるレベルではないだろうと、会社に入った時点ではプログラマになることは断っていたのですが、会社のCRM立ち上げに携わった後に部署がなくなり、開発部にまわされました。

最初にやったのがカメラのPTZ制御プログラムにPELCO-Dプロトコルを追加するというC++の小さな案件でした。それはそれっきりで、次にやったのがTcl/Tkのタッチパネル式のGUIアプリケーションをベースにした開発案件でした。それ以来、3年ほどWindowsアプリケーションをTcl/Tkで作ることになりました。

Tclの自由度は高く、XOTclなどでオブジェクト指向言語のようにも使えます。C#のクラスはプロパティやメソッド以外にイベントというメンバを持つことができるのですが、これだってTclからすればさして特別な機能ではありません(コンテキストのキャプチャは確かに難しいですが)。Ruby on RailsのActiveRecordのようにスキーマを自動的にマッピングする機能はType-safeな方法では実現できないので、C#には同様のライブラリは存在しません(全てを文字列として扱えばよいだけなので、不可能というわけではないです。誰もやらないというだけで)が、Tcl/Tkでコンセプトを真似た簡易版を作って使っています。

しかし、Tcl/Tkの言語本体はそこそこのスピードで進化していくものの、ライブラリ群は放置されてるものが多いです。また、2002年くらいを境に日本語の書籍の発行は途絶えています。オブジェクト指向拡張はあるものの、Rubyみたいに自由度の高いXOTclにはActiveTclのIDEやデバッガが対応していません。

Tclは世間のうわさに反して優れた言語だと思うし、そこそこライブラリも充実してはいるのですが、やはり完璧なアプリを作るに当たって、いろいろと問題があるのは否めません。

BLT Toolkitはすばらしい拡張ライブラリですが、Tcl/Tkの最新版に対応していません。stubに対応すべくGeorgeさんががんばって更新しているようですが、依然完成のめどが立たない状況が続いてます。

ほかにも結構重要なライブラリがちょっとしたバグを残したまま放置された状態です(TclUDP, Tktableとか) 。

teapot化されたライブラリをEXEにラップするにはTclAppをバージョンアップしないといけないし。

新規開発に関しては既にTcl/Tkをあきらめて、C#を採用しています。Tclの自由度に比べれば堅苦しさは否めませんが、.NET Frameworkなら高品質なGUIが開発できるので、安心してお客さんに見せられます。

Tcl/Tkには印刷ダイアログを表示する機能がありません。DataGridView並みに高度なGUIがありません。TkTableやTablelistがあるじゃないか、というかもしれませんが、これらはDataGridViewに比べて非常にプリミティブです。

大学の研究室や社内で使うならまだしも、簡単にGUIを作れるというのは、現代においてもはや売り文句にならない気がします。

C#などのGUIを生かしつつTclの既存アプリを再利用することはできないのでしょうか?これについてはいろいろと調べてきましたが、なかなか有効な手段は見つかりません。WindowsであればCOMの仕組みを使うことで何とかいけるみたいな話(optcl)はありますが、果たして実際にやった人はいるのでしょうか?

エクスポート関数はともかく、引数の型が構造体だったりして、構造体のメンバがさらに構造体だったりしたら、どうするの?とか。

C++の方が相性はいいだろう。MFC DataGridというのが使えたらいいけど、クラスのインポートってできるの?とか。

TclBridgeというのは?高いなあ。ちゃんとメンテされてるの?

Eagleは?Tclの再実装?うーんそういうことじゃないんだよなあ。

じゃあ何ができたらいいのでしょう?

ネイティブのTclに.NETのクラスライブラリをインポートして、publicなクラスや構造体を自由に操作したい。これだ!

私にCの知識と遊んでいても給料払ってくれる社長がいたら多少貢献できると思うのだけど。

・・・いや、無理。私では力不足です。

こうしてネットのところどころでこういうボヤキを書いているのは誰かが作ってくれるかもとちょっと期待してるからなんですが、まあ、そんな都合よくはいかないよな。。。日本語だから外人読めないし。