1 // ========================================================================== 2 // Project: SproutCore - JavaScript Application Framework 3 // Copyright: ©2006-2011 Strobe Inc. and contributors. 4 // Portions ©2008-2011 Apple Inc. All rights reserved. 5 // License: Licensed under MIT license (see license.js) 6 // ========================================================================== 7 8 /** 9 @namespace 10 11 A Collection View Delegate is consulted by a `SC.CollectionView` to make 12 policy decisions about certain behaviors such as selection control and 13 drag and drop. If you need to control other aspects of your data, you may 14 also want to add the `SC.CollectionContent` mixin. 15 16 To act as a Collection Delegate, just apply this mixin to your class. You 17 must then set the "delegate" property on the CollectionView to your object. 18 19 Alternatively, if no delegate is set on a CollectionView, but the content 20 implements this mixin, the content object will be used as the delegate 21 instead. 22 23 If you set an ArrayController or its arrangedObjects property as the content 24 of a CollectionView, the ArrayController will automatically act as the 25 delegate for the view. 26 27 @since SproutCore 1.0 28 */ 29 SC.CollectionViewDelegate = { 30 31 /** 32 Walk like a duck. Used to detect the mixin by SC.CollectionView. 33 34 @type Boolean 35 @default YES 36 @constant 37 */ 38 isCollectionViewDelegate: YES, 39 40 41 // .......................................................... 42 // SELECTION 43 // 44 45 /** 46 This method will be called anytime the collection view is about to 47 change the selection in response to user mouse clicks or keyboard events. 48 49 You can use this method to adjust the proposed selection, eliminating any 50 selected objects that cannot be selected. The default implementation of 51 this method simply returns the proposed selection. 52 53 @param {SC.CollectionView} view the collection view 54 @param {SC.IndexSet} sel Proposed array of selected objects. 55 @returns {SC.IndexSet} Actual allow selection index set 56 */ 57 collectionViewSelectionForProposedSelection: function(view, sel) { 58 return sel; 59 }, 60 61 /** 62 Called by the collection when attempting to select an item. Return the 63 actual indexes you want to allow to be selected. Return null to disallow 64 the change. The default allows all selection. 65 66 @param {SC.CollectionView} view the view collection view 67 @param {SC.IndexSet} indexes the indexes to be selected 68 @param {Boolean} extend YES if the indexes will extend existing sel 69 @returns {SC.IndexSet} allowed index set 70 */ 71 collectionViewShouldSelectIndexes: function (view, indexes, extend) { 72 return indexes; 73 }, 74 75 /** 76 Called by the collection when attempting to deselect an item. Return the 77 actual indexes you want to allow to be deselected. Return `null` to 78 disallow the change. The default allows all selection. 79 80 Note that you should not modify the passed in IndexSet. clone it instead. 81 82 @param {SC.CollectionView} view the view collection view 83 @param {SC.IndexSet} indexes the indexes to be selected 84 @returns {SC.IndexSet} allowed index set 85 */ 86 collectionViewShouldDeselectIndexes: function (view, indexes) { 87 return indexes; 88 }, 89 90 91 // .......................................................... 92 // EDIT OPERATIONS 93 // 94 95 /** 96 Called by the collection view whenever the `deleteSelection()` method is 97 called. You can implement this method to get fine-grained control over 98 which items can be deleted. To prevent deletion, return null. 99 100 This method is only called if canDeleteContent is `YES` on the collection 101 view. 102 103 @param {SC.CollectionView} view the collection view 104 @param {SC.IndexSet} indexes proposed index set of items to delete. 105 @returns {SC.IndexSet} index set allowed to delete or null. 106 */ 107 collectionViewShouldDeleteIndexes: function(view, indexes) { 108 return indexes; 109 }, 110 111 /** 112 Called by the collection view to actually delete the selected items. 113 114 The default behavior will use standard array operators to delete the 115 indexes from the array. You can implement this method to provide your own 116 deletion method. 117 118 If you simply want to control the items to be deleted, you should instead 119 implement `collectionViewShouldDeleteItems()`. This method will only be 120 called if canDeleteContent is `YES` and `collectionViewShouldDeleteIndexes()` 121 returns a non-empty index set 122 123 @param {SC.CollectionView} view collection view 124 @param {SC.IndexSet} indexes the items to delete 125 @returns {Boolean} YES if the deletion was a success. 126 */ 127 collectionViewDeleteContent: function(view, content, indexes) { 128 if (!content) return NO ; 129 130 if (SC.typeOf(content.destroyAt) === SC.T_FUNCTION) { 131 content.destroyAt(indexes); 132 view.selectPreviousItem(NO, 1); 133 return YES ; 134 } else if (SC.typeOf(content.removeAt) === SC.T_FUNCTION) { 135 content.removeAt(indexes); 136 view.selectPreviousItem(NO, 1); 137 return YES; 138 } else { 139 return NO; 140 } 141 }, 142 143 144 // .......................................................... 145 // DRAGGING 146 // 147 148 /** 149 Called by the collection view just before it starts a drag to give you 150 an opportunity to decide if the drag should be allowed. 151 152 You can use this method to implement fine-grained control over when a 153 drag will be allowed and when it will not be allowed. For example, you 154 may enable content reordering but then implement this method to prevent 155 reordering of certain items in the view. 156 157 The default implementation always returns `YES`. 158 159 @param {SC.CollectionView} view the collection view 160 @returns {Boolean} YES to allow, NO to prevent it 161 */ 162 collectionViewShouldBeginDrag: function(view) { 163 return YES; 164 }, 165 166 /** 167 Called by the collection view just before it starts a drag so that 168 you can provide the data types you would like to support in the data. 169 170 You can implement this method to return an array of the data types you 171 will provide for the drag data. 172 173 If you return `null` or an empty array, can you have set `canReorderContent` 174 to `YES` on the CollectionView, then the drag will go ahead but only 175 reordering will be allowed. If `canReorderContent` is `NO`, then the drag 176 will not be allowed to start. 177 178 If you simply want to control whether a drag is allowed or not, you 179 should instead implement `collectionViewShouldBeginDrag()`. 180 181 The default returns an empty array. 182 183 @param {SC.CollectionView} view the collection view to begin dragging. 184 @returns {Array} array of supported data types. 185 */ 186 collectionViewDragDataTypes: function(view) { 187 return []; 188 }, 189 190 /** 191 Called by a collection view when a drag concludes to give you the option 192 to provide the drag data for the drop. 193 194 This method should be implemented essentially as you would implement the 195 `dragDataForType()` if you were a drag data source. You will never be asked 196 to provide drag data for a reorder event, only for other types of data. 197 198 The default implementation returns null. 199 200 @param view {SC.CollectionView} the collection view that initiated the drag 201 @param dataType {String} the data type to provide 202 @param drag {SC.Drag} the drag object 203 @returns {Object} the data object or null if the data could not be provided. 204 */ 205 collectionViewDragDataForType: function(view, drag, dataType) { 206 return null; 207 }, 208 209 /** 210 Called once during a drag the first time view is entered. Return all 211 possible drag operations OR'd together. 212 213 @param {SC.CollectionView} view the collection view that initiated the drag 214 @param {SC.Drag} drag the drag object 215 @param {Number} proposedDragOperations proposed logical OR of allowed drag operations. 216 @returns {Number} the allowed drag operations. Defaults to op 217 */ 218 collectionViewComputeDragOperations: function(view, drag, proposedDragOperations) { 219 return proposedDragOperations; 220 }, 221 222 /** 223 Called by the collection view during a drag to let you determine the 224 kind and location of a drop you might want to accept. 225 226 You can override this method to implement fine-grained control over how 227 and when a dragged item is allowed to be dropped into a collection view. 228 229 This method will be called by the collection view both to determine in 230 general which operations you might support and specifically the operations 231 you would support if the user dropped an item over a specific location. 232 233 If the `proposedDropOperation` parameter is `SC.DROP_ON` or `SC.DROP_BEFORE`, 234 then the `proposedInsertionPoint` will be a non-negative value and you 235 should determine the specific operations you will support if the user 236 dropped the drag item at that point. 237 238 If you do not like the proposed drop operation or insertion point, you 239 can override these properties as well by setting the `proposedDropOperation` 240 and `proposedInsertionIndex` properties on the collection view during this 241 method. These properties are ignored all other times. 242 243 @param {SC.CollectionView} view the collection view 244 @param {SC.Drag} drag the current drag object 245 @param {Number} op proposed logical OR of allowed drag operations. 246 @param {Number} proposedInsertionIndex an index into the content array representing the proposed insertion point. 247 @param {String} proposedDropOperation the proposed drop operation. Will be one of SC.DROP_ON, SC.DROP_BEFORE, or SC.DROP_ANY. 248 @returns the allowed drag operation. Defaults to op 249 */ 250 collectionViewValidateDragOperation: function(view, drag, op, proposedInsertionIndex, proposedDropOperation) { 251 // don't allow dropping on by default 252 return (proposedDropOperation & SC.DROP_ON) ? SC.DRAG_NONE : op ; 253 }, 254 255 /** 256 Called by the collection view to actually accept a drop. This method will 257 only be invoked AFTER your `validateDrop method has been called to 258 determine if you want to even allow the drag operation to go through. 259 260 You should actually make changes to the data model if needed here and 261 then return the actual drag operation that was performed. If you return 262 `SC.DRAG_NONE` and the dragOperation was `SC.DRAG_REORDER`, then the default 263 reorder behavior will be provided by the collection view. 264 265 @param {SC.CollectionView} view 266 @param {SC.Drag} drag the current drag object 267 @param {Number} op proposed logical OR of allowed drag operations. 268 @param {Number} proposedInsertionIndex an index into the content array representing the proposed insertion point. 269 @param {String} proposedDropOperation the proposed drop operation. Will be one of SC.DROP_ON, SC.DROP_BEFORE, or SC.DROP_ANY. 270 @returns the allowed drag operation. Defaults to proposedDragOperation 271 */ 272 collectionViewPerformDragOperation: function(view, drag, op, proposedInsertionIndex, proposedDropOperation) { 273 return SC.DRAG_NONE; 274 }, 275 276 /** 277 Renders a drag view for the passed content indexes. If you return null 278 from this, then a default drag view will be generated for you. 279 280 The default implementation returns null. 281 282 @param {SC.CollectionView} view 283 @param {SC.IndexSet} dragContent 284 @returns {SC.View} view or null 285 */ 286 collectionViewDragViewFor: function(view, dragContent) { 287 return null; 288 }, 289 290 /** 291 Allows the ghost view created in `collectionViewDragViewFor` to be displayed 292 like a cursor instead of the default implementation. This sets the view 293 origin to be the location of the mouse cursor. 294 295 @type Boolean 296 @default NO 297 */ 298 ghostActsLikeCursor: NO 299 300 }; 301