├── .gitignore ├── .gitmodules ├── Documentation ├── Classes │ ├── INDockableAuxiliaryWindow.html │ ├── INDockableDetachControl.html │ ├── INDockablePrimaryWindow.html │ ├── INDockableSplitView.html │ ├── INDockableViewController.html │ ├── INDockableWindow.html │ └── INDockableWindowController.html ├── Protocols │ └── INDockableWindowControllerDelegate.html ├── css │ ├── styles.css │ └── stylesPrint.css ├── hierarchy.html ├── img │ ├── button_bar_background.png │ ├── disclosure.png │ ├── disclosure_open.png │ ├── library_background.png │ └── title_background.png └── index.html ├── Example ├── AppDelegate.h ├── AppDelegate.m ├── INDockableWindow-Info.plist ├── INDockableWindow-Prefix.pch ├── en.lproj │ ├── Credits.rtf │ ├── InfoPlist.strings │ └── MainMenu.xib └── main.m ├── INDockableWindow.podspec ├── INDockableWindow.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcuserdata │ └── indragie.xcuserdatad │ └── xcschemes │ ├── INDockableWindow.xcscheme │ └── xcschememanagement.plist ├── INDockableWindow ├── INDockableAuxiliaryWindow.h ├── INDockableAuxiliaryWindow.m ├── INDockableDetachControl.h ├── INDockableDetachControl.m ├── INDockablePrimaryWindow.h ├── INDockablePrimaryWindow.m ├── INDockableSplitView.h ├── INDockableSplitView.m ├── INDockableViewController.h ├── INDockableViewController.m ├── INDockableWindow.h ├── INDockableWindow.m ├── INDockableWindowController.h ├── INDockableWindowController.m ├── INWindowFrameAnimation.h ├── INWindowFrameAnimation.m ├── NSView+INImagingAdditions.h └── NSView+INImagingAdditions.m ├── LICENSE.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | ######################### 2 | # .gitignore file for Xcode4 / OS X Source projects 3 | # 4 | # NB: if you are storing "built" products, this WILL NOT WORK, 5 | # and you should use a different .gitignore (or none at all) 6 | # This file is for SOURCE projects, where there are many extra 7 | # files that we want to exclude 8 | # 9 | # For updates, see: http://stackoverflow.com/questions/49478/git-ignore-file-for-xcode-projects 10 | ######################### 11 | 12 | ##### 13 | # OS X temporary files that should never be committed 14 | 15 | .DS_Store 16 | *.swp 17 | *.lock 18 | profile 19 | 20 | 21 | #### 22 | # Xcode temporary files that should never be committed 23 | # 24 | # NB: NIB/XIB files still exist even on Storyboard projects, so we want this... 25 | 26 | *~.nib 27 | 28 | 29 | #### 30 | # Xcode build files - 31 | # 32 | # NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "DerivedData" 33 | 34 | DerivedData/ 35 | 36 | # NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "build" 37 | 38 | build/ 39 | 40 | 41 | ##### 42 | # Xcode private settings (window sizes, bookmarks, breakpoints, custom executables, smart groups) 43 | # 44 | # This is complicated: 45 | # 46 | # SOMETIMES you need to put this file in version control. 47 | # Apple designed it poorly - if you use "custom executables", they are 48 | # saved in this file. 49 | # 99% of projects do NOT use those, so they do NOT want to version control this file. 50 | # ..but if you're in the 1%, comment out the line "*.pbxuser" 51 | 52 | *.pbxuser 53 | *.mode1v3 54 | *.mode2v3 55 | *.perspectivev3 56 | # NB: also, whitelist the default ones, some projects need to use these 57 | !default.pbxuser 58 | !default.mode1v3 59 | !default.mode2v3 60 | !default.perspectivev3 61 | 62 | 63 | #### 64 | # Xcode 4 - semi-personal settings, often included in workspaces 65 | # 66 | # You can safely ignore the xcuserdata files - but do NOT ignore the files next to them 67 | # 68 | 69 | xcuserdata 70 | 71 | #### 72 | # XCode 4 workspaces - more detailed 73 | # 74 | # Workspaces are important! They are a core feature of Xcode - don't exclude them :) 75 | # 76 | # Workspace layout is quite spammy. For reference: 77 | # 78 | # (root)/ 79 | # (project-name).xcodeproj/ 80 | # project.pbxproj 81 | # project.xcworkspace/ 82 | # contents.xcworkspacedata 83 | # xcuserdata/ 84 | # (your name).xcuserdatad/ 85 | # WorkspaceSettings.xcsettings 86 | # xcuserdata/ 87 | # (your name).xcuserdatad/ 88 | # xcschemes/ 89 | # (project-name).xcscheme 90 | # 91 | # 92 | # 93 | # Xcode 4 workspaces - SHARED 94 | # 95 | # This is UNDOCUMENTED (google: "developer.apple.com xcshareddata" - 0 results 96 | # But if you're going to kill personal workspaces, at least keep the shared ones... 97 | # 98 | # 99 | !xcshareddata 100 | 101 | #### 102 | # XCode 4 build-schemes 103 | # 104 | # PRIVATE ones are stored inside xcuserdata 105 | !xcschemes 106 | 107 | #### 108 | # Xcode 4 - Deprecated classes 109 | # 110 | # Allegedly, if you manually "deprecate" your classes, they get moved here. 111 | # 112 | # We're using source-control, so this is a "feature" that we do not want! 113 | 114 | *.moved-aside 115 | 116 | 117 | #### 118 | # UNKNOWN: recommended by others, but I can't discover what these files are 119 | # 120 | # ...none. Everything is now explained. -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "External/INAppStoreWindow"] 2 | path = External/INAppStoreWindow 3 | url = git://github.com/indragiek/INAppStoreWindow.git 4 | -------------------------------------------------------------------------------- /Documentation/Classes/INDockableAuxiliaryWindow.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | INDockableAuxiliaryWindow Class Reference 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |

INDockableWindow

16 | Indragie Karunaratne 17 |
18 | 19 | 22 | 54 |
55 | 84 |
85 |
86 | 87 | 93 | 98 |
99 | 100 |
101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 |
Inherits fromINDockableWindow : INAppStoreWindow
Declared inINDockableAuxiliaryWindow.h
INDockableAuxiliaryWindow.m
109 | 110 | 111 | 112 | 113 |
114 | 115 |

Overview

116 |

The auxiliary window class for displaying detached views

117 |
118 | 119 | 120 | 121 | 122 | 123 |
124 | 125 |

Tasks

126 | 127 | 128 | 129 | 130 | 131 |
    132 |
  • 133 | 134 |   viewController 135 |

    The dockabie view controller that this auxiliary window contains.

    136 |
    137 | property 138 | 139 |
  • 140 |
141 | 142 |
143 | 144 | 145 | 146 | 147 | 148 |
149 | 150 |

Properties

151 | 152 |
153 | 154 |

viewController

155 | 156 | 157 | 158 |
159 |

The dockabie view controller that this auxiliary window contains.

160 |
161 | 162 | 163 | 164 |
@property (nonatomic, strong, readonly) INDockableViewController *viewController
165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 |
181 |

Declared In

182 | INDockableAuxiliaryWindow.h
183 |
184 | 185 | 186 |
187 | 188 |
189 | 190 | 191 | 192 | 193 | 194 | 195 |
196 | 202 | 211 |
212 |
213 | 304 | 305 | -------------------------------------------------------------------------------- /Documentation/Classes/INDockableDetachControl.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | INDockableDetachControl Class Reference 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |

INDockableWindow

16 | Indragie Karunaratne 17 |
18 | 19 | 22 | 60 |
61 | 96 |
97 |
98 | 99 | 105 | 110 |
111 | 112 |
113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 |
Inherits fromNSView
Declared inINDockableDetachControl.h
INDockableDetachControl.m
121 | 122 | 123 | 124 | 125 |
126 | 127 |

Overview

128 |

Control that can be dragged to trigger a detach of its parent view controller from the primary window.

129 |
130 | 131 | 132 | 133 | 134 | 135 |
136 | 137 |

Tasks

138 | 139 | 140 | 141 | 142 | 143 |
    144 |
  • 145 | 146 |   image 147 |

    The detach control image.

    148 |
    149 | property 150 | 151 |
  • 152 | 153 |   minimumDragDistance 154 |

    The minimum drag distance to trigger a detach. Default is 10px.

    155 |
    156 | property 157 | 158 |
  • 159 | 160 |   fadeOnHover 161 |

    Whether the control fades in on mouse hover. Default is NO.

    162 |
    163 | property 164 | 165 |
  • 166 | 167 |   viewController 168 |

    The view controller that owns this detach control

    169 |
    170 | property 171 | 172 |
  • 173 |
174 | 175 |
176 | 177 | 178 | 179 | 180 | 181 |
182 | 183 |

Properties

184 | 185 |
186 | 187 |

fadeOnHover

188 | 189 | 190 | 191 |
192 |

Whether the control fades in on mouse hover. Default is NO.

193 |
194 | 195 | 196 | 197 |
@property (nonatomic, assign) BOOL fadeOnHover
198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 |
214 |

Declared In

215 | INDockableDetachControl.h
216 |
217 | 218 | 219 |
220 | 221 |
222 | 223 |

image

224 | 225 | 226 | 227 |
228 |

The detach control image.

229 |
230 | 231 | 232 | 233 |
@property (nonatomic, strong) NSImage *image
234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 |
250 |

Declared In

251 | INDockableDetachControl.h
252 |
253 | 254 | 255 |
256 | 257 |
258 | 259 |

minimumDragDistance

260 | 261 | 262 | 263 |
264 |

The minimum drag distance to trigger a detach. Default is 10px.

265 |
266 | 267 | 268 | 269 |
@property (nonatomic, assign) CGFloat minimumDragDistance
270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 |
286 |

Declared In

287 | INDockableDetachControl.h
288 |
289 | 290 | 291 |
292 | 293 |
294 | 295 |

viewController

296 | 297 | 298 | 299 |
300 |

The view controller that owns this detach control

301 |
302 | 303 | 304 | 305 |
@property (nonatomic, assign, readonly) INDockableViewController *viewController
306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 |
322 |

Declared In

323 | INDockableDetachControl.h
324 |
325 | 326 | 327 |
328 | 329 |
330 | 331 | 332 | 333 | 334 | 335 | 336 |
337 | 343 | 352 |
353 |
354 | 445 | 446 | -------------------------------------------------------------------------------- /Documentation/Classes/INDockablePrimaryWindow.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | INDockablePrimaryWindow Class Reference 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |

INDockableWindow

16 | Indragie Karunaratne 17 |
18 | 19 | 22 | 47 |
48 | 67 |
68 |
69 | 70 | 76 | 81 |
82 | 83 |
84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 |
Inherits fromINDockableWindow : INAppStoreWindow
Declared inINDockablePrimaryWindow.h
INDockablePrimaryWindow.m
92 | 93 | 94 | 95 | 96 |
97 | 98 |

Overview

99 |

The primary window class

100 |
101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 |
116 | 122 | 131 |
132 |
133 | 224 | 225 | -------------------------------------------------------------------------------- /Documentation/Classes/INDockableSplitView.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | INDockableSplitView Class Reference 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |

INDockableWindow

16 | Indragie Karunaratne 17 |
18 | 19 | 22 | 58 |
59 | 92 |
93 |
94 | 95 | 101 | 106 |
107 | 108 |
109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 |
Inherits fromNSSplitView
Declared inINDockableSplitView.h
INDockableSplitView.m
117 | 118 | 119 | 120 | 121 |
122 | 123 |

Overview

124 |

NSSplitView subclass that adds some options for easy customization.

125 |
126 | 127 | 128 | 129 | 130 | 131 |
132 | 133 |

Tasks

134 | 135 | 136 | 137 | 138 | 139 |
    140 |
  • 141 | 142 |   dividerThickness 143 |

    Width of the split view dividers. Default is 1px.

    144 |
    145 | property 146 | 147 |
  • 148 | 149 |   dividerColor 150 |

    Color of the split view dividers.

    151 |
    152 | property 153 | 154 |
  • 155 | 156 |   dividerDrawingBlock 157 |

    Drawing block to draw your own custom dividers.

    158 |
    159 | property 160 | 161 |
  • 162 |
163 | 164 |
165 | 166 | 167 | 168 | 169 | 170 |
171 | 172 |

Properties

173 | 174 |
175 | 176 |

dividerColor

177 | 178 | 179 | 180 |
181 |

Color of the split view dividers.

182 |
183 | 184 | 185 | 186 |
@property (nonatomic, strong) NSColor *dividerColor
187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 |
203 |

Declared In

204 | INDockableSplitView.h
205 |
206 | 207 | 208 |
209 | 210 |
211 | 212 |

dividerDrawingBlock

213 | 214 | 215 | 216 |
217 |

Drawing block to draw your own custom dividers.

218 |
219 | 220 | 221 | 222 |
@property (nonatomic, copy) void ( ^ ) ( NSRect rect ) dividerDrawingBlock
223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 |
239 |

Declared In

240 | INDockableSplitView.h
241 |
242 | 243 | 244 |
245 | 246 |
247 | 248 |

dividerThickness

249 | 250 | 251 | 252 |
253 |

Width of the split view dividers. Default is 1px.

254 |
255 | 256 | 257 | 258 |
@property (nonatomic, assign) CGFloat dividerThickness
259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 |
275 |

Declared In

276 | INDockableSplitView.h
277 |
278 | 279 | 280 |
281 | 282 |
283 | 284 | 285 | 286 | 287 | 288 | 289 |
290 | 296 | 305 |
306 |
307 | 398 | 399 | -------------------------------------------------------------------------------- /Documentation/Classes/INDockableViewController.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | INDockableViewController Class Reference 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |

INDockableWindow

16 | Indragie Karunaratne 17 |
18 | 19 | 22 | 71 |
72 | 119 |
120 |
121 | 122 | 128 | 133 |
134 | 135 |
136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 |
Inherits fromNSViewController
Declared inINDockableViewController.h
INDockableViewController.m
144 | 145 | 146 | 147 | 148 |
149 | 150 |

Overview

151 |

View controller that displays the content for a single dockable pane of the dockable window controller.

152 |
153 | 154 | 155 | 156 | 157 | 158 |
159 | 160 |

Tasks

161 | 162 | 163 | 164 | 165 | 166 |
    167 |
  • 168 | 169 |   dockableWindowController 170 |

    The dockable window controller that owns this view controller.

    171 |
    172 | property 173 | 174 |
  • 175 | 176 |   window 177 |

    The parent window of this view controller

    178 |
    179 | property 180 | 181 |
  • 182 | 183 |   titleBarView 184 |

    The view to display in the title bar. This view will be resized to fit the title bar size.

    185 |
    186 | property 187 | 188 |
  • 189 | 190 |   uniqueIdentifier 191 |

    The unique identifier for this view controller. Set to a generated UUID by default.

    192 |
    193 | property 194 | 195 |
  • 196 | 197 |   detachControl 198 |

    The detach control for the view controller. This control is automatically created when 199 | the view controller is created. It can be placed anywhere in your view hierarchy, and 200 | dragging it will trigger a detach from the primary window.

    201 |
    202 | property 203 | 204 |
  • 205 | 206 |   attached 207 |

    Whether this view controller is attached or in its own separate window.

    208 |
    209 | property 210 | 211 |
  • 212 | 213 | – viewControllerDidDetach 214 |

    Called when the view controller is detached from the primary window.

    215 |
    216 | 217 | 218 |
  • 219 | 220 | – viewControllerDidAttach 221 |

    Called when the view controller is attached to the primary window

    222 |
    223 | 224 | 225 |
  • 226 |
227 | 228 |
229 | 230 | 231 | 232 | 233 | 234 |
235 | 236 |

Properties

237 | 238 |
239 | 240 |

attached

241 | 242 | 243 | 244 |
245 |

Whether this view controller is attached or in its own separate window.

246 |
247 | 248 | 249 | 250 |
@property (nonatomic, assign, getter=isAttached) BOOL attached
251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 |
267 |

