concrete 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (128) hide show
  1. data/CHANGELOG +32 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +87 -0
  4. data/concrete/basic_inline_editor.js +73 -0
  5. data/concrete/clipboard.js +72 -0
  6. data/concrete/concrete.js +58 -0
  7. data/concrete/constraint_checker.js +297 -0
  8. data/concrete/editor.js +964 -0
  9. data/concrete/element_extension.js +68 -0
  10. data/concrete/external_identifier_provider.js +112 -0
  11. data/concrete/helper.js +63 -0
  12. data/concrete/identifier_provider.js +168 -0
  13. data/concrete/inline_editor.js +55 -0
  14. data/concrete/metamodel_provider.js +171 -0
  15. data/concrete/model_interface.js +429 -0
  16. data/concrete/scroller.js +106 -0
  17. data/concrete/selector.js +302 -0
  18. data/concrete/template_provider.js +141 -0
  19. data/concrete/ui/abstract_dialog.js +80 -0
  20. data/concrete/ui/concrete_ui.js +28 -0
  21. data/concrete/ui/create_module_dialog.js +55 -0
  22. data/concrete/ui/images/close.png +0 -0
  23. data/concrete/ui/images/document-new.png +0 -0
  24. data/concrete/ui/images/document-save.png +0 -0
  25. data/concrete/ui/images/edit-find-replace.png +0 -0
  26. data/concrete/ui/images/emblem-symbolic-link.png +0 -0
  27. data/concrete/ui/images/help-browser.png +0 -0
  28. data/concrete/ui/images/minus_11px.png +0 -0
  29. data/concrete/ui/images/plus_11px.png +0 -0
  30. data/concrete/ui/images/preferences-system.png +0 -0
  31. data/concrete/ui/images/process-stop.png +0 -0
  32. data/concrete/ui/images/system-search.png +0 -0
  33. data/concrete/ui/layout_manager.js +54 -0
  34. data/concrete/ui/module_browser.js +88 -0
  35. data/concrete/ui/module_editor.js +217 -0
  36. data/concrete/ui/open_element_dialog.js +90 -0
  37. data/concrete/ui/preferences_dialog.js +75 -0
  38. data/concrete/ui/proceed_dialog.js +52 -0
  39. data/concrete/ui/search_replace_dialog.js +323 -0
  40. data/concrete/ui/style.css +296 -0
  41. data/concrete/ui/toolbar.js +74 -0
  42. data/concrete/ui/workbench.js +165 -0
  43. data/doc/concrete_developers_guide.html +1054 -0
  44. data/doc/concrete_developers_guide.txt +502 -0
  45. data/doc/concrete_users_guide.html +694 -0
  46. data/doc/concrete_users_guide.txt +223 -0
  47. data/example/formula_editor/example_data/example1.json +11 -0
  48. data/example/formula_editor/formula_editor.html +83 -0
  49. data/example/formula_editor/sqrt_horz.png +0 -0
  50. data/example/formula_editor/sqrt_vert.png +0 -0
  51. data/example/formula_editor/style.css +31 -0
  52. data/example/metamodel_editor/edit.rb +54 -0
  53. data/example/metamodel_editor/example_data/formula_metamodel.json +18 -0
  54. data/example/metamodel_editor/example_data/meta_metamodel.json +22 -0
  55. data/example/metamodel_editor/example_data/statemachine_metamodel.json +32 -0
  56. data/example/metamodel_editor/metamodel_editor.html +120 -0
  57. data/example/metamodel_editor/metamodel_editor2.html +135 -0
  58. data/example/metamodel_editor/metamodel_editor3.html +151 -0
  59. data/example/metamodel_editor/style.css +8 -0
  60. data/example/metamodel_editor/style2.css +19 -0
  61. data/example/metamodel_editor/style3.css +35 -0
  62. data/example/minimal_editor/minimal_editor.html +43 -0
  63. data/example/statemachine_editor/example_data/example1.json +11 -0
  64. data/example/statemachine_editor/state_background.png +0 -0
  65. data/example/statemachine_editor/statemachine_editor0.html +55 -0
  66. data/example/statemachine_editor/statemachine_editor1.html +62 -0
  67. data/example/statemachine_editor/statemachine_editor2.html +103 -0
  68. data/example/statemachine_editor/style0.css +8 -0
  69. data/example/statemachine_editor/style1.css +32 -0
  70. data/example/statemachine_editor/style2.css +43 -0
  71. data/example/themes/cobalt.css +176 -0
  72. data/example/themes/dialog-error.png +0 -0
  73. data/example/themes/dialog-information.png +0 -0
  74. data/example/themes/dialog-warning.png +0 -0
  75. data/example/themes/dots_12px.png +0 -0
  76. data/example/themes/fold_button_dots_when_hidden.css +18 -0
  77. data/example/themes/fold_button_plus_minus.css +21 -0
  78. data/example/themes/fold_button_plus_when_hidden.css +18 -0
  79. data/example/themes/light_blue.css +177 -0
  80. data/example/themes/minus_11px.png +0 -0
  81. data/example/themes/minus_13px.png +0 -0
  82. data/example/themes/minus_9px.png +0 -0
  83. data/example/themes/plus_11px.png +0 -0
  84. data/example/themes/plus_13px.png +0 -0
  85. data/example/themes/plus_9px.png +0 -0
  86. data/example/themes/white.css +177 -0
  87. data/lib/concrete/concrete_syntax_provider.rb +63 -0
  88. data/lib/concrete/config.rb +36 -0
  89. data/lib/concrete/file_cache_map.rb +88 -0
  90. data/lib/concrete/index_builder.rb +108 -0
  91. data/lib/concrete/metamodel/concrete_mmm.rb +45 -0
  92. data/lib/concrete/metamodel/ecore_to_concrete.rb +80 -0
  93. data/lib/concrete/server.rb +92 -0
  94. data/lib/concrete/util/logger.rb +24 -0
  95. data/lib/concrete/util/string_writer.rb +17 -0
  96. data/lib/concrete/working_set.rb +41 -0
  97. data/rakefile +33 -0
  98. data/redist/prototype.js +4320 -0
  99. data/redist/scriptaculous/builder.js +136 -0
  100. data/redist/scriptaculous/controls.js +991 -0
  101. data/redist/scriptaculous/dragdrop.js +975 -0
  102. data/redist/scriptaculous/effects.js +1130 -0
  103. data/redist/scriptaculous/scriptaculous.js +60 -0
  104. data/redist/scriptaculous/slider.js +275 -0
  105. data/redist/scriptaculous/sound.js +55 -0
  106. data/redist/scriptaculous/unittest.js +568 -0
  107. data/test/concrete_test.rb +5 -0
  108. data/test/file_cache_map_test.rb +90 -0
  109. data/test/file_cache_map_test/testdir/fileA +1 -0
  110. data/test/index_builder_test.rb +68 -0
  111. data/test/index_builder_test/ecore_index.js +85 -0
  112. data/test/index_builder_test/ecore_index_expected.js +85 -0
  113. data/test/integration/external_elements_test.html +114 -0
  114. data/test/metamodel_test.rb +40 -0
  115. data/test/metamodel_test/concrete_mmm_expected.js +19 -0
  116. data/test/metamodel_test/concrete_mmm_generated.js +19 -0
  117. data/test/metamodel_test/concrete_mmm_regenerated.js +19 -0
  118. data/test/unit/external_identifier_provider_test.html +138 -0
  119. data/test/unit/identifier_provider_test.html +269 -0
  120. data/test/unit/metamodel_provider_test.html +318 -0
  121. data/test/unit/model_interface_test.html +257 -0
  122. data/test/unit/template_provider_test.html +171 -0
  123. data/test/unit/test.css +90 -0
  124. data/test/working_set_test.rb +54 -0
  125. data/test/working_set_test/file1.txt +0 -0
  126. data/test/working_set_test/file2 +0 -0
  127. data/test/working_set_test/subdir/file3.xml +0 -0
  128. metadata +201 -0
