Table View(テーブルビュー)を使う(3) [AppleScript辞書はつくれるか?]
Table View(3) -選択した部分を取得する-
前回の続きになります。
TableViewで表示されている項目を一つ削除しようと思います。
ここでは、Array Controllerのデータを操作するタイプのTableViewのデータの管理方法のを記載していますが、ほかに直接管理タイプもあります。そちらは、ちょっと簡単ではないのでまた別の機会にご紹介します。
前の記事で theData にレコード情報({data1:通し番号, data2:ファイル名})のリスト({レコード1.レコード2. … レコードn})を使っていることを書きましたが、今回はこのリストから削除するレコードを外して、TheDataへ戻す方法を書いていきます。
単純にselectionIndex()を使って選ばれた部分の通し番号(index)のレコードデータを削除すれば良いと思います。(ここで前の記事で書いた『取得される数字が1からではなく0から始まる』ということに注意してください)
on action2_(sender)
tell ArrayController to set theSelect to selectionIndex()
set getData to theData
(* 削除するための準備 *)
set getData to {{}} & getData & {{}} --|前後にデータを追加してthru処理でのエラーを回避します|
set DeleteIndex to theSelect + 1 + 1 --|theSelectに、Indexとの差分を加算 + 前行での空データ分を加算|
set getData1 to item 1 thru (DeleteIndex -1) of getData --|削除する行の前までを取得|
set getData2 to item (DeleteIndex +1) thru -1 of getData --|削除する行の後ろから最後まで取得|
set getData to item 2 thru -2 of (getData1 & getData2) --|2つをまとめて準備で加えた前後の空データを省きます|
set my theData to getData --|TextViewへ返します|
set ans to "データの" & (theSelect +1) & "行目を削除しました"
textField1's setStringValue_(ans)
end action2_
『set getData to {{}} & getData & {{}} 』の意味は、thruでItemを取得する際に1つ目のアイテムまたは最終アイテムを取得するときに出るエラーを回避するために使っています。
1行目で言えば
item 1 thru 0 of … となって存在しないデータを取得しようとしてしまいエラーになってしまうためです。
ですから、最初に追加して1つを増やし、最後に1つを消して反映先に渡せば問題が回避できます。この一手間がプログラム入力をいろいろ捗らせますね。
あとは、getData1で削除する前までのアイテムと、getData2後ろからのアイテムを取得しています。
削除するためのアクションを実行するためのボタンを増やします。
リンク接続も忘れずに。
前回記事で触れなかったヘッダー(Header)も記入しておきましょう。(後で触れる問題への伏線です)
では『ビルド&RUN』してみましょう。
そして、action2を実行するための『削除』ボタンをクリックすると・・・
削除されましたね。
さて、ここからは、ヘッダー(Header)の扱いの問題を書いていこうとおもいます。(伏線回収)
先ほど文字を入力したヘッダーはいろいろ悪さをしてくれます。(いや、何もコードを入力しなくても表示した内容をソートをしてくれる優れものなのですけどね)
例えば、ヘッダーをクリックして表示される順番を変更して表示してみましょう。
順番が変わりましたね。
ではこの状態で、2行目を削除してみましょう。まず2行目を選んで…
『削除』
ふぁっ?
なぜか選んでいる行と違う行が消えてしまいました。
なぜ?と思うでしょうが。これは、Array Controllerのデータを利用した行データ削除で起こる問題です。
問題というか、Array Controllerで受け渡しをしたデータを表示するときだけソートしてるので、いえばArray Controllerが知らないことをやってしまっているわけです。この辺りは、本当ならTableViewを直接扱うDelete rowでも使えばできるのでしょうが、今回は使いません。
写真では13番の行を指定していますが、selectionIndex()では、上から2行目(index 1)と取得してしまいます。Array Controllerでは、表示だけでソートされてるなんて知りませんから、2個目(index 1 +1を加算)をどうにかしようとしてしまいます。
状況によっては、1列目(Contents No)でソートしたり、2列目(Name)でソートしたりしますから、それを反映してソートするとか考えなければいけません。
今回は、印刷業界で使われている『隠しノンブル』という技術を借用したいと思います。
隠しノンブルとは?
普通、本を見てると端にページ番号が表示されていると思います。でもこれは本の最初の方にに目次があったり、口絵があったり、織りこみポスターが入っていたりすると、そこはカウントせず本文が始まるところから1、2…とカウントをする本が時々あります。でも、印刷作業者はそのカウントしていないページも含んで作業をしないと本になりませんから、表記されない仮の番号である通しノンブルをページごとに割り振ることをします。これで管理をするんですね。
この技術を使っていきます。
前回記事で記入して今回流用した applicationWillFinishLaunching_(aNotification) の部分を変更したいと思います。
on applicationWillFinishLaunching_(aNotification)
(* 適当なリストがなかったのでシステムのサウンド名を使いました。 *)
tell application "Finder"
set objList to name of (every item of folder (("/System/Library/Sounds" as POSIX file) astext))
end tell
set testData to {}
repeat with i from 1 to (count of objList)
set testData to testData & {{indexNo: i, data1: i, data2: (item i of objList)}}
end repeat
set my theData to testData
end applicationWillFinishLaunching_
変更する部分は黄色い部分です。
それぞれのレコードにIndexNoという項目を増やしています。
あれ?でも、data1でも同じことしてない?と思うでしょうが、これは先ほど説明した『表示されている側のノンブル』になり、indexNoは隠しノンブルとして使うためです。
でも、ここで増やすと、TableViewでも表示されてしまうのでは? と思うかもしれませんが、ここを表示するためのリンクをしていないのでデータはあるけど、持ち出される場所がない。つまり隠れてしまうわけです。
次に、action2_(sender) をそのノンブルに沿うように書き換えます。
on action2_(sender)
--tell ArrayController to set theSelect to selectionIndex() --|削除|
tell ArrayController to set theSelect to (indexNo of selectedObjects()) as integer
set getData to theData
(* 削除するための準備 *)
set getData to {{}} & getData & {{}}
set DeleteIndex to theSelect + 0 + 1 --|theSelectに、Indexとの差分を加算 + 前行での空データ分を加算|
set getData1 to item 1 thru (DeleteIndex -1) of getData
set getData2 to item (DeleteIndex +1) thru -1 of getData
set getData to item 2 thru -2 of (getData1 & getData2)
repeat with i from 1 to (count of getData)
set indexNo of item i of getData to i --|indexNoを揃え直します|
end repeat
set my theData to getData
set ans to "データの" & (theSelect +1) & "行目を削除しました"
textField1's setStringValue_(ans)
end action2_
では『ビルド&RUN』してみましょう。
2行目を選択して
ちゃんと消えましたね。
何か理不尽ですが、今回はここまで。
コメント 0