1 // Copyright: ©2006-2010 Sprout Systems, Inc. and contributors.
  2 //            Portions ©2008-2010 Apple Inc. All rights reserved.
  3 // License:   Licensed under MIT license (see license.js)
  4 // ==========================================================================
  5 
  6 /**
  7  * Binds a menu view to an owning SC.SelectView, and checks selected items.
  8  *
  9  * @mixin
 10  *
 11  */
 12 SC.SelectViewMenu = {
 13   /**
 14     The SelectView to bind to.
 15     
 16     @property
 17     @type {SC.SelectView}
 18     @default null
 19   */
 20   selectView: null,
 21 
 22   //
 23   // CODE TO MAKE ITEMS BE CHECKED WHEN SELECTED:
 24   //
 25   
 26   /**
 27     The current value of the SelectView.
 28     
 29     @property
 30     @default null
 31   */
 32   value: null,
 33   valueBinding: '.selectView.value',
 34 
 35 
 36   /** 
 37     @private 
 38     Invalidates menu items' isChecked property when the selectView's value changes.
 39   */
 40   valueDidChange: function() {
 41     var items = this.get('menuItemViews'), idx, len = items.length, item;
 42     for (idx = 0; idx < len; idx++) {
 43       // if the item currently is checked, or if it _should_ be checked, we need to
 44       // invalidate the isChecked property.
 45       item = items[idx];
 46       if (item._lastIsChecked) {
 47         item.notifyPropertyChange('isChecked');
 48       }
 49 
 50       if (item.get('isChecked')) {
 51         item.notifyPropertyChange('isChecked');
 52       }
 53     }
 54   }.observes('value'),
 55 
 56   /**
 57     An overridden MenuItemView to create for each menu item that makes itself checked if
 58     it is selected.
 59     
 60     @property
 61     @type {SC.MenuItemView}
 62     @default SC.MenuItemView subclass
 63   */
 64   exampleView: SC.AutoResizingMenuItemView.extend({
 65     isChecked: function() {
 66       var selectView = this.getPath('parentMenu.selectView');
 67 
 68       // _lastIsChecked is used by the SelectViewMenu mixin above to determine whether
 69       // the isChecked property needs to be invalidated.
 70       this._lastIsChecked = selectView.isValueEqualTo(this.get('content'));
 71       
 72       return this._lastIsChecked;
 73     }.property(),
 74 
 75     displayProperties: ['isChecked']
 76   }),
 77 
 78   //
 79   // CODE TO BIND TO SELECTVIEW PROPERTIES
 80   //
 81   
 82   /** @private */
 83   _svm_bindToProperties: [
 84     { from: 'displayItems', to: 'items' },
 85     { from: '_itemTitleKey', to: 'itemTitleKey' },
 86     { from: '_itemIsEnabledKey', to: 'itemIsEnabledKey' },
 87     { from: '_itemValueKey', to: 'itemValueKey' },
 88     'itemIconKey', 'itemHeightKey', 'itemSubMenuKey', 'itemSeparatorKey', 
 89     'itemTargetKey', 'itemActionKey', 'itemCheckboxKey', 'itemShortCutKey',
 90     'itemKeyEquivalentKey', 'itemDisableMenuFlashKey', 'minimumMenuWidth',
 91     'target', 'action',
 92     'preferType', 'preferMatrix'
 93   ],
 94 
 95   /** @private */
 96   _svm_setupBindings: function() {
 97     var bindTo = this.get('selectView');
 98     if (!bindTo) {
 99       return;
100     }
101 
102     var props = this._svm_bindToProperties, idx, len = props.length, from, to;
103 
104     for (idx = 0; idx < len; idx++) {
105       from = to = props[idx];
106 
107       if (SC.typeOf(from) === SC.T_HASH) {
108         from = from.from;
109         to = to.to;
110       }
111       this[to + 'Binding'] = this.bind(to, bindTo, from);
112     }
113 
114     this._svm_isBoundTo = bindTo;
115   },
116 
117   /** @private */
118   _svm_clearBindings: function() {
119     var boundTo = this._svm_isBoundTo;
120     if (!boundTo) {
121       return;
122     }
123 
124     var props = this._svm_bindToProperties, idx, len = props.length, key;
125 
126     for (idx = 0; idx < len; idx++) {
127       key = props[idx];
128 
129       if (SC.typeOf(from) === SC.T_HASH) {
130         key = key.to;
131       }
132       this[key + 'Binding'].disconnect();
133     }
134   },
135 
136   /** @private */
137   _svm_selectViewDidChange: function() {
138     this._svm_clearBindings();
139     this._svm_setupBindings();
140   }.observes('selectView'),
141 
142   /** @private */
143   initMixin: function() {
144     this._svm_setupBindings();
145   },
146 
147   /** @private */
148   destroyMixin: function() {
149     this._svm_clearBindings();
150   }
151 };
152 
153 
154