1 // ==========================================================================
  2 // Project:   SproutCore - JavaScript Application Framework
  3 // Copyright: ©2006-2011 Strobe Inc. and contributors.
  4 //            Portions ©2008-2011 Apple Inc. All rights reserved.
  5 // License:   Licensed under MIT license (see license.js)
  6 // ==========================================================================
  7 /*global test Q$ */
  8 
  9 // TODO: IMPROVE CODE QUALITY.  This code was put together quickly in order to
 10 // test the SproutCore framework.  It does not match up to the project's
 11 // normal documentation, design and coding standards.  Do not rely on this
 12 // code as an example of how to build your own applications.
 13 
 14 /** @class
 15   Generates a pane that will display vertically stacked views for testing.
 16   You can use this class in test mode to easily create a palette with views
 17   configured in different ways.
 18 
 19   # Example
 20 
 21       var pane = SC.ControlTestPane.design()
 22         .add('basic', SC.CheckboxView.design({ title: "Hello World" }))
 23         .add('disabled', SC.CheckboxView.design({
 24           title: "Hello World", isEnabled: NO
 25         }));
 26 
 27       module("CheckboxView UI", pane);
 28 
 29       test("basic", function() {
 30         var view = pane.view('basic');
 31         ok(view.get('isEnabled'), 'should be enabled');
 32       });
 33 
 34   @extends SC.Pane
 35   @since SproutCore 1.0
 36 */
 37 SC.ControlTestPane = SC.Pane.extend(
 38 /** @scope SC.ControlTestPane.prototype */ {
 39 
 40   classNames: ['sc-control-test-pane'],
 41   layout: { right: 20, width: 350, top: 65, bottom: 5 },
 42 
 43   /**
 44     The starting top location for the first row.  This will increment as
 45     views are added to the pane.
 46 
 47     @type Number
 48     @default 0
 49   */
 50   top: 0,
 51 
 52   /**
 53     The default height of each row.  This will be used for a view unless you
 54     manually specify a height in the view's layout.
 55 
 56     @type Number
 57     @default 20
 58   */
 59   height: 20,
 60 
 61   /**
 62     The default padding added to the edges and between each row.
 63 
 64     @type Number
 65     @default 4
 66   */
 67   padding: 4,
 68 
 69   /**
 70     Retrieves the test sample view that was added with the passed key name.
 71 
 72     @param {String} keyName the key used to register the view.
 73     @returns {SC.View} view instance
 74   */
 75   view: function(keyName) {
 76     var idx = this._views[keyName];
 77     if (!idx) throw new Error("SC.ControlTestPane does not have a view named %@".fmt(keyName));
 78     return this.childViews[idx].childViews[0];
 79   },
 80 
 81   /** @private */
 82   init: function() {
 83     sc_super();
 84     if (!this._views) this._views = {};
 85     this.append(); // auto-add to screen
 86 
 87     // Also adjust unit test results to make space
 88     // use setTimeout to avoid screwing with the RunLoop which we might be
 89     // testing.
 90     var l = this.get('layout'), w = l.right + l.width;
 91     setTimeout(function() {
 92       if (!Q$) return ; // nothing to do
 93       Q$('.core-test > .detail').css('marginRight', w);
 94     }, 100);
 95   }
 96 });
 97 
 98 /**
 99   Adds a test view to the control pane design.  The passed label will be used
100   as the key which you can use to find the view layer.  You can either pass
101   a view that is already designed or pass an array of attributes that will be
102   used to create a design on the view.
103 
104   @param {String} label the view key name
105   @param {SC.View} view a view class or view design
106   @param {Hash} attrs optional attrs to use when designing the view
107   @returns {SC.ControlTestPane} receiver
108 */
109 SC.ControlTestPane.add = function(label, view, attrs) {
110   if (attrs === undefined) attrs = {};
111   if (!view.isDesign) view = view.design(attrs);
112 
113   // compute layout.
114   var padding = this.prototype.padding, height = this.prototype.height;
115   var top = this.prototype.top + padding*2, layout;
116   var labelHeight =14;
117   if (top === padding*2) top = padding; // reduce padding @ top
118 
119   // if the passed in view has a layout property and the layout has an
120   // explicit, numerical height, then use that instead.
121   if (view.prototype.layout && (typeof view.prototype.layout.height === SC.T_NUMBER)) height = view.prototype.layout.height;
122 
123   this.prototype.top = top + height+labelHeight+(padding*2); // make room
124 
125   // calculate labelView and add it
126   layout = { left: padding, width: 150, top: top, height: 20 };
127   var labelView = SC.LabelView.design({
128     value: label + ':',
129     layout: { left: 0, right: 0, top: 0, height: labelHeight },
130    // TODO: textAlign: SC.ALIGN_RIGHT,
131     // TODO: fontWeight: SC.BOLD_WEIGHT
132   });
133 
134   // wrap label in parent view in order to center text vertically
135   labelView = SC.View.design().layout(layout).childView(labelView);
136   this.childView(labelView);
137 
138   // now layout view itself...
139   var wrapper = SC.View.design({
140     classNames: ['wrapper'],
141     layout: { left: padding, top: top+labelHeight+padding, right: padding, height: height },
142     childViews: [view]
143   });
144   var idx = this.prototype.childViews.length ;
145   this.childView(wrapper);
146 
147   var views = this.prototype._views;
148   if (!views) views = this.prototype._views = {};
149   views[label] = idx ;
150 
151   return this;
152 };
153 
154 /**
155   Returns a standard setup/teardown object for use by the module() method.
156 */
157 SC.ControlTestPane.standardSetup = function() {
158   var pane = this ;
159   return {
160     setup: function() {
161       SC.RunLoop.begin();
162       pane._pane = pane.create();
163       SC.RunLoop.end();
164     },
165 
166     teardown: function() {
167       SC.RunLoop.begin();
168       if (pane._pane) pane._pane.destroy();
169       SC.RunLoop.end();
170 
171       pane._pane = null ;
172     }
173   } ;
174 };
175 
176 /**
177   Convenience method.  Returns the view with the given name on the current
178   pane instance if there is one.
179 
180   @param {String} keyName the key used to register the view.
181   @returns {SC.View} view instance
182 */
183 SC.ControlTestPane.view = function(viewKey) {
184   var pane = this._pane || this._showPane ;
185   if (!pane) throw new Error("view() cannot be called on a class");
186   return pane.view(viewKey);
187 };
188 
189 /**
190   Registers a final test that will instantiate the control test pane and
191   display it.  This allows the developer to interact with the controls once
192   the test has completed.
193 */
194 SC.ControlTestPane.show = function() {
195   var pane = this ;
196   test("show control test pane", function() {
197     SC.RunLoop.begin();
198     pane._showPane = pane.create();
199     SC.RunLoop.end();
200   });
201 };
202 
203 /**
204   Makes the test pane the key pane, so that key handling methods can be properly tested.
205 */
206 SC.ControlTestPane.becomeKeyPane = function () {
207   var pane = this._pane || this._showPane;
208   if (pane) {
209     SC.run(function () {
210       pane.becomeKeyPane();
211     });
212   }
213 };
214