sproutcore 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (270) hide show
  1. data/History.txt +4 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +269 -0
  4. data/README.txt +67 -0
  5. data/Rakefile +4 -0
  6. data/app_generators/sproutcore/USAGE +5 -0
  7. data/app_generators/sproutcore/sproutcore_generator.rb +66 -0
  8. data/app_generators/sproutcore/templates/README +77 -0
  9. data/app_generators/sproutcore/templates/environment.yml +4 -0
  10. data/bin/sc-build +145 -0
  11. data/bin/sc-gen +24 -0
  12. data/bin/sc-server +63 -0
  13. data/bin/sproutcore +21 -0
  14. data/clients/sc_docs/controllers/docs.js +118 -0
  15. data/clients/sc_docs/core.js +19 -0
  16. data/clients/sc_docs/english.lproj/body.css +159 -0
  17. data/clients/sc_docs/english.lproj/body.rhtml +33 -0
  18. data/clients/sc_docs/english.lproj/controls.css +0 -0
  19. data/clients/sc_docs/english.lproj/icons/small/next.png +0 -0
  20. data/clients/sc_docs/english.lproj/icons/small/reset.png +0 -0
  21. data/clients/sc_docs/english.lproj/images/gradients.png +0 -0
  22. data/clients/sc_docs/english.lproj/images/indicator.gif +0 -0
  23. data/clients/sc_docs/english.lproj/images/toolbar.png +0 -0
  24. data/clients/sc_docs/english.lproj/no_docs.rhtml +7 -0
  25. data/clients/sc_docs/english.lproj/strings.js +14 -0
  26. data/clients/sc_docs/english.lproj/warning.rhtml +6 -0
  27. data/clients/sc_docs/fixtures/doc.js +11 -0
  28. data/clients/sc_docs/main.js +21 -0
  29. data/clients/sc_docs/models/doc.js +9 -0
  30. data/clients/sc_docs/tests/controllers/docs.rhtml +21 -0
  31. data/clients/sc_docs/tests/models/doc.rhtml +21 -0
  32. data/clients/sc_docs/tests/views/doc_frame.rhtml +21 -0
  33. data/clients/sc_docs/tests/views/doc_label_view.rhtml +21 -0
  34. data/clients/sc_docs/views/doc_frame.js +33 -0
  35. data/clients/sc_docs/views/doc_label.js +20 -0
  36. data/clients/sc_test_runner/controllers/runner.js +175 -0
  37. data/clients/sc_test_runner/core.js +19 -0
  38. data/clients/sc_test_runner/english.lproj/body.css +151 -0
  39. data/clients/sc_test_runner/english.lproj/body.rhtml +35 -0
  40. data/clients/sc_test_runner/english.lproj/controls.css +0 -0
  41. data/clients/sc_test_runner/english.lproj/icons/small/next.png +0 -0
  42. data/clients/sc_test_runner/english.lproj/icons/small/reset.png +0 -0
  43. data/clients/sc_test_runner/english.lproj/images/gradients.png +0 -0
  44. data/clients/sc_test_runner/english.lproj/images/indicator.gif +0 -0
  45. data/clients/sc_test_runner/english.lproj/images/toolbar.png +0 -0
  46. data/clients/sc_test_runner/english.lproj/no_tests.rhtml +6 -0
  47. data/clients/sc_test_runner/english.lproj/strings.js +14 -0
  48. data/clients/sc_test_runner/english.lproj/warning.rhtml +6 -0
  49. data/clients/sc_test_runner/fixtures/test.js +12 -0
  50. data/clients/sc_test_runner/main.js +26 -0
  51. data/clients/sc_test_runner/models/test.js +11 -0
  52. data/clients/sc_test_runner/views/runner_frame.js +72 -0
  53. data/clients/sc_test_runner/views/test_label.js +20 -0
  54. data/config/hoe.rb +70 -0
  55. data/config/requirements.rb +17 -0
  56. data/environment.yml +9 -0
  57. data/frameworks/prototype/prototype.js +4186 -0
  58. data/frameworks/sproutcore/Core.js +378 -0
  59. data/frameworks/sproutcore/README +3 -0
  60. data/frameworks/sproutcore/controllers/array.js +236 -0
  61. data/frameworks/sproutcore/controllers/collection.js +305 -0
  62. data/frameworks/sproutcore/controllers/controller.js +323 -0
  63. data/frameworks/sproutcore/controllers/object.js +372 -0
  64. data/frameworks/sproutcore/drag/drag.js +549 -0
  65. data/frameworks/sproutcore/drag/drag_data_source.js +32 -0
  66. data/frameworks/sproutcore/drag/drag_source.js +64 -0
  67. data/frameworks/sproutcore/drag/drop_target.js +153 -0
  68. data/frameworks/sproutcore/english.lproj/blank.gif +0 -0
  69. data/frameworks/sproutcore/english.lproj/buttons.css +589 -0
  70. data/frameworks/sproutcore/english.lproj/buttons.png +0 -0
  71. data/frameworks/sproutcore/english.lproj/inline_text_editor.css +21 -0
  72. data/frameworks/sproutcore/english.lproj/menu.css +121 -0
  73. data/frameworks/sproutcore/english.lproj/panels/background-fat.jpg +0 -0
  74. data/frameworks/sproutcore/english.lproj/panels/background-thin.jpg +0 -0
  75. data/frameworks/sproutcore/english.lproj/panels/bottom-edge.png +0 -0
  76. data/frameworks/sproutcore/english.lproj/panels/bottom-left-corner.png +0 -0
  77. data/frameworks/sproutcore/english.lproj/panels/bottom-right-corner.png +0 -0
  78. data/frameworks/sproutcore/english.lproj/panels/left-edge.png +0 -0
  79. data/frameworks/sproutcore/english.lproj/panels/overlay.png +0 -0
  80. data/frameworks/sproutcore/english.lproj/panels/right-edge.png +0 -0
  81. data/frameworks/sproutcore/english.lproj/panels/top-edge.png +0 -0
  82. data/frameworks/sproutcore/english.lproj/panels/top-left-corner.png +0 -0
  83. data/frameworks/sproutcore/english.lproj/panels/top-right-corner.png +0 -0
  84. data/frameworks/sproutcore/english.lproj/panes.css +155 -0
  85. data/frameworks/sproutcore/english.lproj/picker.css +22 -0
  86. data/frameworks/sproutcore/english.lproj/strings.js +15 -0
  87. data/frameworks/sproutcore/english.lproj/tab.css +23 -0
  88. data/frameworks/sproutcore/english.lproj/tests.css +67 -0
  89. data/frameworks/sproutcore/english.lproj/theme.css +77 -0
  90. data/frameworks/sproutcore/foundation/animator.js +670 -0
  91. data/frameworks/sproutcore/foundation/application.js +199 -0
  92. data/frameworks/sproutcore/foundation/array.js +348 -0
  93. data/frameworks/sproutcore/foundation/benchmark.js +211 -0
  94. data/frameworks/sproutcore/foundation/binding.js +384 -0
  95. data/frameworks/sproutcore/foundation/date.js +357 -0
  96. data/frameworks/sproutcore/foundation/error.js +39 -0
  97. data/frameworks/sproutcore/foundation/input_manager.js +153 -0
  98. data/frameworks/sproutcore/foundation/json.js +296 -0
  99. data/frameworks/sproutcore/foundation/mock.js +42 -0
  100. data/frameworks/sproutcore/foundation/node_descriptor.js +56 -0
  101. data/frameworks/sproutcore/foundation/object.js +777 -0
  102. data/frameworks/sproutcore/foundation/observable.js +451 -0
  103. data/frameworks/sproutcore/foundation/page.js +63 -0
  104. data/frameworks/sproutcore/foundation/path_module.js +413 -0
  105. data/frameworks/sproutcore/foundation/responder.js +310 -0
  106. data/frameworks/sproutcore/foundation/routes.js +371 -0
  107. data/frameworks/sproutcore/foundation/run_loop.js +21 -0
  108. data/frameworks/sproutcore/foundation/server.js +491 -0
  109. data/frameworks/sproutcore/foundation/set.js +96 -0
  110. data/frameworks/sproutcore/foundation/string.js +149 -0
  111. data/frameworks/sproutcore/foundation/undo_manager.js +186 -0
  112. data/frameworks/sproutcore/foundation/unittest.js +622 -0
  113. data/frameworks/sproutcore/foundation/utils.js +61 -0
  114. data/frameworks/sproutcore/globals/panels.js +182 -0
  115. data/frameworks/sproutcore/globals/popups.js +60 -0
  116. data/frameworks/sproutcore/globals/window.js +381 -0
  117. data/frameworks/sproutcore/lib/index.rhtml +66 -0
  118. data/frameworks/sproutcore/models/collection.js +395 -0
  119. data/frameworks/sproutcore/models/record.js +622 -0
  120. data/frameworks/sproutcore/models/store.js +295 -0
  121. data/frameworks/sproutcore/panes/dialog.js +16 -0
  122. data/frameworks/sproutcore/panes/manager.js +164 -0
  123. data/frameworks/sproutcore/panes/menu.js +45 -0
  124. data/frameworks/sproutcore/panes/overlay.js +231 -0
  125. data/frameworks/sproutcore/panes/pane.js +90 -0
  126. data/frameworks/sproutcore/panes/panel.js +19 -0
  127. data/frameworks/sproutcore/panes/picker.js +45 -0
  128. data/frameworks/sproutcore/tests/controllers/array.rhtml +86 -0
  129. data/frameworks/sproutcore/tests/controllers/controller.rhtml +273 -0
  130. data/frameworks/sproutcore/tests/controllers/object.rhtml +327 -0
  131. data/frameworks/sproutcore/tests/foundation/application.rhtml +125 -0
  132. data/frameworks/sproutcore/tests/foundation/array.rhtml +221 -0
  133. data/frameworks/sproutcore/tests/foundation/object.rhtml +69 -0
  134. data/frameworks/sproutcore/tests/globals/window.rhtml +45 -0
  135. data/frameworks/sproutcore/tests/panes/pane.rhtml +88 -0
  136. data/frameworks/sproutcore/tests/views/collection.rhtml +137 -0
  137. data/frameworks/sproutcore/tests/views/popup_button.rhtml +115 -0
  138. data/frameworks/sproutcore/tests/views/text_field.rhtml +37 -0
  139. data/frameworks/sproutcore/validators/credit_card.js +92 -0
  140. data/frameworks/sproutcore/validators/date.js +36 -0
  141. data/frameworks/sproutcore/validators/email.js +29 -0
  142. data/frameworks/sproutcore/validators/not_empty.js +24 -0
  143. data/frameworks/sproutcore/validators/number.js +55 -0
  144. data/frameworks/sproutcore/validators/password.js +78 -0
  145. data/frameworks/sproutcore/validators/validator.js +304 -0
  146. data/frameworks/sproutcore/views/button.js +425 -0
  147. data/frameworks/sproutcore/views/checkbox_field.js +30 -0
  148. data/frameworks/sproutcore/views/collection.js +1521 -0
  149. data/frameworks/sproutcore/views/container.js +62 -0
  150. data/frameworks/sproutcore/views/error_explanation.js +45 -0
  151. data/frameworks/sproutcore/views/field.js +214 -0
  152. data/frameworks/sproutcore/views/filter_button.js +29 -0
  153. data/frameworks/sproutcore/views/form.js +591 -0
  154. data/frameworks/sproutcore/views/image.js +141 -0
  155. data/frameworks/sproutcore/views/inline_text_editor.js +96 -0
  156. data/frameworks/sproutcore/views/label.js +176 -0
  157. data/frameworks/sproutcore/views/menu_item.js +90 -0
  158. data/frameworks/sproutcore/views/pagination.js +54 -0
  159. data/frameworks/sproutcore/views/popup_button.js +86 -0
  160. data/frameworks/sproutcore/views/popup_menu.js +137 -0
  161. data/frameworks/sproutcore/views/progress.js +100 -0
  162. data/frameworks/sproutcore/views/radio_field.js +107 -0
  163. data/frameworks/sproutcore/views/radio_group.js +48 -0
  164. data/frameworks/sproutcore/views/segmented.js +80 -0
  165. data/frameworks/sproutcore/views/select_field.js +272 -0
  166. data/frameworks/sproutcore/views/spinner.js +11 -0
  167. data/frameworks/sproutcore/views/tab.js +126 -0
  168. data/frameworks/sproutcore/views/text_field.js +179 -0
  169. data/frameworks/sproutcore/views/textarea_field.js +14 -0
  170. data/frameworks/sproutcore/views/toolbar.js +29 -0
  171. data/frameworks/sproutcore/views/view.js +1389 -0
  172. data/frameworks/sproutcore/views/workspace.js +170 -0
  173. data/generators/client/README +3 -0
  174. data/generators/client/USAGE +12 -0
  175. data/generators/client/client_generator.rb +53 -0
  176. data/generators/client/templates/core.js +19 -0
  177. data/generators/client/templates/english.lproj/body.css +0 -0
  178. data/generators/client/templates/english.lproj/body.rhtml +3 -0
  179. data/generators/client/templates/english.lproj/controls.css +0 -0
  180. data/generators/client/templates/english.lproj/strings.js +14 -0
  181. data/generators/client/templates/main.js +37 -0
  182. data/generators/controller/USAGE +16 -0
  183. data/generators/controller/controller_generator.rb +51 -0
  184. data/generators/controller/templates/controller.js +21 -0
  185. data/generators/controller/templates/test.rhtml +21 -0
  186. data/generators/framework/README +7 -0
  187. data/generators/framework/USAGE +12 -0
  188. data/generators/framework/framework_generator.rb +53 -0
  189. data/generators/framework/templates/core.js +20 -0
  190. data/generators/framework/templates/english.lproj/body.css +0 -0
  191. data/generators/framework/templates/english.lproj/body.rhtml +3 -0
  192. data/generators/framework/templates/english.lproj/controls.css +0 -0
  193. data/generators/framework/templates/english.lproj/strings.js +14 -0
  194. data/generators/language/USAGE +16 -0
  195. data/generators/language/language_generator.rb +47 -0
  196. data/generators/language/templates/strings.js +10 -0
  197. data/generators/model/USAGE +24 -0
  198. data/generators/model/model_generator.rb +55 -0
  199. data/generators/model/templates/fixture.js +11 -0
  200. data/generators/model/templates/model.js +20 -0
  201. data/generators/model/templates/test.rhtml +21 -0
  202. data/generators/test/USAGE +16 -0
  203. data/generators/test/templates/test.rhtml +21 -0
  204. data/generators/test/test_generator.rb +47 -0
  205. data/generators/view/USAGE +16 -0
  206. data/generators/view/templates/test.rhtml +21 -0
  207. data/generators/view/templates/view.js +20 -0
  208. data/generators/view/view_generator.rb +51 -0
  209. data/jsdoc/README.txt +119 -0
  210. data/jsdoc/app/DocFile.js +137 -0
  211. data/jsdoc/app/DocTag.js +110 -0
  212. data/jsdoc/app/Doclet.js +63 -0
  213. data/jsdoc/app/Dumper.js +143 -0
  214. data/jsdoc/app/JsDoc.js +103 -0
  215. data/jsdoc/app/JsHilite.js +45 -0
  216. data/jsdoc/app/JsIO.js +163 -0
  217. data/jsdoc/app/JsParse.js +385 -0
  218. data/jsdoc/app/JsPlate.js +130 -0
  219. data/jsdoc/app/JsTestrun.js +129 -0
  220. data/jsdoc/app/JsToke.js +564 -0
  221. data/jsdoc/app/Symbol.js +298 -0
  222. data/jsdoc/app/Transformer.js +14 -0
  223. data/jsdoc/app/Util.js +97 -0
  224. data/jsdoc/app/js.jar +0 -0
  225. data/jsdoc/app/run.js +144 -0
  226. data/jsdoc/plugins/min.js +316 -0
  227. data/jsdoc/plugins/strip.js +20 -0
  228. data/jsdoc/templates/sproutcore/class.tmpl +438 -0
  229. data/jsdoc/templates/sproutcore/default.css +241 -0
  230. data/jsdoc/templates/sproutcore/index.html +13 -0
  231. data/jsdoc/templates/sproutcore/index.tmpl +21 -0
  232. data/jsdoc/templates/sproutcore/prototype.js +4186 -0
  233. data/jsdoc/templates/sproutcore/publish.js +236 -0
  234. data/jsdoc/templates/sproutcore/splash.html +7 -0
  235. data/lib/sproutcore/build_tools/html_builder.rb +88 -0
  236. data/lib/sproutcore/build_tools/resource_builder.rb +194 -0
  237. data/lib/sproutcore/build_tools.rb +44 -0
  238. data/lib/sproutcore/bundle.rb +517 -0
  239. data/lib/sproutcore/bundle_manifest.rb +397 -0
  240. data/lib/sproutcore/generator_helper.rb +170 -0
  241. data/lib/sproutcore/helpers/capture_helper.rb +42 -0
  242. data/lib/sproutcore/helpers/static_helper.rb +80 -0
  243. data/lib/sproutcore/helpers/tag_helper.rb +110 -0
  244. data/lib/sproutcore/helpers/text_helper.rb +336 -0
  245. data/lib/sproutcore/helpers.rb +3 -0
  246. data/lib/sproutcore/jsdoc.rb +40 -0
  247. data/lib/sproutcore/jsmin.rb +247 -0
  248. data/lib/sproutcore/library.rb +258 -0
  249. data/lib/sproutcore/merb/bundle_controller.rb +179 -0
  250. data/lib/sproutcore/merb/router.rb +43 -0
  251. data/lib/sproutcore/merb.rb +27 -0
  252. data/lib/sproutcore/version.rb +9 -0
  253. data/lib/sproutcore/view_helpers/button_views.rb +302 -0
  254. data/lib/sproutcore/view_helpers/core_views.rb +284 -0
  255. data/lib/sproutcore/view_helpers/form_views.rb +258 -0
  256. data/lib/sproutcore/view_helpers/menu_views.rb +94 -0
  257. data/lib/sproutcore/view_helpers.rb +628 -0
  258. data/lib/sproutcore.rb +30 -0
  259. data/script/destroy +14 -0
  260. data/script/generate +14 -0
  261. data/script/txt2html +74 -0
  262. data/setup.rb +1585 -0
  263. data/spec/spec.opts +1 -0
  264. data/spec/spec_helper.rb +7 -0
  265. data/spec/sproutcore_spec.rb +11 -0
  266. data/tasks/deployment.rake +34 -0
  267. data/tasks/environment.rake +7 -0
  268. data/tasks/rspec.rake +21 -0
  269. data/tasks/website.rake +17 -0
  270. metadata +365 -0
