├── Capture1.jpg ├── Capture1.png ├── LICENSE ├── MARKDOWN_REFERENCE.md ├── README.md ├── SideBarDemo.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcuserdata │ └── thierryh24.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── SideBarDemo.xcscheme │ └── xcschememanagement.plist ├── SideBarDemo ├── AppDelegate.swift ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ ├── Contents.json │ ├── Department-50.imageset │ │ ├── Contents.json │ │ └── Department-50.png │ ├── DownArrow.imageset │ │ ├── Contents.json │ │ ├── down-arrow-light-1.png │ │ ├── down-arrow-light.png │ │ ├── down-arrow-light@2x-1.png │ │ ├── down-arrow-light@2x.png │ │ ├── down-arrow.png │ │ └── down-arrow@2x.png │ ├── Human_resource.imageset │ │ ├── Contents.json │ │ └── Human_resource_icons-09-512.png │ ├── RightArrow.imageset │ │ ├── Contents.json │ │ ├── right-arrow-light-1.png │ │ ├── right-arrow-light.png │ │ ├── right-arrow-light@2x-1.png │ │ ├── right-arrow-light@2x.png │ │ ├── right-arrow.png │ │ └── right-arrow@2x.png │ ├── account.imageset │ │ ├── Contents.json │ │ └── account.png │ ├── application-sidebar-list.imageset │ │ ├── Contents.json │ │ └── application-sidebar-list.png │ ├── clock.imageset │ │ ├── Contents.json │ │ └── clock.png │ ├── employee.imageset │ │ ├── Contents.json │ │ └── employee.png │ ├── film.imageset │ │ ├── Contents.json │ │ └── film.png │ └── smiley.imageset │ │ ├── Contents.json │ │ └── smiley.png ├── Base.lproj │ └── MainMenu.xib ├── Info.plist ├── MainWindowController.swift ├── MainWindowController.xib ├── Resource │ ├── abundance-church-family.jpg │ ├── hand-tuning-peg-instrument.jpg │ ├── mobile-phone-and-headphones-on-white-wooden-table.jpg │ ├── rayban-ray-bans-spectacles.jpg │ ├── record-vinyl-turntable.jpg │ ├── vintage-radio-on-glass-table.jpg │ └── woman-writing-in-music-sheet.jpg ├── SideBarDemo.entitlements └── View │ ├── CommunController.swift │ ├── ContentView1Controller.swift │ ├── ContentView1Controller.xib │ ├── ContentView2Controller.swift │ ├── ContentView2Controller.xib │ ├── ContentView3Controller.swift │ ├── ContentView3Controller.xib │ ├── ContentView4Controller.swift │ ├── ContentView4Controller.xib │ ├── ContentView5Controller.swift │ ├── ContentView5Controller.xib │ ├── ContentView6Controller.swift │ ├── ContentView6Controller.xib │ ├── ContentView7Controller.swift │ └── ContentView7Controller.xib ├── SideBarDemoTests ├── Info.plist └── SideBarDemoTests.swift ├── SideBarDemoUITests ├── Info.plist └── SideBarDemoUITests.swift └── THSideBar ├── THSideBarCellView.swift ├── THSideBarData.swift ├── THSideBarDataSource.swift ├── THSideBarDelegate.swift ├── THSideBarDragDrop.swift ├── THSideBarViewController.swift ├── THSideBarViewController.xib └── THTextFieldDelegate.swift /Capture1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/Capture1.jpg -------------------------------------------------------------------------------- /Capture1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/Capture1.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /MARKDOWN_REFERENCE.md: -------------------------------------------------------------------------------- 1 | ### Headers 2 | 3 | ```markdown 4 | # H1 5 | ## H2 6 | ### H3 7 | #### H4 8 | ##### H5 9 | ###### H6 10 | ``` 11 | 12 | ### Text 13 | 14 | ```markdown 15 | _italic_ or *italic* 16 | 17 | **bold** or __bold__ 18 | 19 | ~~strikethrough~~ 20 | ``` 21 | 22 | ### Blockquotes 23 | 24 | ```markdown 25 | > This is a blockquote 26 | ``` 27 | 28 | ### Horizontal Rule 29 | 30 | ```markdown 31 | --- 32 | 33 | *** 34 | 35 | ___ 36 | ``` 37 | 38 | ### Lists 39 | 40 | ```markdown 41 | 1. Ordered list 42 | 2. ... 43 | 44 | - Unordered list 45 | * With * 46 | + With + 47 | ``` 48 | 49 | ### Links 50 | 51 | ```markdown 52 | [Inine](https://a.com) 53 | 54 | [Inline with title](https://a.com "A title") 55 | 56 | [Reference][1] 57 | 58 | [Link to file](./Docs/SETUP.md) 59 | 60 | [1]: https://a.com 61 | ``` 62 | 63 | ### Images 64 | 65 | ```markdown 66 | ![Inline](https://a.com/logo.png) 67 | 68 | ![Reference][logo] 69 | 70 | [logo]: https://a.com/logo.png 71 | ``` 72 | 73 | ### Code 74 | 75 | ````markdown 76 | `Inline code` 77 | 78 | ```javascript 79 | const x = 5; 80 | const plusTwo = a => a + 2; 81 | ``` 82 | ```` 83 | 84 | ### Tables 85 | 86 | ```markdown 87 | | Column 1 | Column 2 | Column 3 | 88 | | ------------- |:-------------:| ---------:| 89 | | Col 3 is | right-aligned | $1600 | 90 | | Col 2 is | centered | $12 | 91 | | Tables | are neat | $1 | 92 | ``` 93 | 94 | ### HTML 95 | 96 | ```markdown 97 | Link 98 | 99 | ``` 100 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 | Mac 4 |

