2323import Cocoa
2424import Syntax_Highlight_XPC_Service
2525
26+ enum UTISupported {
27+ case unknown
28+ case no
29+ case yes
30+ case highlight
31+ }
32+
33+ class UTIStatus {
34+ let UTI : UTI
35+ var supported : UTISupported = . unknown
36+ let standard : Bool
37+ init ( UTI: UTI , standard: Bool ) {
38+ self . UTI = UTI
39+ self . standard = standard
40+ }
41+ }
42+
2643class DropView : NSView {
2744 weak var dropDelegate : DropViewDelegate ?
2845
@@ -48,112 +65,122 @@ class DropView: NSView {
4865
4966 override func draggingEntered( _ sender: NSDraggingInfo ) -> NSDragOperation {
5067 self . layer? . borderColor = NSColor . selectedControlColor. cgColor
68+ self . dropDelegate? . enterDrag ( sender)
5169 return . every
5270 }
5371
5472 override func draggingExited( _ sender: NSDraggingInfo ? ) {
5573 self . layer? . borderColor = NSColor . gridColor. cgColor
74+ self . dropDelegate? . exitDrag ( sender)
5675 }
5776
5877 override func draggingEnded( _ sender: NSDraggingInfo ) {
59- if let fileUrl = sender. draggingPasteboard. pasteboardItems? . first? . propertyList ( forType: . fileURL) as? String , let url = URL ( string: fileUrl) {
60-
61- do {
62- let v = try url. resourceValues ( forKeys: [ URLResourceKey . typeIdentifierKey] )
63- if let uti = v. typeIdentifier {
64- let u = UTI ( uti)
65- dropDelegate? . setUTI ( u)
66- } else {
67- dropDelegate? . setUTI ( nil )
68- }
69- } catch {
70- dropDelegate? . setUTI ( nil )
71- }
72- } else {
73- dropDelegate? . setUTI ( nil )
74- }
78+ self . dropDelegate? . endDrag ( sender)
7579 self . layer? . borderColor = NSColor . gridColor. cgColor
7680 }
7781}
7882
7983protocol DropViewDelegate : class {
80- func setUTI( _ type: UTI ? )
84+ func enterDrag( _ sender: NSDraggingInfo )
85+ func exitDrag( _ sender: NSDraggingInfo ? )
86+ func endDrag( _ sender: NSDraggingInfo )
8187}
8288
83- class CustomTypeViewController : NSViewController , DropViewDelegate {
89+ class CustomTypeViewController : NSViewController , DropViewDelegate , NSTableViewDelegate , NSTableViewDataSource {
8490 @IBOutlet weak var dropView : DropView !
8591 @IBOutlet weak var labelView : NSTextField !
86- @IBOutlet weak var warningLabel : NSTextField !
87- @IBOutlet weak var warningImage : NSImageView !
92+
93+ @IBOutlet weak var tableView : NSTableView !
94+ @IBOutlet weak var scrollView : NSScrollView !
95+
96+ @IBOutlet weak var handledLegend : NSStackView !
97+ @IBOutlet weak var notHandledLegend : NSStackView !
98+ @IBOutlet weak var supportedLegend : NSStackView !
99+
100+ private var firstDrop = true
88101
89102 var service : SCSHXPCServiceProtocol ? {
90103 return ( NSApplication . shared. delegate as? AppDelegate ) ? . service
91104 }
92105
93106 var handledUTIs : [ UTIDesc ] = [ ]
94107
95- var UTI : UTI ? {
108+ var UTIs : [ UTIStatus ] = [ ] {
96109 didSet {
97- warningLabel. isHidden = true
98- warningImage. isHidden = true
99- isUTIValid = false
100-
101- if let uti = self . UTI {
102- let s = NSMutableAttributedString ( )
103- var label : String = uti. description
104- if uti. extensions. count > 0 {
105- label += ( label. isEmpty ? " " : " " ) + " [. \( uti. extensions. joined ( separator: " , . " ) ) ] "
106- }
107-
108- let style = NSMutableParagraphStyle ( )
109- style. alignment = . center
110-
111- if !label. isEmpty {
112- s. append ( NSAttributedString ( string: label + " \n " , attributes: [ NSAttributedString . Key. paragraphStyle: style] ) )
113- }
114- s. append ( NSAttributedString ( string: uti. UTI, attributes: [ NSAttributedString . Key. font : NSFont . systemFont ( ofSize: NSFont . systemFontSize ( for: NSControl . ControlSize. small) ) , NSAttributedString . Key. paragraphStyle: style] ) )
115-
116- labelView. attributedStringValue = s
117-
118- if let _ = handledUTIs. first ( where: { $0. uti == uti } ) {
119- self . warningLabel. stringValue = " Format recognized by the extension. "
120- self . warningImage. image = NSImage ( named: NSImage . statusAvailableName)
121-
122- self . warningLabel. isHidden = false
123- self . warningImage. isHidden = false
124-
125- return
126- } else {
127- service? . areSomeSyntaxSupported ( uti. extensions, overrideSettings: nil , reply: { ( state) in
128- self . warningLabel. stringValue = state ? " Format handled by highlight but not by the extension. " : " Format not supported by highlight. "
129- self . warningImage. image = NSImage ( named: state ? NSImage . statusPartiallyAvailableName : NSImage . statusUnavailableName)
130- self . warningLabel. isHidden = false
131- self . warningImage. isHidden = false
132-
133- self . isUTIValid = state
134- } )
110+ self . handledLegend. isHidden = true
111+ self . notHandledLegend. isHidden = true
112+ self . supportedLegend. isHidden = true
113+ if ( self . UTIs. count > 0 ) {
114+ for (i, uti) in self . UTIs. enumerated ( ) {
115+ if let _ = handledUTIs. first ( where: { $0. uti == uti. UTI } ) {
116+ uti. supported = . yes
117+ self . handledLegend. isHidden = false
118+ } else {
119+ service? . areSomeSyntaxSupported ( uti. UTI. extensions, overrideSettings: nil , reply: { ( state) in
120+ self . notHandledLegend. isHidden = state
121+ self . supportedLegend. isHidden = !state
122+ uti. supported = state ? . highlight : . no
123+ let c = self . tableView. column ( withIdentifier: NSUserInterfaceItemIdentifier ( " status " ) )
124+ self . tableView. reloadData ( forRowIndexes: IndexSet ( integer: i) , columnIndexes: IndexSet ( integer: c) )
125+ } )
126+ }
135127 }
136- } else {
137- labelView. stringValue = " Drag a file here "
138128 }
129+
130+ self . tableView. reloadData ( )
139131 }
140132 }
141-
142- fileprivate( set) var isUTIValid : Bool = false
143-
133+
144134 override func viewDidLoad( ) {
145135 self . dropView. dropDelegate = self
146136
147- self . warningLabel. isHidden = true
148- self . warningImage. isHidden = true
149-
150137 handledUTIs = ( NSApplication . shared. delegate as? AppDelegate ) ? . fetchHandledUTIs ( ) ?? [ ]
138+
139+ self . handledLegend. isHidden = true
140+ self . notHandledLegend. isHidden = true
141+ self . supportedLegend. isHidden = true
151142 }
152143
153- func setUTI( _ type: UTI ? ) {
154- self . UTI = type
144+ func enterDrag( _ sender: NSDraggingInfo ) {
145+ self . scrollView. isHidden = true
146+ }
147+ func exitDrag( _ sender: NSDraggingInfo ? ) {
148+ self . scrollView. isHidden = firstDrop
149+ }
150+ func endDrag( _ sender: NSDraggingInfo ) {
151+ if let fileUrl = sender. draggingPasteboard. pasteboardItems? . first? . propertyList ( forType: . fileURL) as? String , let url = URL ( string: fileUrl) {
152+
153+ var UTIs : [ UTIStatus ] = [ ]
154+
155+ do {
156+ let v = try url. resourceValues ( forKeys: [ URLResourceKey . typeIdentifierKey] )
157+ if let uti = v. typeIdentifier {
158+ UTIs . append ( UTIStatus ( UTI: UTI ( uti) , standard: true ) )
159+ }
160+ } catch {
161+ }
162+
163+ let ext = url. pathExtension
164+ if !ext. isEmpty {
165+ let tags = UTTypeCreateAllIdentifiersForTag ( kUTTagClassFilenameExtension, ext as CFString , nil )
166+ if let t = tags? . takeRetainedValue ( ) as? [ String ] {
167+ for u in t {
168+ if UTIs . first ( where: { $0. UTI. UTI == u } ) == nil {
169+ UTIs . append ( UTIStatus ( UTI: UTI ( u) , standard: false ) )
170+ }
171+ }
172+ }
173+ }
174+ self . UTIs = UTIs
175+ self . scrollView. isHidden = false
176+ firstDrop = false
177+ } else {
178+ self . UTIs = [ ]
179+ self . scrollView. isHidden = true
180+ }
155181 }
156182
183+ /*
157184 @IBAction func doSave(_ sender: Any) {
158185 if isUTIValid, let url = (NSApplication.shared.delegate as? AppDelegate)?.getQLAppexUrl(), let bundle = Bundle(url: url) {
159186
@@ -190,4 +217,40 @@ class CustomTypeViewController: NSViewController, DropViewDelegate {
190217 }
191218 dismiss(sender)
192219 }
220+ */
221+
222+ func numberOfRows( in tableView: NSTableView ) -> Int {
223+ return self . UTIs. count
224+ }
225+
226+ func tableView( _ tableView: NSTableView , objectValueFor tableColumn: NSTableColumn ? , row: Int ) -> Any ? {
227+ let uti = self . UTIs [ row]
228+ let font : NSFont
229+
230+ if uti. standard {
231+ font = NSFont . boldSystemFont ( ofSize: NSFont . systemFontSize)
232+ } else {
233+ font = NSFont . labelFont ( ofSize: NSFont . systemFontSize)
234+ }
235+ if tableColumn? . identifier == NSUserInterfaceItemIdentifier ( " description " ) {
236+ return NSAttributedString ( string: uti. UTI. description, attributes: [ NSAttributedString . Key. font: font] )
237+ } else if tableColumn? . identifier == NSUserInterfaceItemIdentifier ( " UTI " ) {
238+ return NSAttributedString ( string: uti. UTI. UTI, attributes: [ NSAttributedString . Key. font: font] )
239+ } else if tableColumn? . identifier == NSUserInterfaceItemIdentifier ( " status " ) {
240+ switch ( uti. supported) {
241+ case . yes:
242+ return NSImage ( named: NSImage . statusAvailableName)
243+ case . no:
244+ return NSImage ( named: NSImage . statusUnavailableName)
245+ case . highlight:
246+ return NSImage ( named: NSImage . statusPartiallyAvailableName)
247+ case . unknown:
248+ return NSImage ( named: NSImage . statusNoneName)
249+ }
250+ } else if tableColumn? . identifier == NSUserInterfaceItemIdentifier ( " ext " ) {
251+ return uti. UTI. extensions. joined ( separator: " , " )
252+ }
253+
254+ return nil
255+ }
193256}
0 commit comments