1 // ========================================================================== 2 // Project: SproutCore - JavaScript Application Framework 3 // Copyright: ©2006-2010 Sprout Systems, Inc. and contributors. 4 // Portions ©2008-2010 Apple Inc. All rights reserved. 5 // License: Licensed under MIT license (see license.js) 6 // ========================================================================== 7 8 sc_require('ext/menu_item'); 9 10 /** 11 @class 12 Extends SC.MenuPane to add support for automatic resizing. 13 */ 14 15 SC.AutoResizingMenuPane = SC.MenuPane.extend( 16 /** @scope SC.AutoResizingMenuPane.prototype */ { 17 18 /** 19 If YES, the menu should automatically resize its width to fit its items. 20 21 This will swap out the default SC.MenuItemView. If you are using a custom 22 exampleView, you will need to mix SC.AutoResize into your exampleView 23 and set shouldAutoResize to NO (the actual resizing will be handled 24 by SC.MenuPane). 25 26 This property must be set before instantiation; any changes after instantiation 27 will not function properly. 28 29 @property 30 @type {Boolean} 31 @default YES 32 */ 33 shouldAutoResize: YES, 34 35 /** 36 The minimum width for this menu if it is to be automatically resized. 37 38 If no value is specified, it will be determined from the controlSize. 39 40 @type Number 41 @default minimumMenuWidth from render delegate, or 0. 42 */ 43 minimumMenuWidth: SC.propertyFromRenderDelegate('minimumMenuWidth', 0), 44 45 /** 46 The amount to add to any calculated width. 47 48 If no value is specified, it will be determined from the controlSize. 49 50 @type Number 51 @default menuWidthPadding from render delegate, or 0 52 */ 53 menuWidthPadding: SC.propertyFromRenderDelegate('menuWidthPadding', 0), 54 55 /** 56 The view class to use when creating new menu item views. 57 58 The menu pane will automatically create an instance of the view class you 59 set here for each item in the `items` array. You may provide your own 60 subclass for this property to display the customized content. 61 62 @type SC.View 63 @default SC.AutoResizingMenuItemView 64 */ 65 exampleView: SC.AutoResizingMenuItemView, 66 67 /** 68 @private 69 In addition to the normal init, we need to schedule an automatic resize. 70 */ 71 init: function() { 72 sc_super(); 73 74 if (this.get('shouldAutoResize')) { 75 this.invokeOnce('_updateMenuWidth'); 76 } 77 }, 78 79 /** 80 The array of child menu item views that compose the menu. 81 82 This computed property parses @displayItems@ and constructs an SC.MenuItemView (or whatever class you have set as the @exampleView@) for every item. 83 84 @property 85 @type Array 86 @readOnly 87 @private 88 */ 89 createMenuItemViews: function() { 90 // EXTENDED to set shouldMeasureSize to its initial value and to 91 // observe the measured size. 92 var views = sc_super(); 93 94 var idx, len = views.length, view; 95 if (this.get('shouldAutoResize')) { 96 for (idx = 0; idx < len; idx++) { 97 view = views[idx]; 98 99 // set up resizing if we want 100 view.set('shouldMeasureSize', YES); 101 view.addObserver('measuredSize', this, this._menuItemMeasuredSizeDidChange); 102 } 103 } 104 105 return views; 106 }, 107 108 _menuItemViewsDidChange: function() { 109 if (this.get('shouldAutoResize')) this.invokeOnce('_updateMenuWidth'); 110 }.observes('menuItemViews'), 111 112 _menuItemMeasuredSizeDidChange: function(menuItem) { 113 this.invokeOnce('_updateMenuWidth'); 114 }, 115 116 _menuMinimumMenuWidthDidChange: function() { 117 this.invokeOnce('_updateMenuWidth'); 118 }.observes('minimumMenuWidth'), 119 120 _updateMenuWidth: function() { 121 var menuItemViews = this.get('menuItemViews'); 122 if (!menuItemViews) return; 123 124 var len = menuItemViews.length, idx, view, 125 width = this.get('minimumMenuWidth'); 126 127 for (idx = 0; idx < len; idx++) { 128 view = menuItemViews[idx]; 129 width = Math.max(width, view.get('measuredSize').width + this.get('menuWidthPadding')); 130 } 131 132 133 this.adjust({ 'width': width, height: this.get('menuHeight') }); 134 this.positionPane(); 135 } 136 }); 137