Declared In

268 | INDockableViewController.h
269 |
270 | 271 | 272 |
273 | 274 |
275 | 276 |

detachControl

277 | 278 | 279 | 280 |
281 |

The detach control for the view controller. This control is automatically created when 282 | the view controller is created. It can be placed anywhere in your view hierarchy, and 283 | dragging it will trigger a detach from the primary window.

284 |
285 | 286 | 287 | 288 |
@property (nonatomic, strong, readonly) INDockableDetachControl *detachControl
289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 |
305 |

Declared In

306 | INDockableViewController.h
307 |
308 | 309 | 310 |
311 | 312 |
313 | 314 |

dockableWindowController

315 | 316 | 317 | 318 |
319 |

The dockable window controller that owns this view controller.

320 |
321 | 322 | 323 | 324 |
@property (nonatomic, assign, readonly) INDockableWindowController *dockableWindowController
325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 |
341 |

Declared In

342 | INDockableViewController.h
343 |
344 | 345 | 346 |
347 | 348 |
349 | 350 |

titleBarView

351 | 352 | 353 | 354 |
355 |

The view to display in the title bar. This view will be resized to fit the title bar size.

356 |
357 | 358 | 359 | 360 |
@property (nonatomic, strong) IBOutlet NSView *titleBarView
361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 |
377 |

Declared In

378 | INDockableViewController.h
379 |
380 | 381 | 382 |
383 | 384 |
385 | 386 |

uniqueIdentifier

387 | 388 | 389 | 390 |
391 |

The unique identifier for this view controller. Set to a generated UUID by default.

392 |
393 | 394 | 395 | 396 |
@property (nonatomic, copy) NSString *uniqueIdentifier
397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 |
407 |

Discussion

408 |

If you decide to set this yourself, ensure that this value is unique from the 409 | identifiers of any other view controllers. If this rule is not followed, the 410 | behaviour is undefined. Setting this identifier will set the identifier of this 411 | view controller’s view as well.

Warning: Do not modify the identifier of the view after 412 | the view controller has been created.

413 |
414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 |
422 |

Declared In

423 | INDockableViewController.h
424 |
425 | 426 | 427 |
428 | 429 |
430 | 431 |

window

432 | 433 | 434 | 435 |
436 |

The parent window of this view controller

437 |
438 | 439 | 440 | 441 |
@property (nonatomic, assign, readonly) NSWindow *window
442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 |
458 |

Declared In

459 | INDockableViewController.h
460 |
461 | 462 | 463 |
464 | 465 |
466 | 467 | 468 | 469 | 470 | 471 |
472 | 473 |

Instance Methods

474 | 475 |
476 | 477 |

viewControllerDidAttach

478 | 479 | 480 | 481 |
482 |

Called when the view controller is attached to the primary window

483 |
484 | 485 | 486 | 487 |
- (void)viewControllerDidAttach
488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 |
498 |

Discussion

499 |

Always call super somewhere in your implementation.

500 |
501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 |
509 |

Declared In

510 | INDockableViewController.h
511 |
512 | 513 | 514 |
515 | 516 |
517 | 518 |

viewControllerDidDetach

519 | 520 | 521 | 522 |
523 |

Called when the view controller is detached from the primary window.

524 |
525 | 526 | 527 | 528 |
- (void)viewControllerDidDetach
529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 |
539 |

Discussion

540 |

Always call super somewhere in your implementation.

541 |
542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 |
550 |

Declared In

551 | INDockableViewController.h
552 |
553 | 554 | 555 |
556 | 557 |
558 | 559 | 560 |
561 | 567 | 576 |
577 |
578 | 669 | 670 | -------------------------------------------------------------------------------- /Documentation/Classes/INDockableWindow.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | INDockableWindow Class Reference 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |

INDockableWindow

16 | Indragie Karunaratne 17 |
18 | 19 | 22 | 54 |
55 | 84 |
85 |
86 | 87 | 93 | 98 |
99 | 100 |
101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 |
Inherits fromINAppStoreWindow
Declared inINDockableWindow.h
INDockableWindow.m
109 | 110 | 111 | 112 | 113 |
114 | 115 |

Overview

116 |

Base class for all windows used by INDockableWindowController

117 |
118 | 119 | 120 | 121 | 122 | 123 |
124 | 125 |

Tasks

126 | 127 | 128 | 129 | 130 | 131 |
    132 |
  • 133 | 134 |   dockableWindowController 135 |

    The dockable window controller that owns this window.

    136 |
    137 | property 138 | 139 |
  • 140 |
141 | 142 |
143 | 144 | 145 | 146 | 147 | 148 |
149 | 150 |

Properties

151 | 152 |
153 | 154 |

dockableWindowController

155 | 156 | 157 | 158 |
159 |

The dockable window controller that owns this window.

160 |
161 | 162 | 163 | 164 |
@property (nonatomic, assign, readonly) INDockableWindowController *dockableWindowController
165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 |
181 |

Declared In

182 | INDockableWindow.h
183 |
184 | 185 | 186 |
187 | 188 |
189 | 190 | 191 | 192 | 193 | 194 | 195 |
196 | 202 | 211 |
212 |
213 | 304 | 305 | -------------------------------------------------------------------------------- /Documentation/Protocols/INDockableWindowControllerDelegate.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | INDockableWindowControllerDelegate Protocol Reference 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 |
15 |

INDockableWindow

16 | Indragie Karunaratne 17 |
18 | 19 | 22 | 62 |
63 | 102 |
103 |
104 | 105 | 111 | 116 |
117 | 118 |
119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 |
Conforms toNSObject
Declared inINDockableWindowController.h
127 | 128 | 129 | 130 | 131 |
132 | 133 |

Overview

134 |

The dockable window controller’s delegate. Contains some methods that are useful for being notified 135 | about events that were triggered by the user and not by methods called on the window controller

136 |
137 | 138 | 139 | 140 | 141 | 142 |
143 | 144 |

Tasks

145 | 146 | 147 | 148 |

Other Methods

149 | 150 | 174 | 175 | 176 | 177 |

NSSplitViewDelegate Methods

178 | 179 | 198 | 199 |
200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 |
210 | 211 |

Instance Methods

212 | 213 |
214 | 215 |

dockableWindowController:auxiliaryWindowDidClose:

216 | 217 | 218 | 219 |
220 |

Called when the user closes an auxiliary window containing a dockable view controller.

221 |
222 | 223 | 224 | 225 |
- (void)dockableWindowController:(INDockableWindowController *)controller auxiliaryWindowDidClose:(INDockableAuxiliaryWindow *)auxiliaryWindow
226 | 227 | 228 | 229 |
230 |

Parameters

231 | 232 |
233 |
controller
234 |

The dockable window controller.

235 |
236 | 237 |
238 |
auxiliaryWindow
239 |

The window that was closed.

240 |
241 | 242 |
243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 |
257 |

Declared In

258 | INDockableWindowController.h
259 |
260 | 261 | 262 |
263 | 264 |
265 | 266 |

dockableWindowController:viewControllerWasAttached:

267 | 268 | 269 | 270 |
271 |

Called when a view controller is attached to the primary window

272 |
273 | 274 | 275 | 276 |
- (void)dockableWindowController:(INDockableWindowController *)controller viewControllerWasAttached:(INDockableViewController *)viewController
277 | 278 | 279 | 280 |
281 |

Parameters

282 | 283 |
284 |
controller
285 |

The dockable window controller.

286 |
287 | 288 |
289 |
viewController
290 |

The view controller that was attached.

291 |
292 | 293 |
294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 |
308 |

Declared In

309 | INDockableWindowController.h
310 |
311 | 312 | 313 |
314 | 315 |
316 | 317 |

dockableWindowController:viewControllerWasDetached:

318 | 319 | 320 | 321 |
322 |

Called when a view controller is detached from the primary window.

323 |
324 | 325 | 326 | 327 |
- (void)dockableWindowController:(INDockableWindowController *)controller viewControllerWasDetached:(INDockableViewController *)viewController
328 | 329 | 330 | 331 |
332 |

Parameters

333 | 334 |
335 |
controller
336 |

The dockable window controller.

337 |
338 | 339 |
340 |
viewController
341 |

The view controller that was detached. 342 | *

343 |
344 | 345 |
346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 |
360 |

Declared In

361 | INDockableWindowController.h
362 |
363 | 364 | 365 |
366 | 367 |
368 | 369 |

splitView:canCollapseSubview:

370 | 371 | 372 | 373 |
374 |

It is recommended that you do not override the following NSSplitView 375 | delegate methods to allow collapsing. Using this class with collapsing enabled 376 | results in undefined behaviour

377 |
378 | 379 | 380 | 381 |
- (BOOL)splitView:(NSSplitView *)splitView canCollapseSubview:(NSView *)subview
382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 |
392 |

Discussion

393 |

Warning: It is recommended that you do not override the following NSSplitView 394 | delegate methods to allow collapsing. Using this class with collapsing enabled 395 | results in undefined behaviour

396 |
397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 |
405 |

Declared In

406 | INDockableWindowController.h
407 |
408 | 409 | 410 |
411 | 412 |
413 | 414 |

splitView:shouldAdjustSizeOfSubview:

415 | 416 | 417 | 418 |
419 |

The documentation for these methods can be found here: http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/NSSplitViewDelegate_Protocol/Reference/Reference.html

420 |
421 | 422 | 423 | 424 |
- (BOOL)splitView:(NSSplitView *)splitView shouldAdjustSizeOfSubview:(NSView *)subview
425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 |
441 |

Declared In

