File: tutorial.sgml

package info (click to toggle)
entity 0.7.2-6
  • links: PTS
  • area: main
  • in suites: woody
  • size: 5,352 kB
  • ctags: 5,272
  • sloc: ansic: 61,707; sh: 7,921; makefile: 732; perl: 399
file content (721 lines) | stat: -rw-r--r-- 22,421 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
<!doctype linuxdoc system>


<article>
    <title> Entity Introduction </title>

<author>
The Entity Team
</author>

<date>March 10, 2001</date>

<abstract>
An introduction to the use of Entity.
</abstract>


<toc>

<sect>Note
<p>
This tutorial was started in hopes of having it complete by the
time we released 0.7.0.  However, I didn't want to wait on it being
done, but thought this still might help people out.  If you would
like to do some work on this, please email imain@gtk.org.
<p>
</sect>



<sect>Introduction
<p>
The road to world domination is paved with obstacles. Your users want
interfaces that are intuitive and flexible, but you don't have the
time to tweak a thousand lines of C++, compilation after tweak after
compilation. Or maybe your users want to modify the interface to their
own needs?
<p>
Perhaps what you want is an easy way to serialize your application's
state, to save it to disk or share it across the network?
<p>
Maybe you want your application use a rich storage format, but can't
spare the investment to draft a format document, implement a parser,
test it, maintain it .. 
<p>
Entity is here to minimize the effect of these obstacles on your
programs.  Entity reduces the time wasted by all these tasks, 
and is a real hoot to work with to boot!
<p>
Entity isn't just a rapid development framework, though. Entity gives
your applications structure and serializable representation, a simple
and powerful component model, and the opportunity to mix and match
languages as you like - write your application's logic in your
favourite dynamic, interpreted language like python or javascript, use
components written in perl, even optimize time-critical sections in C.
<p>
Entity is not geared solely to user interface applications, but it was
designed with this in mind, and works well in that role.  Entity is
actually a program that takes an XML description, and turns that
description into in-memory objects.  The scripting language of your
choice is then used to manipulate these objects at runtime, allowing
you to easily create dynamic applications.  The objects may then be
returned to an XML representation at any time.
<p>
</sect>

<sect>Using XML
<p>
Entity uses XML as a textual representation of an application.
XML is parsed by Entity into a tree in memory.  Everything is marked
up from XML, including the user interface, code, and data that
an application may use.
<p>
Why XML ?  While XML does have its share of problems, it is the natural
fit for a tree-like markup, and is easily human readable and editable.
It's also fairly fast and simple to parse.
<p>
Entity does not use all of the XML specification - only a small subset
of all that "XML" can entail. All you need to know about XML is a few
simple things.  We'll use an example to illustrate:
<p>

<tscreen><verb>

&lt;element attribute="value"&gt;
  some data belonging to the outer node
  &lt;child-element attribute="value"/&gt;
  some more data belonging to the outer node
&lt;/element&gt;

</verb></tscreen>

<p>
The words used in the above example name the parts of the
representation they occupy.  An 'element' defines the type of the
'node'.  A 'node' is a single entry in an XML document.  An attribute
is just that - an attribute of the node, and of course, every
attribute must have a value. You will also find that we use the word
"tag" as synonym for "element".
<p>
You will notice from the above example that XML must be 'balanced',
and that every tag must be properly closed.  You will notice that
the second line is closed by using the '/&gt;' - a special notation to
allow you to close the node without an explicit closing tag.
<p>
In the above example, the 'child-element' node becomes a child of the parent
'element' node.  This is because the 'child-element' is declared within the
'element' node - before the 'element' node was closed.
<p>
You can also bind 'data' to a node.  This is done by having text placed after
you start a node, and before you end it. The data will be concatenated and
attached to its node. For example:
<p>

<tscreen><verb>

&lt;sometag&gt;
here is some data..
  &lt;someothertag&gt; bananas and pineapples &lt;/someothertag&gt;
here is more data
&lt;/sometag&gt;

</verb></tscreen>

