// ==========================================================================
// 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.
    
    @property {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.
    
    @property {Number}
    @default menuWidthPadding from render delegate, or 0
  */
  menuWidthPadding: SC.propertyFromRenderDelegate('menuWidthPadding', 0),

  /**
    @private
    In addition to the normal init, we need to schedule an automatic resize.
  */
  init: function() {
    arguments.callee.base.apply(this,arguments);
    
    this.set('exampleView', SC.AutoResizingMenuItemView);

    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 = arguments.callee.base.apply(this,arguments);

    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);
    this.positionPane();
  }
});
