├── .gitignore ├── LICENSE ├── MultiSelectionSuite.xcworkspace ├── contents.xcworkspacedata └── xcuserdata │ └── sascha.xcuserdatad │ ├── UserInterfaceState.xcuserstate │ ├── WorkspaceSettings.xcsettings │ └── xcdebugger │ └── Breakpoints_v2.xcbkptlist ├── MultiSelectionSuiteApp ├── Libs │ └── SPScannerCaptureWindow.bundle │ │ └── Contents │ │ ├── Info.plist │ │ ├── MacOS │ │ └── SPScannerCaptureWindow │ │ ├── Resources │ │ ├── Base.lproj │ │ │ ├── Localizable.strings │ │ │ ├── SCWError.strings │ │ │ └── SCWWindow.nib │ │ └── de.lproj │ │ │ ├── Localizable.strings │ │ │ ├── SCWError.strings │ │ │ └── SCWWindow.strings │ │ └── _CodeSignature │ │ └── CodeResources ├── MultiSelectionSuiteApp.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── sascha.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── sascha.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ ├── MultiSelectionSuiteApp.xcscheme │ │ └── xcschememanagement.plist └── MultiSelectionSuiteApp │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Base.lproj │ ├── CaptureWindow.xib │ ├── CropImageWindow.xib │ ├── MainMenu.xib │ └── ZoomImageWindow.xib │ ├── CaptureWindow.h │ ├── CaptureWindow.m │ ├── CaptureWindow.xib │ ├── CropImageWindow.h │ ├── CropImageWindow.m │ ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── Info.plist │ ├── MainMenu.xib │ ├── SPWindowBundle.h │ ├── ZoomImageWindow.h │ ├── ZoomImageWindow.m │ ├── animals.jpg │ ├── de.lproj │ ├── CaptureWindow.strings │ ├── CropImageWindow.strings │ ├── MainMenu.strings │ └── ZoomImageWindow.strings │ └── main.m ├── MultiSelectionSuiteFramework ├── MultiSelectionSuite.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── sascha.xcuserdatad │ │ │ ├── UserInterfaceState.xcuserstate │ │ │ └── WorkspaceSettings.xcsettings │ └── xcuserdata │ │ └── sascha.xcuserdatad │ │ ├── xcdebugger │ │ └── Breakpoints_v2.xcbkptlist │ │ └── xcschemes │ │ ├── MultiSelectionSuite.xcscheme │ │ └── xcschememanagement.plist ├── MultiSelectionSuite │ ├── Classes │ │ ├── AddOns │ │ │ └── Extractors │ │ │ │ ├── MSSExtractor.h │ │ │ │ ├── MSSExtractor.m │ │ │ │ ├── MSSImageExtractor.h │ │ │ │ ├── MSSImageExtractor.m │ │ │ │ ├── MSSZoomExtractor.h │ │ │ │ └── MSSZoomExtractor.m │ │ ├── Base │ │ │ ├── MSSCanvas.h │ │ │ ├── MSSCanvas.m │ │ │ ├── MSSCanvasController.h │ │ │ ├── MSSCanvasController.m │ │ │ ├── MSSHandle.h │ │ │ ├── MSSHandle.m │ │ │ ├── MSSHandleStyle.h │ │ │ ├── MSSHandleStyle.m │ │ │ ├── MSSSelector.h │ │ │ ├── MSSSelector.m │ │ │ ├── MSSSelectorStyle.h │ │ │ └── MSSSelectorStyle.m │ │ ├── Others │ │ │ ├── BottomTop@2x.png │ │ │ ├── NSImageView+MSSScaledImage.h │ │ │ ├── NSImageView+MSSScaledImage.m │ │ │ └── TopBottom@2x.png │ │ └── Preferences │ │ │ ├── MSSError.h │ │ │ ├── MSSError.m │ │ │ ├── MSSPreferences.h │ │ │ └── MSSPreferences.m │ ├── Info.plist │ ├── MultiSelectionSuite.h │ ├── de.lproj │ │ └── MSSError.strings │ └── en.lproj │ │ └── MSSError.strings └── MultiSelectionSuiteFramework.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── sascha.xcuserdatad │ │ └── WorkspaceSettings.xcsettings │ └── xcuserdata │ └── sascha.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── MultiSelectionSuite.xcscheme │ └── xcschememanagement.plist └── README.markdown /.gitignore: -------------------------------------------------------------------------------- 1 | doc 2 | makedoc 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 ckteebe 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /MultiSelectionSuite.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /MultiSelectionSuite.xcworkspace/xcuserdata/sascha.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ckteebe/MultiSelectionSuiteFramework/e3840b1a379364416d6113c47391d408d40869b2/MultiSelectionSuite.xcworkspace/xcuserdata/sascha.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /MultiSelectionSuite.xcworkspace/xcuserdata/sascha.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildLocationStyle 6 | UseAppPreferences 7 | CustomBuildLocationType 8 | RelativeToDerivedData 9 | DerivedDataLocationStyle 10 | Default 11 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 12 | 13 | IssueFilterStyle 14 | ShowActiveSchemeOnly 15 | LiveSourceIssuesEnabled 16 | 17 | SnapshotAutomaticallyBeforeSignificantChanges 18 | 19 | SnapshotLocationStyle 20 | Default 21 | 22 | 23 | -------------------------------------------------------------------------------- /MultiSelectionSuite.xcworkspace/xcuserdata/sascha.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/Libs/SPScannerCaptureWindow.bundle/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | BuildMachineOSBuild 6 | 14B25 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleExecutable 10 | SPScannerCaptureWindow 11 | CFBundleIdentifier 12 | com.saschapaulus.bundles.scw 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | SPScannerCaptureWindow 17 | CFBundlePackageType 18 | BNDL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | DTCompiler 26 | com.apple.compilers.llvm.clang.1_0 27 | DTPlatformBuild 28 | 6A2008a 29 | DTPlatformVersion 30 | GM 31 | DTSDKBuild 32 | 14A382 33 | DTSDKName 34 | macosx10.10 35 | DTXcode 36 | 0611 37 | DTXcodeBuild 38 | 6A2008a 39 | NSHumanReadableCopyright 40 | Copyright © 2015 Sascha Paulus. All rights reserved. 41 | NSPrincipalClass 42 | SPScannerCaptureWindow 43 | 44 | 45 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/Libs/SPScannerCaptureWindow.bundle/Contents/MacOS/SPScannerCaptureWindow: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ckteebe/MultiSelectionSuiteFramework/e3840b1a379364416d6113c47391d408d40869b2/MultiSelectionSuiteApp/Libs/SPScannerCaptureWindow.bundle/Contents/MacOS/SPScannerCaptureWindow -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/Libs/SPScannerCaptureWindow.bundle/Contents/Resources/Base.lproj/Localizable.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ckteebe/MultiSelectionSuiteFramework/e3840b1a379364416d6113c47391d408d40869b2/MultiSelectionSuiteApp/Libs/SPScannerCaptureWindow.bundle/Contents/Resources/Base.lproj/Localizable.strings -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/Libs/SPScannerCaptureWindow.bundle/Contents/Resources/Base.lproj/SCWError.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ckteebe/MultiSelectionSuiteFramework/e3840b1a379364416d6113c47391d408d40869b2/MultiSelectionSuiteApp/Libs/SPScannerCaptureWindow.bundle/Contents/Resources/Base.lproj/SCWError.strings -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/Libs/SPScannerCaptureWindow.bundle/Contents/Resources/Base.lproj/SCWWindow.nib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ckteebe/MultiSelectionSuiteFramework/e3840b1a379364416d6113c47391d408d40869b2/MultiSelectionSuiteApp/Libs/SPScannerCaptureWindow.bundle/Contents/Resources/Base.lproj/SCWWindow.nib -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/Libs/SPScannerCaptureWindow.bundle/Contents/Resources/de.lproj/Localizable.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ckteebe/MultiSelectionSuiteFramework/e3840b1a379364416d6113c47391d408d40869b2/MultiSelectionSuiteApp/Libs/SPScannerCaptureWindow.bundle/Contents/Resources/de.lproj/Localizable.strings -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/Libs/SPScannerCaptureWindow.bundle/Contents/Resources/de.lproj/SCWError.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ckteebe/MultiSelectionSuiteFramework/e3840b1a379364416d6113c47391d408d40869b2/MultiSelectionSuiteApp/Libs/SPScannerCaptureWindow.bundle/Contents/Resources/de.lproj/SCWError.strings -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/Libs/SPScannerCaptureWindow.bundle/Contents/Resources/de.lproj/SCWWindow.strings: -------------------------------------------------------------------------------- 1 | 2 | /* Class = "NSButtonCell"; title = "Close"; ObjectID = "1Nw-rq-52g"; */ 3 | "1Nw-rq-52g.title" = "Schließen"; 4 | 5 | /* Class = "NSMenuItem"; title = "Item 2"; ObjectID = "1xP-DU-U3C"; */ 6 | "1xP-DU-U3C.title" = "Item 2"; 7 | 8 | /* Class = "NSTextFieldCell"; title = "Resolution"; ObjectID = "5v5-72-oeJ"; */ 9 | "5v5-72-oeJ.title" = "Auflösung"; 10 | 11 | /* Class = "NSMenuItem"; title = "Item 3"; ObjectID = "6rd-z9-dBD"; */ 12 | "6rd-z9-dBD.title" = "Item 3"; 13 | 14 | /* Class = "NSTextFieldCell"; title = "Scanner"; ObjectID = "AaU-n7-SoU"; */ 15 | "AaU-n7-SoU.title" = "Scanner"; 16 | 17 | /* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "AxK-eE-eZR"; */ 18 | "AxK-eE-eZR.title" = "Text Cell"; 19 | 20 | /* Class = "NSPanel"; title = "Scanner Settings"; ObjectID = "Bdv-du-xhP"; */ 21 | "Bdv-du-xhP.title" = "Scanner Einstellungen"; 22 | 23 | /* Class = "NSButtonCell"; title = "As PDF"; ObjectID = "BkO-LE-PiT"; */ 24 | "BkO-LE-PiT.title" = "Als PDF"; 25 | 26 | /* Class = "NSMenuItem"; title = "Item 3"; ObjectID = "E0E-Fh-ZFv"; */ 27 | "E0E-Fh-ZFv.title" = "Item 3"; 28 | 29 | /* Class = "NSButtonCell"; title = "Radio"; ObjectID = "Gja-vW-xq4"; */ 30 | "Gja-vW-xq4.title" = "Radio"; 31 | 32 | /* Class = "NSButtonCell"; title = "Black/White"; ObjectID = "KYG-IZ-Pgp"; */ 33 | "KYG-IZ-Pgp.title" = "s/w"; 34 | 35 | /* Class = "NSTextFieldCell"; title = "Table View Cell"; ObjectID = "Lgt-U8-CMs"; */ 36 | "Lgt-U8-CMs.title" = "Table View Cell"; 37 | 38 | /* Class = "NSMenuItem"; title = "Item 2"; ObjectID = "O0k-w2-tph"; */ 39 | "O0k-w2-tph.title" = "Item 2"; 40 | 41 | /* Class = "NSButtonCell"; title = "Scan & Save"; ObjectID = "OeV-B7-ct7"; */ 42 | "OeV-B7-ct7.title" = "Scannen"; 43 | 44 | /* Class = "NSMenuItem"; title = "Item 1"; ObjectID = "Prh-kt-xpt"; */ 45 | "Prh-kt-xpt.title" = "Item 1"; 46 | 47 | /* Class = "NSWindow"; title = "Window"; ObjectID = "QvC-M9-y7g"; */ 48 | "QvC-M9-y7g.title" = "Window"; 49 | 50 | /* Class = "NSBox"; title = "Box"; ObjectID = "UwR-LH-3G3"; */ 51 | "UwR-LH-3G3.title" = "Box"; 52 | 53 | /* Class = "NSMenuItem"; title = "Item 3"; ObjectID = "VRN-fb-csU"; */ 54 | "VRN-fb-csU.title" = "Item 3"; 55 | 56 | /* Class = "NSButtonCell"; title = "Preview"; ObjectID = "aZy-J8-7dH"; */ 57 | "aZy-J8-7dH.title" = "Vorschau"; 58 | 59 | /* Class = "NSTextFieldCell"; title = "Text Cell"; ObjectID = "d42-L7-Q0u"; */ 60 | "d42-L7-Q0u.title" = "Text Cell"; 61 | 62 | /* Class = "NSButtonCell"; title = "Grayscale"; ObjectID = "dpA-HZ-dW9"; */ 63 | "dpA-HZ-dW9.title" = "Graustufen"; 64 | 65 | /* Class = "NSButtonCell"; title = "Improve Image"; ObjectID = "fHC-iZ-3KH"; */ 66 | "fHC-iZ-3KH.title" = "Bild verbessern"; 67 | 68 | /* Class = "NSButtonCell"; title = "Color"; ObjectID = "jZm-8I-1Hk"; */ 69 | "jZm-8I-1Hk.title" = "Farbig"; 70 | 71 | /* Class = "NSButtonCell"; title = "Setup"; ObjectID = "li0-Dz-yUp"; */ 72 | "li0-Dz-yUp.title" = "Einstellungen"; 73 | 74 | /* Class = "NSMenuItem"; title = "Item 2"; ObjectID = "oQF-SL-T1m"; */ 75 | "oQF-SL-T1m.title" = "Item 2"; 76 | 77 | /* Class = "NSButtonCell"; title = "Cancel"; ObjectID = "t0r-Hx-eso"; */ 78 | "t0r-Hx-eso.title" = "Abbruch"; 79 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/Libs/SPScannerCaptureWindow.bundle/Contents/_CodeSignature/CodeResources: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | files 6 | 7 | Resources/Base.lproj/Localizable.strings 8 | 9 | hash 10 | 11 | tp46OnJeUpfXDWQp+jjiyi6TPZ0= 12 | 13 | optional 14 | 15 | 16 | Resources/Base.lproj/SCWError.strings 17 | 18 | hash 19 | 20 | wq7Y2pjXYsPX5j4d7MLyRySlS90= 21 | 22 | optional 23 | 24 | 25 | Resources/Base.lproj/SCWWindow.nib 26 | 27 | hash 28 | 29 | DDLJFqBPGS7TZeguM2IsIPVbrgI= 30 | 31 | optional 32 | 33 | 34 | Resources/de.lproj/Localizable.strings 35 | 36 | hash 37 | 38 | R1cgSAGQ0T2tbgi/UyjivI5T1gY= 39 | 40 | optional 41 | 42 | 43 | Resources/de.lproj/SCWError.strings 44 | 45 | hash 46 | 47 | 3Qgzb3o/CIcGeoooxSh//86pCvI= 48 | 49 | optional 50 | 51 | 52 | Resources/de.lproj/SCWWindow.strings 53 | 54 | hash 55 | 56 | 3vxlgHLHesNQRlS+ndGX81eCmBM= 57 | 58 | optional 59 | 60 | 61 | 62 | files2 63 | 64 | Resources/Base.lproj/Localizable.strings 65 | 66 | hash 67 | 68 | tp46OnJeUpfXDWQp+jjiyi6TPZ0= 69 | 70 | optional 71 | 72 | 73 | Resources/Base.lproj/SCWError.strings 74 | 75 | hash 76 | 77 | wq7Y2pjXYsPX5j4d7MLyRySlS90= 78 | 79 | optional 80 | 81 | 82 | Resources/Base.lproj/SCWWindow.nib 83 | 84 | hash 85 | 86 | DDLJFqBPGS7TZeguM2IsIPVbrgI= 87 | 88 | optional 89 | 90 | 91 | Resources/de.lproj/Localizable.strings 92 | 93 | hash 94 | 95 | R1cgSAGQ0T2tbgi/UyjivI5T1gY= 96 | 97 | optional 98 | 99 | 100 | Resources/de.lproj/SCWError.strings 101 | 102 | hash 103 | 104 | 3Qgzb3o/CIcGeoooxSh//86pCvI= 105 | 106 | optional 107 | 108 | 109 | Resources/de.lproj/SCWWindow.strings 110 | 111 | hash 112 | 113 | 3vxlgHLHesNQRlS+ndGX81eCmBM= 114 | 115 | optional 116 | 117 | 118 | 119 | rules 120 | 121 | ^Resources/ 122 | 123 | ^Resources/.*\.lproj/ 124 | 125 | optional 126 | 127 | weight 128 | 1000 129 | 130 | ^Resources/.*\.lproj/locversion.plist$ 131 | 132 | omit 133 | 134 | weight 135 | 1100 136 | 137 | ^version.plist$ 138 | 139 | 140 | rules2 141 | 142 | .*\.dSYM($|/) 143 | 144 | weight 145 | 11 146 | 147 | ^(.*/)?\.DS_Store$ 148 | 149 | omit 150 | 151 | weight 152 | 2000 153 | 154 | ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ 155 | 156 | nested 157 | 158 | weight 159 | 10 160 | 161 | ^.* 162 | 163 | ^Info\.plist$ 164 | 165 | omit 166 | 167 | weight 168 | 20 169 | 170 | ^PkgInfo$ 171 | 172 | omit 173 | 174 | weight 175 | 20 176 | 177 | ^Resources/ 178 | 179 | weight 180 | 20 181 | 182 | ^Resources/.*\.lproj/ 183 | 184 | optional 185 | 186 | weight 187 | 1000 188 | 189 | ^Resources/.*\.lproj/locversion.plist$ 190 | 191 | omit 192 | 193 | weight 194 | 1100 195 | 196 | ^[^/]+$ 197 | 198 | nested 199 | 200 | weight 201 | 10 202 | 203 | ^embedded\.provisionprofile$ 204 | 205 | weight 206 | 20 207 | 208 | ^version\.plist$ 209 | 210 | weight 211 | 20 212 | 213 | 214 | 215 | 216 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 2B08E65C1A6D6AEF00487406 /* CropImageWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2B08E65E1A6D6AEF00487406 /* CropImageWindow.xib */; }; 11 | 2B08E6611A6D6AF800487406 /* ZoomImageWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2B08E6631A6D6AF800487406 /* ZoomImageWindow.xib */; }; 12 | 2B08E67A1A6DBFD900487406 /* SPScannerCaptureWindow.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 2B08E6791A6DBFD900487406 /* SPScannerCaptureWindow.bundle */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 13 | 2B1C2AF01A65E1E900EB881C /* CropImageWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 2B1C2AEE1A65E1E900EB881C /* CropImageWindow.m */; }; 14 | 2B1C2AF51A65E1FB00EB881C /* ZoomImageWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 2B1C2AF31A65E1FB00EB881C /* ZoomImageWindow.m */; }; 15 | 2B24827E1A5AE0EE000C1F7A /* CaptureWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 2B24827C1A5AE0EE000C1F7A /* CaptureWindow.m */; }; 16 | 2B2482851A5AE1D2000C1F7A /* Quartz.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2B2482841A5AE1D2000C1F7A /* Quartz.framework */; }; 17 | 2B2482871A5AE1FC000C1F7A /* animals.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 2B2482861A5AE1FC000C1F7A /* animals.jpg */; }; 18 | 2B2482CB1A5B4656000C1F7A /* MultiSelectionSuite.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2B2482CA1A5B4656000C1F7A /* MultiSelectionSuite.framework */; }; 19 | 2B7077C61A5AC3C000707A69 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 2B7077C51A5AC3C000707A69 /* AppDelegate.m */; }; 20 | 2B7077C81A5AC3C000707A69 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2B7077C71A5AC3C000707A69 /* main.m */; }; 21 | 2B7077CA1A5AC3C000707A69 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2B7077C91A5AC3C000707A69 /* Images.xcassets */; }; 22 | 2B9549161A5C0C5E00EB11A9 /* CaptureWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2B9549141A5C0C5E00EB11A9 /* CaptureWindow.xib */; }; 23 | 2B9549181A5C0DAE00EB11A9 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2B95491A1A5C0DAE00EB11A9 /* MainMenu.xib */; }; 24 | /* End PBXBuildFile section */ 25 | 26 | /* Begin PBXCopyFilesBuildPhase section */ 27 | 2B1C2AF71A65EBEB00EB881C /* CopyFiles */ = { 28 | isa = PBXCopyFilesBuildPhase; 29 | buildActionMask = 2147483647; 30 | dstPath = ""; 31 | dstSubfolderSpec = 13; 32 | files = ( 33 | 2B08E67A1A6DBFD900487406 /* SPScannerCaptureWindow.bundle in CopyFiles */, 34 | ); 35 | runOnlyForDeploymentPostprocessing = 0; 36 | }; 37 | /* End PBXCopyFilesBuildPhase section */ 38 | 39 | /* Begin PBXFileReference section */ 40 | 2B08E6501A6D697C00487406 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 41 | 2B08E6511A6D697C00487406 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/CaptureWindow.xib; sourceTree = ""; }; 42 | 2B08E6531A6D698800487406 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/MainMenu.strings; sourceTree = ""; }; 43 | 2B08E6551A6D698C00487406 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/CaptureWindow.strings; sourceTree = ""; }; 44 | 2B08E65D1A6D6AEF00487406 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/CropImageWindow.xib; sourceTree = ""; }; 45 | 2B08E6601A6D6AF200487406 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/CropImageWindow.strings; sourceTree = ""; }; 46 | 2B08E6621A6D6AF800487406 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/ZoomImageWindow.xib; sourceTree = ""; }; 47 | 2B08E6651A6D6B5D00487406 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/ZoomImageWindow.strings; sourceTree = ""; }; 48 | 2B08E6791A6DBFD900487406 /* SPScannerCaptureWindow.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = SPScannerCaptureWindow.bundle; path = Libs/SPScannerCaptureWindow.bundle; sourceTree = ""; }; 49 | 2B1C2AED1A65E1E900EB881C /* CropImageWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CropImageWindow.h; sourceTree = ""; }; 50 | 2B1C2AEE1A65E1E900EB881C /* CropImageWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CropImageWindow.m; sourceTree = ""; }; 51 | 2B1C2AF21A65E1FB00EB881C /* ZoomImageWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ZoomImageWindow.h; sourceTree = ""; }; 52 | 2B1C2AF31A65E1FB00EB881C /* ZoomImageWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ZoomImageWindow.m; sourceTree = ""; }; 53 | 2B1C2AF81A65EBFF00EB881C /* SPScannerCaptureWindow.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = SPScannerCaptureWindow.bundle; path = "../../../../../../../Library/Developer/Xcode/DerivedData/SPScannerCaptureWindow-fcqkvrzpurajcdckqzbsffrhhfpq/Build/Products/Debug/SPScannerCaptureWindow.bundle"; sourceTree = ""; }; 54 | 2B1C2B001A65ED3200EB881C /* SPWindowBundle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SPWindowBundle.h; sourceTree = ""; }; 55 | 2B24827B1A5AE0EE000C1F7A /* CaptureWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CaptureWindow.h; sourceTree = ""; }; 56 | 2B24827C1A5AE0EE000C1F7A /* CaptureWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CaptureWindow.m; sourceTree = ""; }; 57 | 2B2482841A5AE1D2000C1F7A /* Quartz.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quartz.framework; path = System/Library/Frameworks/Quartz.framework; sourceTree = SDKROOT; }; 58 | 2B2482861A5AE1FC000C1F7A /* animals.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = animals.jpg; sourceTree = ""; }; 59 | 2B2482CA1A5B4656000C1F7A /* MultiSelectionSuite.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MultiSelectionSuite.framework; path = "../../../../../../Library/Developer/Xcode/DerivedData/MultiSelectionSuite-egxvbyyfhzsysaembhlgxpzaxisx/Build/Products/Debug/MultiSelectionSuite.framework"; sourceTree = ""; }; 60 | 2B7077BF1A5AC3C000707A69 /* MultiSelectionSuiteApp.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MultiSelectionSuiteApp.app; sourceTree = BUILT_PRODUCTS_DIR; }; 61 | 2B7077C31A5AC3C000707A69 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 62 | 2B7077C41A5AC3C000707A69 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 63 | 2B7077C51A5AC3C000707A69 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 64 | 2B7077C71A5AC3C000707A69 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 65 | 2B7077C91A5AC3C000707A69 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 66 | /* End PBXFileReference section */ 67 | 68 | /* Begin PBXFrameworksBuildPhase section */ 69 | 2B7077BC1A5AC3C000707A69 /* Frameworks */ = { 70 | isa = PBXFrameworksBuildPhase; 71 | buildActionMask = 2147483647; 72 | files = ( 73 | 2B2482CB1A5B4656000C1F7A /* MultiSelectionSuite.framework in Frameworks */, 74 | 2B2482851A5AE1D2000C1F7A /* Quartz.framework in Frameworks */, 75 | ); 76 | runOnlyForDeploymentPostprocessing = 0; 77 | }; 78 | /* End PBXFrameworksBuildPhase section */ 79 | 80 | /* Begin PBXGroup section */ 81 | 2B1C2AFA1A65EC1300EB881C /* Crop */ = { 82 | isa = PBXGroup; 83 | children = ( 84 | 2B1C2AED1A65E1E900EB881C /* CropImageWindow.h */, 85 | 2B1C2AEE1A65E1E900EB881C /* CropImageWindow.m */, 86 | 2B08E65E1A6D6AEF00487406 /* CropImageWindow.xib */, 87 | ); 88 | name = Crop; 89 | sourceTree = ""; 90 | }; 91 | 2B1C2AFB1A65EC2000EB881C /* Zoom */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | 2B1C2AF21A65E1FB00EB881C /* ZoomImageWindow.h */, 95 | 2B1C2AF31A65E1FB00EB881C /* ZoomImageWindow.m */, 96 | 2B08E6631A6D6AF800487406 /* ZoomImageWindow.xib */, 97 | ); 98 | name = Zoom; 99 | sourceTree = ""; 100 | }; 101 | 2B1C2AFC1A65EC2600EB881C /* Scan */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | 2B1C2B001A65ED3200EB881C /* SPWindowBundle.h */, 105 | 2B1C2AF81A65EBFF00EB881C /* SPScannerCaptureWindow.bundle */, 106 | ); 107 | name = Scan; 108 | sourceTree = ""; 109 | }; 110 | 2B7077B61A5AC3C000707A69 = { 111 | isa = PBXGroup; 112 | children = ( 113 | 2B08E6791A6DBFD900487406 /* SPScannerCaptureWindow.bundle */, 114 | 2B2482CA1A5B4656000C1F7A /* MultiSelectionSuite.framework */, 115 | 2B2482841A5AE1D2000C1F7A /* Quartz.framework */, 116 | 2B7077C11A5AC3C000707A69 /* MultiSelectionSuiteApp */, 117 | 2B7077C01A5AC3C000707A69 /* Products */, 118 | ); 119 | sourceTree = ""; 120 | }; 121 | 2B7077C01A5AC3C000707A69 /* Products */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 2B7077BF1A5AC3C000707A69 /* MultiSelectionSuiteApp.app */, 125 | ); 126 | name = Products; 127 | sourceTree = ""; 128 | }; 129 | 2B7077C11A5AC3C000707A69 /* MultiSelectionSuiteApp */ = { 130 | isa = PBXGroup; 131 | children = ( 132 | 2B1C2AFC1A65EC2600EB881C /* Scan */, 133 | 2B1C2AFB1A65EC2000EB881C /* Zoom */, 134 | 2B1C2AFA1A65EC1300EB881C /* Crop */, 135 | 2B95491A1A5C0DAE00EB11A9 /* MainMenu.xib */, 136 | 2B9549141A5C0C5E00EB11A9 /* CaptureWindow.xib */, 137 | 2B24827B1A5AE0EE000C1F7A /* CaptureWindow.h */, 138 | 2B24827C1A5AE0EE000C1F7A /* CaptureWindow.m */, 139 | 2B7077C41A5AC3C000707A69 /* AppDelegate.h */, 140 | 2B7077C51A5AC3C000707A69 /* AppDelegate.m */, 141 | 2B7077C91A5AC3C000707A69 /* Images.xcassets */, 142 | 2B7077C21A5AC3C000707A69 /* Supporting Files */, 143 | ); 144 | path = MultiSelectionSuiteApp; 145 | sourceTree = ""; 146 | }; 147 | 2B7077C21A5AC3C000707A69 /* Supporting Files */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | 2B2482861A5AE1FC000C1F7A /* animals.jpg */, 151 | 2B7077C31A5AC3C000707A69 /* Info.plist */, 152 | 2B7077C71A5AC3C000707A69 /* main.m */, 153 | ); 154 | name = "Supporting Files"; 155 | sourceTree = ""; 156 | }; 157 | /* End PBXGroup section */ 158 | 159 | /* Begin PBXNativeTarget section */ 160 | 2B7077BE1A5AC3C000707A69 /* MultiSelectionSuiteApp */ = { 161 | isa = PBXNativeTarget; 162 | buildConfigurationList = 2B7077DC1A5AC3C000707A69 /* Build configuration list for PBXNativeTarget "MultiSelectionSuiteApp" */; 163 | buildPhases = ( 164 | 2B7077BB1A5AC3C000707A69 /* Sources */, 165 | 2B7077BC1A5AC3C000707A69 /* Frameworks */, 166 | 2B7077BD1A5AC3C000707A69 /* Resources */, 167 | 2B1C2AF71A65EBEB00EB881C /* CopyFiles */, 168 | ); 169 | buildRules = ( 170 | ); 171 | dependencies = ( 172 | ); 173 | name = MultiSelectionSuiteApp; 174 | productName = MultiSelectionSuiteApp; 175 | productReference = 2B7077BF1A5AC3C000707A69 /* MultiSelectionSuiteApp.app */; 176 | productType = "com.apple.product-type.application"; 177 | }; 178 | /* End PBXNativeTarget section */ 179 | 180 | /* Begin PBXProject section */ 181 | 2B7077B71A5AC3C000707A69 /* Project object */ = { 182 | isa = PBXProject; 183 | attributes = { 184 | LastUpgradeCheck = 0610; 185 | ORGANIZATIONNAME = "Sascha Paulus"; 186 | TargetAttributes = { 187 | 2B7077BE1A5AC3C000707A69 = { 188 | CreatedOnToolsVersion = 6.1; 189 | }; 190 | }; 191 | }; 192 | buildConfigurationList = 2B7077BA1A5AC3C000707A69 /* Build configuration list for PBXProject "MultiSelectionSuiteApp" */; 193 | compatibilityVersion = "Xcode 3.2"; 194 | developmentRegion = English; 195 | hasScannedForEncodings = 0; 196 | knownRegions = ( 197 | en, 198 | de, 199 | Base, 200 | ); 201 | mainGroup = 2B7077B61A5AC3C000707A69; 202 | productRefGroup = 2B7077C01A5AC3C000707A69 /* Products */; 203 | projectDirPath = ""; 204 | projectRoot = ""; 205 | targets = ( 206 | 2B7077BE1A5AC3C000707A69 /* MultiSelectionSuiteApp */, 207 | ); 208 | }; 209 | /* End PBXProject section */ 210 | 211 | /* Begin PBXResourcesBuildPhase section */ 212 | 2B7077BD1A5AC3C000707A69 /* Resources */ = { 213 | isa = PBXResourcesBuildPhase; 214 | buildActionMask = 2147483647; 215 | files = ( 216 | 2B08E6611A6D6AF800487406 /* ZoomImageWindow.xib in Resources */, 217 | 2B7077CA1A5AC3C000707A69 /* Images.xcassets in Resources */, 218 | 2B9549181A5C0DAE00EB11A9 /* MainMenu.xib in Resources */, 219 | 2B9549161A5C0C5E00EB11A9 /* CaptureWindow.xib in Resources */, 220 | 2B08E65C1A6D6AEF00487406 /* CropImageWindow.xib in Resources */, 221 | 2B2482871A5AE1FC000C1F7A /* animals.jpg in Resources */, 222 | ); 223 | runOnlyForDeploymentPostprocessing = 0; 224 | }; 225 | /* End PBXResourcesBuildPhase section */ 226 | 227 | /* Begin PBXSourcesBuildPhase section */ 228 | 2B7077BB1A5AC3C000707A69 /* Sources */ = { 229 | isa = PBXSourcesBuildPhase; 230 | buildActionMask = 2147483647; 231 | files = ( 232 | 2B7077C81A5AC3C000707A69 /* main.m in Sources */, 233 | 2B1C2AF51A65E1FB00EB881C /* ZoomImageWindow.m in Sources */, 234 | 2B7077C61A5AC3C000707A69 /* AppDelegate.m in Sources */, 235 | 2B24827E1A5AE0EE000C1F7A /* CaptureWindow.m in Sources */, 236 | 2B1C2AF01A65E1E900EB881C /* CropImageWindow.m in Sources */, 237 | ); 238 | runOnlyForDeploymentPostprocessing = 0; 239 | }; 240 | /* End PBXSourcesBuildPhase section */ 241 | 242 | /* Begin PBXVariantGroup section */ 243 | 2B08E65E1A6D6AEF00487406 /* CropImageWindow.xib */ = { 244 | isa = PBXVariantGroup; 245 | children = ( 246 | 2B08E65D1A6D6AEF00487406 /* Base */, 247 | 2B08E6601A6D6AF200487406 /* de */, 248 | ); 249 | name = CropImageWindow.xib; 250 | sourceTree = ""; 251 | }; 252 | 2B08E6631A6D6AF800487406 /* ZoomImageWindow.xib */ = { 253 | isa = PBXVariantGroup; 254 | children = ( 255 | 2B08E6621A6D6AF800487406 /* Base */, 256 | 2B08E6651A6D6B5D00487406 /* de */, 257 | ); 258 | name = ZoomImageWindow.xib; 259 | sourceTree = ""; 260 | }; 261 | 2B9549141A5C0C5E00EB11A9 /* CaptureWindow.xib */ = { 262 | isa = PBXVariantGroup; 263 | children = ( 264 | 2B08E6511A6D697C00487406 /* Base */, 265 | 2B08E6551A6D698C00487406 /* de */, 266 | ); 267 | name = CaptureWindow.xib; 268 | sourceTree = ""; 269 | }; 270 | 2B95491A1A5C0DAE00EB11A9 /* MainMenu.xib */ = { 271 | isa = PBXVariantGroup; 272 | children = ( 273 | 2B08E6501A6D697C00487406 /* Base */, 274 | 2B08E6531A6D698800487406 /* de */, 275 | ); 276 | name = MainMenu.xib; 277 | sourceTree = ""; 278 | }; 279 | /* End PBXVariantGroup section */ 280 | 281 | /* Begin XCBuildConfiguration section */ 282 | 2B7077DA1A5AC3C000707A69 /* Debug */ = { 283 | isa = XCBuildConfiguration; 284 | buildSettings = { 285 | ALWAYS_SEARCH_USER_PATHS = NO; 286 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 287 | CLANG_CXX_LIBRARY = "libc++"; 288 | CLANG_ENABLE_MODULES = YES; 289 | CLANG_ENABLE_OBJC_ARC = YES; 290 | CLANG_WARN_BOOL_CONVERSION = YES; 291 | CLANG_WARN_CONSTANT_CONVERSION = YES; 292 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 293 | CLANG_WARN_EMPTY_BODY = YES; 294 | CLANG_WARN_ENUM_CONVERSION = YES; 295 | CLANG_WARN_INT_CONVERSION = YES; 296 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 297 | CLANG_WARN_UNREACHABLE_CODE = YES; 298 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 299 | CODE_SIGN_IDENTITY = "-"; 300 | COPY_PHASE_STRIP = NO; 301 | ENABLE_STRICT_OBJC_MSGSEND = YES; 302 | GCC_C_LANGUAGE_STANDARD = gnu99; 303 | GCC_DYNAMIC_NO_PIC = NO; 304 | GCC_OPTIMIZATION_LEVEL = 0; 305 | GCC_PREPROCESSOR_DEFINITIONS = ( 306 | "DEBUG=1", 307 | "$(inherited)", 308 | ); 309 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 310 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 311 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 312 | GCC_WARN_UNDECLARED_SELECTOR = YES; 313 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 314 | GCC_WARN_UNUSED_FUNCTION = YES; 315 | GCC_WARN_UNUSED_VARIABLE = YES; 316 | HEADER_SEARCH_PATHS = ( 317 | "$(inherited)", 318 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 319 | ); 320 | MACOSX_DEPLOYMENT_TARGET = 10.8; 321 | MTL_ENABLE_DEBUG_INFO = YES; 322 | ONLY_ACTIVE_ARCH = YES; 323 | SDKROOT = macosx; 324 | }; 325 | name = Debug; 326 | }; 327 | 2B7077DB1A5AC3C000707A69 /* Release */ = { 328 | isa = XCBuildConfiguration; 329 | buildSettings = { 330 | ALWAYS_SEARCH_USER_PATHS = NO; 331 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 332 | CLANG_CXX_LIBRARY = "libc++"; 333 | CLANG_ENABLE_MODULES = YES; 334 | CLANG_ENABLE_OBJC_ARC = YES; 335 | CLANG_WARN_BOOL_CONVERSION = YES; 336 | CLANG_WARN_CONSTANT_CONVERSION = YES; 337 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 338 | CLANG_WARN_EMPTY_BODY = YES; 339 | CLANG_WARN_ENUM_CONVERSION = YES; 340 | CLANG_WARN_INT_CONVERSION = YES; 341 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 342 | CLANG_WARN_UNREACHABLE_CODE = YES; 343 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 344 | CODE_SIGN_IDENTITY = "-"; 345 | COPY_PHASE_STRIP = YES; 346 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 347 | ENABLE_NS_ASSERTIONS = NO; 348 | ENABLE_STRICT_OBJC_MSGSEND = YES; 349 | GCC_C_LANGUAGE_STANDARD = gnu99; 350 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 351 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 352 | GCC_WARN_UNDECLARED_SELECTOR = YES; 353 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 354 | GCC_WARN_UNUSED_FUNCTION = YES; 355 | GCC_WARN_UNUSED_VARIABLE = YES; 356 | HEADER_SEARCH_PATHS = ( 357 | "$(inherited)", 358 | /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, 359 | ); 360 | MACOSX_DEPLOYMENT_TARGET = 10.8; 361 | MTL_ENABLE_DEBUG_INFO = NO; 362 | SDKROOT = macosx; 363 | }; 364 | name = Release; 365 | }; 366 | 2B7077DD1A5AC3C000707A69 /* Debug */ = { 367 | isa = XCBuildConfiguration; 368 | buildSettings = { 369 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 370 | COMBINE_HIDPI_IMAGES = YES; 371 | FRAMEWORK_SEARCH_PATHS = ( 372 | "$(inherited)", 373 | /Users/sascha/Desktop, 374 | "$(PROJECT_DIR)", 375 | "$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/MultiSelectionSuite-daemarwshbwuqqaxicrxiitewggc/Build/Products/Debug", 376 | "$(LOCAL_LIBRARY_DIR)/Frameworks", 377 | /Users/sascha/DATEN/DEV/Mac/OpenSource/MultiSelectionSuite/MultiSelectionSuiteFramework/build/Debug, 378 | "$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/MultiSelectionSuite-egxvbyyfhzsysaembhlgxpzaxisx/Build/Products/Debug", 379 | ); 380 | INFOPLIST_FILE = MultiSelectionSuiteApp/Info.plist; 381 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 382 | PRODUCT_NAME = "$(TARGET_NAME)"; 383 | }; 384 | name = Debug; 385 | }; 386 | 2B7077DE1A5AC3C000707A69 /* Release */ = { 387 | isa = XCBuildConfiguration; 388 | buildSettings = { 389 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 390 | COMBINE_HIDPI_IMAGES = YES; 391 | FRAMEWORK_SEARCH_PATHS = ( 392 | "$(inherited)", 393 | /Users/sascha/Desktop, 394 | "$(PROJECT_DIR)", 395 | "$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/MultiSelectionSuite-daemarwshbwuqqaxicrxiitewggc/Build/Products/Debug", 396 | "$(LOCAL_LIBRARY_DIR)/Frameworks", 397 | /Users/sascha/DATEN/DEV/Mac/OpenSource/MultiSelectionSuite/MultiSelectionSuiteFramework/build/Debug, 398 | "$(USER_LIBRARY_DIR)/Developer/Xcode/DerivedData/MultiSelectionSuite-egxvbyyfhzsysaembhlgxpzaxisx/Build/Products/Debug", 399 | ); 400 | INFOPLIST_FILE = MultiSelectionSuiteApp/Info.plist; 401 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 402 | PRODUCT_NAME = "$(TARGET_NAME)"; 403 | }; 404 | name = Release; 405 | }; 406 | /* End XCBuildConfiguration section */ 407 | 408 | /* Begin XCConfigurationList section */ 409 | 2B7077BA1A5AC3C000707A69 /* Build configuration list for PBXProject "MultiSelectionSuiteApp" */ = { 410 | isa = XCConfigurationList; 411 | buildConfigurations = ( 412 | 2B7077DA1A5AC3C000707A69 /* Debug */, 413 | 2B7077DB1A5AC3C000707A69 /* Release */, 414 | ); 415 | defaultConfigurationIsVisible = 0; 416 | defaultConfigurationName = Release; 417 | }; 418 | 2B7077DC1A5AC3C000707A69 /* Build configuration list for PBXNativeTarget "MultiSelectionSuiteApp" */ = { 419 | isa = XCConfigurationList; 420 | buildConfigurations = ( 421 | 2B7077DD1A5AC3C000707A69 /* Debug */, 422 | 2B7077DE1A5AC3C000707A69 /* Release */, 423 | ); 424 | defaultConfigurationIsVisible = 0; 425 | defaultConfigurationName = Release; 426 | }; 427 | /* End XCConfigurationList section */ 428 | }; 429 | rootObject = 2B7077B71A5AC3C000707A69 /* Project object */; 430 | } 431 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp.xcodeproj/project.xcworkspace/xcuserdata/sascha.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ckteebe/MultiSelectionSuiteFramework/e3840b1a379364416d6113c47391d408d40869b2/MultiSelectionSuiteApp/MultiSelectionSuiteApp.xcodeproj/project.xcworkspace/xcuserdata/sascha.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp.xcodeproj/xcuserdata/sascha.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp.xcodeproj/xcuserdata/sascha.xcuserdatad/xcschemes/MultiSelectionSuiteApp.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 94 | 100 | 101 | 102 | 103 | 105 | 106 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp.xcodeproj/xcuserdata/sascha.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | MultiSelectionSuiteApp.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 2B7077BE1A5AC3C000707A69 16 | 17 | primary 18 | 19 | 20 | 2B7077D11A5AC3C000707A69 21 | 22 | primary 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp/AppDelegate.h: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | 4 | @class CaptureWindow; 5 | 6 | @interface AppDelegate : NSObject 7 | 8 | @property CaptureWindow *window; 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp/AppDelegate.m: -------------------------------------------------------------------------------- 1 | 2 | 3 | #import "AppDelegate.h" 4 | #import "CaptureWindow.h" 5 | 6 | @interface AppDelegate () 7 | 8 | @end 9 | 10 | 11 | @implementation AppDelegate 12 | 13 | @synthesize window; 14 | 15 | - (void)awakeFromNib { 16 | 17 | 18 | } 19 | 20 | 21 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { 22 | 23 | if (!window) { 24 | window = [[CaptureWindow alloc] initWithWindowNibName:@"CaptureWindow"]; 25 | } 26 | [window showWindow:nil]; 27 | 28 | } 29 | 30 | 31 | 32 | - (void)applicationWillTerminate:(NSNotification *)aNotification { 33 | // Insert code here to tear down your application 34 | } 35 | 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp/Base.lproj/CaptureWindow.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 33 | 43 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp/Base.lproj/CropImageWindow.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 | 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 | 89 | 90 | 91 | 92 | 93 | 94 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp/Base.lproj/MainMenu.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 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp/Base.lproj/ZoomImageWindow.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 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp/CaptureWindow.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ------------------------------------------------------------------------------------ 4 | CaptureWindow.h 5 | ------------------------------------------------------------------------------------ 6 | Just the window controller from where everything begins. 7 | Tipp: For a quick start please read the README document. 8 | ------------------------------------------------------------------------------------ 9 | 10 | The MIT License (MIT) 11 | 12 | Copyright (c) 2014 Sascha Paulus 13 | 14 | Permission is hereby granted, free of charge, to any person obtaining a copy 15 | of this software and associated documentation files (the "Software"), to deal 16 | in the Software without restriction, including without limitation the rights 17 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | copies of the Software, and to permit persons to whom the Software is 19 | furnished to do so, subject to the following conditions: 20 | 21 | The above copyright notice and this permission notice shall be included in all 22 | copies or substantial portions of the Software. 23 | 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | SOFTWARE. 31 | 32 | */ 33 | 34 | #import 35 | #import "CropImageWindow.h" 36 | #import "ZoomImageWindow.h" 37 | #import "SPWindowBundle.h" 38 | 39 | @interface CaptureWindow : NSWindowController 40 | 41 | @property (nonatomic) NSWindowController *cropImageWindow; 42 | @property (nonatomic) NSWindowController *zoomImageWindow; 43 | 44 | - (IBAction)cropImage:(id)sender; 45 | - (IBAction)zoomImage:(id)sender; 46 | - (IBAction)scanWindow:(id)sender; 47 | 48 | @end 49 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp/CaptureWindow.m: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ------------------------------------------------------------------------------------ 4 | CaptureWindow.m 5 | ------------------------------------------------------------------------------------ 6 | Just the window controller from where everything begins. 7 | Tipp: For a quick start please read the README document. 8 | ------------------------------------------------------------------------------------ 9 | 10 | The MIT License (MIT) 11 | 12 | Copyright (c) 2014 Sascha Paulus 13 | 14 | Permission is hereby granted, free of charge, to any person obtaining a copy 15 | of this software and associated documentation files (the "Software"), to deal 16 | in the Software without restriction, including without limitation the rights 17 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | copies of the Software, and to permit persons to whom the Software is 19 | furnished to do so, subject to the following conditions: 20 | 21 | The above copyright notice and this permission notice shall be included in all 22 | copies or substantial portions of the Software. 23 | 24 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | SOFTWARE. 31 | 32 | */ 33 | 34 | 35 | #import "CaptureWindow.h" 36 | 37 | @interface CaptureWindow () 38 | @property (nonatomic,strong) SPWindowBundle *scanBundle; 39 | @end 40 | 41 | @implementation CaptureWindow 42 | 43 | - (void)cropImage:(id)sender { 44 | 45 | if(!self.cropImageWindow) { 46 | self.cropImageWindow = [[CropImageWindow alloc] init]; 47 | } 48 | [self.cropImageWindow showWindow:self]; 49 | 50 | } 51 | 52 | 53 | - (void)zoomImage:(id)sender { 54 | if(!self.zoomImageWindow) { 55 | self.zoomImageWindow = [[ZoomImageWindow alloc] init]; 56 | } 57 | [self.zoomImageWindow showWindow:self]; 58 | 59 | } 60 | 61 | - (void)scanWindow:(id)sender { 62 | 63 | NSURL *pluginUrl = [[[NSBundle mainBundle] builtInPlugInsURL] URLByAppendingPathComponent:@"SPScannerCaptureWindow.bundle"]; 64 | 65 | NSBundle *scannerBundle = [NSBundle bundleWithURL:pluginUrl]; 66 | 67 | id currInstance; 68 | Class currPrincipalClass = [scannerBundle principalClass]; 69 | if (currPrincipalClass) { 70 | currInstance = [[currPrincipalClass alloc] init]; 71 | } 72 | 73 | 74 | if(currInstance) { 75 | self.scanBundle = (SPWindowBundle *)currInstance; 76 | [self.scanBundle openWindowWithDelegate:self asSheet:YES]; 77 | } 78 | 79 | } 80 | 81 | #pragma mark - ScannerCaptureWindowDelegate 82 | 83 | - (void)saveContentElements:(NSArray *)elements withProperties:(NSDictionary *)properties { 84 | NSLog(@"Your scanned Images are here: saveContentElements"); 85 | } 86 | 87 | @end 88 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp/CropImageWindow.h: -------------------------------------------------------------------------------- 1 | // 2 | // CropImageWindow.h 3 | // MultiSelectionSuiteApp 4 | // 5 | // Created by Sascha Paulus on 14.01.15. 6 | // Copyright (c) 2015 Sascha Paulus. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface CropImageWindow : NSWindowController 13 | 14 | @property (nonatomic) IBOutlet NSImageView *imageView; 15 | @property (nonatomic) IBOutlet MSSImageExtractor *imageExtractor; 16 | 17 | - (IBAction)saveImages:(id)sender; 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp/CropImageWindow.m: -------------------------------------------------------------------------------- 1 | // 2 | // CropImageWindow.m 3 | // MultiSelectionSuiteApp 4 | // 5 | // Created by Sascha Paulus on 14.01.15. 6 | // Copyright (c) 2015 Sascha Paulus. All rights reserved. 7 | // 8 | 9 | #import "CropImageWindow.h" 10 | 11 | @interface CropImageWindow () 12 | 13 | @end 14 | 15 | @implementation CropImageWindow 16 | 17 | @synthesize imageExtractor; 18 | 19 | - (NSString *)windowNibName { 20 | return @"CropImageWindow"; 21 | } 22 | 23 | - (void)awakeFromNib { 24 | 25 | // Set an example image 26 | NSImage *exampleImage = [NSImage imageNamed:@"animals"]; 27 | [self.imageView setImage:exampleImage]; 28 | 29 | } 30 | 31 | #pragma mark - MSSExtractorDelegate 32 | 33 | - (void) extractor:(MSSExtractor*)extractor extractElement:(id)element forJob:(NSString*)identifier { 34 | 35 | if ([element isKindOfClass:[NSImage class]]) { 36 | 37 | // NSImage *image = (NSImage*)element; 38 | 39 | if ([identifier isEqualToString:MSSExtractorJobCropping]) { 40 | 41 | } 42 | } 43 | 44 | 45 | } 46 | 47 | 48 | - (void) extractor:(MSSExtractor*)extractor didCompleteWithError:(NSError*)error { 49 | 50 | if(error == nil) { 51 | 52 | // If everything is good ask extractor to save the images 53 | NSOpenPanel *openDialog = [NSOpenPanel openPanel]; 54 | [openDialog setCanChooseDirectories:YES]; 55 | [openDialog setCanChooseFiles:NO]; 56 | [openDialog setAllowsMultipleSelection:NO]; 57 | if( [openDialog runModal] == NSModalResponseOK) { 58 | [extractor setSaveDirectory:[openDialog directoryURL]]; 59 | for(NSImage *image in extractor.elements) { 60 | [extractor saveImage:image withType:NSJPEGFileType compression:ExtractorImageCompressionLevelNone]; 61 | } 62 | } 63 | 64 | } else { 65 | [[NSAlert alertWithError:error] runModal]; 66 | } 67 | 68 | } 69 | 70 | - (void) extractor:(MSSExtractor*)extractor didSaveImage:(NSURL*)fileUrl withError:(NSError*)error; { 71 | if(error) { 72 | [[NSAlert alertWithError:error] runModal]; 73 | } 74 | } 75 | 76 | - (IBAction)saveImages:(id)sender { 77 | [self.imageExtractor prepareJob:MSSExtractorJobCropping]; 78 | } 79 | 80 | 81 | @end 82 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp/Images.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 | } -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.saschapaulus.apps.mss 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | $(MACOSX_DEPLOYMENT_TARGET) 27 | NSHumanReadableCopyright 28 | Copyright © 2015 Sascha Paulus. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp/MainMenu.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 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp/SPWindowBundle.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #import 4 | 5 | @protocol ScannerCaptureWindowDelegate 6 | - (void)saveContentElements:(NSArray *)elements withProperties:(NSDictionary*)properties; 7 | @end 8 | 9 | 10 | @interface SPWindowBundle : NSObject 11 | 12 | - (BOOL) openWindowWithDelegate:(id)delegate asSheet:(BOOL)sheet; 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp/ZoomImageWindow.h: -------------------------------------------------------------------------------- 1 | // 2 | // ZoomImageWindow.h 3 | // MultiSelectionSuiteApp 4 | // 5 | // Created by Sascha Paulus on 14.01.15. 6 | // Copyright (c) 2015 Sascha Paulus. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface ZoomImageWindow : NSWindowController 13 | 14 | @property (nonatomic) MSSCanvasController *zoomCanvasController; 15 | @property (nonatomic) MSSCanvas *zoomCanvas; 16 | @property (nonatomic) MSSZoomExtractor *zoomExtractor; 17 | @property (nonatomic) IBOutlet NSImageView *sourceView; 18 | @property (nonatomic) IBOutlet NSImageView *zoomTargetView; 19 | @property (nonatomic) IBOutlet MSSSelectorStyle *zoomSelectorStyle; 20 | @property (nonatomic) IBOutlet MSSHandleStyle *zoomHandleStyle; 21 | 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp/ZoomImageWindow.m: -------------------------------------------------------------------------------- 1 | // 2 | // ZoomImageWindow.m 3 | // MultiSelectionSuiteApp 4 | // 5 | // Created by Sascha Paulus on 14.01.15. 6 | // Copyright (c) 2015 Sascha Paulus. All rights reserved. 7 | // 8 | 9 | #import "ZoomImageWindow.h" 10 | 11 | @interface ZoomImageWindow () 12 | 13 | @end 14 | 15 | @implementation ZoomImageWindow 16 | 17 | @synthesize zoomCanvas; 18 | @synthesize zoomCanvasController; 19 | @synthesize zoomExtractor; 20 | 21 | - (NSString *)windowNibName { 22 | return @"ZoomImageWindow"; 23 | } 24 | 25 | 26 | - (void)awakeFromNib { 27 | 28 | 29 | // Setup without interface builder 30 | self.zoomCanvas = [[MSSCanvas alloc] init]; 31 | self.zoomCanvasController = [MSSCanvasController canvasControllerForCanvas:zoomCanvas withContentView:self.sourceView]; 32 | [self.zoomCanvas setDelegate:zoomCanvasController]; 33 | self.zoomExtractor = [[MSSZoomExtractor alloc] init]; 34 | [self.zoomExtractor setCanvasController:zoomCanvasController]; 35 | [self.zoomExtractor setDelegate:self]; 36 | [self.zoomExtractor prepareJob:MSSExtractorJobZoom]; 37 | [self.zoomCanvasController setSingleSelectionMode:YES]; 38 | [self.zoomCanvasController setSelectorStyle:self.zoomSelectorStyle]; 39 | [self.zoomCanvasController setHandleStyle:self.zoomHandleStyle]; 40 | [self.zoomCanvasController setContentExtractor:self.zoomExtractor]; 41 | } 42 | 43 | #pragma mark - MSSExtractorDelegate 44 | 45 | - (void) extractor:(MSSExtractor*)extractor extractElement:(id)element forJob:(NSString*)identifier { 46 | 47 | if ([element isKindOfClass:[NSImage class]]) { 48 | 49 | NSImage *image = (NSImage*)element; 50 | 51 | if(identifier == MSSExtractorJobZoom) { 52 | [self.zoomTargetView setImage:image]; 53 | } 54 | } 55 | 56 | 57 | } 58 | 59 | 60 | - (void) extractor:(MSSExtractor*)extractor didCompleteWithError:(NSError*)error { 61 | } 62 | 63 | - (void) extractor:(MSSExtractor*)extractor didSaveImage:(NSURL*)fileUrl withError:(NSError*)error; { 64 | } 65 | 66 | 67 | @end 68 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp/animals.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ckteebe/MultiSelectionSuiteFramework/e3840b1a379364416d6113c47391d408d40869b2/MultiSelectionSuiteApp/MultiSelectionSuiteApp/animals.jpg -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp/de.lproj/CaptureWindow.strings: -------------------------------------------------------------------------------- 1 | 2 | /* Class = "NSButtonCell"; title = "Zoom Image"; ObjectID = "P77-cU-SBm"; */ 3 | "P77-cU-SBm.title" = "Bild vergrößern"; 4 | 5 | /* Class = "NSButtonCell"; title = "Scan"; ObjectID = "Vw1-me-1A6"; */ 6 | "Vw1-me-1A6.title" = "Einscannen"; 7 | 8 | /* Class = "NSButtonCell"; title = "Crop Image"; ObjectID = "y7c-44-Lgh"; */ 9 | "y7c-44-Lgh.title" = "Bild zerschneiden"; 10 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp/de.lproj/CropImageWindow.strings: -------------------------------------------------------------------------------- 1 | 2 | /* Class = "NSWindow"; title = "Window"; ObjectID = "F0z-JX-Cv5"; */ 3 | "F0z-JX-Cv5.title" = "Window"; 4 | 5 | /* Class = "NSTextFieldCell"; title = "Hold ⌘ to add another selector. ⌘ + A to highlight all. ⌫ or ⌦ to delete highlighted selectors."; ObjectID = "JRj-H6-t4l"; */ 6 | "JRj-H6-t4l.title" = "Halte ⌘ für eine weitere Auswahlbox. ⌘ + A um alle Boxen zu markieren. ⌫ oder ⌦ um markierte Boxen zu löschen."; 7 | 8 | /* Class = "NSButtonCell"; title = "Save"; ObjectID = "mKc-fU-U1a"; */ 9 | "mKc-fU-U1a.title" = "Speichern"; 10 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp/de.lproj/MainMenu.strings: -------------------------------------------------------------------------------- 1 | 2 | /* Class = "NSMenuItem"; title = "MSS Demo App"; ObjectID = "1Xt-HY-uBw"; */ 3 | "1Xt-HY-uBw.title" = "MSS Demo App"; 4 | 5 | /* Class = "NSMenuItem"; title = "Quit"; ObjectID = "4sb-4s-VLi"; */ 6 | "4sb-4s-VLi.title" = "Schließen"; 7 | 8 | /* Class = "NSMenu"; title = "Main Menu"; ObjectID = "AYu-sK-qS6"; */ 9 | "AYu-sK-qS6.title" = "Main Menu"; 10 | 11 | /* Class = "NSMenu"; title = "MSS Demo App"; ObjectID = "uQy-DD-JDr"; */ 12 | "uQy-DD-JDr.title" = "MSS Demo App"; 13 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp/de.lproj/ZoomImageWindow.strings: -------------------------------------------------------------------------------- 1 | 2 | /* Class = "NSWindow"; title = "Window"; ObjectID = "F0z-JX-Cv5"; */ 3 | "F0z-JX-Cv5.title" = "Window"; 4 | 5 | /* Class = "NSTextFieldCell"; title = "Original"; ObjectID = "URH-hl-mUI"; */ 6 | "URH-hl-mUI.title" = "Original"; 7 | 8 | /* Class = "NSTextFieldCell"; title = "Zoom"; ObjectID = "pfa-VK-fsv"; */ 9 | "pfa-VK-fsv.title" = "Vergrößerung"; 10 | -------------------------------------------------------------------------------- /MultiSelectionSuiteApp/MultiSelectionSuiteApp/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // MultiSelectionSuiteApp 4 | // 5 | // Created by Sascha Paulus on 05.01.15. 6 | // Copyright (c) 2015 Sascha Paulus. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]) { 12 | return NSApplicationMain(argc, argv); 13 | } 14 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite.xcodeproj/project.xcworkspace/xcuserdata/sascha.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ckteebe/MultiSelectionSuiteFramework/e3840b1a379364416d6113c47391d408d40869b2/MultiSelectionSuiteFramework/MultiSelectionSuite.xcodeproj/project.xcworkspace/xcuserdata/sascha.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite.xcodeproj/project.xcworkspace/xcuserdata/sascha.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 6 | 7 | SnapshotAutomaticallyBeforeSignificantChanges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite.xcodeproj/xcuserdata/sascha.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite.xcodeproj/xcuserdata/sascha.xcuserdatad/xcschemes/MultiSelectionSuite.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 94 | 96 | 97 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite.xcodeproj/xcuserdata/sascha.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | MultiSelectionSuite.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 2B24828E1A5AF9B9000C1F7A 16 | 17 | primary 18 | 19 | 20 | 2B7076CE1A5ABE4200707A69 21 | 22 | primary 23 | 24 | 25 | 2B7076D91A5ABE4200707A69 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/Classes/AddOns/Extractors/MSSExtractor.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ------------------------------------------------------------------------------------ 4 | MSSExtractor.h 5 | ------------------------------------------------------------------------------------ 6 | The extractor is an Add-On for SelectorSuite to extract content from the contentView 7 | of the canvasController. It must be derived for each purpose like image cropping 8 | or scanning (see MSSImageExtractor or MSSScanExtractor). 9 | Tipp: For a quick start please read the README document. 10 | ------------------------------------------------------------------------------------ 11 | 12 | The MIT License (MIT) 13 | 14 | Copyright (c) 2014 Sascha Paulus 15 | 16 | Permission is hereby granted, free of charge, to any person obtaining a copy 17 | of this software and associated documentation files (the "Software"), to deal 18 | in the Software without restriction, including without limitation the rights 19 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 20 | copies of the Software, and to permit persons to whom the Software is 21 | furnished to do so, subject to the following conditions: 22 | 23 | The above copyright notice and this permission notice shall be included in all 24 | copies or substantial portions of the Software. 25 | 26 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 31 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 | SOFTWARE. 33 | 34 | */ 35 | 36 | #import 37 | #import "MSSCanvasController.h" 38 | 39 | @class MSSExtractor; 40 | 41 | /** Defines requirements for a controller object to receive feedback from a MSSExtractor */ 42 | @protocol MSSExtractorDelegate 43 | 44 | /** Will be called whenever an element is extracted with a given key. 45 | @param extractor The extractor object from which the element comes 46 | @param element The fragment which has been return from the extractor 47 | @param identifier The name of the extraction job 48 | */ 49 | - (void) extractor:(MSSExtractor*)extractor extractElement:(id)element forJob:(NSString*)identifier; 50 | /** Will be called when the extraction is completed 51 | @param extractor The extractor object which extraction has been completed 52 | @param error An error during the extraction (if occurred) 53 | */ 54 | - (void) extractor:(MSSExtractor*)extractor didCompleteWithError:(NSError*)error; 55 | @optional 56 | /** Will be called whenever an image has been saved. 57 | @param extractor The extractor which has saved the image 58 | @param fileUrl The URL to the saved file 59 | @param error An error during the saving (if occurred) 60 | */ 61 | - (void) extractor:(MSSExtractor*)extractor didSaveImage:(NSURL*)fileUrl withError:(NSError*)error; 62 | 63 | @end 64 | 65 | 66 | IB_DESIGNABLE 67 | /** Extracts content from the contentView of MSSCanvasController or its MSSCanvas. */ 68 | @interface MSSExtractor : NSObject { 69 | 70 | } 71 | /** @name Delegation */ 72 | /** The controller object to receive feedback from the extractor */ 73 | @property (nonatomic) IBOutlet id delegate; 74 | /** @name Properties */ 75 | /** Identifies for which extraction job the extracation element is created */ 76 | @property (nonatomic, readonly) NSString *jobIdentifier; 77 | /** The ViewController which manages the canvas. */ 78 | @property (nonatomic) IBOutlet MSSCanvasController *canvasController; 79 | /** A file prefix which the files will be saved with. */ 80 | @property (nonatomic) IBInspectable NSString *filePrefix; 81 | /** The folder URL in which the files will be stored. */ 82 | @property (nonatomic) NSURL *saveDirectory; 83 | 84 | /** @name Results */ 85 | /** Holds the extracted elements. */ 86 | @property (nonatomic, readonly) NSMutableArray *elements; 87 | 88 | /** @name Methods */ 89 | /** Saves an image with a chosen file type 90 | @param image The image which should be saved 91 | @param fileType The type of image which should be created 92 | */ 93 | - (BOOL) saveImage:(NSImage*)image withType:(NSBitmapImageFileType)fileType compression:(ExtractorImageCompressionLevel)compressionLevel; 94 | /** Extracts each selected part from the content holder. Returing elements are using the given identifier. 95 | @param identifier A unique identifier for the job in order to recognize corresponding return values 96 | */ 97 | - (void) prepareJob:(NSString*)identifier; 98 | /** Sets the observation for changes on the canvas */ 99 | - (void) setObservation; 100 | /** Will be called whenever an element is extracted. 101 | @param element The element which has been extracted 102 | @param error An error during the extraction (if occurred) 103 | */ 104 | - (void) didExtractElement:(id)element withError:(NSError*)error; 105 | 106 | @end 107 | 108 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/Classes/AddOns/Extractors/MSSExtractor.m: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ------------------------------------------------------------------------------------ 4 | MSSExtractor.m 5 | ------------------------------------------------------------------------------------ 6 | The extractor is an Add-On for SelectorSuite to extract content from the contentView 7 | of the canvasController. It must be derived for each purpose like image cropping 8 | or scanning (see MSSImageExtractor or MSSScanExtractor). 9 | Tipp: For a quick start please read the README document. 10 | ------------------------------------------------------------------------------------ 11 | 12 | The MIT License (MIT) 13 | 14 | Copyright (c) 2014 Sascha Paulus 15 | 16 | Permission is hereby granted, free of charge, to any person obtaining a copy 17 | of this software and associated documentation files (the "Software"), to deal 18 | in the Software without restriction, including without limitation the rights 19 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 20 | copies of the Software, and to permit persons to whom the Software is 21 | furnished to do so, subject to the following conditions: 22 | 23 | The above copyright notice and this permission notice shall be included in all 24 | copies or substantial portions of the Software. 25 | 26 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 31 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 | SOFTWARE. 33 | 34 | */ 35 | 36 | #import "MSSExtractor.h" 37 | #import "MSSError.h" 38 | #import "MSSPreferences.h" 39 | 40 | @implementation MSSExtractor 41 | 42 | @synthesize saveDirectory; 43 | @synthesize elements = _elements; 44 | @synthesize jobIdentifier = _jobIdentifier; 45 | 46 | #pragma mark - Init 47 | 48 | - (void) commonInit { 49 | _elements = [NSMutableArray array]; 50 | [self setObservation]; 51 | } 52 | 53 | -(instancetype)init { 54 | self = [super init]; 55 | if (self) { 56 | [self commonInit]; 57 | } 58 | return self; 59 | } 60 | 61 | #pragma mark - MSSCanvasEventSubscriber 62 | 63 | - (void) setObservation { 64 | return; 65 | } 66 | 67 | - (void)canvasHasChanged { 68 | return; 69 | } 70 | 71 | - (void)selectorHasChanged:(MSSSelector *)selector { 72 | return; 73 | } 74 | 75 | 76 | #pragma mark - Default methods 77 | 78 | - (void) prepareJob:(NSString*)identifier { 79 | 80 | _jobIdentifier = identifier; 81 | } 82 | 83 | - (BOOL) saveImage:(NSImage*)image withType:(NSBitmapImageFileType)fileType compression:(ExtractorImageCompressionLevel)compressionLevel { 84 | 85 | 86 | if(self.saveDirectory==nil) { 87 | NSDictionary *errorDesc = @{ NSLocalizedDescriptionKey : MSS_ERROR_DESC(MSSErrorNoSaveDirectory) }; 88 | NSError *error = [NSError errorWithDomain:MSSErrorDomain code:MSSErrorNoSaveDirectory userInfo:errorDesc]; 89 | [self.delegate extractor:self didSaveImage:nil withError:error]; 90 | return NO; 91 | } 92 | 93 | if([[NSFileManager defaultManager] fileExistsAtPath:[self.saveDirectory path]]) { 94 | NSNumber *isDirectory; 95 | BOOL success = [self.saveDirectory getResourceValue:&isDirectory forKey:NSURLIsDirectoryKey error:nil]; 96 | if(!success || ![isDirectory boolValue]) { 97 | NSDictionary *errorDesc = @{ NSLocalizedDescriptionKey : MSS_ERROR_DESC(MSSErrorSaveDirectoryNotExists) }; 98 | NSError *error = [NSError errorWithDomain:MSSErrorDomain code:MSSErrorSaveDirectoryNotExists userInfo:errorDesc]; 99 | [self.delegate extractor:self didSaveImage:nil withError:error]; 100 | return NO; 101 | } 102 | } else { 103 | NSDictionary *errorDesc = @{ NSLocalizedDescriptionKey : MSS_ERROR_DESC(MSSErrorSaveDirectoryUrlIsNoDirectory) }; 104 | NSError *error = [NSError errorWithDomain:MSSErrorDomain code:MSSErrorSaveDirectoryUrlIsNoDirectory userInfo:errorDesc]; 105 | [self.delegate extractor:self didSaveImage:nil withError:error]; 106 | return NO; 107 | } 108 | 109 | NSString *extention = nil; 110 | 111 | switch (fileType) { 112 | case NSPNGFileType: 113 | extention = @".png"; 114 | break; 115 | case NSJPEGFileType: 116 | extention = @".jpg"; 117 | break; 118 | case NSGIFFileType: 119 | extention = @".gif"; 120 | break; 121 | case NSBMPFileType: 122 | extention = @".bmp"; 123 | break; 124 | case NSTIFFFileType: 125 | extention = @".tiff"; 126 | break; 127 | default: 128 | break; 129 | } 130 | 131 | if(extention!=nil) { 132 | 133 | int i = 0; 134 | NSURL *saveUrl = nil; 135 | while (saveUrl == nil || [[NSFileManager defaultManager] fileExistsAtPath:[saveUrl path]]) { 136 | i++; 137 | NSString *filename = [NSString stringWithFormat:@"%@%i%@",self.filePrefix,i,extention]; 138 | saveUrl = [self.saveDirectory URLByAppendingPathComponent:filename]; 139 | } 140 | 141 | CGFloat imageCompression = 1.0; 142 | NSError *error = nil; 143 | NSDictionary *options = nil; 144 | if(fileType == NSJPEGFileType) { 145 | switch (compressionLevel) { 146 | case ExtractorImageCompressionLevelLow: 147 | imageCompression = 0.8; 148 | break; 149 | case ExtractorImageCompressionLevelMiddle: 150 | imageCompression = 0.6; 151 | break; 152 | case ExtractorImageCompressionLevelHigh: 153 | imageCompression = 0.3; 154 | break; 155 | case ExtractorImageCompressionLevelHighest: 156 | imageCompression = 0.1; 157 | break; 158 | default: 159 | imageCompression = 1.0; 160 | break; 161 | } 162 | options = [NSDictionary dictionaryWithObjectsAndKeys: 163 | [NSNumber numberWithDouble:imageCompression], NSImageCompressionFactor, 164 | [NSNumber numberWithBool:NO], NSImageProgressive, 165 | nil]; 166 | } 167 | 168 | NSBitmapImageRep *rep = [[NSBitmapImageRep alloc] initWithData:[image TIFFRepresentation]]; 169 | NSData *fileData = [rep representationUsingType:fileType properties:options]; 170 | [fileData writeToURL:saveUrl options:NSDataWritingWithoutOverwriting error:&error]; 171 | if(error!=nil) { 172 | [self.delegate extractor:self didSaveImage:nil withError:error]; 173 | NSDictionary *errorDesc = @{ NSLocalizedDescriptionKey : MSS_ERROR_DESC(MSSErrorImageSavingFailed) }; 174 | NSError *error = [NSError errorWithDomain:MSSErrorDomain code:MSSErrorImageSavingFailed userInfo:errorDesc]; 175 | [self.delegate extractor:self didSaveImage:nil withError:error]; 176 | } else { 177 | [self.delegate extractor:self didSaveImage:saveUrl withError:nil]; 178 | } 179 | 180 | } else { 181 | 182 | NSDictionary *errorDesc = @{ NSLocalizedDescriptionKey : MSS_ERROR_DESC(MSSErrorFileTypeNotSupportedYet) }; 183 | NSError *error = [NSError errorWithDomain:MSSErrorDomain code:MSSErrorFileTypeNotSupportedYet userInfo:errorDesc]; 184 | [self.delegate extractor:self didSaveImage:nil withError:error]; 185 | return NO; 186 | } 187 | 188 | return YES; 189 | } 190 | 191 | #pragma mark - delegate notification 192 | 193 | - (void) didExtractElement:(id)element withError:(NSError*)error { 194 | 195 | if(error == nil && element != nil) { 196 | if(self.jobIdentifier == nil) _jobIdentifier = MSSExtractorJobUnknown; 197 | [_elements addObject:element]; 198 | [self.delegate extractor:self extractElement:element forJob:self.jobIdentifier]; 199 | } else { 200 | [self.delegate extractor:self didCompleteWithError:error]; 201 | } 202 | } 203 | 204 | 205 | 206 | 207 | @end 208 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/Classes/AddOns/Extractors/MSSImageExtractor.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ------------------------------------------------------------------------------------ 4 | MSSImageExtractor.h 5 | ------------------------------------------------------------------------------------ 6 | The extractor is an Add-On for SelectorSuite to extract content from the contentView 7 | of the canvasController. This derived version extracts image parts from the 8 | contentView's original image based on the selections. 9 | Tipp: For a quick start please read the README document. 10 | ------------------------------------------------------------------------------------ 11 | 12 | The MIT License (MIT) 13 | 14 | Copyright (c) 2014 Sascha Paulus 15 | 16 | Permission is hereby granted, free of charge, to any person obtaining a copy 17 | of this software and associated documentation files (the "Software"), to deal 18 | in the Software without restriction, including without limitation the rights 19 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 20 | copies of the Software, and to permit persons to whom the Software is 21 | furnished to do so, subject to the following conditions: 22 | 23 | The above copyright notice and this permission notice shall be included in all 24 | copies or substantial portions of the Software. 25 | 26 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 31 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 | SOFTWARE. 33 | 34 | */ 35 | 36 | 37 | #import 38 | #import "MSSExtractor.h" 39 | 40 | /** A concrete MSSExtractor class optimized for image cropping */ 41 | @interface MSSImageExtractor : MSSExtractor 42 | 43 | /** @name States */ 44 | /** Determines if everything is ready to save the selected parts. */ 45 | @property (nonatomic) BOOL readyForSave; 46 | 47 | @end 48 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/Classes/AddOns/Extractors/MSSImageExtractor.m: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ------------------------------------------------------------------------------------ 4 | MSSImageExtractor.m 5 | ------------------------------------------------------------------------------------ 6 | The extractor is an Add-On for SelectorSuite to extract content from the contentView 7 | of the canvasController. This derived version extracts image parts from the 8 | contentView's original image based on the selections. 9 | Tipp: For a quick start please read the README document. 10 | ------------------------------------------------------------------------------------ 11 | 12 | The MIT License (MIT) 13 | 14 | Copyright (c) 2014 Sascha Paulus 15 | 16 | Permission is hereby granted, free of charge, to any person obtaining a copy 17 | of this software and associated documentation files (the "Software"), to deal 18 | in the Software without restriction, including without limitation the rights 19 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 20 | copies of the Software, and to permit persons to whom the Software is 21 | furnished to do so, subject to the following conditions: 22 | 23 | The above copyright notice and this permission notice shall be included in all 24 | copies or substantial portions of the Software. 25 | 26 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 31 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 | SOFTWARE. 33 | 34 | */ 35 | 36 | #import "MSSImageExtractor.h" 37 | #import "MSSError.h" 38 | #import "MSSPreferences.h" 39 | #import "NSImageView+MSSScaledImage.h" 40 | #import "MSSSelector.h" 41 | 42 | @implementation MSSImageExtractor 43 | 44 | @synthesize readyForSave; 45 | 46 | #pragma mark - ReadyStates 47 | 48 | - (void)canvasHasChanged { 49 | [self setReadyForSave:self.canvasController.hasSelectors]; 50 | } 51 | 52 | 53 | #pragma mark - MSSExtractor 54 | 55 | - (void) prepareJob:(NSString*)identifier { 56 | 57 | [super prepareJob:identifier]; 58 | 59 | [self.elements removeAllObjects]; 60 | 61 | if(!self.canvasController.hasSelectors) { 62 | NSDictionary *errorDesc = @{ NSLocalizedDescriptionKey : MSS_ERROR_DESC(MSSErrorNoSelections) }; 63 | NSError *error = [NSError errorWithDomain:MSSErrorDomain code:MSSErrorNoSelections userInfo:errorDesc]; 64 | [self didExtractElement:nil withError:error]; 65 | return; 66 | } 67 | 68 | for(MSSSelector *selector in self.canvasController.selectors) { 69 | 70 | NSSize ratio = [(NSImageView*)self.canvasController.contentView originalImageRatio]; 71 | CGFloat x = selector.frame.origin.x / ratio.width; 72 | CGFloat y = selector.frame.origin.y / ratio.height; 73 | CGFloat w = selector.frame.size.width / ratio.width; 74 | CGFloat h = selector.frame.size.height / ratio.height; 75 | NSRect sourceFrame = NSMakeRect(x, y, w, h); 76 | NSRect targetFrame = NSMakeRect(0, 0, w*1.0f, h*1.0f); 77 | NSImage *targetImage = [[NSImage alloc] initWithSize:targetFrame.size]; 78 | if(targetImage.size.width > 0 && targetFrame.size.height > 0) { 79 | [targetImage lockFocus]; 80 | [[(NSImageView*)self.canvasController.contentView originalImage] drawInRect:targetFrame fromRect:sourceFrame operation:NSCompositeCopy fraction:1.0f]; 81 | [targetImage unlockFocus]; 82 | [self didExtractElement:targetImage withError:nil]; 83 | } 84 | 85 | } 86 | 87 | [self.delegate extractor:self didCompleteWithError:nil]; 88 | 89 | 90 | } 91 | 92 | 93 | 94 | @end 95 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/Classes/AddOns/Extractors/MSSZoomExtractor.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ----------------------------------------------------------------------------------------- 4 | MSSZoomExtractor.h 5 | ----------------------------------------------------------------------------------------- 6 | The extractor is an Add-On for SelectorSuite to extract content from the contentView 7 | of the canvasController. This derived version extracts one part from the contentView's 8 | original image based on the selection and "zooms" it by using the original size. 9 | Tipp: For a quick start please read the README document. 10 | ----------------------------------------------------------------------------------------- 11 | 12 | The MIT License (MIT) 13 | 14 | Copyright (c) 2014 Sascha Paulus 15 | 16 | Permission is hereby granted, free of charge, to any person obtaining a copy 17 | of this software and associated documentation files (the "Software"), to deal 18 | in the Software without restriction, including without limitation the rights 19 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 20 | copies of the Software, and to permit persons to whom the Software is 21 | furnished to do so, subject to the following conditions: 22 | 23 | The above copyright notice and this permission notice shall be included in all 24 | copies or substantial portions of the Software. 25 | 26 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 31 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 | SOFTWARE. 33 | 34 | */ 35 | 36 | #import "MSSExtractor.h" 37 | 38 | /** A concrete MSSExtractor class optimized for image zooming activities */ 39 | @interface MSSZoomExtractor : MSSExtractor 40 | 41 | @end 42 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/Classes/AddOns/Extractors/MSSZoomExtractor.m: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ----------------------------------------------------------------------------------------- 4 | MSSZoomExtractor.m 5 | ----------------------------------------------------------------------------------------- 6 | The extractor is an Add-On for SelectorSuite to extract content from the contentView 7 | of the canvasController. This derived version extracts one part from the contentView's 8 | original image based on the selection and "zooms" it by using the original size. 9 | Tipp: For a quick start please read the README document. 10 | ----------------------------------------------------------------------------------------- 11 | 12 | The MIT License (MIT) 13 | 14 | Copyright (c) 2014 Sascha Paulus 15 | 16 | Permission is hereby granted, free of charge, to any person obtaining a copy 17 | of this software and associated documentation files (the "Software"), to deal 18 | in the Software without restriction, including without limitation the rights 19 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 20 | copies of the Software, and to permit persons to whom the Software is 21 | furnished to do so, subject to the following conditions: 22 | 23 | The above copyright notice and this permission notice shall be included in all 24 | copies or substantial portions of the Software. 25 | 26 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 31 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 | SOFTWARE. 33 | 34 | */ 35 | 36 | #import "MSSZoomExtractor.h" 37 | #import "MSSError.h" 38 | #import "MSSPreferences.h" 39 | #import "NSImageView+MSSScaledImage.h" 40 | #import "MSSSelector.h" 41 | 42 | @implementation MSSZoomExtractor 43 | 44 | - (void) prepareJob:(NSString *)identifier { 45 | [super prepareJob:identifier]; 46 | } 47 | 48 | - (void)selectorHasChanged:(MSSSelector *)selector { 49 | 50 | if(selector!=nil) { 51 | 52 | NSRect frame = [self.canvasController defaultRectForFrame:selector.frame]; 53 | NSSize ratio = [(NSImageView*)self.canvasController.contentView originalImageRatio]; 54 | CGFloat x = frame.origin.x / ratio.width; 55 | CGFloat y = frame.origin.y / ratio.height; 56 | CGFloat w = frame.size.width / ratio.width; 57 | CGFloat h = frame.size.height / ratio.height; 58 | NSRect sourceFrame = NSMakeRect(x, y, w, h); 59 | NSRect targetFrame = NSMakeRect(0, 0, w*1.0f, h*1.0f); 60 | NSImage *targetImage = [[NSImage alloc] initWithSize:targetFrame.size]; 61 | if(targetImage.size.width > 0 && targetFrame.size.height > 0) { 62 | [targetImage lockFocus]; 63 | [[(NSImageView*)self.canvasController.contentView originalImage] drawInRect:targetFrame fromRect:sourceFrame operation:NSCompositeCopy fraction:1.0f]; 64 | [targetImage unlockFocus]; 65 | [self didExtractElement:targetImage withError:nil]; 66 | 67 | } 68 | } 69 | } 70 | 71 | 72 | @end 73 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/Classes/Base/MSSCanvas.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ------------------------------------------------------------------------------------ 4 | MSSCanvas.h 5 | ------------------------------------------------------------------------------------ 6 | The canvas is a normal NSView which can add as subview on any other view. 7 | This is the place where the MSSSelector(s) are drawn. A canvas can have multiple 8 | selectors. The canvas is controlled by the canvasController who is responsible for 9 | almost every interaction between the canvas, the selectors and the mouse. 10 | The frame of the canvas will be arranged automatically. 11 | Tipp: For a quick start please read the README document. 12 | ------------------------------------------------------------------------------------ 13 | 14 | The MIT License (MIT) 15 | 16 | Copyright (c) 2014 Sascha Paulus 17 | 18 | Permission is hereby granted, free of charge, to any person obtaining a copy 19 | of this software and associated documentation files (the "Software"), to deal 20 | in the Software without restriction, including without limitation the rights 21 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 22 | copies of the Software, and to permit persons to whom the Software is 23 | furnished to do so, subject to the following conditions: 24 | 25 | The above copyright notice and this permission notice shall be included in all 26 | copies or substantial portions of the Software. 27 | 28 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 29 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 30 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 31 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 32 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 33 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 34 | SOFTWARE. 35 | 36 | */ 37 | 38 | #import 39 | #import 40 | #import "MSSHandle.h" 41 | #import "MSSSelectorStyle.h" 42 | #import "MSSHandleStyle.h" 43 | 44 | @class MSSCanvas; 45 | @class MSSSelector; 46 | @class MSSExtractor; 47 | 48 | /** Defines requirements for an eventSubscriber object to receive events */ 49 | @protocol MSSCanvasEventSubscriber 50 | /** @name Methods */ 51 | /** Will be called whenever the canvas has changed */ 52 | - (void) canvasHasChanged; 53 | /** Will be called wheneever a selector has changed 54 | @param selector The selector which has been changed 55 | */ 56 | - (void) selectorHasChanged:(MSSSelector*)selector; 57 | @end 58 | 59 | /** Defines requirements for a controller object to manage a MSSCanvas */ 60 | @protocol MSSCanvasDelegate 61 | 62 | /** @name Properties */ 63 | /** Holds all selectors on the canvas */ 64 | @property (nonatomic, readonly) NSArray *selectors; 65 | /** Determines the current selector */ 66 | @property (atomic) IBOutlet MSSCanvas* view; 67 | /** Determines the chosen SelectorStyle */ 68 | @property (nonatomic) IBOutlet MSSSelectorStyle *selectorStyle; 69 | /** Determines the chosen HandleStyle */ 70 | @property (nonatomic) IBOutlet MSSHandleStyle *handleStyle; 71 | /** Determines if the canvas has selectors or not */ 72 | @property (nonatomic, readonly) BOOL hasSelectors; 73 | /** The view with will contain the canvas as subview */ 74 | @property (nonatomic) IBOutlet NSView *contentView; 75 | /** Determines the current selector */ 76 | @property (nonatomic, readonly) MSSSelector *currentSelector; 77 | /** Determines if the canvas can have only one selector */ 78 | @property (nonatomic) IBInspectable BOOL singleSelectionMode; 79 | /** The object which extracts the content from the contentView */ 80 | @property (nonatomic) IBOutlet MSSExtractor *contentExtractor; 81 | 82 | /** @name Methods */ 83 | /** Returns a frame with normal (lower-left) origin based on the current frame. 84 | @param frame The frame which should be normalized 85 | */ 86 | - (NSRect) defaultRectForFrame:(NSRect)frame; 87 | /** Discards all selectors from the canvas which are marked as selected */ 88 | - (void)removeAllSelectorsFromCanvas; 89 | /** Prepares to controller after a canvas has been set */ 90 | - (void) prepareController; 91 | 92 | /** Creates a canvasController for a canvas and a contentView 93 | @param theCanvas The canvas to create a controller for 94 | @param theContentView The view (e.g. NSImageView) which provides the content 95 | */ 96 | + (instancetype)canvasControllerForCanvas:(MSSCanvas*)theCanvas withContentView:(NSView*)theContentView; 97 | 98 | /** @name Eventhandling */ 99 | - (void)mouseDown:(NSEvent *)theEvent; 100 | - (void)mouseDragged:(NSEvent *)theEvent; 101 | - (void)mouseUp:(NSEvent *)theEvent; 102 | - (void)keyDown:(NSEvent *)theEvent; 103 | 104 | @end 105 | 106 | IB_DESIGNABLE 107 | /** Represents a canvas view on which the selectors will be drawn */ 108 | @interface MSSCanvas : NSView 109 | /** @name Delegation */ 110 | /** The controller of the canvas */ 111 | @property (nonatomic) IBOutlet id delegate; 112 | /** @name Properties */ 113 | /** Determines if intersections between selections are allowed. (Default: YES) */ 114 | @property (nonatomic) IBInspectable BOOL allowIntersections; 115 | 116 | @end 117 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/Classes/Base/MSSCanvas.m: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | 4 | ------------------------------------------------------------------------------------ 5 | MSSCanvas.m 6 | ------------------------------------------------------------------------------------ 7 | The canvas is a normal NSView which can add as subview on any other view. 8 | This is the place where the MSSSelector(s) are drawn. A canvas can have multiple 9 | selectors. The canvas is controlled by the canvasController who is responsible for 10 | almost every interaction between the canvas, the selectors and the mouse. 11 | The frame of the canvas will be arranged automatically. 12 | Tipp: For a quick start please read the README document. 13 | ------------------------------------------------------------------------------------ 14 | 15 | The MIT License (MIT) 16 | 17 | Copyright (c) 2014 Sascha Paulus 18 | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy 20 | of this software and associated documentation files (the "Software"), to deal 21 | in the Software without restriction, including without limitation the rights 22 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 23 | copies of the Software, and to permit persons to whom the Software is 24 | furnished to do so, subject to the following conditions: 25 | 26 | The above copyright notice and this permission notice shall be included in all 27 | copies or substantial portions of the Software. 28 | 29 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 30 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 31 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 32 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 33 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 34 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 35 | SOFTWARE. 36 | 37 | */ 38 | 39 | #import "MSSCanvas.h" 40 | #import "MSSSelector.h" 41 | #import "MSSHandle.h" 42 | 43 | 44 | @implementation MSSCanvas 45 | 46 | #pragma mark - Redrawing 47 | 48 | - (void)awakeFromNib { 49 | self.allowIntersections = YES; 50 | } 51 | 52 | - (void)drawRect:(NSRect)dirtyRect { 53 | 54 | /** Draw all selectors */ 55 | for (MSSSelector *selector in self.delegate.selectors) { 56 | [selector drawPath]; 57 | } 58 | /** Draw the current selector (not part of self.delegate.selectors yet) */ 59 | if(self.delegate.currentSelector) { 60 | [self.delegate.currentSelector drawPath]; 61 | } 62 | } 63 | 64 | #pragma mark - Events 65 | 66 | - (void)mouseDown:(NSEvent *)theEvent { 67 | [self.delegate mouseDown:theEvent]; 68 | } 69 | 70 | - (void)mouseUp:(NSEvent *)theEvent { 71 | [self.delegate mouseUp:theEvent]; 72 | } 73 | 74 | - (void)mouseDragged:(NSEvent *)theEvent { 75 | [self.delegate mouseDragged:theEvent]; 76 | } 77 | 78 | - (void)keyDown:(NSEvent *)theEvent { 79 | [self.delegate keyDown:theEvent]; 80 | } 81 | 82 | 83 | #pragma First Responder 84 | 85 | - (BOOL)acceptsFirstResponder { 86 | return YES; 87 | } 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/Classes/Base/MSSCanvasController.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ------------------------------------------------------------------------------------ 4 | MSSCanvasController.h 5 | ------------------------------------------------------------------------------------ 6 | The canvasController handles any interaction between the canvas, the mouse 7 | and other objects. The controller moves and resizes the canvas's selectors. 8 | Optional canvasController can provide the styles for the selectors and the handles. 9 | Tipp: For a quick start please read the README document. 10 | ------------------------------------------------------------------------------------ 11 | 12 | The MIT License (MIT) 13 | 14 | Copyright (c) 2014 Sascha Paulus 15 | 16 | Permission is hereby granted, free of charge, to any person obtaining a copy 17 | of this software and associated documentation files (the "Software"), to deal 18 | in the Software without restriction, including without limitation the rights 19 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 20 | copies of the Software, and to permit persons to whom the Software is 21 | furnished to do so, subject to the following conditions: 22 | 23 | The above copyright notice and this permission notice shall be included in all 24 | copies or substantial portions of the Software. 25 | 26 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 31 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 | SOFTWARE. 33 | 34 | */ 35 | 36 | #import 37 | #import "MSSCanvas.h" 38 | #import "MSSSelectorStyle.h" 39 | #import "MSSHandleStyle.h" 40 | 41 | @class MSSExtractor; 42 | 43 | IB_DESIGNABLE 44 | /** Represents a ViewController customized to control a MSSCanvas object */ 45 | @interface MSSCanvasController : NSViewController 46 | /** @name Properties */ 47 | /** Holds all selectors on the canvas */ 48 | @property (nonatomic, readonly) NSArray *selectors; 49 | /** Determines the canvas */ 50 | @property (atomic) IBOutlet MSSCanvas* view; 51 | /** Determines the chosen SelectorStyle */ 52 | @property (nonatomic) IBOutlet MSSSelectorStyle *selectorStyle; 53 | /** Determines the chosen HandleStyle */ 54 | @property (nonatomic) IBOutlet MSSHandleStyle *handleStyle; 55 | /** Determines if the canvas has selectors or not */ 56 | @property (nonatomic, readonly) BOOL hasSelectors; 57 | /** The view with will contain the canvas as subview */ 58 | @property (nonatomic) IBOutlet NSView *contentView; 59 | /** Determines if the canvas can have only one selector */ 60 | @property (nonatomic) IBInspectable BOOL singleSelectionMode; 61 | /** The object which extracts the content from the contentView */ 62 | @property (nonatomic) IBOutlet MSSExtractor *contentExtractor; 63 | 64 | /** @name Methods */ 65 | - (NSRect) defaultRectForFrame:(NSRect)frame; 66 | - (void)removeAllSelectorsFromCanvas; 67 | - (void) prepareController; 68 | + (instancetype)canvasControllerForCanvas:(MSSCanvas*)theCanvas withContentView:(NSView*)theContentView; 69 | 70 | 71 | @end 72 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/Classes/Base/MSSCanvasController.m: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ------------------------------------------------------------------------------------ 4 | MSSCanvasController.m 5 | ------------------------------------------------------------------------------------ 6 | The canvasController handles any interaction between the canvas, the mouse 7 | and other objects. The controller moves and resizes the canvas's selectors. 8 | Optional canvasController can provide the styles for the selectors and the handles. 9 | Tipp: For a quick start please read the README document. 10 | ------------------------------------------------------------------------------------ 11 | 12 | The MIT License (MIT) 13 | 14 | Copyright (c) 2014 Sascha Paulus 15 | 16 | Permission is hereby granted, free of charge, to any person obtaining a copy 17 | of this software and associated documentation files (the "Software"), to deal 18 | in the Software without restriction, including without limitation the rights 19 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 20 | copies of the Software, and to permit persons to whom the Software is 21 | furnished to do so, subject to the following conditions: 22 | 23 | The above copyright notice and this permission notice shall be included in all 24 | copies or substantial portions of the Software. 25 | 26 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 27 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 28 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 30 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 31 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 32 | SOFTWARE. 33 | 34 | */ 35 | 36 | #import "MSSCanvasController.h" 37 | #import "MSSSelector.h" 38 | #import "MSSHandle.h" 39 | #import "NSImageView+MSSScaledImage.h" 40 | #import "MSSExtractor.h" 41 | 42 | @interface MSSCanvasController () 43 | 44 | /** All selectors */ 45 | @property (nonatomic) NSMutableArray *_selectors; 46 | /** Current selector */ 47 | @property (nonatomic) MSSSelector *currentSelector; 48 | /** Current handle */ 49 | @property (nonatomic) MSSHandle *handle; 50 | /** Determines the canvas frame based on the contentView type */ 51 | @property (nonatomic, readonly) NSRect canvasFrame; 52 | 53 | @property (nonatomic) BOOL cursorCanBeChanged; 54 | 55 | 56 | /** Marks all selectors as unselected and redraws canvas if needed 57 | @param redraw Selectors should be redrawn after change 58 | */ 59 | - (void) markAllUnselected:(BOOL)redraw; 60 | /** Marks all selectors as selected and redraws canvas if needed 61 | @param redraw Selectors should be redrawn after change 62 | */ 63 | - (void) markAllSelected:(BOOL)redraw; 64 | /** Discards all selectors from the canvas which are marked as selected */ 65 | - (void) removeMarkedSelectorsFromCanvas; 66 | /** Creates a new selector and defines him as the current selector object 67 | @param frame The initial frame of the new selector 68 | */ 69 | - (void) addSelectorWithFrame:(NSRect)frame; 70 | /** @abstract Creates a new picker selector and defines him as the current selector object. 71 | 72 | @discussion For more details about the distinction between picker and selector checkout the isPicker property of the MSSSelector class. 73 | @param frame The initial frame of the new picker 74 | */ 75 | - (void) setPickerWithFrame:(NSRect)frame; 76 | /** Determines if the canvas has current selector object or not */ 77 | - (BOOL) hasSelector; 78 | /** Sets or replaces the canvas in the view's subviews */ 79 | - (void) arrangeCanvas; 80 | /** Reset the canvas and remove all selections */ 81 | - (void) resetCanvas; 82 | /** Will be called whenever something on the contentView has changed 83 | @param notification The notification with information about the change 84 | */ 85 | - (void) contentViewDidChange:(NSNotification*)notification; 86 | 87 | 88 | @end 89 | 90 | @implementation MSSCanvasController 91 | 92 | #pragma mark - Init 93 | 94 | - (instancetype)initWithCanvas:(MSSCanvas*)theCanvas withContentView:(NSView*)theContentView { 95 | self = [super init]; 96 | if(self) { 97 | self.view = theCanvas; 98 | self.contentView = theContentView; 99 | [self prepareController]; 100 | } 101 | return self; 102 | } 103 | 104 | + (instancetype)canvasControllerForCanvas:(MSSCanvas*)theCanvas withContentView:(NSView*)theContentView { 105 | return [[self alloc] initWithCanvas:theCanvas withContentView:theContentView]; 106 | } 107 | 108 | - (void)awakeFromNib { 109 | 110 | [self prepareController]; 111 | } 112 | 113 | - (void) prepareController { 114 | 115 | self.cursorCanBeChanged = YES; 116 | 117 | NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld; 118 | 119 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contentViewDidChange:) name:NSViewFrameDidChangeNotification object:self.contentView]; 120 | 121 | if([self.contentView isKindOfClass:[NSImageView class]]) { 122 | 123 | [(NSImageView*)self.contentView setRefusesFirstResponder:YES]; 124 | 125 | NSArray *keyPaths = @[@"self.contentView.image", 126 | @"self.contentView.image.size", 127 | @"self.contentView.imageAlignment", 128 | @"self.contentView.imageFrameStyle", 129 | @"self.contentView.imageScaling"]; 130 | 131 | for(NSString *keyPath in keyPaths) { 132 | 133 | [self addObserver:self forKeyPath:keyPath options:options context:NULL]; 134 | } 135 | } 136 | 137 | 138 | self._selectors = [NSMutableArray array]; 139 | self.currentSelector = nil; 140 | 141 | [self arrangeCanvas]; 142 | 143 | } 144 | 145 | 146 | #pragma mark - Observation 147 | 148 | - (void) resetCanvas { 149 | [self removeAllSelectorsFromCanvas]; 150 | [self arrangeCanvas]; 151 | } 152 | 153 | - (void) contentViewDidChange:(NSNotification*)notification { 154 | [self resetCanvas]; 155 | } 156 | 157 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 158 | { 159 | [self resetCanvas]; 160 | } 161 | 162 | #pragma mark - Events 163 | 164 | /** @abstract If the left mouse button is pressed and no selector is on the canvas or the command key is pressed add a new selector to the canvas and define him as the current selector object. Otherwise determine if an existing selector has been touched. If yes, mark this selector as selected and define him as the current selector object. If not, create a picker selector. 165 | @param theEvent An object encapsulating information about the mouse-down event. 166 | @discussion For more details about the distinction between picker and selector checkout the isPicker property of the MSSSelector class. 167 | */ 168 | - (void)mouseDown:(NSEvent *)theEvent { 169 | 170 | self.cursorCanBeChanged = NO; 171 | [self.view.window disableCursorRects]; 172 | 173 | [self markAllUnselected:YES]; 174 | 175 | NSPoint currentPoint = [self.view convertPoint:[theEvent locationInWindow] fromView:nil]; 176 | NSRect initalFrame = NSMakeRect(currentPoint.x, currentPoint.y, 0, 0); 177 | self.currentSelector = nil; 178 | 179 | if(([theEvent modifierFlags] & NSCommandKeyMask) || self.selectors.count == 0) { 180 | [self addSelectorWithFrame:initalFrame]; 181 | } else { 182 | BOOL didHitSelector = NO; 183 | 184 | for(MSSSelector *selector in self.selectors) { 185 | if((didHitSelector = [selector intersectsFrame:initalFrame])) { 186 | self.currentSelector = selector; 187 | [self.currentSelector touchedHandle:initalFrame]; 188 | break; 189 | } 190 | } 191 | if(!didHitSelector) { 192 | [self setPickerWithFrame:initalFrame]; 193 | } 194 | } 195 | 196 | [self.view setNeedsDisplay:YES]; 197 | } 198 | 199 | /** If the left mouse button has been released and the canvas has selectors determine if the current selector object is a picker. If yes, mark every intersecting selection as selected. If not, try to drop the current selector object on the canvas. If this is not possible discard the current selector object. 200 | @param theEvent An object encapsulating information about the mouse-up event. 201 | */ 202 | - (void)mouseUp:(NSEvent *)theEvent { 203 | 204 | self.cursorCanBeChanged = YES; 205 | 206 | if(self.hasSelector) { 207 | if(self.currentSelector.isPicker) { 208 | for(MSSSelector *selector in self.selectors) { 209 | [selector intersectsFrame:self.currentSelector.frame]; 210 | } 211 | self.currentSelector = nil; 212 | } else { 213 | if(self.currentSelector.canDropOnCanvas) { 214 | [self performSelector:@selector(canvasHasChanged)]; 215 | 216 | } else { 217 | [self._selectors removeObject:self.currentSelector]; 218 | self.currentSelector = nil; 219 | } 220 | } 221 | } 222 | [self.view setNeedsDisplay:YES]; 223 | 224 | } 225 | 226 | 227 | /** If the left mouse button is pressed, the mouse has been moved and the canvas has selectors execute the corresponding action of the current selection object. 228 | @param theEvent An object encapsulating information about the mouse-dragged event. 229 | */ 230 | - (void)mouseDragged:(NSEvent *)theEvent { 231 | 232 | NSPoint currentPoint = [self.view convertPoint:[theEvent locationInWindow] fromView:nil]; 233 | 234 | if(self.hasSelector) { 235 | 236 | if(self.currentSelector.action == SelectorActionInit || self.currentSelector.action == SelectorActionResize) { 237 | [self.currentSelector resizeToPoint:currentPoint]; 238 | [self.view setNeedsDisplay:YES]; 239 | if([self.currentSelector touchedBoundaries]) { 240 | [self.view setNeedsDisplay:YES]; 241 | } 242 | } else if (self.currentSelector.action == SelectorActionMove) { 243 | [self.currentSelector moveSelectorToPoint:currentPoint]; 244 | [self.view setNeedsDisplay:YES]; 245 | if([self.currentSelector touchedBoundaries]) { 246 | [self.view setNeedsDisplay:YES]; 247 | } 248 | } 249 | } 250 | 251 | } 252 | 253 | /** If the DEL or BACKSPACE key is pressed delete all as selected marked selections. 254 | If CMD + A key is pressed mark all selectors as selected. 255 | If the ESC key is pressed mark all selectors as unselected. 256 | @param theEvent An object encapsulating information about the key-down event. 257 | */ 258 | - (void)keyDown:(NSEvent *)theEvent { 259 | 260 | if(theEvent.keyCode == 51 || theEvent.keyCode == 117) { 261 | [self removeMarkedSelectorsFromCanvas]; 262 | } else if(theEvent.keyCode == 0 && theEvent.modifierFlags&NSCommandKeyMask) { 263 | [self markAllSelected:YES]; 264 | } else if(theEvent.keyCode == 53) { 265 | [self markAllUnselected:YES]; 266 | } 267 | } 268 | 269 | - (void)mouseEntered:(NSEvent *)theEvent { 270 | if(self.cursorCanBeChanged) { 271 | NSDictionary *userInfo = (NSDictionary *)[theEvent userData]; 272 | NSCursor *cursor = [userInfo objectForKey:@"Cursor"]; 273 | [cursor set]; 274 | } 275 | } 276 | 277 | 278 | - (void)mouseExited:(NSEvent *)theEvent { 279 | 280 | if(self.cursorCanBeChanged) { 281 | [[NSCursor arrowCursor] set]; 282 | } 283 | } 284 | 285 | - (BOOL)acceptsFirstResponder { 286 | return YES; 287 | } 288 | 289 | 290 | #pragma mark - Public methods 291 | 292 | - (NSRect) defaultRectForFrame:(NSRect)frame { 293 | 294 | NSRect result = NSZeroRect; 295 | 296 | CGFloat newX = frame.origin.x; 297 | CGFloat newY = frame.origin.y; 298 | CGFloat newW = frame.size.width; 299 | CGFloat newH = frame.size.height; 300 | 301 | if(frame.size.width < 0) { 302 | newX = frame.origin.x + frame.size.width; 303 | newW = fabs(frame.size.width); 304 | } 305 | 306 | if(frame.size.height < 0) { 307 | newY = frame.origin.y + frame.size.height; 308 | newH = fabs(frame.size.height); 309 | } 310 | 311 | result = NSMakeRect(newX, newY, newW, newH); 312 | 313 | return result; 314 | 315 | } 316 | 317 | - (void) removeAllSelectorsFromCanvas { 318 | [self markAllSelected:NO]; 319 | [self removeMarkedSelectorsFromCanvas]; 320 | } 321 | 322 | - (BOOL) hasSelectors { 323 | 324 | if(self.selectors && self.selectors.count > 0) { 325 | return YES; 326 | } 327 | return NO; 328 | 329 | } 330 | 331 | #pragma mark - Other methods 332 | 333 | - (void) markAllUnselected:(BOOL)redraw { 334 | 335 | for(MSSSelector *selector in self.selectors) { 336 | [selector setUnselected]; 337 | } 338 | 339 | if(redraw) { 340 | [self.view setNeedsDisplay:YES]; 341 | } 342 | } 343 | 344 | - (void) markAllSelected:(BOOL)redraw { 345 | 346 | for(MSSSelector *selector in self.selectors) { 347 | [selector setSelected]; 348 | } 349 | 350 | if(redraw) { 351 | [self.view setNeedsDisplay:YES]; 352 | } 353 | } 354 | 355 | - (void) removeMarkedSelectorsFromCanvas { 356 | 357 | 358 | self.currentSelector = nil; 359 | NSMutableIndexSet *discardedItems = [NSMutableIndexSet indexSet]; 360 | for(int i=0;i 41 | #import 42 | #import "MSSPreferences.h" 43 | 44 | @class MSSSelector; 45 | 46 | /** Designable NSBezierPath to resize a MSSSelection from different corners */ 47 | @interface MSSHandle : NSObject { 48 | 49 | } 50 | /** @name Properties */ 51 | /** The handle's MSSSelector */ 52 | @property (nonatomic, readonly) MSSSelector* selector; 53 | /** The type (SelectorHandleType) of the handle */ 54 | @property (nonatomic, readonly) SelectorHandleType type; 55 | /** The handle's frame */ 56 | @property (nonatomic, readonly) NSRect frame; 57 | /** The handle's boundaries */ 58 | @property (nonatomic, readonly) NSRect bounds; 59 | /** The handle's NSShadow */ 60 | @property (nonatomic, readonly) NSShadow *shadow; 61 | /** The actual NSBezierPath of the handle */ 62 | @property (nonatomic, readonly) NSBezierPath *bezierPath; 63 | /** The current NSTrackingArea of the handle */ 64 | @property (nonatomic, readonly) NSTrackingArea *trackingArea; 65 | /** @name Methods */ 66 | /** Creates a handle with type for a given MSSSelector 67 | @param type The type handle which should be created 68 | @param selector The selector to create the handle for 69 | */ 70 | + (instancetype) handleWithType:(SelectorHandleType)type forSelector:(MSSSelector*)selector; 71 | /** Draws the handle on the canvas */ 72 | - (void) drawPath; 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/Classes/Base/MSSHandle.m: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ------------------------------------------------------------------------------------ 4 | MSSHandle.m 5 | ------------------------------------------------------------------------------------ 6 | A handle is a little NSBezierPath (by default a rectangle) element. 7 | The handles are used to resize a MSSSelector starting from the corners. 8 | By default every selector has four handles (one for each corner). 9 | In order to know which corner handle is selected the handle has a type. 10 | Of course the NSBezierPath can be overwritten. This applies for the NSShadow, too. 11 | Every handle can also have a different look (stroke and fill color). 12 | The look is defined by a style which is determinated in the canvasController. 13 | Tipp: For a quick start please read the README document. 14 | ------------------------------------------------------------------------------------ 15 | 16 | The MIT License (MIT) 17 | 18 | Copyright (c) 2014 Sascha Paulus 19 | 20 | Permission is hereby granted, free of charge, to any person obtaining a copy 21 | of this software and associated documentation files (the "Software"), to deal 22 | in the Software without restriction, including without limitation the rights 23 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 24 | copies of the Software, and to permit persons to whom the Software is 25 | furnished to do so, subject to the following conditions: 26 | 27 | The above copyright notice and this permission notice shall be included in all 28 | copies or substantial portions of the Software. 29 | 30 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 31 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 32 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 33 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 34 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 35 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 36 | SOFTWARE. 37 | 38 | */ 39 | 40 | #import "MSSHandle.h" 41 | #import "MSSSelector.h" 42 | #import "MSSHandleStyle.h" 43 | 44 | @interface MSSHandle () 45 | 46 | @property (nonatomic) MSSHandleStyle *handleStyle; 47 | 48 | /** Sets the frame for the handle according to the selectors frame */ 49 | - (void) makeHandleFrameWithSelectorFrame; 50 | /** Sets the handles's HandleStyle wheather from a default style or a style which is assigned to the canvas's delegate. */ 51 | - (void)setStyle; 52 | /** Update the tracking area */ 53 | - (void) updateTrackingArea; 54 | 55 | @end 56 | 57 | @implementation MSSHandle 58 | 59 | @synthesize type = _type; 60 | @synthesize frame = _frame; 61 | @synthesize bounds = _bounds; 62 | @synthesize selector = _selector; 63 | @synthesize trackingArea = _trackingArea; 64 | 65 | #pragma mark - Init & Alloc 66 | 67 | /** Initilizes a handle with a type for a given MSSSelector 68 | @param handleType The type handle which should be created 69 | @param selector The selector to create the handle for 70 | */ 71 | - (instancetype) initWithType:(SelectorHandleType)handleType forSelector:(MSSSelector*)selector { 72 | 73 | self = [super init]; 74 | if(self) { 75 | _selector = selector; 76 | [self setStyle]; 77 | _type = handleType; 78 | } 79 | return self; 80 | } 81 | 82 | + (instancetype) handleWithType:(SelectorHandleType)type forSelector:(MSSSelector*)selector { 83 | id instance = [[self alloc] initWithType:type forSelector:selector]; 84 | return instance; 85 | } 86 | 87 | - (void)setStyle { 88 | if([self.selector.canvas.delegate handleStyle]!=nil) { 89 | self.handleStyle = [self.selector.canvas.delegate handleStyle]; 90 | } else { 91 | self.handleStyle = [[MSSHandleStyle alloc] init]; 92 | } 93 | } 94 | 95 | #pragma mark - Public methods 96 | 97 | - (void) drawPath { 98 | 99 | [self makeHandleFrameWithSelectorFrame]; 100 | 101 | NSBezierPath *path = self.bezierPath; 102 | [self.handleStyle.strokeColor setStroke]; 103 | [path stroke]; 104 | 105 | [NSGraphicsContext saveGraphicsState]; 106 | NSShadow *shadow; 107 | if((shadow = self.shadow)!=nil) [shadow set]; 108 | [self.handleStyle.fillColor setFill]; 109 | [path fill]; 110 | [NSGraphicsContext restoreGraphicsState]; 111 | 112 | } 113 | 114 | #pragma mark - Internal methods 115 | 116 | 117 | - (void) updateTrackingArea { 118 | 119 | NSRect trackingRect = [self.selector.canvas.delegate defaultRectForFrame:self.frame]; 120 | if(self.trackingArea != nil) { 121 | [self.selector.canvas removeTrackingArea:self.trackingArea]; 122 | _trackingArea = nil; 123 | } 124 | 125 | NSCursor *cursor = [NSCursor crosshairCursor]; 126 | NSPoint hotSpot = NSMakePoint(9,9); 127 | NSBundle *frameworkBundle = [NSBundle bundleForClass:[self class]]; 128 | NSString *buttomTopPath = [frameworkBundle pathForImageResource:@"BottomTop"]; 129 | NSString *topButtomPath = [frameworkBundle pathForImageResource:@"TopBottom"]; 130 | NSImage *buttomTop = [[NSImage alloc] initByReferencingFile:buttomTopPath]; 131 | NSImage *topButtom = [[NSImage alloc] initByReferencingFile:topButtomPath]; 132 | 133 | 134 | if (self.type == SelectorHandleTypeLowerLeft) { 135 | cursor = [[NSCursor alloc] initWithImage:buttomTop hotSpot:hotSpot]; 136 | } else if (self.type == SelectorHandleTypeUpperLeft) { 137 | cursor = [[NSCursor alloc] initWithImage:topButtom hotSpot:hotSpot]; 138 | } else if (self.type == SelectorHandleTypeUpperRight) { 139 | cursor = [[NSCursor alloc] initWithImage:buttomTop hotSpot:hotSpot]; 140 | } else if (self.type == SelectorHandleTypeLowerRight) { 141 | cursor = [[NSCursor alloc] initWithImage:topButtom hotSpot:hotSpot]; 142 | } 143 | 144 | NSTrackingAreaOptions options = NSTrackingActiveAlways | NSTrackingMouseEnteredAndExited; 145 | _trackingArea = [[NSTrackingArea alloc] initWithRect:trackingRect options:options owner:self.selector.canvas userInfo:@{@"Cursor":cursor,@"Rect":NSStringFromRect(trackingRect)}]; 146 | [self.selector.canvas addTrackingArea:self.trackingArea]; 147 | 148 | } 149 | - (void) makeHandleFrameWithSelectorFrame { 150 | 151 | 152 | CGFloat halfWidth = self.handleStyle.size.width / 2; 153 | CGFloat halfHeight = self.handleStyle.size.height /2; 154 | 155 | NSRect selectorFrame = self.selector.frame; 156 | CGFloat minY = selectorFrame.origin.y; 157 | CGFloat maxY = selectorFrame.origin.y + selectorFrame.size.height; 158 | CGFloat minX = selectorFrame.origin.x; 159 | CGFloat maxX = selectorFrame.origin.x + selectorFrame.size.width; 160 | 161 | switch (self.type) { 162 | case SelectorHandleTypeUpperLeft: { 163 | _frame = NSMakeRect(minX - halfWidth, maxY - halfHeight, self.handleStyle.size.width, self.handleStyle.size.height); 164 | break; 165 | } 166 | case SelectorHandleTypeUpperRight: { 167 | _frame = NSMakeRect(maxX - halfWidth, maxY - halfHeight, self.handleStyle.size.width, self.handleStyle.size.height); 168 | break; 169 | } 170 | case SelectorHandleTypeLowerLeft: { 171 | _frame = NSMakeRect(minX - halfWidth, minY - halfHeight, self.handleStyle.size.width, self.handleStyle.size.height); 172 | break; 173 | } 174 | case SelectorHandleTypeLowerRight: { 175 | _frame = NSMakeRect(maxX - halfWidth, minY - halfHeight, self.handleStyle.size.width, self.handleStyle.size.height); 176 | break; 177 | } 178 | default: { 179 | _frame = NSZeroRect; 180 | break; 181 | } 182 | } 183 | 184 | _bounds = _frame; 185 | 186 | [self updateTrackingArea]; 187 | 188 | } 189 | 190 | 191 | 192 | - (NSShadow *) shadow { 193 | return nil; 194 | } 195 | 196 | - (NSBezierPath*) bezierPath { 197 | NSBezierPath *path = [NSBezierPath bezierPathWithOvalInRect:self.frame]; 198 | [path setLineWidth:2.0f]; 199 | return path; 200 | } 201 | 202 | @end 203 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/Classes/Base/MSSHandleStyle.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ------------------------------------------------------------------------------------ 4 | HandleStyle.h 5 | ------------------------------------------------------------------------------------ 6 | This class provides properties for the look of a MSSHandle. 7 | If maintained via interface builder it is possible set the values via IB UI. 8 | Tipp: For a quick start please read the README document. 9 | ------------------------------------------------------------------------------------ 10 | 11 | The MIT License (MIT) 12 | 13 | Copyright (c) 2014 Sascha Paulus 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining a copy 16 | of this software and associated documentation files (the "Software"), to deal 17 | in the Software without restriction, including without limitation the rights 18 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 19 | copies of the Software, and to permit persons to whom the Software is 20 | furnished to do so, subject to the following conditions: 21 | 22 | The above copyright notice and this permission notice shall be included in all 23 | copies or substantial portions of the Software. 24 | 25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | SOFTWARE. 32 | 33 | */ 34 | 35 | #import 36 | 37 | IB_DESIGNABLE 38 | /** Represents a style object for a MSSHandle. */ 39 | @interface MSSHandleStyle : NSObject { 40 | 41 | } 42 | /** @name Properties */ 43 | /** Determines the stroke color for a handle. */ 44 | @property (nonatomic) IBInspectable NSColor *strokeColor; 45 | /** Determines the fill color for a handle. */ 46 | @property (nonatomic) IBInspectable NSColor *fillColor; 47 | /** Determines the size for a handle. */ 48 | @property (nonatomic) IBInspectable NSSize size; 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/Classes/Base/MSSHandleStyle.m: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ------------------------------------------------------------------------------------ 4 | MSSHandleStyle.m 5 | ------------------------------------------------------------------------------------ 6 | This class provides properties for the look of a MSSHandle. 7 | If maintained via interface builder it is possible set the values via IB UI. 8 | Tipp: For a quick start please read the README document. 9 | ------------------------------------------------------------------------------------ 10 | 11 | The MIT License (MIT) 12 | 13 | Copyright (c) 2014 Sascha Paulus 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining a copy 16 | of this software and associated documentation files (the "Software"), to deal 17 | in the Software without restriction, including without limitation the rights 18 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 19 | copies of the Software, and to permit persons to whom the Software is 20 | furnished to do so, subject to the following conditions: 21 | 22 | The above copyright notice and this permission notice shall be included in all 23 | copies or substantial portions of the Software. 24 | 25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | SOFTWARE. 32 | 33 | */ 34 | 35 | #import "MSSHandleStyle.h" 36 | 37 | @implementation MSSHandleStyle 38 | 39 | - (instancetype) init { 40 | self = [super init]; 41 | if(self != nil) { 42 | 43 | CGFloat red = 0.1054f; 44 | CGFloat green = 0.4531f; 45 | CGFloat blue = 0.7929f; 46 | self.size = NSMakeSize(8.5f, 8.5f); 47 | self.strokeColor = [NSColor whiteColor]; 48 | self.fillColor = [NSColor colorWithCalibratedRed:red green:green blue:blue alpha:1.0f]; 49 | } 50 | return self; 51 | } 52 | 53 | 54 | @end 55 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/Classes/Base/MSSSelector.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ------------------------------------------------------------------------------------ 4 | MSSSelector.h 5 | ------------------------------------------------------------------------------------ 6 | This class is the actual selection path on a MSSCanvas. A canvas can have 7 | multiple selectors. Basically a selector is a NSBezierPath which interacts with 8 | the mouse activities. Movement and Resizing are controlled by the canvasController. 9 | Their two types of selectors: picker and selector. A normal selector stays drawn 10 | on the canvas and a picker selector is just for the purpose of selecting/collecting 11 | available selectors and mark them as selected. The NSBezierPaths for the picker and 12 | for the selector can be overwritten. Each selector has four handles for resizing. 13 | Every selector can also have a different look (stroke and fill colors). 14 | The look is defined by a style which is determinated in the canvasController. 15 | Tipp: For a quick start please read the README document. 16 | ------------------------------------------------------------------------------------ 17 | 18 | The MIT License (MIT) 19 | 20 | Copyright (c) 2014 Sascha Paulus 21 | 22 | Permission is hereby granted, free of charge, to any person obtaining a copy 23 | of this software and associated documentation files (the "Software"), to deal 24 | in the Software without restriction, including without limitation the rights 25 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 26 | copies of the Software, and to permit persons to whom the Software is 27 | furnished to do so, subject to the following conditions: 28 | 29 | The above copyright notice and this permission notice shall be included in all 30 | copies or substantial portions of the Software. 31 | 32 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 33 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 34 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 35 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 36 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 37 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 38 | SOFTWARE. 39 | 40 | */ 41 | 42 | #import 43 | #import 44 | #import "MSSPreferences.h" 45 | #import "MSSCanvas.h" 46 | #import "MSSHandle.h" 47 | 48 | /** Represents a designable selection rectangle with handles to resize */ 49 | @interface MSSSelector : NSObject { 50 | 51 | } 52 | /** @name Properties */ 53 | /** The MSSCanvas on which the selector is drawn */ 54 | @property (nonatomic, readonly) MSSCanvas *canvas; 55 | /** The selector's frame */ 56 | @property (nonatomic, readonly) NSRect frame; 57 | /** Determines if the selector is selected */ 58 | @property (nonatomic, readonly) BOOL isSelected; 59 | /** Determines if the selector is just a picker 60 | 61 | A non-picker selector stays drawn on the canvas and a picker selector is just for the purpose of selecting/collecting available selectors and mark them as selected. 62 | */ 63 | @property (nonatomic, readonly) BOOL isPicker; 64 | /** Determines the current SelectorAction */ 65 | @property (nonatomic, readonly) SelectorAction action; 66 | /** Holds all handles of the selector */ 67 | @property (nonatomic, readonly) NSMutableArray *handles; 68 | /** Determines the current handle */ 69 | @property (nonatomic, readonly) MSSHandle *currentHandle; 70 | /** The actual NSBezierPath of the selector */ 71 | @property (nonatomic, readonly) NSBezierPath *selectorBezierPath; 72 | /** @abstract The actual NSBezierPath of the selector if the selector is a picker 73 | @discussion For more details about the distinction between picker and selector checkout the isPicker property. 74 | */ 75 | @property (nonatomic, readonly) NSBezierPath *pickerBezierPath; 76 | /** The current NSTrackingArea of the handle */ 77 | @property (nonatomic, readonly) NSTrackingArea *trackingArea; 78 | /** @name Methods */ 79 | /** 80 | @abstract Creates a selector or picker for a given MSSCanvas 81 | @param rect The frame for the selector 82 | @param canvas The canvas on which the selector should be drawn 83 | @param picker Determines if the new selector should be a picker 84 | @discussion For more details about the distinction between picker and selector checkout the isPicker property. 85 | */ 86 | + (instancetype) selectorWithFrame:(NSRect)rect forCanvas:canvas asPicker:(BOOL)picker; 87 | /** Determines if a selector's handle has been touched and prepare the corresponding action for the selector 88 | @param rect The frame, which could have touched the handle. 89 | */ 90 | - (BOOL) touchedHandle:(NSRect)rect; 91 | /** Determines if the selector's frame intersects with a given NSRect 92 | @param rect The frame, which could have intersected the selector. 93 | */ 94 | - (BOOL) intersectsFrame:(NSRect)rect; 95 | /** Draws the selector's NSBezierPath */ 96 | - (void) drawPath; 97 | /** Marks the selector as selected */ 98 | - (void) setSelected; 99 | /** Marks the selector as unselected */ 100 | - (void) setUnselected; 101 | /** Moves the selector to a given point 102 | @param point The point on the canvas to move the selector to. 103 | */ 104 | - (void) moveSelectorToPoint:(CGPoint)point; 105 | /** Resizes the selector from the current origin to a given point 106 | @param point The point on the canvas to resize the selector to. 107 | */ 108 | - (void) resizeToPoint:(CGPoint)point; 109 | /** Determines if the selector can be dropped on the canvas 110 | 111 | Depending on whether intersections with other selectors is allowed or not or the minimum rectangle size for new selectors does not apply, the dropping of the current selector can be denied. In this case the current selector will be discarded, regardless if the selector is new or already existed and only has been resized or moved. 112 | 113 | */ 114 | - (BOOL) canDropOnCanvas; 115 | /** Determines if the selector's frame crosses the canvas boundaries */ 116 | - (BOOL) touchedBoundaries; 117 | /** Prepares the selector for a certain action 118 | @param action The SelectorAction to prepare the selector for. 119 | */ 120 | - (void) prepareAction:(SelectorAction)action; 121 | /** Removes all tracking areas for this selector */ 122 | - (void) removeTrackingAreas; 123 | 124 | @end 125 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/Classes/Base/MSSSelectorStyle.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ------------------------------------------------------------------------------------ 4 | MSSSelectorStyle.h 5 | ------------------------------------------------------------------------------------ 6 | This class provides properties for the look of a MSSSelector. 7 | If maintained via interface builder it is possible set the values via IB UI. 8 | Tipp: For a quick start please read the README document. 9 | ------------------------------------------------------------------------------------ 10 | 11 | The MIT License (MIT) 12 | 13 | Copyright (c) 2014 Sascha Paulus 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining a copy 16 | of this software and associated documentation files (the "Software"), to deal 17 | in the Software without restriction, including without limitation the rights 18 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 19 | copies of the Software, and to permit persons to whom the Software is 20 | furnished to do so, subject to the following conditions: 21 | 22 | The above copyright notice and this permission notice shall be included in all 23 | copies or substantial portions of the Software. 24 | 25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | SOFTWARE. 32 | 33 | */ 34 | 35 | #import 36 | 37 | IB_DESIGNABLE 38 | /** Represents a style object for a MSSSelector. */ 39 | @interface MSSSelectorStyle : NSObject { 40 | 41 | } 42 | /** @name Properties */ 43 | /** Determines the minimum height for a selector */ 44 | @property (nonatomic) IBInspectable CGFloat minHeight; 45 | /** Determines the minimum width for a selector */ 46 | @property (nonatomic) IBInspectable CGFloat minWidth; 47 | /** @abstract Determines the stroke color for a picker selector. 48 | @discussion For more details about the distinction between picker and selector checkout the isPicker property. */ 49 | @property (nonatomic) IBInspectable NSColor *strokeColorPicker; 50 | /** Determines the fill color for a picker selector. 51 | @discussion For more details about the distinction between picker and selector checkout the isPicker property. */ 52 | @property (nonatomic) IBInspectable NSColor *fillColorPicker; 53 | /** Determines the stroke color for a selector if it is marked as selected. */ 54 | @property (nonatomic) IBInspectable NSColor *strokeColorSelected; 55 | /** Determines the stroke color for a selector if it is NOT marked as selected. */ 56 | @property (nonatomic) IBInspectable NSColor *strokeColorUnselected; 57 | /** Determines the fill color for a selector if it is marked as selected. */ 58 | @property (nonatomic) IBInspectable NSColor *fillColorSelected; 59 | /** Determines the fill color for a selector if it is NOT marked as selected. */ 60 | @property (nonatomic) IBInspectable NSColor *fillColorUnselected; 61 | /** Determines the width of the stroke line if selector is marked as selected */ 62 | @property (nonatomic) IBInspectable CGFloat lineWidthSelected; 63 | /** Determines the width of the stroke line if selector is NOT marked as selected */ 64 | @property (nonatomic) IBInspectable CGFloat lineWidthUnselected; 65 | /** Determines if the stroke line should be dashed if selector is marked as selected */ 66 | @property (nonatomic) IBInspectable BOOL lineDashedSelected; 67 | /** Determines if the stroke line should be dashed if selector is NOT marked as selected */ 68 | @property (nonatomic) IBInspectable BOOL lineDashedUnselected; 69 | 70 | @end 71 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/Classes/Base/MSSSelectorStyle.m: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ------------------------------------------------------------------------------------ 4 | MSSSelectorStyle.m 5 | ------------------------------------------------------------------------------------ 6 | This class provides properties for the look of a MSSSelector. 7 | If maintained via interface builder it is possible set the values via IB UI. 8 | Tipp: For a quick start please read the README document. 9 | ------------------------------------------------------------------------------------ 10 | 11 | The MIT License (MIT) 12 | 13 | Copyright (c) 2014 Sascha Paulus 14 | 15 | Permission is hereby granted, free of charge, to any person obtaining a copy 16 | of this software and associated documentation files (the "Software"), to deal 17 | in the Software without restriction, including without limitation the rights 18 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 19 | copies of the Software, and to permit persons to whom the Software is 20 | furnished to do so, subject to the following conditions: 21 | 22 | The above copyright notice and this permission notice shall be included in all 23 | copies or substantial portions of the Software. 24 | 25 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | SOFTWARE. 32 | 33 | */ 34 | 35 | #import "MSSSelectorStyle.h" 36 | 37 | @implementation MSSSelectorStyle 38 | 39 | - (instancetype)init { 40 | self = [super init]; 41 | if(self != nil) { 42 | self.minHeight = 20.0f; 43 | self.minWidth = 20.0f; 44 | self.strokeColorSelected = [NSColor lightGrayColor]; 45 | self.strokeColorUnselected = [NSColor lightGrayColor]; 46 | self.fillColorSelected = [NSColor colorWithCalibratedRed:0.0f green:0.2f blue:1.0f alpha:0.10f]; 47 | self.fillColorUnselected = [NSColor clearColor]; 48 | self.strokeColorPicker = self.strokeColorSelected; 49 | self.fillColorPicker = self.fillColorSelected; 50 | self.lineDashedSelected = YES; 51 | self.lineDashedUnselected = YES; 52 | self.lineWidthSelected = 1; 53 | self.lineWidthUnselected = 1; 54 | 55 | } 56 | return self; 57 | } 58 | 59 | 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/Classes/Others/BottomTop@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ckteebe/MultiSelectionSuiteFramework/e3840b1a379364416d6113c47391d408d40869b2/MultiSelectionSuiteFramework/MultiSelectionSuite/Classes/Others/BottomTop@2x.png -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/Classes/Others/NSImageView+MSSScaledImage.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ------------------------------------------------------------------------------------ 4 | NSImageView+MSSScaledImage.h 5 | ------------------------------------------------------------------------------------ 6 | Category for NSImageView to deal with the original image 7 | ------------------------------------------------------------------------------------ 8 | 9 | The MIT License (MIT) 10 | 11 | Copyright (c) 2014 Sascha Paulus 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy 14 | of this software and associated documentation files (the "Software"), to deal 15 | in the Software without restriction, including without limitation the rights 16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | copies of the Software, and to permit persons to whom the Software is 18 | furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included in all 21 | copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 29 | SOFTWARE. 30 | 31 | */ 32 | 33 | #import 34 | #import 35 | 36 | /** Category for NSImageView to deal with the original image and the image's fileURL */ 37 | @interface NSImageView (MSSScaledImage) 38 | /** @name Properties */ 39 | /** The original image behind the scaled image */ 40 | @property (nonatomic, readonly) NSImage *originalImage; 41 | /** The ratio/scale between the controlView's frame and the original image */ 42 | @property (nonatomic, readonly) NSSize originalImageRatio; 43 | /** The ratio/scale between the controlView's frame and the scaled image */ 44 | @property (nonatomic, readonly) NSSize imageRatio; 45 | /** The frame of the scaled image */ 46 | @property (nonatomic, readonly) NSRect scaledImageRect; 47 | /** @abstract The URL of the current image 48 | @discussion If the image is changed by Drag & Drop this value will be set automatically */ 49 | @property (nonatomic) NSURL *fileURL; 50 | @end 51 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/Classes/Others/NSImageView+MSSScaledImage.m: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ------------------------------------------------------------------------------------ 4 | NSimageView+MSSScaledImage.m 5 | ------------------------------------------------------------------------------------ 6 | Category for NSImageView to deal with the original image 7 | ------------------------------------------------------------------------------------ 8 | 9 | The MIT License (MIT) 10 | 11 | Copyright (c) 2014 Sascha Paulus 12 | 13 | Permission is hereby granted, free of charge, to any person obtaining a copy 14 | of this software and associated documentation files (the "Software"), to deal 15 | in the Software without restriction, including without limitation the rights 16 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 | copies of the Software, and to permit persons to whom the Software is 18 | furnished to do so, subject to the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be included in all 21 | copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 29 | SOFTWARE. 30 | 31 | */ 32 | 33 | #import "NSImageView+MSSScaledImage.h" 34 | #import 35 | 36 | @implementation NSImageView (MSSScaledImage) 37 | 38 | @dynamic fileURL; 39 | 40 | - (void) setFileURL:(NSURL*)url { 41 | objc_setAssociatedObject(self, @selector(fileURL), url, OBJC_ASSOCIATION_RETAIN); 42 | } 43 | 44 | - (NSURL*) fileURL { 45 | return objc_getAssociatedObject(self, @selector(fileURL)); 46 | } 47 | 48 | - (NSImage*) originalImage { 49 | 50 | CGFloat scale = 1.0f; 51 | // If fileURL exists and the file is a PDF scale it up by 2.5 52 | NSString *fileType; 53 | if(self.fileURL) { 54 | CGImageSourceRef isr = CGImageSourceCreateWithURL((__bridge CFURLRef)(self.fileURL), NULL); 55 | fileType = (__bridge NSString*)CGImageSourceGetType(isr); 56 | CFRelease(isr); 57 | } 58 | if(fileType && [fileType isEqualToString:@"com.adobe.pdf"]) { 59 | scale = 2.5; 60 | } 61 | 62 | NSImageRep *imageRep = [self.image.representations objectAtIndex:0]; 63 | CGFloat w = fmaxf(imageRep.size.width, imageRep.pixelsWide); 64 | CGFloat h = fmaxf(imageRep.size.height, imageRep.pixelsHigh); 65 | NSImage *image = [[NSImage alloc] initWithSize:NSMakeSize(w*scale, h*scale)]; 66 | [image addRepresentation:imageRep]; 67 | return image; 68 | } 69 | 70 | - (NSSize) originalImageRatio { 71 | 72 | 73 | NSImage *actualImage = [self originalImage]; 74 | 75 | NSSize imageSize = NSMakeSize(actualImage.size.width, actualImage.size.height); 76 | NSRect frameRect = [self.cell drawingRectForBounds:self.bounds]; 77 | NSSize frameSize = frameRect.size; 78 | 79 | NSSize ratio = NSZeroSize; 80 | CGFloat ratioX = frameSize.width / imageSize.width; 81 | CGFloat ratioY = frameSize.height / imageSize.height; 82 | CGFloat scale = 1.0f; 83 | 84 | switch (self.imageScaling) { 85 | case NSImageScaleProportionallyDown: 86 | scale = fminf(ratioX, ratioY); 87 | scale = fminf(scale, 1.0f); 88 | ratio = NSMakeSize(scale, scale); 89 | break; 90 | case NSImageScaleProportionallyUpOrDown: 91 | scale = fminf(ratioX, ratioY); 92 | ratio = NSMakeSize(scale, scale); 93 | break; 94 | case NSImageScaleAxesIndependently: 95 | ratio = NSMakeSize(ratioX, ratioY); 96 | break; 97 | default: 98 | ratio = NSMakeSize(scale, scale); 99 | break; 100 | } 101 | 102 | return ratio; 103 | 104 | 105 | } 106 | 107 | - (NSSize) imageRatio { 108 | 109 | NSSize imageSize = self.image.size; 110 | 111 | NSRect frameRect = [self.cell drawingRectForBounds:self.bounds]; 112 | NSSize frameSize = frameRect.size; 113 | 114 | NSSize ratio = NSZeroSize; 115 | CGFloat ratioX = frameSize.width / imageSize.width; 116 | CGFloat ratioY = frameSize.height / imageSize.height; 117 | CGFloat scale = 1.0f; 118 | 119 | switch (self.imageScaling) { 120 | case NSImageScaleProportionallyDown: 121 | scale = fminf(ratioX, ratioY); 122 | scale = fminf(scale, 1.0f); 123 | ratio = NSMakeSize(scale, scale); 124 | break; 125 | case NSImageScaleProportionallyUpOrDown: 126 | scale = fminf(ratioX, ratioY); 127 | ratio = NSMakeSize(scale, scale); 128 | break; 129 | case NSImageScaleAxesIndependently: 130 | ratio = NSMakeSize(ratioX, ratioY); 131 | break; 132 | default: 133 | ratio = NSMakeSize(scale, scale); 134 | break; 135 | } 136 | 137 | return ratio; 138 | 139 | } 140 | 141 | - (NSRect) scaledImageRect { 142 | 143 | NSRect scaledRect = NSZeroRect; 144 | 145 | NSSize imageSize = self.image.size; 146 | if (imageSize.width < 1.0 || imageSize.height < 1.0) { 147 | return scaledRect; 148 | } 149 | NSRect frameRect = [self.cell drawingRectForBounds:self.bounds]; 150 | NSSize frameSize = frameRect.size; 151 | NSSize ratio = self.imageRatio; 152 | 153 | 154 | CGFloat scaledWidth = imageSize.width * ratio.width; 155 | CGFloat scaledHeight = imageSize.height * ratio.height; 156 | NSSize scaledSize = NSMakeSize(scaledWidth, scaledHeight); 157 | 158 | CGFloat Xmin = 0.0f; 159 | CGFloat Xmax = frameSize.width - scaledSize.width; 160 | CGFloat verticalCenter = (frameSize.width - scaledSize.width) / 2; 161 | CGFloat Ymin = 0.0f; 162 | CGFloat Ymax = frameSize.height - scaledSize.height; 163 | CGFloat horizontalCenter = (frameSize.height - scaledSize.height) / 2; 164 | 165 | switch (self.imageAlignment) { 166 | case NSImageAlignCenter: 167 | scaledRect = NSMakeRect(verticalCenter, horizontalCenter, scaledSize.width, scaledSize.height); 168 | break; 169 | case NSImageAlignLeft: 170 | scaledRect = NSMakeRect(Xmin, horizontalCenter, scaledSize.width, scaledSize.height); 171 | break; 172 | case NSImageAlignRight: 173 | scaledRect = NSMakeRect(Xmax, horizontalCenter, scaledSize.width, scaledSize.height); 174 | break; 175 | case NSImageAlignTop: 176 | scaledRect = NSMakeRect(verticalCenter, Ymax, scaledSize.width, scaledSize.height); 177 | break; 178 | case NSImageAlignTopLeft: 179 | scaledRect = NSMakeRect(Xmin, Ymax, scaledSize.width, scaledSize.height); 180 | break; 181 | case NSImageAlignTopRight: 182 | scaledRect = NSMakeRect(Xmax, Ymax, scaledSize.width, scaledSize.height); 183 | break; 184 | case NSImageAlignBottom: 185 | scaledRect = NSMakeRect(verticalCenter, Ymin, scaledSize.width, scaledSize.height); 186 | break; 187 | case NSImageAlignBottomLeft: 188 | scaledRect = NSMakeRect(Xmin, Ymin, scaledSize.width, scaledSize.height); 189 | break; 190 | case NSImageAlignBottomRight: 191 | scaledRect = NSMakeRect(Xmax, Ymin, scaledSize.width, scaledSize.height); 192 | break; 193 | } 194 | 195 | scaledRect = NSOffsetRect(scaledRect, frameRect.origin.x, frameRect.origin.y); 196 | 197 | return scaledRect; 198 | } 199 | 200 | /** Overwrites the default draggingEntered in order to intercept the draged fileUrl */ 201 | - (NSDragOperation)draggingEntered:(id)sender { 202 | 203 | NSPasteboard *pboard = [sender draggingPasteboard]; 204 | NSDragOperation sourceDragMask = [sender draggingSourceOperationMask]; 205 | 206 | if([[pboard types] containsObject:NSURLPboardType]) { 207 | if(sourceDragMask & NSDragOperationGeneric) { 208 | self.fileURL = [NSURL URLFromPasteboard:pboard]; 209 | return NSDragOperationCopy; 210 | } 211 | 212 | } 213 | return NSDragOperationNone; 214 | } 215 | 216 | 217 | @end 218 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/Classes/Others/TopBottom@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ckteebe/MultiSelectionSuiteFramework/e3840b1a379364416d6113c47391d408d40869b2/MultiSelectionSuiteFramework/MultiSelectionSuite/Classes/Others/TopBottom@2x.png -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/Classes/Preferences/MSSError.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ------------------------------------------------------------------------------------ 4 | MSSError.h 5 | ------------------------------------------------------------------------------------ 6 | 7 | The MIT License (MIT) 8 | 9 | Copyright (c) 2014 Sascha Paulus 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy 12 | of this software and associated documentation files (the "Software"), to deal 13 | in the Software without restriction, including without limitation the rights 14 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | copies of the Software, and to permit persons to whom the Software is 16 | furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in all 19 | copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | SOFTWARE. 28 | 29 | */ 30 | 31 | #import 32 | 33 | #define MSS_ERROR_KEY(code) [NSString stringWithFormat:@"%d",code] 34 | #define MSS_ERROR_DESC(code) NSLocalizedStringFromTableInBundle(MSS_ERROR_KEY(code), @"MSSError", [NSBundle bundleForClass:[self class]], nil) 35 | 36 | FOUNDATION_EXPORT NSString *const MSSErrorDomain; 37 | 38 | enum { 39 | /** Error if no selection is on the canvas */ 40 | MSSErrorNoSelections = 1000, 41 | /** Error if no save directory is given */ 42 | MSSErrorNoSaveDirectory, 43 | /** Error if save directory not exists */ 44 | MSSErrorSaveDirectoryNotExists, 45 | /** Error if save target is not a directory */ 46 | MSSErrorSaveDirectoryUrlIsNoDirectory, 47 | /** Error if saving failed */ 48 | MSSErrorImageSavingFailed, 49 | /** Error if given file type is not supported yet */ 50 | MSSErrorFileTypeNotSupportedYet, 51 | }; -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/Classes/Preferences/MSSError.m: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ------------------------------------------------------------------------------------ 4 | MSSError.m 5 | ------------------------------------------------------------------------------------ 6 | 7 | The MIT License (MIT) 8 | 9 | Copyright (c) 2014 Sascha Paulus 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy 12 | of this software and associated documentation files (the "Software"), to deal 13 | in the Software without restriction, including without limitation the rights 14 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | copies of the Software, and to permit persons to whom the Software is 16 | furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in all 19 | copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | SOFTWARE. 28 | 29 | */ 30 | 31 | #import "MSSError.h" 32 | 33 | NSString *const MSSErrorDomain = @"com.saschapaulus.frameworks.mss"; 34 | 35 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/Classes/Preferences/MSSPreferences.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ------------------------------------------------------------------------------------ 4 | MSSPreferences.h 5 | ------------------------------------------------------------------------------------ 6 | 7 | The MIT License (MIT) 8 | 9 | Copyright (c) 2014 Sascha Paulus 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy 12 | of this software and associated documentation files (the "Software"), to deal 13 | in the Software without restriction, including without limitation the rights 14 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | copies of the Software, and to permit persons to whom the Software is 16 | furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in all 19 | copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | SOFTWARE. 28 | 29 | */ 30 | 31 | #import 32 | 33 | FOUNDATION_EXPORT NSString * const MSSExtractorJobUnknown; 34 | FOUNDATION_EXPORT NSString * const MSSExtractorJobCropping; 35 | FOUNDATION_EXPORT NSString * const MSSExtractorJobOverviewScan; 36 | FOUNDATION_EXPORT NSString * const MSSExtractorJobImageScan; 37 | FOUNDATION_EXPORT NSString * const MSSExtractorJobZoom; 38 | 39 | /** Determines the type of a selector handle */ 40 | typedef NS_ENUM(NSInteger, SelectorHandleType) { 41 | /** No handle is selected or handle has no type */ 42 | SelectorHandleTypeNoHandle, 43 | /** Selected handle is on the upper left */ 44 | SelectorHandleTypeUpperLeft, 45 | /** Selected handle is on the upper right */ 46 | SelectorHandleTypeUpperRight, 47 | /** Selected handle is on the lower left */ 48 | SelectorHandleTypeLowerLeft, 49 | /** Selected handle is on the upper right */ 50 | SelectorHandleTypeLowerRight, 51 | }; 52 | 53 | /** Defines to current action of a selector */ 54 | typedef NS_ENUM(NSInteger, SelectorAction) { 55 | /** Selector has no action yet */ 56 | SelectorActionNone, 57 | /** Selector is about to resize */ 58 | SelectorActionResize, 59 | /** Selector is about to move */ 60 | SelectorActionMove, 61 | /** Selector is about to initialize */ 62 | SelectorActionInit, 63 | }; 64 | 65 | /** Determines the current selector position in the canvas boundaries */ 66 | typedef NS_ENUM(NSInteger, SelectorBoundariesPosition) { 67 | /** Selector is in boundaries */ 68 | SelectorBoundariesPositionInBounderies, 69 | /** Selector is out of boundaries (left side) */ 70 | SelectorBoundariesPositionLeftOuterBounderies, 71 | /** Selector is out of boundaries (right side) */ 72 | SelectorBoundariesPositionRightOuterBounderies, 73 | /** Selector is out of boundaries (top side) */ 74 | SelectorBoundariesPositionUpperOuterBounderies, 75 | /** Selector is out of boundaries (bottom side) */ 76 | SelectorBoundariesPositionLowerOuterBounderies, 77 | }; 78 | 79 | /** Defines the struture of a boundary */ 80 | typedef struct { 81 | /** Position (x,y) of the boundary */ 82 | CGFloat position; 83 | /** Size (width,height) of the boundary */ 84 | CGFloat size; 85 | } Boundary; 86 | 87 | /** Defines the boundaries of an object */ 88 | typedef struct { 89 | /** Boundary on the top side */ 90 | Boundary top; 91 | /** Boundary on the bottom side */ 92 | Boundary bottom; 93 | /** Boundary on the left side */ 94 | Boundary left; 95 | /** Boundary on the right side */ 96 | Boundary right; 97 | } Boundaries; 98 | 99 | 100 | /** Defines how much images should be compress */ 101 | typedef NS_ENUM(NSInteger, ExtractorImageCompressionLevel) { 102 | /** No compression (Image quality 100%) */ 103 | ExtractorImageCompressionLevelNone, 104 | /** Little compression (Image quality 80%) */ 105 | ExtractorImageCompressionLevelLow, 106 | /** Medium compression (Image quality 60%) */ 107 | ExtractorImageCompressionLevelMiddle, 108 | /** High compression (Image quality 30%) */ 109 | ExtractorImageCompressionLevelHigh, 110 | /** Highest compression (Image quality 10%) */ 111 | ExtractorImageCompressionLevelHighest, 112 | }; 113 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/Classes/Preferences/MSSPreferences.m: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | ------------------------------------------------------------------------------------ 4 | MSSPreferences.m 5 | ------------------------------------------------------------------------------------ 6 | 7 | The MIT License (MIT) 8 | 9 | Copyright (c) 2014 Sascha Paulus 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy 12 | of this software and associated documentation files (the "Software"), to deal 13 | in the Software without restriction, including without limitation the rights 14 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | copies of the Software, and to permit persons to whom the Software is 16 | furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in all 19 | copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | SOFTWARE. 28 | 29 | */ 30 | 31 | #import "MSSPreferences.h" 32 | 33 | NSString * const MSSExtractorJobUnknown = @"MSSExtractorJobUnknown"; 34 | NSString * const MSSExtractorJobCropping = @"MSSExtractorJobCropping"; 35 | NSString * const MSSExtractorJobOverviewScan = @"MSSExtractorJobOverviewScan"; 36 | NSString * const MSSExtractorJobImageScan = @"MSSExtractorJobImageScan"; 37 | NSString * const MSSExtractorJobZoom = @"MSSExtractorJobZoom"; -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.saschapaulus.frameworks.mss 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | $(CURRENT_PROJECT_VERSION) 23 | NSHumanReadableCopyright 24 | Copyright © 2015 Sascha Paulus. All rights reserved. 25 | NSPrincipalClass 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/MultiSelectionSuite.h: -------------------------------------------------------------------------------- 1 | 2 | #import 3 | 4 | //! Project version number for MultiSelectionSuite. 5 | FOUNDATION_EXPORT double MultiSelectionSuiteVersionNumber; 6 | 7 | //! Project version string for MultiSelectionSuite. 8 | FOUNDATION_EXPORT const unsigned char MultiSelectionSuiteVersionString[]; 9 | 10 | 11 | #import 12 | #import 13 | #import 14 | #import 15 | #import 16 | #import 17 | 18 | #import 19 | #import 20 | 21 | #import 22 | #import 23 | #import 24 | 25 | #import -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/de.lproj/MSSError.strings: -------------------------------------------------------------------------------- 1 | "1000" = "Es wurde keine Auswahl getroffen"; 2 | "1001" = "Es wurde kein Speicherverzeichnis gefunden"; 3 | "1002" = "Das genannte Verzeichnis existiert nicht"; 4 | "1003" = "Die genannte URL ist kein Verzeichnis"; 5 | "1004" = "Ein oder mehrere Bilder konnte nicht gespeichert werden"; 6 | "1005" = "Dieser Dateityp wird derzeit nicht unterstützt"; -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuite/en.lproj/MSSError.strings: -------------------------------------------------------------------------------- 1 | "1000" = "No selector has been set"; 2 | "1001" = "Delegate does not provide saving folder"; 3 | "1002" = "The provided saving folder does not exists"; 4 | "1003" = "The provided saving URL is no directory"; 5 | "1004" = "Saving of one or more images has been failed"; 6 | "1005" = "You use a not supported file type"; 7 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuiteFramework.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuiteFramework.xcodeproj/project.xcworkspace/xcuserdata/sascha.xcuserdatad/WorkspaceSettings.xcsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | HasAskedToTakeAutomaticSnapshotBeforeSignificantChanges 6 | 7 | SnapshotAutomaticallyBeforeSignificantChanges 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuiteFramework.xcodeproj/xcuserdata/sascha.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuiteFramework.xcodeproj/xcuserdata/sascha.xcuserdatad/xcschemes/MultiSelectionSuite.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 94 | 100 | 101 | 102 | 103 | 105 | 106 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /MultiSelectionSuiteFramework/MultiSelectionSuiteFramework.xcodeproj/xcuserdata/sascha.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | MultiSelectionSuite.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 2B24828E1A5AF9B9000C1F7A 16 | 17 | primary 18 | 19 | 20 | 2B7076CE1A5ABE4200707A69 21 | 22 | primary 23 | 24 | 25 | 2B7076D91A5ABE4200707A69 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | # MultiSelectionSuite.framework 2 | 3 | ## About 4 | The "MultiSelectionSuite" Framework provides an easy way to draw multiple, designable and interactive selection paths (mostly rectangles or any thinkable path) on any **MacOS** (not iOS) view. In addition it has out-of-the-box modules to extract the content of the selected areas. 5 | 6 | ![Example](http://assets.saschapaulus.de/mss/example.jpg) 7 | 8 | ## Understand "MultiSelectionSuite" 9 | 10 | **In order to have an easy start it is recommended to read the following lines.** 11 | I will try to keep them as short as possible. 12 | 13 | The base of MSS consists of four classes 14 | 15 | ### MSSSelector 16 | The selector is the actual path (mostly a rectangle) to mark a selection on the content. The selector can have any form since it is a simple NSBezierPath. But if you just like to change colors or lines you don't have to overwrite the MSSSelector class because MSS comes with MSSSelectorStyles which are easily configurable via Interface Builder. 17 | 18 | ### MSSCanvas 19 | To avoid any conflics with the contentView (e.g. NSImageView) all selectors will be drawn on a so called canvas.That's it. :) 20 | 21 | ### MSSCanvasController 22 | The canvasController handles all interactions between the view, the canvas, selectors, the mouse and others. canvasController also takes care of drawing, resizing, moving and removing. You don't even have to add the canvas as subview on your view since the controller takes care of adding and arranging too. 23 | 24 | ### MSSHandle 25 | A handle is a little path (by default a circle) at the selector's corners. The task of a handle is to provide an anchor to resize the selector in different directions. Like the selector, a handle can have any form you like. To change the colors only, MSS provides a style class (MSSHandleStyle) here as well. 26 | 27 | ### AddOn: MSSExtractor 28 | An extractor is not part of the actual base classes but yet quite important. Why ? Well, because all the fancy selectors would be very useless unless you can extract the content out of the selected areas. Because the job of an extractor depends on the purpose (e.g. cropping images) the MSSExtractor class is meant to be "abstract" and must be derived for any new purpose. The example project will make that more clear. 29 | 30 | 31 | ## Quick start & further information 32 | 33 | If you clone the git repository you'll get a complete Xcode workspace including 34 | the framework (MultiSelectionSuite) itself and an example project (MultiSelectionSuiteApp). 35 | If you press "Run" the framework and the example app should be built. 36 | 37 | Now let's take a closer look on the example project: 38 | 39 | ### Understand the example project 40 | 41 | The example project contains three real-world applications for MSS: 42 | 43 | - Image cropping 44 | - Zooming 45 | - Scan data extraction (Using my SPScannerCaptureWindow.bundle) 46 | 47 | **Next:** Open the example project (MultiSelectionSuiteApp) and take a look on the CropImageWindow.xib (under "Crop" Group) 48 | 49 | - The main view under the window containts a normal NSImageView 50 | - This image view is connected to the Outlet "contentView" of the "Canvas Controller" (MSSCanvasController) 51 | - The Outlet "view" of the "Canvas Controller" is connected to the "Canvas" (MSSCanvas) 52 | - Note that the "Canvas" is just somewhere in the room and not a subview of another view 53 | - The Outlet "delegate" of the "Canvas" is connected to the "Canvas Controller" 54 | 55 | **If we only would like to have selectors on the image view without any purpose we would be finish here.** 56 | 57 | **BUT** We're not satisfied yet, cause we want extract some content. 58 | 59 | - The Outlet "canvasController" of "Image Extractor" (MSSImageExtractor) is connected to "Canvas Controller" 60 | - The Outlet "contentExtractor" of "Canvas Controller" is connected to "Image Extractor" 61 | - The Outlet "delegate" of the "Image Extractor" is connected to the "File's owner" (CropImageWindow.h) 62 | - The IBAction of the "Save" button is in the "File's Owner" - so open "CropImageWindow.m" 63 | - The IBAction "saveImages" calls the "prepareJob"-Method of the "Image Extractor" (MSSImageExtractor) 64 | - Note that "CropImageWindow" confirms with the "MSSExtractorDelegate" protocol 65 | - Take look in the "extractor:extractElement:forJob"-Method (in CropImageWindow.h) 66 | - Whenever an extractor pulls content (here: images) this delegate method will be called 67 | - When all extractions are done the "extractor:didCompleteWithError"-Method will be called 68 | - The image extractor comes with a "saveImage:withType"-Method which will be called here 69 | - Note that the extractor contains all "elements" which have been extracted ... **DONE** 70 | 71 | ### Use the framework outside the example project 72 | 73 | The example project uses the product (MultiSelectionSuite.framework) of the framework project (MultiSelectionSuite). 74 | If you like to use the framework outside the example project you can either install 75 | the framework under /Library/Frameworks or embed it as "Private Framework" in your project's Application Bundle. The advantage of latter is there is no need of an installation process 76 | because everything will be inside your Application Bundle. Drawback: In order to use newer versions of the framework you need to rebuild your App, too. However: Here you'll learn about how to embed & link to a private framework in your Application. 77 | 78 | ### Nice to have information 79 | 80 | But how, where and when we assign which content fragment we want ? Well, this is all done in the MSSImageExtractor in cooperation with the canvasController. Since this project is open source and MSSImageExtractor has only one method you'll easily understand how it works. 81 | 82 | ### Strong recommendation 83 | 84 | Since you have a good basic understanding how MSS works and how you can use it in your projects I want to stop here explaining the example project. Of course I encourage you to discover the "Scan" and "Zoom" sections in the project. The "Zoom" section uses the styles for selectors (MSSSelectionStyle) and handles (MSSHandleStyle). You'll be delighted how nice & easy these are to use. 85 | 86 | The "Scan" section uses a special bundle of mine to encapsulate the quite complex scanning process. With "complex" I mean: There's a lot of boiler code which could distract you from learning more about this framework. Btw: The bundle uses the framework as well. If you like to know more about how scanning works in Cocoa: The bundle is open source too. You'll find it [here](https://github.com/ckteebe/SPScannerCaptureWindow). 87 | 88 | In order to understand the complete workflow between the canvasController and the extractors you should make you own extractor. Please keep in mind to derive your extractor from the master class MSSExtractor. If the extractor is useful for others I would be happy if you make it public for everyone by a pull request. 89 | 90 | 91 | ## Documention 92 | 93 | The code documentation of the framework can be found [here](http://assets.saschapaulus.de/mss/doc/v1/). 94 | --------------------------------------------------------------------------------