アラートダイアログを作成し、その上にScroll View+Table ViewおよびMap Viewを表示して選択肢の選択を行うAppleScriptです。Segmented Controlで地図の種別切り替えを行い、項目選択用のTable Viewを編集不可にしました。
Map Viewを使用するために、インターネット接続が必要です。地図表示パフォーマンスはインターネット接続速度次第です。
▲Map Type = Standard (Map)
▲Map Type = Satellite
▲Map Type = Hybrid (Satellite + Map)
本Scriptに与える緯度・経度情報についてはあらかじめ住所ジオコーダーによって「住所情報→緯度・経度情報」の変換を行なったものを書いておく必要がありますが、Yahoo!の住所ジオコーダーサービスなどを呼び出せば、住所情報をパラメーターとすることも可能です。
サンプルデータの緯度・経度情報は、例によって「戦場の絆」の入っている近所のゲーセンの情報を適当にみつくろって入れてみたものです。
本ダイアログは、それほど件数の多くない(20件ぐらい?)選択肢からの選択を意図して作ったものですが、数百件とか数千件のデータから選ぶような場合には、Outline Viewを利用して小エリアごとに分割するとか、Search Fieldを連動させてキーワードによる絞り込みを有効にするなど、それなりの対処が必要です。
AppleScript名:アラートダイアログ上にTable View+Map View+Segmented Controlを表示 |
— Created 2019-02-23 by Takaaki Naganoya — 2019 Piyomaru Software use AppleScript version "2.5" use scripting additions use framework "Foundation" use framework "AppKit" use framework "MapKit" property NSAlert : a reference to current application’s NSAlert property NSIndexSet : a reference to current application’s NSIndexSet property MKMapView : a reference to current application’s MKMapView property NSScrollView : a reference to current application’s NSScrollView property NSTableView : a reference to current application’s NSTableView property NSTableColumn : a reference to current application’s NSTableColumn property NSMutableArray : a reference to current application’s NSMutableArray property MKPointAnnotation : a reference to current application’s MKPointAnnotation property NSSegmentedControl : a reference to current application’s NSSegmentedControl property NSRunningApplication : a reference to current application’s NSRunningApplication property NSAlertSecondButtonReturn : a reference to current application’s NSAlertSecondButtonReturn property NSSegmentStyleTexturedRounded : a reference to current application’s NSSegmentStyleTexturedRounded property MKMapTypeHybrid : a reference to current application’s MKMapTypeHybrid property MKMapTypeSatellite : a reference to current application’s MKMapTypeSatellite property MKMapTypeStandard : a reference to current application’s MKMapTypeStandard property zLevel : 21 –Map Zoom Level (0:World View, 21:House/Building Zoom View) property aMaxViewWidth : 800 property theResult : 0 property returnCode : 0 property theDataSource : {} property curRow : 0 property aMapView : missing value property nameL : {} property placeL : {} set aPlaceList to {{placeName:"Hey", aLat:"35.69906613", aLong:"139.77084064"}, {placeName:"namco中野", aLat:"35.70859274", aLong:"139.66584339"}, {placeName:"ゲームシティ板橋", aLat:"35.74572771", aLong:"139.67553260"}, {placeName:"ラウンドワンスタジアム板橋", aLat:"35.77661583", aLong:"139.67864491"}, {placeName:"キャロム練馬", aLat:"35.76386421", aLong:"139.66591600"}, {placeName:"アミュージアムOSC", aLat:"35.75308308", aLong:"139.59476696"}} set paramObj to {myMessage:"場所の選択", mySubMessage:"適切な場所を以下のリストからえらんでください", placeList:aPlaceList} my performSelectorOnMainThread:"chooseItemByTableViewWithMapAndSegment:" withObject:(paramObj) waitUntilDone:true if (my theResult) = 0 then error number -128 return (my theResult) on chooseItemByTableViewWithMapAndSegment:paramObj set aMainMes to myMessage of paramObj set aSubMes to mySubMessage of paramObj set aTList to (placeList of paramObj) as list set nameL to {} set placeL to {} repeat with i in aTList set the end of nameL to (placeName of i) set the end of placeL to {contents of (aLat of i), contents of (aLong of i)} end repeat — create a view set theView to current application’s NSView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 0, aMaxViewWidth, 400)) — make table view with scroll view set aScrollWithTable to makeTableView(nameL, 200, 400) of me set aMapView to MKMapView’s alloc()’s initWithFrame:(current application’s NSMakeRect(210, 30, aMaxViewWidth – 210, 370)) tell aMapView its setMapType:MKMapTypeStandard its setZoomEnabled:true its setScrollEnabled:true its setPitchEnabled:true its setRotateEnabled:true its setShowsCompass:true its setShowsZoomControls:true its setShowsScale:true its setShowsUserLocation:true set aLocation to current application’s CLLocationCoordinate2DMake((first item of first item of placeL) as real, (second item of first item of placeL) as real) its setCenterCoordinate:aLocation zoomLevel:(zLevel) animated:false its setDelegate:me end tell –MapにPinを追加 repeat with i from 1 to (length of nameL) set tmpAdr to contents of item i of nameL copy item i of placeL to {tmpLat, tmpLong} set aLocation to current application’s CLLocationCoordinate2DMake(tmpLat as real, tmpLong as real) set anAnnotation to MKPointAnnotation’s alloc()’s init() (anAnnotation’s setCoordinate:aLocation) (anAnnotation’s setTitle:tmpAdr) (aMapView’s addAnnotation:anAnnotation) end repeat –Segmented Controlをつくる set segTitleList to {"Map", "Satellite", "Satellite + Map"} set aSeg to makeSegmentedControl(segTitleList, 210, 0, 150, 20) of me theView’s setSubviews:{aScrollWithTable, aMapView, aSeg} — set up alert set theAlert to NSAlert’s alloc()’s init() tell theAlert its setMessageText:aMainMes its setInformativeText:aSubMes its addButtonWithTitle:"OK" its addButtonWithTitle:"Cancel" its setAccessoryView:theView end tell –To enable the first annotation visible copy item 1 of placeL to {tmpLat, tmpLong} set aLocation to current application’s CLLocationCoordinate2DMake(tmpLat as real, tmpLong as real) aMapView’s setCenterCoordinate:aLocation zoomLevel:(zLevel) animated:false — show alert in modal loop NSRunningApplication’s currentApplication()’s activateWithOptions:0 my performSelectorOnMainThread:"doModal:" withObject:(theAlert) waitUntilDone:true set (my theResult) to (aScrollWithTable’s documentView’s selectedRow()) + 1 end chooseItemByTableViewWithMapAndSegment: on doModal:aParam set (my returnCode) to aParam’s runModal() end doModal: on makeTableView(aList as list, aWidth as number, aHeight as number) set aOffset to 0 set sourceList to {} repeat with i in aList set the end of sourceList to {dataItem:(contents of i)} end repeat set theDataSource to NSMutableArray’s alloc()’s init() theDataSource’s addObjectsFromArray:sourceList set aScroll to NSScrollView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 30, aWidth, aHeight – 30)) set aView to NSTableView’s alloc()’s initWithFrame:(current application’s NSMakeRect(0, 30, aWidth, aHeight – 30)) set aColumn to (NSTableColumn’s alloc()’s initWithIdentifier:"dataItem") (aColumn’s setWidth:aWidth) (aColumn’s headerCell()’s setStringValue:"dataItem") (aView’s addTableColumn:aColumn) aView’s setDelegate:me aView’s setDataSource:me aView’s reloadData() aScroll’s setDocumentView:aView aView’s enclosingScrollView()’s setHasVerticalScroller:true –1行目を選択 set aIndexSet to NSIndexSet’s indexSetWithIndex:0 aView’s selectRowIndexes:aIndexSet byExtendingSelection:false –強制的にトップにスクロール set aDBounds to aScroll’s documentView()’s |bounds|() if class of aDBounds = list then –macOS 10.13 or later set maxHeight to item 2 of item 1 of aDBounds else –macOS 10.10, 10.11, 10.12 set maxHeight to height of |size| of aDBounds end if set aPT to current application’s NSMakePoint(0.0, -40.0) —— (aScroll’s documentView()’s |bounds|()’s |size|()’s height)) aScroll’s documentView()’s scrollPoint:aPT return aScroll end makeTableView –TableView Event Handlers on numberOfRowsInTableView:aView return my theDataSource’s |count|() end numberOfRowsInTableView: on tableView:aView objectValueForTableColumn:aColumn row:aRow set (tmpRow) to aView’s selectedRow() as number –Table View上で現在選択行「以外の」行が選択されたら、Mapを選択項目で更新 if (my curRow) is not equal to tmpRow then set tmpLat to (first item of item (tmpRow + 1) of placeL) as real set tmpLong to (second item of item (tmpRow + 1) of placeL) as real tell aMapView set aLocation to current application’s CLLocationCoordinate2DMake(tmpLat, tmpLong) its setCenterCoordinate:aLocation zoomLevel:(zLevel) animated:false end tell set (my curRow) to tmpRow end if set aRec to (my theDataSource)’s objectAtIndex:(aRow as number) set aTitle to (aColumn’s headerCell()’s title()) as string set aRes to (aRec’s valueForKey:aTitle) return aRes end tableView:objectValueForTableColumn:row: on tableView:aView shouldEditTableColumn:aTableColumn row:rowIndex return false –Not Editable end tableView:shouldEditTableColumn:row: –Segmented Controlをつくる on makeSegmentedControl(titleList, startX, startY, aWidth, aHeight) set aLen to length of titleList set aSeg to NSSegmentedControl’s alloc()’s init() aSeg’s setSegmentCount:aLen set aCount to 0 repeat with i in titleList set j to contents of i (aSeg’s setLabel:j forSegment:aCount) set aCount to aCount + 1 end repeat aSeg’s setTranslatesAutoresizingMaskIntoConstraints:false aSeg’s setSegmentStyle:(NSSegmentStyleTexturedRounded) aSeg’s setFrame:(current application’s NSMakeRect(startX, startY, aWidth, aHeight)) aSeg’s setTrackingMode:0 aSeg’s setTarget:me aSeg’s setAction:"clickedSeg:" aSeg’s setSelectedSegment:0 return aSeg end makeSegmentedControl –Segmented Controlのクリック時のイベントハンドラ on clickedSeg:aSender set aSel to aSender’s selectedSegment() set tList to {MKMapTypeStandard, MKMapTypeSatellite, MKMapTypeHybrid} set tmpType to contents of item (aSel + 1) of tList aMapView’s setMapType:(tmpType) set selSeg to aSel end clickedSeg: |