Menu

Skip to content
AppleScriptの穴
  • Home
  • Products
  • Books
  • Docs
  • Events
  • Forum
  • About This Blog
  • License
  • 仕事依頼

AppleScriptの穴

Useful & Practical AppleScript archive. Click '★Click Here to Open This Script' Link to download each AppleScript

アラートダイアログ上にTable Viewを表示 v8_ソート、並び替え、複数選択

Posted on 12月 25, 2019 by Takaaki Naganoya

アラートダイアログ上にTable Viewを表示するGUI部品を提供するAppleScriptです。Edama2さんから投稿していただいたものです。

箱庭テーブルビューシリーズは、macOS標準装備の「choose from list」コマンドでは選択肢が増えたときに使いにくいので、その代替品としてTable Viewを用いたポップアップしない単項目の選択UIを実装したものでした。


▲最初のバージョン。みなぎる使い捨て感

それが途中から「Myriad Tablesが使えない場面(Framework入りの高機能ライブラリのため、利用できないケースが発生)に使う使い捨て部品」に進化。

コードサイズの投げやりなまでの小ささと、いつもどおりのプレーンな読み味から改造のためのベースキットとして活用されまくり、派生品や亜種が内外でいろいろ発生しています(きっと知らないところで改変版が作られているはず)。

sdefをつけてライブラリ化したり、色付きダイアログなどいろいろキワモノが派生しましたが、実用性を考慮して半透明ウィンドウではなく通常ウィンドウとして表示する方向に変わりつつあります。

Version Author Date Description
v1 Piyomaru 2019/2/14 For choose from list without popup menu. One field selection UI.
v2 Piyomaru 2019/2/14
v3 Piyomaru 2019/2/14
v4 Piyomaru 2019/7/11 Table user interface for item selection
v5_e KniazidisR 2019/11/2 Separate display dialog stage into making and displaying
v5_m Piyomaru 2019/12/23 Filtering by multiple field
v6 Piyomaru 2019/12/24 Search Field Added
v7 Edama2 2019/12/240 Vertical & horizontal resizing
v8 Edama2 2019/12/25 Record sorting & Field re-ordering

以下、v8についてのedama2さんからの説明文です。

コラムのヘッダのクリックでテーブルのソート
ドラッグ&ドロップによる行の並び替え
行の複数選択

ができるようになりましたが、ヘッダのソート状態のときにD&Dの並び替えはできません。
飛び飛びに複数行選択しても並び替えできますが、たまにズレている気がします...(汗)

ArrayControllerを使用したのが機能過剰と思われたかもしれませんが、まずXCode上で一度組んだものを逆移植しているのでそんなに深い意味はないです。
でもソート方法を試行錯誤して調べていたら、Cocoa bindingをコーディングから設定できることがわかった(よく考えれば当たり前ですが)のが、何か壁を一枚破った気がしました。

Cocoa bindingがプログラムから動的に実行できることは、調査して知っていましたが、実際にAppleScriptのコードとして記述されたものは見たことがありませんでした(Mac Scripterのフォーラムを漁ると出てくるのかも?)。

### 表示内容をNSArrayControllerにバインディング
bind_toObject_withKeyPath_options_(current application’s NSValueBinding, my _data_source, "arrangedObjects." & aTitle, missing value)

ここの部分の記述は、クリスマスプレゼントとして楽しませていただきます。Cocoa Bindingなんて、Xcode上でGUI部品とイベント受信部分のハンドラとの接続をただ漫然とヒモでつなぐ作業をしていただけだったので、Cocoa Binding Referenceなんてはじめて細部にわたって眺めましたわー。


▲起動状態。フィールドの横サイズそろえ、レコード数により表UIの縦サイズが調整されている


▲Specsフィールドを中央に持ってきた。ちゃんとUIが細かいアニメーション動作を行う


▲Priceフィールドを先頭に移動させてみた


▲Priceでソートさせてみた


▲Specsでソートさせてみた


