// ========================================================================== // Project: SproutCore - JavaScript Application Framework // Copyright: ©2006-2011 Strobe Inc. and contributors. // portions copyright @2011 Apple Inc. // License: Licensed under MIT license (see license.js) // ========================================================================== /*global module, test, same, ok, CoreTest */

var scrollView, view;

module(“SC.GridView”, {

setup: function () {

  SC.run(function () {
    view = SC.GridView.create({
      columnWidth: 100,

      content: "a b c d e f".w().map(function (x) {
        return SC.Object.create({ title: x });
      }),

      // ..........................................................
      // STUB: itemViewForContentIndex
      //
      itemViewForContentIndex: CoreTest.stub('itemViewForContentIndex', SC.GridView.prototype.itemViewForContentIndex),

      layout: { minWidth: 200 },

      // ..........................................................
      // STUB: layoutForContentIndex
      //
      layoutForContentIndex: CoreTest.stub('layoutForContentIndex', SC.GridView.prototype.layoutForContentIndex),

      // ..........................................................
      // STUB: adjustLayout
      //
      adjustLayout: CoreTest.stub('adjustLayout', SC.CollectionView.prototype.adjustLayout)

    });

    scrollView = SC.ScrollView.create({
      contentView: view,

      layout: { centerX: 0, centerY: 0, height: 400, width: 200 }
    });
  });

},

teardown: function () {
  view = scrollView = null;
}

});

/**

GridView used to position items according to its clippingFrame, which meant
that a GridView could not specify a frame width in order to scroll
horizontally.  This also manifested in a bug where itemsPerRow was based on
frame but clippingFrame would change first so that GridView's would not
update properly when clippingFrame changed and frame did not change.  For
example during a rotation on an iPad.

*/ test(“GridView items should be positioned according to frame”, function () {

var layout,
  expectedLayout;

layout = view.layoutForContentIndex(0);
expectedLayout = { left: 0, top: 0, height: 48, width: 100 };
same(layout, expectedLayout, "Layout of first item should be");

layout = view.layoutForContentIndex(1);
expectedLayout = { left: 100, top: 0, height: 48, width: 100 };
same(layout, expectedLayout, "Layout of second item should be");

layout = view.layoutForContentIndex(2);
expectedLayout = { left: 0, top: 48, height: 48, width: 100 };
same(layout, expectedLayout, "Layout of third item should be");

layout = view.layoutForContentIndex(3);
expectedLayout = { left: 100, top: 48, height: 48, width: 100 };
same(layout, expectedLayout, "Layout of fourth item should be");

SC.RunLoop.begin();
scrollView.adjust('width', 100);
SC.RunLoop.end();

layout = view.layoutForContentIndex(0);
expectedLayout = { left: 0, top: 0, height: 48, width: 100 };
same(layout, expectedLayout, "Layout of first item should be");

layout = view.layoutForContentIndex(1);
expectedLayout = { left: 100, top: 0, height: 48, width: 100 };
same(layout, expectedLayout, "Layout of second item should be");

layout = view.layoutForContentIndex(2);
expectedLayout = { left: 0, top: 48, height: 48, width: 100 };
same(layout, expectedLayout, "Layout of third item should be");

layout = view.layoutForContentIndex(3);
expectedLayout = { left: 100, top: 48, height: 48, width: 100 };
same(layout, expectedLayout, "Layout of fourth item should be");

});

/*

GridView would adjust all of its item views every time that its frame
changed (which happens on scroll), which was very wasteful.  Instead, it was
improved to only reposition the nowShowing item views, which improved the
efficiency and also allowed the content to be sparse.  Finally, since the
position of the item views is only effected by changes to the frame's
width and not its x, y or height properties.  We can optimize it further to
only adjust item views when the width is different.

*/ test(“Optimized re-position of item views when the frame changes.”, function () {

view.itemViewForContentIndex.expect(0);
view.layoutForContentIndex.expect(0);

SC.RunLoop.begin();
view.notifyPropertyChange('frame');
SC.RunLoop.end();

view.itemViewForContentIndex.expect(0);
view.layoutForContentIndex.expect(0);

SC.RunLoop.begin();
view.adjust('height', 500);
SC.RunLoop.end();

view.itemViewForContentIndex.expect(0);
view.layoutForContentIndex.expect(0);

SC.RunLoop.begin();
view.adjust('width', 400);
SC.RunLoop.end();

// Six item requests, twelve layout requests
view.itemViewForContentIndex.expect(6);
view.layoutForContentIndex.expect(12);

});

/**

GridView used to not re-compute its layout when the frame changed, which meant
that if the itemsPerRow changed the calculated height of the grid would not
update to fit the new number of rows.

*/ test(“Adjusts layout when the itemsPerRow changes.”, function () {

// adjustLayout is called once on initialization so that the layout "style" that the view will be using
// is known.
view.adjustLayout.expect(2);

SC.RunLoop.begin();
view.notifyPropertyChange('frame');
SC.RunLoop.end();

view.adjustLayout.expect(2);

SC.RunLoop.begin();
view.adjust('height', 500);
SC.RunLoop.end();

view.adjustLayout.expect(2);

SC.RunLoop.begin();
view.adjust('width', 400);
SC.RunLoop.end();

view.adjustLayout.expect(3);

});

test(“computeLayout gives back sane values when itemsPerRow is 0”, function () {

SC.RunLoop.begin();
view.adjust('width', 0);
SC.RunLoop.end();

var layout = view.computeLayout();
var minHeightIsInfinity = layout.minHeight === Infinity;
ok(!minHeightIsInfinity, "SC.GridView#computeLayout should not have Infinity as value for layout.minHeight");

});