view.js 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. "use strict";
  2. // Copyright 2012 United States Government, as represented by the Secretary of Defense, Under
  3. // Secretary of Defense (Personnel & Readiness).
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
  6. // in compliance with the License. You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software distributed under the License
  11. // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
  12. // or implied. See the License for the specific language governing permissions and limitations under
  13. // the License.
  14. /// vwf/view.js is the common implementation of all Virtual World Framework views. Views
  15. /// interpret information from the simulation, present it to the user, and accept user input
  16. /// influencing the simulation.
  17. ///
  18. /// Views are outside of the simulation. Unlike models, they may accept external input--such as
  19. /// pointer and key events from a user--but may only affect the simulation indirectly through the
  20. /// synchronization server.
  21. ///
  22. /// vwf/view and all deriving views are loaded as RequireJS (http://requirejs.org) modules.
  23. ///
  24. /// @module vwf/view
  25. /// @requires logger
  26. /// @requires vwf/api/kernel
  27. /// @requires vwf/api/view
  28. define( [ "module", "logger", "vwf/api/kernel", "vwf/api/view" ], function( module, logger, kernel_api, view_api ) {
  29. // TODO: most of this is the same between vwf/model.js and vwf/view.js. Find a way to share.
  30. var label = module.id.replace( /\//g, "." );
  31. logger.for( label ).debug( "loading" );
  32. var exports = {
  33. module: module,
  34. logger: logger.for( label ),
  35. load: function( module, initializer, viewGenerator, kernelGenerator ) {
  36. var instance = Object.create( this );
  37. instance.module = module;
  38. instance.logger = logger.for( instance.module.id.replace( /\//g, "." ), instance );
  39. instance.logger.debug( "loading" );
  40. if ( typeof initializer == "function" || initializer instanceof Function ) {
  41. initializer = initializer();
  42. }
  43. for ( var key in initializer ) {
  44. instance[key] = initializer[key];
  45. }
  46. viewGenerator && Object.keys( view_api ).forEach( function( viewFunctionName ) {
  47. if ( ! instance.hasOwnProperty( viewFunctionName ) ) {
  48. instance[viewFunctionName] = viewGenerator.call( instance, viewFunctionName );
  49. instance[viewFunctionName] || delete instance[viewFunctionName];
  50. }
  51. } );
  52. kernelGenerator && Object.keys( kernel_api ).forEach( function( kernelFunctionName ) {
  53. if ( ! instance.hasOwnProperty( kernelFunctionName ) ) {
  54. instance[kernelFunctionName] = kernelGenerator.call( instance, kernelFunctionName );
  55. instance[kernelFunctionName] || delete instance[kernelFunctionName];
  56. }
  57. } );
  58. return instance;
  59. },
  60. create: function( kernel, view, stages, state, parameters ) {
  61. this.logger.debug( "creating" );
  62. // Interpret create( kernel, stages, ... ) as create( kernel, undefined, stages, ... )
  63. if ( view && view.length !== undefined ) { // is an array?
  64. parameters = state;
  65. state = stages;
  66. stages = view;
  67. view = undefined;
  68. }
  69. // Append this driver's stages to the pipeline to be placed in front of this driver.
  70. if ( ! view ) {
  71. stages = Array.prototype.concat.apply( [], ( this.pipeline || [] ).map( function( stage ) {
  72. return ( stages || [] ).concat( stage );
  73. } ) ).concat( stages || [] );
  74. } else {
  75. stages = ( stages || [] ).concat( this.pipeline || [] );
  76. }
  77. // Create the driver stage using its module as its prototype.
  78. var instance = Object.create( this );
  79. // Attach the reference to the stage to the right through the view API.
  80. viewize.call( instance, view, view_api );
  81. // Create the pipeline to the left and attach the reference to the stage to the left
  82. // through the kernel API.
  83. kernelize.call( instance,
  84. stages.length ?
  85. stages.pop().create( kernel, instance, stages ) :
  86. kernel,
  87. kernel_api );
  88. // Attach the shared state object.
  89. instance.state = state || {};
  90. // Call the driver's initialize().
  91. initialize.apply( instance, parameters );
  92. // Call viewize() on the driver.
  93. function viewize( view, view_api ) {
  94. Object.getPrototypeOf( this ) && viewize.call( Object.getPrototypeOf( this ), view, view_api ); // depth-first recursion through the prototypes
  95. this.hasOwnProperty( "viewize" ) && this.viewize.call( instance, view, view_api ); // viewize() from the bottom up
  96. }
  97. // Call kernelize() on the driver.
  98. function kernelize( kernel, kernel_api ) {
  99. Object.getPrototypeOf( this ) && kernelize.call( Object.getPrototypeOf( this ), kernel, kernel_api ); // depth-first recursion through the prototypes
  100. this.hasOwnProperty( "kernelize" ) && this.kernelize.call( instance, kernel, kernel_api ); // kernelize() from the bottom up
  101. }
  102. // Call initialize() on the driver.
  103. function initialize( /* parameters */ ) {
  104. Object.getPrototypeOf( this ) && initialize.apply( Object.getPrototypeOf( this ), arguments ); // depth-first recursion through the prototypes
  105. this.hasOwnProperty( "initialize" ) && this.initialize.apply( instance, arguments ); // initialize() from the bottom up
  106. }
  107. // Return the driver stage. For the actual driver, return the leftmost stage in the
  108. // pipeline.
  109. if ( ! view ) {
  110. while ( instance.kernel !== kernel ) {
  111. instance = instance.kernel;
  112. }
  113. }
  114. return instance;
  115. },
  116. kernelize: function( kernel, kernel_api ) {
  117. this.kernel = kernel;
  118. },
  119. };
  120. return exports;
  121. } );