// ========================================================================== // Project: SproutCore - JavaScript Application Framework // Copyright: ©2006-2010 Sprout Systems, Inc. and contributors. // Portions ©2008-2010 Apple Inc. All rights reserved. // License: Licensed under MIT license (see license.js) // ========================================================================== sc_require('ext/menu_item'); /** @class Extends SC.MenuPane to add support for automatic resizing. */ SC.AutoResizingMenuPane = SC.MenuPane.extend( /** @scope SC.AutoResizingMenuPane.prototype */ { /** If YES, the menu should automatically resize its width to fit its items. This will swap out the default SC.MenuItemView. If you are using a custom exampleView, you will need to mix SC.AutoResize into your exampleView and set shouldAutoResize to NO (the actual resizing will be handled by SC.MenuPane). This property must be set before instantiation; any changes after instantiation will not function properly. @property @type {Boolean} @default YES */ shouldAutoResize: YES, /** The minimum width for this menu if it is to be automatically resized. If no value is specified, it will be determined from the controlSize. @type Number @default minimumMenuWidth from render delegate, or 0. */ minimumMenuWidth: SC.propertyFromRenderDelegate('minimumMenuWidth', 0), /** The amount to add to any calculated width. If no value is specified, it will be determined from the controlSize. @type Number @default menuWidthPadding from render delegate, or 0 */ menuWidthPadding: SC.propertyFromRenderDelegate('menuWidthPadding', 0), /** The view class to use when creating new menu item views. The menu pane will automatically create an instance of the view class you set here for each item in the `items` array. You may provide your own subclass for this property to display the customized content. @type SC.View @default SC.AutoResizingMenuItemView */ exampleView: SC.AutoResizingMenuItemView, /** @private In addition to the normal init, we need to schedule an automatic resize. */ init: function() { sc_super(); if (this.get('shouldAutoResize')) { this.invokeOnce('_updateMenuWidth'); } }, /** The array of child menu item views that compose the menu. This computed property parses @displayItems@ and constructs an SC.MenuItemView (or whatever class you have set as the @exampleView@) for every item. @property @type Array @readOnly @private */ createMenuItemViews: function() { // EXTENDED to set shouldMeasureSize to its initial value and to // observe the measured size. var views = sc_super(); var idx, len = views.length, view; if (this.get('shouldAutoResize')) { for (idx = 0; idx < len; idx++) { view = views[idx]; // set up resizing if we want view.set('shouldMeasureSize', YES); view.addObserver('measuredSize', this, this._menuItemMeasuredSizeDidChange); } } return views; }, _menuItemViewsDidChange: function() { if (this.get('shouldAutoResize')) this.invokeOnce('_updateMenuWidth'); }.observes('menuItemViews'), _menuItemMeasuredSizeDidChange: function(menuItem) { this.invokeOnce('_updateMenuWidth'); }, _menuMinimumMenuWidthDidChange: function() { this.invokeOnce('_updateMenuWidth'); }.observes('minimumMenuWidth'), _updateMenuWidth: function() { var menuItemViews = this.get('menuItemViews'); if (!menuItemViews) return; var len = menuItemViews.length, idx, view, width = this.get('minimumMenuWidth'); for (idx = 0; idx < len; idx++) { view = menuItemViews[idx]; width = Math.max(width, view.get('measuredSize').width + this.get('menuWidthPadding')); } this.adjust({ 'width': width, height: this.get('menuHeight') }); this.positionPane(); } });