▲選択行をドラッグ&ドロップで移動。複数行も移動可能。ただし、フィールド指定のソート状態を有効にすると行移動が効かないという


▲Commandキーを押しながら複数行選択


▲ドラッグ&ドロップで移動


▲移動後

AppleScript名:アラートダイアログ上にTable Viewを表示 v8_ソート、並び替え、複数選択.scpt
on run
  
  
set aTableList to {}
  
set aTableList’s end to {|Name|:"MacBook Air", Price:"119,800円", Specs:"1.6GHzデュアルコアIntel Core i5(Turbo Boost使用時最大3.6GHz)、4MB L3キャッシュ"}
  
set aTableList’s end to {|Name|:"MacBook Pro 13", Price:"139,800円", Specs:"1.4GHzクアッドコアIntel Core i5(Turbo Boost使用時最大3.9GHz)、128MB eDRAM"}
  
set aTableList’s end to {|Name|:"MacBook Pro 15", Price:"258,800円", Specs:"2.6GHz 6コアIntel Core i7(Turbo Boost使用時最大4.5GHz)、12MB共有L3キャッシュ"}
  
set aTableList’s end to {|Name|:"Mac mini", Price:"122,800円", Specs:"3.0GHz 6コアIntel Core i5 Turbo Boost使用時最大4.1GHz 9MB共有L3キャッシュ"}
  
set aTableList’s end to {|Name|:"iMac 21.5", Price:"120,800円", Specs:"2.3GHzデュアルコアIntel Core i5(Turbo Boost使用時最大3.6GHz)"}
  
set aTableList’s end to {|Name|:"iMac 4K 21.5", Price:"142,800円", Specs:"3.6GHzクアッドコアIntel Core i3"}
  
set aTableList’s end to {|Name|:"iMac 5K 27", Price:"198,800円", Specs:"3.0GHz 6コア Intel Core i5(Turbo Boost使用時最大4.1GHz)"}
  
set optionRec to {aTableList:aTableList}
  
set optionRec to optionRec & {aSortOrder:{column1:"Name", column2:"Price", column3:"Specs"}}
  
  
set aMainMes to "項目の選択"
  
set aSubMes to "適切なものを以下からえらんでください"
  
set dateObj to my chooseData(aMainMes, aSubMes, optionRec)
end run

# アラートダイアログでtableviewを表示
on chooseData(aMainMes, aSubMes, optionRec)
  script MyDialog
    property parent : AppleScript
    
use AppleScript
    
use scripting additions
    
use framework "Foundation"
    
property _retrieve_data : missing value
    
on make
      set aClass to me
      
script
        property parent : aClass
      end script
    end make
    
## ダイアログの呼び出し
    
on call(aMainMes, aSubMes, optionRec)
      set paramObj to {myMessage:aMainMes, mySubMessage:aSubMes, myOption:optionRec}
      
parent’s performSelectorOnMainThread:"raize:" withObject:paramObj waitUntilDone:true
      
if (my _retrieve_data) is missing value then error number -128
      
return (my _retrieve_data)
    end call
    
## ダイアログの生成
    
on raize:paramObj
      ###
      
set mesText to paramObj’s myMessage
      
set infoText to paramObj’s mySubMessage
      
set paramObj to paramObj’s myOption
      
### set up view
      
set {theView, makeObj} to my makeContentView(paramObj)
      
### set up alert
      
tell current application’s NSAlert’s new()
        setMessageText_(mesText)
        
setInformativeText_(infoText)
        
addButtonWithTitle_("OK")
        
addButtonWithTitle_("Cancel")
        
setAccessoryView_(theView)
        
tell |window|()
          setInitialFirstResponder_(theView)
        end tell
        
#### show alert in modal loop
        
if runModal() is (current application’s NSAlertSecondButtonReturn) then return
      end tell
      
### retrieve date
      
my retrieveData(makeObj)
    end raize:
    
    
## ContentView を作成
    
property _data_source : missing value
    