<p>
The string "\nhere is some data..\n \nhere is more data", (\n is a way
to say "enter" or "linebreak") will then be bound to the "sometag"
node, and "bananas and pineapples" will be bound to the "someothertag"

<p>
Another useful XML-ism used in Entity is CDATA.  CDATA is just a way to
quote the data of a node, so you can use XML's special characters in
your data.  Here's what it looks like:

<p>

<tscreen><verb>

&lt;javascript&gt;
&lt;![CDATA[

data goes here ...
&lt;this won't confuse the parser&gt;

]]&gt;
&lt;/javascript&gt;

</verb></tscreen>
<p>
This allows you to insert any kind of text in the CDATA section, without
escaping it.  This is often used for code sections within Entity.
<p>
Similar to CDATA are "processing command" nodes. The XML specification
states that the data between &lt;? and ?&gt; markers should be passed
straight to the program, without interpretation as XML. This is used
to make a less ugly quoted tag. The example for CDATA would look like
this with a processing command node instead:
<p>

<tscreen><verb>

&lt;?javascript

data goes here
&lt;this won't confuse the parser&gt;
?&gt;

</verb></tscreen>
<p>
</sect>






<sect>Data Structures
<p>
The XML tree is translated into a live tree of objects, but these objects
may be thought of as if you were manipulating the XML tree directly.
The structures/concepts that make up this tree are:
<p>

<itemize>
<item><tt>ENode</tt><p>
		This is the basic in-memory node, it has attributes
		and stores the information about the item it builds
		when it is added to the tree.  An enode is displayed
		as 'element.name', when element is the type of node,
		and name is the name attribute, if no name attribute
		is set, name will be an underscore and a unique
		number.  ex 'button._342'.  This is mapped into a Class
		in most languages, which you can use to bind to a node
		in a running Entity application.  See the ENode API
		reference below for more details.
</item>

<item><tt>Attribute</tt><p>
        	This is an attribute of the enode, within the renderers
		functions are registered for when an attribute is set or
		requested.  In OO speak, these act as methods of the class of
		the node type.
</item>

<item<tt>Path</tt><p>
		A Path is how to describe where an enode is in the
		program, it starts at the root and progresses down the
		tree of enodes, putting the element.name
		representation seperated by '/'s until it gets the the
		destination enode.  In most languages if you print an
		enode it will give its path.
</item>
</itemize>
<p>

</sect>

<sect>Getting Started.
<p>
Now that we have an understanding of XML, and a general idea of how Entity
itself works, we'll show you how to create and run simple program.
<p>
Running entity Programs
<p>
Entity works like a scripting languages in how it loads up its applications.
The command:
<p>
$ entity file.e
<p>
will load up file.e (which contains an application marked up in
XML), and begin interpreting it.  
<p>
Alternatively you can use what is called the 'shebang' method, in
which you make the first line of the file:
<p>
#!/path/to/entity

or

#!/usr/bin/env entity
<p>
and set the file's permissions to include execution. This allows you
to run it as an interpreted file directly, without having to call
entity on it each time.  The second method is preferred because it
will work as long as you have /usr/bin/env, and Entity is in your
path. Entity's XML parser knows to ignore shebang lines if they are
present.
<p>
A first Entity program
<p>
Our sample file looks like this:
<p>

<tscreen><verb>

&lt;object name="foo"&gt;
  &lt;window title="This app rules"&gt;
    &lt;button label="DO NOT CLICK ME"/&gt;
  &lt;/window&gt;
  &lt;?perl
### This is where the code will go, when we write it later
  ?&gt;	
&lt;/object&gt;

</verb></tscreen>
<p>
When entity parses this, it builds a tree of ENodes that can be
represented like this:
<p>
<tscreen><verb>
/object.foo
  /window._123
    /button._254
  /perl._343