5 | 6 | # SideBarDemo 7 | NSOutlineView and badge 8 | 9 | ![Alt text](https://github.com/thierryH91200/SideBarDemo/blob/master/Capture1.png) 10 | 11 | 12 | # THSideBar 13 | 14 | 15 | THSideBar framework written in Swift for OS X 16 | 17 | 18 | 19 | 20 | [![Stargazers over time](https://starchart.cc/thierryH91200/THSideBar.svg)](https://starchart.cc/thierryH91200/THSideBar) 21 | 22 | 23 | # Usage 24 | 25 | ### look at example 26 | 27 | ## Initialize the THSideBar 28 | 29 | ``` 30 | var sideBarViewController : THSideBarViewController? 31 | 32 | 33 | 34 | ``` 35 | 36 | 37 | ## Add THSideBar to the view hierarchy 38 | 39 | ``` 40 | self.sideBarViewController = THSideBarViewController() 41 | addSubview(subView: (sideBarViewController?.view)!, toView: sourceView) 42 | 43 | sideBarViewController?.delegate = self 44 | sideBarViewController?.allowDragAndDrop = false/true 45 | sideBarViewController?.saveSection = false/true 46 | setUpLayoutConstraints(item: sideBarViewController!.view, toItem: sourceView) 47 | self.sideBarViewController!.view.setFrameSize( NSMakeSize(100, 200)) 48 | ``` 49 | 50 | ## Init data 51 | 52 | ``` 53 | let item1 = Account(name:"ContentView1", icon:NSImage (named: NSImage.Name(rawValue: "Human_resource"))!, nameView: "ContentView1Controller", badge: "10", colorBadge: .blue) 54 | let item2 = Account(name:"ContentView2", icon:NSImage (named: NSImage.Name(rawValue: "Human_resource"))!, nameView: "ContentView2Controller", badge: "-5", colorBadge: .red) 55 | let item3 = Account(name:"ContentView3", icon:NSImage (named: NSImage.Name(rawValue: "employee"))!, nameView: "ContentView3Controller", badge: "3", colorBadge: .blue) 56 | let item4 = Account(name:"ContentView4", icon:NSImage (named: NSImage.Name(rawValue: "employee"))!, nameView: "ContentView4Controller", badge: "1", colorBadge: .blue) 57 | 58 | account1.accounts.append(item1) 59 | account1.accounts.append(item2) 60 | account2.accounts.append(item3) 61 | account2.accounts.append(item4) 62 | 63 | allSection.sections.removeAll() 64 | allSection.sections.append(account1) 65 | allSection.sections.append(account2) 66 | allSection.dump() 67 | sideBarViewController?.initData( allSection: allSection ) 68 | 69 | ``` 70 | 71 | ## create all the viewController 72 | 73 | 74 | ``` 75 | extension MainWindowController: THSideBarViewDelegate 76 | { 77 | func changeView(item : Item) 78 | { 79 | var vc = NSView() 80 | 81 | if item.nameView == "City" { 82 | 83 | nameCity = item.name 84 | NotificationCenter.send(.updateView) 85 | return 86 | } 87 | 88 | switch item.nameView 89 | { 90 | case "ContentView1Controller": 91 | vc = contentView1Controller.view 92 | 93 | case "ContentView2Controller": 94 | vc = contentView2Controller.view 95 | 96 | case "ContentView3Controller": 97 | vc = contentView3Controller.view 98 | 99 | case "ContentView4Controller": 100 | vc = contentView4Controller.view 101 | 102 | case "ContentView5Controller": 103 | vc = contentView5Controller.view 104 | 105 | case "ContentView6Controller": 106 | vc = contentView6Controller.view 107 | 108 | case "ContentView7Controller": 109 | vc = contentView7Controller.view 110 | 111 | default: 112 | vc = contentView1Controller.view 113 | } 114 | 115 | addSubview(subView: vc, toView: tableTargetView) 116 | vc.translatesAutoresizingMaskIntoConstraints = false 117 | 118 | var viewBindingsDict = [String: AnyObject]() 119 | viewBindingsDict["vc"] = vc 120 | tableTargetView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[vc]|", options: [], metrics: nil, views: viewBindingsDict)) 121 | tableTargetView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[vc]|", options: [], metrics: nil, views: viewBindingsDict)) 122 | } 123 | 124 | ``` 125 | 126 | ## Custom NSOutlineView 127 | 128 | var isSaveSection = true // Ideal for dynamic sections 129 | var colorBackGround = NSColor.blue 130 | var rowSizeStyle = NSTableView.RowSizeStyle.small 131 | var allowDragAndDrop = true 132 | 133 | -------------------------------------------------------------------------------- /SideBarDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 48; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 0305FAC41F80AE3900D9B979 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0305FAC31F80AE3900D9B979 /* AppDelegate.swift */; }; 11 | 0305FAC61F80AE3900D9B979 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0305FAC51F80AE3900D9B979 /* Assets.xcassets */; }; 12 | 0305FAC91F80AE3900D9B979 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0305FAC71F80AE3900D9B979 /* MainMenu.xib */; }; 13 | 0305FAD51F80AE3900D9B979 /* SideBarDemoTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0305FAD41F80AE3900D9B979 /* SideBarDemoTests.swift */; }; 14 | 0305FAE01F80AE3900D9B979 /* SideBarDemoUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0305FADF1F80AE3900D9B979 /* SideBarDemoUITests.swift */; }; 15 | 0305FAF21F80BBA500D9B979 /* THSideBarCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0305FAF11F80BBA500D9B979 /* THSideBarCellView.swift */; }; 16 | 0305FAF41F8117A600D9B979 /* ContentView1Controller.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0305FAF31F8117A600D9B979 /* ContentView1Controller.xib */; }; 17 | 0305FAF61F8117BC00D9B979 /* ContentView2Controller.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0305FAF51F8117BC00D9B979 /* ContentView2Controller.xib */; }; 18 | 0305FAF81F8117D500D9B979 /* ContentView3Controller.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0305FAF71F8117D500D9B979 /* ContentView3Controller.xib */; }; 19 | 032081E01FA309BB000925C6 /* ContentView5Controller.xib in Resources */ = {isa = PBXBuildFile; fileRef = 032081DC1FA309BB000925C6 /* ContentView5Controller.xib */; }; 20 | 032081E11FA309BB000925C6 /* ContentView4Controller.xib in Resources */ = {isa = PBXBuildFile; fileRef = 032081DD1FA309BB000925C6 /* ContentView4Controller.xib */; }; 21 | 032081E21FA309BB000925C6 /* ContentView7Controller.xib in Resources */ = {isa = PBXBuildFile; fileRef = 032081DE1FA309BB000925C6 /* ContentView7Controller.xib */; }; 22 | 032081E31FA309BB000925C6 /* ContentView6Controller.xib in Resources */ = {isa = PBXBuildFile; fileRef = 032081DF1FA309BB000925C6 /* ContentView6Controller.xib */; }; 23 | 032081EB1FA30C97000925C6 /* abundance-church-family.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 032081E41FA30C96000925C6 /* abundance-church-family.jpg */; }; 24 | 032081EC1FA30C97000925C6 /* mobile-phone-and-headphones-on-white-wooden-table.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 032081E51FA30C96000925C6 /* mobile-phone-and-headphones-on-white-wooden-table.jpg */; }; 25 | 032081ED1FA30C97000925C6 /* hand-tuning-peg-instrument.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 032081E61FA30C96000925C6 /* hand-tuning-peg-instrument.jpg */; }; 26 | 032081EE1FA30C97000925C6 /* vintage-radio-on-glass-table.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 032081E71FA30C96000925C6 /* vintage-radio-on-glass-table.jpg */; }; 27 | 032081EF1FA30C97000925C6 /* woman-writing-in-music-sheet.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 032081E81FA30C96000925C6 /* woman-writing-in-music-sheet.jpg */; }; 28 | 032081F01FA30C97000925C6 /* rayban-ray-bans-spectacles.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 032081E91FA30C96000925C6 /* rayban-ray-bans-spectacles.jpg */; }; 29 | 032081F11FA30C97000925C6 /* record-vinyl-turntable.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 032081EA1FA30C96000925C6 /* record-vinyl-turntable.jpg */; }; 30 | 032081F31FA31F2B000925C6 /* THSideBarDragDrop.swift in Sources */ = {isa = PBXBuildFile; fileRef = 032081F21FA31F2B000925C6 /* THSideBarDragDrop.swift */; }; 31 | 0324E0901FA085EF00D0AB52 /* THSideBarDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0324E08F1FA085EF00D0AB52 /* THSideBarDelegate.swift */; }; 32 | 0324E0921FA0867400D0AB52 /* THSideBarDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0324E0911FA0867400D0AB52 /* THSideBarDataSource.swift */; }; 33 | 0336FB2322DAF11900FEC527 /* CommunController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0336FB2222DAF11900FEC527 /* CommunController.swift */; }; 34 | 0346867C1FC7634B0065C180 /* THTextFieldDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0346867B1FC7634B0065C180 /* THTextFieldDelegate.swift */; }; 35 | 034CF9EB22E5BC22005BDF21 /* MARKDOWN_REFERENCE.md in Resources */ = {isa = PBXBuildFile; fileRef = 034CF9EA22E5BC22005BDF21 /* MARKDOWN_REFERENCE.md */; }; 36 | 034D65631FBD6C0F00D980A9 /* ContentView1Controller.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034D65621FBD6C0F00D980A9 /* ContentView1Controller.swift */; }; 37 | 034D65651FBD6C3100D980A9 /* ContentView2Controller.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034D65641FBD6C3100D980A9 /* ContentView2Controller.swift */; }; 38 | 034D65671FBD6C5800D980A9 /* ContentView3Controller.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034D65661FBD6C5800D980A9 /* ContentView3Controller.swift */; }; 39 | 034D65691FBD6C7B00D980A9 /* ContentView4Controller.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034D65681FBD6C7B00D980A9 /* ContentView4Controller.swift */; }; 40 | 034D656B1FBD6CA700D980A9 /* ContentView5Controller.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034D656A1FBD6CA700D980A9 /* ContentView5Controller.swift */; }; 41 | 034D656D1FBD6CC100D980A9 /* ContentView6Controller.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034D656C1FBD6CC100D980A9 /* ContentView6Controller.swift */; }; 42 | 034D656F1FBD6CD800D980A9 /* ContentView7Controller.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034D656E1FBD6CD800D980A9 /* ContentView7Controller.swift */; }; 43 | 034D65721FBD72A300D980A9 /* THSideBarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 034D65701FBD72A300D980A9 /* THSideBarViewController.swift */; }; 44 | 034D65731FBD72A300D980A9 /* THSideBarViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 034D65711FBD72A300D980A9 /* THSideBarViewController.xib */; }; 45 | 035BAA8F22CCB4820081B76B /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 035BAA8E22CCB4820081B76B /* README.md */; }; 46 | 0361A1281F9FD05B00FED796 /* THSideBarData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0361A1271F9FD05B00FED796 /* THSideBarData.swift */; }; 47 | 0373C89D1FBC03F40000757D /* MainWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 0373C89C1FBC03F40000757D /* MainWindowController.xib */; }; 48 | 0373C89F1FBC04020000757D /* MainWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0373C89E1FBC04020000757D /* MainWindowController.swift */; }; 49 | /* End PBXBuildFile section */ 50 | 51 | /* Begin PBXContainerItemProxy section */ 52 | 0305FAD11F80AE3900D9B979 /* PBXContainerItemProxy */ = { 53 | isa = PBXContainerItemProxy; 54 | containerPortal = 0305FAB81F80AE3900D9B979 /* Project object */; 55 | proxyType = 1; 56 | remoteGlobalIDString = 0305FABF1F80AE3900D9B979; 57 | remoteInfo = SideBarDemo; 58 | }; 59 | 0305FADC1F80AE3900D9B979 /* PBXContainerItemProxy */ = { 60 | isa = PBXContainerItemProxy; 61 | containerPortal = 0305FAB81F80AE3900D9B979 /* Project object */; 62 | proxyType = 1; 63 | remoteGlobalIDString = 0305FABF1F80AE3900D9B979; 64 | remoteInfo = SideBarDemo; 65 | }; 66 | /* End PBXContainerItemProxy section */ 67 | 68 | /* Begin PBXFileReference section */ 69 | 0305FAC01F80AE3900D9B979 /* SideBarDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SideBarDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 70 | 0305FAC31F80AE3900D9B979 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 71 | 0305FAC51F80AE3900D9B979 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 72 | 0305FAC81F80AE3900D9B979 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 73 | 0305FACA1F80AE3900D9B979 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 74 | 0305FACB1F80AE3900D9B979 /* SideBarDemo.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = SideBarDemo.entitlements; sourceTree = ""; }; 75 | 0305FAD01F80AE3900D9B979 /* SideBarDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SideBarDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 76 | 0305FAD41F80AE3900D9B979 /* SideBarDemoTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SideBarDemoTests.swift; sourceTree = ""; }; 77 | 0305FAD61F80AE3900D9B979 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 78 | 0305FADB1F80AE3900D9B979 /* SideBarDemoUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SideBarDemoUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 79 | 0305FADF1F80AE3900D9B979 /* SideBarDemoUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SideBarDemoUITests.swift; sourceTree = ""; }; 80 | 0305FAE11F80AE3900D9B979 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 81 | 0305FAF11F80BBA500D9B979 /* THSideBarCellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = THSideBarCellView.swift; sourceTree = ""; }; 82 | 0305FAF31F8117A600D9B979 /* ContentView1Controller.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ContentView1Controller.xib; sourceTree = ""; }; 83 | 0305FAF51F8117BC00D9B979 /* ContentView2Controller.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ContentView2Controller.xib; sourceTree = ""; }; 84 | 0305FAF71F8117D500D9B979 /* ContentView3Controller.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ContentView3Controller.xib; sourceTree = ""; }; 85 | 032081DC1FA309BB000925C6 /* ContentView5Controller.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ContentView5Controller.xib; sourceTree = ""; }; 86 | 032081DD1FA309BB000925C6 /* ContentView4Controller.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ContentView4Controller.xib; sourceTree = ""; }; 87 | 032081DE1FA309BB000925C6 /* ContentView7Controller.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ContentView7Controller.xib; sourceTree = ""; }; 88 | 032081DF1FA309BB000925C6 /* ContentView6Controller.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ContentView6Controller.xib; sourceTree = ""; }; 89 | 032081E41FA30C96000925C6 /* abundance-church-family.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "abundance-church-family.jpg"; sourceTree = ""; }; 90 | 032081E51FA30C96000925C6 /* mobile-phone-and-headphones-on-white-wooden-table.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "mobile-phone-and-headphones-on-white-wooden-table.jpg"; sourceTree = ""; }; 91 | 032081E61FA30C96000925C6 /* hand-tuning-peg-instrument.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "hand-tuning-peg-instrument.jpg"; sourceTree = ""; }; 92 | 032081E71FA30C96000925C6 /* vintage-radio-on-glass-table.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "vintage-radio-on-glass-table.jpg"; sourceTree = ""; }; 93 | 032081E81FA30C96000925C6 /* woman-writing-in-music-sheet.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "woman-writing-in-music-sheet.jpg"; sourceTree = ""; }; 94 | 032081E91FA30C96000925C6 /* rayban-ray-bans-spectacles.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "rayban-ray-bans-spectacles.jpg"; sourceTree = ""; }; 95 | 032081EA1FA30C96000925C6 /* record-vinyl-turntable.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "record-vinyl-turntable.jpg"; sourceTree = ""; }; 96 | 032081F21FA31F2B000925C6 /* THSideBarDragDrop.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = THSideBarDragDrop.swift; sourceTree = ""; }; 97 | 0324E08F1FA085EF00D0AB52 /* THSideBarDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = THSideBarDelegate.swift; sourceTree = ""; }; 98 | 0324E0911FA0867400D0AB52 /* THSideBarDataSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = THSideBarDataSource.swift; sourceTree = ""; }; 99 | 0336FB2222DAF11900FEC527 /* CommunController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommunController.swift; sourceTree = ""; }; 100 | 0346867B1FC7634B0065C180 /* THTextFieldDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = THTextFieldDelegate.swift; sourceTree = ""; }; 101 | 034CF9EA22E5BC22005BDF21 /* MARKDOWN_REFERENCE.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = MARKDOWN_REFERENCE.md; sourceTree = ""; }; 102 | 034D65621FBD6C0F00D980A9 /* ContentView1Controller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView1Controller.swift; sourceTree = ""; }; 103 | 034D65641FBD6C3100D980A9 /* ContentView2Controller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView2Controller.swift; sourceTree = ""; }; 104 | 034D65661FBD6C5800D980A9 /* ContentView3Controller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView3Controller.swift; sourceTree = ""; }; 105 | 034D65681FBD6C7B00D980A9 /* ContentView4Controller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView4Controller.swift; sourceTree = ""; }; 106 | 034D656A1FBD6CA700D980A9 /* ContentView5Controller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView5Controller.swift; sourceTree = ""; }; 107 | 034D656C1FBD6CC100D980A9 /* ContentView6Controller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView6Controller.swift; sourceTree = ""; }; 108 | 034D656E1FBD6CD800D980A9 /* ContentView7Controller.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView7Controller.swift; sourceTree = ""; }; 109 | 034D65701FBD72A300D980A9 /* THSideBarViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = THSideBarViewController.swift; sourceTree = ""; }; 110 | 034D65711FBD72A300D980A9 /* THSideBarViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = THSideBarViewController.xib; sourceTree = ""; }; 111 | 035BAA8E22CCB4820081B76B /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; 112 | 0361A1271F9FD05B00FED796 /* THSideBarData.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = THSideBarData.swift; sourceTree = ""; }; 113 | 0373C89C1FBC03F40000757D /* MainWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MainWindowController.xib; sourceTree = ""; }; 114 | 0373C89E1FBC04020000757D /* MainWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainWindowController.swift; sourceTree = ""; }; 115 | /* End PBXFileReference section */ 116 | 117 | /* Begin PBXFrameworksBuildPhase section */ 118 | 0305FABD1F80AE3900D9B979 /* Frameworks */ = { 119 | isa = PBXFrameworksBuildPhase; 120 | buildActionMask = 2147483647; 121 | files = ( 122 | ); 123 | runOnlyForDeploymentPostprocessing = 0; 124 | }; 125 | 0305FACD1F80AE3900D9B979 /* Frameworks */ = { 126 | isa = PBXFrameworksBuildPhase; 127 | buildActionMask = 2147483647; 128 | files = ( 129 | ); 130 | runOnlyForDeploymentPostprocessing = 0; 131 | }; 132 | 0305FAD81F80AE3900D9B979 /* Frameworks */ = { 133 | isa = PBXFrameworksBuildPhase; 134 | buildActionMask = 2147483647; 135 | files = ( 136 | ); 137 | runOnlyForDeploymentPostprocessing = 0; 138 | }; 139 | /* End PBXFrameworksBuildPhase section */ 140 | 141 | /* Begin PBXGroup section */ 142 | 0305FAB71F80AE3900D9B979 = { 143 | isa = PBXGroup; 144 | children = ( 145 | 034CF9EA22E5BC22005BDF21 /* MARKDOWN_REFERENCE.md */, 146 | 035BAA8E22CCB4820081B76B /* README.md */, 147 | 0324E08E1FA0847700D0AB52 /* THSideBar */, 148 | 0305FAC21F80AE3900D9B979 /* SideBarDemo */, 149 | 0305FAD31F80AE3900D9B979 /* SideBarDemoTests */, 150 | 0305FADE1F80AE3900D9B979 /* SideBarDemoUITests */, 151 | 0305FAC11F80AE3900D9B979 /* Products */, 152 | ); 153 | sourceTree = ""; 154 | }; 155 | 0305FAC11F80AE3900D9B979 /* Products */ = { 156 | isa = PBXGroup; 157 | children = ( 158 | 0305FAC01F80AE3900D9B979 /* SideBarDemo.app */, 159 | 0305FAD01F80AE3900D9B979 /* SideBarDemoTests.xctest */, 160 | 0305FADB1F80AE3900D9B979 /* SideBarDemoUITests.xctest */, 161 | ); 162 | name = Products; 163 | sourceTree = ""; 164 | }; 165 | 0305FAC21F80AE3900D9B979 /* SideBarDemo */ = { 166 | isa = PBXGroup; 167 | children = ( 168 | 034D65611FBD6BDB00D980A9 /* View */, 169 | 0305FAC31F80AE3900D9B979 /* AppDelegate.swift */, 170 | 0305FAC51F80AE3900D9B979 /* Assets.xcassets */, 171 | 0305FACA1F80AE3900D9B979 /* Info.plist */, 172 | 0373C89E1FBC04020000757D /* MainWindowController.swift */, 173 | 0373C89C1FBC03F40000757D /* MainWindowController.xib */, 174 | 0305FAC71F80AE3900D9B979 /* MainMenu.xib */, 175 | 032081DB1FA3098E000925C6 /* Resource */, 176 | 0305FACB1F80AE3900D9B979 /* SideBarDemo.entitlements */, 177 | ); 178 | path = SideBarDemo; 179 | sourceTree = ""; 180 | }; 181 | 0305FAD31F80AE3900D9B979 /* SideBarDemoTests */ = { 182 | isa = PBXGroup; 183 | children = ( 184 | 0305FAD41F80AE3900D9B979 /* SideBarDemoTests.swift */, 185 | 0305FAD61F80AE3900D9B979 /* Info.plist */, 186 | ); 187 | path = SideBarDemoTests; 188 | sourceTree = ""; 189 | }; 190 | 0305FADE1F80AE3900D9B979 /* SideBarDemoUITests */ = { 191 | isa = PBXGroup; 192 | children = ( 193 | 0305FADF1F80AE3900D9B979 /* SideBarDemoUITests.swift */, 194 | 0305FAE11F80AE3900D9B979 /* Info.plist */, 195 | ); 196 | path = SideBarDemoUITests; 197 | sourceTree = ""; 198 | }; 199 | 032081DB1FA3098E000925C6 /* Resource */ = { 200 | isa = PBXGroup; 201 | children = ( 202 | 032081E41FA30C96000925C6 /* abundance-church-family.jpg */, 203 | 032081E61FA30C96000925C6 /* hand-tuning-peg-instrument.jpg */, 204 | 032081E51FA30C96000925C6 /* mobile-phone-and-headphones-on-white-wooden-table.jpg */, 205 | 032081E91FA30C96000925C6 /* rayban-ray-bans-spectacles.jpg */, 206 | 032081EA1FA30C96000925C6 /* record-vinyl-turntable.jpg */, 207 | 032081E71FA30C96000925C6 /* vintage-radio-on-glass-table.jpg */, 208 | 032081E81FA30C96000925C6 /* woman-writing-in-music-sheet.jpg */, 209 | ); 210 | path = Resource; 211 | sourceTree = ""; 212 | }; 213 | 0324E08E1FA0847700D0AB52 /* THSideBar */ = { 214 | isa = PBXGroup; 215 | children = ( 216 | 0305FAF11F80BBA500D9B979 /* THSideBarCellView.swift */, 217 | 0361A1271F9FD05B00FED796 /* THSideBarData.swift */, 218 | 0324E0911FA0867400D0AB52 /* THSideBarDataSource.swift */, 219 | 0324E08F1FA085EF00D0AB52 /* THSideBarDelegate.swift */, 220 | 032081F21FA31F2B000925C6 /* THSideBarDragDrop.swift */, 221 | 0346867B1FC7634B0065C180 /* THTextFieldDelegate.swift */, 222 | 034D65701FBD72A300D980A9 /* THSideBarViewController.swift */, 223 | 034D65711FBD72A300D980A9 /* THSideBarViewController.xib */, 224 | ); 225 | path = THSideBar; 226 | sourceTree = ""; 227 | }; 228 | 034D65611FBD6BDB00D980A9 /* View */ = { 229 | isa = PBXGroup; 230 | children = ( 231 | 034D65621FBD6C0F00D980A9 /* ContentView1Controller.swift */, 232 | 0305FAF31F8117A600D9B979 /* ContentView1Controller.xib */, 233 | 034D65641FBD6C3100D980A9 /* ContentView2Controller.swift */, 234 | 0305FAF51F8117BC00D9B979 /* ContentView2Controller.xib */, 235 | 034D65661FBD6C5800D980A9 /* ContentView3Controller.swift */, 236 | 0305FAF71F8117D500D9B979 /* ContentView3Controller.xib */, 237 | 034D65681FBD6C7B00D980A9 /* ContentView4Controller.swift */, 238 | 032081DD1FA309BB000925C6 /* ContentView4Controller.xib */, 239 | 034D656A1FBD6CA700D980A9 /* ContentView5Controller.swift */, 240 | 032081DC1FA309BB000925C6 /* ContentView5Controller.xib */, 241 | 034D656C1FBD6CC100D980A9 /* ContentView6Controller.swift */, 242 | 032081DF1FA309BB000925C6 /* ContentView6Controller.xib */, 243 | 034D656E1FBD6CD800D980A9 /* ContentView7Controller.swift */, 244 | 032081DE1FA309BB000925C6 /* ContentView7Controller.xib */, 245 | 0336FB2222DAF11900FEC527 /* CommunController.swift */, 246 | ); 247 | path = View; 248 | sourceTree = ""; 249 | }; 250 | /* End PBXGroup section */ 251 | 252 | /* Begin PBXNativeTarget section */ 253 | 0305FABF1F80AE3900D9B979 /* SideBarDemo */ = { 254 | isa = PBXNativeTarget; 255 | buildConfigurationList = 0305FAE41F80AE3900D9B979 /* Build configuration list for PBXNativeTarget "SideBarDemo" */; 256 | buildPhases = ( 257 | 0305FABC1F80AE3900D9B979 /* Sources */, 258 | 0305FABD1F80AE3900D9B979 /* Frameworks */, 259 | 0305FABE1F80AE3900D9B979 /* Resources */, 260 | ); 261 | buildRules = ( 262 | ); 263 | dependencies = ( 264 | ); 265 | name = SideBarDemo; 266 | productName = SideBarDemo; 267 | productReference = 0305FAC01F80AE3900D9B979 /* SideBarDemo.app */; 268 | productType = "com.apple.product-type.application"; 269 | }; 270 | 0305FACF1F80AE3900D9B979 /* SideBarDemoTests */ = { 271 | isa = PBXNativeTarget; 272 | buildConfigurationList = 0305FAE71F80AE3900D9B979 /* Build configuration list for PBXNativeTarget "SideBarDemoTests" */; 273 | buildPhases = ( 274 | 0305FACC1F80AE3900D9B979 /* Sources */, 275 | 0305FACD1F80AE3900D9B979 /* Frameworks */, 276 | 0305FACE1F80AE3900D9B979 /* Resources */, 277 | ); 278 | buildRules = ( 279 | ); 280 | dependencies = ( 281 | 0305FAD21F80AE3900D9B979 /* PBXTargetDependency */, 282 | ); 283 | name = SideBarDemoTests; 284 | productName = SideBarDemoTests; 285 | productReference = 0305FAD01F80AE3900D9B979 /* SideBarDemoTests.xctest */; 286 | productType = "com.apple.product-type.bundle.unit-test"; 287 | }; 288 | 0305FADA1F80AE3900D9B979 /* SideBarDemoUITests */ = { 289 | isa = PBXNativeTarget; 290 | buildConfigurationList = 0305FAEA1F80AE3900D9B979 /* Build configuration list for PBXNativeTarget "SideBarDemoUITests" */; 291 | buildPhases = ( 292 | 0305FAD71F80AE3900D9B979 /* Sources */, 293 | 0305FAD81F80AE3900D9B979 /* Frameworks */, 294 | 0305FAD91F80AE3900D9B979 /* Resources */, 295 | ); 296 | buildRules = ( 297 | ); 298 | dependencies = ( 299 | 0305FADD1F80AE3900D9B979 /* PBXTargetDependency */, 300 | ); 301 | name = SideBarDemoUITests; 302 | productName = SideBarDemoUITests; 303 | productReference = 0305FADB1F80AE3900D9B979 /* SideBarDemoUITests.xctest */; 304 | productType = "com.apple.product-type.bundle.ui-testing"; 305 | }; 306 | /* End PBXNativeTarget section */ 307 | 308 | /* Begin PBXProject section */ 309 | 0305FAB81F80AE3900D9B979 /* Project object */ = { 310 | isa = PBXProject; 311 | attributes = { 312 | LastSwiftUpdateCheck = 0910; 313 | LastUpgradeCheck = 1100; 314 | ORGANIZATIONNAME = thierryH24; 315 | TargetAttributes = { 316 | 0305FABF1F80AE3900D9B979 = { 317 | CreatedOnToolsVersion = 9.1; 318 | LastSwiftMigration = 1020; 319 | ProvisioningStyle = Automatic; 320 | SystemCapabilities = { 321 | com.apple.Sandbox = { 322 | enabled = 0; 323 | }; 324 | }; 325 | }; 326 | 0305FACF1F80AE3900D9B979 = { 327 | CreatedOnToolsVersion = 9.1; 328 | LastSwiftMigration = 1020; 329 | ProvisioningStyle = Automatic; 330 | TestTargetID = 0305FABF1F80AE3900D9B979; 331 | }; 332 | 0305FADA1F80AE3900D9B979 = { 333 | CreatedOnToolsVersion = 9.1; 334 | LastSwiftMigration = 1020; 335 | ProvisioningStyle = Automatic; 336 | TestTargetID = 0305FABF1F80AE3900D9B979; 337 | }; 338 | }; 339 | }; 340 | buildConfigurationList = 0305FABB1F80AE3900D9B979 /* Build configuration list for PBXProject "SideBarDemo" */; 341 | compatibilityVersion = "Xcode 8.0"; 342 | developmentRegion = en; 343 | hasScannedForEncodings = 0; 344 | knownRegions = ( 345 | en, 346 | Base, 347 | ); 348 | mainGroup = 0305FAB71F80AE3900D9B979; 349 | productRefGroup = 0305FAC11F80AE3900D9B979 /* Products */; 350 | projectDirPath = ""; 351 | projectRoot = ""; 352 | targets = ( 353 | 0305FABF1F80AE3900D9B979 /* SideBarDemo */, 354 | 0305FACF1F80AE3900D9B979 /* SideBarDemoTests */, 355 | 0305FADA1F80AE3900D9B979 /* SideBarDemoUITests */, 356 | ); 357 | }; 358 | /* End PBXProject section */ 359 | 360 | /* Begin PBXResourcesBuildPhase section */ 361 | 0305FABE1F80AE3900D9B979 /* Resources */ = { 362 | isa = PBXResourcesBuildPhase; 363 | buildActionMask = 2147483647; 364 | files = ( 365 | 0305FAF41F8117A600D9B979 /* ContentView1Controller.xib in Resources */, 366 | 032081EB1FA30C97000925C6 /* abundance-church-family.jpg in Resources */, 367 | 032081E31FA309BB000925C6 /* ContentView6Controller.xib in Resources */, 368 | 0305FAF61F8117BC00D9B979 /* ContentView2Controller.xib in Resources */, 369 | 0305FAF81F8117D500D9B979 /* ContentView3Controller.xib in Resources */, 370 | 032081EC1FA30C97000925C6 /* mobile-phone-and-headphones-on-white-wooden-table.jpg in Resources */, 371 | 032081E11FA309BB000925C6 /* ContentView4Controller.xib in Resources */, 372 | 032081F01FA30C97000925C6 /* rayban-ray-bans-spectacles.jpg in Resources */, 373 | 032081ED1FA30C97000925C6 /* hand-tuning-peg-instrument.jpg in Resources */, 374 | 0373C89D1FBC03F40000757D /* MainWindowController.xib in Resources */, 375 | 0305FAC61F80AE3900D9B979 /* Assets.xcassets in Resources */, 376 | 032081F11FA30C97000925C6 /* record-vinyl-turntable.jpg in Resources */, 377 | 032081E01FA309BB000925C6 /* ContentView5Controller.xib in Resources */, 378 | 035BAA8F22CCB4820081B76B /* README.md in Resources */, 379 | 0305FAC91F80AE3900D9B979 /* MainMenu.xib in Resources */, 380 | 032081EE1FA30C97000925C6 /* vintage-radio-on-glass-table.jpg in Resources */, 381 | 032081EF1FA30C97000925C6 /* woman-writing-in-music-sheet.jpg in Resources */, 382 | 034CF9EB22E5BC22005BDF21 /* MARKDOWN_REFERENCE.md in Resources */, 383 | 034D65731FBD72A300D980A9 /* THSideBarViewController.xib in Resources */, 384 | 032081E21FA309BB000925C6 /* ContentView7Controller.xib in Resources */, 385 | ); 386 | runOnlyForDeploymentPostprocessing = 0; 387 | }; 388 | 0305FACE1F80AE3900D9B979 /* Resources */ = { 389 | isa = PBXResourcesBuildPhase; 390 | buildActionMask = 2147483647; 391 | files = ( 392 | ); 393 | runOnlyForDeploymentPostprocessing = 0; 394 | }; 395 | 0305FAD91F80AE3900D9B979 /* Resources */ = { 396 | isa = PBXResourcesBuildPhase; 397 | buildActionMask = 2147483647; 398 | files = ( 399 | ); 400 | runOnlyForDeploymentPostprocessing = 0; 401 | }; 402 | /* End PBXResourcesBuildPhase section */ 403 | 404 | /* Begin PBXSourcesBuildPhase section */ 405 | 0305FABC1F80AE3900D9B979 /* Sources */ = { 406 | isa = PBXSourcesBuildPhase; 407 | buildActionMask = 2147483647; 408 | files = ( 409 | 0305FAF21F80BBA500D9B979 /* THSideBarCellView.swift in Sources */, 410 | 0361A1281F9FD05B00FED796 /* THSideBarData.swift in Sources */, 411 | 034D656D1FBD6CC100D980A9 /* ContentView6Controller.swift in Sources */, 412 | 034D65721FBD72A300D980A9 /* THSideBarViewController.swift in Sources */, 413 | 0346867C1FC7634B0065C180 /* THTextFieldDelegate.swift in Sources */, 414 | 034D65671FBD6C5800D980A9 /* ContentView3Controller.swift in Sources */, 415 | 0336FB2322DAF11900FEC527 /* CommunController.swift in Sources */, 416 | 034D65651FBD6C3100D980A9 /* ContentView2Controller.swift in Sources */, 417 | 034D65631FBD6C0F00D980A9 /* ContentView1Controller.swift in Sources */, 418 | 034D656F1FBD6CD800D980A9 /* ContentView7Controller.swift in Sources */, 419 | 0324E0921FA0867400D0AB52 /* THSideBarDataSource.swift in Sources */, 420 | 032081F31FA31F2B000925C6 /* THSideBarDragDrop.swift in Sources */, 421 | 0324E0901FA085EF00D0AB52 /* THSideBarDelegate.swift in Sources */, 422 | 0305FAC41F80AE3900D9B979 /* AppDelegate.swift in Sources */, 423 | 0373C89F1FBC04020000757D /* MainWindowController.swift in Sources */, 424 | 034D656B1FBD6CA700D980A9 /* ContentView5Controller.swift in Sources */, 425 | 034D65691FBD6C7B00D980A9 /* ContentView4Controller.swift in Sources */, 426 | ); 427 | runOnlyForDeploymentPostprocessing = 0; 428 | }; 429 | 0305FACC1F80AE3900D9B979 /* Sources */ = { 430 | isa = PBXSourcesBuildPhase; 431 | buildActionMask = 2147483647; 432 | files = ( 433 | 0305FAD51F80AE3900D9B979 /* SideBarDemoTests.swift in Sources */, 434 | ); 435 | runOnlyForDeploymentPostprocessing = 0; 436 | }; 437 | 0305FAD71F80AE3900D9B979 /* Sources */ = { 438 | isa = PBXSourcesBuildPhase; 439 | buildActionMask = 2147483647; 440 | files = ( 441 | 0305FAE01F80AE3900D9B979 /* SideBarDemoUITests.swift in Sources */, 442 | ); 443 | runOnlyForDeploymentPostprocessing = 0; 444 | }; 445 | /* End PBXSourcesBuildPhase section */ 446 | 447 | /* Begin PBXTargetDependency section */ 448 | 0305FAD21F80AE3900D9B979 /* PBXTargetDependency */ = { 449 | isa = PBXTargetDependency; 450 | target = 0305FABF1F80AE3900D9B979 /* SideBarDemo */; 451 | targetProxy = 0305FAD11F80AE3900D9B979 /* PBXContainerItemProxy */; 452 | }; 453 | 0305FADD1F80AE3900D9B979 /* PBXTargetDependency */ = { 454 | isa = PBXTargetDependency; 455 | target = 0305FABF1F80AE3900D9B979 /* SideBarDemo */; 456 | targetProxy = 0305FADC1F80AE3900D9B979 /* PBXContainerItemProxy */; 457 | }; 458 | /* End PBXTargetDependency section */ 459 | 460 | /* Begin PBXVariantGroup section */ 461 | 0305FAC71F80AE3900D9B979 /* MainMenu.xib */ = { 462 | isa = PBXVariantGroup; 463 | children = ( 464 | 0305FAC81F80AE3900D9B979 /* Base */, 465 | ); 466 | name = MainMenu.xib; 467 | sourceTree = ""; 468 | }; 469 | /* End PBXVariantGroup section */ 470 | 471 | /* Begin XCBuildConfiguration section */ 472 | 0305FAE21F80AE3900D9B979 /* Debug */ = { 473 | isa = XCBuildConfiguration; 474 | buildSettings = { 475 | ALWAYS_SEARCH_USER_PATHS = NO; 476 | CLANG_ANALYZER_NONNULL = YES; 477 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 478 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 479 | CLANG_CXX_LIBRARY = "libc++"; 480 | CLANG_ENABLE_MODULES = YES; 481 | CLANG_ENABLE_OBJC_ARC = YES; 482 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 483 | CLANG_WARN_BOOL_CONVERSION = YES; 484 | CLANG_WARN_COMMA = YES; 485 | CLANG_WARN_CONSTANT_CONVERSION = YES; 486 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 487 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 488 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 489 | CLANG_WARN_EMPTY_BODY = YES; 490 | CLANG_WARN_ENUM_CONVERSION = YES; 491 | CLANG_WARN_INFINITE_RECURSION = YES; 492 | CLANG_WARN_INT_CONVERSION = YES; 493 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 494 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 495 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 496 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 497 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 498 | CLANG_WARN_STRICT_PROTOTYPES = YES; 499 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 500 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 501 | CLANG_WARN_UNREACHABLE_CODE = YES; 502 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 503 | CODE_SIGN_IDENTITY = "-"; 504 | COPY_PHASE_STRIP = NO; 505 | DEBUG_INFORMATION_FORMAT = dwarf; 506 | ENABLE_STRICT_OBJC_MSGSEND = YES; 507 | ENABLE_TESTABILITY = YES; 508 | GCC_C_LANGUAGE_STANDARD = gnu11; 509 | GCC_DYNAMIC_NO_PIC = NO; 510 | GCC_NO_COMMON_BLOCKS = YES; 511 | GCC_OPTIMIZATION_LEVEL = 0; 512 | GCC_PREPROCESSOR_DEFINITIONS = ( 513 | "DEBUG=1", 514 | "$(inherited)", 515 | ); 516 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 517 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 518 | GCC_WARN_UNDECLARED_SELECTOR = YES; 519 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 520 | GCC_WARN_UNUSED_FUNCTION = YES; 521 | GCC_WARN_UNUSED_VARIABLE = YES; 522 | MACOSX_DEPLOYMENT_TARGET = 10.14; 523 | MTL_ENABLE_DEBUG_INFO = YES; 524 | ONLY_ACTIVE_ARCH = YES; 525 | SDKROOT = macosx; 526 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 527 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 528 | }; 529 | name = Debug; 530 | }; 531 | 0305FAE31F80AE3900D9B979 /* Release */ = { 532 | isa = XCBuildConfiguration; 533 | buildSettings = { 534 | ALWAYS_SEARCH_USER_PATHS = NO; 535 | CLANG_ANALYZER_NONNULL = YES; 536 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 537 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 538 | CLANG_CXX_LIBRARY = "libc++"; 539 | CLANG_ENABLE_MODULES = YES; 540 | CLANG_ENABLE_OBJC_ARC = YES; 541 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 542 | CLANG_WARN_BOOL_CONVERSION = YES; 543 | CLANG_WARN_COMMA = YES; 544 | CLANG_WARN_CONSTANT_CONVERSION = YES; 545 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 546 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 547 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 548 | CLANG_WARN_EMPTY_BODY = YES; 549 | CLANG_WARN_ENUM_CONVERSION = YES; 550 | CLANG_WARN_INFINITE_RECURSION = YES; 551 | CLANG_WARN_INT_CONVERSION = YES; 552 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 553 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 554 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 555 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 556 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 557 | CLANG_WARN_STRICT_PROTOTYPES = YES; 558 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 559 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 560 | CLANG_WARN_UNREACHABLE_CODE = YES; 561 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 562 | CODE_SIGN_IDENTITY = "-"; 563 | COPY_PHASE_STRIP = NO; 564 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 565 | ENABLE_NS_ASSERTIONS = NO; 566 | ENABLE_STRICT_OBJC_MSGSEND = YES; 567 | GCC_C_LANGUAGE_STANDARD = gnu11; 568 | GCC_NO_COMMON_BLOCKS = YES; 569 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 570 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 571 | GCC_WARN_UNDECLARED_SELECTOR = YES; 572 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 573 | GCC_WARN_UNUSED_FUNCTION = YES; 574 | GCC_WARN_UNUSED_VARIABLE = YES; 575 | MACOSX_DEPLOYMENT_TARGET = 10.14; 576 | MTL_ENABLE_DEBUG_INFO = NO; 577 | SDKROOT = macosx; 578 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 579 | }; 580 | name = Release; 581 | }; 582 | 0305FAE51F80AE3900D9B979 /* Debug */ = { 583 | isa = XCBuildConfiguration; 584 | buildSettings = { 585 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 586 | CODE_SIGN_IDENTITY = "-"; 587 | CODE_SIGN_STYLE = Automatic; 588 | COMBINE_HIDPI_IMAGES = YES; 589 | INFOPLIST_FILE = SideBarDemo/Info.plist; 590 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 591 | MACOSX_DEPLOYMENT_TARGET = 10.14; 592 | MARKETING_VERSION = 2.0; 593 | PRODUCT_BUNDLE_IDENTIFIER = com.thierry24100.SideBarDemo; 594 | PRODUCT_NAME = "$(TARGET_NAME)"; 595 | SWIFT_VERSION = 5.0; 596 | }; 597 | name = Debug; 598 | }; 599 | 0305FAE61F80AE3900D9B979 /* Release */ = { 600 | isa = XCBuildConfiguration; 601 | buildSettings = { 602 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 603 | CODE_SIGN_IDENTITY = "-"; 604 | CODE_SIGN_STYLE = Automatic; 605 | COMBINE_HIDPI_IMAGES = YES; 606 | INFOPLIST_FILE = SideBarDemo/Info.plist; 607 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 608 | MACOSX_DEPLOYMENT_TARGET = 10.14; 609 | MARKETING_VERSION = 2.0; 610 | PRODUCT_BUNDLE_IDENTIFIER = com.thierry24100.SideBarDemo; 611 | PRODUCT_NAME = "$(TARGET_NAME)"; 612 | SWIFT_VERSION = 5.0; 613 | }; 614 | name = Release; 615 | }; 616 | 0305FAE81F80AE3900D9B979 /* Debug */ = { 617 | isa = XCBuildConfiguration; 618 | buildSettings = { 619 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 620 | BUNDLE_LOADER = "$(TEST_HOST)"; 621 | CODE_SIGN_STYLE = Automatic; 622 | COMBINE_HIDPI_IMAGES = YES; 623 | INFOPLIST_FILE = SideBarDemoTests/Info.plist; 624 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 625 | PRODUCT_BUNDLE_IDENTIFIER = com.thierry24100..SideBarDemoTests; 626 | PRODUCT_NAME = "$(TARGET_NAME)"; 627 | SWIFT_VERSION = 5.0; 628 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SideBarDemo.app/Contents/MacOS/SideBarDemo"; 629 | }; 630 | name = Debug; 631 | }; 632 | 0305FAE91F80AE3900D9B979 /* Release */ = { 633 | isa = XCBuildConfiguration; 634 | buildSettings = { 635 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 636 | BUNDLE_LOADER = "$(TEST_HOST)"; 637 | CODE_SIGN_STYLE = Automatic; 638 | COMBINE_HIDPI_IMAGES = YES; 639 | INFOPLIST_FILE = SideBarDemoTests/Info.plist; 640 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 641 | PRODUCT_BUNDLE_IDENTIFIER = com.thierry24100..SideBarDemoTests; 642 | PRODUCT_NAME = "$(TARGET_NAME)"; 643 | SWIFT_VERSION = 5.0; 644 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SideBarDemo.app/Contents/MacOS/SideBarDemo"; 645 | }; 646 | name = Release; 647 | }; 648 | 0305FAEB1F80AE3900D9B979 /* Debug */ = { 649 | isa = XCBuildConfiguration; 650 | buildSettings = { 651 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 652 | CODE_SIGN_STYLE = Automatic; 653 | COMBINE_HIDPI_IMAGES = YES; 654 | INFOPLIST_FILE = SideBarDemoUITests/Info.plist; 655 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 656 | PRODUCT_BUNDLE_IDENTIFIER = com.thierry24100..SideBarDemoUITests; 657 | PRODUCT_NAME = "$(TARGET_NAME)"; 658 | SWIFT_VERSION = 5.0; 659 | TEST_TARGET_NAME = SideBarDemo; 660 | }; 661 | name = Debug; 662 | }; 663 | 0305FAEC1F80AE3900D9B979 /* Release */ = { 664 | isa = XCBuildConfiguration; 665 | buildSettings = { 666 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 667 | CODE_SIGN_STYLE = Automatic; 668 | COMBINE_HIDPI_IMAGES = YES; 669 | INFOPLIST_FILE = SideBarDemoUITests/Info.plist; 670 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 671 | PRODUCT_BUNDLE_IDENTIFIER = com.thierry24100..SideBarDemoUITests; 672 | PRODUCT_NAME = "$(TARGET_NAME)"; 673 | SWIFT_VERSION = 5.0; 674 | TEST_TARGET_NAME = SideBarDemo; 675 | }; 676 | name = Release; 677 | }; 678 | /* End XCBuildConfiguration section */ 679 | 680 | /* Begin XCConfigurationList section */ 681 | 0305FABB1F80AE3900D9B979 /* Build configuration list for PBXProject "SideBarDemo" */ = { 682 | isa = XCConfigurationList; 683 | buildConfigurations = ( 684 | 0305FAE21F80AE3900D9B979 /* Debug */, 685 | 0305FAE31F80AE3900D9B979 /* Release */, 686 | ); 687 | defaultConfigurationIsVisible = 0; 688 | defaultConfigurationName = Release; 689 | }; 690 | 0305FAE41F80AE3900D9B979 /* Build configuration list for PBXNativeTarget "SideBarDemo" */ = { 691 | isa = XCConfigurationList; 692 | buildConfigurations = ( 693 | 0305FAE51F80AE3900D9B979 /* Debug */, 694 | 0305FAE61F80AE3900D9B979 /* Release */, 695 | ); 696 | defaultConfigurationIsVisible = 0; 697 | defaultConfigurationName = Release; 698 | }; 699 | 0305FAE71F80AE3900D9B979 /* Build configuration list for PBXNativeTarget "SideBarDemoTests" */ = { 700 | isa = XCConfigurationList; 701 | buildConfigurations = ( 702 | 0305FAE81F80AE3900D9B979 /* Debug */, 703 | 0305FAE91F80AE3900D9B979 /* Release */, 704 | ); 705 | defaultConfigurationIsVisible = 0; 706 | defaultConfigurationName = Release; 707 | }; 708 | 0305FAEA1F80AE3900D9B979 /* Build configuration list for PBXNativeTarget "SideBarDemoUITests" */ = { 709 | isa = XCConfigurationList; 710 | buildConfigurations = ( 711 | 0305FAEB1F80AE3900D9B979 /* Debug */, 712 | 0305FAEC1F80AE3900D9B979 /* Release */, 713 | ); 714 | defaultConfigurationIsVisible = 0; 715 | defaultConfigurationName = Release; 716 | }; 717 | /* End XCConfigurationList section */ 718 | }; 719 | rootObject = 0305FAB81F80AE3900D9B979 /* Project object */; 720 | } 721 | -------------------------------------------------------------------------------- /SideBarDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /SideBarDemo.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /SideBarDemo.xcodeproj/xcuserdata/thierryh24.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | -------------------------------------------------------------------------------- /SideBarDemo.xcodeproj/xcuserdata/thierryh24.xcuserdatad/xcschemes/SideBarDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 37 | 38 | 39 | 40 | 42 | 48 | 49 | 50 | 52 | 58 | 59 | 60 | 61 | 62 | 72 | 74 | 80 | 81 | 82 | 83 | 86 | 87 | 88 | 89 | 95 | 97 | 103 | 104 | 105 | 106 | 108 | 109 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /SideBarDemo.xcodeproj/xcuserdata/thierryh24.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | SideBarDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 0305FABF1F80AE3900D9B979 16 | 17 | primary 18 | 19 | 20 | 0305FACF1F80AE3900D9B979 21 | 22 | primary 23 | 24 | 25 | 0305FADA1F80AE3900D9B979 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /SideBarDemo/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // SideBarDemo 4 | // 5 | // Created by thierryH24 on 01/10/2017. 6 | // Copyright © 2017 thierryH24. All rights reserved. 7 | // 8 | 9 | import AppKit 10 | 11 | @NSApplicationMain 12 | class AppDelegate: NSObject, NSApplicationDelegate { 13 | 14 | @IBOutlet weak var window: NSWindow! 15 | 16 | var mainWindowController: MainWindowController? 17 | 18 | func applicationDidFinishLaunching(_ aNotification: Notification) { 19 | // Insert code here to initialize your application 20 | 21 | initializeLibraryAndShowMainWindow() 22 | } 23 | 24 | func applicationWillTerminate(_ aNotification: Notification) { 25 | // Insert code here to tear down your application 26 | } 27 | 28 | func applicationShouldTerminateAfterLastWindowClosed (_ sender: NSApplication) -> Bool 29 | { 30 | return true 31 | } 32 | 33 | func initializeLibraryAndShowMainWindow() { 34 | 35 | mainWindowController = MainWindowController(windowNibName: "MainWindowController") 36 | mainWindowController?.showWindow(self) 37 | } 38 | 39 | } 40 | 41 | -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/Department-50.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Department-50.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/Department-50.imageset/Department-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/SideBarDemo/Assets.xcassets/Department-50.imageset/Department-50.png -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/DownArrow.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "filename" : "down-arrow-light.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "filename" : "down-arrow.png", 11 | "appearances" : [ 12 | { 13 | "appearance" : "luminosity", 14 | "value" : "light" 15 | } 16 | ], 17 | "scale" : "1x" 18 | }, 19 | { 20 | "idiom" : "mac", 21 | "filename" : "down-arrow-light-1.png", 22 | "appearances" : [ 23 | { 24 | "appearance" : "luminosity", 25 | "value" : "dark" 26 | } 27 | ], 28 | "scale" : "1x" 29 | }, 30 | { 31 | "idiom" : "mac", 32 | "filename" : "down-arrow-light@2x.png", 33 | "scale" : "2x" 34 | }, 35 | { 36 | "idiom" : "mac", 37 | "filename" : "down-arrow@2x.png", 38 | "appearances" : [ 39 | { 40 | "appearance" : "luminosity", 41 | "value" : "light" 42 | } 43 | ], 44 | "scale" : "2x" 45 | }, 46 | { 47 | "idiom" : "mac", 48 | "filename" : "down-arrow-light@2x-1.png", 49 | "appearances" : [ 50 | { 51 | "appearance" : "luminosity", 52 | "value" : "dark" 53 | } 54 | ], 55 | "scale" : "2x" 56 | } 57 | ], 58 | "info" : { 59 | "version" : 1, 60 | "author" : "xcode" 61 | } 62 | } -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/DownArrow.imageset/down-arrow-light-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/SideBarDemo/Assets.xcassets/DownArrow.imageset/down-arrow-light-1.png -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/DownArrow.imageset/down-arrow-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/SideBarDemo/Assets.xcassets/DownArrow.imageset/down-arrow-light.png -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/DownArrow.imageset/down-arrow-light@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/SideBarDemo/Assets.xcassets/DownArrow.imageset/down-arrow-light@2x-1.png -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/DownArrow.imageset/down-arrow-light@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/SideBarDemo/Assets.xcassets/DownArrow.imageset/down-arrow-light@2x.png -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/DownArrow.imageset/down-arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/SideBarDemo/Assets.xcassets/DownArrow.imageset/down-arrow.png -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/DownArrow.imageset/down-arrow@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/SideBarDemo/Assets.xcassets/DownArrow.imageset/down-arrow@2x.png -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/Human_resource.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "Human_resource_icons-09-512.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/Human_resource.imageset/Human_resource_icons-09-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/SideBarDemo/Assets.xcassets/Human_resource.imageset/Human_resource_icons-09-512.png -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/RightArrow.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "filename" : "right-arrow-light.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "filename" : "right-arrow.png", 11 | "appearances" : [ 12 | { 13 | "appearance" : "luminosity", 14 | "value" : "light" 15 | } 16 | ], 17 | "scale" : "1x" 18 | }, 19 | { 20 | "idiom" : "mac", 21 | "filename" : "right-arrow-light-1.png", 22 | "appearances" : [ 23 | { 24 | "appearance" : "luminosity", 25 | "value" : "dark" 26 | } 27 | ], 28 | "scale" : "1x" 29 | }, 30 | { 31 | "idiom" : "mac", 32 | "filename" : "right-arrow-light@2x.png", 33 | "scale" : "2x" 34 | }, 35 | { 36 | "idiom" : "mac", 37 | "filename" : "right-arrow@2x.png", 38 | "appearances" : [ 39 | { 40 | "appearance" : "luminosity", 41 | "value" : "light" 42 | } 43 | ], 44 | "scale" : "2x" 45 | }, 46 | { 47 | "idiom" : "mac", 48 | "filename" : "right-arrow-light@2x-1.png", 49 | "appearances" : [ 50 | { 51 | "appearance" : "luminosity", 52 | "value" : "dark" 53 | } 54 | ], 55 | "scale" : "2x" 56 | } 57 | ], 58 | "info" : { 59 | "version" : 1, 60 | "author" : "xcode" 61 | } 62 | } -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/RightArrow.imageset/right-arrow-light-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/SideBarDemo/Assets.xcassets/RightArrow.imageset/right-arrow-light-1.png -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/RightArrow.imageset/right-arrow-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/SideBarDemo/Assets.xcassets/RightArrow.imageset/right-arrow-light.png -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/RightArrow.imageset/right-arrow-light@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/SideBarDemo/Assets.xcassets/RightArrow.imageset/right-arrow-light@2x-1.png -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/RightArrow.imageset/right-arrow-light@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/SideBarDemo/Assets.xcassets/RightArrow.imageset/right-arrow-light@2x.png -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/RightArrow.imageset/right-arrow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/SideBarDemo/Assets.xcassets/RightArrow.imageset/right-arrow.png -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/RightArrow.imageset/right-arrow@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/SideBarDemo/Assets.xcassets/RightArrow.imageset/right-arrow@2x.png -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/account.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "account.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/account.imageset/account.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/SideBarDemo/Assets.xcassets/account.imageset/account.png -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/application-sidebar-list.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "application-sidebar-list.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/application-sidebar-list.imageset/application-sidebar-list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/SideBarDemo/Assets.xcassets/application-sidebar-list.imageset/application-sidebar-list.png -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/clock.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "clock.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/clock.imageset/clock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/SideBarDemo/Assets.xcassets/clock.imageset/clock.png -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/employee.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "employee.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/employee.imageset/employee.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/SideBarDemo/Assets.xcassets/employee.imageset/employee.png -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/film.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "filename" : "film.png", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/film.imageset/film.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/SideBarDemo/Assets.xcassets/film.imageset/film.png -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/smiley.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "filename" : "smiley.png", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /SideBarDemo/Assets.xcassets/smiley.imageset/smiley.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/SideBarDemo/Assets.xcassets/smiley.imageset/smiley.png -------------------------------------------------------------------------------- /SideBarDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | $(MARKETING_VERSION) 21 | CFBundleVersion 22 | 1 23 | LSMinimumSystemVersion 24 | $(MACOSX_DEPLOYMENT_TARGET) 25 | NSHumanReadableCopyright 26 | Copyright © 2017 thierryH24. All rights reserved. 27 | NSMainNibFile 28 | MainMenu 29 | NSPrincipalClass 30 | NSApplication 31 | 32 | 33 | -------------------------------------------------------------------------------- /SideBarDemo/MainWindowController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // MainWindowController.swift 3 | // iMeteoGraph 4 | // 5 | // Created by thierryH24 on 04/11/2017. 6 | // Copyright © 2017 thierryH24. All rights reserved. 7 | // 8 | 9 | import AppKit 10 | 11 | var nameCity = "" 12 | 13 | class MainWindowController: NSWindowController { 14 | 15 | @IBOutlet weak var sourceView: NSView! 16 | @IBOutlet weak var sourceView1: NSView! 17 | 18 | @IBOutlet weak var tableTargetView: NSView! 19 | @IBOutlet weak var splitView: NSSplitView! 20 | 21 | var sideBarViewController1 : THSideBarViewController? 22 | var sideBarViewController2 : THSideBarViewController? 23 | 24 | var contentView1Controller = ContentView1Controller() 25 | var contentView2Controller = ContentView2Controller() 26 | var contentView3Controller = ContentView3Controller() 27 | var contentView4Controller = ContentView4Controller() 28 | var contentView5Controller = ContentView5Controller() 29 | var contentView6Controller = ContentView6Controller() 30 | var contentView7Controller = ContentView7Controller() 31 | 32 | override func windowDidLoad() { 33 | super.windowDidLoad() 34 | 35 | splitView.autosaveName = "splitView" 36 | splitView.minPossiblePositionOfDivider(at: 0) 37 | splitView.maxPossiblePositionOfDivider(at: 999) 38 | 39 | setUpSourceList1() 40 | setUpSourceList2() 41 | } 42 | 43 | func setUpSourceList1() 44 | { 45 | self.sideBarViewController1 = THSideBarViewController() 46 | addSubview(subView: (sideBarViewController1?.view)!, toView: sourceView) 47 | 48 | sideBarViewController1?.delegate = self 49 | sideBarViewController1?.isAllowDragAndDrop = true 50 | sideBarViewController1?.isSaveSection = false 51 | sideBarViewController1?.rowStyle = .medium 52 | sideBarViewController1?.name = "view" 53 | 54 | setUpLayoutConstraints(item: sideBarViewController1!.view, toItem: sourceView) 55 | let sections = initData1() 56 | 57 | sideBarViewController1?.initData( allSection: sections ) 58 | sideBarViewController1?.reloadData() 59 | } 60 | 61 | func initData1() -> [Section] { 62 | 63 | var section = [Section]() 64 | 65 | let item1 = Item(name:"ContentView1", icon: "Human_resource", nameView: "ContentView1Controller", badge: "10", colorBadge: .blue) 66 | let item2 = Item(name:"ContentView2", icon: "Human_resource", nameView: "ContentView2Controller", badge: "-5", colorBadge: .red) 67 | let item3 = Item(name:"ContentView3", icon: "employee", nameView: "ContentView3Controller", badge: "3", colorBadge: .blue) 68 | let item4 = Item(name:"ContentView4", icon: "employee", nameView: "ContentView4Controller", badge: "1", colorBadge: .blue) 69 | let item5 = Item(name:"ContentView5", icon: "employee", nameView: "ContentView5Controller", badge: "3", colorBadge: .blue) 70 | let item6 = Item(name:"ContentView6", icon: "employee", nameView: "ContentView6Controller", badge: "8", colorBadge: .blue) 71 | let item7 = Item(name:"ContentView7", icon: "employee", nameView: "ContentView7Controller", badge: "-1", colorBadge: .red) 72 | 73 | let sectionItem = Item(name:"Account1", icon: "Human_resource", nameView: "ContentView1Controller", badge: "10", colorBadge: .blue) 74 | var item = [Item]() 75 | item.append(item1) 76 | item.append(item2) 77 | let section1 = Section(section: sectionItem, item: item) 78 | 79 | var item20 = [Item]() 80 | item20.append(item3) 81 | item20.append(item4) 82 | item20.append(item5) 83 | item20.append(item6) 84 | item20.append(item7) 85 | let sectionItem2 = Item(name:"Account3", icon: "Human_resource", nameView: "ContentView1Controller", badge: "40", colorBadge: .blue) 86 | let section2 = Section(section: sectionItem2, item: item20) 87 | 88 | section.removeAll() 89 | section.append(section1) 90 | section.append(section2) 91 | // sideBarViewController1?.initData( allSection: section ) 92 | return section 93 | 94 | } 95 | 96 | func setUpSourceList2() 97 | { 98 | self.sideBarViewController2 = THSideBarViewController() 99 | addSubview(subView: (sideBarViewController2?.view)!, toView: sourceView1) 100 | 101 | sideBarViewController2?.delegate = self 102 | sideBarViewController2?.colorBackGround = #colorLiteral(red: 0.9764705896, green: 0.850980401, blue: 0.5490196347, alpha: 1) 103 | sideBarViewController2?.rowStyle = .small 104 | sideBarViewController2?.name = "city" 105 | sideBarViewController2?.isSaveSection = true 106 | sideBarViewController2?.isAllowDragAndDrop = true 107 | 108 | setUpLayoutConstraints(item: sideBarViewController2!.view, toItem: sourceView1) 109 | 110 | var sections = sideBarViewController2?.load() 111 | if sections?.count ?? 0 == 0 { 112 | sections = initData2() 113 | sideBarViewController2?.save() 114 | } 115 | sideBarViewController2?.initData( allSection: sections! ) 116 | sideBarViewController2?.reloadData() 117 | } 118 | 119 | func initData2() -> [Section] { 120 | 121 | var section = [Section]() 122 | 123 | sideBarViewController2?.group.title = "City" 124 | 125 | let item1 = Item(name:"London", icon: "Human_resource", nameView: "City", badge: "3", colorBadge: .blue) 126 | item1.isHidden = true 127 | 128 | let item2 = Item(name:"Paris", icon: "employee", nameView: "City", badge: "-8", colorBadge: .red) 129 | item2.isHidden = true 130 | 131 | let item3 = Item(name:"Tokyo", icon: "Human_resource", nameView: "City", badge: "-2", colorBadge: .red) 132 | let item4 = Item(name:"Mexico", icon: "employee", nameView: "City", badge: "0", colorBadge: .blue) 133 | let item5 = Item(name:"Ottawa", icon: "employee", nameView: "City", badge: "0", colorBadge: .blue) 134 | let item6 = Item(name:"Berlin", icon: "employee", nameView: "City", badge: "0", colorBadge: .blue) 135 | let item7 = Item(name:"Madrid", icon: "employee", nameView: "City", badge: "0", colorBadge: .blue) 136 | let item8 = Item(name:"Bruxelles", icon: "employee", nameView: "City", badge: "0", colorBadge: .blue) 137 | let item9 = Item(name:"New Delhi", icon: "employee", nameView: "City", badge: "0", colorBadge: .blue) 138 | let item10 = Item(name:"Washingtown", icon: "employee", nameView: "City", badge: "0", colorBadge: .blue) 139 | 140 | var item = [Item]() 141 | item.append(item1) 142 | item.append(item2) 143 | item.append(item3) 144 | item.append(item4) 145 | item.append(item5) 146 | item.append(item6) 147 | item.append(item7) 148 | item.append(item8) 149 | item.append(item9) 150 | item.append(item10) 151 | 152 | let sectionItem = Item(name:"Cities", icon: "Human_resource", nameView: "ContentView1Controller", badge: "10", colorBadge: .blue) 153 | 154 | item = item.sorted(by: { $0.name < $1.name }) 155 | let section1 = Section(section: sectionItem, item: item) 156 | 157 | section.removeAll() 158 | section.append(section1) 159 | // sideBarViewController2?.initData( allSection: section3 ) 160 | return section 161 | } 162 | 163 | func addSubview(subView: NSView, toView parentView : NSView) 164 | { 165 | let myView = parentView.subviews 166 | if myView.count > 0 167 | { 168 | parentView.replaceSubview(myView[0], with: subView) 169 | print("replace View : ", subView) 170 | } 171 | else 172 | { 173 | parentView.addSubview(subView) 174 | print("add View : ", subView) 175 | } 176 | } 177 | 178 | func setUpLayoutConstraints(item : NSView, toItem: NSView) 179 | { 180 | item.translatesAutoresizingMaskIntoConstraints = false 181 | let sourceListLayoutConstraints = [ 182 | NSLayoutConstraint(item: item, attribute: .left, relatedBy: .equal, toItem: toItem, attribute: .left, multiplier: 1, constant: 0), 183 | NSLayoutConstraint(item: item, attribute: .right, relatedBy: .equal, toItem: toItem, attribute: .right, multiplier: 1, constant: 0), 184 | NSLayoutConstraint(item: item, attribute: .top, relatedBy: .equal, toItem: toItem, attribute: .top, multiplier: 1, constant: 0), 185 | NSLayoutConstraint(item: item, attribute: .bottom, relatedBy: .equal, toItem: toItem, attribute: .bottom, multiplier: 1, constant: 0)] 186 | NSLayoutConstraint.activate(sourceListLayoutConstraints) 187 | } 188 | 189 | @IBAction func ItemPlus(_ sender: Any) { 190 | let account8 = Item(name:"Account 8", icon: "account", nameView: "ContentView4Controller", badge: "5", colorBadge: .blue) 191 | sideBarViewController1?.sections[0].item.append(account8) 192 | 193 | sideBarViewController1?.sidebarOutlineView.sizeLastColumnToFit() 194 | sideBarViewController1?.sidebarOutlineView.reloadData() 195 | } 196 | 197 | @IBAction func buttonBadgeP(_ sender: Any) { 198 | let selectedIndex = 1 199 | let badge = sideBarViewController1?.sections[0].item[selectedIndex - 1].badge 200 | var numBadge = Int(badge!) 201 | 202 | numBadge = numBadge! + 1 203 | sideBarViewController1?.sections[0].item[selectedIndex - 1].badge = String(describing: numBadge!) 204 | sideBarViewController1?.sections[0].item[selectedIndex - 1].colorBadge = numBadge! >= 0 ? .blue : .red 205 | 206 | sideBarViewController1?.sidebarOutlineView.sizeLastColumnToFit() 207 | sideBarViewController1?.sidebarOutlineView.reloadData() 208 | 209 | let item = sideBarViewController1?.sections[0].item[selectedIndex - 1] 210 | sideBarViewController1?.sidebarOutlineView.reloadItem(item) 211 | 212 | sideBarViewController1?.sidebarOutlineView.selectRowIndexes(NSIndexSet(index: selectedIndex ) as IndexSet, byExtendingSelection: false) 213 | } 214 | 215 | @IBAction func buttonBadgeM(_ sender: Any) { 216 | let selectedIndex = 1 217 | let item = sideBarViewController1?.sections[0].item[selectedIndex - 1] 218 | var numBadge = Int((item?.badge)!) 219 | 220 | numBadge = numBadge! - 1 221 | sideBarViewController1?.sections[0].item[selectedIndex - 1].badge = String(describing: numBadge!) 222 | sideBarViewController1?.sections[0].item[selectedIndex - 1].colorBadge = numBadge! >= 0 ? .blue : .red 223 | 224 | sideBarViewController1?.sidebarOutlineView.sizeLastColumnToFit() 225 | sideBarViewController1?.sidebarOutlineView.reloadData() 226 | 227 | sideBarViewController1?.sidebarOutlineView.selectRowIndexes(NSIndexSet(index: selectedIndex ) as IndexSet, byExtendingSelection: false) 228 | } 229 | } 230 | 231 | // just for the debug 232 | extension NSView { 233 | 234 | override open var description: String { 235 | let id = identifier ?? NSUserInterfaceItemIdentifier(rawValue: "view ") 236 | return "id: \(String(describing: id))" 237 | } 238 | } 239 | 240 | extension MainWindowController: THSideBarViewDelegate 241 | { 242 | func changeView(item : Item) 243 | { 244 | var vc = NSView() 245 | 246 | if item.nameView == "City" { 247 | 248 | nameCity = item.name 249 | NotificationCenter.send(.updateView) 250 | return 251 | } 252 | 253 | switch item.nameView 254 | { 255 | case "ContentView1Controller": 256 | vc = contentView1Controller.view 257 | 258 | case "ContentView2Controller": 259 | vc = contentView2Controller.view 260 | 261 | case "ContentView3Controller": 262 | vc = contentView3Controller.view 263 | 264 | case "ContentView4Controller": 265 | vc = contentView4Controller.view 266 | 267 | case "ContentView5Controller": 268 | vc = contentView5Controller.view 269 | 270 | case "ContentView6Controller": 271 | vc = contentView6Controller.view 272 | 273 | case "ContentView7Controller": 274 | vc = contentView7Controller.view 275 | 276 | default: 277 | vc = contentView1Controller.view 278 | } 279 | 280 | addSubview(subView: vc, toView: tableTargetView) 281 | vc.translatesAutoresizingMaskIntoConstraints = false 282 | 283 | var viewBindingsDict = [String: AnyObject]() 284 | viewBindingsDict["vc"] = vc 285 | tableTargetView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[vc]|", options: [], metrics: nil, views: viewBindingsDict)) 286 | tableTargetView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[vc]|", options: [], metrics: nil, views: viewBindingsDict)) 287 | } 288 | } 289 | 290 | 291 | 292 | 293 | -------------------------------------------------------------------------------- /SideBarDemo/MainWindowController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 69 | 79 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | -------------------------------------------------------------------------------- /SideBarDemo/Resource/abundance-church-family.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/SideBarDemo/Resource/abundance-church-family.jpg -------------------------------------------------------------------------------- /SideBarDemo/Resource/hand-tuning-peg-instrument.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/SideBarDemo/Resource/hand-tuning-peg-instrument.jpg -------------------------------------------------------------------------------- /SideBarDemo/Resource/mobile-phone-and-headphones-on-white-wooden-table.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/SideBarDemo/Resource/mobile-phone-and-headphones-on-white-wooden-table.jpg -------------------------------------------------------------------------------- /SideBarDemo/Resource/rayban-ray-bans-spectacles.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/SideBarDemo/Resource/rayban-ray-bans-spectacles.jpg -------------------------------------------------------------------------------- /SideBarDemo/Resource/record-vinyl-turntable.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/SideBarDemo/Resource/record-vinyl-turntable.jpg -------------------------------------------------------------------------------- /SideBarDemo/Resource/vintage-radio-on-glass-table.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/SideBarDemo/Resource/vintage-radio-on-glass-table.jpg -------------------------------------------------------------------------------- /SideBarDemo/Resource/woman-writing-in-music-sheet.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/thierryH91200/THSideBar/ae134d8e9a05363c0a53a81d4dcb61dc7194bc2d/SideBarDemo/Resource/woman-writing-in-music-sheet.jpg -------------------------------------------------------------------------------- /SideBarDemo/SideBarDemo.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /SideBarDemo/View/CommunController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CommunController.swift 3 | // SideBarDemo 4 | // 5 | // Created by thierry hentic on 14/07/2019. 6 | // Copyright © 2019 thierryH24. All rights reserved. 7 | // 8 | 9 | import AppKit 10 | 11 | 12 | class CommunController 13 | { 14 | static let shared = CommunController() 15 | 16 | func initLayer( titleView: NSView, textLayer: CATextLayer) { 17 | 18 | let titleView = titleView 19 | let textLayer = textLayer 20 | 21 | let layer = CALayer() 22 | layer.frame = titleView.frame 23 | layer.backgroundColor = NSColor.clear.cgColor 24 | titleView.layer = layer 25 | titleView.wantsLayer = true 26 | layer.layoutManager = CAConstraintLayoutManager() 27 | 28 | textLayer.frame = layer.frame 29 | textLayer.string = "" 30 | textLayer.font = "Menlo" as CFTypeRef 31 | textLayer.fontSize = 32.0 32 | textLayer.shadowOpacity = 0.5 33 | textLayer.allowsFontSubpixelQuantization = true 34 | textLayer.foregroundColor = CGColor(red: 13.0/255.0, green: 116.0/255.0, blue: 1.0, alpha: 1.0) 35 | 36 | textLayer.addConstraint(constraint(attribute: .midX, relativeTo: "superlayer", attribute2: .midX)) 37 | textLayer.addConstraint(constraint(attribute: .midY, relativeTo: "superlayer", attribute2: .midY)) 38 | 39 | layer.addSublayer(textLayer) 40 | } 41 | 42 | func constraint(attribute: CAConstraintAttribute, relativeTo: String, attribute2: CAConstraintAttribute) -> CAConstraint 43 | { 44 | return CAConstraint(attribute: attribute, relativeTo: relativeTo, attribute: attribute2) 45 | } 46 | 47 | } 48 | 49 | extension NotificationCenter { 50 | 51 | /// Send(Post) Notification 52 | static func send(_ key: Notification.Name) { 53 | self.default.post( 54 | name: key, 55 | object: nil 56 | ) 57 | } 58 | 59 | /// Receive(addObserver) Notification 60 | static func receive(instance: Any, name: Notification.Name, selector: Selector) { 61 | self.default.addObserver( 62 | instance, 63 | selector: selector, 64 | name: name, 65 | object: nil 66 | ) 67 | } 68 | 69 | /// Remove(removeObserver) Notification 70 | static func remove( instance: Any, name: Notification.Name ) { 71 | self.default.removeObserver( 72 | instance, 73 | name: name, 74 | object: nil 75 | ) 76 | } 77 | 78 | } 79 | 80 | public extension Notification.Name { 81 | 82 | static let updateView = Notification.Name( "updateView") 83 | } 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /SideBarDemo/View/ContentView1Controller.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView1Controller.swift 3 | // SideBarDemo 4 | // 5 | // Created by thierryH24 on 16/11/2017. 6 | // Copyright © 2017 thierryH24. All rights reserved. 7 | // 8 | 9 | import AppKit 10 | 11 | 12 | class ContentView1Controller: NSViewController { 13 | 14 | @IBOutlet weak var titleView: NSView! 15 | 16 | let textLayer = CATextLayer() 17 | let nameView = "View1 : " 18 | 19 | override func viewDidLoad() { 20 | super.viewDidLoad() 21 | // Do view setup here. 22 | 23 | NotificationCenter.receive(instance: self, name: .updateView, selector: #selector(UpdateView(_: ))) 24 | CommunController.shared.initLayer(titleView: titleView, textLayer: textLayer) 25 | UpdateView(Notification(name: .updateView)) 26 | } 27 | 28 | @objc func UpdateView(_ notification: Notification) { 29 | textLayer.string = nameView + nameCity 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SideBarDemo/View/ContentView1Controller.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /SideBarDemo/View/ContentView2Controller.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView2Controller.swift 3 | // SideBarDemo 4 | // 5 | // Created by thierryH24 on 16/11/2017. 6 | // Copyright © 2017 thierryH24. All rights reserved. 7 | // 8 | 9 | import AppKit 10 | 11 | 12 | class ContentView2Controller: NSViewController { 13 | 14 | @IBOutlet weak var titleView: NSView! 15 | 16 | let textLayer = CATextLayer() 17 | let nameView = "View2 : " 18 | 19 | override func viewDidLoad() { 20 | super.viewDidLoad() 21 | // Do view setup here. 22 | 23 | NotificationCenter.receive(instance: self, name: .updateView, selector: #selector(UpdateView(_: ))) 24 | CommunController.shared.initLayer(titleView: titleView, textLayer: textLayer) 25 | UpdateView(Notification(name: .updateView)) 26 | } 27 | 28 | @objc func UpdateView(_ notification: Notification) { 29 | textLayer.string = nameView + nameCity 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SideBarDemo/View/ContentView2Controller.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /SideBarDemo/View/ContentView3Controller.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView3Controller.swift 3 | // SideBarDemo 4 | // 5 | // Created by thierryH24 on 16/11/2017. 6 | // Copyright © 2017 thierryH24. All rights reserved. 7 | // 8 | 9 | import AppKit 10 | 11 | 12 | class ContentView3Controller: NSViewController { 13 | 14 | @IBOutlet weak var titleView: NSView! 15 | 16 | let textLayer = CATextLayer() 17 | let nameView = "View3 : " 18 | 19 | override func viewDidLoad() { 20 | super.viewDidLoad() 21 | // Do view setup here. 22 | 23 | NotificationCenter.receive(instance: self, name: .updateView, selector: #selector(UpdateView(_: ))) 24 | CommunController.shared.initLayer(titleView: titleView, textLayer: textLayer) 25 | UpdateView(Notification(name: .updateView)) 26 | } 27 | 28 | @objc func UpdateView(_ notification: Notification) { 29 | textLayer.string = nameView + nameCity 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SideBarDemo/View/ContentView3Controller.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /SideBarDemo/View/ContentView4Controller.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView4Controller.swift 3 | // SideBarDemo 4 | // 5 | // Created by thierryH24 on 16/11/2017. 6 | // Copyright © 2017 thierryH24. All rights reserved. 7 | // 8 | 9 | import AppKit 10 | 11 | 12 | class ContentView4Controller: NSViewController { 13 | 14 | @IBOutlet weak var titleView: NSView! 15 | 16 | let textLayer = CATextLayer() 17 | let nameView = "View4 : " 18 | 19 | override func viewDidLoad() { 20 | super.viewDidLoad() 21 | // Do view setup here. 22 | 23 | NotificationCenter.receive(instance: self, name: .updateView, selector: #selector(UpdateView(_: ))) 24 | CommunController.shared.initLayer(titleView: titleView, textLayer: textLayer) 25 | UpdateView(Notification(name: .updateView)) 26 | } 27 | 28 | @objc func UpdateView(_ notification: Notification) { 29 | textLayer.string = nameView + nameCity 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SideBarDemo/View/ContentView4Controller.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /SideBarDemo/View/ContentView5Controller.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView5Controller.swift 3 | // SideBarDemo 4 | // 5 | // Created by thierryH24 on 16/11/2017. 6 | // Copyright © 2017 thierryH24. All rights reserved. 7 | // 8 | 9 | import AppKit 10 | 11 | 12 | class ContentView5Controller: NSViewController { 13 | 14 | @IBOutlet weak var titleView: NSView! 15 | 16 | let textLayer = CATextLayer() 17 | let nameView = "View5 : " 18 | 19 | override func viewDidLoad() { 20 | super.viewDidLoad() 21 | // Do view setup here. 22 | 23 | NotificationCenter.receive(instance: self, name: .updateView, selector: #selector(UpdateView(_: ))) 24 | CommunController.shared.initLayer(titleView: titleView, textLayer: textLayer) 25 | UpdateView(Notification(name: .updateView)) 26 | } 27 | 28 | @objc func UpdateView(_ notification: Notification) { 29 | textLayer.string = nameView + nameCity 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SideBarDemo/View/ContentView5Controller.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /SideBarDemo/View/ContentView6Controller.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView6Controller.swift 3 | // SideBarDemo 4 | // 5 | // Created by thierryH24 on 16/11/2017. 6 | // Copyright © 2017 thierryH24. All rights reserved. 7 | // 8 | 9 | import AppKit 10 | 11 | 12 | class ContentView6Controller: NSViewController { 13 | 14 | @IBOutlet weak var titleView: NSView! 15 | 16 | let textLayer = CATextLayer() 17 | let nameView = "View6 : " 18 | 19 | override func viewDidLoad() { 20 | super.viewDidLoad() 21 | // Do view setup here. 22 | 23 | NotificationCenter.receive(instance: self, name: .updateView, selector: #selector(UpdateView(_: ))) 24 | CommunController.shared.initLayer(titleView: titleView, textLayer: textLayer) 25 | UpdateView(Notification(name: .updateView)) 26 | } 27 | 28 | @objc func UpdateView(_ notification: Notification) { 29 | textLayer.string = nameView + nameCity 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SideBarDemo/View/ContentView6Controller.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /SideBarDemo/View/ContentView7Controller.swift: -------------------------------------------------------------------------------- 1 | // 2 | // ContentView7Controller.swift 3 | // SideBarDemo 4 | // 5 | // Created by thierryH24 on 16/11/2017. 6 | // Copyright © 2017 thierryH24. All rights reserved. 7 | // 8 | 9 | import AppKit 10 | 11 | 12 | class ContentView7Controller: NSViewController { 13 | 14 | @IBOutlet weak var titleView: NSView! 15 | 16 | let textLayer = CATextLayer() 17 | let nameView = "View7 : " 18 | 19 | override func viewDidLoad() { 20 | super.viewDidLoad() 21 | // Do view setup here. 22 | 23 | NotificationCenter.receive(instance: self, name: .updateView, selector: #selector(UpdateView(_: ))) 24 | CommunController.shared.initLayer(titleView: titleView, textLayer: textLayer) 25 | UpdateView(Notification(name: .updateView)) 26 | } 27 | 28 | @objc func UpdateView(_ notification: Notification) { 29 | textLayer.string = nameView + nameCity 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SideBarDemo/View/ContentView7Controller.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /SideBarDemoTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /SideBarDemoTests/SideBarDemoTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SideBarDemoTests.swift 3 | // SideBarDemoTests 4 | // 5 | // Created by thierryH24 on 01/10/2017. 6 | // Copyright © 2017 thierryH24. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import SideBarDemo 11 | 12 | class SideBarDemoTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measure { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /SideBarDemoUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /SideBarDemoUITests/SideBarDemoUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SideBarDemoUITests.swift 3 | // SideBarDemoUITests 4 | // 5 | // Created by thierryH24 on 01/10/2017. 6 | // Copyright © 2017 thierryH24. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class SideBarDemoUITests: XCTestCase { 12 | 13 | override func setUp() { 14 | super.setUp() 15 | 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | 18 | // In UI tests it is usually best to stop immediately when a failure occurs. 19 | continueAfterFailure = false 20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 21 | XCUIApplication().launch() 22 | 23 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 24 | } 25 | 26 | override func tearDown() { 27 | // Put teardown code here. This method is called after the invocation of each test method in the class. 28 | super.tearDown() 29 | } 30 | 31 | func testExample() { 32 | // Use recording to get started writing UI tests. 33 | // Use XCTAssert and related functions to verify your tests produce the correct results. 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /THSideBar/THSideBarCellView.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SidebarTableCellView.swift 3 | // SideBarDemo 4 | // 5 | // Created by thierryH24 on 01/10/2017. 6 | // Copyright © 2017 thierryH24. All rights reserved. 7 | // 8 | 9 | import AppKit 10 | 11 | 12 | class KSHeaderCellView : NSTableCellView { 13 | 14 | var fillColor = #colorLiteral(red: 0.9764705896, green: 0.850980401, blue: 0.5490196347, alpha: 1) 15 | 16 | override func draw(_ dirtyRect: NSRect) { 17 | 18 | super.draw(dirtyRect) 19 | } 20 | } 21 | 22 | class THSideBarCellView: NSTableCellView { 23 | 24 | var attribut = [NSAttributedString.Key : Any] () 25 | 26 | var backgroundColor : CGColor = NSColor.green.cgColor 27 | var cornerRadius : CGFloat = 8.0 28 | var title = "0" 29 | var foregroundColor = NSColor.white 30 | var font = NSFont(name: "Avenir", size: 10.0)! 31 | 32 | @IBOutlet var button: NSButton! 33 | 34 | override func draw(_ dirtyRect: NSRect) { 35 | super.draw(dirtyRect) 36 | 37 | // Drawing code here. 38 | } 39 | 40 | // The standard rowSizeStyle does some specific layout for us. To customize layout for our button, we first call super and then modify things 41 | // Overlapping accesses to 'textFrame', but modification requires exclusive access; consider copying to a local variable 42 | override func viewWillDraw() { 43 | super.viewWillDraw() 44 | if button.isHidden == false 45 | { 46 | button.wantsLayer = true 47 | button.layer?.backgroundColor = backgroundColor 48 | button.layer?.cornerRadius = cornerRadius 49 | 50 | let paragraph = NSMutableParagraphStyle() 51 | paragraph.alignment = .center 52 | attribut[ .font] = font 53 | attribut[ .paragraphStyle] = paragraph 54 | attribut[ .foregroundColor] = foregroundColor 55 | 56 | let attributText = NSMutableAttributedString(string: title) 57 | attributText.setAttributes(attribut, range: NSMakeRange(0, attributText.length)) 58 | button.attributedTitle = attributText 59 | 60 | button.sizeToFit() 61 | var buttonFrame = button.frame 62 | buttonFrame.origin.x = self.frame.width - buttonFrame.width 63 | button.frame = buttonFrame 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /THSideBar/THSideBarData.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SideBarData.swift 3 | // SideBarDemo 4 | // 5 | // Created by thierryH24 on 25/10/2017. 6 | // Copyright © 2017 thierryH24. All rights reserved. 7 | // 8 | 9 | import AppKit 10 | 11 | public class Item : Codable { 12 | 13 | var name: String 14 | var nameView: String 15 | var icon : String 16 | var badge: String 17 | var colorBadge : NSColor 18 | var isHidden : Bool 19 | 20 | init(name: String, icon: String, nameView : String, badge : String, colorBadge : NSColor) { 21 | self.name = name 22 | self.nameView = nameView 23 | self.icon = icon 24 | self.badge = badge 25 | self.colorBadge = colorBadge 26 | self.isHidden = false 27 | } 28 | 29 | enum CodingKeys: String, CodingKey { 30 | case name = "name" 31 | case nameView = "nameView" 32 | case icon = "icon" 33 | case badge = "badge" 34 | case colorBadge = "colorBadge" 35 | case isHidden = "isHidden" 36 | } 37 | 38 | required public init(from decoder: Decoder) throws { 39 | let container = try decoder.container(keyedBy: CodingKeys.self) 40 | name = try container.decode(String.self, forKey: .name) 41 | nameView = try container.decode(String.self, forKey: .nameView) 42 | badge = try container.decode(String.self, forKey: .badge) 43 | icon = try container.decode(String.self, forKey: .icon) 44 | colorBadge = try container.decode(Color.self, forKey: .colorBadge).uiColor 45 | isHidden = try container.decode(Bool.self, forKey: .isHidden) 46 | } 47 | 48 | public func encode(to encoder: Encoder) throws { 49 | var container = encoder.container(keyedBy: CodingKeys.self) 50 | try container.encode(name, forKey: .name) 51 | try container.encode(nameView, forKey: .nameView) 52 | try container.encode(icon, forKey: .icon) 53 | try container.encode(badge, forKey: .badge) 54 | try container.encode(Color(uiColor: colorBadge), forKey: .colorBadge) 55 | try container.encode(isHidden, forKey: .isHidden) 56 | } 57 | } 58 | 59 | class Section : Codable { 60 | 61 | var section : Item 62 | var item : [Item] 63 | 64 | init(section: Item, item: [Item]) { 65 | self.section = section 66 | self.item = item 67 | } 68 | 69 | enum CodingKeys: String, CodingKey { 70 | case item = "item" 71 | case section = "section" 72 | } 73 | 74 | } 75 | 76 | public class Color : Codable { 77 | var red : CGFloat = 0.0, green: CGFloat = 0.0, blue: CGFloat = 0.0, alpha: CGFloat = 0.0 78 | 79 | var uiColor : NSColor { 80 | return NSColor(red: red, green: green, blue: blue, alpha: alpha) 81 | } 82 | 83 | init(uiColor : NSColor) { 84 | uiColor.getRed(&red, green: &green, blue: &blue, alpha: &alpha) 85 | } 86 | } 87 | 88 | extension Section: Equatable { 89 | static func == (lhs: Section, rhs: Section) -> Bool { 90 | return lhs.section.name == rhs.section.name && 91 | lhs.section.nameView == rhs.section.nameView && 92 | lhs.section.icon == rhs.section.icon 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /THSideBar/THSideBarDataSource.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SideBarDataSource.swift 3 | // SideBarDemo 4 | // 5 | // Created by thierryH24 on 25/10/2017. 6 | // Copyright © 2017 thierryH24. All rights reserved. 7 | // 8 | 9 | import AppKit 10 | 11 | extension THSideBarViewController: NSOutlineViewDataSource { 12 | 13 | /// Number of items in the sidebar 14 | func outlineView(_ outlineView: NSOutlineView, numberOfChildrenOfItem item: Any?) -> Int { 15 | 16 | var count = 0 17 | if item == nil { 18 | //at root 19 | count = sections.count 20 | } else { 21 | let section = item as! Section 22 | count = section.item.count 23 | } 24 | return count 25 | } 26 | 27 | /// Returns the child item at the specified index of a given item 28 | func outlineView(_ outlineView: NSOutlineView, child index: Int, ofItem item: Any?) -> Any { 29 | 30 | if item == nil { 31 | return sections[index] 32 | } else { 33 | let section = item as! Section 34 | return section.item[index] 35 | 36 | } 37 | } 38 | 39 | /// Whether rows are expandable by an arrow 40 | func outlineView(_ outlineView: NSOutlineView, isItemExpandable item: Any) -> Bool { 41 | if let section = item as? Section { 42 | return section.item.count > 0 43 | } else { 44 | return false 45 | } 46 | } 47 | 48 | func isSourceGroupItem(_ item: Any) -> Bool 49 | { 50 | if item is Section { 51 | return true 52 | } 53 | return false 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /THSideBar/THSideBarDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SideBarDelegate.swift 3 | // SideBarDemo 4 | // 5 | // Created by thierryH24 on 25/10/2017. 6 | // Copyright © 2017 thierryH24. All rights reserved. 7 | // 8 | 9 | import AppKit 10 | 11 | 12 | public protocol THSideBarViewDelegate : class 13 | { 14 | /// Called when a value has been selected inside the outline. 15 | func changeView( item : Item) 16 | } 17 | 18 | extension THSideBarViewController: NSOutlineViewDelegate { 19 | 20 | 21 | /// When a row is clicked on should it be selected 22 | public func outlineView(_ outlineView: NSOutlineView, shouldSelectItem item: Any) -> Bool 23 | { 24 | return !isSourceGroupItem(item) 25 | } 26 | 27 | /// Height of each row 28 | func outlineView(_ outlineView: NSOutlineView, heightOfRowByItem item: Any) -> CGFloat { 29 | if isSourceGroupItem(item) == true { 30 | return 30.0 31 | } 32 | return 20.0 33 | } 34 | 35 | /// Whether a row should be collapsed 36 | func outlineView(_ outlineView: NSOutlineView, shouldCollapseItem item: Any) -> Bool { 37 | return isSourceGroupItem(item) 38 | } 39 | 40 | func outlineView(_ outlineView: NSOutlineView, viewFor tableColumn: NSTableColumn?, item: Any) -> NSView? { 41 | 42 | if let section = item as? Section 43 | { 44 | let cell = outlineView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "FeedCellHeader"), owner: self) as! KSHeaderCellView 45 | 46 | // cell.fillColor = self.colorBackGround 47 | cell.wantsLayer = true 48 | cell.layer?.backgroundColor = self.colorBackGround.cgColor 49 | 50 | 51 | cell.textField!.stringValue = section.section.name.uppercased() 52 | // cell.imageView!.image = section.icon 53 | return cell 54 | } 55 | else if let account = item as? Item 56 | { 57 | let cell = outlineView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "FeedCell"), owner: self) as? THSideBarCellView 58 | 59 | // cell?.imageView!.image = account.icon 60 | // cell?.backgroundColor = account.colorBadge.cgColor 61 | 62 | 63 | var attribut = [NSAttributedString.Key : Any]() 64 | attribut[.foregroundColor] = NSColor.gray 65 | attribut[ .font] = NSFont.boldSystemFont(ofSize: 12.0) 66 | let attributText = NSMutableAttributedString(string: account.name ) 67 | attributText.setAttributes(attribut, range: NSMakeRange(0, attributText.length)) 68 | 69 | cell?.textField!.delegate = self 70 | cell?.textField!.attributedStringValue = attributText 71 | cell?.textField!.textColor = colorText 72 | 73 | cell?.button.isHidden = account.isHidden 74 | cell?.title = account.badge 75 | // cell?.backgroundColor = account.colorBadge.cgColor 76 | 77 | cell?.button?.bezelStyle = .inline // Make it appear as a normal label and not a button 78 | cell?.needsDisplay = true 79 | return cell 80 | } 81 | return nil 82 | } 83 | 84 | public func outlineViewSelectionDidChange(_ notification: Notification) 85 | { 86 | guard let outlineView = notification.object as? NSOutlineView else { return } 87 | 88 | let selectedIndex = outlineView.selectedRow 89 | if let item = outlineView.item(atRow: selectedIndex) as? Item 90 | { 91 | delegate?.changeView( item : item) 92 | } 93 | } 94 | 95 | } 96 | -------------------------------------------------------------------------------- /THSideBar/THSideBarDragDrop.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SideBarDataSource.swift 3 | // SideBarDemo 4 | // 5 | // Created by thierryH24 on 25/10/2017. 6 | // Copyright © 2017 thierryH24. All rights reserved. 7 | // 8 | 9 | import AppKit 10 | 11 | 12 | extension THSideBarViewController: NSPasteboardItemDataProvider { 13 | 14 | func outlineView(_ outlineView: NSOutlineView, pasteboardWriterForItem item: Any) -> NSPasteboardWriting? { 15 | 16 | let pbItem = NSPasteboardItem() 17 | if let playlist = item as? Item { 18 | 19 | pbItem.setString(playlist.name, forType: NSPasteboard.PasteboardType.string) 20 | return pbItem 21 | } 22 | return nil 23 | } 24 | 25 | func outlineView(_ outlineView: NSOutlineView, draggingSession session: NSDraggingSession, willBeginAt screenPoint: NSPoint, forItems draggedItems: [Any]) { 26 | draggedNode = draggedItems[0] as AnyObject? 27 | session.draggingPasteboard.setData(Data(), forType: NSPasteboard.PasteboardType(rawValue: REORDER_PASTEBOARD_TYPE)) 28 | debugPrint("Drag session begin") 29 | } 30 | 31 | func outlineView(_ outlineView: NSOutlineView, draggingSession session: NSDraggingSession, endedAt screenPoint: NSPoint, operation: NSDragOperation) { 32 | debugPrint("Drag session ended") 33 | self.draggedNode = nil 34 | if isSaveSection == true { 35 | save() 36 | } 37 | } 38 | 39 | func outlineView(_ outlineView: NSOutlineView, validateDrop info: NSDraggingInfo, proposedItem item: Any?, proposedChildIndex index: Int) -> NSDragOperation { 40 | 41 | let canDrag = index >= 0 //&& item != nil 42 | print(index," ", item) 43 | 44 | if canDrag == true { 45 | return .move 46 | } else { 47 | return NSDragOperation() 48 | } 49 | } 50 | 51 | func outlineView(_ outlineView: NSOutlineView, 52 | acceptDrop info: NSDraggingInfo, 53 | item: Any?, 54 | childIndex index: Int) -> Bool { 55 | 56 | guard (draggedNode is Item) == true else { return false } 57 | 58 | var retVal = false 59 | 60 | let srcItem = draggedNode as! Item 61 | let srcParent = outlineView.parent(forItem: srcItem) as? Section 62 | let fromIndex = sidebarOutlineView.childIndex(forItem: srcItem) 63 | 64 | var toIndex = index 65 | let toParent = item as? Section 66 | 67 | if toParent != nil && srcParent != nil 68 | { 69 | print("") 70 | print("move srcItem : \(srcItem.name)") 71 | print(" srcParent : \(srcParent!.section.name)") 72 | print(" fromIndex : \(fromIndex)") 73 | print("") 74 | print(" toParent : \(toParent!.section.name)") 75 | print(" toIndex : \(toIndex)") 76 | 77 | } 78 | else 79 | { 80 | print("destination or parent is nil") 81 | } 82 | 83 | guard toParent != nil else { return false } 84 | 85 | if (toIndex == NSOutlineViewDropOnItemIndex) // This should never happen, prevented in validateDrop 86 | { 87 | toIndex = 0 88 | } 89 | else if toIndex > fromIndex && srcParent == toParent { 90 | toIndex -= 1 91 | } 92 | 93 | if fromIndex != toIndex || srcParent != toParent 94 | { 95 | self.moveItemAtIndex(fromIndex : fromIndex, oldParent: srcParent, toIndex: toIndex, newParent: toParent) 96 | outlineView.moveItem(at: fromIndex, inParent: srcParent, to: toIndex, inParent: toParent) 97 | retVal = true 98 | } 99 | 100 | print(" returning:\(retVal)") 101 | return retVal 102 | } 103 | 104 | /// NSPasteboardItemDataProvider 105 | func pasteboard(_ pasteboard: NSPasteboard?, item: NSPasteboardItem, provideDataForType type: NSPasteboard.PasteboardType) 106 | { 107 | let s = "Outline Pasteboard Item" 108 | item.setString(s, forType: type) 109 | } 110 | 111 | func moveItemAtIndex( fromIndex: Int, oldParent: Section?, toIndex: Int, newParent: Section?) 112 | { 113 | // var removedSection : Section? 114 | var removedItem : Item? 115 | 116 | let oldParent = oldParent 117 | let newParent = newParent 118 | 119 | if oldParent == nil 120 | { 121 | // removedSection = self.deleteSection(element: allSection, index: fromIndex) 122 | } 123 | else 124 | { 125 | removedItem = oldParent?.item.remove(at: fromIndex) 126 | } 127 | 128 | 129 | if newParent == nil 130 | { 131 | // self.add(section: allSection, element: removedSection! , index: toIndex) 132 | } 133 | else 134 | { 135 | newParent!.item.insert(removedItem! , at: toIndex) 136 | } 137 | } 138 | 139 | } 140 | 141 | -------------------------------------------------------------------------------- /THSideBar/THSideBarViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SideBarViewController.swift 3 | // iMeteoGraph 4 | // 5 | // Created by thierryH24 on 07/11/2017. 6 | // Copyright © 2017 thierryH24. All rights reserved. 7 | // 8 | 9 | 10 | import AppKit 11 | 12 | 13 | class THSideBarViewController: NSViewController { 14 | 15 | @IBOutlet var sidebarOutlineView: JPOutliveView! 16 | @IBOutlet weak var group: NSButton! 17 | 18 | /// delegate to receive events 19 | open weak var delegate: THSideBarViewDelegate? 20 | 21 | var draggedNode:AnyObject? = nil 22 | 23 | var sections = [ Section]() 24 | 25 | var isAllowDragAndDrop = false 26 | var isSaveSection = false 27 | var colorBackGround = #colorLiteral(red: 0.721568644, green: 0.8862745166, blue: 0.5921568871, alpha: 1) 28 | var rowStyle = NSTableView.RowSizeStyle.medium 29 | var colorText = NSColor.black 30 | 31 | var selectIndex = [1] 32 | let Defaults = UserDefaults.standard 33 | var name = "" 34 | 35 | let REORDER_PASTEBOARD_TYPE = "com.outline.item" 36 | 37 | override func viewDidLoad() { 38 | super.viewDidLoad() 39 | // Do view setup here. 40 | } 41 | 42 | override open func viewDidAppear() 43 | { 44 | super.viewDidAppear() 45 | 46 | if isAllowDragAndDrop == true { 47 | // Register for the dropped object types we can accept. 48 | sidebarOutlineView.registerForDraggedTypes([NSPasteboard.PasteboardType(rawValue: REORDER_PASTEBOARD_TYPE)]) 49 | 50 | // Disable dragging items from our view to other applications. 51 | sidebarOutlineView.setDraggingSourceOperationMask(NSDragOperation(), forLocal: false) 52 | 53 | // Enable dragging items within and into our view. 54 | sidebarOutlineView.setDraggingSourceOperationMask(NSDragOperation.every, forLocal: true) 55 | } 56 | 57 | sidebarOutlineView.rowSizeStyle = rowStyle 58 | 59 | let index = sidebarOutlineView.row(forItem: 1) 60 | sidebarOutlineView.scrollRowToVisible(index) 61 | sidebarOutlineView.selectRowIndexes(IndexSet(selectIndex), byExtendingSelection: false) 62 | } 63 | 64 | func initData( allSection: [Section]) { 65 | self.sections = allSection 66 | } 67 | 68 | func reloadData() { 69 | 70 | sidebarOutlineView.sizeLastColumnToFit() 71 | sidebarOutlineView.reloadData() 72 | sidebarOutlineView.floatsGroupRows = false 73 | 74 | sidebarOutlineView.rowSizeStyle = rowStyle 75 | sidebarOutlineView.expandItem(nil, expandChildren: true) 76 | sidebarOutlineView.selectRowIndexes(IndexSet(selectIndex), byExtendingSelection: false) 77 | } 78 | 79 | 80 | func load() -> [Section] { 81 | var model = [Section]() 82 | let json = UserDefaults.standard.data(forKey: name) 83 | if let json = json { 84 | do { 85 | let decoder = JSONDecoder() 86 | model = try decoder.decode(Array
.self, from: json) 87 | return model 88 | } catch let DecodingError.dataCorrupted(context) { 89 | print(context) 90 | } catch let DecodingError.keyNotFound(key, context) { 91 | print("Key '\(key)' not found:", context.debugDescription) 92 | print("codingPath:", context.codingPath) 93 | } catch let DecodingError.valueNotFound(value, context) { 94 | print("Value '\(value)' not found:", context.debugDescription) 95 | print("codingPath:", context.codingPath) 96 | } catch let DecodingError.typeMismatch(type, context) { 97 | print("Type '\(type)' mismatch:", context.debugDescription) 98 | print("codingPath:", context.codingPath) 99 | } catch { 100 | print("error: ", error) 101 | } 102 | } 103 | return [] 104 | } 105 | 106 | func save() 107 | { 108 | do { 109 | let encoder = JSONEncoder() 110 | encoder.outputFormatting = .prettyPrinted 111 | 112 | let data = try encoder.encode(sections) 113 | Defaults.set(data, forKey: name) 114 | 115 | } catch { 116 | print("error: ", error) 117 | } 118 | } 119 | } 120 | 121 | class JPOutliveView : NSOutlineView { 122 | 123 | let kOutlineCellWidth : CGFloat = 30 124 | let kOutlineMinLeftMargin : CGFloat = 25 125 | 126 | override func makeView(withIdentifier identifier: NSUserInterfaceItemIdentifier, owner: Any?) -> NSView? { 127 | 128 | let view = super.makeView(withIdentifier:identifier, owner:owner) 129 | 130 | if identifier == NSOutlineView.disclosureButtonIdentifier 131 | { 132 | if let btnView = view as? NSButton { 133 | 134 | let targetSize = NSSize(width: 20.0, height: 20.0) 135 | let image = NSImage(named: "RightArrow")?.resized(to: targetSize) 136 | let alternateImage = NSImage(named: "DownArrow")?.resized(to: targetSize) 137 | 138 | 139 | btnView.image = image 140 | btnView.alternateImage = alternateImage 141 | 142 | btnView.frame = NSMakeRect(0, 0, 50, 50) 143 | } 144 | } 145 | return view 146 | } 147 | 148 | override func frameOfOutlineCell(atRow row: Int) -> NSRect { 149 | var superFrame = super.frameOfOutlineCell(atRow: row) 150 | superFrame.size.width = 30 151 | return superFrame 152 | } 153 | 154 | override func frameOfCell(atColumn column: Int, row: Int) -> NSRect { 155 | let superFrame = super.frameOfCell(atColumn: column, row: row) 156 | 157 | if (column == 0) { 158 | // expand by kOutlineCellWidth to the left to cancel the indent 159 | var adjustment = kOutlineCellWidth 160 | 161 | // ...but be extra defensive because we have no fucking clue what is going on here 162 | if (superFrame.origin.x - adjustment < kOutlineMinLeftMargin) { 163 | print("adjustment amount is incorrect: adjustment ") 164 | adjustment = max(0, superFrame.origin.x - kOutlineMinLeftMargin); 165 | } 166 | return NSMakeRect(superFrame.origin.x - adjustment, superFrame.origin.y, superFrame.size.width + adjustment, superFrame.size.height) 167 | 168 | } 169 | return superFrame 170 | } 171 | 172 | 173 | 174 | } 175 | 176 | extension NSImage { 177 | func resized(to newSize: NSSize) -> NSImage? { 178 | if let bitmapRep = NSBitmapImageRep( 179 | bitmapDataPlanes: nil, pixelsWide: Int(newSize.width), pixelsHigh: Int(newSize.height), 180 | bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, 181 | colorSpaceName: .calibratedRGB, bytesPerRow: 0, bitsPerPixel: 0 182 | ) { 183 | bitmapRep.size = newSize 184 | NSGraphicsContext.saveGraphicsState() 185 | NSGraphicsContext.current = NSGraphicsContext(bitmapImageRep: bitmapRep) 186 | draw(in: NSRect(x: 0, y: 0, width: newSize.width, height: newSize.height), from: .zero, operation: .copy, fraction: 1.0) 187 | NSGraphicsContext.restoreGraphicsState() 188 | 189 | let resizedImage = NSImage(size: newSize) 190 | resizedImage.addRepresentation(bitmapRep) 191 | return resizedImage 192 | } 193 | 194 | return nil 195 | } 196 | } 197 | 198 | 199 | 200 | 201 | -------------------------------------------------------------------------------- /THSideBar/THSideBarViewController.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 118 | 122 | 123 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /THSideBar/THTextFieldDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // SideBarDataSource.swift 3 | // SideBarDemo 4 | // 5 | // Created by thierryH24 on 25/10/2017. 6 | // Copyright © 2017 thierryH24. All rights reserved. 7 | // 8 | 9 | import AppKit 10 | 11 | 12 | extension THSideBarViewController: NSTextFieldDelegate { 13 | 14 | func controlTextDidEndEditing(_ obj: Notification) { 15 | 16 | let textField = obj.object as! NSTextField 17 | let row = sidebarOutlineView.row(for: textField) 18 | let item = sidebarOutlineView.item(atRow: row) 19 | 20 | if let theItem = item as? Item 21 | { 22 | theItem.name = textField.stringValue 23 | } 24 | } 25 | } 26 | --------------------------------------------------------------------------------