property _data_type : (current date) as text –do shell script "uuidgen" –>ユニークな文字列ならなんでもいい?
    
on makeContentView(paramObj)
      ## 準備
      
set aList to (paramObj’s aTableList) as list
      
set keyRec to (paramObj’s aSortOrder) as record
      
set keyDict to (current application’s NSDictionary’s dictionaryWithDictionary:keyRec)
      
      
set my _data_source to current application’s NSArrayController’s new()
      
repeat with anItem in aList
        set aDict to (current application’s NSDictionary’s dictionaryWithDictionary:anItem)
        ((
my _data_source)’s addObject:aDict)
      end repeat
      (
my _data_source)’s setSelectionIndex:0
      
      
## NSTableView
      
tell current application’s NSTableView’s alloc()
        tell initWithFrame_(current application’s CGRectZero)
          setAllowsEmptySelection_(false)
          
setAllowsMultipleSelection_(true)
          
setDataSource_(me)
          
setDelegate_(me)
          
setDoubleAction_("doubleAction:")
          
setGridStyleMask_(current application’s NSTableViewSolidVerticalGridLineMask)
          
setSelectionHighlightStyle_(current application’s NSTableViewSelectionHighlightStyleRegular)
          
setTarget_(me)
          
setUsesAlternatingRowBackgroundColors_(true)
          
          
registerForDraggedTypes_({my _data_type})
          
setDraggingSourceOperationMask_forLocal_(current application’s NSDragOperationCopy, false)
          
          
set thisRowHeight to rowHeight() as integer
          
set aTableObj to it
        end tell
      end tell
      
      
## NSTableColumn
      
### Columnの並び順を指定する
      
set viewWidth to 0
      
set columnsCount to keyDict’s |count|()
      
repeat with colNum from 1 to columnsCount
        
        
set keyName to "column" & colNum as text
        
set aTitle to (keyDict’s objectForKey:keyName)
        
        
tell (current application’s NSTableColumn’s alloc()’s initWithIdentifier:(colNum as text))
          tell headerCell()
            setStringValue_(aTitle)
            
set thisHeaderHeight to cellSize()’s height
          end tell
          
          
### ソートの設定
          
set sortDescriptor to (current application’s NSSortDescriptor’s sortDescriptorWithKey:aTitle ascending:true selector:"compare:")
          
setSortDescriptorPrototype_(sortDescriptor)
          
          
### 表示内容をNSArrayControllerにバインディング
          
bind_toObject_withKeyPath_options_(current application’s NSValueBinding, my _data_source, "arrangedObjects." & aTitle, missing value)
          
          
set aTableColumn to it
        end tell
        
        
### Columnの横幅を調整
        
tell aTableObj
          addTableColumn_(aTableColumn)
          
–reloadData()
          
set colWidthMax to 0
          
set rowCount to numberOfRows()
          
          
repeat with rowNum from 1 to rowCount
            tell preparedCellAtColumn_row_(colNum – 1, rowNum – 1)
              set thisWidthSize to cellSize()’s width
              
–log result
              
if thisWidthSize is greater than or equal to colWidthMax then set colWidthMax to thisWidthSize
            end tell
          end repeat
        end tell
        
–log colWidthMax
        
        
set colWidthMax to colWidthMax + 5 –> 5は余白
        
tell aTableColumn
          setWidth_(colWidthMax)
        end tell
        
        
set viewWidth to viewWidth + colWidthMax
      end repeat
      
      
## NSScrollView
      
### Viewの高さを計算
      
set viewHeight to (thisRowHeight + 2) * rowCount + thisHeaderHeight –> 2を足さないと高さが合わない
      
set vSize to current application’s NSMakeRect(0, 0, viewWidth + 10, viewHeight) –> 10を足すといい感じの横幅になる
      
      
### Viewを作成
      
tell current application’s NSScrollView’s alloc()
        tell initWithFrame_(vSize)
          setBorderType_(current application’s NSBezelBorder)
          
