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,502 @@
1
+ = Concrete Developers Guide =
2
+
3
+ This document describes the _Concrete_ model editor from a DSL developer's point of view. If you are interested in using the editor for a given DSL, refer to the users guide.
4
+
5
+
6
+ == Metamodels ==
7
+
8
+ _Concrete_ uses metamodels to define the abstract syntax of a DSL. A metamodel specifies the possible abstract content of models by means of _metamodel classes_. Each metamodel class defines the _features_ the instance model elements can have. Features are _attributes_, _references_ and _containments_. Attributes hold primitive values, references reference other model elements and containments contain other elements as part of the element itself. Each feature has a name and a type.
9
+
10
+ In case of an attribute, the type must be one of the predefined primitive datatypes (currently String, Bool, Integer and Float) or a custom defined enum datatype. Enum datatypes consist of a set of string literals.
11
+
12
+ In case of a reference, the type must be a metamodel class. Only instances of that metamodel class can be valid targets of the reference.
13
+
14
+ In case of a containment, the type must be a metamodel class as well. Only instances of that metamodel class can be nested in the containment.
15
+
16
+ Optionally, an upper and lower limit may be specified for each feature. For example, an upper limit of "1" means that only one attribute/reference value or contained element is allowed. A lower limit of "2" means that at least 2 values or contained elements are required.
17
+
18
+ Some of the constraines defined by the metamodel are enforced by the editor, i.e. only valid changes can be done. For the other constraints, errors are annotated at the model.
19
+
20
+
21
+ == Models ==
22
+
23
+ Models are represented by DOM nodes with special (CSS) classes. Elements, attributes, references and containments are represented by DOM nodes with classes +ct_element+, +ct_attribute+, +ct_reference+ and +ct_containment+ respectively. Attribute, reference and containment nodes are child nodes of element nodes. However, they do not have to be direct children, there can be other nodes around them.
24
+
25
+ Within each attribute, reference or containment node, there has to be a _slot_ node marked by class +ct_slot+. Again, slots don't have to be direct children and may have other nodes around them. The slot is the place where attribute values, reference values or child elements are inserted.
26
+
27
+ Attribute and reference values are DOM nodes marked with class +ct_value+. These nodes contain plain text which represents the actual attribute value or the identifier of the referenced element. Note that the visible value of an attribute or reference may be different from the actual value in the model. As an example, long references by qualified names may be shortened to only the last path element. The internal model value is stored in a Javascript property "value" of the value node. Between the slot and the contained values or elements, there must not be any other nodes.
28
+
29
+ Note, that other custom CSS classes may be added to all the nodes as long as no predefined, reserved class is used (see CSS Class Reference).
30
+
31
+ For each element, the corresponding metamodel class is indicated by an additional CSS class. The CSS class name consists of the prefix +ctc_+ followed by the name of the metamodel class. For example, an instance of the metamodel class "State" is annotated with CSS class +ctc_State+.
32
+
33
+ In order to indentify the features within each model element, they are annotated with CSS classes indicating the feature name. The CSS class name consists of the prefix +ctn_+ followed by the name of the feature. For example an instance of the feature "name" would be annotated with CSS class +ctn_name+.
34
+
35
+ Here is an example:
36
+
37
+ ----
38
+ <div class="ct_element ctc_Class1">
39
+ <p>Here comes an attribute:</p>
40
+ <span class="ct_attribuet ctn_feature1">
41
+ <p>Inside the attribute</p>
42
+ <span class="ct_slot">
43
+ <span class="ct_value">Value 1</span>
44
+ <span class="ct_value">Value 2</span>
45
+ <span class="ct_value">Value 3</span>
46
+ </span>
47
+ <p>After the slot</p>
48
+ </span>
49
+ <p>Here comes a reference:</p>
50
+ <span class="ct_reference ctn_feature2">
51
+ <p>Inside the reference</p>
52
+ <span class="ct_slot">
53
+ <span class="ct_value">/ref/to/elementA</span>
54
+ <span class="ct_value">/ref/to/elementB</span>
55
+ <span class="ct_value">/ref/to/elementC</span>
56
+ </span>
57
+ <p>After the slot</p>
58
+ </span>
59
+ <p>Here comes a containment:</p>
60
+ <div class="ct_containment ctn_feature3">
61
+ <p>Inside the containment</p>
62
+ <div class="ct_slot">
63
+ <div class="ct_element ctc_Class2">
64
+ <p>Here go the element's attributes, references and containments</p>
65
+ </div>
66
+ <div class="ct_element">
67
+ <p>Another element</p>
68
+ </div>
69
+ </div>
70
+ <p>After the slot</p>
71
+ </div>
72
+ <p>End of element</p>
73
+ </div>
74
+ ----
75
+
76
+ In this example, +div+ nodes are used for elements and +span+ nodes are used for attributes and references. Note however, that this is not mandatory. In fact, any valid HTML tag can be used.
77
+
78
+
79
+ == DOM Templates ==
80
+
81
+ The concrete syntax of a _Concrete_ DSL is specified using CSS. However, since CSS has it's limits and CSS based layouts often need special DOM nodes, also DOM nodes are part of the concrete syntax. In order to facilitate this, DOM templates can be specified for each metamodel class. Together with CSS, these templates define the graphical representation of instance elements of that class.
82
+
83
+ DOM Templates are very similar to the model itself. The only difference is that all slots are empty and thus template definitions are not nested. In fact, a model is created by applying and nesting DOM templates.
84
+
85
+ Here is an example:
86
+
87
+ ----
88
+ <div class="ct_element ctc_Class1">
89
+ <p>Here comes an attribute:</p>
90
+ <span class="ct_attribuet ctn_feature1">
91
+ <p>Inside the attribute</p>
92
+ <span class="ct_slot">
93
+ </span>
94
+ <p>After the slot</p>
95
+ </span>
96
+ <p>Here comes a reference:</p>
97
+ <span class="ct_reference ctn_feature2">
98
+ <p>Inside the reference</p>
99
+ <span class="ct_slot">
100
+ </span>
101
+ <p>After the slot</p>
102
+ </span>
103
+ <p>Here comes a containment:</p>
104
+ <div class="ct_containment ctn_feature3">
105
+ <p>Inside the containment</p>
106
+ <div class="ct_slot">
107
+ </div>
108
+ <p>After the slot</p>
109
+ </div>
110
+ <p>End of element</p>
111
+ </div>
112
+ ----
113
+
114
+ This template describes the DOM representation used for elements which are instances of metamodel class "Class1". The example model shown in section "Models" could have been created by this template.
115
+
116
+ CSS definitions can use the mandatory CSS classes as well as any additional custom CSS class.
117
+
118
+
119
+ == JSON Model Exchange Format ==
120
+
121
+ As described above, models are represented by DOM nodes at runtime. However, neither DOM nodes nor the corresponding HTML code are well suited to exchange the model data. One reason is that the DOM representation also contains part of the concrete syntax which should not be part of the pure model.
122
+
123
+ Instead of HTML, models are exchanged using the well known JSON format. JSON is basically the textual representation of objects/hashes/maps, arrays and primitive values in Javascript syntax. Today, JSON libraries are available for many major programming languages.
124
+
125
+ _Concrete_ models are represented in JSON using the following conventions:
126
+
127
+ * A model is an array holding the top-level model elements.
128
+ * Model elements are hashes, the metamodel class name is stored in a hash property named "_class".
129
+ * Feature values and contained elements are stored in properties named like the feature.
130
+ * If a feature contains multiple values/elements, they are grouped in an array. Otherwise the value/element is assigned directly to the property.
131
+ * Attribute values are converted to text using Javascript's default conversion mechanism.
132
+ * Reference values are strings holding the identifier of the referenced element.
133
+
134
+ Here is an example:
135
+
136
+ ----
137
+ [{"_class": "Statemachine", "name": "AC", "states": [
138
+ {"_class": "SimpleState", "name": "Off", "transitions":
139
+ {"_class": "Transition", "target": "/AC/On"}},
140
+ {"_class": "CompositeState", "name": "On", "subStates": [
141
+ {"_class": "SimpleState", "name": "Heating", "transitions":
142
+ {"_class": "Transition", "target": "/AC/On/Cooling"}},
143
+ {"_class": "SimpleState", "name": "Cooling", "transitions":
144
+ {"_class": "Transition", "target": "/AC/On/Heating"}}], "transitions":
145
+ {"_class": "Transition", "target": "/AC/Off"}}]}]
146
+ ----
147
+
148
+ == Embedding Concrete ==
149
+
150
+ === Depencencies ===
151
+
152
+ _Concrete_ depends on _Prototype_ and _Scriptaculous_. So you need to make sure, that these libraries are included before _Concrete_ itself:
153
+
154
+ ----
155
+ <script src="../../redist/prototype.js" type="text/javascript"></script>
156
+ <script src="../../redist/scriptaculous/scriptaculous.js" type="text/javascript"></script>
157
+ <script src="../../concrete/concrete.js" type="text/javascript"></script>
158
+ ----
159
+
160
+ Note that for the current version of _Concrete_, a slightly patched version of Scriptaculous is required which comes in the release package.
161
+
162
+ === Style Sheets ===
163
+
164
+ In order to make the editor look right, you need to define styles for the CSS classes mentioned above (alse see the CSS Class Reference). You can start with one of the "theme" CSS files from the examples folder. Then for DSL specific styles, you can add another stylesheet overwriting some of the definitions in the "theme" stylesheet. Of course, another option is to create one single new stylesheet.
165
+
166
+ ----
167
+ <link rel="stylesheet" href="../../example/themes/cobalt.css" type="text/css" />
168
+ <link rel="stylesheet" href="../../editor/specific/style.css" type="text/css" />
169
+ ----
170
+
171
+ === Template Provider ===
172
+
173
+ _Concrete_ needs a place where the DOM templates can be located. This is the place where custom DOM templates are specified, as well as the place where the default DOM templates are prepared automatically in case there are no custom templates. There is no special CSS class required, just an ID to reference the node. Normally, this template container should be made invisible.
174
+
175
+ ----
176
+ <div id="templates1" style="display: none">
177
+ </div>
178
+ ----
179
+
180
+ Then, an instance of +TemplateProvider+ needs to be created. The constructor gets the template container DOM node and may take additional options. For example, by setting +identifierAttribute+ to "name", all attributes named "name" will be marked as identifier attributes when the default templates are created. This can be used to highlight these attributes differently.
181
+
182
+ ----
183
+ var tp = new Concrete.TemplateProvider($("templates1"), {identifierAttribute: "name"});
184
+ ----
185
+
186
+ === Metamodel Provider ===
187
+
188
+ _Concret_ knows about the metamodel by asking an instance of +MetamodelProvider+. The constructor takes the metamodel which is a model by itself, following the conventions described for the _Concrete_ JSON format. It can be convenient to put the metamodel as text in JSON format into the HTML code. In this case, the text content of the containing node has to be evaluated as JSON before the metamodel provider can use it.
189
+
190
+ Here is a simple example metamodel:
191
+
192
+ ----
193
+ <div id="metamodel1" style="display: none">
194
+ [
195
+ {"_class": "Datatype", "name": "String"},
196
+ {"_class": "Class", "A": "Feature", "features": [
197
+ {"_class": "Feature", "name": "feat1", "kind": "attribute", "type": "String"},
198
+ {"_class": "Feature", "name": "feat2", "kind": "attribute", "type": "String"},
199
+ ]}
200
+ ]
201
+ </div>
202
+ ----
203
+
204
+ Here is how this metamodel can be fed into a new instance of +MetamodelProvider+.
205
+
206
+ ----
207
+ var mp = new Concrete.MetamodelProvider($("metamodel1").textContent.evalJSON());
208
+ ----
209
+
210
+ === Identifier Provider ===
211
+
212
+ In _Concrete_, identifiers are used to define reference targets. In order to create identifiers, the editor needs an identifier provider. Currently, the +QualifiedNameBasedIdentifierProvider+ is included with _Concrete_, but other providers implementing custom identifier calculation strategies could be used instead. The +QualifiedNameBasedIdentifierProvider+ needs to know the name of the attribute holding the local (non-qualified) name.
213
+
214
+ In the following example, all attributes named "name" are used for qualified name calculation.
215
+
216
+ ----
217
+ var ip = new Concrete.QualifiedNameBasedIdentifierProvider({nameAttribute: "name"});
218
+ ----
219
+
220
+ === Clipboard ===
221
+
222
+ By default, the editor uses a clipboard it creates internally. However, to let several editors share a clipboard, an instance of +Clipboard+ can be explicitly passed into each editor. This is also useful for making the clipboard content visible or editable. When a clipboard is created, a DOM node can be passed into the constructor which acts as the container of the clipboard data. If a HTML +Textarea+ node is used, the clipboard content will be visible and editable within this textarea. If another type of node is passed in, its text content will hold the clipboard data and make it visible. If no DOM node is given, the data will be held as plain text internally.
223
+
224
+ Here is an example:
225
+
226
+ ----
227
+ <textarea id="clipboard1" style="background-color: white; color: black; border: 1px solid grey" cols="80" rows="10" wrap="off">
228
+ </textarea>
229
+ ----
230
+
231
+ This textarea can be passed into a new instance of +Clipboard+.
232
+
233
+ ----
234
+ var cb = new Concrete.Clipboard($("clipboard1"));
235
+ ----
236
+
237
+ === Conrete Editor ===
238
+
239
+ The editor itself is some kind of widget which lives in a DOM node with CSS class +ct_editor+.
240
+
241
+ ----
242
+ <div class="ct_editor" id="editor1">
243
+ </div>
244
+ ----
245
+
246
+ With all the objects created before, the editor can be instantiated. The constructor takes the DOM node the editor should live in, the template provider, the metamodel provider, the identifier provider and additional options. One of the options is an externally created clipboard as described above. Another option defines the metamodel classes which can be instantiated on root level. If not specified, all metamodel classes can be instantiated on root level.
247
+
248
+ Here is an example:
249
+
250
+ ----
251
+ var ed = new Concrete.Editor($("editor1"), tp, mp, ip, {clipboard: cb,
252
+ rootClasses: mp.metaclasses.select(function(c) { return ["Class", "Datatype", "Enum"].include(c.name)})});
253
+ ----
254
+
255
+ Once the editor has been created it has to be connected to the browser window events. Currently the +click+, +keydown+ and +mousemove+ events are supported.
256
+
257
+ ----
258
+ Event.observe(window, 'click', function(event) {
259
+ ed.handleEvent(event);
260
+ });
261
+ Event.observe(window, 'keydown', function(event) {
262
+ ed.handleEvent(event);
263
+ });
264
+ Event.observe(window, 'mousemove', function(event) {
265
+ ed.handleEvent(event);
266
+ });
267
+ ----
268
+
269
+ === Loading and Storing Data ===
270
+
271
+ A newly created editor is empty and the user can start building a model from scratch. However in most cases, some prebuilt model should be loaded and the final result should be stored. For this purpose, the _Concrete_ editor provides the methods +getModel+ and +setModel+. In both cases the model is a JSON string following the JSON conventions as described above.
272
+
273
+ One possible way to use this API is to get the data from a server via AJAX and also store it back in the same way. Another option for loading is to embed the model in an HTML element in JSON text format and load it from there.
274
+
275
+ ----
276
+ <div id="model1" style="display: none">
277
+ <!-- json model here -->
278
+ </div>
279
+ ----
280
+
281
+ Code for loading the model...
282
+
283
+ ----
284
+ // load model only if present and valid JSON
285
+ var modelData = $("model1").textContent;
286
+ if (modelData.isJSON()) {
287
+ ed.setModel(modelData);
288
+ }
289
+ ----
290
+
291
+ ...and for storing it via AJAX using the Prototype library.
292
+
293
+ ----
294
+ new Ajax.Request("/save", { method: 'post', postBody: ed.getModel() });
295
+ ----
296
+
297
+
298
+ == The Workbench ==
299
+
300
+ The "workbench" is an environment for editing larger models which are made up from _modules_. It is actually an assembly of two _Concrete_ editor widgets. Thus it is both, an example of how the editor widget can be used in a larger scope and a base for more sophisticated editors. Just like the simple editor widget itself, the workbench is metamodel independant.
301
+
302
+ The workbench features:
303
+
304
+ * a module index view (read only)
305
+ * a module editor
306
+ * an inter module index supporting inter module references
307
+ * a dialog to jump to elements based on the index
308
+ * search/replace functionality
309
+ * support for switchable layouts via a preferences dialog
310
+ * a Ruby based server backend for reading/writing to the filesystem
311
+
312
+ In order to use the Ruby backend, you need to have the Ruby runtime installed. Once Ruby is installed _Concrete_ can be installed as a Ruby _gem_. See the Readme file for details.
313
+
314
+
315
+ === Modules and Index ===
316
+
317
+ The workbench is used to edit models devided into modules. It is based on the assumption that modules can be loaded and stored independantly.
318
+
319
+ An index is used to implement inter-module search and link functionality. The overall index is composed of the the indices of the individual modules. In case a module is modified, only this module's index needs to be regenerated.
320
+
321
+ The index is a stripped down version of the original model. From the point of view of the _Concrete_ editor widget, the index is just a model as any other model. Thus it needs to be an instance of a metamodel, the _index metamodel_. The index metamodel can be derived from the original metamodel: It contains a metaclass for each metaclass in the original metamodel. However the only features of an index metaclass are the name ("name") and the child elements ("elements"). The _Concrete::IndexBuilder_ can be used to both create the index metamodel from the original metamodel and the index model from the original model.
322
+
323
+ The module index view of the workbench is actually a _Concret_ editor widget which shows the index model. With the index structure as described above, class information, element names and the containment structure are available in the index. Using class information, class specific layouts (e.g. class specific icons) can be applied to the index view.
324
+
325
+
326
+ === Data Provider and Working Set ===
327
+
328
+ The workbench functionality is generic, you need to provide a metamodel as well as an instantiator and serializer for your models. This is done by passing a _data provider_ to the generic server. The data provider is a Ruby object implementing the following methods:
329
+
330
+ .Methods to be implemented by a Data Provider
331
+ [frame="topbot",grid="none"]
332
+ |=======================
333
+ | metamodelAsJson | returns the metamodel as a JSON string following the conventions described above
334
+ | indexMetamodelAsJson | returns the index metamodel as a JSON string
335
+ | getJsonModel(fileIdent) | reads the model part contained in module _fileIdent_ from the filesystem or a database and returns a JSON string
336
+ | setJsonModel(fileIdent, data) | takes a JSON string representing the model in module _fileIdent_ and writes it to the filesystem or a database
337
+ | createModule(fileIdent) | creates a new empty module for the given identifier
338
+ | getAllJsonIndex | returns a JSON string representing the overall model index (i.e. the composition of all module indices)
339
+ |=======================
340
+
341
+ The server also needs to know which modules exist. Therefor you should provide an instance of _Concrete::WorkingSet_ which is basically a set of module identifiers.
342
+
343
+
344
+ === Concrete Syntaxes ===
345
+
346
+ The workbench server supports selecting a concrete syntax from a set of available syntaxes. A concrete syntax consists of a stylesheet part and a HTML template part. Use an instance of _Concrete::ConcreteSyntaxProvider_ to tell the server about the available syntaxes. The syntax provider takes a set of directories which contain concrete syntax information represented by directories and files following a naming convention:
347
+
348
+ ----
349
+ <syntax root dir 1>
350
+ <syntax 1>
351
+ style.css
352
+ templates.html
353
+ <syntax 2>
354
+ style.css
355
+ templates.html
356
+ ----
357
+
358
+ There can be several syntax root directories (e.g. one which is deployed with your editor and one in the user's home directory). The display name of a specific syntax is derived from the syntax directory within a root directory. The syntax directory should contain a file "templates.html" in case the syntax contains a HTML part. It should also contain a CSS file "style.css" and it may contain more resources (e.g. images) referenced from that stylesheet.
359
+
360
+ The server will make the files in the directory of the selected syntax available via the path prefix "/syntax". It will also insert the contents of the file "template.html" in the main HTML file by replacing the placeholder comment "html templates". See below for an example.
361
+
362
+
363
+ === Setting up the Server ===
364
+
365
+ With a working set, data provider and syntax provider in place the server can be instantiated. As an additional argument, it needs the location of its HTML root directory. The root directory should contain a file named "editor.html" which is the main HTML file as described in the next section.
366
+
367
+ The following example code sets up an instance of _Concrete::Server_. It reads the module names as file names from the command line and uses the RGen builtin ECore meta-metamodel as metamodel (in fact this is taken form the "mmedit" metamodel editor project). It uses the _Concrete::IndexBuilder_ to derive the index metamodel and the index model and it uses a _Concrete::Config_ to store the preferences in the user's home directory.
368
+
369
+ ----
370
+ logger = Concrete::Util::Logger.new
371
+
372
+ workingSet = Concrete::WorkingSet.new(".")
373
+ ARGV.each{|a| workingSet.addFile(a)}
374
+
375
+ mm = RGen::ECore
376
+ indexBuilder = Concrete::IndexBuilder.new(mm)
377
+ indexBuilder.indexMetamodel
378
+
379
+ dataProvider = MMEdit::DataProvider.new(workingSet, mm, indexBuilder, logger)
380
+ config = Concrete::Config.new(File.expand_path("~/.mmedit_config"))
381
+ syntaxProvider = Concrete::ConcreteSyntaxProvider.new([File.dirname(__FILE__)+"/../syntax"], logger, config)
382
+ Concrete::Server.new(workingSet, dataProvider, syntaxProvider, File.dirname(__FILE__)+"/../html").start
383
+ ----
384
+
385
+
386
+ === Setting up the Javascript Part ===
387
+
388
+ The server expects a file named "editor.html" in its HTML root directory. This is the place to setup the Javascript part of the workbench.
389
+
390
+ To be able to use the workbench functionality, you need to include the "concrete_ui" package as well as the workbench specific styles.
391
+
392
+ Note that the server will automatically redirect requests with prefix "/concrete" to the directory containing the _Concrete_ Javascript code. It will redirect requests to "/html" to the HTML root directory and it will redirect requests to "/syntax" to the selected syntax directory. Requests to "metamodel.js" and "index_metamodel.js" will be served with the data returned from the data provider methodes "metamodelAsJson" and "indexMetamodelAsJson".
393
+
394
+ Here is an example from the "mmedit" project.
395
+
396
+ ----
397
+ <link rel="stylesheet" href="/concrete/example/themes/white.css" type="text/css" />
398
+ <link rel="stylesheet" href="/concrete/concrete/ui/style.css" type="text/css" />
399
+ <link rel="stylesheet" href="/html/style.css" type="text/css" />
400
+ <link rel="stylesheet" href="/syntax/style.css" type="text/css" />
401
+ <script src="/concrete/redist/prototype.js" type="text/javascript"></script>
402
+ <script src="/concrete/redist/scriptaculous/scriptaculous.js" type="text/javascript"></script>
403
+ <script src="/concrete/concrete/concrete.js" type="text/javascript"></script>
404
+ <script src="/concrete/concrete/ui/concrete_ui.js" type="text/javascript"></script>
405
+ <script src="metamodel.js" type="text/javascript"></script>
406
+ <script src="index_metamodel.js" type="text/javascript"></script>
407
+ ----
408
+
409
+ The "editor.html" file should also contain the placeholder which is to be replaced with the HTML templates from the syntax directory. Therefor it should contain a template container element including the placeholder:
410
+
411
+ ----
412
+ <div id="editor_templates" style='display: none'>
413
+ <!-- html templates -->
414
+ </div>
415
+ ----
416
+
417
+ The workbench is created by means of a setup method which takes the metamodel and index metamodel as arguments. Note that in this example, the requests to "metamodel.js" and "index_metamodel.js" do not only return the JSON text but they return a Javascript assignment of this text to the variables "Metamodel" and "IndexMetamodel". In addition to the metamodels, the setup method takes options which are passed to the index view editor widget and the model editor widget.
418
+
419
+ ----
420
+ Concrete.UI.Workbench.setup(Metamodel, IndexMetamodel, {
421
+
422
+ moduleEditorOptions: {
423
+ rootClasses: ["EPackage"],
424
+ templateProvider: new Concrete.TemplateProvider($("editor_templates"), {
425
+ identifierAttribute: "name"
426
+ }),
427
+ shortReferences: true
428
+ }
429
+ });
430
+ ----
431
+
432
+
433
+ === Going beyond the Workbench ===
434
+
435
+ The "workbench" should cover a number of editing usecases without change. In case you need different functionality, just use it as an example and starting point to create your own _Concrete_ based editor.
436
+
437
+
438
+ == CSS Class Reference ==
439
+
440
+ .Model and Template Related CSS Classes
441
+ [frame="topbot",grid="none"]
442
+ |=======================
443
+ | ct_element | model element
444
+ | ct_attribute | model element attribute
445
+ | ct_reference | model element reference to other model element
446
+ | ct_containment | model element containment of other element
447
+ | ct_slot | slot inside an attribute, reference or containment
448
+ | ct_value | attribute or reference value
449
+ | ctc_<...> | class indicating an element's metamodel class
450
+ | ctn_<...> | class indicating a feature's name
451
+ | ct_handle | marks a DOM node which is used as an element's handle, this node will change into an editor when the element's class is to be changed
452
+ | ct_auto_hide | marks a feature as "auto hide", it will be hidden if it is empty
453
+ | ct_always_hide | marks a feature as "always hide", it will be hidden when the selection leaves the current element
454
+ | ct_root | internal. marks the model root node
455
+ |=======================
456
+
457
+ .Editor Related CSS Classes
458
+ [frame="topbot",grid="none"]
459
+ |=======================
460
+ | ct_editor | the editor itself
461
+ | ct_inline_editor | inline editor for editing text inside the editor
462
+ | ct_focus | this class is present at the editor node if it is focused
463
+ | ct_selected | this class is present at an element or value if it is selected
464
+ | ct_cursor | cursor on the border of the currently selected element
465
+ | ct_empty | empty value or element placeholder
466
+ | ct_fold_button | marks the fold button
467
+ | ct_fold_open | present at the fold button when the fold is open
468
+ | ct_fold_closed | present at the fold button when the fold is closed
469
+ | ct_fold_empty | present at the fold button when the containing element has no contained elements
470
+ | ct_message_popup | popup window shown when hovering over a model element
471
+ | ct_info_message | info message within the message popup window
472
+ | ct_error_message | error message within the message popup window
473
+ |=======================
474
+
475
+ .Highlighting Related CSS Classes
476
+ [frame="topbot",grid="none"]
477
+ |=======================
478
+ | ct_identifier_attribute | marks the attribute holding the identifier of an element
479
+ | ct_class_name | marks an element's class name
480
+ | ct_feature_name | marks the feature name
481
+ | ct_error | marks elements and features for which a constraint check failed
482
+ | ct_error_description | internal. error description to be displayed for a node
483
+ | ct_error_popup | popup window shown when the mouse is over an erroneous element
484
+ | ct_ref_source | marks a reference when it is highlighted
485
+ | ct_ref_target | marks the target element when a reference is highlighted
486
+ | ct_element_icon | marks a node which can take an element's icon with a "background" style
487
+ |=======================
488
+
489
+ .CSS Classes used by the Workbench
490
+ [frame="topbot",grid="none"]
491
+ |=======================
492
+ | ct_layout_main | marks the main editor pane
493
+ | ct_layout_sidebar | marks the module index view
494
+ | ct_layout_sidebar_drag | draggable border of the index view
495
+ | ct_layout_toolbar | toolbar pane
496
+ | ct_toolbar | the toolbar
497
+ | ct_toolbar_icon | an icon of a toolbar button
498
+ | ct_tooltop_popup | tooltip popup
499
+ | ct_<...>_button | specific toolbar buttons
500
+ | ct_<...>_dialog | marks nodes serving as dialog windows
501
+ | ct_clipboard_area | the clipboard area (textarea) in the module editor
502
+ |=======================