</verb></tscreen>
<p>
The names "_123", "_254" and "_343" are just unique identifiers made
up by entity; they may be different from run to run.
<p>
This should be familiar to anyone who has seen a graphical directory
tree browser.  We can see that we have a root, "/", which has a single
child, an object node called "foo". "foo" in turn has two children:  a
window node with an arbitrary (but unique) name, and a perl node with
another arbitrary name.  The window has one child: a button node with
an arbitrary name.
<p>
At parse time entity will construct the implementations of these
tags and keep them synchronized with your tree.  In our example, a
window is made with title "This app rules", containing just a button
labelled "DO NOT CLICK ME".  Also, the perl code is compiled and placed
in its own perl namespace. 
<p>
As a consequence of these at-startup actions, syntax errors or
compilation errors in code elements will be flagged at startup.  The
tree will still continue being built and the program will be run, but
the offending node will not be added to the tree.
<p>
Once entity has finished parsing the XML file and building the
in-memory objects, entity waits for events to happen - events being
anything the application listens to, from user actions to network
activity.
<p>
If the user clicks the button, entity looks to see if that button
wants to report the event to anyone.  Since our example has no code,
nothing happens.  Let's change that now.
<p>
Change your file to look like this:
<p>

<tscreen><verb>

&lt;object name="foo"&gt;
  &lt;window title="This app rules"&gt;
    &lt;button label="DO NOT CLICK ME" onclick="perl:clicked"/&gt;
  &lt;/window&gt;
  &lt;?perl
    sub clicked
    {
      $the_button = shift;
      print "button $the_button was clicked\n";
    }
  ?&gt;	
&lt;/object&gt;

</verb></tscreen>
<p>
So what's changed?  We've added an attribute called "onclick" to our
button tag, with the value "perl:clicked".  This means that when a
click event happens, entity looks in any perl nodes within the parent
object tag (this is one of the main roles of the object tag)
for a procedure called "clicked" and executes that. 
<p>
We've also added some code in the perl node, a sub called "clicked"
that we've told the button to call on click events.  This sub takes one
parameter: the node that was clicked.  This is so you can use a single
handler for a number of events, which can often be a very elegant way
of doing things.
<p>
You will find that in many applications programmers will set the
"default-lang" attribute in the object node to specify what language
should be called when no language identifier is given.  For example:
<p>

<tscreen><verb>

&lt;object default-lang="javascript"&gt;
    &lt;button onclick="some_javascript_function"/&gt;
    ...
&lt;/object&gt;

</verb></tscreen>
<p>

Because of the 'default-lang="javascript"' attribute of this object, when
the button is clicked, entity assumes the onclick callback
"some_javascript_function" is in fact a javascript function.  Entity will
search for this function in any javascript nodes within this object and
execute this function.
<p>
</sect>

<sect>A More complex Application
<p>
To really excercise some entity, we're going to make an application
that modifies its own structure.
<p>
Here's the XML:
<p>
<tscreen><verb>

&lt;object name="foo"&gt;
  &lt;window title="This app rules"&gt;
    &lt;button label="DO NOT CLICK ME" onclick="perl:clicked"/&gt;
  &lt;/window&gt;
  &lt;?perl
    sub clicked
    {
      $the_button = shift;
      print "button $the_button was clicked\n";
      $the_button-&gt;attrib("label" =&gt; "I TOLD YOU NOT TO CLICK ME");
      $xml_to_be_appended = qq!
        &lt;window title="This app still rules"&gt;
          &lt;button label="REALLY, DO NOT CLICK ME" onclick="perl:clicked"/&gt;
        &lt;/window&gt;
!;
      $the_button-&gt;append_xml($xml_to_be_appended);
    }
  ?&gt;
&lt;/object&gt;

</verb></tscreen>
<p>
Now every time a button is clicked, this button-node has its "label"
attribute changed, and a small XML tree is appended to the button-node.
The appended XML becomes a child of the button-node and consists of a
window-node which in turn has another button-node as its child.
This new button can then be clicked, which calls the "perl:clicked" callback,
which then changes the label and appends another small XML tree... 
and so on ad infinitum.
<p>
Note in this case that the same perl callback function can be used any number
of times with various entity events (in this case, with "onclick" events
from various buttons).  Notice, also, that entity dynamically
re-renders changed attributes and new nodes.
<p>