setDocumentView_(aTableObj)
          
–setHasHorizontalScroller_(true)
          
–setHasVerticalScroller_(true)
          
set aScroll to it
        end tell
      end tell
      
      
return {aScroll, aTableObj}
    end makeContentView
    
    
## retrieve date
    
on retrieveData(aTableObj)
      set aIndexSet to aTableObj’s selectedRowIndexes()
      
set my _retrieve_data to ((my _data_source)’s arrangedObjects()’s objectsAtIndexes:aIndexSet) as list –setSelectionIndexes:aIndexSet
      
log result
    end retrieveData
    
    
    
# NSTableViewDatasource
    
on numberOfRowsInTableView:aTableView
      –log "numberOfRowsInTableView:"
      
return (my _data_source)’s content()’s |count|()
    end numberOfRowsInTableView:
    
# NSTableViewDelegate
    
on tableView:aTableView objectValueForTableColumn:aColumn row:aRow
    
end tableView:objectValueForTableColumn:row:
    
# テーブル内のセルが編集できるか
    
on tableView:aTableView shouldEditTableColumn:aColumn row:aRow
      return false
    end tableView:shouldEditTableColumn:row:
    
# テーブル内をダブルクリックしたらOKボタンを押す
    
on doubleAction:sender
      –log "doubleAction"
      
–log sender’s |className|() as text
      
## ヘッダをクリックした時は何もしない
      
if (sender’s clickedRow()) is -1 then return
      
      
set theEvent to current application’s NSEvent’s ¬
        keyEventWithType:(current application’s NSEventTypeKeyDown) ¬
          location:(current application’s NSZeroPoint) ¬
          
modifierFlags:0 ¬
          
timestamp:0.0 ¬
          
windowNumber:(sender’s |window|()’s windowNumber()) ¬
          
context:(current application’s NSGraphicsContext’s currentContext()) ¬
          
|characters|:return ¬
          
charactersIgnoringModifiers:(missing value) ¬
          
isARepeat:false ¬
          
keyCode:0
      current application’s NSApp’s postEvent:theEvent atStart:(not false)
    end doubleAction:
    
    
# Drag Operation Method
    
## ドラッグを開始(ペーストボードに書き込む)
    
on tableView:aTableView writeRowsWithIndexes:rowIndexes toPasteboard:pboard
      –log "writeRowsWithIndexes"
      
set aData to current application’s NSKeyedArchiver’s archivedDataWithRootObject:rowIndexes
      
pboard’s declareTypes:{my _data_type} owner:(missing value)
      
pboard’s setData:aData forType:(my _data_type)
      
return true
    end tableView:writeRowsWithIndexes:toPasteboard:
    
## ドラッグ途中
    
on tableView:aTableView validateDrop:info proposedRow:row proposedDropOperation:operation
      –log "validateDrop"
      
### 列の間にドラッグ
      
if (operation is current application’s NSTableViewDropAbove) then
        return current application’s NSDragOperationMove
      end if
      
### 項目の上にドラッグ
      
set aTypes to info’s draggingPasteboard’s types()
      
if (aTypes’s containsObject:(my _data_type)) as boolean then
        return current application’s NSDragOperationNone
      end if
      
return current application’s NSDragOperationNone
    end tableView:validateDrop:proposedRow:proposedDropOperation:
    
## ドラッグ終了
    
on tableView:aTableView acceptDrop:info row:row dropOperation:operation
      –log "acceptDrop"
      
set pboard to info’s draggingPasteboard()
      
      
set rowData to pboard’s dataForType:(my _data_type)
      
set rowIndexes to current application’s NSKeyedUnarchiver’s unarchiveObjectWithData:rowData
      
      
if (rowIndexes’s firstIndex()) < row then
        set row to row – (rowIndexes’s |count|())
      end if
      
      
set aRange to current application’s NSMakeRange(row, rowIndexes’s |count|())
      
