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
|
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE chapter SYSTEM "chapter.dtd">
<chapter>
<header>
<copyright>
<year>2000</year><year>2013</year>
<holder>Ericsson AB. All Rights Reserved.</holder>
</copyright>
<legalnotice>
The contents of this file are subject to the Erlang Public License,
Version 1.1, (the "License"); you may not use this file except in
compliance with the License. You should have received a copy of the
Erlang Public License along with this software. If not, it can be
retrieved online at http://www.erlang.org/.
Software distributed under the License is distributed on an "AS IS"
basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
the License for the specific language governing rights and limitations
under the License.
</legalnotice>
<title>Interface Functions</title>
<prepared></prepared>
<docno></docno>
<date></date>
<rev></rev>
<file>gs_chapter2.xml</file>
</header>
<section>
<title>Overview</title>
<p>The following interface functions are included with the graphics system:</p>
<list type="bulleted">
<item><c><![CDATA[gs:start().]]></c> This function starts the graphics server and returns its object identifier. If the graphics server has already been started, it returns its original identifier.</item>
<item><c><![CDATA[gs:stop().]]></c> This function stops the graphics server and closes all windows which <c><![CDATA[gs]]></c> has launched. This function is not the opposite of <c><![CDATA[gs:start/0]]></c> because <c><![CDATA[gs:stop/1]]></c> causes all applications to lose the graphics server and the objects created with the <c><![CDATA[gs]]></c> system.</item>
<item><c><![CDATA[gs:create(Objtype, Parent, Options).]]></c> This function creates a new object of specified <c><![CDATA[Objtype]]></c> as a child to the specified <c><![CDATA[Parent]]></c>. It configures the object with <c><![CDATA[Options]]></c> and returns the identifier for the object, or <c><![CDATA[{error,Reason}]]></c>.</item>
<item><c><![CDATA[gs:create(Objtype, Name, Parent, Options).]]></c> This function is identical to the previously listed function, except that a <c><![CDATA[Name]]></c> is specified to reference the object. <c><![CDATA[Name]]></c> is an atom.</item>
<item><c><![CDATA[gs:destroy(IdOrName).]]></c> This function destroys an object and all its children.</item>
<item><c><![CDATA[gs:config(IdOrNeme, Options).]]></c> This function configures an object with <c><![CDATA[Options]]></c>. It returns <c><![CDATA[ok]]></c>, or <c><![CDATA[{error,Reason}]]></c>.</item>
<item><c><![CDATA[gs:read(Id_or_Name, OptionKey).]]></c> This function reads the value of an object option. It returns the value, or <c><![CDATA[{error,Reason}]]></c>.</item>
</list>
<p>The above list contains all the function which are <em>needed</em> with the graphics system. For convenience, the following aliases also exist:</p>
<list type="bulleted">
<item><c><![CDATA[gs:create(Obttype, Parent).]]></c></item>
<item><c><![CDATA[gs:create(Objtype, Parent, Options).]]></c></item>
<item><c><![CDATA[gs:create(Objtype, Parent, Option).]]></c></item>
<item><c><![CDATA[gs:create(Objtype, Name, Parent, Options).]]></c></item>
<item><c><![CDATA[gs:create(Objtype, Name, Parent, Option).]]></c></item>
<item><c><![CDATA[gs:Objecttype(Parent).]]></c></item>
<item><c><![CDATA[gs:Objecttype(Parent,Options).]]></c></item>
<item><c><![CDATA[gs:Objecttype(Parent, Option).]]></c></item>
<item><c><![CDATA[gs:Objecttype(Name, Parent, Options).]]></c></item>
<item><c><![CDATA[gs:Objecttype(Name, Parent, Option).]]></c></item>
<item><c><![CDATA[gs:config(IdOrName, Option).]]></c></item>
</list>
<p>These shorthands can be used as follows:</p>
<list type="bulleted">
<item><c><![CDATA[gs:window(gs:start(), {map,true}).]]></c></item>
<item><c><![CDATA[gs:button(W).]]></c></item>
<item><c><![CDATA[gs:config(B,{label,{text,"Hi!"}}).]]></c></item>
</list>
<p>The <c><![CDATA[create_tree/2]]></c> function is useful for creating a large hierarchy of objects. It has the following syntax: </p>
<code type="none"><![CDATA[
create_tree(ParentId,Tree) -> | {error,Reason}
]]></code>
<p><c><![CDATA[Tree]]></c> is a list of <c><![CDATA[Object]]></c>, and <c><![CDATA[Object]]></c> is any of the following:</p>
<list type="bulleted">
<item><c><![CDATA[{ObjectType,Name,Options,Tree}]]></c></item>
<item><c><![CDATA[{ObjectType,Options,Tree}]]></c></item>
<item><c><![CDATA[{ObjectType,Options}]]></c></item>
</list>
<p>The following example constructs a window which contains two objects, a button and a frame with a label:</p>
<code type="none"><![CDATA[
R = [{window,[{map,true}],
[{button,[{label,{text,"Butt1"}}]},
{frame,[{y,40}],[{label,[{label,{text,"Lbl1"}}]}]}]}],
gs:create_tree(gs:start(),R).
]]></code>
</section>
<section>
<title>A First Example</title>
<p>The first action required is to start up the graphics server. This operation returns an identifier for the server process, which registers itself under the name <c><![CDATA[gs]]></c>. If a graphics server was already started, its identifier is returned. We can now create objects and configure the behavior and appearance of these objects. When all objects are created and configured in a top level window, we map it on the screen to make it visible. The example below shows how to create a window with a button that says "Press Me".</p>
<codeinclude file="examples/ex1.erl" tag="" type="erl"></codeinclude>
<p>The following steps were completed in this code:</p>
<list type="bulleted">
<item>start a graphics server</item>
<item>create a window of specified width and height</item>
<item>create a button with the text "Press Me"</item>
<item>map the window on the screen</item>
<item>enter the event loop.</item>
</list>
<p>The event loop is where we receive events from <c><![CDATA[gs]]></c>. In this case, we want to receive a click event from the button. This event is delivered when the user presses the button.</p>
<marker id="gs_fig4"></marker>
<image file="images/ex1.gif">
<icaption>
"Press Me" Button Example</icaption>
</image>
<p>The Erlang <c><![CDATA[gs]]></c> system includes many examples. All examples in this document can be found in the <c><![CDATA[doc/users_guide/examples/]]></c> directory. In addition, there is an example directory which contains examples of fractal trees, bouncing balls, a color editor, and a couple of other <c><![CDATA[gs]]></c> applications.</p>
</section>
<section>
<title>Creating Objects</title>
<p>You create an object of a specified type with the <c><![CDATA[create/3]]></c> or the <c><![CDATA[create/4]]></c> function. The difference is that the <c><![CDATA[create/4]]></c> function allows you to assign names to the objects. You can then refer to the object instead of using the object identifier. The two forms of the <c><![CDATA[create]]></c> function look as follows:</p>
<code type="none"><![CDATA[
ObjId = gs:create(Objtype, Parent, Options)
ObjId = gs:create(Objtype, Name, Parent, Options)
]]></code>
<p>Examples of built-in object types are:</p>
<list type="bulleted">
<item>window</item>
<item>frame</item>
<item>menu</item>
<item>button</item>
<item>radio button</item>
<item>list box.</item>
</list>
<p>Objects are created in a hierarchical order. The top level object is the window object which is a container object for most other object types.</p>
<marker id="gs_fig5"></marker>
<image file="images/gs1-1-image-4.gif">
<icaption>Hierarchy of Objects</icaption>
</image>
<p>A frame object is like a sub-window but also a container object which can have children objects.</p>
<p>The <c><![CDATA[create/3]]></c> or <c><![CDATA[create/4]]></c> functions return an object identifier, or the tuple <c><![CDATA[{error, Reason}]]></c>. The object identifier uniquely identifies the object within the system. The object identifier is used to:</p>
<list type="bulleted">
<item>reconfigure an object</item>
<item>identify events from a particular object.</item>
</list>
</section>
<section>
<title>Ownership</title>
<p>The process which creates an object is said to own the object. When a process dies, all objects owned by the process are destroyed. The ownership also means that all events generated by a specific object are delivered to the owner process. The graphics server keeps track of all Erlang processes that create objects. It is therefore able to take appropriate actions if a process should die.</p>
</section>
<section>
<title>Naming Objects</title>
<p>As shown previously, the <c><![CDATA[create/4]]></c> function can be used to name objects. The name should be a unique atom which is used to reference the object. The advantage of naming objects is that we do not have to pass object identifiers as arguments to the event loop. Instead, we can use the object name in our code. To name objects in the following example, the code gives the name <c><![CDATA[win1]]></c> to the window, and <c><![CDATA[b1]]></c> to the button.</p>
<codeinclude file="examples/ex2.erl" tag="" type="erl"></codeinclude>
<p>The name is <em>local</em> for the process which creates the object. This means that the name have a meaning only for one process. Different processes can give different objects the same name. When passing references to objects between processes, the object identifier has to be used because names only has a meaning in a process context. If necessary, the object identifier can be retrieved by reading the <c><![CDATA[id]]></c> option.</p>
<p>When using distributed Erlang, objects should be named carefully. A named object always refers to an object in the graphics system on the node where it was created. The syntax <c><![CDATA[{Name,Node}]]></c> should be used when referring to a named object on another node.</p>
<p>The following example receives a canvas object from another node and creates a line named <c><![CDATA[myline1]]></c> that will appear in the canvas. Also, this example demonstrates how to configure the line using the special syntax.</p>
<code type="none"><![CDATA[
foo() ->
receive
{gs_obj,Canvas,FromNode} -> ok
end,
gs:create(line,myline1,Canvas,[{coords,[{10,10},{20,20}]}]),
gs:config({myline1,FromNode},[{buttonpress,true}]).
]]></code>
<p>Unnamed objects are transparent. For example, a line object can be created from a canvas on another node and then configured as any other object.</p>
<code type="none"><![CDATA[
bar() ->
receive
{gs_obj,Canvas,_FromNode} -> ok
end,
L = gs:create(line,Canvas,[{coords,[{10,10},{20,20}]}]),
gs:config(L,[{buttonpress,true}]).
]]></code>
</section>
</chapter>
|