@@ -0,0 +1,149 @@
1
+ // ==========================================================================
2
+ // SproutCore -- JavaScript Application Framework
3
+ // copyright 2006-2007, Sprout Systems, Inc. and contributors.
4
+ // ==========================================================================
5
+
6
+ // These are basic enhancements to the string class used throughout
7
+ // SproutCore.
8
+ // capitalize a string.
9
+ Object.extend(String.prototype,{
10
+
11
+ // Capitalize a string.
12
+ //
13
+ // mode: optional. 'each' - capitalize each word. the default.
14
+ // 'first' - capitalize the first word only.
15
+
16
+ capitalize: function(mode) {
17
+ var words = (mode == 'first') ? this : this.split(' ') ;
18
+ words = words.map(function(word) {
19
+ if (word.length == 0) return word ;
20
+ return word.charAt(0).toUpperCase() + word.substring(1) ;
21
+ }) ;
22
+ return words.join(' ') ;
23
+ },
24
+
25
+ // Interpolate string. looks for %@ or %@1; to control the order of params.
26
+ format: function() {
27
+ var args = $A(arguments) ;
28
+
29
+ // first, replace any ORDERED replacements.
30
+ var str = this.gsub(/%@([0-9]+)/, function(m) {
31
+ return args[parseInt(m[1],0)-1] || '';
32
+ }) ;
33
+
34
+ // now, replace any remaining %@ items. Use this indexOf() method b/c
35
+ // it is faster than split().
36
+ var ret = [] ;
37
+ var idx = -1 ;
38
+ var loc = 0 ;
39
+ while((idx = str.indexOf("%@",loc)) >= 0) {
40
+ // slice off initial part of string and push into ret. update loc.
41
+ ret.push(str.slice(loc,idx)) ;
42
+ loc = idx + 2 ; // 2 to skip '%@'.
43
+
44
+ // add in replacement.
45
+ ret.push(args.shift()) ;
46
+ }
47
+
48
+ // include any remaining bits of the string.
49
+ if (loc < str.length) {
50
+ ret.push(str.slice(loc,str.length)) ;
51
+ }
52
+
53
+ // join return value.
54
+ return (ret.length > 1) ? ret.join('') : ret[0] ;
55
+ },
56
+
57
+ // localize a string. Also interpolates any items you pass just like
58
+ // format().
59
+ loc: function() {
60
+ // NB: This could be implemented as a wrapper to locWithDefault() but
61
+ // it would add some overhead to deal with the arguments and adds stack
62
+ // frames, so we are keeping the implementation separate.
63
+
64
+ var kit = String[String.currentLanguage()];
65
+ var str = kit[this] ;
66
+ if (!str) str = String.English[this] || this ;
67
+ return str.format.apply(str,arguments) ;
68
+ },
69
+
70
+ // this works just like loc except it will return the first argument
71
+ // as a default if the matching value is not found.
72
+ locWithDefault: function(def) {
73
+ var kit = String[String.currentLanguage()];
74
+ var str = kit[this] ;
75
+ if (!str) str = String.English[this] || def ;
76
+ var args = $A(arguments) ;
77
+ args.shift() ; // escape def.
78
+ return str.format.apply(str, args) ;
79
+ },
80
+
81
+ classify: function() {
82
+ return this.camelize().capitalize() ;
83
+ },
84
+
85
+ decamelize: function() {
86
+ return this.replace(/([a-z])([A-Z])/g,'$1_$2').toLowerCase();
87
+ },
88
+
89
+ dasherize: function() {
90
+ return this.decamelize().replace(/[ _]/g,'-') ;
91
+ },
92
+
93
+ humanize: function() {
94
+ return this.decamelize().replace(/[-_]/g,' ') ;
95
+ },
96
+
97
+ toHref: function() {
98
+ if (this.match(/.+@.+\...+/)) {
99
+ return 'mailto:' + this;
100
+ } else if (this.indexOf('http://') != 0 && this.indexOf('https://') !=0 && this.match(/[^.]+\.[^.]+/)) {
101
+ return 'http://' + this;
102
+ } else {
103
+ return this;
104
+ }
105
+ },
106
+
107
+ trim: function ()
108
+ {
109
+ return this.replace(/^\s+|\s+$/g,"");
110
+ },
111
+
112
+ strip: function()
113
+ {
114
+ return this.trim();
115
+ }
116
+
117
+ }) ;
118
+
119
+ // Shorter alias of the format function.
120
+ String.prototype.fmt = String.prototype.format ;
121
+
122
+ // Add strings for various languages to this collection. String.loc()
123
+ // method will try to localize the string passed using the current language.
124
+ // if the language is not available, it will use English.
125
+ Object.extend(String,{
126
+
127
+ // Default language is English. Currently French, German, and Japanese are
128
+ // detected. All other languages default to English.
129
+ currentLanguage: function () {
130
+ var browserLanguage = (navigator.language || navigator.browserLanguage).split('-', 1);
131
+ switch(browserLanguage[0])
132
+ {
133
+ case 'fr':
134
+ return 'French';
135
+ case 'de':
136
+ return 'German';
137
+ case 'ja':
138
+ return 'Japanese';
139
+ default:
140
+ return 'English';
141
+ }
142
+ }
143
+
144
+ });
145
+
146
+ String.English = String.English || {};
147
+ String.French = String.French || {};
148
+ String.German = String.German || {};
149
+ String.Japanese = String.Japanese || {};
@@ -0,0 +1,186 @@
1
+ // ==========================================================================
2
+ // SproutCore -- JavaScript Application Framework
3
+ // copyright 2006-2007, Sprout Systems, Inc. and contributors.
4
+ // ==========================================================================
5
+
6
+ require('Core');
7
+
8
+ /**
9
+ @class
10
+
11
+ This is a simple undo manager. To use this UndoManager, all you need to
12
+ do is to make sure that you register a function with this manager to undo
13
+ every change you make. You can then invoke the undo/redo methods to do it.
14
+
15
+ h4. USING THE UNDOMANAGER
16
+
17
+ Typically you create an undo manager inside on of your controllers. Then,
18
+ whenever you are about to perform an action on your model object, all you
19
+ need to do is to register a function with the undo manager that can undo
20
+ whatever you just did.
21
+
22
+ Besure the undo function you register also saves undo functions. This makes
23
+ redo possible.
24
+
25
+ More docs TBD.
26
+
27
+ @extends SC.Object
28
+ */
29
+ SC.UndoManager = SC.Object.extend(
30
+ /** @scope SC.UndoManager.prototype */
31
+ {
32
+
33
+ /**
34
+ (Property) Name of the next undo action name.
35
+
36
+ Use this property to build your Undo menu name.
37
+
38
+ */
39
+ undoActionName: function() {
40
+ return (this.undoStack) ? this.undoStack.name : null ;
41
+ }.property('undoStack'),
42
+
43
+ /**
44
+ (Property) Name of the next return action name.
45
+
46
+ Use this property to build your Redo menu name.
47
+
48
+ */
49
+ redoActionName: function() {
50
+ return (this.redoStack) ? this.redoStack.name : null ;
51
+ }.property('redoStack'),
52
+
53
+ /**
54
+ True if there is an undo action on the stack.
55
+
56
+ Use to validate your menu item.
57
+ */
58
+ canUndo: function() {
59
+ return this.undoStack != null;
60
+ }.property('undoStack'),
61
+
62
+ /**
63
+ True if there is an redo action on the stack.
64
+
65
+ Use to validate your menu item.
66
+ */
67
+ canRedo: function() {
68
+ return this.redoStack != null;
69
+ }.property('redoStack'),
70
+
71
+ /**
72
+ Tries to undo the last action.
73
+
74
+ Returns true if succeeded. Fails if an undo group is currently open.
75
+ */
76
+ undo: function() { this._undoOrRedo('undoStack','isUndoing'); },
77
+
78
+ /**
79
+ Tries to redo the last action.
80
+
81
+ Returns true if succeeded. Fails if an undo group is currently open.
82
+ */
83
+ redo: function() { this._undoOrRedo('redoStack','isRedoing'); },
84
+
85
+ /**
86
+ True if the manager is currently undoing events.
87
+ */
88
+ isUndoing: false,
89
+
90
+ /**
91
+ True if the manager is currently redoing events.
92
+ */
93
+ isRedoing: false,
94
+
95
+ /** @private */
96
+ groupingLevel: 0,
97
+
98
+ // --------------------------------
99
+ // SIMPLE REGISTRATION
100
+ //
101
+ // These are the core method to register undo/redo events.
102
+
103
+ /**
104
+ This is how you save new undo events.
105
+
106
+ @param {Function} func A prebound function to be invoked when the undo executes.
107
+ @param {String} [name] An optional name for the undo. If you are using
108
+ groups, this is not necessary.
109
+ */
110
+ registerUndo: function(func, name) {
111
+ this.beginUndoGroup(name) ;
112
+ this._activeGroup.actions.push(func) ;
113
+ this.endUndoGroup(name) ;
114
+ },
115
+
116
+ /**
117
+ Begins a new undo groups
118
+
119
+ Whenver you start an action that you expect to need to bundle under a single
120
+ undo action in the menu, you should begin an undo group. This way any
121
+ undo actions registered by other parts of the application will be
122
+ automatically bundled into this one action.
123
+
124
+ When you are finished performing the action, balance this with a call to
125
+ endUndoGroup().
126
+ */
127
+ beginUndoGroup: function(name) {
128
+ // is a group already active? Just increment the counter.
129
+ if (this._activeGroup) {
130
+ this.groupingLevel++ ;
131
+
132
+ // otherwise, create a new active group.
133
+ } else {
134
+ var stack = (this.isUndoing) ? 'redoStack' : 'undoStack' ;
135
+ this._activeGroup = { name: name, actions: [], prev: this.get(stack) } ;
136
+ this.set(stack, this._activeGroup) ;
137
+ this.groupingLevel = 1 ;
138
+ }
139
+ },
140
+
141
+ /** end the undo group. see beginUndoGroup() */
142
+ endUndoGroup: function(name) {
143
+ // if more than one groups are active, just decrement the counter.
144
+ if (!this._activeGroup) raise("endUndoGroup() called outside group.") ;
145
+ if (this.groupingLevel > 1) {
146
+ this.groupingLevel-- ;
147
+
148
+ // otherwise, close out the current group.
149
+ } else {
150
+ this._activeGroup = null ; this.groupingLevel = 0 ;
151
+ }
152
+ this.propertyDidChange((this.isUndoing) ? 'redoStack' : 'undoStack') ;
153
+ },
154
+
155
+ /**
156
+ Change the name of the current undo group.
157
+
158
+ Normally you don't want to do this as it will effect the whole group.
159
+ */
160
+ setActionName: function(name) {
161
+ if (!this._activeGroup) raise("setActionName() called outside group.") ;
162
+ this._activeGroup.name = name ;
163
+ },
164
+
165
+ // --------------------------------
166
+ // PRIVATE
167
+ //
168
+ _activeGroup: null, undoStack: null, redoStack: null,
169
+ _undoOrRedo: function(stack,state) {
170
+ if (this._activeGroup) return false ;
171
+ if (this.get(stack) == null) return true; // noting to do.
172
+
173
+ this.set(state, true) ;
174
+ var group = this.get(stack) ;
175
+ this.set(stack, group.prev) ;
176
+ var action ;
177
+
178
+ var useGroup = group.actions.length > 1;
179
+ if (useGroup) this.beginUndoGroup(group.name) ;
180
+ while(action = group.actions.pop()) { action(); }
181
+ if (useGroup) this.endUndoGroup(group.name) ;
182
+
183
+ this.set(state, false) ;
184
+ }
185
+
186
+ }) ;