set aIndexSet to current application’s NSIndexSet’s indexSetWithIndexesInRange:aRange
      
      
tell my _data_source
        set anObj to content()’s objectsAtIndexes:rowIndexes
        
removeObjects_(anObj)
        
insertObjects_atArrangedObjectIndexes_(anObj, aIndexSet)
        
rearrangeObjects()
      end tell
      
return true
    end tableView:acceptDrop:row:dropOperation:
  end script
  
  
##
  
tell (make MyDialog)
    return call(aMainMes, aSubMes, optionRec)
  end tell
end chooseData

★Click Here to Open This Script 

More from my site

  • アラートダイアログ上にTable Viewを表示 v7_サイズ調整ありアラートダイアログ上にTable Viewを表示 v7_サイズ調整あり
  • アラートダイアログ上にTable Viewを表示 v6_サーチフィールドつきアラートダイアログ上にTable Viewを表示 v6_サーチフィールドつき
  • アラートダイアログ上にTable Viewを表示 v5_複数キー抽出つきアラートダイアログ上にTable Viewを表示 v5_複数キー抽出つき
  • アラートダイアログ上にTable Viewを表示 v4アラートダイアログ上にTable Viewを表示 v4
  • 相対パスを計算で求める相対パスを計算で求める
  • 人類史上初、魔導書の観点から書かれたAppleScript入門書「7つの宝珠」シリーズ開始?!人類史上初、魔導書の観点から書かれたAppleScript入門書「7つの宝珠」シリーズ開始?!
(Visited 106 times, 1 visits today)
Posted in dialog GUI | Tagged 10.13savvy 10.14savvy 10.15savvy | Leave a comment

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

電子書籍(PDF)をオンラインストアで販売中!

Google Search

Popular posts

  • macOS 13, Ventura(継続更新)
  • アラートダイアログ上にWebViewで3Dコンテンツを表示(WebGL+three.js)v3
  • UI Browserがgithub上でソース公開され、オープンソースに
  • Xcode 14.2でAppleScript App Templateを復活させる
  • macOS 13 TTS Voice環境に変更
  • 2022年に書いた価値あるAppleScript
  • ChatGPTで文章のベクトル化(Embedding)
  • 新発売:AppleScriptからSiriを呼び出そう!
  • iWork 12.2がリリースされた
  • 従来と異なるmacOS 13の性格?
  • 新発売:CotEditor Scripting Book with AppleScript
  • macOS 13対応アップデート:AppleScript実践的テクニック集(1)GUI Scripting
  • AS関連データの取り扱いを容易にする(はずの)privateDataTypeLib
  • macOS 12.5.1、11.6.8でFinderのselectionでスクリーンショット画像をopenできない問題
  • macOS 13でNSNotFoundバグふたたび
  • ChatGPTでchatに対する応答文を取得
  • 新発売:iWork Scripting Book with AppleScript
  • Finderの隠し命令openVirtualLocationが発見される
  • macOS 13.1アップデートでスクリプトエディタの挙動がようやくまともに
  • あのコン過去ログビューワー(暫定版)

Tags

10.11savvy (1101) 10.12savvy (1242) 10.13savvy (1390) 10.14savvy (586) 10.15savvy (434) 11.0savvy (277) 12.0savvy (185) 13.0savvy (55) CotEditor (60) Finder (47) iTunes (19) Keynote (98) NSAlert (60) NSArray (51) NSBezierPath (18) NSBitmapImageRep (20) NSBundle (20) NSButton (34) NSColor (51) NSDictionary (27) NSFileManager (23) NSFont (18) NSImage (41) NSJSONSerialization (21) NSMutableArray (62) NSMutableDictionary (21) NSPredicate (36) NSRunningApplication (56) NSScreen (30) NSScrollView (22) NSString (117) NSURL (97) NSURLRequest (23) NSUTF8StringEncoding (30) NSView (33) NSWorkspace (20) Numbers (56) Pages (37) Safari (41) Script Editor (20) WKUserContentController (21) WKUserScript (20) WKUserScriptInjectionTimeAtDocumentEnd (18) WKWebView (23) WKWebViewConfiguration (22)