442 | INDockableWindowController.h
443 |
444 | 445 | 446 |
447 | 448 |
449 | 450 | 451 |
452 | 458 | 467 |
468 |
469 | 560 | 561 | -------------------------------------------------------------------------------- /Documentation/css/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: 'Lucida Grande',Geneva,Helvetica,Arial,sans-serif; 3 | font-size: 13px; 4 | } 5 | 6 | code { 7 | font-family: Courier, Consolas, monospace; 8 | font-size: 13px; 9 | color: #666; 10 | } 11 | 12 | pre { 13 | font-family: Courier, Consolas, monospace; 14 | font-size: 13px; 15 | line-height: 18px; 16 | tab-interval: 0.5em; 17 | border: 1px solid #C7CFD5; 18 | background-color: #F1F5F9; 19 | color: #666; 20 | padding: 0.3em 1em; 21 | } 22 | 23 | ul { 24 | list-style-type: square; 25 | } 26 | 27 | li { 28 | margin-bottom: 10px; 29 | } 30 | 31 | a, a code { 32 | text-decoration: none; 33 | color: #36C; 34 | } 35 | 36 | a:hover, a:hover code { 37 | text-decoration: underline; 38 | color: #36C; 39 | } 40 | 41 | h2 { 42 | border-bottom: 1px solid #8391A8; 43 | color: #3C4C6C; 44 | font-size: 187%; 45 | font-weight: normal; 46 | margin-top: 1.75em; 47 | padding-bottom: 2px; 48 | } 49 | 50 | table { 51 | margin-bottom: 4em; 52 | border-collapse:collapse; 53 | vertical-align: middle; 54 | } 55 | 56 | td { 57 | border: 1px solid #9BB3CD; 58 | padding: .667em; 59 | font-size: 100%; 60 | } 61 | 62 | th { 63 | border: 1px solid #9BB3CD; 64 | padding: .3em .667em .3em .667em; 65 | background: #93A5BB; 66 | font-size: 103%; 67 | font-weight: bold; 68 | color: white; 69 | text-align: left; 70 | } 71 | 72 | /* @group Common page elements */ 73 | 74 | #top_header { 75 | height: 91px; 76 | left: 0; 77 | min-width: 598px; 78 | position: absolute; 79 | right: 0; 80 | top: 0; 81 | z-index: 900; 82 | } 83 | 84 | #footer { 85 | clear: both; 86 | padding-top: 20px; 87 | text-align: center; 88 | } 89 | 90 | #contents, #overview_contents { 91 | -webkit-overflow-scrolling: touch; 92 | border-top: 1px solid #2B334F; 93 | position: absolute; 94 | top: 91px; 95 | left: 0; 96 | right: 0; 97 | bottom: 0; 98 | overflow-x: hidden; 99 | overflow-y: auto; 100 | padding-left: 2em; 101 | padding-right: 2em; 102 | padding-top: 1em; 103 | min-width: 550px; 104 | } 105 | 106 | #contents.isShowingTOC { 107 | left: 230px; 108 | min-width: 320px; 109 | } 110 | 111 | .copyright { 112 | font-size: 12px; 113 | } 114 | 115 | .generator { 116 | font-size: 11px; 117 | } 118 | 119 | .main-navigation ul li { 120 | display: inline; 121 | margin-left: 15px; 122 | list-style: none; 123 | } 124 | 125 | .navigation-top { 126 | clear: both; 127 | float: right; 128 | } 129 | 130 | .navigation-bottom { 131 | clear: both; 132 | float: right; 133 | margin-top: 20px; 134 | margin-bottom: -10px; 135 | } 136 | 137 | .open > .disclosure { 138 | background-image: url("../img/disclosure_open.png"); 139 | } 140 | 141 | .disclosure { 142 | background: url("../img/disclosure.png") no-repeat scroll 0 0; 143 | } 144 | 145 | .disclosure, .nodisclosure { 146 | display: inline-block; 147 | height: 8px; 148 | margin-right: 5px; 149 | position: relative; 150 | width: 9px; 151 | } 152 | 153 | /* @end */ 154 | 155 | /* @group Header */ 156 | 157 | #top_header #library { 158 | background: url("../img/library_background.png") repeat-x 0 0 #485E78; 159 | background-color: #ccc; 160 | height: 35px; 161 | font-size: 115%; 162 | } 163 | 164 | #top_header #library #libraryTitle { 165 | color: #FFFFFF; 166 | margin-left: 15px; 167 | text-shadow: 0 -1px 0 #485E78; 168 | top: 8px; 169 | position: absolute; 170 | } 171 | 172 | #top_header #library #developerHome { 173 | color: #92979E; 174 | right: 15px; 175 | top: 8px; 176 | position: absolute; 177 | } 178 | 179 | #top_header #library a:hover { 180 | text-decoration: none; 181 | } 182 | 183 | #top_header #title { 184 | background: url("../img/title_background.png") repeat-x 0 0 #8A98A9; 185 | border-bottom: 1px solid #B6B6B6; 186 | height: 25px; 187 | overflow: hidden; 188 | } 189 | 190 | #top_header h1 { 191 | font-size: 115%; 192 | font-weight: normal; 193 | margin: 0; 194 | padding: 3px 0 2px; 195 | text-align: center; 196 | text-shadow: 0 1px 0 #D5D5D5; 197 | white-space: nowrap; 198 | } 199 | 200 | #headerButtons { 201 | background-color: #D8D8D8; 202 | background-image: url("../img/button_bar_background.png"); 203 | border-bottom: 1px solid #EDEDED; 204 | border-top: 1px solid #2B334F; 205 | font-size: 8pt; 206 | height: 28px; 207 | left: 0; 208 | list-style: none outside none; 209 | margin: 0; 210 | overflow: hidden; 211 | padding: 0; 212 | position: absolute; 213 | right: 0; 214 | top: 61px; 215 | } 216 | 217 | #headerButtons li { 218 | background-repeat: no-repeat; 219 | display: inline; 220 | margin-top: 0; 221 | margin-bottom: 0; 222 | padding: 0; 223 | } 224 | 225 | #toc_button button { 226 | border-color: #ACACAC; 227 | border-style: none solid none none; 228 | border-width: 0 1px 0 0; 229 | height: 28px; 230 | margin: 0; 231 | padding-left: 30px; 232 | text-align: left; 233 | width: 230px; 234 | } 235 | 236 | li#jumpto_button { 237 | left: 230px; 238 | margin-left: 0; 239 | position: absolute; 240 | } 241 | 242 | li#jumpto_button select { 243 | height: 22px; 244 | margin: 5px 2px 0 10px; 245 | max-width: 300px; 246 | } 247 | 248 | /* @end */ 249 | 250 | /* @group Table of contents */ 251 | 252 | #tocContainer.isShowingTOC { 253 | border-right: 1px solid #ACACAC; 254 | display: block; 255 | overflow-x: hidden; 256 | overflow-y: auto; 257 | padding: 0; 258 | } 259 | 260 | #tocContainer { 261 | background-color: #E4EBF7; 262 | border-top: 1px solid #2B334F; 263 | bottom: 0; 264 | display: none; 265 | left: 0; 266 | overflow: hidden; 267 | position: absolute; 268 | top: 91px; 269 | width: 229px; 270 | } 271 | 272 | #tocContainer > ul#toc { 273 | font-size: 11px; 274 | margin: 0; 275 | padding: 12px 0 18px; 276 | width: 209px; 277 | -moz-user-select: none; 278 | -webkit-user-select: none; 279 | user-select: none; 280 | } 281 | 282 | #tocContainer > ul#toc > li { 283 | margin: 0; 284 | padding: 0 0 7px 30px; 285 | text-indent: -15px; 286 | } 287 | 288 | #tocContainer > ul#toc > li > .sectionName a { 289 | color: #000000; 290 | font-weight: bold; 291 | } 292 | 293 | #tocContainer > ul#toc > li > .sectionName a:hover { 294 | text-decoration: none; 295 | } 296 | 297 | #tocContainer > ul#toc li.children > ul { 298 | display: none; 299 | height: 0; 300 | } 301 | 302 | #tocContainer > ul#toc > li > ul { 303 | margin: 0; 304 | padding: 0; 305 | } 306 | 307 | #tocContainer > ul#toc > li > ul, ul#toc > li > ul > li { 308 | margin-left: 0; 309 | margin-bottom: 0; 310 | padding-left: 15px; 311 | } 312 | 313 | #tocContainer > ul#toc > li ul { 314 | list-style: none; 315 | margin-right: 0; 316 | padding-right: 0; 317 | } 318 | 319 | #tocContainer > ul#toc li.children.open > ul { 320 | display: block; 321 | height: auto; 322 | margin-left: -15px; 323 | padding-left: 0; 324 | } 325 | 326 | #tocContainer > ul#toc > li > ul, ul#toc > li > ul > li { 327 | margin-left: 0; 328 | padding-left: 15px; 329 | } 330 | 331 | #tocContainer li ul li { 332 | margin-top: 0.583em; 333 | overflow: hidden; 334 | text-overflow: ellipsis; 335 | white-space: nowrap; 336 | } 337 | 338 | #tocContainer li ul li span.sectionName { 339 | white-space: normal; 340 | } 341 | 342 | #tocContainer > ul#toc > li > ul > li > .sectionName a { 343 | font-weight: bold; 344 | } 345 | 346 | #tocContainer > ul#toc > li > ul a { 347 | color: #4F4F4F; 348 | } 349 | 350 | /* @end */ 351 | 352 | /* @group Index formatting */ 353 | 354 | .index-title { 355 | font-size: 13px; 356 | font-weight: normal; 357 | } 358 | 359 | .index-column { 360 | float: left; 361 | width: 30%; 362 | min-width: 200px; 363 | font-size: 11px; 364 | } 365 | 366 | .index-column ul { 367 | margin: 8px 0 0 0; 368 | padding: 0; 369 | list-style: none; 370 | } 371 | 372 | .index-column ul li { 373 | margin: 0 0 3px 0; 374 | padding: 0; 375 | } 376 | 377 | .hierarchy-column { 378 | min-width: 400px; 379 | } 380 | 381 | .hierarchy-column ul { 382 | margin: 3px 0 0 15px; 383 | } 384 | 385 | .hierarchy-column ul li { 386 | list-style-type: square; 387 | } 388 | 389 | /* @end */ 390 | 391 | /* @group Common formatting elements */ 392 | 393 | .title { 394 | font-weight: normal; 395 | font-size: 215%; 396 | margin-top:0; 397 | } 398 | 399 | .subtitle { 400 | font-weight: normal; 401 | font-size: 180%; 402 | color: #3C4C6C; 403 | border-bottom: 1px solid #5088C5; 404 | } 405 | 406 | .subsubtitle { 407 | font-weight: normal; 408 | font-size: 145%; 409 | height: 0.7em; 410 | } 411 | 412 | .note { 413 | border: 1px solid #5088C5; 414 | background-color: white; 415 | margin: 1.667em 0 1.75em 0; 416 | padding: 0 .667em .083em .750em; 417 | } 418 | 419 | .warning { 420 | border: 1px solid #5088C5; 421 | background-color: #F0F3F7; 422 | margin-bottom: 0.5em; 423 | padding: 0.3em 0.8em; 424 | } 425 | 426 | .bug { 427 | border: 1px solid #000; 428 | background-color: #ffffcc; 429 | margin-bottom: 0.5em; 430 | padding: 0.3em 0.8em; 431 | } 432 | 433 | .deprecated { 434 | color: #F60425; 435 | } 436 | 437 | /* @end */ 438 | 439 | /* @group Common layout */ 440 | 441 | .section { 442 | margin-top: 3em; 443 | } 444 | 445 | /* @end */ 446 | 447 | /* @group Object specification section */ 448 | 449 | .section-specification { 450 | margin-left: 2.5em; 451 | margin-right: 2.5em; 452 | font-size: 12px; 453 | } 454 | 455 | .section-specification table { 456 | margin-bottom: 0em; 457 | border-top: 1px solid #d6e0e5; 458 | } 459 | 460 | .section-specification td { 461 | vertical-align: top; 462 | border-bottom: 1px solid #d6e0e5; 463 | border-left-width: 0px; 464 | border-right-width: 0px; 465 | border-top-width: 0px; 466 | padding: .6em; 467 | } 468 | 469 | .section-specification .specification-title { 470 | font-weight: bold; 471 | } 472 | 473 | /* @end */ 474 | 475 | /* @group Tasks section */ 476 | 477 | .task-list { 478 | list-style-type: none; 479 | padding-left: 0px; 480 | } 481 | 482 | .task-list li { 483 | margin-bottom: 3px; 484 | } 485 | 486 | .task-item-suffix { 487 | color: #996; 488 | font-size: 12px; 489 | font-style: italic; 490 | margin-left: 0.5em; 491 | } 492 | 493 | span.tooltip span.tooltip { 494 | font-size: 1.0em; 495 | display: none; 496 | padding: 0.3em; 497 | border: 1px solid #aaa; 498 | background-color: #fdfec8; 499 | color: #000; 500 | text-align: left; 501 | } 502 | 503 | span.tooltip:hover span.tooltip { 504 | display: block; 505 | position: absolute; 506 | margin-left: 2em; 507 | } 508 | 509 | /* @end */ 510 | 511 | /* @group Method section */ 512 | 513 | .section-method { 514 | margin-top: 2.3em; 515 | } 516 | 517 | .method-title { 518 | margin-bottom: 1.5em; 519 | } 520 | 521 | .method-subtitle { 522 | margin-top: 0.7em; 523 | margin-bottom: 0.2em; 524 | } 525 | 526 | .method-subsection p { 527 | margin-top: 0.4em; 528 | margin-bottom: 0.8em; 529 | } 530 | 531 | .method-declaration { 532 | margin-top:1.182em; 533 | margin-bottom:.909em; 534 | } 535 | 536 | .method-declaration code { 537 | font:14px Courier, Consolas, monospace; 538 | color:#000; 539 | } 540 | 541 | .declaration { 542 | color: #000; 543 | } 544 | 545 | .argument-def { 546 | margin-top: 0.3em; 547 | margin-bottom: 0.3em; 548 | } 549 | 550 | .argument-def dd { 551 | margin-left: 1.25em; 552 | } 553 | 554 | .see-also-section ul { 555 | list-style-type: none; 556 | padding-left: 0px; 557 | margin-top: 0; 558 | } 559 | 560 | .see-also-section li { 561 | margin-bottom: 3px; 562 | } 563 | 564 | .declared-in-ref { 565 | color: #666; 566 | } 567 | 568 | #tocContainer.hideInXcode { 569 | display: none; 570 | border: 0px solid black; 571 | } 572 | 573 | #top_header.hideInXcode { 574 | display: none; 575 | } 576 | 577 | #contents.hideInXcode { 578 | border: 0px solid black; 579 | top: 0px; 580 | left: 0px; 581 | } 582 | 583 | /* @end */ 584 | 585 | -------------------------------------------------------------------------------- /Documentation/css/stylesPrint.css: -------------------------------------------------------------------------------- 1 | 2 | header { 3 | display: none; 4 | } 5 | 6 | div.main-navigation, div.navigation-top { 7 | display: none; 8 | } 9 | 10 | div#overview_contents, div#contents.isShowingTOC, div#contents { 11 | overflow: visible; 12 | position: relative; 13 | top: 0px; 14 | border: none; 15 | left: 0; 16 | } 17 | #tocContainer.isShowingTOC { 18 | display: none; 19 | } 20 | nav { 21 | display: none; 22 | } -------------------------------------------------------------------------------- /Documentation/hierarchy.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | INDockableWindow Hierarchy 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |

INDockableWindow

14 | Indragie Karunaratne 15 |
16 | 17 | 20 | 21 |
22 |
23 |
24 | 27 | 32 |
33 | 34 |
35 |

Class Hierarchy

36 | 37 | 88 | 89 |
90 | 91 | 92 | 93 |
94 | 95 |

Protocol References

96 | 101 | 102 | 103 |
104 | 105 |
106 | 109 | 119 |
120 |
121 | 122 | -------------------------------------------------------------------------------- /Documentation/img/button_bar_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/indragiek/INDockableWindow/4b8c5f598615b2aa92d027c34d62c71cb395af3a/Documentation/img/button_bar_background.png -------------------------------------------------------------------------------- /Documentation/img/disclosure.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/indragiek/INDockableWindow/4b8c5f598615b2aa92d027c34d62c71cb395af3a/Documentation/img/disclosure.png -------------------------------------------------------------------------------- /Documentation/img/disclosure_open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/indragiek/INDockableWindow/4b8c5f598615b2aa92d027c34d62c71cb395af3a/Documentation/img/disclosure_open.png -------------------------------------------------------------------------------- /Documentation/img/library_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/indragiek/INDockableWindow/4b8c5f598615b2aa92d027c34d62c71cb395af3a/Documentation/img/library_background.png -------------------------------------------------------------------------------- /Documentation/img/title_background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/indragiek/INDockableWindow/4b8c5f598615b2aa92d027c34d62c71cb395af3a/Documentation/img/title_background.png -------------------------------------------------------------------------------- /Documentation/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | INDockableWindow Reference 6 | 7 | 8 | 9 | 10 | 11 |
12 |
13 |

INDockableWindow

14 | Indragie Karunaratne 15 |
16 | 17 | 20 | 21 |
22 |
23 |
24 | 27 | 32 |
33 | 34 | 35 | 36 | 37 | 38 |
39 |

Class References

40 | 57 |
58 | 59 | 60 | 61 |
62 | 63 |

Protocol References

64 | 69 | 70 | 71 |
72 | 73 |
74 | 77 | 87 |
88 |
89 | 90 | -------------------------------------------------------------------------------- /Example/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // INDockableWindow 4 | // 5 | // Copyright 2013 Indragie Karunaratne. All rights reserved. 6 | // 7 | // Licensed under the BSD License 8 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 9 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 10 | // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 11 | // SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 12 | // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 13 | // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 14 | // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 15 | // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 16 | // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 17 | // 18 | 19 | #import 20 | #import "INDockableWindowController.h" 21 | 22 | @interface AppDelegate : NSObject 23 | 24 | @property (assign) IBOutlet NSWindow *window; 25 | @property (nonatomic, strong) IBOutlet INDockableViewController *primaryViewController; 26 | @property (nonatomic, strong) IBOutlet INDockableViewController *secondaryViewController; 27 | 28 | - (IBAction)attach:(id)sender; 29 | - (IBAction)detach:(id)sender; 30 | @end 31 | -------------------------------------------------------------------------------- /Example/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // INDockableWindow 4 | // 5 | // Copyright 2013 Indragie Karunaratne. All rights reserved. 6 | // 7 | // Licensed under the BSD License 8 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 9 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 10 | // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 11 | // SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 12 | // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 13 | // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 14 | // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 15 | // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 16 | // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 17 | // 18 | 19 | #import "AppDelegate.h" 20 | 21 | @implementation AppDelegate { 22 | INDockableWindowController *_windowController; 23 | } 24 | 25 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 26 | { 27 | _windowController = [INDockableWindowController new]; 28 | _windowController.primaryViewController = self.primaryViewController; 29 | _windowController.splitView.dividerColor = [NSColor blackColor]; 30 | _windowController.titleBarHeight = 40.f; 31 | [_windowController showWindow:nil]; 32 | [_windowController addViewController:self.secondaryViewController attached:YES]; 33 | } 34 | 35 | - (IBAction)attach:(id)sender 36 | { 37 | [_windowController addViewController:self.secondaryViewController attached:YES]; 38 | } 39 | 40 | - (IBAction)detach:(id)sender 41 | { 42 | [_windowController detachViewController:self.secondaryViewController]; 43 | } 44 | @end 45 | -------------------------------------------------------------------------------- /Example/INDockableWindow-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.indragie.${PRODUCT_NAME:rfc1034identifier} 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 © 2013 indragie. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /Example/INDockableWindow-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header for all source files of the 'INDockableWindow' target in the 'INDockableWindow' project 3 | // 4 | 5 | #ifdef __OBJC__ 6 | #import 7 | #endif 8 | -------------------------------------------------------------------------------- /Example/en.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} 2 | {\colortbl;\red255\green255\blue255;} 3 | \paperw9840\paperh8400 4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural 5 | 6 | \f0\b\fs24 \cf0 Engineering: 7 | \b0 \ 8 | Some people\ 9 | \ 10 | 11 | \b Human Interface Design: 12 | \b0 \ 13 | Some other people\ 14 | \ 15 | 16 | \b Testing: 17 | \b0 \ 18 | Hopefully not nobody\ 19 | \ 20 | 21 | \b Documentation: 22 | \b0 \ 23 | Whoever\ 24 | \ 25 | 26 | \b With special thanks to: 27 | \b0 \ 28 | Mom\ 29 | } 30 | -------------------------------------------------------------------------------- /Example/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // INDockableWindow 4 | // 5 | // Created by Indragie Karunaratne on 2013-01-19. 6 | // Copyright (c) 2013 indragie. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, char *argv[]) 12 | { 13 | return NSApplicationMain(argc, (const char **)argv); 14 | } 15 | -------------------------------------------------------------------------------- /INDockableWindow.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'INDockableWindow' 3 | s.version = '1.0' 4 | s.summary = 'A window to which other views can be docked to and separated into their own windows ' 5 | s.homepage = 'https://github.com/indragiek/INDockableWindow' 6 | s.author = { 'Indragie Karunaratne' => 'i@indragie.com' } 7 | s.source_files = 'INDockableWindow' 8 | s.source = { :git => 'https://github.com/indragiek/INDockableWindow.git', :tag => 'v1.0' } 9 | s.platform = :osx 10 | s.requires_arc = true 11 | s.license = { :type => 'MIT' } 12 | s.dependency 'INAppStoreWindow' 13 | end -------------------------------------------------------------------------------- /INDockableWindow.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 0314FBFD16ADCE8800E73E86 /* INDockableAuxiliaryWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 0314FBF016ADCE8800E73E86 /* INDockableAuxiliaryWindow.m */; }; 11 | 0314FBFE16ADCE8800E73E86 /* INDockableDetachControl.m in Sources */ = {isa = PBXBuildFile; fileRef = 0314FBF216ADCE8800E73E86 /* INDockableDetachControl.m */; }; 12 | 0314FBFF16ADCE8800E73E86 /* INDockablePrimaryWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 0314FBF416ADCE8800E73E86 /* INDockablePrimaryWindow.m */; }; 13 | 0314FC0016ADCE8800E73E86 /* INDockableSplitView.m in Sources */ = {isa = PBXBuildFile; fileRef = 0314FBF616ADCE8800E73E86 /* INDockableSplitView.m */; }; 14 | 0314FC0116ADCE8800E73E86 /* INDockableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0314FBF816ADCE8800E73E86 /* INDockableViewController.m */; }; 15 | 0314FC0216ADCE8800E73E86 /* INDockableWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 0314FBFA16ADCE8800E73E86 /* INDockableWindow.m */; }; 16 | 0314FC0316ADCE8800E73E86 /* INDockableWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0314FBFC16ADCE8800E73E86 /* INDockableWindowController.m */; }; 17 | 034754FE16ACF53100747D93 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 034754FC16ACF53100747D93 /* AppDelegate.m */; }; 18 | 0347550116ACF53600747D93 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 034754FF16ACF53600747D93 /* MainMenu.xib */; }; 19 | 0347550616ACF54000747D93 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 0347550416ACF54000747D93 /* main.m */; }; 20 | 0347550B16ACF54600747D93 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 0347550716ACF54600747D93 /* Credits.rtf */; }; 21 | 0347550C16ACF54600747D93 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0347550916ACF54600747D93 /* InfoPlist.strings */; }; 22 | 03D8036918832C8900DB33C5 /* INAppStoreWindow.m in Sources */ = {isa = PBXBuildFile; fileRef = 03D8036618832C8900DB33C5 /* INAppStoreWindow.m */; }; 23 | 03D8036A18832C8900DB33C5 /* INWindowButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 03D8036818832C8900DB33C5 /* INWindowButton.m */; }; 24 | 03E1B15816AB5DD60018E31F /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 03E1B15716AB5DD60018E31F /* Cocoa.framework */; }; 25 | 211E4E451749096100BAA283 /* INWindowFrameAnimation.m in Sources */ = {isa = PBXBuildFile; fileRef = 211E4E421749096100BAA283 /* INWindowFrameAnimation.m */; }; 26 | 211E4E461749096100BAA283 /* NSView+INImagingAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 211E4E441749096100BAA283 /* NSView+INImagingAdditions.m */; }; 27 | /* End PBXBuildFile section */ 28 | 29 | /* Begin PBXFileReference section */ 30 | 0314FBEF16ADCE8800E73E86 /* INDockableAuxiliaryWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = INDockableAuxiliaryWindow.h; path = INDockableWindow/INDockableAuxiliaryWindow.h; sourceTree = ""; }; 31 | 0314FBF016ADCE8800E73E86 /* INDockableAuxiliaryWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = INDockableAuxiliaryWindow.m; path = INDockableWindow/INDockableAuxiliaryWindow.m; sourceTree = ""; }; 32 | 0314FBF116ADCE8800E73E86 /* INDockableDetachControl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = INDockableDetachControl.h; path = INDockableWindow/INDockableDetachControl.h; sourceTree = ""; }; 33 | 0314FBF216ADCE8800E73E86 /* INDockableDetachControl.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = INDockableDetachControl.m; path = INDockableWindow/INDockableDetachControl.m; sourceTree = ""; }; 34 | 0314FBF316ADCE8800E73E86 /* INDockablePrimaryWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = INDockablePrimaryWindow.h; path = INDockableWindow/INDockablePrimaryWindow.h; sourceTree = ""; }; 35 | 0314FBF416ADCE8800E73E86 /* INDockablePrimaryWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = INDockablePrimaryWindow.m; path = INDockableWindow/INDockablePrimaryWindow.m; sourceTree = ""; }; 36 | 0314FBF516ADCE8800E73E86 /* INDockableSplitView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = INDockableSplitView.h; path = INDockableWindow/INDockableSplitView.h; sourceTree = ""; }; 37 | 0314FBF616ADCE8800E73E86 /* INDockableSplitView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = INDockableSplitView.m; path = INDockableWindow/INDockableSplitView.m; sourceTree = ""; }; 38 | 0314FBF716ADCE8800E73E86 /* INDockableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = INDockableViewController.h; path = INDockableWindow/INDockableViewController.h; sourceTree = ""; }; 39 | 0314FBF816ADCE8800E73E86 /* INDockableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = INDockableViewController.m; path = INDockableWindow/INDockableViewController.m; sourceTree = ""; }; 40 | 0314FBF916ADCE8800E73E86 /* INDockableWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = INDockableWindow.h; path = INDockableWindow/INDockableWindow.h; sourceTree = ""; }; 41 | 0314FBFA16ADCE8800E73E86 /* INDockableWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = INDockableWindow.m; path = INDockableWindow/INDockableWindow.m; sourceTree = ""; }; 42 | 0314FBFB16ADCE8800E73E86 /* INDockableWindowController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = INDockableWindowController.h; path = INDockableWindow/INDockableWindowController.h; sourceTree = ""; }; 43 | 0314FBFC16ADCE8800E73E86 /* INDockableWindowController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = INDockableWindowController.m; path = INDockableWindow/INDockableWindowController.m; sourceTree = ""; }; 44 | 034754FC16ACF53100747D93 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = Example/AppDelegate.m; sourceTree = SOURCE_ROOT; }; 45 | 034754FD16ACF53100747D93 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AppDelegate.h; path = Example/AppDelegate.h; sourceTree = SOURCE_ROOT; }; 46 | 0347550016ACF53600747D93 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = Example/en.lproj/MainMenu.xib; sourceTree = SOURCE_ROOT; }; 47 | 0347550216ACF54000747D93 /* INDockableWindow-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "INDockableWindow-Info.plist"; path = "Example/INDockableWindow-Info.plist"; sourceTree = SOURCE_ROOT; }; 48 | 0347550316ACF54000747D93 /* INDockableWindow-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "INDockableWindow-Prefix.pch"; path = "Example/INDockableWindow-Prefix.pch"; sourceTree = SOURCE_ROOT; }; 49 | 0347550416ACF54000747D93 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = Example/main.m; sourceTree = SOURCE_ROOT; }; 50 | 0347550816ACF54600747D93 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = Example/en.lproj/Credits.rtf; sourceTree = SOURCE_ROOT; }; 51 | 0347550A16ACF54600747D93 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = Example/en.lproj/InfoPlist.strings; sourceTree = SOURCE_ROOT; }; 52 | 03D8036518832C8900DB33C5 /* INAppStoreWindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = INAppStoreWindow.h; sourceTree = ""; }; 53 | 03D8036618832C8900DB33C5 /* INAppStoreWindow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = INAppStoreWindow.m; sourceTree = ""; }; 54 | 03D8036718832C8900DB33C5 /* INWindowButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = INWindowButton.h; sourceTree = ""; }; 55 | 03D8036818832C8900DB33C5 /* INWindowButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = INWindowButton.m; sourceTree = ""; }; 56 | 03E1B15416AB5DD60018E31F /* INDockableWindow.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = INDockableWindow.app; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | 03E1B15716AB5DD60018E31F /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 58 | 03E1B15A16AB5DD60018E31F /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 59 | 03E1B15B16AB5DD60018E31F /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 60 | 03E1B15C16AB5DD60018E31F /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 61 | 211E4E411749096100BAA283 /* INWindowFrameAnimation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = INWindowFrameAnimation.h; path = INDockableWindow/INWindowFrameAnimation.h; sourceTree = ""; }; 62 | 211E4E421749096100BAA283 /* INWindowFrameAnimation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = INWindowFrameAnimation.m; path = INDockableWindow/INWindowFrameAnimation.m; sourceTree = ""; }; 63 | 211E4E431749096100BAA283 /* NSView+INImagingAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSView+INImagingAdditions.h"; path = "INDockableWindow/NSView+INImagingAdditions.h"; sourceTree = ""; }; 64 | 211E4E441749096100BAA283 /* NSView+INImagingAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSView+INImagingAdditions.m"; path = "INDockableWindow/NSView+INImagingAdditions.m"; sourceTree = ""; }; 65 | /* End PBXFileReference section */ 66 | 67 | /* Begin PBXFrameworksBuildPhase section */ 68 | 03E1B15116AB5DD60018E31F /* Frameworks */ = { 69 | isa = PBXFrameworksBuildPhase; 70 | buildActionMask = 2147483647; 71 | files = ( 72 | 03E1B15816AB5DD60018E31F /* Cocoa.framework in Frameworks */, 73 | ); 74 | runOnlyForDeploymentPostprocessing = 0; 75 | }; 76 | /* End PBXFrameworksBuildPhase section */ 77 | 78 | /* Begin PBXGroup section */ 79 | 03D8036418832C8900DB33C5 /* INAppStoreWindow */ = { 80 | isa = PBXGroup; 81 | children = ( 82 | 03D8036518832C8900DB33C5 /* INAppStoreWindow.h */, 83 | 03D8036618832C8900DB33C5 /* INAppStoreWindow.m */, 84 | 03D8036718832C8900DB33C5 /* INWindowButton.h */, 85 | 03D8036818832C8900DB33C5 /* INWindowButton.m */, 86 | ); 87 | name = INAppStoreWindow; 88 | path = External/INAppStoreWindow/INAppStoreWindow; 89 | sourceTree = ""; 90 | }; 91 | 03E1B14B16AB5DD60018E31F = { 92 | isa = PBXGroup; 93 | children = ( 94 | 03D8036418832C8900DB33C5 /* INAppStoreWindow */, 95 | 03E1B17416AB5DE00018E31F /* INDockableWindow */, 96 | 03E1B15D16AB5DD60018E31F /* Example */, 97 | 03E1B15616AB5DD60018E31F /* Frameworks */, 98 | 03E1B15516AB5DD60018E31F /* Products */, 99 | ); 100 | sourceTree = ""; 101 | }; 102 | 03E1B15516AB5DD60018E31F /* Products */ = { 103 | isa = PBXGroup; 104 | children = ( 105 | 03E1B15416AB5DD60018E31F /* INDockableWindow.app */, 106 | ); 107 | name = Products; 108 | sourceTree = ""; 109 | }; 110 | 03E1B15616AB5DD60018E31F /* Frameworks */ = { 111 | isa = PBXGroup; 112 | children = ( 113 | 03E1B15716AB5DD60018E31F /* Cocoa.framework */, 114 | 03E1B15916AB5DD60018E31F /* Other Frameworks */, 115 | ); 116 | name = Frameworks; 117 | sourceTree = ""; 118 | }; 119 | 03E1B15916AB5DD60018E31F /* Other Frameworks */ = { 120 | isa = PBXGroup; 121 | children = ( 122 | 03E1B15A16AB5DD60018E31F /* AppKit.framework */, 123 | 03E1B15B16AB5DD60018E31F /* CoreData.framework */, 124 | 03E1B15C16AB5DD60018E31F /* Foundation.framework */, 125 | ); 126 | name = "Other Frameworks"; 127 | sourceTree = ""; 128 | }; 129 | 03E1B15D16AB5DD60018E31F /* Example */ = { 130 | isa = PBXGroup; 131 | children = ( 132 | 034754FC16ACF53100747D93 /* AppDelegate.m */, 133 | 034754FD16ACF53100747D93 /* AppDelegate.h */, 134 | 034754FF16ACF53600747D93 /* MainMenu.xib */, 135 | 03E1B15E16AB5DD60018E31F /* Supporting Files */, 136 | ); 137 | name = Example; 138 | path = INDockableWindow; 139 | sourceTree = ""; 140 | }; 141 | 03E1B15E16AB5DD60018E31F /* Supporting Files */ = { 142 | isa = PBXGroup; 143 | children = ( 144 | 0347550216ACF54000747D93 /* INDockableWindow-Info.plist */, 145 | 0347550316ACF54000747D93 /* INDockableWindow-Prefix.pch */, 146 | 0347550416ACF54000747D93 /* main.m */, 147 | 0347550716ACF54600747D93 /* Credits.rtf */, 148 | 0347550916ACF54600747D93 /* InfoPlist.strings */, 149 | ); 150 | name = "Supporting Files"; 151 | sourceTree = ""; 152 | }; 153 | 03E1B17416AB5DE00018E31F /* INDockableWindow */ = { 154 | isa = PBXGroup; 155 | children = ( 156 | 0314FBEF16ADCE8800E73E86 /* INDockableAuxiliaryWindow.h */, 157 | 0314FBF016ADCE8800E73E86 /* INDockableAuxiliaryWindow.m */, 158 | 0314FBF116ADCE8800E73E86 /* INDockableDetachControl.h */, 159 | 0314FBF216ADCE8800E73E86 /* INDockableDetachControl.m */, 160 | 0314FBF316ADCE8800E73E86 /* INDockablePrimaryWindow.h */, 161 | 0314FBF416ADCE8800E73E86 /* INDockablePrimaryWindow.m */, 162 | 0314FBF516ADCE8800E73E86 /* INDockableSplitView.h */, 163 | 0314FBF616ADCE8800E73E86 /* INDockableSplitView.m */, 164 | 0314FBF716ADCE8800E73E86 /* INDockableViewController.h */, 165 | 0314FBF816ADCE8800E73E86 /* INDockableViewController.m */, 166 | 0314FBF916ADCE8800E73E86 /* INDockableWindow.h */, 167 | 0314FBFA16ADCE8800E73E86 /* INDockableWindow.m */, 168 | 0314FBFB16ADCE8800E73E86 /* INDockableWindowController.h */, 169 | 0314FBFC16ADCE8800E73E86 /* INDockableWindowController.m */, 170 | 211E4E411749096100BAA283 /* INWindowFrameAnimation.h */, 171 | 211E4E421749096100BAA283 /* INWindowFrameAnimation.m */, 172 | 211E4E431749096100BAA283 /* NSView+INImagingAdditions.h */, 173 | 211E4E441749096100BAA283 /* NSView+INImagingAdditions.m */, 174 | ); 175 | name = INDockableWindow; 176 | sourceTree = ""; 177 | }; 178 | /* End PBXGroup section */ 179 | 180 | /* Begin PBXNativeTarget section */ 181 | 03E1B15316AB5DD60018E31F /* INDockableWindow */ = { 182 | isa = PBXNativeTarget; 183 | buildConfigurationList = 03E1B17116AB5DD60018E31F /* Build configuration list for PBXNativeTarget "INDockableWindow" */; 184 | buildPhases = ( 185 | 03E1B15016AB5DD60018E31F /* Sources */, 186 | 03E1B15116AB5DD60018E31F /* Frameworks */, 187 | 03E1B15216AB5DD60018E31F /* Resources */, 188 | ); 189 | buildRules = ( 190 | ); 191 | dependencies = ( 192 | ); 193 | name = INDockableWindow; 194 | productName = INDockableWindow; 195 | productReference = 03E1B15416AB5DD60018E31F /* INDockableWindow.app */; 196 | productType = "com.apple.product-type.application"; 197 | }; 198 | /* End PBXNativeTarget section */ 199 | 200 | /* Begin PBXProject section */ 201 | 03E1B14C16AB5DD60018E31F /* Project object */ = { 202 | isa = PBXProject; 203 | attributes = { 204 | LastUpgradeCheck = 0460; 205 | ORGANIZATIONNAME = indragie; 206 | }; 207 | buildConfigurationList = 03E1B14F16AB5DD60018E31F /* Build configuration list for PBXProject "INDockableWindow" */; 208 | compatibilityVersion = "Xcode 3.2"; 209 | developmentRegion = English; 210 | hasScannedForEncodings = 0; 211 | knownRegions = ( 212 | en, 213 | ); 214 | mainGroup = 03E1B14B16AB5DD60018E31F; 215 | productRefGroup = 03E1B15516AB5DD60018E31F /* Products */; 216 | projectDirPath = ""; 217 | projectRoot = ""; 218 | targets = ( 219 | 03E1B15316AB5DD60018E31F /* INDockableWindow */, 220 | ); 221 | }; 222 | /* End PBXProject section */ 223 | 224 | /* Begin PBXResourcesBuildPhase section */ 225 | 03E1B15216AB5DD60018E31F /* Resources */ = { 226 | isa = PBXResourcesBuildPhase; 227 | buildActionMask = 2147483647; 228 | files = ( 229 | 0347550116ACF53600747D93 /* MainMenu.xib in Resources */, 230 | 0347550B16ACF54600747D93 /* Credits.rtf in Resources */, 231 | 0347550C16ACF54600747D93 /* InfoPlist.strings in Resources */, 232 | ); 233 | runOnlyForDeploymentPostprocessing = 0; 234 | }; 235 | /* End PBXResourcesBuildPhase section */ 236 | 237 | /* Begin PBXSourcesBuildPhase section */ 238 | 03E1B15016AB5DD60018E31F /* Sources */ = { 239 | isa = PBXSourcesBuildPhase; 240 | buildActionMask = 2147483647; 241 | files = ( 242 | 034754FE16ACF53100747D93 /* AppDelegate.m in Sources */, 243 | 0347550616ACF54000747D93 /* main.m in Sources */, 244 | 0314FBFD16ADCE8800E73E86 /* INDockableAuxiliaryWindow.m in Sources */, 245 | 0314FBFE16ADCE8800E73E86 /* INDockableDetachControl.m in Sources */, 246 | 03D8036A18832C8900DB33C5 /* INWindowButton.m in Sources */, 247 | 0314FBFF16ADCE8800E73E86 /* INDockablePrimaryWindow.m in Sources */, 248 | 0314FC0016ADCE8800E73E86 /* INDockableSplitView.m in Sources */, 249 | 03D8036918832C8900DB33C5 /* INAppStoreWindow.m in Sources */, 250 | 0314FC0116ADCE8800E73E86 /* INDockableViewController.m in Sources */, 251 | 0314FC0216ADCE8800E73E86 /* INDockableWindow.m in Sources */, 252 | 0314FC0316ADCE8800E73E86 /* INDockableWindowController.m in Sources */, 253 | 211E4E451749096100BAA283 /* INWindowFrameAnimation.m in Sources */, 254 | 211E4E461749096100BAA283 /* NSView+INImagingAdditions.m in Sources */, 255 | ); 256 | runOnlyForDeploymentPostprocessing = 0; 257 | }; 258 | /* End PBXSourcesBuildPhase section */ 259 | 260 | /* Begin PBXVariantGroup section */ 261 | 034754FF16ACF53600747D93 /* MainMenu.xib */ = { 262 | isa = PBXVariantGroup; 263 | children = ( 264 | 0347550016ACF53600747D93 /* en */, 265 | ); 266 | name = MainMenu.xib; 267 | sourceTree = ""; 268 | }; 269 | 0347550716ACF54600747D93 /* Credits.rtf */ = { 270 | isa = PBXVariantGroup; 271 | children = ( 272 | 0347550816ACF54600747D93 /* en */, 273 | ); 274 | name = Credits.rtf; 275 | sourceTree = ""; 276 | }; 277 | 0347550916ACF54600747D93 /* InfoPlist.strings */ = { 278 | isa = PBXVariantGroup; 279 | children = ( 280 | 0347550A16ACF54600747D93 /* en */, 281 | ); 282 | name = InfoPlist.strings; 283 | sourceTree = ""; 284 | }; 285 | /* End PBXVariantGroup section */ 286 | 287 | /* Begin XCBuildConfiguration section */ 288 | 03E1B16F16AB5DD60018E31F /* Debug */ = { 289 | isa = XCBuildConfiguration; 290 | buildSettings = { 291 | ALWAYS_SEARCH_USER_PATHS = NO; 292 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 293 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 294 | CLANG_CXX_LIBRARY = "libc++"; 295 | CLANG_ENABLE_OBJC_ARC = YES; 296 | CLANG_WARN_CONSTANT_CONVERSION = YES; 297 | CLANG_WARN_EMPTY_BODY = YES; 298 | CLANG_WARN_ENUM_CONVERSION = YES; 299 | CLANG_WARN_INT_CONVERSION = YES; 300 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 301 | COPY_PHASE_STRIP = NO; 302 | GCC_C_LANGUAGE_STANDARD = gnu99; 303 | GCC_DYNAMIC_NO_PIC = NO; 304 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 305 | GCC_OPTIMIZATION_LEVEL = 0; 306 | GCC_PREPROCESSOR_DEFINITIONS = ( 307 | "DEBUG=1", 308 | "$(inherited)", 309 | ); 310 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 311 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 312 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 313 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 314 | GCC_WARN_UNUSED_VARIABLE = YES; 315 | MACOSX_DEPLOYMENT_TARGET = 10.8; 316 | ONLY_ACTIVE_ARCH = YES; 317 | SDKROOT = macosx; 318 | }; 319 | name = Debug; 320 | }; 321 | 03E1B17016AB5DD60018E31F /* Release */ = { 322 | isa = XCBuildConfiguration; 323 | buildSettings = { 324 | ALWAYS_SEARCH_USER_PATHS = NO; 325 | ARCHS = "$(ARCHS_STANDARD_64_BIT)"; 326 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 327 | CLANG_CXX_LIBRARY = "libc++"; 328 | CLANG_ENABLE_OBJC_ARC = YES; 329 | CLANG_WARN_CONSTANT_CONVERSION = YES; 330 | CLANG_WARN_EMPTY_BODY = YES; 331 | CLANG_WARN_ENUM_CONVERSION = YES; 332 | CLANG_WARN_INT_CONVERSION = YES; 333 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 334 | COPY_PHASE_STRIP = YES; 335 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 336 | GCC_C_LANGUAGE_STANDARD = gnu99; 337 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 338 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 339 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 340 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 341 | GCC_WARN_UNUSED_VARIABLE = YES; 342 | MACOSX_DEPLOYMENT_TARGET = 10.8; 343 | SDKROOT = macosx; 344 | }; 345 | name = Release; 346 | }; 347 | 03E1B17216AB5DD60018E31F /* Debug */ = { 348 | isa = XCBuildConfiguration; 349 | buildSettings = { 350 | COMBINE_HIDPI_IMAGES = YES; 351 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 352 | GCC_PREFIX_HEADER = "Example/INDockableWindow-Prefix.pch"; 353 | INFOPLIST_FILE = "Example/INDockableWindow-Info.plist"; 354 | PRODUCT_NAME = "$(TARGET_NAME)"; 355 | WRAPPER_EXTENSION = app; 356 | }; 357 | name = Debug; 358 | }; 359 | 03E1B17316AB5DD60018E31F /* Release */ = { 360 | isa = XCBuildConfiguration; 361 | buildSettings = { 362 | COMBINE_HIDPI_IMAGES = YES; 363 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 364 | GCC_PREFIX_HEADER = "Example/INDockableWindow-Prefix.pch"; 365 | INFOPLIST_FILE = "Example/INDockableWindow-Info.plist"; 366 | PRODUCT_NAME = "$(TARGET_NAME)"; 367 | WRAPPER_EXTENSION = app; 368 | }; 369 | name = Release; 370 | }; 371 | /* End XCBuildConfiguration section */ 372 | 373 | /* Begin XCConfigurationList section */ 374 | 03E1B14F16AB5DD60018E31F /* Build configuration list for PBXProject "INDockableWindow" */ = { 375 | isa = XCConfigurationList; 376 | buildConfigurations = ( 377 | 03E1B16F16AB5DD60018E31F /* Debug */, 378 | 03E1B17016AB5DD60018E31F /* Release */, 379 | ); 380 | defaultConfigurationIsVisible = 0; 381 | defaultConfigurationName = Release; 382 | }; 383 | 03E1B17116AB5DD60018E31F /* Build configuration list for PBXNativeTarget "INDockableWindow" */ = { 384 | isa = XCConfigurationList; 385 | buildConfigurations = ( 386 | 03E1B17216AB5DD60018E31F /* Debug */, 387 | 03E1B17316AB5DD60018E31F /* Release */, 388 | ); 389 | defaultConfigurationIsVisible = 0; 390 | defaultConfigurationName = Release; 391 | }; 392 | /* End XCConfigurationList section */ 393 | }; 394 | rootObject = 03E1B14C16AB5DD60018E31F /* Project object */; 395 | } 396 | -------------------------------------------------------------------------------- /INDockableWindow.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /INDockableWindow.xcodeproj/xcuserdata/indragie.xcuserdatad/xcschemes/INDockableWindow.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 51 | 52 | 58 | 59 | 60 | 61 | 62 | 63 | 69 | 70 | 76 | 77 | 78 | 79 | 81 | 82 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /INDockableWindow.xcodeproj/xcuserdata/indragie.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | INDockableWindow.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 03E1B15316AB5DD60018E31F 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /INDockableWindow/INDockableAuxiliaryWindow.h: -------------------------------------------------------------------------------- 1 | // 2 | // INDockableAuxiliaryWindow.h 3 | // INDockableWindow 4 | // 5 | // Copyright (c) 2013, Indragie Karunaratne. All rights reserved. 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 8 | // software and associated documentation files (the "Software"), to deal in the Software 9 | // without restriction, including without limitation the rights to use, copy, modify, merge, 10 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 11 | // to whom the Software is furnished to do so, subject to the following conditions: 12 | 13 | // The above copyright notice and this permission notice shall be included in all copies or 14 | // substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 17 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 19 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 20 | // OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | 23 | #import "INDockableWindow.h" 24 | 25 | @class INDockableViewController; 26 | /** The auxiliary window class for displaying detached views */ 27 | @interface INDockableAuxiliaryWindow : INDockableWindow 28 | /** 29 | The dockabie view controller that this auxiliary window contains. 30 | */ 31 | @property (nonatomic, strong, readonly) INDockableViewController *viewController; 32 | @end 33 | -------------------------------------------------------------------------------- /INDockableWindow/INDockableAuxiliaryWindow.m: -------------------------------------------------------------------------------- 1 | // 2 | // INDockableAuxiliaryWindow.m 3 | // INDockableWindow 4 | // 5 | // Copyright (c) 2013, Indragie Karunaratne. All rights reserved. 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 8 | // software and associated documentation files (the "Software"), to deal in the Software 9 | // without restriction, including without limitation the rights to use, copy, modify, merge, 10 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 11 | // to whom the Software is furnished to do so, subject to the following conditions: 12 | 13 | // The above copyright notice and this permission notice shall be included in all copies or 14 | // substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 17 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 19 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 20 | // OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | #import "INDockableAuxiliaryWindow.h" 23 | #import "INDockableViewController.h" 24 | #import "NSView+INImagingAdditions.h" 25 | 26 | @interface INDockableWindow (Private) 27 | @property (nonatomic, assign, readwrite) INDockableWindowController *dockableWindowController; 28 | @end 29 | 30 | @implementation INDockableAuxiliaryWindow { 31 | NSImageView *_contentImageView; 32 | NSImageView *_titleBarImageView; 33 | } 34 | 35 | - (id)initWithViewController:(INDockableViewController *)viewController styleMask:(NSUInteger)styleMask; 36 | { 37 | if ((self = [super initWithContentRect:viewController.view.bounds styleMask:styleMask backing:NSBackingStoreBuffered defer:NO])) { 38 | _viewController = viewController; 39 | self.dockableWindowController = viewController.dockableWindowController; 40 | } 41 | return self; 42 | } 43 | 44 | #pragma mark - Private 45 | 46 | - (void)showViewControllerImage 47 | { 48 | NSView *contentView = self.viewController.view; 49 | NSView *titleBarView = self.viewController.titleBarView; 50 | if (contentView) { 51 | _contentImageView = [[NSImageView alloc] initWithFrame:[self.contentView bounds]]; 52 | _contentImageView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; 53 | _contentImageView.image = contentView.in_image; 54 | [self.contentView addSubview:_contentImageView positioned:NSWindowBelow relativeTo:nil]; 55 | } 56 | if (titleBarView) { 57 | _titleBarImageView = [[NSImageView alloc] initWithFrame:[self.titleBarView bounds]]; 58 | _titleBarImageView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; 59 | _titleBarImageView.image = titleBarView.in_image; 60 | [self.titleBarView addSubview:_titleBarImageView positioned:NSWindowBelow relativeTo:nil]; 61 | } 62 | if (_viewController.view.superview == self.contentView) { 63 | [_viewController.view removeFromSuperview]; 64 | [_viewController.titleBarView removeFromSuperview]; 65 | } 66 | } 67 | 68 | - (void)showViewController 69 | { 70 | NSView *view = _viewController.view; 71 | if (view) { 72 | view.frame = [self.contentView bounds]; 73 | view.autoresizingMask = NSViewHeightSizable | NSViewWidthSizable; 74 | [self.contentView addSubview:view positioned:NSWindowBelow relativeTo:nil]; 75 | } 76 | 77 | NSView *titleBarView = _viewController.titleBarView; 78 | if (titleBarView) { 79 | titleBarView.frame = [self.titleBarView bounds]; 80 | titleBarView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; 81 | [self.titleBarView addSubview:titleBarView positioned:NSWindowBelow relativeTo:nil]; 82 | } 83 | 84 | [_contentImageView removeFromSuperview]; 85 | [_titleBarImageView removeFromSuperview]; 86 | _contentImageView = nil; 87 | _titleBarImageView = nil; 88 | } 89 | @end 90 | -------------------------------------------------------------------------------- /INDockableWindow/INDockableDetachControl.h: -------------------------------------------------------------------------------- 1 | // 2 | // INDockableDetachControl.h 3 | // INDockableWindow 4 | // 5 | // Copyright (c) 2013, Indragie Karunaratne. All rights reserved. 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 8 | // software and associated documentation files (the "Software"), to deal in the Software 9 | // without restriction, including without limitation the rights to use, copy, modify, merge, 10 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 11 | // to whom the Software is furnished to do so, subject to the following conditions: 12 | 13 | // The above copyright notice and this permission notice shall be included in all copies or 14 | // substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 17 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 19 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 20 | // OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | 23 | #import 24 | 25 | extern NSString* const INDockableDetachControlTriggerNotification; 26 | 27 | @class INDockableViewController; 28 | /** 29 | Control that can be dragged to trigger a detach of its parent view controller from the primary window. 30 | */ 31 | @interface INDockableDetachControl : NSView 32 | /** 33 | The detach control image. 34 | */ 35 | @property (nonatomic, strong) NSImage *image; 36 | 37 | /** 38 | The minimum drag distance to trigger a detach. Default is 10px. 39 | */ 40 | @property (nonatomic, assign) CGFloat minimumDragDistance; 41 | 42 | /** 43 | Whether the control fades in on mouse hover. Default is NO. 44 | */ 45 | @property (nonatomic, assign) BOOL fadeOnHover; 46 | 47 | /** 48 | The view controller that owns this detach control 49 | */ 50 | @property (nonatomic, assign, readonly) INDockableViewController *viewController; 51 | @end 52 | -------------------------------------------------------------------------------- /INDockableWindow/INDockableDetachControl.m: -------------------------------------------------------------------------------- 1 | // 2 | // INDockableDetachControl.m 3 | // INDockableWindow 4 | // 5 | // Copyright (c) 2013, Indragie Karunaratne. All rights reserved. 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 8 | // software and associated documentation files (the "Software"), to deal in the Software 9 | // without restriction, including without limitation the rights to use, copy, modify, merge, 10 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 11 | // to whom the Software is furnished to do so, subject to the following conditions: 12 | 13 | // The above copyright notice and this permission notice shall be included in all copies or 14 | // substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 17 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 19 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 20 | // OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | 23 | #import "INDockableDetachControl.h" 24 | #import "INDockableViewController.h" 25 | 26 | NSString* const INDockableDetachControlTriggerNotification = @"INDockableDetachControlTriggerNotification"; 27 | 28 | @interface INDockableDetachControl () 29 | @property (nonatomic, assign, readwrite) INDockableViewController *viewController; 30 | @end 31 | 32 | @implementation INDockableDetachControl { 33 | NSImageView *_imageView; 34 | NSTrackingArea *_trackingArea; 35 | NSPoint _initialPoint; 36 | BOOL _trackingTriggerAction; 37 | } 38 | 39 | - (id)initWithFrame:(NSRect)frame 40 | { 41 | if ((self = [super initWithFrame:frame])) { 42 | _imageView = [[NSImageView alloc] initWithFrame:self.bounds]; 43 | _imageView.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable; 44 | [self addSubview:_imageView]; 45 | _minimumDragDistance = 10.f; 46 | } 47 | return self; 48 | } 49 | 50 | - (void)updateTrackingAreas 51 | { 52 | [super updateTrackingAreas]; 53 | if (_trackingArea) { 54 | [self removeTrackingArea:_trackingArea]; 55 | } 56 | if (self.fadeOnHover) { 57 | _trackingArea = [[NSTrackingArea alloc] initWithRect:self.bounds options:NSTrackingActiveInKeyWindow | NSTrackingMouseEnteredAndExited owner:self userInfo:nil]; 58 | [self addTrackingArea:_trackingArea]; 59 | } 60 | } 61 | 62 | - (void)viewDidMoveToWindow 63 | { 64 | [super viewDidMoveToWindow]; 65 | [self updateTrackingAreas]; 66 | } 67 | 68 | #pragma mark - Mouse Events 69 | 70 | - (void)mouseEntered:(NSEvent *)theEvent 71 | { 72 | [super mouseEntered:theEvent]; 73 | [_imageView.animator setAlphaValue:1.f]; 74 | } 75 | 76 | - (void)mouseExited:(NSEvent *)theEvent 77 | { 78 | [super mouseExited:theEvent]; 79 | [_imageView.animator setAlphaValue:0.f]; 80 | } 81 | 82 | - (void)mouseDown:(NSEvent *)theEvent 83 | { 84 | [super mouseDragged:theEvent]; 85 | _initialPoint = [self convertPoint:[theEvent locationInWindow] fromView:nil]; 86 | _trackingTriggerAction = YES; 87 | } 88 | 89 | CGFloat INDistanceBetweenPoints(NSPoint a, NSPoint b) 90 | { 91 | CGFloat dx = a.x - b.x; 92 | CGFloat dy = a.y - b.y; 93 | return sqrt((dx * dx) + (dy * dy)); 94 | } 95 | 96 | - (void)mouseDragged:(NSEvent *)theEvent 97 | { 98 | if ([self.window styleMask] & NSFullScreenWindowMask) return; 99 | NSPoint point = [self convertPoint:[theEvent locationInWindow] fromView:nil]; 100 | if (_trackingTriggerAction) { 101 | if (INDistanceBetweenPoints(_initialPoint, point) >= self.minimumDragDistance) { 102 | [[NSNotificationCenter defaultCenter] postNotificationName:INDockableDetachControlTriggerNotification object:self.viewController userInfo:nil]; 103 | _trackingTriggerAction = NO; 104 | // At this point, the events in the event loop are still using the coordinates of the primary window 105 | // even though the window has changed. Therefore, events need to be synthesized to convert the events 106 | // into new events with the proper coordinates for the new window. 107 | [self moveParentWindowWithEvent:[self.class synthesisedEventWithEvent:theEvent forWindow:self.window]]; 108 | } 109 | } else { 110 | [self moveParentWindowWithEvent:theEvent]; 111 | } 112 | } 113 | 114 | - (void)moveParentWindowWithEvent:(NSEvent *)theEvent 115 | { 116 | NSPoint where = [self.window convertBaseToScreen:[theEvent locationInWindow]]; 117 | NSPoint origin = [self.window frame].origin; 118 | while ((theEvent = [NSApp nextEventMatchingMask:NSLeftMouseDownMask | NSLeftMouseDraggedMask | NSLeftMouseUpMask untilDate:[NSDate distantFuture] inMode:NSEventTrackingRunLoopMode dequeue:YES]) && ([theEvent type] != NSLeftMouseUp)) { 119 | @autoreleasepool { 120 | if (theEvent.window != self.window) { 121 | theEvent = [self.class synthesisedEventWithEvent:theEvent forWindow:self.window]; 122 | } 123 | NSPoint now = [self.window convertBaseToScreen:[theEvent locationInWindow]]; 124 | origin.x += now.x - where.x; 125 | origin.y += now.y - where.y; 126 | [self.window setFrameOrigin:origin]; 127 | where = now; 128 | } 129 | } 130 | } 131 | 132 | + (NSEvent *)synthesisedEventWithEvent:(NSEvent *)theEvent forWindow:(NSWindow *)window 133 | { 134 | NSPoint screenPoint = [theEvent.window convertBaseToScreen:[theEvent locationInWindow]]; 135 | NSPoint windowPoint = [window convertScreenToBase:screenPoint]; 136 | return [NSEvent mouseEventWithType:theEvent.type location:windowPoint modifierFlags:theEvent.modifierFlags timestamp:theEvent.timestamp windowNumber:window.windowNumber context:theEvent.context eventNumber:theEvent.eventNumber clickCount:theEvent.clickCount pressure:theEvent.pressure]; 137 | } 138 | 139 | #pragma mark - Accessors 140 | 141 | - (void)setImage:(NSImage *)image 142 | { 143 | _imageView.image = image; 144 | } 145 | 146 | - (NSImage *)image 147 | { 148 | return _imageView.image; 149 | } 150 | 151 | - (void)setFadeOnHover:(BOOL)fadeOnHover 152 | { 153 | if (_fadeOnHover != fadeOnHover) { 154 | _fadeOnHover = fadeOnHover; 155 | _imageView.alphaValue = fadeOnHover ? 0.f : 1.f; 156 | [self updateTrackingAreas]; 157 | } 158 | } 159 | @end 160 | -------------------------------------------------------------------------------- /INDockableWindow/INDockablePrimaryWindow.h: -------------------------------------------------------------------------------- 1 | // 2 | // INDockablePrimaryWindow.h 3 | // INDockableWindow 4 | // 5 | // Copyright (c) 2013, Indragie Karunaratne. All rights reserved. 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 8 | // software and associated documentation files (the "Software"), to deal in the Software 9 | // without restriction, including without limitation the rights to use, copy, modify, merge, 10 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 11 | // to whom the Software is furnished to do so, subject to the following conditions: 12 | 13 | // The above copyright notice and this permission notice shall be included in all copies or 14 | // substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 17 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 19 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 20 | // OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | 23 | #import "INDockableWindow.h" 24 | 25 | /** The primary window class */ 26 | @interface INDockablePrimaryWindow : INDockableWindow 27 | @end 28 | -------------------------------------------------------------------------------- /INDockableWindow/INDockablePrimaryWindow.m: -------------------------------------------------------------------------------- 1 | // 2 | // INDockablePrimaryWindow.m 3 | // INDockableWindow 4 | // 5 | // Copyright (c) 2013, Indragie Karunaratne. All rights reserved. 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 8 | // software and associated documentation files (the "Software"), to deal in the Software 9 | // without restriction, including without limitation the rights to use, copy, modify, merge, 10 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 11 | // to whom the Software is furnished to do so, subject to the following conditions: 12 | 13 | // The above copyright notice and this permission notice shall be included in all copies or 14 | // substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 17 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 19 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 20 | // OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | 23 | #import "INDockablePrimaryWindow.h" 24 | 25 | @implementation INDockablePrimaryWindow 26 | @end 27 | -------------------------------------------------------------------------------- /INDockableWindow/INDockableSplitView.h: -------------------------------------------------------------------------------- 1 | // 2 | // INDockableSplitView.h 3 | // INDockableWindow 4 | // 5 | // Copyright (c) 2013, Indragie Karunaratne. All rights reserved. 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 8 | // software and associated documentation files (the "Software"), to deal in the Software 9 | // without restriction, including without limitation the rights to use, copy, modify, merge, 10 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 11 | // to whom the Software is furnished to do so, subject to the following conditions: 12 | 13 | // The above copyright notice and this permission notice shall be included in all copies or 14 | // substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 17 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 19 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 20 | // OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | 23 | #import 24 | 25 | /** 26 | NSSplitView subclass that adds some options for easy customization. 27 | */ 28 | @interface INDockableSplitView : NSSplitView 29 | /** 30 | Width of the split view dividers. Default is 1px. 31 | */ 32 | @property (nonatomic, assign) CGFloat ind_dividerThickness; 33 | 34 | /** 35 | Color of the split view dividers. 36 | */ 37 | @property (nonatomic, strong) NSColor *ind_dividerColor; 38 | 39 | /** 40 | Drawing block to draw your own custom dividers. 41 | */ 42 | @property (nonatomic, copy) void(^dividerDrawingBlock)(NSRect rect); 43 | @end 44 | -------------------------------------------------------------------------------- /INDockableWindow/INDockableSplitView.m: -------------------------------------------------------------------------------- 1 | // 2 | // INDockableSplitView.m 3 | // INDockableWindow 4 | // 5 | // Copyright (c) 2013, Indragie Karunaratne. All rights reserved. 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 8 | // software and associated documentation files (the "Software"), to deal in the Software 9 | // without restriction, including without limitation the rights to use, copy, modify, merge, 10 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 11 | // to whom the Software is furnished to do so, subject to the following conditions: 12 | 13 | // The above copyright notice and this permission notice shall be included in all copies or 14 | // substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 17 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 19 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 20 | // OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | 23 | #import "INDockableSplitView.h" 24 | 25 | @implementation INDockableSplitView 26 | 27 | #pragma mark - NSSplitView 28 | 29 | - (id)initWithFrame:(NSRect)frameRect 30 | { 31 | if ((self = [super initWithFrame:frameRect])) { 32 | [self setVertical:YES]; 33 | self.dividerStyle = NSSplitViewDividerStyleThin; 34 | _ind_dividerThickness = 1.f; 35 | _ind_dividerColor = [super dividerColor]; 36 | } 37 | return self; 38 | } 39 | 40 | - (void)drawDividerInRect:(NSRect)rect 41 | { 42 | NSRect integral = NSIntegralRect(rect); 43 | if (self.dividerDrawingBlock) { 44 | self.dividerDrawingBlock(integral); 45 | } else { 46 | [super drawDividerInRect:integral]; 47 | } 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /INDockableWindow/INDockableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // INDockableViewController.h 3 | // INDockableWindow 4 | // 5 | // Copyright (c) 2013, Indragie Karunaratne. All rights reserved. 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 8 | // software and associated documentation files (the "Software"), to deal in the Software 9 | // without restriction, including without limitation the rights to use, copy, modify, merge, 10 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 11 | // to whom the Software is furnished to do so, subject to the following conditions: 12 | 13 | // The above copyright notice and this permission notice shall be included in all copies or 14 | // substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 17 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 19 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 20 | // OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | 23 | #import 24 | #import "INDockableDetachControl.h" 25 | 26 | @class INDockableWindowController; 27 | @class INDockableWindow; 28 | 29 | /** 30 | View controller that displays the content for a single dockable pane of the dockable window controller. 31 | */ 32 | @interface INDockableViewController : NSViewController 33 | /** 34 | The dockable window controller that owns this view controller. 35 | */ 36 | @property (nonatomic, assign, readonly) INDockableWindowController *dockableWindowController; 37 | /** 38 | The parent window of this view controller 39 | */ 40 | @property (nonatomic, assign, readonly) INDockableWindow *window; 41 | /** 42 | The view to display in the title bar. This view will be resized to fit the title bar size. 43 | */ 44 | @property (nonatomic, strong) IBOutlet NSView *titleBarView; 45 | 46 | /** 47 | The unique identifier for this view controller. Set to a generated UUID by default. 48 | 49 | If you decide to set this yourself, ensure that this value is unique from the 50 | identifiers of any other view controllers. If this rule is not followed, the 51 | behaviour is undefined. Setting this identifier will set the identifier of this 52 | view controller's view as well. 53 | 54 | @warning Do not modify the identifier of the view after 55 | the view controller has been created. 56 | */ 57 | @property (nonatomic, copy) NSString *uniqueIdentifier; 58 | 59 | /** 60 | The index of the view controller in it's parent window controller if attached. 61 | If the view controller is detached, returns NSNotFound. 62 | */ 63 | @property (nonatomic, assign, readonly) NSUInteger index; 64 | 65 | /** 66 | The detach control for the view controller. This control is automatically created when 67 | the view controller is created. It can be placed anywhere in your view hierarchy, and 68 | dragging it will trigger a detach from the primary window. 69 | */ 70 | @property (nonatomic, strong, readonly) INDockableDetachControl *detachControl; 71 | 72 | /** 73 | Whether this view controller is attached or in its own separate window. 74 | */ 75 | @property (nonatomic, assign, getter = isAttached) BOOL attached; 76 | 77 | /** 78 | Called when the view controller is about to become detached from the primary window 79 | 80 | Always call super somewhere in your implementation. 81 | */ 82 | - (void)viewControllerWillDetach; 83 | 84 | /** 85 | Called when the view controller is detached from the primary window. 86 | 87 | Always call super somewhere in your implementation. 88 | */ 89 | - (void)viewControllerDidDetach; 90 | 91 | /** 92 | Called when the view controller is about to attach to the primary window 93 | 94 | Always call super somewhere in your implementation. 95 | */ 96 | - (void)viewControllerWillAttach; 97 | 98 | /** 99 | Called when the view controller is attached to the primary window 100 | 101 | Always call super somewhere in your implementation. 102 | */ 103 | - (void)viewControllerDidAttach; 104 | 105 | /** 106 | Detach this view controller from the primary window. 107 | */ 108 | - (void)detach; 109 | 110 | /** 111 | Attach this window to the primary window 112 | */ 113 | - (void)attach; 114 | @end 115 | -------------------------------------------------------------------------------- /INDockableWindow/INDockableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // INDockableViewController.m 3 | // INDockableWindow 4 | // 5 | // Copyright (c) 2013, Indragie Karunaratne. All rights reserved. 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 8 | // software and associated documentation files (the "Software"), to deal in the Software 9 | // without restriction, including without limitation the rights to use, copy, modify, merge, 10 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 11 | // to whom the Software is furnished to do so, subject to the following conditions: 12 | 13 | // The above copyright notice and this permission notice shall be included in all copies or 14 | // substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 17 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 19 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 20 | // OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | 23 | #import "INDockableViewController.h" 24 | #import "INDockablePrimaryWindow.h" 25 | #import "INDockableWindowController.h" 26 | 27 | @interface INDockableViewController () 28 | @property (nonatomic, assign, readwrite) INDockableWindowController *dockableWindowController; 29 | @property (nonatomic, assign, readwrite) NSUInteger index; 30 | @property (nonatomic, strong, readonly) NSString *UUID; 31 | @end 32 | 33 | @interface INDockableDetachControl (Private) 34 | @property (nonatomic, assign, readwrite) INDockableViewController *viewController; 35 | @end 36 | 37 | @implementation INDockableViewController 38 | @synthesize uniqueIdentifier = _uniqueIdentifier; 39 | 40 | - (void)commonInitForINDockableViewController 41 | { 42 | _detachControl = [[INDockableDetachControl alloc] initWithFrame:NSZeroRect]; 43 | _detachControl.viewController = self; 44 | _UUID = [[NSUUID UUID] UUIDString]; 45 | _index = NSNotFound; 46 | _uniqueIdentifier = self.defaultIdentifier; 47 | } 48 | 49 | - (id)initWithCoder:(NSCoder *)aDecoder 50 | { 51 | if ((self = [super initWithCoder:aDecoder])) { 52 | [self commonInitForINDockableViewController]; 53 | } 54 | return self; 55 | } 56 | 57 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 58 | { 59 | if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) { 60 | [self commonInitForINDockableViewController]; 61 | } 62 | return self; 63 | } 64 | 65 | #pragma mark - Public API 66 | 67 | - (void)viewControllerWillDetach 68 | { 69 | 70 | } 71 | 72 | - (void)viewControllerDidDetach 73 | { 74 | [self.detachControl setHidden:YES]; 75 | } 76 | 77 | - (void)viewControllerWillAttach 78 | { 79 | 80 | } 81 | 82 | - (void)viewControllerDidAttach 83 | { 84 | [self.detachControl setHidden:NO]; 85 | } 86 | 87 | - (void)detach 88 | { 89 | [self.dockableWindowController detachViewController:self]; 90 | } 91 | 92 | - (void)attach 93 | { 94 | [self.dockableWindowController attachViewController:self]; 95 | } 96 | 97 | #pragma mark - Accessors 98 | 99 | - (void)setView:(NSView *)view 100 | { 101 | [super setView:view]; 102 | view.identifier = self.uniqueIdentifier; 103 | } 104 | 105 | - (BOOL)isAttached 106 | { 107 | return self.index != NSNotFound; 108 | } 109 | 110 | - (NSWindow *)window 111 | { 112 | return self.view.window; 113 | } 114 | 115 | - (void)setUniqueIdentifier:(NSString *)uniqueIdentifier 116 | { 117 | uniqueIdentifier = uniqueIdentifier ?: self.defaultIdentifier; 118 | if (_uniqueIdentifier != uniqueIdentifier) { 119 | _uniqueIdentifier = uniqueIdentifier; 120 | self.view.identifier = uniqueIdentifier; 121 | } 122 | } 123 | 124 | - (NSString *)defaultIdentifier 125 | { 126 | NSString *indexString = self.attached ? @(self.index).stringValue : nil; 127 | return indexString ?: self.UUID; 128 | } 129 | 130 | @end 131 | -------------------------------------------------------------------------------- /INDockableWindow/INDockableWindow.h: -------------------------------------------------------------------------------- 1 | // 2 | // INDockableWindow.h 3 | // Flamingo 4 | // 5 | // Copyright (c) 2013, Indragie Karunaratne. All rights reserved. 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 8 | // software and associated documentation files (the "Software"), to deal in the Software 9 | // without restriction, including without limitation the rights to use, copy, modify, merge, 10 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 11 | // to whom the Software is furnished to do so, subject to the following conditions: 12 | 13 | // The above copyright notice and this permission notice shall be included in all copies or 14 | // substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 17 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 19 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 20 | // OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | 23 | #import "INAppStoreWindow.h" 24 | 25 | @class INDockableWindowController; 26 | /** 27 | This notification is posted when the user has finished moving the window and released the mouse 28 | */ 29 | extern NSString* const INDockableWindowFinishedMovingNotification; 30 | 31 | /** 32 | Base class for all windows used by INDockableWindowController 33 | */ 34 | @interface INDockableWindow : INAppStoreWindow 35 | /** 36 | The dockable window controller that owns this window. 37 | */ 38 | @property (nonatomic, assign, readonly) INDockableWindowController *dockableWindowController; 39 | @end 40 | -------------------------------------------------------------------------------- /INDockableWindow/INDockableWindow.m: -------------------------------------------------------------------------------- 1 | // 2 | // INDockableWindow.m 3 | // Flamingo 4 | // 5 | // Copyright (c) 2013, Indragie Karunaratne. All rights reserved. 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 8 | // software and associated documentation files (the "Software"), to deal in the Software 9 | // without restriction, including without limitation the rights to use, copy, modify, merge, 10 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 11 | // to whom the Software is furnished to do so, subject to the following conditions: 12 | 13 | // The above copyright notice and this permission notice shall be included in all copies or 14 | // substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 17 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 19 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 20 | // OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | #import "INDockableWindow.h" 23 | 24 | NSString* const INDockableWindowFinishedMovingNotification = @"INDockableWindowFinishedMovingNotification"; 25 | 26 | @interface INDockableWindow () 27 | @property (nonatomic, assign, readwrite) INDockableWindowController *dockableWindowController; 28 | @end 29 | 30 | @implementation INDockableWindow { 31 | NSRect _lastWindowFrame; 32 | 33 | } 34 | #pragma mark - Event Handling 35 | 36 | - (void)sendEvent:(NSEvent *)theEvent 37 | { 38 | if (theEvent.type == NSLeftMouseDown) { 39 | _lastWindowFrame = self.frame; 40 | } else { 41 | // TODO: Check for a specific event type/subtype for when the mouse has been released 42 | // NSWindow's dragging runs its own event loop so it NSLeftMouseUp events are not sent 43 | // The event(s) that are sent when the mouse has been released are these: 44 | // NSEvent: type=Kitdefined loc=(0,622) time=12283.8 flags=0x100 win=0x101928e40 winNum=4075 ctxt=0x0 subtype=4 45 | if (!NSEqualRects(self.frame, _lastWindowFrame)) { 46 | // Call super -sendEvent *before* sending the notification and return early because the window may 47 | // be removed and deallocated as a result of this notification being received, and calling super 48 | // would result in EXC_BAD_ACCESS 49 | [super sendEvent:theEvent]; 50 | [[NSNotificationCenter defaultCenter] postNotificationName:INDockableWindowFinishedMovingNotification object:self]; 51 | return; 52 | } 53 | _lastWindowFrame = NSZeroRect; 54 | } 55 | [super sendEvent:theEvent]; 56 | } 57 | 58 | @end 59 | -------------------------------------------------------------------------------- /INDockableWindow/INDockableWindowController.h: -------------------------------------------------------------------------------- 1 | // 2 | // INDockableWindowController.h 3 | // INDockableWindow 4 | // 5 | // Copyright (c) 2013, Indragie Karunaratne. All rights reserved. 6 | // 7 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 8 | // software and associated documentation files (the "Software"), to deal in the Software 9 | // without restriction, including without limitation the rights to use, copy, modify, merge, 10 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 11 | // to whom the Software is furnished to do so, subject to the following conditions: 12 | 13 | // The above copyright notice and this permission notice shall be included in all copies or 14 | // substantial portions of the Software. 15 | 16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 17 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 19 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 20 | // OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | 23 | #import 24 | #import "INDockableViewController.h" 25 | #import "INDockablePrimaryWindow.h" 26 | #import "INDockableAuxiliaryWindow.h" 27 | #import "INDockableSplitView.h" 28 | 29 | 30 | /*------ Notifications -------*/ 31 | 32 | // Posted before the window's frame changes due to a layout operation. 33 | extern NSString * const INDockableWindowFrameWillChangeNotification; 34 | 35 | // Posted when the window's frame changes due to a layout operation. 36 | // 37 | // Unlike the normal NSWindow resizing notification, this is only posted once 38 | // after the frame size has been adjusted to its final value (even during 39 | // a frame animation). 40 | extern NSString * const INDockableWindowFrameDidChangeNotification; 41 | 42 | @protocol INDockableWindowControllerDelegate; 43 | /** 44 | Window controller that manages a collection of dockable views and auxiliary windows 45 | */ 46 | @interface INDockableWindowController : NSWindowController 47 | /** 48 | The window controller's delegate. 49 | */ 50 | @property (nonatomic, assign) id delegate; 51 | 52 | /** 53 | The primary window that the auxiliary windows dock to. 54 | 55 | @warning The `titleBarHeight` of the window should not be set directly, 56 | and should be set via the `titleBarHeight` property of the INDockableWindowController. 57 | @warning Don't set the delegate of the window. 58 | */ 59 | @property (nonatomic, strong, readonly) INDockablePrimaryWindow *primaryWindow; 60 | 61 | /** 62 | Style mask to use when creating auxiliary windows. 63 | 64 | Customizing the style mask of the primary window should be done by creating the window yourself and using 65 | -initWithWindow: or using your own XIB with -initWithWindowNibName: instead of using -init. 66 | */ 67 | @property (nonatomic, assign) NSUInteger windowStyleMask; 68 | 69 | /** 70 | Array of INDockableAuxiliaryWindow's that are detached from the primary window 71 | 72 | Windows in this array should not be modified. Set the `configureAuxiliaryWindowBlock` block to 73 | implement custom configuration for auxiliary windows. 74 | */ 75 | @property (nonatomic, strong, readonly) NSSet *auxiliaryWindows; 76 | 77 | /** 78 | Block that is called to configure a new auxiliary window 79 | */ 80 | @property (nonatomic, copy) void(^configureAuxiliaryWindowBlock)(INDockableAuxiliaryWindow *window); 81 | 82 | /** 83 | Array of INDockabieViewController's (both attached and detached from the primary window) 84 | */ 85 | @property (nonatomic, strong, readonly) NSSet *viewControllers; 86 | 87 | /** 88 | Array of INDockableViewController's that are attached to the primary window 89 | 90 | The order of this array indicates the order in which the view controllers are displayed, 91 | from left to right. 92 | */ 93 | @property (nonatomic, strong, readonly) NSArray *attachedViewControllers; 94 | 95 | /** 96 | The primary view controller that should always be visible. Auxiliary view controllers 97 | are added to the right of this primary view. 98 | */ 99 | @property (nonatomic, strong) INDockableViewController *primaryViewController; 100 | 101 | /** 102 | The split view that displays each of the view controllers. You can use this reference to the split view 103 | to set divider width, color, and a custom divider drawing block. 104 | 105 | @warning Do not set the delegate of the split view. The delegate is 106 | automatically set to the INDockableWindowController. To override split view 107 | delegate methods, subclass the INDockableWindowController and override the split 108 | view delegate methods. INDockableWindowController implements all of the 109 | methods documented in the NSSplitViewDelegate protocol. Always call super 110 | in any overriden implementations of delegate methods. 111 | */ 112 | @property (nonatomic, strong, readonly) INDockableSplitView *splitView; 113 | 114 | /** 115 | The title bar height to use for all the windows (primary and auxiliary). Default is 22.f. 116 | */ 117 | @property (nonatomic, assign) CGFloat titleBarHeight; 118 | 119 | /** 120 | The minimum height for the primary and auxiliary windows. Default is 0px. 121 | */ 122 | @property (nonatomic, assign) CGFloat minimumWindowHeight; 123 | 124 | /** 125 | The maximum height for the primary and auxiliary windows. Default is FLT_MAX. 126 | 127 | Set to FLT_MAX to allow an unlimited window height. 128 | */ 129 | @property (nonatomic, assign) CGFloat maximumWindowHeight; 130 | 131 | /** 132 | The minimum distance (in pixels) that a window needs to be dragged near the 133 | right edge of the primary window to attach it to the window. Default is 8px. 134 | */ 135 | @property (nonatomic, assign) CGFloat attachmentProximity; 136 | 137 | /** 138 | Autosave name for saving information to user defaults. 139 | 140 | Setting an autosave name will enable the window controller to automatically 141 | save and restore the frames of view controllers and the primary window. The autossave data 142 | is keyed using the identifiers of the view controllers. 143 | */ 144 | @property (nonatomic, copy) NSString *autosaveName; 145 | 146 | /** 147 | Set to YES to animate the addition and removal of view controllers by animating 148 | the frame change of the window. Default is NO. 149 | */ 150 | @property (nonatomic, assign) BOOL animatesFrameChange; 151 | 152 | /** 153 | The animation curve to use for window animations (if animatesFrameChange = YES). 154 | Default is NSAnimationEaseInOut. 155 | */ 156 | @property (nonatomic, assign) NSAnimationCurve windowAnimationCurve; 157 | 158 | /** 159 | The animation duration to use for window animations (if animatesFrameChange = YES). 160 | Default is 0.20 seconds. 161 | */ 162 | @property (nonatomic, assign) NSTimeInterval windowAnimationDuration; 163 | 164 | /** @name Retrieving View Controllers */ 165 | 166 | /** 167 | Returns the attached view controller at the specified index. 168 | 169 | Throws an exception if `index` is not within the valid range of indices. 170 | @param index The index of the attached view controller (indicies are ordered from left to right). 171 | @return The attached view controller at the specified index. 172 | */ 173 | - (INDockableViewController *)attachedViewControllerAtIndex:(NSUInteger)index; 174 | 175 | /** 176 | Returns the view controller with the specified identifier (attached or not). 177 | 178 | Returns nil if no view controller with the identifier is found. 179 | @param identifier The identifier of the view controller (set using the `identifier` property of INDockableViewController) 180 | @return The view controller with the specified identifier. 181 | */ 182 | - (INDockableViewController *)viewControllerWithIdentifier:(NSString *)identifier; 183 | 184 | /** @name Positioning Attached View Controllers */ 185 | 186 | /** 187 | Moves an attached view controller to a new index. 188 | 189 | If `viewController` is not attached to the window, this method does nothing. If `index` is out of bounds, 190 | an exception will be thrown 191 | @param index The index to move the view controller to. 192 | @param viewController The view controller to move. 193 | */ 194 | - (void)setIndex:(NSUInteger)index forAttachedViewController:(INDockableViewController *)viewController; 195 | 196 | /** 197 | Returns the index of the specified attached view controller. 198 | @param viewController The attached view controller to get the index of. 199 | @return The index of the attached view controller, or NSNotFound if the view controller is nil or has not been attached 200 | */ 201 | - (NSUInteger)indexOAttachedfViewController:(INDockableViewController *)viewController; 202 | 203 | /** @name Adding and Removing View Controllers */ 204 | 205 | /** 206 | Adds the specified view controller to the end of the view controller array. 207 | 208 | Does nothing if `viewController` has already been added. 209 | @param attached If YES, the view controller will be attached to the main window. If NO, the view controller 210 | will be placed inside an auxiliary window and the window will be shown. 211 | @param viewController The view controller to add 212 | */ 213 | - (void)addViewController:(INDockableViewController *)viewController attached:(BOOL)attached; 214 | 215 | /** 216 | Adds the specified view controller to the window at the specified index. 217 | 218 | Throws an exception if `index` if out of bounds. If `viewController` is already attached to the window, 219 | this will just call -setIndex:forAttachedViewController: with the specified index. 220 | @param viewController The view controller to add and attach to the primary window 221 | @param index The index that the view controller will be placed at 222 | */ 223 | - (void)insertViewController:(INDockableViewController *)viewController atIndex:(NSUInteger)index; 224 | 225 | /** 226 | Replaces the specified view controller with a new view controller 227 | 228 | This method only works for view controllers that are attached to the main window. 229 | @param oldViewController The view controller to remove 230 | @param newViewController The view controller to replace it with 231 | */ 232 | - (void)replaceAttachedViewController:(INDockableViewController *)oldViewController withViewController:(INDockableViewController *)newViewController; 233 | 234 | /** 235 | Replaces the view controller at the specified index with a new view controller 236 | 237 | This method only works for view controllers that are attached to the main window. 238 | @param index The index of the view controller to replace 239 | @param viewController The view controller to replace it with 240 | */ 241 | - (void)replaceAttachedViewControllerAtIndex:(NSUInteger)index withViewController:(INDockableViewController *)viewController; 242 | 243 | typedef NS_ENUM(NSInteger, INDockableViewRelativePosition) { 244 | INDockableViewRight, 245 | INDockableViewLeft 246 | }; 247 | 248 | /** 249 | Adds the specified view controller to the window positioned relative to another attached view controller. 250 | 251 | This method does nothing if `viewController` is nil, `position` is not one of the defined values, or if `anotherViewController` is not attached to the primary window. 252 | @param viewController The view controller to add and attach to the primary window. 253 | @param position The relative position of the view controller 254 | @param anotherViewController The existing attached view controller to position the new view controller relative to 255 | */ 256 | - (void)insertViewController:(INDockableViewController *)viewController positioned:(INDockableViewRelativePosition)position relativeTo:(INDockableViewController *)anotherViewController; 257 | 258 | /** 259 | Removes the specified view controller. 260 | 261 | If `viewController` is attached to the primary window, it will be removed from the window. If it is 262 | inside an auxiliary window, the window will be closed and removed. 263 | @param viewController The view controller to remove. 264 | */ 265 | - (void)removeViewController:(INDockableViewController *)viewController; 266 | 267 | /** @name Attaching and Detaching View Controllers */ 268 | 269 | /** 270 | Detaches the specified view controller from the primary window. 271 | 272 | If `viewController` is not attached to the primary window, this method does nothing. 273 | @param viewController The view controller to detach. 274 | */ 275 | - (void)detachViewController:(INDockableViewController *)viewController; 276 | 277 | /** 278 | Attaches the specified view controller to the primary window. 279 | 280 | If `viewController` is already attached to the primary window, this method does nothing. 281 | @param viewController The view controller to attach 282 | */ 283 | - (void)attachViewController:(INDockableViewController *)viewController; 284 | 285 | /** @name Managing Resizing of View Controllers */ 286 | 287 | /** 288 | Set a minimum width for the specified view controller. 289 | 290 | This method affects both the width of the view when its attached to the main window in the split view, 291 | and also affects the minimum size of any auxiliary window its in. 292 | @param width The minimum width. 293 | @param viewController The view controller to set the minimum width for. 294 | */ 295 | - (void)setMinimumWidth:(CGFloat)width forViewController:(INDockableViewController *)viewController; 296 | 297 | /** 298 | Set a maximum width for the specified view controller. 299 | 300 | This method affects both the width of the view when its attached to the main window in the split view, 301 | and also affects the minimum size of any auxiliary window its in. 302 | @param width The maximum width. 303 | @param viewController The view controller to set the maximum width for. 304 | */ 305 | - (void)setMaximumWidth:(CGFloat)width forViewController:(INDockableViewController *)viewController; 306 | 307 | /** 308 | Controls whether the view controller's view should be resized when the primary window is resized. 309 | 310 | This method only has any effect when the view controller is attached to the primary window. When detached 311 | in an auxiliary window, the view will always resize with the window unless maximum/minimum size constraints 312 | have been set on the auxiliary window (can be set in the `configureAuxiliaryWindowBlock` block). 313 | @param shouldAdjust YES if the view controller should resize with the primary window, NO otherwise. 314 | @param viewController The view controller. 315 | */ 316 | - (void)setShouldAdjustSize:(BOOL)shouldAdjust ofViewController:(INDockableViewController *)viewController; 317 | 318 | /** @name Advanced Window Customization */ 319 | 320 | /** 321 | Subclasses can override this method to return an alternate class for the primary window. 322 | 323 | The window must be a subclass of INDockablePrimaryWindow. 324 | */ 325 | + (Class)primaryWindowClass; 326 | 327 | /** 328 | Subclasses can override this method to return an alternate class for the auxiliary window. 329 | 330 | The window must be a subclass of INDockableAuxiliaryWindow. 331 | */ 332 | + (Class)auxiliaryWindowClass; 333 | @end 334 | 335 | /** 336 | The dockable window controller's delegate. Contains some methods that are useful for being notified 337 | about events that were triggered by the user and not by methods called on the window controller 338 | */ 339 | @protocol INDockableWindowControllerDelegate 340 | @optional 341 | /** 342 | Called when a view controller is detached from the primary window. 343 | @param controller The dockable window controller. 344 | @param viewController The view controller that was detached. 345 | **/ 346 | - (void)dockableWindowController:(INDockableWindowController *)controller 347 | viewControllerWasDetached:(INDockableViewController *)viewController; 348 | 349 | /** 350 | Called when a view controller is attached to the primary window 351 | @param controller The dockable window controller. 352 | @param viewController The view controller that was attached. 353 | */ 354 | - (void)dockableWindowController:(INDockableWindowController *)controller 355 | viewControllerWasAttached:(INDockableViewController *)viewController; 356 | 357 | /** 358 | Called when the user closes an auxiliary window containing a dockable view controller. 359 | @param controller The dockable window controller. 360 | @param auxiliaryWindow The window that was closed. 361 | */ 362 | - (void)dockableWindowController:(INDockableWindowController *)controller 363 | auxiliaryWindowDidClose:(INDockableAuxiliaryWindow *)auxiliaryWindow; 364 | 365 | /** 366 | Called when a view controller (either attached or detached) is about to be removed. 367 | @param controller The dockable window controller. 368 | @param viewController The view controller that is about to be removed. 369 | */ 370 | - (void)dockableWindowController:(INDockableWindowController *)controller 371 | willRemoveViewController:(INDockableViewController *)viewController; 372 | 373 | /** 374 | Called when a view controller (either attached or detached) is removed 375 | @param controller The dockable window controller. 376 | @param viewController The view controller that was removed. 377 | */ 378 | - (void)dockableWindowController:(INDockableWindowController *)controller 379 | didRemoveViewController:(INDockableViewController *)viewController; 380 | 381 | /** 382 | Called when a view controller (either attached or detached) is about to be added 383 | @param controller The dockable window controller 384 | @param viewController The view controller that is about to be added 385 | */ 386 | - (void)dockableWindowController:(INDockableWindowController *)controller 387 | willAddViewController:(INDockableViewController *)viewController; 388 | 389 | /** 390 | Called when a view controller (either attached or detached) is added 391 | @param controller The dockable window controller 392 | @param viewController The view controller that was added 393 | */ 394 | - (void)dockableWindowController:(INDockableWindowController *)controller 395 | didAddViewController:(INDockableViewController *)viewController; 396 | 397 | /** @name NSSplitViewDelegate Methods */ 398 | 399 | /** 400 | The documentation for these methods can be found here: http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/NSSplitViewDelegate_Protocol/Reference/Reference.html 401 | */ 402 | 403 | - (BOOL)splitView:(NSSplitView *)splitView shouldAdjustSizeOfSubview:(NSView *)subview; 404 | - (CGFloat)splitView:(NSSplitView *)splitView constrainMinCoordinate:(CGFloat)proposedMin ofSubviewAt:(NSInteger)dividerIndex; 405 | - (CGFloat)splitView:(NSSplitView *)splitView constrainMaxCoordinate:(CGFloat)proposedMax ofSubviewAt:(NSInteger)dividerIndex; 406 | - (CGFloat)splitView:(NSSplitView *)splitView constrainSplitPosition:(CGFloat)proposedPosition ofSubviewAt:(NSInteger)dividerIndex; 407 | - (void)splitViewWillResizeSubviews:(NSNotification *)aNotification; 408 | - (void)splitViewDidResizeSubviews:(NSNotification *)aNotification; 409 | - (void)splitView:(NSSplitView *)splitView resizeSubviewsWithOldSize:(NSSize)oldSize; 410 | - (NSRect)splitView:(NSSplitView *)splitView additionalEffectiveRectOfDividerAtIndex:(NSInteger)dividerIndex; 411 | 412 | /** 413 | @warning It is recommended that you do not override the following NSSplitView 414 | delegate methods to allow collapsing. Using this class with collapsing enabled 415 | results in undefined behaviour 416 | */ 417 | 418 | - (BOOL)splitView:(NSSplitView *)splitView canCollapseSubview:(NSView *)subview; 419 | - (BOOL)splitView:(NSSplitView *)splitView shouldCollapseSubview:(NSView *)subview forDoubleClickOnDividerAtIndex:(NSInteger)dividerIndex; 420 | - (BOOL)splitView:(NSSplitView *)splitView shouldHideDividerAtIndex:(NSInteger)dividerIndex; 421 | @end 422 | -------------------------------------------------------------------------------- /INDockableWindow/INWindowFrameAnimation.h: -------------------------------------------------------------------------------- 1 | // 2 | // INWindowFrameAnimation.h 3 | // Flamingo 4 | // 5 | // Created by Indragie Karunaratne on 2013-03-02. 6 | // Copyright (c) 2013, Indragie Karunaratne. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 9 | // software and associated documentation files (the "Software"), to deal in the Software 10 | // without restriction, including without limitation the rights to use, copy, modify, merge, 11 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 12 | // to whom the Software is furnished to do so, subject to the following conditions: 13 | 14 | // The above copyright notice and this permission notice shall be included in all copies or 15 | // substantial portions of the Software. 16 | 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 18 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 21 | // OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | 23 | #import 24 | 25 | /** 26 | * NSAnimation subclass for animating the frame of a window 27 | * This is used instead of NSWindow's animation methods because they block the main thread 28 | * This animation performs the same task, except with variable animation durve and without 29 | * blocking the main thread. 30 | 31 | * Do not set the delegate of this object. Delegate methods are handled internally. 32 | */ 33 | @interface INWindowFrameAnimation : NSAnimation 34 | @property (nonatomic, strong, readonly) NSWindow *window; 35 | @property (nonatomic, assign) NSRect toFrame; 36 | @property (nonatomic, copy) void (^completionBlock)(BOOL finished); 37 | 38 | /** 39 | Creates a new INWindowFrameAnimation object. 40 | @param duration The animation duration 41 | @param animationCurve The animation timing function 42 | @param window The window to animate 43 | @return An instance of INWindowFrameAnimation 44 | */ 45 | - (id)initWithDuration:(NSTimeInterval)duration 46 | animationCurve:(NSAnimationCurve)animationCurve 47 | window:(NSWindow *)window; 48 | 49 | /** 50 | Animates the winow to the specified frame. 51 | @param frame The frame to animate to 52 | */ 53 | - (void)startAnimationToFrame:(NSRect)frame; 54 | @end 55 | -------------------------------------------------------------------------------- /INDockableWindow/INWindowFrameAnimation.m: -------------------------------------------------------------------------------- 1 | // 2 | // INWindowFrameAnimation.m 3 | // Flamingo 4 | // 5 | // Created by Indragie Karunaratne on 2013-03-02. 6 | // Copyright (c) 2013, Indragie Karunaratne. All rights reserved. 7 | // 8 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this 9 | // software and associated documentation files (the "Software"), to deal in the Software 10 | // without restriction, including without limitation the rights to use, copy, modify, merge, 11 | // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 12 | // to whom the Software is furnished to do so, subject to the following conditions: 13 | 14 | // The above copyright notice and this permission notice shall be included in all copies or 15 | // substantial portions of the Software. 16 | 17 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 18 | // BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | // WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE 21 | // OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | #import "INWindowFrameAnimation.h" 23 | 24 | @implementation INWindowFrameAnimation { 25 | NSRect _oldFrame; 26 | } 27 | 28 | #pragma mark - Initialization 29 | 30 | - (id)initWithDuration:(NSTimeInterval)duration 31 | animationCurve:(NSAnimationCurve)animationCurve 32 | window:(NSWindow *)window 33 | { 34 | if ((self = [super initWithDuration:duration animationCurve:animationCurve])) { 35 | _window = window; 36 | self.delegate = self; 37 | self.animationBlockingMode = NSAnimationNonblocking; 38 | } 39 | return self; 40 | } 41 | 42 | #pragma mark - Animation 43 | 44 | - (void)startAnimationToFrame:(NSRect)frame 45 | { 46 | _oldFrame = self.window.frame; 47 | _toFrame = frame; 48 | [self startAnimation]; 49 | } 50 | 51 | #pragma mark - NSAnimation 52 | 53 | - (void)setCurrentProgress:(NSAnimationProgress)progress 54 | { 55 | [super setCurrentProgress:progress]; 56 | NSRect newWindowFrame = _oldFrame; 57 | newWindowFrame.origin.x += progress * (_toFrame.origin.x - _oldFrame.origin.x); 58 | newWindowFrame.origin.y += progress * (_toFrame.origin.y - _oldFrame.origin.y); 59 | newWindowFrame.size.width += progress * (_toFrame.size.width - _oldFrame.size.width); 60 | newWindowFrame.size.height += progress * (_toFrame.size.height - _oldFrame.size.height); 61 | [self.window setFrame:newWindowFrame display:YES]; 62 | } 63 | 64 | #pragma mark - NSAnimationDelegate 65 | 66 | - (void)animationDidEnd:(NSAnimation *)animation 67 | { 68 | if (self.completionBlock) self.completionBlock(YES); 69 | } 70 | 71 | - (void)animationDidStop:(NSAnimation *)animation 72 | { 73 | if (self.completionBlock) self.completionBlock(NO); 74 | } 75 | @end 76 | -------------------------------------------------------------------------------- /INDockableWindow/NSView+INImagingAdditions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSView+INImagingAdditions.h 3 | // Flamingo 4 | // 5 | // Created by Indragie Karunaratne on 2013-03-02. 6 | // Copyright (c) 2013 Indragie Karunaratne. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSView (INImagingAdditions) 12 | @property (nonatomic, strong, readonly) NSImage *in_image; 13 | @end 14 | -------------------------------------------------------------------------------- /INDockableWindow/NSView+INImagingAdditions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSView+INImagingAdditions.m 3 | // Flamingo 4 | // 5 | // Created by Indragie Karunaratne on 2013-03-02. 6 | // Copyright (c) 2013 Indragie Karunaratne. All rights reserved. 7 | // 8 | 9 | #import "NSView+INImagingAdditions.h" 10 | 11 | @implementation NSView (INImagingAdditions) 12 | - (NSImage *)in_image 13 | { 14 | NSSize viewSize = [self bounds].size; 15 | NSBitmapImageRep *bir = [self bitmapImageRepForCachingDisplayInRect:[self bounds]]; 16 | [bir setSize:viewSize]; 17 | [self cacheDisplayInRect:[self bounds] toBitmapImageRep:bir]; 18 | NSImage* image = [[NSImage alloc] initWithSize:viewSize]; 19 | [image addRepresentation:bir]; 20 | return image; 21 | } 22 | @end 23 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | **Copyright (c) 2013, Indragie Karunaratne. All rights reserved.** 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## INDockableWindow 2 | ### Dockable window controller for AppKit 3 | 4 | #### Overview 5 | 6 | `INDockableWindow` is a collection of classes that allows you to create a column based application UI, where each column can be "docked" to a primary window and also separated into its own window by dragging on a detach handle. This type of UI can be seen in [Tweetbot for Mac](http://tapbots.com/software/tweetbot/mac/), for example. 7 | 8 | **NOTE: This control, while feature complete, is still in early development, and is to be considered beta quality code at best.** 9 | 10 | #### Features 11 | 12 | * **Simple API.** There's really only 2 or 3 classes you'll need to interact with. 13 | * **Fully customizable.** Everything, including size constraints, split view appearance, and the windows themselves are customizable. 14 | * **Built on [INAppStoreWindow](https://github.com/indragiek/INAppStoreWindow)**. Every window is a subclass of `INAppStoreWindow`, so customizing the title bar and traffic lights is trivial. 15 | * **User draggable split dividers.** When the views are docked on the main window, the size of each view is resizable via user draggable split dividers. The views maintain this width when they're popped into separate windows. 16 | * **Smooth transition.** The smoothness of the transition between a docked view and an undocked window was a major consideration for this project, and the transition between the two is as fluid as possible. 17 | * **Drag auxiliary windows near the primary window to attach and detach.** They work like magnets! 18 | 19 | #### Adding it to your project 20 | 21 | * Clone this repository 22 | * Run `git submodule update --init --recursive` to download `INAppStoreWindow` 23 | * Add the `INAppStoreWindow` and `INDockableWindow` source code files to your project 24 | 25 | ##### ARC 26 | 27 | `INDockableWindow` **requires ARC**. If your project doesn't use ARC, add the `-fobjc-arc` compiler flag to all of the `INDockableWindow` source files. 28 | 29 | ##### Auto Layout 30 | 31 | `INDockableWindow` **does not support auto layout**. The behaviour is undefined when using auto layout. 32 | 33 | 34 | #### Example 35 | 36 | The project includes a simple example application that demonstrates docking and undocking with a 2 column layout: 37 | 38 | ![Docked](http://i.imgur.com/RtQtA4i.png) 39 | ![Undocked](http://i.imgur.com/5xNlePB.png) 40 | 41 | I hope to write a more advanced example project at some point. 42 | 43 | #### Documentation 44 | 45 | Full documentation is inside the Documentation folder. The headers are also fully documented. 46 | 47 | #### Getting Started 48 | 49 | * Create a new instance of `INDockableWindowController` 50 | * Assign the primary view controller (the "core view" that will always be displayed) to `primaryViewController`. 51 | * Add additional view controllers using `-addViewController:attached:` 52 | 53 | #### Contribution 54 | 55 | Contributions via pull requests are always very welcome. I would greatly appreciate any fixes to bugs that you encounter, or implementation of additional features. 56 | 57 | #### Contact 58 | 59 | * Indragie Karunaratne 60 | * [@indragie](http://twitter.com/indragie) 61 | * [http://indragie.com](http://indragie.com) 62 | 63 | #### License 64 | 65 | `INDockableWindow` is licensed under MIT. See LICENSE.md for more information. 66 | --------------------------------------------------------------------------------