@@ -0,0 +1,68 @@
1
+ // Concrete Model Editor
2
+ //
3
+ // Copyright (c) 2010 Martin Thiede
4
+ //
5
+ // Concrete is freely distributable under the terms of an MIT-style license.
6
+
7
+ Element.addMethods({
8
+ left: function(e) {
9
+ return e.cumulativeOffset().left;
10
+ },
11
+ right: function(e) {
12
+ return e.cumulativeOffset().left + Element.getWidth(e);
13
+ },
14
+ top: function(e) {
15
+ return e.cumulativeOffset().top;
16
+ },
17
+ bottom: function(e) {
18
+ return e.cumulativeOffset().top + Element.getHeight(e);
19
+ },
20
+ matchesClasses: function(e, classes) {
21
+ for (var i=0; i<classes.length; i++) {
22
+ if (e.hasClassName(classes[i])) return true;
23
+ }
24
+ return false;
25
+ },
26
+ // this method is necessary because Prototype's up() doesn't support searching for multiple classes
27
+ // optionally a single class may be specified, in this case this is a speed improvement over up()
28
+ findAncestor: function(e, classes) {
29
+ var parent = e.parentNode;
30
+ if (classes instanceof Array) {
31
+ while (!parent.matchesClasses(classes)) {
32
+ parent = parent.parentNode;
33
+ if (!parent || parent.nodeType != 1) return;
34
+ }
35
+ }
36
+ else {
37
+ while (!parent.hasClassName(classes)) {
38
+ parent = parent.parentNode;
39
+ if (!parent || parent.nodeType != 1) return;
40
+ }
41
+ }
42
+ return parent;
43
+ },
44
+ findAncestorOrSelf: function(e, classes) {
45
+ if ( e.matchesClasses(classes) )
46
+ return e;
47
+ else
48
+ return e.findAncestor(classes);
49
+ },
50
+ // collects the first elements on each descendant path which match the searchClasses
51
+ // stops searching a path when it hits an element matching the stopClasses
52
+ findFirstDescendants: function(e, searchClasses, stopClasses) {
53
+ return e.childElements().collect(function(c) {
54
+ if (c.matchesClasses(searchClasses)) {
55
+ return c;
56
+ }
57
+ else if (c.matchesClasses(stopClasses)) {
58
+ return [];
59
+ }
60
+ else {
61
+ return c.findFirstDescendants(searchClasses, stopClasses);
62
+ }
63
+ }, this).flatten();
64
+ },
65
+ allChildren: function(e) {
66
+ return $A(e.getElementsByTagName("*"));
67
+ }
68
+ })
@@ -0,0 +1,112 @@
1
+ // Concrete Model Editor
2
+ //
3
+ // Copyright (c) 2010 Martin Thiede
4
+ //
5
+ // Concrete is freely distributable under the terms of an MIT-style license.
6
+
7
+ // Interface ExternalIdentifierProvider
8
+ //
9
+ // getElementInfo: function(ident, options) {}
10
+ // returns the element info if +ident+ is the identifier of an element, false otherwise
11
+ // the element info is an object with properties +type+ and +module+
12
+ // if option +ignoreModule+ is specified, elements from that module will be ignored
13
+ //
14
+ // getIdentifiers: function(types) {}
15
+ // returns the identifiers of all elements of classes given in +types+
16
+
17
+ // assumes an index consisting of modules, each with the following structure:
18
+ // [ { name: <module name>, elements: [
19
+ // { _class: <class name>, name: <element name>, elements: [
20
+ // { _class: <class name>, name: <element name>, ...
21
+ //
22
+ // optionally the property "elements" may hold a single element instead of an Array
23
+ //
24
+ Concrete.IndexBasedExternalIdentifierProvider = Class.create({
25
+
26
+ initialize: function(index, metamodelProvider) {
27
+ this._index = index;
28
+ this._metamodelProvider = metamodelProvider;
29
+ this._separator = "/";
30
+ },
31
+
32
+ getElementInfo: function(ident, options) {
33
+ if (!Object.isString(ident)) return false;
34
+ for (var i=0; i<this._index.size(); i++) {
35
+ var m = this._index[i];
36
+ if (!options || !options.ignoreModule || options.ignoreModule != m.name) {
37
+ var parts = ident.split(this._separator);
38
+ var type = this._getType(m, parts);
39
+ if (type) return { type: type, module: m.name };
40
+ }
41
+ };
42
+ return false;
43
+ },
44
+
45
+ getIdentifiers: function(type) {
46
+ var typenames = type.allSubTypes().concat(type).collect(function(t){return t.name});
47
+ var result = [];
48
+ this._index.each(function(m) {
49
+ result = result.concat(this._getIdentifiers(m, typenames, ""));
50
+ }, this);
51
+ return result;
52
+ },
53
+
54
+ getAllElementInfo: function() {
55
+ var result = [];
56
+ this._index.each(function(m) {
57
+ result = result.concat(this._getAllElementInfo(m, "", m));
58
+ }, this);
59
+ return result;
60
+ },
61
+
62
+ // private
63
+
64
+ _getType: function(cont, parts) {
65
+ var local = parts.shift();
66
+ while (local == "" && parts.size() > 0) { local = parts.shift() }
67
+ if (local == "") return false;
68
+ var elements = cont.elements
69
+ if (!(elements instanceof Array)) elements = [elements].compact();
70
+ var e = elements.find(function(e) { return e.name == local });
71
+ if (e) {
72
+ if (parts.size() > 0) {
73
+ return this._getType(e, parts);
74
+ }
75
+ else {
76
+ return this._metamodelProvider.metaclassesByName[e._class];
77
+ }
78
+ }
79
+ else {
80
+ return false;
81
+ }
82
+ },
83
+
84
+ _getIdentifiers: function(cont, typenames, path) {
85
+ var result = [];
86
+ var elements = cont.elements
87
+ if (!(elements instanceof Array)) elements = [elements].compact();
88
+ elements.each(function(e) {
89
+ var epath = path + this._separator + e.name;
90
+ if (typenames.include(e._class)) {
91
+ result.push(epath);
92
+ }
93
+ result = result.concat(this._getIdentifiers(e, typenames, epath));
94
+ }, this);
95
+ return result;
96
+ },
97
+
98
+ _getAllElementInfo: function(cont, path, module) {
99
+ var result = [];
100
+ var elements = cont.elements
101
+ if (!(elements instanceof Array)) elements = [elements].compact();
102
+ elements.each(function(e) {
103
+ var epath = path + this._separator + e.name;
104
+ result.push({identifier: epath, type: e._class, module: module.name});
105
+ result = result.concat(this._getAllElementInfo(e, epath, module));
106
+ }, this);
107
+ return result;
108
+ }
109
+
110
+
111
+ });
112
+
@@ -0,0 +1,63 @@
1
+ // Concrete Model Editor
2
+ //
3
+ // Copyright (c) 2010 Martin Thiede
4
+ //
5
+ // Concrete is freely distributable under the terms of an MIT-style license.
6
+
7
+ Concrete.Helper = {
8
+
9
+ createDOMNode: function(tag, attrs, inner) {
10
+ var node = new Element(tag);
11
+ if (attrs.class) node.className = attrs.class;
12
+ if (attrs.style) node.writeAttribute("style", attrs.style);
13
+ node.innerHTML = inner;
14
+ return node;
15
+ },
16
+
17
+ // simple pretty printing, objects in an array are indented
18
+ prettyPrintJSON: function(json) {
19
+ var lastIndex = 0;
20
+ var result = "";
21
+ var indent = "";
22
+ var objectNestLevel = 0;
23
+ var dedentLevels = [];
24
+ var firstObject = true;
25
+ var firstList = true;
26
+ var writeLine = function(i) {
27
+ result = result + json.slice(lastIndex, i);
28
+ lastIndex = i;
29
+ }
30
+ for (var i=0; i < json.length; i++) {
31
+ if (json[i] == "{" ) {
32
+ writeLine(i);
33
+ if (!firstObject) result = result + "\n" + indent;
34
+ firstObject = false;
35
+ objectNestLevel++;
36
+ }
37
+ else if (json[i] == "}" ) {
38
+ objectNestLevel--;
39
+ if (objectNestLevel == dedentLevels.last()) {
40
+ dedentLevels.pop();
41
+ indent = indent.slice(2);
42
+ }
43
+ }
44
+ else if (json[i] == "[") {
45
+ writeLine(i+1);
46
+ if (!firstList) indent = indent + " ";
47
+ firstList = false;
48
+ }
49
+ else if (json[i] == "]") {
50
+ indent = indent.slice(2);
51
+ }
52
+ else if (json[i] == ":" && json[i+2] == "{") {
53
+ writeLine(i+2);
54
+ indent = indent + " ";
55
+ dedentLevels.push(objectNestLevel);
56
+ }
57
+ }
58
+ writeLine(json.length);
59
+ return result;
60
+ }
61
+
62
+ };
63
+
@@ -0,0 +1,168 @@
1
+ // Concrete Model Editor
2
+ //
3
+ // Copyright (c) 2010 Martin Thiede
4
+ //
5
+ // Concrete is freely distributable under the terms of an MIT-style license.
6
+
7
+ Concrete.AbstractIdentifierProvider = Class.create({
8
+
9
+ initialize: function() {
10
+ this._elementByIdentifier = {};
11
+ },
12
+
13
+ // returns the identifier for +element+
14
+ // returns undefined if the element has no identifier
15
+ getIdentifier: function(element) {
16
+ return element._identifier;
17
+ },
18
+
19
+ // returns the element associated with +identifier+
20
+ // returns undefined if there is no element with this identifier
21
+ getElement: function(identifier) {
22
+ return this._elementByIdentifier[identifier];
23
+ },
24
+
25
+ // ModelChangeListener Interface
26
+
27
+ elementAdded: function(element) {
28
+ throw new Error("Abstract, override in subclass");
29
+ },
30
+
31
+ elementChanged: function(element, feature) {
32
+ throw new Error("Abstract, override in subclass");
33
+ },
34
+
35
+ elementRemoved: function(element) {
36
+ throw new Error("Abstract, override in subclass");
37
+ },
38
+
39
+ rootChanged: function(root) {
40
+ throw new Error("Abstract, override in subclass");
41
+ },
42
+
43
+ commitChanges: function() {
44
+ throw new Error("Abstract, override in subclass");
45
+ },
46
+
47
+ // ModelChangeListener End
48
+
49
+ // Private
50
+
51
+ _changeIdentifier: function(element, identifier) {
52
+ var identifierChanged = (identifier != element._identifier);
53
+ if (identifierChanged) {
54
+ var lastWithSameId = this._elementByIdentifier[identifier];
55
+ // old identifier
56
+ if (element._identifier) {
57
+ var ebi = this._elementByIdentifier[element._identifier];
58
+ if (ebi instanceof Array) {
59
+ var idx = ebi.indexOf(element);
60
+ if (idx >= 0) delete ebi[idx];
61
+ ebi = ebi.compact();
62
+ this._elementByIdentifier[element._identifier] = (ebi.size() > 1) ? ebi : ebi.first();
63
+ }
64
+ else {
65
+ delete this._elementByIdentifier[element._identifier];
66
+ }
67
+ }
68
+ // new identifier
69
+ if (identifier == undefined) {
70
+ delete element._identifier;
71
+ }
72
+ else {
73
+ var ebi = this._elementByIdentifier[identifier];
74
+ if (ebi instanceof Array) {
75
+ ebi.push(element);
76
+ }
77
+ else if (ebi) {
78
+ this._elementByIdentifier[identifier] = [ebi, element];
79
+ }
80
+ else {
81
+ this._elementByIdentifier[identifier] = element;
82
+ }
83
+ element._identifier = identifier;
84
+ }
85
+ }
86
+ }
87
+ });
88
+
89
+ Concrete.QualifiedNameBasedIdentifierProvider = Class.create(Concrete.AbstractIdentifierProvider, {
90
+
91
+ // Options:
92
+ // - nameAttribute: name of the attribute which holds an element's (non qualified) name, defaults to "name"
93
+ // - separator: separator between parts (non qualified names) of qualified name, defaults to "/"
94
+ // - leadingSeparator: specifies if qualified names should start with a leading separator, defaults to "true"
95
+ initialize: function($super, options) {
96
+ $super();
97
+ this.options = options || {};
98
+ this.options.nameAttribute = this.options.nameAttribute || "name";
99
+ this.options.separator = this.options.separator || "/";
100
+ if (this.options.leadingSeparator == undefined) this.options.leadingSeparator = true;
101
+ },
102
+
103
+ // ModelChangeListener Interface
104
+
105
+ elementAdded: function(element) {
106
+ this._updateElement(element);
107
+ },
108
+
109
+ elementChanged: function(element, feature) {
110
+ this._updateElement(element);
111
+ },
112
+
113
+ elementRemoved: function(element) {
114
+ this._removeIdentifiers(element);
115
+ },
116
+
117
+ rootChanged: function(root) {
118
+ },
119
+
120
+ commitChanges: function() {
121
+ },
122
+
123
+ // ModelChangeListener End
124
+
125
+ _updateElement: function(element) {
126
+ var parent = element.ancestors().find(function(a) {return a._identifier; });
127
+ var qnamePrefix = (parent && parent._identifier) || "";
128
+ this._updateQNames(element, qnamePrefix);
129
+ },
130
+
131
+ _updateQNames: function(element, qnamePrefix) {
132
+ var nameAttribute = element.features.find(function(f) { return f.mmFeature.name == this.options.nameAttribute; }, this);
133
+ var nameValue = nameAttribute && nameAttribute.slot.childElements().select(function(e) { return !e.hasClassName("ct_empty"); }).first();
134
+ var name = nameValue && nameValue.value;
135
+ if (name) {
136
+ if (qnamePrefix.length > 0 || this.options.leadingSeparator) {
137
+ var qname = qnamePrefix+this.options.separator+name;
138
+ }
139
+ else {
140
+ var qname = name;
141
+ }
142
+ this._changeIdentifier(element, qname);
143
+ }
144
+ else {
145
+ var qname = qnamePrefix;
146
+ this._changeIdentifier(element, undefined);
147
+ }
148
+ element.features.each(function(f) {
149
+ if (f.mmFeature.isContainment()) {
150
+ f.slot.childElements().each(function(e) {
151
+ this._updateQNames(e, qname);
152
+ }, this);
153
+ }
154
+ }, this);
155
+ },
156
+
157
+ _removeIdentifiers: function(element) {
158
+ this._changeIdentifier(element, undefined)
159
+ element.features.each(function(f) {
160
+ if (f.mmFeature.isContainment()) {
161
+ f.slot.childElements().each(function(e) {
162
+ this._removeIdentifiers(e);
163
+ }, this);
164
+ }
165
+ }, this);
166
+ }
167
+ });
168
+
@@ -0,0 +1,55 @@
1
+ // Concrete Model Editor
2
+ //
3
+ // Copyright (c) 2010 Martin Thiede
4
+ //
5
+ // Concrete is freely distributable under the terms of an MIT-style license.
6
+
7
+ Concrete.InlineEditor = Class.create(Concrete.BasicInlineEditor, {
8
+
9
+ initialize: function(stateChangeFunc) {
10
+ this.stateChangeFunc = stateChangeFunc;
11
+ },
12
+
13
+ edit: function(element, opt) {
14
+ var init = opt.init || ""
15
+ var partial = opt.partial || false
16
+ if (opt.options instanceof Array) {
17
+ this._options = opt.options
18
+ this._regexp = undefined
19
+ }
20
+ else if (opt.options instanceof RegExp) {
21
+ this._options = []
22
+ this._regexp = opt.options
23
+ }
24
+ else {
25
+ this._options = []
26
+ }
27
+ this._successHandler = opt.onSuccess
28
+ this._failureHandler = opt.onFailure
29
+ this.isActive = true
30
+ this.stateChangeFunc(this.isActive);
31
+ this.show(element, init, partial, this._options)
32
+ },
33
+
34
+ finish: function() {
35
+ if ((this._options.size() == 0 || this._options.include(this.getText())) && (this._regexp == undefined || this._regexp.test(this.getText()))) {
36
+ this.isActive = false
37
+ this.stateChangeFunc(this.isActive);
38
+ this.hide()
39
+ if (this._successHandler) this._successHandler(this.getText())
40
+ }
41
+ else {
42
+ this.setError()
43
+ }
44
+ },
45
+
46
+ cancel: function() {
47
+ this.isActive = false
48
+ this.stateChangeFunc(this.isActive);
49
+ this.hide()
50
+ if (this._failureHandler) this._failureHandler()
51
+ }
52
+
53
+ })
54
+
55
+