カテゴリー

  • 2D Bin Packing
  • 3D
  • AirDrop
  • AirPlay
  • Animation
  • AppleScript Application on Xcode
  • beta
  • Bluetooth
  • Books
  • boolean
  • bounds
  • Bug
  • Calendar
  • call by reference
  • Clipboard
  • Code Sign
  • Color
  • Custom Class
  • dialog
  • drive
  • exif
  • file
  • File path
  • filter
  • folder
  • Font
  • Font
  • GAME
  • geolocation
  • GUI
  • GUI Scripting
  • Hex
  • History
  • How To
  • iCloud
  • Icon
  • Image
  • Input Method
  • Internet
  • iOS App
  • JavaScript
  • JSON
  • JXA
  • Keychain
  • Keychain
  • Language
  • Library
  • list
  • Locale
  • Machine Learning
  • Map
  • Markdown
  • Menu
  • Metadata
  • MIDI
  • MIME
  • Natural Language Processing
  • Network
  • news
  • Noification
  • Notarization
  • Number
  • Object control
  • OCR
  • OSA
  • PDF
  • Peripheral
  • PRODUCTS
  • QR Code
  • Raw AppleEvent Code
  • Record
  • rectangle
  • recursive call
  • regexp
  • Release
  • Remote Control
  • Require Control-Command-R to run
  • REST API
  • Review
  • RTF
  • Sandbox
  • Screen Saver
  • Script Libraries
  • sdef
  • search
  • Security
  • selection
  • shell script
  • Shortcuts Workflow
  • Sort
  • Sound
  • Spellchecker
  • Spotlight
  • SVG
  • System
  • Tag
  • Telephony
  • Text
  • Text to Speech
  • timezone
  • Tools
  • Update
  • URL
  • UTI
  • Web Contents Control
  • WiFi
  • XML
  • XML-RPC
  • イベント(Event)
  • 未分類

アーカイブ

  • 2023年9月
  • 2023年8月
  • 2023年7月
  • 2023年6月
  • 2023年5月
  • 2023年4月
  • 2023年3月
  • 2023年2月
  • 2023年1月
  • 2022年12月
  • 2022年11月
  • 2022年10月
  • 2022年9月
  • 2022年8月
  • 2022年7月
  • 2022年6月
  • 2022年5月
  • 2022年4月
  • 2022年3月
  • 2022年2月
  • 2022年1月
  • 2021年12月
  • 2021年11月
  • 2021年10月
  • 2021年9月
  • 2021年8月
  • 2021年7月
  • 2021年6月
  • 2021年5月
  • 2021年4月
  • 2021年3月
  • 2021年2月
  • 2021年1月
  • 2020年12月
  • 2020年11月
  • 2020年10月
  • 2020年9月
  • 2020年8月
  • 2020年7月
  • 2020年6月
  • 2020年5月
  • 2020年4月
  • 2020年3月
  • 2020年2月
  • 2020年1月
  • 2019年12月
  • 2019年11月
  • 2019年10月
  • 2019年9月
  • 2019年8月
  • 2019年7月
  • 2019年6月
  • 2019年5月
  • 2019年4月
  • 2019年3月
  • 2019年2月
  • 2019年1月
  • 2018年12月
  • 2018年11月
  • 2018年10月
  • 2018年9月
  • 2018年8月
  • 2018年7月
  • 2018年6月
  • 2018年5月
  • 2018年4月
  • 2018年3月
  • 2018年2月

https://piyomarusoft.booth.pm/items/301502

メタ情報

  • ログイン
  • 投稿フィード
  • コメントフィード
  • WordPress.org

Forum Posts

  • 人気のトピック
  • 返信がないトピック

メタ情報

  • ログイン
  • 投稿フィード
  • コメントフィード
  • WordPress.org
Proudly powered by WordPress
Theme: Flint by Star Verte LLC