</sect>
<sect> ENode API
<p>
The ENode API is the interface with which all work is done in 
Entity.  It is through this API that the programmer is able to 
change the XML tree at runtime, and thereby produce a non-static
application.
<p>
The enode API is similar across all languages, but not identical.
The reference API is documented in docs/ENode.idl, in the Entity
distribution.  This API is then mapped as well as possible into
each language supported by Entity.  Some languages also have 
special ways of doing things that can make life easier.  Where
that is the case, those features have been used.
<p>
There are a few global methods that the langauges embedded within
Entity will recognise.  These will all return either a single 
ENode object (an instance of the ENode class), or a list of ENode
objects.  These are generally designed to find nodes within your
application, and return the object representation of them to you
so that you may manipulate them.  All these search routines will
start at the parent 'object' tag of the code that calls them.  This
allows seperate 'object's to exist within entity, and not have them
interfere with one another.
<p>

<itemize>
<item><tt>enode</tt><p>
                This function returns the ENode that matches its
		argument.  This is generally a 'basename' argument,
		that is, the type of the node concatenated with
		the name of the node (eg, 'button.mybutton').  The
		name is also optional, so you may simply search
		for 'button' and it will return the first match.
		If the arg starts with a '/' it will return the
		node based on a full path starting at the root of
		the XML tree.  If no node matches it will return
		the appropriate NULL construct for the language it
		was called from.
                <p>
                <tscreen><verb>
		Examples:
			perl:
				my $node = enode("button.Mybutton");
			javascript:
				othernode = enode ("ctree.FooCtree");
			C:
				ENode *thisnode;
				thisnode = enode ("valign.MyAlign");
			python:
				thatnode = enode("object");
			tcl:
				set node [enode object.FooObject]
                </verb></tscreen>
</item>

<item><tt>enode_rx</tt><p>

                Same as enode except the argument it accepts is a regular
		expression (perl compatible), matching the basename of each
		node in turn.
                <p>
                <tscreen><verb>
		Examples:
			perl:
				$node = enode_rx('window\.Win[1-4]');
			javascript:
				anothernode = enode_rx("ctree\.FB.*");
			C:
				Enode *mynode;
				mynode = enode_rx ("[button|window]\.ThisNode");
			python:
				nodetwo = enode_rx (".*");
			tcl:
				set foonode [enode_rx object\..*]
                </verb></tscreen>
</item>

<item><tt>elist</tt><p>

                Returns a list of nodes matching the argument.

                <p>
                <tscreen><verb>
		Examples:
			perl:
				my @nodes = elist("ctree");
			javascript:
				nodes = elist("ctree-row");
			C:
			python:
				nodes = elist("graph");
			tcl:
                </verb></tscreen>
</item>

<item><tt>elist_rx</tt><p>
                Same as elist but uses a regular expression to perform the match.
</item>
</itemize>

<p>
Now that we know how to get an ENode object, there are many things we can do
once we get this object.  The following is a list of methods supported:
<p>
<itemize>

<item><tt>parent</tt><p>
                Return a new ENode object that is the first parent
		that matches the string, this
		only searches directly up the tree.  If no argument
		is given (or in the case of C, it is NULL) it will return 
		the immediate parent.
</item>

<item><tt>child</tt><p>
		Much like enode, but searches only the children of the ENode
		object it is called with.  Note that this will return any
		matching descendant node, not just immediate children.

</item>

<item><tt>child_rx</tt><p>
        	Same as child but uses a regular expression for matching.
<item>

<item><tt>children</tt><p>
        	Returns a list of ENode's matching the first basename argument.
		If there is no argument, it returns all the immediate children.
</item>

<item<tt>children_rx</tt><p>
        	Like children but uses a regex.
</item>

<item><tt>children_attrib</tt><p>
       		Takes two arguments, attrib and value.  This will search
		all children of the node it is called from, and return any
		children who have the an attribute matching the given value.
</item>

<item><tt>children_attrib_rx</tt><p>

                Identical to above, but a regular expression
		may be used for the value argument, and will
		return the list of nodes that have values
		for the supplied attribute matching that
		regular expression.
</item>

