├── .gitignore ├── README.md ├── Snip.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata ├── xcshareddata │ └── xcschemes │ │ └── SnipManager.xcscheme └── xcuserdata │ └── liupeng.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ └── Snip.xcscheme ├── Snip ├── AppDelegate.h ├── AppDelegate.m ├── Base.lproj │ └── MainMenu.xib ├── DemoViewController.h ├── DemoViewController.m ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── Info.plist ├── app.icns └── main.m ├── SnipManager ├── DrawPathInfo.h ├── DrawPathInfo.m ├── DrawPathView.h ├── DrawPathView.m ├── ImageButton.h ├── ImageButton.m ├── Info.plist ├── MouseEventProtocol.h ├── NSColor+Helper.h ├── NSColor+Helper.m ├── Resource │ └── Images.bundle │ │ ├── ScreenCapture_toolbar_arrow_effect.tiff │ │ ├── ScreenCapture_toolbar_arrow_ineffect.tiff │ │ ├── ScreenCapture_toolbar_cross_normal.tiff │ │ ├── ScreenCapture_toolbar_ellipse_effect.tiff │ │ ├── ScreenCapture_toolbar_ellipse_ineffect.tiff │ │ ├── ScreenCapture_toolbar_export.tiff │ │ ├── ScreenCapture_toolbar_rect_effect.tiff │ │ ├── ScreenCapture_toolbar_rect_ineffect.tiff │ │ └── ScreenCapture_toolbar_tick_normal.tiff ├── SimpleLabelView.h ├── SimpleLabelView.m ├── SnipManager.h ├── SnipManager.m ├── SnipUtil.h ├── SnipUtil.m ├── SnipView.h ├── SnipView.m ├── SnipWindow.h ├── SnipWindow.m ├── SnipWindowController.h ├── SnipWindowController.m ├── SnipWindowController.xib ├── ToolContainer.h └── ToolContainer.m ├── SnipTests ├── Info.plist └── SnipTests.m └── src.png /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | .DS_Store 3 | */build/* 4 | *.pbxuser 5 | !default.pbxuser 6 | *.mode1v3 7 | !default.mode1v3 8 | *.mode2v3 9 | !default.mode2v3 10 | *.perspectivev3 11 | !default.perspectivev3 12 | xcuserdata 13 | project.xcworkspace 14 | profile 15 | *.moved-aside 16 | DerivedData 17 | .idea/ 18 | .svn/ 19 | *.hmap 20 | xcshareddata 21 | .last-build-date 22 | .xcodebuild_output 23 | 24 | Carthage 25 | Pods 26 | dmg-releases -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Capture Screen For Multi Screens On Mac 2 | There are many implementation about capture screen for mac. 3 |
4 | A sample is in xcode sample code. 5 |
6 | And mogutt also show code in https://github.com/mogutt/TTMacClient. 7 |
8 | But on dual monitors mode, they are all not work, 9 |
10 | even weixin's mac client and http://snip.qq.com/. 11 |
12 | Only QQ is powerful and perfect. 13 |
14 | And it's not open source. 15 |
16 | 17 | #So, I try to do the capture screen sample to support dual monitors. 18 |
19 | ![image](src.png) 20 | -------------------------------------------------------------------------------- /Snip.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 06C042CE1BBB77AB00B3B473 /* DrawPathInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 06C042B71BBB77AB00B3B473 /* DrawPathInfo.h */; settings = {ASSET_TAGS = (); }; }; 11 | 06C042CF1BBB77AB00B3B473 /* DrawPathInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 06C042B81BBB77AB00B3B473 /* DrawPathInfo.m */; settings = {ASSET_TAGS = (); }; }; 12 | 06C042D01BBB77AB00B3B473 /* DrawPathView.h in Headers */ = {isa = PBXBuildFile; fileRef = 06C042B91BBB77AB00B3B473 /* DrawPathView.h */; settings = {ASSET_TAGS = (); }; }; 13 | 06C042D11BBB77AB00B3B473 /* DrawPathView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06C042BA1BBB77AB00B3B473 /* DrawPathView.m */; settings = {ASSET_TAGS = (); }; }; 14 | 06C042D21BBB77AB00B3B473 /* ImageButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 06C042BB1BBB77AB00B3B473 /* ImageButton.h */; settings = {ASSET_TAGS = (); }; }; 15 | 06C042D31BBB77AB00B3B473 /* ImageButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 06C042BC1BBB77AB00B3B473 /* ImageButton.m */; settings = {ASSET_TAGS = (); }; }; 16 | 06C042D41BBB77AB00B3B473 /* MouseEventProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 06C042BD1BBB77AB00B3B473 /* MouseEventProtocol.h */; settings = {ASSET_TAGS = (); }; }; 17 | 06C042D51BBB77AB00B3B473 /* NSColor+Helper.h in Headers */ = {isa = PBXBuildFile; fileRef = 06C042BE1BBB77AB00B3B473 /* NSColor+Helper.h */; settings = {ASSET_TAGS = (); }; }; 18 | 06C042D61BBB77AB00B3B473 /* NSColor+Helper.m in Sources */ = {isa = PBXBuildFile; fileRef = 06C042BF1BBB77AB00B3B473 /* NSColor+Helper.m */; settings = {ASSET_TAGS = (); }; }; 19 | 06C042D71BBB77AB00B3B473 /* SimpleLabelView.h in Headers */ = {isa = PBXBuildFile; fileRef = 06C042C01BBB77AB00B3B473 /* SimpleLabelView.h */; settings = {ASSET_TAGS = (); }; }; 20 | 06C042D81BBB77AB00B3B473 /* SimpleLabelView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06C042C11BBB77AB00B3B473 /* SimpleLabelView.m */; settings = {ASSET_TAGS = (); }; }; 21 | 06C042D91BBB77AB00B3B473 /* SnipManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 06C042C21BBB77AB00B3B473 /* SnipManager.m */; settings = {ASSET_TAGS = (); }; }; 22 | 06C042DA1BBB77AB00B3B473 /* SnipUtil.h in Headers */ = {isa = PBXBuildFile; fileRef = 06C042C31BBB77AB00B3B473 /* SnipUtil.h */; settings = {ASSET_TAGS = (); }; }; 23 | 06C042DB1BBB77AB00B3B473 /* SnipUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = 06C042C41BBB77AB00B3B473 /* SnipUtil.m */; settings = {ASSET_TAGS = (); }; }; 24 | 06C042DC1BBB77AB00B3B473 /* SnipView.h in Headers */ = {isa = PBXBuildFile; fileRef = 06C042C51BBB77AB00B3B473 /* SnipView.h */; settings = {ASSET_TAGS = (); }; }; 25 | 06C042DD1BBB77AB00B3B473 /* SnipView.m in Sources */ = {isa = PBXBuildFile; fileRef = 06C042C61BBB77AB00B3B473 /* SnipView.m */; settings = {ASSET_TAGS = (); }; }; 26 | 06C042DE1BBB77AB00B3B473 /* SnipWindow.h in Headers */ = {isa = PBXBuildFile; fileRef = 06C042C71BBB77AB00B3B473 /* SnipWindow.h */; settings = {ASSET_TAGS = (); }; }; 27 | 06C042DF1BBB77AB00B3B473 /* SnipWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 06C042C81BBB77AB00B3B473 /* SnipWindow.m */; settings = {ASSET_TAGS = (); }; }; 28 | 06C042E01BBB77AB00B3B473 /* SnipWindowController.h in Headers */ = {isa = PBXBuildFile; fileRef = 06C042C91BBB77AB00B3B473 /* SnipWindowController.h */; settings = {ASSET_TAGS = (); }; }; 29 | 06C042E11BBB77AB00B3B473 /* SnipWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 06C042CA1BBB77AB00B3B473 /* SnipWindowController.m */; settings = {ASSET_TAGS = (); }; }; 30 | 06C042E21BBB77AB00B3B473 /* SnipWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 06C042CB1BBB77AB00B3B473 /* SnipWindowController.xib */; settings = {ASSET_TAGS = (); }; }; 31 | 06C042E31BBB77AB00B3B473 /* ToolContainer.h in Headers */ = {isa = PBXBuildFile; fileRef = 06C042CC1BBB77AB00B3B473 /* ToolContainer.h */; settings = {ASSET_TAGS = (); }; }; 32 | 06C042E41BBB77AB00B3B473 /* ToolContainer.m in Sources */ = {isa = PBXBuildFile; fileRef = 06C042CD1BBB77AB00B3B473 /* ToolContainer.m */; settings = {ASSET_TAGS = (); }; }; 33 | 06C043551BBBBA5400B3B473 /* SnipManager.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 06EC06A01BBABE1A00D3384D /* SnipManager.framework */; }; 34 | 06C0436B1BBBBF1200B3B473 /* Images.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 06C0436A1BBBBF1200B3B473 /* Images.bundle */; settings = {ASSET_TAGS = (); }; }; 35 | 06EC06A31BBABE1A00D3384D /* SnipManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 06EC06A21BBABE1A00D3384D /* SnipManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; 36 | 326AA0B71A7D116E00507232 /* DemoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 326AA0B61A7D116E00507232 /* DemoViewController.m */; }; 37 | 32E071C61A7C6A5A0094D5DE /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 32E071C51A7C6A5A0094D5DE /* AppDelegate.m */; }; 38 | 32E071C81A7C6A5A0094D5DE /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 32E071C71A7C6A5A0094D5DE /* main.m */; }; 39 | 32E071CA1A7C6A5A0094D5DE /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 32E071C91A7C6A5A0094D5DE /* Images.xcassets */; }; 40 | 32E071CD1A7C6A5A0094D5DE /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 32E071CB1A7C6A5A0094D5DE /* MainMenu.xib */; }; 41 | 32E071D91A7C6A5A0094D5DE /* SnipTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 32E071D81A7C6A5A0094D5DE /* SnipTests.m */; }; 42 | D29A35711A8398BD00DD41BC /* app.icns in Resources */ = {isa = PBXBuildFile; fileRef = D29A35701A8398BD00DD41BC /* app.icns */; }; 43 | /* End PBXBuildFile section */ 44 | 45 | /* Begin PBXContainerItemProxy section */ 46 | 32E071D31A7C6A5A0094D5DE /* PBXContainerItemProxy */ = { 47 | isa = PBXContainerItemProxy; 48 | containerPortal = 32E071B71A7C6A5A0094D5DE /* Project object */; 49 | proxyType = 1; 50 | remoteGlobalIDString = 32E071BE1A7C6A5A0094D5DE; 51 | remoteInfo = Snip; 52 | }; 53 | /* End PBXContainerItemProxy section */ 54 | 55 | /* Begin PBXFileReference section */ 56 | 06C042B71BBB77AB00B3B473 /* DrawPathInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DrawPathInfo.h; sourceTree = ""; }; 57 | 06C042B81BBB77AB00B3B473 /* DrawPathInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DrawPathInfo.m; sourceTree = ""; }; 58 | 06C042B91BBB77AB00B3B473 /* DrawPathView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DrawPathView.h; sourceTree = ""; }; 59 | 06C042BA1BBB77AB00B3B473 /* DrawPathView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DrawPathView.m; sourceTree = ""; }; 60 | 06C042BB1BBB77AB00B3B473 /* ImageButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageButton.h; sourceTree = ""; }; 61 | 06C042BC1BBB77AB00B3B473 /* ImageButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ImageButton.m; sourceTree = ""; }; 62 | 06C042BD1BBB77AB00B3B473 /* MouseEventProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MouseEventProtocol.h; sourceTree = ""; }; 63 | 06C042BE1BBB77AB00B3B473 /* NSColor+Helper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSColor+Helper.h"; sourceTree = ""; }; 64 | 06C042BF1BBB77AB00B3B473 /* NSColor+Helper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSColor+Helper.m"; sourceTree = ""; }; 65 | 06C042C01BBB77AB00B3B473 /* SimpleLabelView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SimpleLabelView.h; sourceTree = ""; }; 66 | 06C042C11BBB77AB00B3B473 /* SimpleLabelView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SimpleLabelView.m; sourceTree = ""; }; 67 | 06C042C21BBB77AB00B3B473 /* SnipManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SnipManager.m; sourceTree = ""; }; 68 | 06C042C31BBB77AB00B3B473 /* SnipUtil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SnipUtil.h; sourceTree = ""; }; 69 | 06C042C41BBB77AB00B3B473 /* SnipUtil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SnipUtil.m; sourceTree = ""; }; 70 | 06C042C51BBB77AB00B3B473 /* SnipView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SnipView.h; sourceTree = ""; }; 71 | 06C042C61BBB77AB00B3B473 /* SnipView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SnipView.m; sourceTree = ""; }; 72 | 06C042C71BBB77AB00B3B473 /* SnipWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SnipWindow.h; sourceTree = ""; }; 73 | 06C042C81BBB77AB00B3B473 /* SnipWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SnipWindow.m; sourceTree = ""; }; 74 | 06C042C91BBB77AB00B3B473 /* SnipWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SnipWindowController.h; sourceTree = ""; }; 75 | 06C042CA1BBB77AB00B3B473 /* SnipWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SnipWindowController.m; sourceTree = ""; }; 76 | 06C042CB1BBB77AB00B3B473 /* SnipWindowController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = SnipWindowController.xib; sourceTree = ""; }; 77 | 06C042CC1BBB77AB00B3B473 /* ToolContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ToolContainer.h; sourceTree = ""; }; 78 | 06C042CD1BBB77AB00B3B473 /* ToolContainer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ToolContainer.m; sourceTree = ""; }; 79 | 06C0436A1BBBBF1200B3B473 /* Images.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Images.bundle; sourceTree = ""; }; 80 | 06EC06A01BBABE1A00D3384D /* SnipManager.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = SnipManager.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 81 | 06EC06A21BBABE1A00D3384D /* SnipManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SnipManager.h; sourceTree = ""; }; 82 | 06EC06A41BBABE1A00D3384D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 83 | 326AA0B51A7D116E00507232 /* DemoViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoViewController.h; sourceTree = ""; }; 84 | 326AA0B61A7D116E00507232 /* DemoViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DemoViewController.m; sourceTree = ""; }; 85 | 32E071BF1A7C6A5A0094D5DE /* Snip.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Snip.app; sourceTree = BUILT_PRODUCTS_DIR; }; 86 | 32E071C31A7C6A5A0094D5DE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 87 | 32E071C41A7C6A5A0094D5DE /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 88 | 32E071C51A7C6A5A0094D5DE /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 89 | 32E071C71A7C6A5A0094D5DE /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 90 | 32E071C91A7C6A5A0094D5DE /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 91 | 32E071CC1A7C6A5A0094D5DE /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 92 | 32E071D21A7C6A5A0094D5DE /* SnipTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SnipTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 93 | 32E071D71A7C6A5A0094D5DE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 94 | 32E071D81A7C6A5A0094D5DE /* SnipTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SnipTests.m; sourceTree = ""; }; 95 | D29A35701A8398BD00DD41BC /* app.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; path = app.icns; sourceTree = ""; }; 96 | /* End PBXFileReference section */ 97 | 98 | /* Begin PBXFrameworksBuildPhase section */ 99 | 06EC069C1BBABE1A00D3384D /* Frameworks */ = { 100 | isa = PBXFrameworksBuildPhase; 101 | buildActionMask = 2147483647; 102 | files = ( 103 | ); 104 | runOnlyForDeploymentPostprocessing = 0; 105 | }; 106 | 32E071BC1A7C6A5A0094D5DE /* Frameworks */ = { 107 | isa = PBXFrameworksBuildPhase; 108 | buildActionMask = 2147483647; 109 | files = ( 110 | 06C043551BBBBA5400B3B473 /* SnipManager.framework in Frameworks */, 111 | ); 112 | runOnlyForDeploymentPostprocessing = 0; 113 | }; 114 | 32E071CF1A7C6A5A0094D5DE /* Frameworks */ = { 115 | isa = PBXFrameworksBuildPhase; 116 | buildActionMask = 2147483647; 117 | files = ( 118 | ); 119 | runOnlyForDeploymentPostprocessing = 0; 120 | }; 121 | /* End PBXFrameworksBuildPhase section */ 122 | 123 | /* Begin PBXGroup section */ 124 | 06C043691BBBBF1200B3B473 /* Resource */ = { 125 | isa = PBXGroup; 126 | children = ( 127 | 06C0436A1BBBBF1200B3B473 /* Images.bundle */, 128 | ); 129 | path = Resource; 130 | sourceTree = ""; 131 | }; 132 | 06EC06A11BBABE1A00D3384D /* SnipManager */ = { 133 | isa = PBXGroup; 134 | children = ( 135 | 06C043691BBBBF1200B3B473 /* Resource */, 136 | 06EC06A21BBABE1A00D3384D /* SnipManager.h */, 137 | 06C042C21BBB77AB00B3B473 /* SnipManager.m */, 138 | 06C042B71BBB77AB00B3B473 /* DrawPathInfo.h */, 139 | 06C042B81BBB77AB00B3B473 /* DrawPathInfo.m */, 140 | 06C042B91BBB77AB00B3B473 /* DrawPathView.h */, 141 | 06C042BA1BBB77AB00B3B473 /* DrawPathView.m */, 142 | 06C042BB1BBB77AB00B3B473 /* ImageButton.h */, 143 | 06C042BC1BBB77AB00B3B473 /* ImageButton.m */, 144 | 06C042BD1BBB77AB00B3B473 /* MouseEventProtocol.h */, 145 | 06C042BE1BBB77AB00B3B473 /* NSColor+Helper.h */, 146 | 06C042BF1BBB77AB00B3B473 /* NSColor+Helper.m */, 147 | 06C042C01BBB77AB00B3B473 /* SimpleLabelView.h */, 148 | 06C042C11BBB77AB00B3B473 /* SimpleLabelView.m */, 149 | 06C042C31BBB77AB00B3B473 /* SnipUtil.h */, 150 | 06C042C41BBB77AB00B3B473 /* SnipUtil.m */, 151 | 06C042C51BBB77AB00B3B473 /* SnipView.h */, 152 | 06C042C61BBB77AB00B3B473 /* SnipView.m */, 153 | 06C042C71BBB77AB00B3B473 /* SnipWindow.h */, 154 | 06C042C81BBB77AB00B3B473 /* SnipWindow.m */, 155 | 06C042C91BBB77AB00B3B473 /* SnipWindowController.h */, 156 | 06C042CA1BBB77AB00B3B473 /* SnipWindowController.m */, 157 | 06C042CB1BBB77AB00B3B473 /* SnipWindowController.xib */, 158 | 06C042CC1BBB77AB00B3B473 /* ToolContainer.h */, 159 | 06C042CD1BBB77AB00B3B473 /* ToolContainer.m */, 160 | 06EC06A41BBABE1A00D3384D /* Info.plist */, 161 | ); 162 | path = SnipManager; 163 | sourceTree = ""; 164 | }; 165 | 32E071B61A7C6A5A0094D5DE = { 166 | isa = PBXGroup; 167 | children = ( 168 | 32E071C11A7C6A5A0094D5DE /* Snip */, 169 | 32E071D51A7C6A5A0094D5DE /* SnipTests */, 170 | 06EC06A11BBABE1A00D3384D /* SnipManager */, 171 | 32E071C01A7C6A5A0094D5DE /* Products */, 172 | ); 173 | sourceTree = ""; 174 | }; 175 | 32E071C01A7C6A5A0094D5DE /* Products */ = { 176 | isa = PBXGroup; 177 | children = ( 178 | 32E071BF1A7C6A5A0094D5DE /* Snip.app */, 179 | 32E071D21A7C6A5A0094D5DE /* SnipTests.xctest */, 180 | 06EC06A01BBABE1A00D3384D /* SnipManager.framework */, 181 | ); 182 | name = Products; 183 | sourceTree = ""; 184 | }; 185 | 32E071C11A7C6A5A0094D5DE /* Snip */ = { 186 | isa = PBXGroup; 187 | children = ( 188 | D29A35701A8398BD00DD41BC /* app.icns */, 189 | 32E071C41A7C6A5A0094D5DE /* AppDelegate.h */, 190 | 32E071C51A7C6A5A0094D5DE /* AppDelegate.m */, 191 | 32E071C91A7C6A5A0094D5DE /* Images.xcassets */, 192 | 32E071CB1A7C6A5A0094D5DE /* MainMenu.xib */, 193 | 32E071C21A7C6A5A0094D5DE /* Supporting Files */, 194 | 326AA0B51A7D116E00507232 /* DemoViewController.h */, 195 | 326AA0B61A7D116E00507232 /* DemoViewController.m */, 196 | ); 197 | path = Snip; 198 | sourceTree = ""; 199 | }; 200 | 32E071C21A7C6A5A0094D5DE /* Supporting Files */ = { 201 | isa = PBXGroup; 202 | children = ( 203 | 32E071C31A7C6A5A0094D5DE /* Info.plist */, 204 | 32E071C71A7C6A5A0094D5DE /* main.m */, 205 | ); 206 | name = "Supporting Files"; 207 | sourceTree = ""; 208 | }; 209 | 32E071D51A7C6A5A0094D5DE /* SnipTests */ = { 210 | isa = PBXGroup; 211 | children = ( 212 | 32E071D81A7C6A5A0094D5DE /* SnipTests.m */, 213 | 32E071D61A7C6A5A0094D5DE /* Supporting Files */, 214 | ); 215 | path = SnipTests; 216 | sourceTree = ""; 217 | }; 218 | 32E071D61A7C6A5A0094D5DE /* Supporting Files */ = { 219 | isa = PBXGroup; 220 | children = ( 221 | 32E071D71A7C6A5A0094D5DE /* Info.plist */, 222 | ); 223 | name = "Supporting Files"; 224 | sourceTree = ""; 225 | }; 226 | /* End PBXGroup section */ 227 | 228 | /* Begin PBXHeadersBuildPhase section */ 229 | 06EC069D1BBABE1A00D3384D /* Headers */ = { 230 | isa = PBXHeadersBuildPhase; 231 | buildActionMask = 2147483647; 232 | files = ( 233 | 06C042E01BBB77AB00B3B473 /* SnipWindowController.h in Headers */, 234 | 06C042DA1BBB77AB00B3B473 /* SnipUtil.h in Headers */, 235 | 06C042D41BBB77AB00B3B473 /* MouseEventProtocol.h in Headers */, 236 | 06EC06A31BBABE1A00D3384D /* SnipManager.h in Headers */, 237 | 06C042CE1BBB77AB00B3B473 /* DrawPathInfo.h in Headers */, 238 | 06C042DE1BBB77AB00B3B473 /* SnipWindow.h in Headers */, 239 | 06C042D71BBB77AB00B3B473 /* SimpleLabelView.h in Headers */, 240 | 06C042DC1BBB77AB00B3B473 /* SnipView.h in Headers */, 241 | 06C042D21BBB77AB00B3B473 /* ImageButton.h in Headers */, 242 | 06C042D01BBB77AB00B3B473 /* DrawPathView.h in Headers */, 243 | 06C042E31BBB77AB00B3B473 /* ToolContainer.h in Headers */, 244 | 06C042D51BBB77AB00B3B473 /* NSColor+Helper.h in Headers */, 245 | ); 246 | runOnlyForDeploymentPostprocessing = 0; 247 | }; 248 | /* End PBXHeadersBuildPhase section */ 249 | 250 | /* Begin PBXNativeTarget section */ 251 | 06EC069F1BBABE1A00D3384D /* SnipManager */ = { 252 | isa = PBXNativeTarget; 253 | buildConfigurationList = 06EC06AB1BBABE1A00D3384D /* Build configuration list for PBXNativeTarget "SnipManager" */; 254 | buildPhases = ( 255 | 06EC069B1BBABE1A00D3384D /* Sources */, 256 | 06EC069C1BBABE1A00D3384D /* Frameworks */, 257 | 06EC069D1BBABE1A00D3384D /* Headers */, 258 | 06EC069E1BBABE1A00D3384D /* Resources */, 259 | ); 260 | buildRules = ( 261 | ); 262 | dependencies = ( 263 | ); 264 | name = SnipManager; 265 | productName = SnipManager; 266 | productReference = 06EC06A01BBABE1A00D3384D /* SnipManager.framework */; 267 | productType = "com.apple.product-type.framework"; 268 | }; 269 | 32E071BE1A7C6A5A0094D5DE /* Snip */ = { 270 | isa = PBXNativeTarget; 271 | buildConfigurationList = 32E071DC1A7C6A5A0094D5DE /* Build configuration list for PBXNativeTarget "Snip" */; 272 | buildPhases = ( 273 | 32E071BB1A7C6A5A0094D5DE /* Sources */, 274 | 32E071BC1A7C6A5A0094D5DE /* Frameworks */, 275 | 32E071BD1A7C6A5A0094D5DE /* Resources */, 276 | ); 277 | buildRules = ( 278 | ); 279 | dependencies = ( 280 | ); 281 | name = Snip; 282 | productName = Snip; 283 | productReference = 32E071BF1A7C6A5A0094D5DE /* Snip.app */; 284 | productType = "com.apple.product-type.application"; 285 | }; 286 | 32E071D11A7C6A5A0094D5DE /* SnipTests */ = { 287 | isa = PBXNativeTarget; 288 | buildConfigurationList = 32E071DF1A7C6A5A0094D5DE /* Build configuration list for PBXNativeTarget "SnipTests" */; 289 | buildPhases = ( 290 | 32E071CE1A7C6A5A0094D5DE /* Sources */, 291 | 32E071CF1A7C6A5A0094D5DE /* Frameworks */, 292 | 32E071D01A7C6A5A0094D5DE /* Resources */, 293 | ); 294 | buildRules = ( 295 | ); 296 | dependencies = ( 297 | 32E071D41A7C6A5A0094D5DE /* PBXTargetDependency */, 298 | ); 299 | name = SnipTests; 300 | productName = SnipTests; 301 | productReference = 32E071D21A7C6A5A0094D5DE /* SnipTests.xctest */; 302 | productType = "com.apple.product-type.bundle.unit-test"; 303 | }; 304 | /* End PBXNativeTarget section */ 305 | 306 | /* Begin PBXProject section */ 307 | 32E071B71A7C6A5A0094D5DE /* Project object */ = { 308 | isa = PBXProject; 309 | attributes = { 310 | LastUpgradeCheck = 0700; 311 | ORGANIZATIONNAME = isee15; 312 | TargetAttributes = { 313 | 06EC069F1BBABE1A00D3384D = { 314 | CreatedOnToolsVersion = 7.0; 315 | }; 316 | 32E071BE1A7C6A5A0094D5DE = { 317 | CreatedOnToolsVersion = 6.1.1; 318 | }; 319 | 32E071D11A7C6A5A0094D5DE = { 320 | CreatedOnToolsVersion = 6.1.1; 321 | TestTargetID = 32E071BE1A7C6A5A0094D5DE; 322 | }; 323 | }; 324 | }; 325 | buildConfigurationList = 32E071BA1A7C6A5A0094D5DE /* Build configuration list for PBXProject "Snip" */; 326 | compatibilityVersion = "Xcode 3.2"; 327 | developmentRegion = English; 328 | hasScannedForEncodings = 0; 329 | knownRegions = ( 330 | en, 331 | Base, 332 | ); 333 | mainGroup = 32E071B61A7C6A5A0094D5DE; 334 | productRefGroup = 32E071C01A7C6A5A0094D5DE /* Products */; 335 | projectDirPath = ""; 336 | projectRoot = ""; 337 | targets = ( 338 | 32E071BE1A7C6A5A0094D5DE /* Snip */, 339 | 32E071D11A7C6A5A0094D5DE /* SnipTests */, 340 | 06EC069F1BBABE1A00D3384D /* SnipManager */, 341 | ); 342 | }; 343 | /* End PBXProject section */ 344 | 345 | /* Begin PBXResourcesBuildPhase section */ 346 | 06EC069E1BBABE1A00D3384D /* Resources */ = { 347 | isa = PBXResourcesBuildPhase; 348 | buildActionMask = 2147483647; 349 | files = ( 350 | 06C042E21BBB77AB00B3B473 /* SnipWindowController.xib in Resources */, 351 | 06C0436B1BBBBF1200B3B473 /* Images.bundle in Resources */, 352 | ); 353 | runOnlyForDeploymentPostprocessing = 0; 354 | }; 355 | 32E071BD1A7C6A5A0094D5DE /* Resources */ = { 356 | isa = PBXResourcesBuildPhase; 357 | buildActionMask = 2147483647; 358 | files = ( 359 | 32E071CA1A7C6A5A0094D5DE /* Images.xcassets in Resources */, 360 | 32E071CD1A7C6A5A0094D5DE /* MainMenu.xib in Resources */, 361 | D29A35711A8398BD00DD41BC /* app.icns in Resources */, 362 | ); 363 | runOnlyForDeploymentPostprocessing = 0; 364 | }; 365 | 32E071D01A7C6A5A0094D5DE /* Resources */ = { 366 | isa = PBXResourcesBuildPhase; 367 | buildActionMask = 2147483647; 368 | files = ( 369 | ); 370 | runOnlyForDeploymentPostprocessing = 0; 371 | }; 372 | /* End PBXResourcesBuildPhase section */ 373 | 374 | /* Begin PBXSourcesBuildPhase section */ 375 | 06EC069B1BBABE1A00D3384D /* Sources */ = { 376 | isa = PBXSourcesBuildPhase; 377 | buildActionMask = 2147483647; 378 | files = ( 379 | 06C042D31BBB77AB00B3B473 /* ImageButton.m in Sources */, 380 | 06C042E11BBB77AB00B3B473 /* SnipWindowController.m in Sources */, 381 | 06C042CF1BBB77AB00B3B473 /* DrawPathInfo.m in Sources */, 382 | 06C042E41BBB77AB00B3B473 /* ToolContainer.m in Sources */, 383 | 06C042DD1BBB77AB00B3B473 /* SnipView.m in Sources */, 384 | 06C042DB1BBB77AB00B3B473 /* SnipUtil.m in Sources */, 385 | 06C042DF1BBB77AB00B3B473 /* SnipWindow.m in Sources */, 386 | 06C042D61BBB77AB00B3B473 /* NSColor+Helper.m in Sources */, 387 | 06C042D11BBB77AB00B3B473 /* DrawPathView.m in Sources */, 388 | 06C042D81BBB77AB00B3B473 /* SimpleLabelView.m in Sources */, 389 | 06C042D91BBB77AB00B3B473 /* SnipManager.m in Sources */, 390 | ); 391 | runOnlyForDeploymentPostprocessing = 0; 392 | }; 393 | 32E071BB1A7C6A5A0094D5DE /* Sources */ = { 394 | isa = PBXSourcesBuildPhase; 395 | buildActionMask = 2147483647; 396 | files = ( 397 | 326AA0B71A7D116E00507232 /* DemoViewController.m in Sources */, 398 | 32E071C81A7C6A5A0094D5DE /* main.m in Sources */, 399 | 32E071C61A7C6A5A0094D5DE /* AppDelegate.m in Sources */, 400 | ); 401 | runOnlyForDeploymentPostprocessing = 0; 402 | }; 403 | 32E071CE1A7C6A5A0094D5DE /* Sources */ = { 404 | isa = PBXSourcesBuildPhase; 405 | buildActionMask = 2147483647; 406 | files = ( 407 | 32E071D91A7C6A5A0094D5DE /* SnipTests.m in Sources */, 408 | ); 409 | runOnlyForDeploymentPostprocessing = 0; 410 | }; 411 | /* End PBXSourcesBuildPhase section */ 412 | 413 | /* Begin PBXTargetDependency section */ 414 | 32E071D41A7C6A5A0094D5DE /* PBXTargetDependency */ = { 415 | isa = PBXTargetDependency; 416 | target = 32E071BE1A7C6A5A0094D5DE /* Snip */; 417 | targetProxy = 32E071D31A7C6A5A0094D5DE /* PBXContainerItemProxy */; 418 | }; 419 | /* End PBXTargetDependency section */ 420 | 421 | /* Begin PBXVariantGroup section */ 422 | 32E071CB1A7C6A5A0094D5DE /* MainMenu.xib */ = { 423 | isa = PBXVariantGroup; 424 | children = ( 425 | 32E071CC1A7C6A5A0094D5DE /* Base */, 426 | ); 427 | name = MainMenu.xib; 428 | sourceTree = ""; 429 | }; 430 | /* End PBXVariantGroup section */ 431 | 432 | /* Begin XCBuildConfiguration section */ 433 | 06EC06A91BBABE1A00D3384D /* Debug */ = { 434 | isa = XCBuildConfiguration; 435 | buildSettings = { 436 | COMBINE_HIDPI_IMAGES = YES; 437 | CURRENT_PROJECT_VERSION = 1; 438 | DEBUG_INFORMATION_FORMAT = dwarf; 439 | DEFINES_MODULE = YES; 440 | DYLIB_COMPATIBILITY_VERSION = 1; 441 | DYLIB_CURRENT_VERSION = 1; 442 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 443 | ENABLE_TESTABILITY = YES; 444 | FRAMEWORK_VERSION = A; 445 | GCC_NO_COMMON_BLOCKS = YES; 446 | INFOPLIST_FILE = SnipManager/Info.plist; 447 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 448 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 449 | MACOSX_DEPLOYMENT_TARGET = 10.11; 450 | PRODUCT_BUNDLE_IDENTIFIER = com.hj.SnipManager; 451 | PRODUCT_NAME = "$(TARGET_NAME)"; 452 | SKIP_INSTALL = YES; 453 | VERSIONING_SYSTEM = "apple-generic"; 454 | VERSION_INFO_PREFIX = ""; 455 | }; 456 | name = Debug; 457 | }; 458 | 06EC06AA1BBABE1A00D3384D /* Release */ = { 459 | isa = XCBuildConfiguration; 460 | buildSettings = { 461 | COMBINE_HIDPI_IMAGES = YES; 462 | COPY_PHASE_STRIP = NO; 463 | CURRENT_PROJECT_VERSION = 1; 464 | DEFINES_MODULE = YES; 465 | DYLIB_COMPATIBILITY_VERSION = 1; 466 | DYLIB_CURRENT_VERSION = 1; 467 | DYLIB_INSTALL_NAME_BASE = "@rpath"; 468 | FRAMEWORK_VERSION = A; 469 | GCC_NO_COMMON_BLOCKS = YES; 470 | INFOPLIST_FILE = SnipManager/Info.plist; 471 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; 472 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks"; 473 | MACOSX_DEPLOYMENT_TARGET = 10.11; 474 | PRODUCT_BUNDLE_IDENTIFIER = com.hj.SnipManager; 475 | PRODUCT_NAME = "$(TARGET_NAME)"; 476 | SKIP_INSTALL = YES; 477 | VERSIONING_SYSTEM = "apple-generic"; 478 | VERSION_INFO_PREFIX = ""; 479 | }; 480 | name = Release; 481 | }; 482 | 32E071DA1A7C6A5A0094D5DE /* Debug */ = { 483 | isa = XCBuildConfiguration; 484 | buildSettings = { 485 | ALWAYS_SEARCH_USER_PATHS = NO; 486 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 487 | CLANG_CXX_LIBRARY = "libc++"; 488 | CLANG_ENABLE_MODULES = YES; 489 | CLANG_ENABLE_OBJC_ARC = YES; 490 | CLANG_WARN_BOOL_CONVERSION = YES; 491 | CLANG_WARN_CONSTANT_CONVERSION = YES; 492 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 493 | CLANG_WARN_EMPTY_BODY = YES; 494 | CLANG_WARN_ENUM_CONVERSION = YES; 495 | CLANG_WARN_INT_CONVERSION = YES; 496 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 497 | CLANG_WARN_UNREACHABLE_CODE = YES; 498 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 499 | CODE_SIGN_IDENTITY = "-"; 500 | COPY_PHASE_STRIP = NO; 501 | ENABLE_STRICT_OBJC_MSGSEND = YES; 502 | ENABLE_TESTABILITY = YES; 503 | GCC_C_LANGUAGE_STANDARD = gnu99; 504 | GCC_DYNAMIC_NO_PIC = NO; 505 | GCC_OPTIMIZATION_LEVEL = 0; 506 | GCC_PREPROCESSOR_DEFINITIONS = ( 507 | "DEBUG=1", 508 | "$(inherited)", 509 | ); 510 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 511 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 512 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 513 | GCC_WARN_UNDECLARED_SELECTOR = YES; 514 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 515 | GCC_WARN_UNUSED_FUNCTION = YES; 516 | GCC_WARN_UNUSED_VARIABLE = YES; 517 | MACOSX_DEPLOYMENT_TARGET = 10.10; 518 | MTL_ENABLE_DEBUG_INFO = YES; 519 | ONLY_ACTIVE_ARCH = YES; 520 | SDKROOT = macosx; 521 | }; 522 | name = Debug; 523 | }; 524 | 32E071DB1A7C6A5A0094D5DE /* Release */ = { 525 | isa = XCBuildConfiguration; 526 | buildSettings = { 527 | ALWAYS_SEARCH_USER_PATHS = NO; 528 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 529 | CLANG_CXX_LIBRARY = "libc++"; 530 | CLANG_ENABLE_MODULES = YES; 531 | CLANG_ENABLE_OBJC_ARC = YES; 532 | CLANG_WARN_BOOL_CONVERSION = YES; 533 | CLANG_WARN_CONSTANT_CONVERSION = YES; 534 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 535 | CLANG_WARN_EMPTY_BODY = YES; 536 | CLANG_WARN_ENUM_CONVERSION = YES; 537 | CLANG_WARN_INT_CONVERSION = YES; 538 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 539 | CLANG_WARN_UNREACHABLE_CODE = YES; 540 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 541 | CODE_SIGN_IDENTITY = "-"; 542 | COPY_PHASE_STRIP = YES; 543 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 544 | ENABLE_NS_ASSERTIONS = NO; 545 | ENABLE_STRICT_OBJC_MSGSEND = YES; 546 | GCC_C_LANGUAGE_STANDARD = gnu99; 547 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 548 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 549 | GCC_WARN_UNDECLARED_SELECTOR = YES; 550 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 551 | GCC_WARN_UNUSED_FUNCTION = YES; 552 | GCC_WARN_UNUSED_VARIABLE = YES; 553 | MACOSX_DEPLOYMENT_TARGET = 10.10; 554 | MTL_ENABLE_DEBUG_INFO = NO; 555 | SDKROOT = macosx; 556 | }; 557 | name = Release; 558 | }; 559 | 32E071DD1A7C6A5A0094D5DE /* Debug */ = { 560 | isa = XCBuildConfiguration; 561 | buildSettings = { 562 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 563 | COMBINE_HIDPI_IMAGES = YES; 564 | INFOPLIST_FILE = Snip/Info.plist; 565 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 566 | PRODUCT_BUNDLE_IDENTIFIER = "cn.z.$(PRODUCT_NAME:rfc1034identifier)"; 567 | PRODUCT_NAME = "$(TARGET_NAME)"; 568 | }; 569 | name = Debug; 570 | }; 571 | 32E071DE1A7C6A5A0094D5DE /* Release */ = { 572 | isa = XCBuildConfiguration; 573 | buildSettings = { 574 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 575 | COMBINE_HIDPI_IMAGES = YES; 576 | INFOPLIST_FILE = Snip/Info.plist; 577 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; 578 | PRODUCT_BUNDLE_IDENTIFIER = "cn.z.$(PRODUCT_NAME:rfc1034identifier)"; 579 | PRODUCT_NAME = "$(TARGET_NAME)"; 580 | }; 581 | name = Release; 582 | }; 583 | 32E071E01A7C6A5A0094D5DE /* Debug */ = { 584 | isa = XCBuildConfiguration; 585 | buildSettings = { 586 | BUNDLE_LOADER = "$(TEST_HOST)"; 587 | COMBINE_HIDPI_IMAGES = YES; 588 | FRAMEWORK_SEARCH_PATHS = ( 589 | "$(DEVELOPER_FRAMEWORKS_DIR)", 590 | "$(inherited)", 591 | ); 592 | GCC_PREPROCESSOR_DEFINITIONS = ( 593 | "DEBUG=1", 594 | "$(inherited)", 595 | ); 596 | INFOPLIST_FILE = SnipTests/Info.plist; 597 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 598 | PRODUCT_BUNDLE_IDENTIFIER = "cn.z.$(PRODUCT_NAME:rfc1034identifier)"; 599 | PRODUCT_NAME = "$(TARGET_NAME)"; 600 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Snip.app/Contents/MacOS/Snip"; 601 | }; 602 | name = Debug; 603 | }; 604 | 32E071E11A7C6A5A0094D5DE /* Release */ = { 605 | isa = XCBuildConfiguration; 606 | buildSettings = { 607 | BUNDLE_LOADER = "$(TEST_HOST)"; 608 | COMBINE_HIDPI_IMAGES = YES; 609 | FRAMEWORK_SEARCH_PATHS = ( 610 | "$(DEVELOPER_FRAMEWORKS_DIR)", 611 | "$(inherited)", 612 | ); 613 | INFOPLIST_FILE = SnipTests/Info.plist; 614 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; 615 | PRODUCT_BUNDLE_IDENTIFIER = "cn.z.$(PRODUCT_NAME:rfc1034identifier)"; 616 | PRODUCT_NAME = "$(TARGET_NAME)"; 617 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Snip.app/Contents/MacOS/Snip"; 618 | }; 619 | name = Release; 620 | }; 621 | /* End XCBuildConfiguration section */ 622 | 623 | /* Begin XCConfigurationList section */ 624 | 06EC06AB1BBABE1A00D3384D /* Build configuration list for PBXNativeTarget "SnipManager" */ = { 625 | isa = XCConfigurationList; 626 | buildConfigurations = ( 627 | 06EC06A91BBABE1A00D3384D /* Debug */, 628 | 06EC06AA1BBABE1A00D3384D /* Release */, 629 | ); 630 | defaultConfigurationIsVisible = 0; 631 | defaultConfigurationName = Release; 632 | }; 633 | 32E071BA1A7C6A5A0094D5DE /* Build configuration list for PBXProject "Snip" */ = { 634 | isa = XCConfigurationList; 635 | buildConfigurations = ( 636 | 32E071DA1A7C6A5A0094D5DE /* Debug */, 637 | 32E071DB1A7C6A5A0094D5DE /* Release */, 638 | ); 639 | defaultConfigurationIsVisible = 0; 640 | defaultConfigurationName = Release; 641 | }; 642 | 32E071DC1A7C6A5A0094D5DE /* Build configuration list for PBXNativeTarget "Snip" */ = { 643 | isa = XCConfigurationList; 644 | buildConfigurations = ( 645 | 32E071DD1A7C6A5A0094D5DE /* Debug */, 646 | 32E071DE1A7C6A5A0094D5DE /* Release */, 647 | ); 648 | defaultConfigurationIsVisible = 0; 649 | defaultConfigurationName = Release; 650 | }; 651 | 32E071DF1A7C6A5A0094D5DE /* Build configuration list for PBXNativeTarget "SnipTests" */ = { 652 | isa = XCConfigurationList; 653 | buildConfigurations = ( 654 | 32E071E01A7C6A5A0094D5DE /* Debug */, 655 | 32E071E11A7C6A5A0094D5DE /* Release */, 656 | ); 657 | defaultConfigurationIsVisible = 0; 658 | defaultConfigurationName = Release; 659 | }; 660 | /* End XCConfigurationList section */ 661 | }; 662 | rootObject = 32E071B71A7C6A5A0094D5DE /* Project object */; 663 | } 664 | -------------------------------------------------------------------------------- /Snip.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Snip.xcodeproj/xcshareddata/xcschemes/SnipManager.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 45 | 46 | 52 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 70 | 71 | 72 | 73 | 75 | 76 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /Snip.xcodeproj/xcuserdata/liupeng.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 20 | 21 | 22 | 24 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Snip.xcodeproj/xcuserdata/liupeng.xcuserdatad/xcschemes/Snip.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 42 | 43 | 49 | 50 | 51 | 52 | 53 | 54 | 64 | 66 | 72 | 73 | 74 | 75 | 79 | 80 | 84 | 85 | 89 | 90 | 94 | 95 | 96 | 97 | 103 | 105 | 111 | 112 | 113 | 114 | 116 | 117 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /Snip/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // Snip 4 | // 5 | // Created by rz on 15/1/31. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : NSObject 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /Snip/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // Snip 4 | // 5 | // Created by rz on 15/1/31. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @property(weak) IBOutlet NSWindow *window; 14 | @end 15 | 16 | @implementation AppDelegate 17 | 18 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { 19 | // Insert code here to initialize your application 20 | } 21 | 22 | - (void)applicationWillTerminate:(NSNotification *)aNotification { 23 | // Insert code here to tear down your application 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Snip/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 | 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 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | Default 545 | 546 | 547 | 548 | 549 | 550 | 551 | Left to Right 552 | 553 | 554 | 555 | 556 | 557 | 558 | Right to Left 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | Default 570 | 571 | 572 | 573 | 574 | 575 | 576 | Left to Right 577 | 578 | 579 | 580 | 581 | 582 | 583 | Right to Left 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | -------------------------------------------------------------------------------- /Snip/DemoViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoViewController.h 3 | // Snip 4 | // 5 | // Created by rz on 15/1/31. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface DemoViewController : NSViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /Snip/DemoViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoViewController.m 3 | // Snip 4 | // 5 | // Created by rz on 15/1/31. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import "DemoViewController.h" 10 | #import "SnipManager.h" 11 | 12 | @interface DemoViewController () 13 | @property(weak) IBOutlet NSImageView *backImageView; 14 | 15 | @end 16 | 17 | @implementation DemoViewController 18 | 19 | - (void)awakeFromNib { 20 | // Do view setup here. 21 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onEndCapture:) name:kNotifyCaptureEnd object:nil]; 22 | } 23 | 24 | - (void)dealloc { 25 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 26 | } 27 | 28 | - (void)onEndCapture:(NSNotification *)notification { 29 | if (notification.userInfo[@"image"]) { 30 | self.backImageView.image = notification.userInfo[@"image"]; 31 | return; 32 | } 33 | // NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; 34 | // NSArray *classArray = [NSArray arrayWithObject:[NSImage class]]; 35 | // NSDictionary *options = [NSDictionary dictionary]; 36 | // BOOL ok = [pasteboard canReadObjectForClasses:classArray options:options]; 37 | // if(ok) { 38 | // NSArray *objectsToPaste = [pasteboard readObjectsForClasses:classArray options:options]; 39 | // NSImage *image = [objectsToPaste objectAtIndex:0]; 40 | // self.backImageView.image = image; 41 | // //[self.view.window setBackgroundColor:[NSColor colorWithPatternImage:image]]; 42 | // } else { 43 | // NSLog(@"Error: Clipboard doesn't seem to contain an image."); 44 | // } 45 | } 46 | 47 | - (IBAction)onStart:(id)sender { 48 | [[SnipManager sharedInstance] startCapture]; 49 | } 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /Snip/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 | } -------------------------------------------------------------------------------- /Snip/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIconFile 10 | app 11 | CFBundleIdentifier 12 | $(PRODUCT_BUNDLE_IDENTIFIER) 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年 isee15. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /Snip/app.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yihuds/SnipManager/7901c2785dbff4d64ff9695dd0cfa1c3670b22d9/Snip/app.icns -------------------------------------------------------------------------------- /Snip/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Snip 4 | // 5 | // Created by rz on 15/1/31. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char *argv[]) { 12 | return NSApplicationMain(argc, argv); 13 | } 14 | -------------------------------------------------------------------------------- /SnipManager/DrawPathInfo.h: -------------------------------------------------------------------------------- 1 | // 2 | // DrawPathInfo.h 3 | // Snip 4 | // 5 | // Created by isee15 on 15/2/4. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "SnipManager.h" 11 | 12 | @interface DrawPathInfo : NSObject 13 | 14 | @property NSPoint startPoint; 15 | @property NSPoint endPoint; 16 | @property DRAW_TYPE drawType; 17 | 18 | - (instancetype)initWith:(NSPoint)startPoint andEndPoint:(NSPoint)endPoint andType:(DRAW_TYPE)drawType; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /SnipManager/DrawPathInfo.m: -------------------------------------------------------------------------------- 1 | // 2 | // DrawPathInfo.m 3 | // Snip 4 | // 5 | // Created by isee15 on 15/2/4. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import "DrawPathInfo.h" 10 | 11 | @implementation DrawPathInfo 12 | 13 | - (instancetype)initWith:(NSPoint)startPoint andEndPoint:(NSPoint)endPoint andType:(DRAW_TYPE)drawType 14 | { 15 | if (self = [super init]) { 16 | _startPoint = startPoint; 17 | _endPoint = endPoint; 18 | _drawType = drawType; 19 | } 20 | return self; 21 | } 22 | @end 23 | -------------------------------------------------------------------------------- /SnipManager/DrawPathView.h: -------------------------------------------------------------------------------- 1 | // 2 | // DrawPathView.h 3 | // Snip 4 | // 5 | // Created by isee15 on 15/2/5. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "DrawPathInfo.h" 11 | 12 | @interface DrawPathView : NSView 13 | @property NSMutableArray *rectArray; 14 | @property DrawPathInfo *currentInfo; 15 | 16 | - (void)drawFinishCommentInRect:(NSRect)imageRect; 17 | @end 18 | -------------------------------------------------------------------------------- /SnipManager/DrawPathView.m: -------------------------------------------------------------------------------- 1 | // 2 | // DrawPathView.m 3 | // Snip 4 | // 5 | // Created by isee15 on 15/2/5. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import "DrawPathView.h" 10 | #import "SnipUtil.h" 11 | 12 | @implementation DrawPathView 13 | 14 | - (instancetype)init 15 | { 16 | if (self = [super init]) { 17 | _rectArray = [NSMutableArray array]; 18 | } 19 | return self; 20 | } 21 | 22 | - (NSRect)rectFromScreen:(NSRect)rect 23 | { 24 | NSRect rectRet = [self.window convertRectFromScreen:rect]; 25 | rectRet.origin.x -= self.frame.origin.x; 26 | rectRet.origin.y -= self.frame.origin.y; 27 | return rectRet; 28 | } 29 | 30 | - (void)drawRect:(NSRect)dirtyRect 31 | { 32 | [super drawRect:dirtyRect]; 33 | if ([SnipManager sharedInstance].captureState == CAPTURE_STATE_EDIT) { 34 | [self drawCommentInRect:self.bounds]; 35 | if (self.currentInfo) { 36 | [self drawShape:self.currentInfo inBackground:NO]; 37 | } 38 | } 39 | // Drawing code here. 40 | } 41 | 42 | - (void)drawCommentInRect:(NSRect)imageRect 43 | { 44 | NSBezierPath *path = [NSBezierPath bezierPathWithRect:imageRect]; 45 | [path addClip]; 46 | [[NSColor redColor] set]; 47 | for (DrawPathInfo *info in self.rectArray) { 48 | [self drawShape:info inBackground:NO]; 49 | } 50 | } 51 | 52 | - (void)drawFinishCommentInRect:(NSRect)imageRect 53 | { 54 | NSBezierPath *path = [NSBezierPath bezierPathWithRect:imageRect]; 55 | [path addClip]; 56 | [[NSColor redColor] set]; 57 | for (DrawPathInfo *info in self.rectArray) { 58 | [self drawShape:info inBackground:YES]; 59 | } 60 | } 61 | 62 | - (void)drawShape:(DrawPathInfo *)info inBackground:(BOOL)bIn 63 | { 64 | NSRect rect = NSMakeRect(info.startPoint.x, info.startPoint.y, info.endPoint.x - info.startPoint.x, info.endPoint.y - info.startPoint.y); 65 | if (bIn) { 66 | rect = [self.window convertRectFromScreen:rect]; 67 | } 68 | else { 69 | rect = [self rectFromScreen:rect]; 70 | } 71 | NSBezierPath *rectPath = [NSBezierPath bezierPath]; 72 | [rectPath setLineWidth:4]; 73 | [rectPath setLineCapStyle:NSRoundLineCapStyle]; 74 | [rectPath setLineJoinStyle:NSRoundLineJoinStyle]; 75 | switch (info.drawType) { 76 | case DRAW_TYPE_RECT: 77 | rect = [SnipUtil uniformRect:rect]; 78 | if (rect.size.width * rect.size.width < 1e-2) return; 79 | [rectPath appendBezierPathWithRect:rect]; 80 | [rectPath stroke]; 81 | break; 82 | case DRAW_TYPE_ELLIPSE: 83 | rect = [SnipUtil uniformRect:rect]; 84 | if (rect.size.width * rect.size.width < 1e-2) return; 85 | [rectPath appendBezierPathWithOvalInRect:rect]; 86 | [rectPath stroke]; 87 | break; 88 | case DRAW_TYPE_ARROW: { 89 | // arrow 90 | CGFloat x0 = rect.origin.x; 91 | CGFloat y0 = rect.origin.y; 92 | CGFloat x1 = x0 + rect.size.width; 93 | CGFloat y1 = y0 + rect.size.height; 94 | 95 | [rectPath moveToPoint:CGPointZero]; 96 | CGFloat ex1 = sqrt((x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0)); 97 | if (abs(rect.size.width) < 5 && abs(rect.size.height) < 5) return; 98 | [rectPath lineToPoint:NSMakePoint(ex1, 0)]; 99 | [rectPath lineToPoint:NSMakePoint(ex1 - 8, 5)]; 100 | [rectPath lineToPoint:NSMakePoint(ex1 - 2, 0)]; 101 | [rectPath lineToPoint:NSMakePoint(ex1 - 8, -5)]; 102 | [rectPath lineToPoint:NSMakePoint(ex1, 0)]; 103 | [rectPath closePath]; 104 | 105 | NSAffineTransform *af = [NSAffineTransform transform]; 106 | [af translateXBy:x0 yBy:y0]; 107 | [af rotateByRadians:atan2(y1 - y0, x1 - x0)]; 108 | [rectPath transformUsingAffineTransform:af]; 109 | [rectPath fill]; 110 | [rectPath stroke]; 111 | } 112 | break; 113 | } 114 | } 115 | 116 | @end 117 | -------------------------------------------------------------------------------- /SnipManager/ImageButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // ImageButton.h 3 | // Snip 4 | // 5 | // Created by isee15 on 15/2/5. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ImageButton : NSImageView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /SnipManager/ImageButton.m: -------------------------------------------------------------------------------- 1 | // 2 | // ImageButton.m 3 | // Snip 4 | // 5 | // Created by isee15 on 15/2/5. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import "ImageButton.h" 10 | 11 | @implementation ImageButton 12 | 13 | - (void)drawRect:(NSRect)dirtyRect 14 | { 15 | [super drawRect:dirtyRect]; 16 | 17 | // Drawing code here. 18 | } 19 | 20 | - (void)mouseDown:(NSEvent *)theEvent 21 | { 22 | [NSApp sendAction:self.action 23 | to:self.target 24 | from:self]; 25 | } 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /SnipManager/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 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 isee15. All rights reserved. 25 | NSPrincipalClass 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /SnipManager/MouseEventProtocol.h: -------------------------------------------------------------------------------- 1 | // 2 | // MouseEventProtocol.h 3 | // Snip 4 | // 5 | // Created by isee15 on 15/2/5. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol MouseEventProtocol 12 | 13 | - (void)mouseDown:(NSEvent *)theEvent; 14 | 15 | - (void)mouseUp:(NSEvent *)theEvent; 16 | 17 | - (void)mouseDragged:(NSEvent *)theEvent; 18 | 19 | - (void)mouseMoved:(NSEvent *)theEvent; 20 | @end 21 | -------------------------------------------------------------------------------- /SnipManager/NSColor+Helper.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSColor+Helper.h 3 | // Snip 4 | // 5 | // Created by isee15 on 15/2/5. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSColor (Helper) 12 | + (NSColor *)colorFromInt:(int)colorValue; 13 | + (NSColor*)colorWithHex:(NSString *)hexValue alpha:(CGFloat)alphaValue; 14 | @end 15 | -------------------------------------------------------------------------------- /SnipManager/NSColor+Helper.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSColor+Helper.m 3 | // Snip 4 | // 5 | // Created by isee15 on 15/2/5. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import "NSColor+Helper.h" 10 | 11 | @implementation NSColor (Helper) 12 | 13 | + (NSColor *)colorFromInt:(int)colorValue 14 | { 15 | float b = colorValue & 0xff; 16 | float g = (colorValue & 0xff00) >> 8; 17 | float r = (colorValue & 0xff0000) >> 16; 18 | return [NSColor colorWithRed:r / 255 green:g / 255 blue:b / 255 alpha:1]; 19 | } 20 | 21 | + (NSColor*)colorWithHex:(NSString *)hexValue alpha:(CGFloat)alphaValue 22 | { 23 | NSScanner *scanner = [NSScanner scannerWithString:hexValue]; 24 | unsigned hexNum; 25 | if (![scanner scanHexInt:&hexNum]){ 26 | return [NSColor blackColor]; 27 | } 28 | return [NSColor colorWithRed:((float)((hexNum & 0xFF0000) >> 16))/255.0 29 | green:((float)((hexNum & 0xFF00) >> 8))/255.0 30 | blue:((float)(hexNum & 0xFF))/255.0 alpha:alphaValue]; 31 | } 32 | @end 33 | -------------------------------------------------------------------------------- /SnipManager/Resource/Images.bundle/ScreenCapture_toolbar_arrow_effect.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yihuds/SnipManager/7901c2785dbff4d64ff9695dd0cfa1c3670b22d9/SnipManager/Resource/Images.bundle/ScreenCapture_toolbar_arrow_effect.tiff -------------------------------------------------------------------------------- /SnipManager/Resource/Images.bundle/ScreenCapture_toolbar_arrow_ineffect.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yihuds/SnipManager/7901c2785dbff4d64ff9695dd0cfa1c3670b22d9/SnipManager/Resource/Images.bundle/ScreenCapture_toolbar_arrow_ineffect.tiff -------------------------------------------------------------------------------- /SnipManager/Resource/Images.bundle/ScreenCapture_toolbar_cross_normal.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yihuds/SnipManager/7901c2785dbff4d64ff9695dd0cfa1c3670b22d9/SnipManager/Resource/Images.bundle/ScreenCapture_toolbar_cross_normal.tiff -------------------------------------------------------------------------------- /SnipManager/Resource/Images.bundle/ScreenCapture_toolbar_ellipse_effect.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yihuds/SnipManager/7901c2785dbff4d64ff9695dd0cfa1c3670b22d9/SnipManager/Resource/Images.bundle/ScreenCapture_toolbar_ellipse_effect.tiff -------------------------------------------------------------------------------- /SnipManager/Resource/Images.bundle/ScreenCapture_toolbar_ellipse_ineffect.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yihuds/SnipManager/7901c2785dbff4d64ff9695dd0cfa1c3670b22d9/SnipManager/Resource/Images.bundle/ScreenCapture_toolbar_ellipse_ineffect.tiff -------------------------------------------------------------------------------- /SnipManager/Resource/Images.bundle/ScreenCapture_toolbar_export.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yihuds/SnipManager/7901c2785dbff4d64ff9695dd0cfa1c3670b22d9/SnipManager/Resource/Images.bundle/ScreenCapture_toolbar_export.tiff -------------------------------------------------------------------------------- /SnipManager/Resource/Images.bundle/ScreenCapture_toolbar_rect_effect.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yihuds/SnipManager/7901c2785dbff4d64ff9695dd0cfa1c3670b22d9/SnipManager/Resource/Images.bundle/ScreenCapture_toolbar_rect_effect.tiff -------------------------------------------------------------------------------- /SnipManager/Resource/Images.bundle/ScreenCapture_toolbar_rect_ineffect.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yihuds/SnipManager/7901c2785dbff4d64ff9695dd0cfa1c3670b22d9/SnipManager/Resource/Images.bundle/ScreenCapture_toolbar_rect_ineffect.tiff -------------------------------------------------------------------------------- /SnipManager/Resource/Images.bundle/ScreenCapture_toolbar_tick_normal.tiff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yihuds/SnipManager/7901c2785dbff4d64ff9695dd0cfa1c3670b22d9/SnipManager/Resource/Images.bundle/ScreenCapture_toolbar_tick_normal.tiff -------------------------------------------------------------------------------- /SnipManager/SimpleLabelView.h: -------------------------------------------------------------------------------- 1 | // 2 | // FlatView.h 3 | // Snip 4 | // 5 | // Created by isee15 on 15/2/6. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface SimpleLabelView : NSView 12 | @property NSString *text; 13 | @end 14 | -------------------------------------------------------------------------------- /SnipManager/SimpleLabelView.m: -------------------------------------------------------------------------------- 1 | // 2 | // FlatView.m 3 | // Snip 4 | // 5 | // Created by isee15 on 15/2/6. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import "SimpleLabelView.h" 10 | 11 | @implementation SimpleLabelView 12 | 13 | - (void)drawRect:(NSRect)dirtyRect 14 | { 15 | [super drawRect:dirtyRect]; 16 | NSBezierPath *bgPath = [NSBezierPath bezierPathWithRoundedRect:self.bounds xRadius:6 yRadius:6]; 17 | [bgPath setClip]; 18 | [[NSColor colorWithCalibratedWhite:0.0 alpha:0.8f] setFill]; 19 | NSRectFill(self.bounds); 20 | if (self.text.length > 0) { 21 | NSDictionary *stringAttributes = @{NSForegroundColorAttributeName : [NSColor colorWithCalibratedWhite:1.0 alpha:1.0], 22 | NSFontAttributeName : [NSFont boldSystemFontOfSize:12.0]}; 23 | NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:self.text attributes:stringAttributes]; 24 | NSRect stringRect = [attrStr boundingRectWithSize:self.bounds.size options:(NSStringDrawingUsesFontLeading | NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin)]; 25 | 26 | [attrStr drawAtPoint:NSMakePoint((self.bounds.size.width - stringRect.size.width) / 2, (self.bounds.size.height - stringRect.size.height) / 2)]; 27 | } 28 | // Drawing code here. 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /SnipManager/SnipManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // SnipManager.h 3 | // Snip 4 | // 5 | // Created by rz on 15/1/31. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | typedef NS_ENUM(NSInteger, CAPTURE_STATE) 13 | { 14 | CAPTURE_STATE_IDLE, 15 | CAPTURE_STATE_HILIGHT, 16 | CAPTURE_STATE_FIRSTMOUSEDOWN, 17 | CAPTURE_STATE_READYADJUST, 18 | CAPTURE_STATE_ADJUST, 19 | CAPTURE_STATE_EDIT, 20 | CAPTURE_STATE_DONE, 21 | }; 22 | 23 | typedef NS_ENUM(int, DRAW_TYPE) 24 | { 25 | DRAW_TYPE_RECT, 26 | DRAW_TYPE_ELLIPSE, 27 | DRAW_TYPE_ARROW 28 | }; 29 | 30 | #define kNotifyCaptureEnd @"kNotifyCaptureEnd" 31 | #define kNotifyMouseLocationChange @"kNotifyMouseLocationChange" 32 | extern const double kBORDER_LINE_WIDTH; 33 | extern const int kBORDER_LINE_COLOR; 34 | extern const int kKEY_ESC_CODE; 35 | 36 | 37 | @interface SnipManager : NSObject 38 | 39 | @property NSMutableArray *windowControllerArray; 40 | 41 | @property NSMutableArray *arrayRect; 42 | 43 | @property CAPTURE_STATE captureState; 44 | 45 | @property DRAW_TYPE drawType; 46 | 47 | @property NSBundle *bundle; 48 | 49 | @property BOOL isWorking; 50 | 51 | + (instancetype)sharedInstance; 52 | 53 | - (void)endCapture:(NSImage *)image; 54 | 55 | - (void)startCapture; 56 | 57 | - (void)configExportPath:(NSString *)path; 58 | 59 | - (NSString* )getExportPath; 60 | 61 | - (NSImage *)getImageFromResource:(NSString *) imageName; 62 | @end 63 | -------------------------------------------------------------------------------- /SnipManager/SnipManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // SnipManager.m 3 | // Snip 4 | // 5 | // Created by rz on 15/1/31. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import "SnipManager.h" 10 | #import "SnipWindowController.h" 11 | #import "SnipView.h" 12 | #import "SnipWindow.h" 13 | 14 | const double kBORDER_LINE_WIDTH = 2.0; 15 | const int kBORDER_LINE_COLOR = 0x1191FE; 16 | const int kKEY_ESC_CODE = 53; 17 | 18 | @interface SnipManager () 19 | { 20 | NSString *exportPath; 21 | } 22 | @end 23 | 24 | @implementation SnipManager 25 | 26 | + (instancetype)sharedInstance 27 | { 28 | static SnipManager *sharedSingleton = nil; 29 | static dispatch_once_t onceToken; 30 | dispatch_once(&onceToken, ^(void) { 31 | sharedSingleton = [[self alloc] init]; 32 | sharedSingleton.windowControllerArray = [NSMutableArray array]; 33 | [[[NSWorkspace sharedWorkspace] notificationCenter] addObserver:sharedSingleton 34 | selector:@selector(screenChanged:) 35 | name:NSWorkspaceActiveSpaceDidChangeNotification 36 | object:[NSWorkspace sharedWorkspace]]; 37 | [[NSNotificationCenter defaultCenter] addObserver:sharedSingleton selector:@selector(screenChanged:) name:NSApplicationDidChangeScreenParametersNotification object:nil]; 38 | NSBundle *frameworkBundle = [NSBundle bundleForClass:self]; 39 | NSString *imagesBundlePath = [frameworkBundle pathForResource:@"Images" ofType:@"bundle"]; 40 | if (imagesBundlePath) 41 | { 42 | sharedSingleton.bundle = [NSBundle bundleWithPath:imagesBundlePath]; 43 | } 44 | }); 45 | return sharedSingleton; 46 | } 47 | 48 | - (void)dealloc 49 | { 50 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 51 | [[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self]; 52 | } 53 | 54 | - (void)screenChanged:(NSNotification *)notify 55 | { 56 | if (self.isWorking) { 57 | [self endCapture:nil]; 58 | } 59 | } 60 | 61 | - (void)clearController 62 | { 63 | if (_windowControllerArray) { 64 | [_windowControllerArray removeAllObjects]; 65 | } 66 | } 67 | 68 | - (void)startCapture 69 | { 70 | 71 | if (self.isWorking) return; 72 | self.isWorking = YES; 73 | self.arrayRect = [NSMutableArray array]; 74 | //CFArrayRef windowArray = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID); 75 | NSArray *windows = (__bridge NSArray *) CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly, kCGNullWindowID); 76 | NSUInteger count = [windows count]; 77 | for (NSUInteger i = 0; i < count; i++) { 78 | NSDictionary *windowDescriptionDictionary = windows[i]; 79 | // CGRect bounds; 80 | // CGRectMakeWithDictionaryRepresentation((__bridge CFDictionaryRef) windowDescriptionDictionary[(id) kCGWindowBounds], &bounds); 81 | //NSLog(@"------%@",NSStringFromRect(bounds)); 82 | [self.arrayRect addObject:windowDescriptionDictionary]; 83 | } 84 | //CFRelease(windowArray); 85 | 86 | for (NSScreen *screen in [NSScreen screens]) { 87 | // SnipWindowController *snipController = [[SnipWindowController alloc] initWithWindowNibName:@"SnipWindowController"]; 88 | SnipWindowController *snipController = [[SnipWindowController alloc] init]; 89 | SnipWindow *snipWindow = [[SnipWindow alloc] initWithContentRect:[screen frame] styleMask:NSNonactivatingPanelMask backing:NSBackingStoreBuffered defer:NO screen:screen]; 90 | snipController.window = snipWindow; 91 | SnipView *snipView = [[SnipView alloc] initWithFrame:NSMakeRect(0, 0, [screen frame].size.width, [screen frame].size.height)]; 92 | snipWindow.contentView = snipView; 93 | [self.windowControllerArray addObject:snipController]; 94 | self.captureState = CAPTURE_STATE_HILIGHT; 95 | [snipController startCaptureWithScreen:screen]; 96 | } 97 | } 98 | 99 | - (void)endCapture:(NSImage *)image 100 | { 101 | if (!self.isWorking) return; 102 | self.isWorking = NO; 103 | for (SnipWindowController *windowController in self.windowControllerArray) { 104 | [windowController.window orderOut:nil]; 105 | } 106 | [self clearController]; 107 | [[NSNotificationCenter defaultCenter] postNotificationName:kNotifyCaptureEnd object:nil userInfo:image == nil ? nil : @{@"image" : image}]; 108 | } 109 | 110 | - (void)configExportPath:(NSString *)path { 111 | exportPath = path; 112 | } 113 | 114 | - (NSString* )getExportPath { 115 | if (exportPath) { 116 | return [self checkSnipFolder:exportPath]; 117 | } 118 | exportPath = [NSSearchPathForDirectoriesInDomains(NSPicturesDirectory, NSUserDomainMask, YES) firstObject]; 119 | return [self checkSnipFolder:exportPath]; 120 | } 121 | 122 | - (NSString* )checkSnipFolder:(NSString* )rootPath { 123 | if (![[NSFileManager defaultManager] fileExistsAtPath:rootPath]) { 124 | [[NSFileManager defaultManager] createDirectoryAtPath:rootPath attributes:nil]; 125 | } 126 | NSString *path = [NSString stringWithFormat:@"%@/snip",rootPath]; 127 | if (![[NSFileManager defaultManager] fileExistsAtPath:path]) { 128 | [[NSFileManager defaultManager] createDirectoryAtPath:path attributes:nil]; 129 | } 130 | return path; 131 | } 132 | 133 | - (NSImage *)getImageFromResource:(NSString *) imageName { 134 | if (self.bundle) { 135 | NSString* s =[[self.bundle resourcePath] stringByAppendingPathComponent:imageName]; 136 | return [[NSImage alloc] initWithContentsOfFile:s]; 137 | } 138 | return nil; 139 | } 140 | @end 141 | -------------------------------------------------------------------------------- /SnipManager/SnipUtil.h: -------------------------------------------------------------------------------- 1 | // 2 | // SnipUtil.h 3 | // Snip 4 | // 5 | // Created by rz on 15/1/31. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "ImageButton.h" 12 | 13 | @interface SnipUtil : NSObject 14 | + (CGImageRef)screenShot:(NSScreen *)screen; 15 | 16 | + (BOOL)isPoint:(NSPoint)point inRect:(NSRect)rect; 17 | 18 | + (double)pointDistance:(NSPoint)p1 toPoint:(NSPoint)p2; 19 | 20 | + (NSRect)uniformRect:(NSRect)rect; 21 | 22 | + (NSRect)rectToZero:(NSRect)rect; 23 | 24 | + (NSRect)cgWindowRectToScreenRect:(CGRect)windowRect; 25 | 26 | + (ImageButton *)createButton:(NSImage *)image withAlternate:(NSImage *)alter; 27 | @end 28 | -------------------------------------------------------------------------------- /SnipManager/SnipUtil.m: -------------------------------------------------------------------------------- 1 | // 2 | // SnipUtil.m 3 | // Snip 4 | // 5 | // Created by rz on 15/1/31. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import "SnipUtil.h" 10 | 11 | @implementation SnipUtil 12 | + (CGImageRef)screenShot:(NSScreen *)screen 13 | { 14 | CFArrayRef windowsRef = CGWindowListCreate(kCGWindowListOptionOnScreenOnly, kCGNullWindowID); 15 | 16 | NSRect rect = [screen frame]; 17 | NSRect mainRect = [NSScreen mainScreen].frame; 18 | for (NSScreen *subScreen in [NSScreen screens]) { 19 | if ((int) subScreen.frame.origin.x == 0 && (int) subScreen.frame.origin.y == 0) { 20 | mainRect = subScreen.frame; 21 | } 22 | } 23 | rect = NSMakeRect(rect.origin.x, (mainRect.size.height) - (rect.origin.y + rect.size.height), rect.size.width, rect.size.height); 24 | 25 | NSLog(@"screenShot: %@", NSStringFromRect(rect)); 26 | CGImageRef imgRef = CGWindowListCreateImageFromArray(rect, windowsRef, kCGWindowImageDefault); 27 | CFRelease(windowsRef); 28 | 29 | return imgRef; 30 | } 31 | 32 | + (BOOL)isPoint:(NSPoint)point inRect:(NSRect)rect 33 | { 34 | //if (NSPointInRect(point, rect)) 35 | //NSLog(@"point:%@ in rect:%@",NSStringFromPoint(point),NSStringFromRect(rect)); 36 | return NSPointInRect(point, rect); 37 | } 38 | 39 | + (double)pointDistance:(NSPoint)p1 toPoint:(NSPoint)p2 40 | { 41 | return (p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y); 42 | } 43 | 44 | + (NSRect)uniformRect:(NSRect)rect 45 | { 46 | double x = rect.origin.x; 47 | double y = rect.origin.y; 48 | double w = rect.size.width; 49 | double h = rect.size.height; 50 | if (w < 0) { 51 | x += w; 52 | w = -w; 53 | } 54 | if (h < 0) { 55 | y += h; 56 | h = -h; 57 | } 58 | return NSMakeRect(x, y, w, h); 59 | } 60 | 61 | + (NSRect)rectToZero:(NSRect)rect 62 | { 63 | return NSOffsetRect(rect, -rect.origin.x, -rect.origin.y); 64 | } 65 | 66 | + (NSRect)cgWindowRectToScreenRect:(CGRect)windowRect 67 | { 68 | NSRect mainRect = [NSScreen mainScreen].frame; 69 | //NSRect snipRect = screen.frame; 70 | for (NSScreen *screen in [NSScreen screens]) { 71 | if ((int) screen.frame.origin.x == 0 && (int) screen.frame.origin.y == 0) { 72 | mainRect = screen.frame; 73 | } 74 | } 75 | NSRect rect = NSMakeRect(windowRect.origin.x, mainRect.size.height - windowRect.size.height - windowRect.origin.y, windowRect.size.width, windowRect.size.height); 76 | return rect; 77 | } 78 | 79 | + (ImageButton *)createButton:(NSImage *)image withAlternate:(NSImage *)alter 80 | { 81 | ImageButton *button = [[ImageButton alloc] init]; 82 | //button.bordered = NO; 83 | //button.bezelStyle = NSShadowlessSquareBezelStyle; 84 | [button setImage:image]; 85 | //[button setAlternateImage:alter]; 86 | return button; 87 | } 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /SnipManager/SnipView.h: -------------------------------------------------------------------------------- 1 | // 2 | // SnipView.h 3 | // Snip 4 | // 5 | // Created by rz on 15/1/31. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "DrawPathInfo.h" 11 | #import "ToolContainer.h" 12 | #import "DrawPathView.h" 13 | 14 | @interface SnipView : NSView 15 | @property NSImage *image; 16 | @property NSRect drawingRect; 17 | @property DrawPathView *pathView; 18 | 19 | @property(nonatomic, strong) NSTrackingArea *trackingArea; 20 | //@property NSMutableArray *rectArray; 21 | //@property DrawPathInfo *currentInfo; 22 | @property ToolContainer *toolContainer; 23 | 24 | - (void)setupTrackingArea:(NSRect)rect; 25 | 26 | - (void)setupTool; 27 | 28 | - (void)setupDrawPath; 29 | 30 | - (void)showToolkit; 31 | 32 | - (void)hideToolkit; 33 | 34 | - (void)showTip; 35 | 36 | - (void)hideTip; 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /SnipManager/SnipView.m: -------------------------------------------------------------------------------- 1 | // 2 | // SnipView.m 3 | // Snip 4 | // 5 | // Created by rz on 15/1/31. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import "SnipView.h" 10 | #import "NSColor+Helper.h" 11 | #import "SimpleLabelView.h" 12 | 13 | const int kDRAG_POINT_NUM = 8; 14 | const int kDRAG_POINT_LEN = 5; 15 | 16 | @interface SnipView () 17 | @property SimpleLabelView *tipView; 18 | 19 | @end 20 | 21 | @implementation SnipView 22 | 23 | 24 | - (instancetype)initWithCoder:(NSCoder *)coder 25 | { 26 | 27 | if (self = [super initWithCoder:coder]) { 28 | //_rectArray = [NSMutableArray array]; 29 | 30 | } 31 | return self; 32 | } 33 | 34 | - (void)setupTrackingArea:(NSRect)rect 35 | { 36 | self.trackingArea = [[NSTrackingArea alloc] initWithRect:rect options:NSTrackingMouseMoved | NSTrackingActiveAlways owner:self userInfo:nil]; 37 | NSLog(@"track init:%@", NSStringFromRect(self.frame)); 38 | [self addTrackingArea:self.trackingArea]; 39 | } 40 | 41 | - (void)setupTool 42 | { 43 | self.toolContainer = [[ToolContainer alloc] init]; 44 | [self addSubview:self.toolContainer]; 45 | [self hideToolkit]; 46 | 47 | self.tipView = [[SimpleLabelView alloc] init]; 48 | [self addSubview:self.tipView]; 49 | [self hideTip]; 50 | } 51 | 52 | - (void)setupDrawPath 53 | { 54 | if (self.pathView != nil) return; 55 | NSLog(@"setupDrawPath"); 56 | self.pathView = [[DrawPathView alloc] init]; 57 | [self addSubview:self.pathView]; 58 | NSRect imageRect = NSIntersectionRect(self.drawingRect, self.bounds); 59 | [self.pathView setFrame:imageRect]; 60 | [self.pathView setHidden:NO]; 61 | } 62 | 63 | - (void)showToolkit 64 | { 65 | NSLog(@"show toolkit:%@",self); 66 | NSRect imageRect = NSIntersectionRect(self.drawingRect, self.bounds); 67 | double y = imageRect.origin.y - 28; 68 | double x = imageRect.origin.x + imageRect.size.width; 69 | if (y < 0) y = 0; 70 | int margin = 10; 71 | int toolWidth = 35 * 6 + margin * 2 - (35-28); 72 | if (x < toolWidth) x = toolWidth; 73 | if (!NSEqualRects(self.toolContainer.frame,NSMakeRect(x - toolWidth, y, toolWidth, 26))) { 74 | [self.toolContainer setFrame:NSMakeRect(x - toolWidth, y, toolWidth, 26)]; 75 | } 76 | if (self.toolContainer.isHidden) { 77 | [self.toolContainer setHidden:NO]; 78 | } 79 | } 80 | 81 | - (void)hideToolkit 82 | { 83 | [self.toolContainer setHidden:YES]; 84 | } 85 | 86 | //- (void)mouseMoved:(NSEvent *)theEvent 87 | //{ 88 | // [super mouseMoved:theEvent]; 89 | // NSLog(@"snipview track mouse moved:%@",self); 90 | // 91 | //} 92 | - (void)showTip 93 | { 94 | NSPoint mouseLocation = [NSEvent mouseLocation]; 95 | NSRect frame = self.window.frame; 96 | if (mouseLocation.x > frame.origin.x + frame.size.width - 100) { 97 | mouseLocation.x -= 100; 98 | } 99 | if (mouseLocation.x < frame.origin.x) { 100 | mouseLocation.x = frame.origin.x; 101 | } 102 | if (mouseLocation.y > frame.origin.y + frame.size.height - 26) { 103 | mouseLocation.y -= 26; 104 | } 105 | if (mouseLocation.y < frame.origin.y) { 106 | mouseLocation.y = frame.origin.y; 107 | } 108 | 109 | NSRect rect = NSMakeRect(mouseLocation.x, mouseLocation.y, 100, 25); 110 | NSRect imageRect = NSIntersectionRect(self.drawingRect, self.bounds); 111 | self.tipView.text = [NSString stringWithFormat:@"%dX%d", (int) imageRect.size.width, (int) imageRect.size.height]; 112 | [self.tipView setFrame:[self.window convertRectFromScreen:rect]]; 113 | [self.tipView setHidden:NO]; 114 | } 115 | 116 | - (void)hideTip 117 | { 118 | [self.tipView setHidden:YES]; 119 | } 120 | 121 | - (BOOL)acceptsFirstMouse:(NSEvent *)theEvent 122 | { 123 | return YES; 124 | } 125 | 126 | - (NSRect)pointRect:(int)index inRect:(NSRect)rect 127 | { 128 | double x = 0, y = 0; 129 | switch (index) { 130 | case 0: 131 | x = NSMinX(rect); 132 | y = NSMaxY(rect); 133 | break; 134 | case 1: 135 | x = NSMidX(rect); 136 | y = NSMaxY(rect); 137 | break; 138 | case 2: 139 | x = NSMaxX(rect); 140 | y = NSMaxY(rect); 141 | break; 142 | case 3: 143 | x = NSMinX(rect); 144 | y = NSMidY(rect); 145 | break; 146 | case 4: 147 | x = NSMaxX(rect); 148 | y = NSMidY(rect); 149 | break; 150 | case 5: 151 | x = NSMinX(rect); 152 | y = NSMinY(rect); 153 | break; 154 | case 6: 155 | x = NSMidX(rect); 156 | y = NSMinY(rect); 157 | break; 158 | case 7: 159 | x = NSMaxX(rect); 160 | y = NSMinY(rect); 161 | break; 162 | 163 | default: 164 | break; 165 | } 166 | return NSMakeRect(x - kDRAG_POINT_LEN, y - kDRAG_POINT_LEN, kDRAG_POINT_LEN * 2, kDRAG_POINT_LEN * 2); 167 | } 168 | 169 | - (void)drawRect:(NSRect)dirtyRect 170 | { 171 | NSDisableScreenUpdates(); 172 | [super drawRect:dirtyRect]; 173 | /*if (self.window.screen) 174 | { 175 | [[NSColor whiteColor] set]; 176 | for (NSDictionary *dir in [SnipManager sharedInstance].arrayRect) { 177 | CGRect windowRect; 178 | CGRectMakeWithDictionaryRepresentation((__bridge CFDictionaryRef) dir[(id) kCGWindowBounds], &windowRect); 179 | NSRect rect = [SnipUtil cgWindowRectToWindowRect:windowRect inScreen:self.window.screen]; 180 | NSBezierPath *rectPath = [NSBezierPath bezierPath]; 181 | [rectPath setLineWidth:0.5]; 182 | [rectPath appendBezierPathWithRect:rect]; 183 | [rectPath stroke]; 184 | } 185 | }*/ 186 | 187 | if (self.image) { 188 | NSRect imageRect = NSIntersectionRect(self.drawingRect, self.bounds); 189 | [self.image drawInRect:imageRect fromRect:imageRect operation:NSCompositeSourceOver fraction:1.0]; 190 | [[NSColor colorFromInt:kBORDER_LINE_COLOR] set]; 191 | NSBezierPath *rectPath = [NSBezierPath bezierPath]; 192 | [rectPath setLineWidth:kBORDER_LINE_WIDTH]; 193 | [rectPath removeAllPoints]; 194 | [rectPath appendBezierPathWithRect:imageRect]; 195 | [rectPath stroke]; 196 | if ([SnipManager sharedInstance].captureState == CAPTURE_STATE_ADJUST) { 197 | [[NSColor whiteColor] set]; 198 | for (int i = 0; i < kDRAG_POINT_NUM; i++) { 199 | NSBezierPath *adjustPath = [NSBezierPath bezierPath]; 200 | [adjustPath removeAllPoints]; 201 | [adjustPath appendBezierPathWithOvalInRect:[self pointRect:i inRect:imageRect]]; 202 | [adjustPath fill]; 203 | } 204 | } 205 | // else if ([SnipManager sharedInstance].captureState == CAPTURE_STATE_EDIT) { 206 | // [self drawCommentInRect:imageRect]; 207 | // if (self.currentInfo) { 208 | // NSRect rect = NSMakeRect(self.currentInfo.startPoint.x, self.currentInfo.startPoint.y, self.currentInfo.endPoint.x-self.currentInfo.startPoint.x, self.currentInfo.endPoint.y-self.currentInfo.startPoint.y); 209 | // rect = [SnipUtil uniformRect:rect]; 210 | // rect = [self.window convertRectFromScreen:rect]; 211 | // NSBezierPath *rectPath = [NSBezierPath bezierPath]; 212 | // [rectPath setLineWidth:1.5]; 213 | // [rectPath appendBezierPathWithRect:rect]; 214 | // [rectPath stroke]; 215 | // } 216 | // } 217 | } 218 | if (self.toolContainer != nil && !self.toolContainer.isHidden) { 219 | [self showToolkit]; 220 | } 221 | // Drawing code here. 222 | NSEnableScreenUpdates(); 223 | } 224 | 225 | @end 226 | -------------------------------------------------------------------------------- /SnipManager/SnipWindow.h: -------------------------------------------------------------------------------- 1 | // 2 | // SnipWindow.h 3 | // Snip 4 | // 5 | // Created by rz on 15/1/31. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "MouseEventProtocol.h" 11 | 12 | @interface SnipWindow : NSPanel 13 | 14 | @property(weak) id mouseDelegate; 15 | @end 16 | -------------------------------------------------------------------------------- /SnipManager/SnipWindow.m: -------------------------------------------------------------------------------- 1 | // 2 | // SnipWindow.m 3 | // Snip 4 | // 5 | // Created by rz on 15/1/31. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import "SnipWindow.h" 10 | #import "SnipManager.h" 11 | 12 | @interface SnipWindow () 13 | @end 14 | 15 | @implementation SnipWindow 16 | 17 | //- (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag 18 | //{ 19 | // // Using NSBorderlessWindowMask results in a window without a title bar. 20 | // if (self = [super initWithContentRect:contentRect styleMask:NSBorderlessWindowMask backing:NSBackingStoreBuffered defer:NO]) { 21 | // [self setAcceptsMouseMovedEvents:YES]; 22 | // self.movable = NO; 23 | // self.movableByWindowBackground = NO; 24 | // } 25 | // return self; 26 | //} 27 | 28 | - (instancetype)initWithContentRect:(NSRect)contentRect styleMask:(NSUInteger)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag screen:(NSScreen *)screen 29 | { 30 | if (self = [super initWithContentRect:contentRect styleMask:aStyle backing:NSBackingStoreBuffered defer:NO screen:screen]) { 31 | [self setAcceptsMouseMovedEvents:YES]; 32 | [self setFloatingPanel:YES]; 33 | [self setCollectionBehavior:NSWindowCollectionBehaviorCanJoinAllSpaces | NSWindowCollectionBehaviorFullScreenAuxiliary]; 34 | [self setMovableByWindowBackground:NO]; 35 | [self setExcludedFromWindowsMenu:YES]; 36 | [self setAlphaValue:1.0]; 37 | [self setOpaque:NO]; 38 | [self setHasShadow:NO]; 39 | [self setHidesOnDeactivate:NO]; 40 | [self setLevel:kCGMaximumWindowLevel]; 41 | [self setRestorable:NO]; 42 | [self disableSnapshotRestoration]; 43 | [self setLevel:kCGMaximumWindowLevel]; 44 | 45 | self.movable = NO; 46 | } 47 | return self; 48 | } 49 | 50 | - (void)dealloc 51 | { 52 | NSLog(@"snip window dealloc"); 53 | } 54 | 55 | - (void)mouseMoved:(NSEvent *)theEvent 56 | { 57 | //[super mouseMoved:theEvent]; 58 | [self.mouseDelegate mouseMoved:theEvent]; 59 | 60 | } 61 | 62 | - (BOOL)canBecomeKeyWindow 63 | { 64 | return YES; 65 | } 66 | 67 | - (BOOL)canBecomeMainWindow 68 | { 69 | return YES; 70 | } 71 | 72 | - (void)mouseDown:(NSEvent *)theEvent 73 | { 74 | //[super mouseDown:theEvent]; 75 | [self.mouseDelegate mouseDown:theEvent]; 76 | } 77 | 78 | - (void)mouseUp:(NSEvent *)theEvent 79 | { 80 | //[super mouseUp:theEvent]; 81 | [self.mouseDelegate mouseUp:theEvent]; 82 | } 83 | 84 | - (void)mouseDragged:(NSEvent *)theEvent 85 | { 86 | //[super mouseDragged:theEvent]; 87 | [self.mouseDelegate mouseDragged:theEvent]; 88 | 89 | } 90 | 91 | - (void)keyDown:(NSEvent *)event 92 | { 93 | if ([event keyCode] == kKEY_ESC_CODE) { 94 | NSLog(@"Escape has been pressed"); 95 | [self orderOut:nil]; 96 | [[SnipManager sharedInstance] endCapture:nil]; 97 | return; 98 | } 99 | [super keyDown:event]; 100 | } 101 | 102 | @end 103 | -------------------------------------------------------------------------------- /SnipManager/SnipWindowController.h: -------------------------------------------------------------------------------- 1 | // 2 | // SnipWindowController.h 3 | // Snip 4 | // 5 | // Created by rz on 15/1/31. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "MouseEventProtocol.h" 12 | 13 | @interface SnipWindowController : NSWindowController 14 | 15 | - (void)startCaptureWithScreen:(NSScreen *)screen; 16 | @end 17 | -------------------------------------------------------------------------------- /SnipManager/SnipWindowController.m: -------------------------------------------------------------------------------- 1 | // 2 | // SnipWindowController.m 3 | // Snip 4 | // 5 | // Created by rz on 15/1/31. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import "SnipWindowController.h" 10 | #import "SnipWindow.h" 11 | #import "SnipUtil.h" 12 | #import "SnipView.h" 13 | 14 | const int kAdjustKnown = 8; 15 | 16 | @interface SnipWindowController () 17 | //@property SnipWindow *window; 18 | @property(weak) SnipView *snipView; 19 | @property NSImage *originImage; 20 | @property NSImage *darkImage; 21 | @property(assign) NSRect captureWindowRect; 22 | @property(assign) NSRect dragWindowRect; 23 | 24 | @property NSRect lastRect; 25 | @property NSPoint startPoint; 26 | @property NSPoint endPoint; 27 | @property int dragDirection; 28 | 29 | @property NSPoint rectBeginPoint; 30 | @property NSPoint rectEndPoint; 31 | @property BOOL rectDrawing; 32 | @end 33 | 34 | @implementation SnipWindowController 35 | 36 | - (void)windowDidLoad 37 | { 38 | [super windowDidLoad]; 39 | // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file. 40 | } 41 | 42 | - (void)dealloc 43 | { 44 | [[NSNotificationCenter defaultCenter] removeObserver:self]; 45 | } 46 | 47 | - (void)doSnapshot:(NSScreen *)screen 48 | { 49 | // 获取所有OnScreen的窗口 50 | //kCGWindowListExcludeDesktopElements 51 | 52 | CGImageRef imgRef = [SnipUtil screenShot:screen]; 53 | 54 | NSRect mainFrame = [screen frame]; 55 | self.originImage = [[NSImage alloc] initWithCGImage:imgRef size:mainFrame.size]; 56 | self.darkImage = [[NSImage alloc] initWithCGImage:imgRef size:mainFrame.size]; 57 | CGImageRelease(imgRef); 58 | 59 | // 对darkImage做暗化处理 60 | [self.darkImage lockFocus]; 61 | [[NSColor colorWithCalibratedWhite:0 alpha:0.33] set]; 62 | NSRectFillUsingOperation([SnipUtil rectToZero:mainFrame], NSCompositeSourceAtop); 63 | [self.darkImage unlockFocus]; 64 | 65 | } 66 | 67 | - (void)captureAppScreen 68 | { 69 | NSScreen *screen = self.window.screen; 70 | NSPoint mouseLocation = [NSEvent mouseLocation]; 71 | //NSLog(@"screen:%@ mouse:%@",NSStringFromRect(screen.frame),NSStringFromPoint(mouseLocation)); 72 | NSRect screenFrame = [screen frame]; 73 | self.captureWindowRect = screenFrame; 74 | double minArea = screenFrame.size.width * screenFrame.size.height; 75 | for (NSDictionary *dir in [SnipManager sharedInstance].arrayRect) { 76 | CGRect windowRect; 77 | CGRectMakeWithDictionaryRepresentation((__bridge CFDictionaryRef) dir[(id) kCGWindowBounds], &windowRect); 78 | NSRect rect = [SnipUtil cgWindowRectToScreenRect:windowRect]; 79 | int layer = 0; 80 | CFNumberRef numberRef = (__bridge CFNumberRef) dir[(id) kCGWindowLayer]; 81 | CFNumberGetValue(numberRef, kCFNumberSInt32Type, &layer); 82 | if (layer < 0) continue; 83 | if ([SnipUtil isPoint:mouseLocation inRect:rect]) { 84 | if (layer == 0) { 85 | self.captureWindowRect = rect; 86 | break; 87 | } 88 | else { 89 | if (rect.size.width * rect.size.height < minArea) { 90 | self.captureWindowRect = rect; 91 | minArea = rect.size.width * rect.size.height; 92 | break; 93 | } 94 | 95 | } 96 | } 97 | 98 | } 99 | //NSLog(@"capture-----%@",NSStringFromRect(self.captureWindowRect)); 100 | if ([SnipUtil isPoint:mouseLocation inRect:screenFrame]) { 101 | [self redrawView:self.originImage]; 102 | } 103 | else { 104 | [self redrawView:nil]; 105 | [[NSNotificationCenter defaultCenter] postNotificationName:kNotifyMouseLocationChange object:nil userInfo:@{@"context":self}]; 106 | } 107 | } 108 | 109 | - (void)redrawView:(NSImage *)image 110 | { 111 | self.captureWindowRect = NSIntersectionRect(self.captureWindowRect, self.window.frame); 112 | if (image != nil && (int) self.lastRect.origin.x == (int) self.captureWindowRect.origin.x 113 | && (int) self.lastRect.origin.y == (int) self.captureWindowRect.origin.y 114 | && (int) self.lastRect.size.width == (int) self.captureWindowRect.size.width 115 | && (int) self.lastRect.size.height == (int) self.captureWindowRect.size.height) { 116 | return; 117 | } 118 | if (self.snipView.image == nil && image == nil) return; 119 | dispatch_async(dispatch_get_main_queue(), ^() { 120 | [self.snipView setImage:image]; 121 | NSRect rect = [self.window convertRectFromScreen:self.captureWindowRect]; 122 | [self.snipView setDrawingRect:rect]; 123 | [self.snipView setNeedsDisplay:YES]; 124 | self.lastRect = self.captureWindowRect; 125 | //NSLog(@"redraw hilight:[%@]", NSStringFromRect(rect)); 126 | }); 127 | 128 | } 129 | 130 | - (NSPoint)dragPointCenter:(int)index 131 | { 132 | double x = 0, y = 0; 133 | switch (index) { 134 | case 0: 135 | x = NSMinX(self.captureWindowRect); 136 | y = NSMaxY(self.captureWindowRect); 137 | break; 138 | case 1: 139 | x = NSMidX(self.captureWindowRect); 140 | y = NSMaxY(self.captureWindowRect); 141 | break; 142 | case 2: 143 | x = NSMaxX(self.captureWindowRect); 144 | y = NSMaxY(self.captureWindowRect); 145 | break; 146 | case 3: 147 | x = NSMinX(self.captureWindowRect); 148 | y = NSMidY(self.captureWindowRect); 149 | break; 150 | case 4: 151 | x = NSMaxX(self.captureWindowRect); 152 | y = NSMidY(self.captureWindowRect); 153 | break; 154 | case 5: 155 | x = NSMinX(self.captureWindowRect); 156 | y = NSMinY(self.captureWindowRect); 157 | break; 158 | case 6: 159 | x = NSMidX(self.captureWindowRect); 160 | y = NSMinY(self.captureWindowRect); 161 | break; 162 | case 7: 163 | x = NSMaxX(self.captureWindowRect); 164 | y = NSMinY(self.captureWindowRect); 165 | break; 166 | 167 | default: 168 | break; 169 | } 170 | return NSMakePoint(x, y); 171 | } 172 | 173 | 174 | - (int)dragDirectionFromPoint:(NSPoint)point 175 | { 176 | if (NSWidth(self.captureWindowRect) <= kAdjustKnown * 2 || NSHeight(self.captureWindowRect) <= kAdjustKnown * 2) { 177 | if (NSPointInRect(point, self.captureWindowRect)) { 178 | return 8; 179 | } 180 | } 181 | NSRect innerRect = NSInsetRect(self.captureWindowRect, kAdjustKnown, kAdjustKnown); 182 | if (NSPointInRect(point, innerRect)) { 183 | return 8; 184 | } 185 | NSRect outerRect = NSInsetRect(self.captureWindowRect, -kAdjustKnown, -kAdjustKnown); 186 | if (!NSPointInRect(point, outerRect)) { 187 | return -1; 188 | } 189 | double minDistance = kAdjustKnown * kAdjustKnown; 190 | int ret = -1; 191 | for (int i = 0; i < 8; i++) { 192 | NSPoint dragPoint = [self dragPointCenter:i]; 193 | double distance = [SnipUtil pointDistance:dragPoint toPoint:point]; 194 | if (distance < minDistance) { 195 | minDistance = distance; 196 | ret = i; 197 | } 198 | } 199 | return ret; 200 | } 201 | 202 | - (void)setupToolClick 203 | { 204 | __weak __typeof__(self) weakSelf = self; 205 | self.snipView.toolContainer.toolClick = ^(long index) { 206 | __typeof__(self) strongSelf = weakSelf; 207 | switch (index) { 208 | case ActionShapeRect: 209 | [SnipManager sharedInstance].drawType = DRAW_TYPE_RECT; 210 | [SnipManager sharedInstance].captureState = CAPTURE_STATE_EDIT; 211 | [strongSelf.snipView setupDrawPath]; 212 | [strongSelf.snipView setNeedsDisplay:YES]; 213 | break; 214 | case ActionShapeEllipse: 215 | [SnipManager sharedInstance].drawType = DRAW_TYPE_ELLIPSE; 216 | [SnipManager sharedInstance].captureState = CAPTURE_STATE_EDIT; 217 | [strongSelf.snipView setupDrawPath]; 218 | [strongSelf.snipView setNeedsDisplay:YES]; 219 | break; 220 | case ActionShapeArrow: 221 | [SnipManager sharedInstance].drawType = DRAW_TYPE_ARROW; 222 | [SnipManager sharedInstance].captureState = CAPTURE_STATE_EDIT; 223 | [strongSelf.snipView setupDrawPath]; 224 | [strongSelf.snipView setNeedsDisplay:YES]; 225 | break; 226 | case ActionExport: 227 | [strongSelf onExportImage]; 228 | [[SnipManager sharedInstance] endCapture:nil]; 229 | break; 230 | case ActionCancel: 231 | [[SnipManager sharedInstance] endCapture:nil]; 232 | break; 233 | case ActionOK: 234 | [strongSelf onOK]; 235 | break; 236 | default: 237 | break; 238 | } 239 | }; 240 | 241 | } 242 | 243 | - (void)startCaptureWithScreen:(NSScreen *)screen 244 | { 245 | [self doSnapshot:screen]; 246 | 247 | [self.window setBackgroundColor:[NSColor colorWithPatternImage:self.darkImage]]; 248 | NSRect screenFrame = [screen frame]; 249 | screenFrame.size.width /= 1; 250 | screenFrame.size.height /= 1; 251 | [self.window setFrame:screenFrame display:YES animate:NO]; 252 | 253 | self.snipView = self.window.contentView; 254 | ((SnipWindow *) self.window).mouseDelegate = self; 255 | [self.snipView setupTrackingArea:self.window.screen.frame]; 256 | 257 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onNotifyMouseChange:) name:kNotifyMouseLocationChange object:nil]; 258 | [self showWindow:nil]; 259 | //[self.window makeKeyAndOrderFront:nil]; 260 | [self captureAppScreen]; 261 | } 262 | 263 | - (void)onNotifyMouseChange:(NSNotification *)notify 264 | { 265 | if (notify.userInfo[@"context"] == self) return; 266 | if ([SnipManager sharedInstance].captureState == CAPTURE_STATE_HILIGHT && self.window.isVisible && [SnipUtil isPoint:[NSEvent mouseLocation] inRect:self.window.screen.frame]) { 267 | 268 | __weak __typeof__(self) weakSelf = self; 269 | dispatch_async(dispatch_get_main_queue(), ^() { 270 | __typeof__(self) strongSelf = weakSelf; 271 | [strongSelf showWindow:nil]; 272 | //[self.window makeKeyAndOrderFront:nil]; 273 | [strongSelf captureAppScreen]; 274 | }); 275 | 276 | } 277 | } 278 | 279 | - (void)mouseDown:(NSEvent *)event 280 | { 281 | if ([event clickCount] == 2) { 282 | if ([SnipManager sharedInstance].captureState != CAPTURE_STATE_HILIGHT) { 283 | [self onOK]; 284 | } 285 | } 286 | 287 | if ([SnipManager sharedInstance].captureState == CAPTURE_STATE_HILIGHT) { 288 | [SnipManager sharedInstance].captureState = CAPTURE_STATE_FIRSTMOUSEDOWN; 289 | self.startPoint = [NSEvent mouseLocation]; 290 | [self.snipView setupTool]; 291 | [self setupToolClick]; 292 | } 293 | else if ([SnipManager sharedInstance].captureState == CAPTURE_STATE_ADJUST) { 294 | self.startPoint = [NSEvent mouseLocation]; 295 | self.captureWindowRect = [SnipUtil uniformRect:self.captureWindowRect]; 296 | self.dragWindowRect = self.captureWindowRect; 297 | self.dragDirection = [self dragDirectionFromPoint:[NSEvent mouseLocation]]; 298 | } 299 | if ([SnipManager sharedInstance].captureState != CAPTURE_STATE_EDIT) { 300 | [self.snipView hideToolkit]; 301 | } 302 | else { 303 | NSPoint mouseLocation = [NSEvent mouseLocation]; 304 | if (NSPointInRect(mouseLocation, self.captureWindowRect)) { 305 | self.rectBeginPoint = mouseLocation; 306 | self.rectDrawing = YES; 307 | } 308 | } 309 | } 310 | 311 | - (void)mouseUp:(NSEvent *)theEvent 312 | { 313 | if ([SnipManager sharedInstance].captureState == CAPTURE_STATE_FIRSTMOUSEDOWN || [SnipManager sharedInstance].captureState == CAPTURE_STATE_READYADJUST) { 314 | [SnipManager sharedInstance].captureState = CAPTURE_STATE_ADJUST; 315 | [self.snipView setNeedsDisplay:YES]; 316 | } 317 | if ([SnipManager sharedInstance].captureState != CAPTURE_STATE_EDIT) { 318 | [self.snipView showToolkit]; 319 | [self.snipView hideTip]; 320 | [self.snipView setNeedsDisplay:YES]; 321 | } 322 | else { 323 | if (self.rectDrawing) { 324 | self.rectDrawing = NO; 325 | self.rectEndPoint = [NSEvent mouseLocation]; 326 | [self.snipView.pathView.rectArray addObject:[[DrawPathInfo alloc] initWith:self.rectBeginPoint andEndPoint:self.rectEndPoint andType:[SnipManager sharedInstance].drawType]]; 327 | [self.snipView setNeedsDisplayInRect:[self.window convertRectFromScreen:self.captureWindowRect]]; 328 | } 329 | } 330 | 331 | } 332 | 333 | - (void)mouseDragged:(NSEvent *)theEvent 334 | { 335 | if ([SnipManager sharedInstance].captureState == CAPTURE_STATE_FIRSTMOUSEDOWN 336 | || [SnipManager sharedInstance].captureState == CAPTURE_STATE_READYADJUST) { 337 | [SnipManager sharedInstance].captureState = CAPTURE_STATE_READYADJUST; 338 | self.endPoint = [NSEvent mouseLocation]; 339 | 340 | self.captureWindowRect = NSUnionRect(NSMakeRect(self.startPoint.x, self.startPoint.y, 1, 1), NSMakeRect(self.endPoint.x, self.endPoint.y, 1, 1)); 341 | self.captureWindowRect = NSIntersectionRect(self.captureWindowRect, self.window.frame); 342 | [self redrawView:self.originImage]; 343 | } 344 | else if ([SnipManager sharedInstance].captureState == CAPTURE_STATE_EDIT) { 345 | if (self.rectDrawing) { 346 | self.rectEndPoint = [NSEvent mouseLocation]; 347 | self.snipView.pathView.currentInfo = [[DrawPathInfo alloc] initWith:self.rectBeginPoint andEndPoint:self.rectEndPoint andType:[SnipManager sharedInstance].drawType]; 348 | [self.snipView.pathView setNeedsDisplay:YES]; 349 | } 350 | } 351 | else if ([SnipManager sharedInstance].captureState == CAPTURE_STATE_ADJUST) { 352 | if (self.dragDirection == -1) return; 353 | NSPoint mouseLocation = [NSEvent mouseLocation]; 354 | self.endPoint = mouseLocation; 355 | CGFloat deltaX = self.endPoint.x - self.startPoint.x; 356 | CGFloat deltaY = self.endPoint.y - self.startPoint.y; 357 | NSRect rect = self.dragWindowRect; 358 | switch (self.dragDirection) { 359 | case 8: { 360 | rect = NSOffsetRect(rect, self.endPoint.x - self.startPoint.x, self.endPoint.y - self.startPoint.y); 361 | if (!NSContainsRect(self.window.frame, rect)) { 362 | NSRect rcOrigin = self.window.frame; 363 | if (rect.origin.x < rcOrigin.origin.x) { 364 | rect.origin.x = rcOrigin.origin.x; 365 | } 366 | if (rect.origin.y < rcOrigin.origin.y) { 367 | rect.origin.y = rcOrigin.origin.y; 368 | } 369 | if (rect.origin.x > rcOrigin.origin.x + rcOrigin.size.width - rect.size.width) { 370 | rect.origin.x = rcOrigin.origin.x + rcOrigin.size.width - rect.size.width; 371 | } 372 | if (rect.origin.y > rcOrigin.origin.y + rcOrigin.size.height - rect.size.height) { 373 | rect.origin.y = rcOrigin.origin.y + rcOrigin.size.height - rect.size.height; 374 | } 375 | self.endPoint = NSMakePoint(self.startPoint.x + rect.origin.x - self.dragWindowRect.origin.x, self.startPoint.y + rect.origin.y - self.dragWindowRect.origin.y); 376 | } 377 | } 378 | break; 379 | case 7: { 380 | rect.origin.y += deltaY; 381 | rect.size.width += deltaX; 382 | rect.size.height -= deltaY; 383 | 384 | } 385 | break; 386 | case 6: { 387 | rect.origin.y += deltaY; 388 | rect.size.height -= deltaY; 389 | } 390 | break; 391 | case 5: { 392 | rect.origin.x += deltaX; 393 | rect.origin.y += deltaY; 394 | rect.size.width -= deltaX; 395 | rect.size.height -= deltaY; 396 | } 397 | break; 398 | case 4: { 399 | rect.size.width += deltaX; 400 | } 401 | break; 402 | case 3: { 403 | rect.origin.x += deltaX; 404 | rect.size.width -= deltaX; 405 | } 406 | break; 407 | case 2: { 408 | rect.size.width += deltaX; 409 | rect.size.height += deltaY; 410 | } 411 | break; 412 | case 1: { 413 | rect.size.height += deltaY; 414 | } 415 | break; 416 | case 0: { 417 | rect.origin.x += deltaX; 418 | rect.size.width -= deltaX; 419 | rect.size.height += deltaY; 420 | } 421 | break; 422 | default: 423 | break; 424 | } 425 | self.dragWindowRect = rect; 426 | if ((int) rect.size.width == 0) rect.size.width = 1; 427 | if ((int) rect.size.height == 0) rect.size.height = 1; 428 | self.captureWindowRect = [SnipUtil uniformRect:rect]; 429 | self.startPoint = self.endPoint; 430 | [self.snipView showTip]; 431 | [self redrawView:self.originImage]; 432 | } 433 | } 434 | 435 | - (void)mouseMoved:(NSEvent *)theEvent 436 | { 437 | if ([SnipManager sharedInstance].captureState == CAPTURE_STATE_HILIGHT) { 438 | [self captureAppScreen]; 439 | } 440 | } 441 | 442 | - (void)onOK 443 | { 444 | //获取截屏的图片 445 | NSImage *pasteImage = [self getCaptureImage]; 446 | // 把选择的截图保存到粘贴板 447 | if (pasteImage != nil) { 448 | NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard]; 449 | [pasteBoard clearContents]; 450 | [pasteBoard writeObjects:@[pasteImage]]; 451 | } 452 | [[SnipManager sharedInstance] endCapture:pasteImage]; 453 | [self.window orderOut:nil]; 454 | 455 | } 456 | 457 | - (void)onExportImage { 458 | NSImage *pasteImage = [self getCaptureImage]; 459 | if (pasteImage != nil) { 460 | NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 461 | formatter.dateFormat = @"yyyy-MM-dd-HH-mm-ss"; 462 | NSString *imagePath = [NSString stringWithFormat:@"%@/snip-%@.png",[[SnipManager sharedInstance] getExportPath],[formatter stringFromDate:[NSDate new]]]; 463 | [self saveImage:pasteImage atPath:imagePath]; 464 | NSLog(@"onExportImage: %@",imagePath); 465 | } 466 | } 467 | 468 | - (NSImage *)getCaptureImage { 469 | [self.originImage lockFocus]; 470 | NSRect rect = NSIntersectionRect(self.captureWindowRect, self.window.frame); 471 | [self.snipView.pathView drawFinishCommentInRect:[self.window convertRectFromScreen:rect]]; 472 | //先设置 下面一个实例 473 | NSBitmapImageRep *bits = [[NSBitmapImageRep alloc] initWithFocusedViewRect:[self.window convertRectFromScreen:rect]]; 474 | 475 | [self.originImage unlockFocus]; 476 | 477 | //再设置后面要用到得 props属性 478 | NSDictionary *imageProps = @{NSImageCompressionFactor : @(1.0)}; 479 | 480 | //之后 转化为NSData 以便存到文件中 481 | NSData *imageData = [bits representationUsingType:NSJPEGFileType properties:imageProps]; 482 | 483 | return [[NSImage alloc] initWithData:imageData]; 484 | } 485 | 486 | - (void)saveImage:(NSImage *)image atPath:(NSString *)path { 487 | 488 | CGImageRef cgRef = [image CGImageForProposedRect:NULL 489 | context:nil 490 | hints:nil]; 491 | NSBitmapImageRep *newRep = [[NSBitmapImageRep alloc] initWithCGImage:cgRef]; 492 | [newRep setSize:[image size]]; // if you want the same resolution 493 | NSData *pngData = [newRep representationUsingType:NSPNGFileType properties:nil]; 494 | [pngData writeToFile:path atomically:YES]; 495 | } 496 | 497 | @end 498 | -------------------------------------------------------------------------------- /SnipManager/SnipWindowController.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 | -------------------------------------------------------------------------------- /SnipManager/ToolContainer.h: -------------------------------------------------------------------------------- 1 | // 2 | // ToolContainer.h 3 | // Snip 4 | // 5 | // Created by isee15 on 15/2/5. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | typedef NS_ENUM(NSInteger, ActionType) 12 | { 13 | ActionCancel, 14 | ActionOK, 15 | ActionExport, 16 | ActionShapeRect, 17 | ActionShapeEllipse, 18 | ActionShapeArrow 19 | }; 20 | 21 | @interface ToolContainer : NSView 22 | @property(nonatomic, copy) void (^toolClick)(long index); 23 | @end 24 | -------------------------------------------------------------------------------- /SnipManager/ToolContainer.m: -------------------------------------------------------------------------------- 1 | // 2 | // ToolContainer.m 3 | // Snip 4 | // 5 | // Created by isee15 on 15/2/5. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import "ToolContainer.h" 10 | #import "SnipUtil.h" 11 | #import "SnipManager.h" 12 | 13 | @interface ToolContainer () 14 | @property ImageButton *rectButton; 15 | @property ImageButton *ellipseButton; 16 | @property ImageButton *arrowButton; 17 | @property ImageButton *cancelButton; 18 | @property ImageButton *exportButton; 19 | @property ImageButton *okButton; 20 | @end 21 | 22 | @implementation ToolContainer 23 | 24 | - (instancetype)init 25 | { 26 | if (self = [super init]) { 27 | 28 | _rectButton = [SnipUtil createButton: [[SnipManager sharedInstance] getImageFromResource:@"ScreenCapture_toolbar_rect_ineffect.tiff"] withAlternate:nil]; 29 | _rectButton.tag = ActionShapeRect; 30 | 31 | _ellipseButton = [SnipUtil createButton:[[SnipManager sharedInstance] getImageFromResource:@"ScreenCapture_toolbar_ellipse_ineffect.tiff"] withAlternate:nil]; 32 | _ellipseButton.tag = ActionShapeEllipse; 33 | 34 | _arrowButton = [SnipUtil createButton:[[SnipManager sharedInstance] getImageFromResource:@"ScreenCapture_toolbar_arrow_ineffect.tiff"] withAlternate:nil]; 35 | _arrowButton.tag = ActionShapeArrow; 36 | 37 | _exportButton = [SnipUtil createButton:[[SnipManager sharedInstance] getImageFromResource:@"ScreenCapture_toolbar_export.tiff"] withAlternate:nil]; 38 | _exportButton.tag = ActionExport; 39 | 40 | _cancelButton = [SnipUtil createButton:[[SnipManager sharedInstance] getImageFromResource:@"ScreenCapture_toolbar_cross_normal.tiff"] withAlternate:nil]; 41 | _cancelButton.tag = ActionCancel; 42 | 43 | _okButton = [SnipUtil createButton:[[SnipManager sharedInstance] getImageFromResource:@"ScreenCapture_toolbar_tick_normal.tiff"] withAlternate:nil]; 44 | _okButton.tag = ActionOK; 45 | 46 | _rectButton.target = self; 47 | _rectButton.action = @selector(onToolClick:); 48 | _ellipseButton.target = self; 49 | _ellipseButton.action = @selector(onToolClick:); 50 | _arrowButton.target = self; 51 | _arrowButton.action = @selector(onToolClick:); 52 | _exportButton.target = self; 53 | _exportButton.action = @selector(onToolClick:); 54 | _cancelButton.target = self; 55 | _cancelButton.action = @selector(onToolClick:); 56 | _okButton.target = self; 57 | _okButton.action = @selector(onToolClick:); 58 | 59 | [self addSubview:_rectButton]; 60 | [self addSubview:_ellipseButton]; 61 | [self addSubview:_arrowButton]; 62 | [self addSubview:_exportButton]; 63 | [self addSubview:_cancelButton]; 64 | [self addSubview:_okButton]; 65 | } 66 | return self; 67 | } 68 | 69 | 70 | - (void)drawRect:(NSRect)dirtyRect 71 | { 72 | [super drawRect:dirtyRect]; 73 | NSBezierPath *bgPath = [NSBezierPath bezierPathWithRoundedRect:self.bounds xRadius:3 yRadius:3]; 74 | [bgPath setClip]; 75 | [[NSColor colorWithCalibratedWhite:0.0 alpha:0.8f] setFill]; 76 | NSRectFill(self.bounds); 77 | // Drawing code here. 78 | } 79 | 80 | - (void)setFrame:(NSRect)frame 81 | { 82 | [super setFrame:frame]; 83 | int step = 35; 84 | int margin = 10; 85 | [self.rectButton setFrame:NSMakeRect(margin, 0, 28, 26)]; 86 | [self.ellipseButton setFrame:NSMakeRect(margin+step * 1, 0, 28, 26)]; 87 | [self.arrowButton setFrame:NSMakeRect(margin+step * 2, 0, 28, 26)]; 88 | [self.exportButton setFrame:NSMakeRect(margin+step * 3, 0, 28, 26)]; 89 | [self.cancelButton setFrame:NSMakeRect(margin+step * 4, 0, 28, 26)]; 90 | [self.okButton setFrame:NSMakeRect(margin+step * 5, 0, 28, 26)]; 91 | 92 | } 93 | 94 | - (void)onToolClick:(NSControl *)sender 95 | { 96 | //need refactor 97 | if (sender == self.rectButton) { 98 | self.rectButton.image = [[SnipManager sharedInstance] getImageFromResource:@"ScreenCapture_toolbar_rect_effect.tiff"]; 99 | self.ellipseButton.image = [[SnipManager sharedInstance] getImageFromResource:@"ScreenCapture_toolbar_ellipse_ineffect.tiff"]; 100 | self.arrowButton.image = [[SnipManager sharedInstance] getImageFromResource:@"ScreenCapture_toolbar_arrow_ineffect.tiff"]; 101 | } 102 | else if (sender == self.ellipseButton) { 103 | self.rectButton.image = [[SnipManager sharedInstance] getImageFromResource:@"ScreenCapture_toolbar_rect_ineffect.tiff"]; 104 | self.ellipseButton.image = [[SnipManager sharedInstance] getImageFromResource:@"ScreenCapture_toolbar_ellipse_effect.tiff"]; 105 | self.arrowButton.image = [[SnipManager sharedInstance] getImageFromResource:@"ScreenCapture_toolbar_arrow_ineffect.tiff"]; 106 | } 107 | else if (sender == self.arrowButton) { 108 | self.rectButton.image = [[SnipManager sharedInstance] getImageFromResource:@"ScreenCapture_toolbar_rect_ineffect.tiff"]; 109 | self.ellipseButton.image = [[SnipManager sharedInstance] getImageFromResource:@"ScreenCapture_toolbar_ellipse_ineffect.tiff"]; 110 | self.arrowButton.image = [[SnipManager sharedInstance] getImageFromResource:@"ScreenCapture_toolbar_arrow_effect.tiff"]; 111 | } 112 | if (self.toolClick) { 113 | self.toolClick([sender tag]); 114 | } 115 | 116 | } 117 | 118 | - (void)mouseDown:(NSEvent *)theEvent 119 | { 120 | } 121 | 122 | 123 | @end 124 | -------------------------------------------------------------------------------- /SnipTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /SnipTests/SnipTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // SnipTests.m 3 | // SnipTests 4 | // 5 | // Created by rz on 15/1/31. 6 | // Copyright (c) 2015年 isee15. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface SnipTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation SnipTests 17 | 18 | - (void)setUp { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown { 24 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /src.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/yihuds/SnipManager/7901c2785dbff4d64ff9695dd0cfa1c3670b22d9/src.png --------------------------------------------------------------------------------