<item><tt>attrib</tt><p>

                Get or set an attribute.  The first argument is the attribute,
                the second is the new value.  If no second argument is given, this
                function returns the present value of that attribute.
                Note that many language bindings use a
                more natural notation to express attribute
                getting and setting - python for example lets
                you reference a node's attributes using
                indexing (ie, node["attribute"] = value).
<item>


<item><tt>attrib_is_true</tt><p>
                Check to see if the attribute supplied is true, (true, yes, 1, etc).
                Returns a boolean.
</item>

<item><tt>destroy</tt><p>
                Destroy the current node, and all children.
</item>

<item><tt>destroy_children</tt><p>
                Destroy all the children of the current node while
                leaving the node it is referred from alone.
</item>

<item><tt>get_xml</tt><p>
                Returns an XML representation of the given node and
		all its children.

<item><tt>get_child_xml</tt><p>
                Returns an XML representation of all the given node's
		descendants, NOT including itself.
</item>

<item><tt>append_xml</tt><p>
                Parse the given XML string and build the objects it
		specifies under the referred ENode.
</item>

<item><tt>call</tt><p>

                Entity has a universal way of calling functions in
		any of the languages that it supports.	This method of the
		ENode class, allows you to tap into this functionality, and
		call a function in another language, and optionally, in another
		'object'.
                <p>
		The ENode object that is calling this method, will be used as
		the 'reference node', in determining which object the search
		for the function to call will be performed in.  It will also
		appear as the first argument to the called function, regardless
		of other arguments supplied.
                <p>
		The second argument, is the name of the function you wish to call.
		This may use the "language:function" notation that you see in callbacks
		from nodes (because it's the same mechanism).
		<p>
		The third argument, is the prototype string that lists the type
		of the following arguments.  This had to be done for languages like C
		that make it impossible to determine argument types, and
		because many language have stricter typing rules than perl,
		python, javascript etc.
                <p>
		The argument string can have these letters "nesidb".
		n, s, and i should be all you need externally, they are for
		node, string, and int respectively.
                <p>
		Example: calling a the python function "foo" with
		parameters (1, "a string")
		<p>
                <tscreen><verb>
		node.call("python:foo", "is", 1, "a string")
                </verb></tscreen>
</item>

<item><tt>new_child</tt><p>
                Create a new child within the node, new_child can accept info
		about the new node in a few ways.  The name can be specified
		with the element like new_child("button.goodname").  Also attributes
		may be set by doing attrib, value, attrib, value.  Note that this
		is another function that will vary slightly depending on the language
		used.  This returns the newly created child ENode object.
</item>

<item><tt>set_data</tt><p>
                Set the data of the ENode to the string supplied as the only arugment.
</item>

<item><tt>get_data</tt><p>
                Retrieve the data of the ENode.
</item>

<item><tt>append_data</tt><p>
                Append the string given as the only node, to the data currently
		bound to the node.
</item>

<item><tt>insert_data</tt><p>
                Insert a string at any location within the current data.
</item>

<item><tt>delete_data</tt><p>
                Delete a range of data within the node beginning at any offset.
</item>
</itemize>
<p>

</sect>


<sect>Going Further With Entity
<p>
This section is incomplete.  It should show a good sample program
showing callbacks, tree searches, attrib functions etc.  This should
really be the bulk of the tutorial.
</sect>

<sect>Tips and tricks
<p>
This section is incomplete.  Should mention:

<itemize>
<item>
Config files in XML.
</item>
<item>
timers.
</item>
<item>
which attribs get saved.
</item>
<item>
userrenderers
</item>
<item>
norender
</item>
<item>
nodes as DB, interfaces with DB's etc.
</item>
<item>
entity -a file.e stembuilder.e for inspection/tweaking
</item>
<item>
multiple 'concurrent' objects
</item>
<item>
polling with the io renderer
</item>
</itemize>
<p>
</sect>


<sect>About
<p>
Many thanks to John Wimer, Ian Main, Jim Meier, and Stephen Balukoff for
helping with this tutorial.
<p>
The latest version of this tutorial will always be made available at http://www.entity.cx.
</sect>

</article>