aboutsummaryrefslogtreecommitdiffstats
path: root/lib/gs/examples
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
committerErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
commit84adefa331c4159d432d22840663c38f155cd4c1 (patch)
treebff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/gs/examples
downloadotp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz
otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2
otp-84adefa331c4159d432d22840663c38f155cd4c1.zip
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/gs/examples')
-rw-r--r--lib/gs/examples/Makefile95
-rw-r--r--lib/gs/examples/README24
-rw-r--r--lib/gs/examples/ball.erl71
-rw-r--r--lib/gs/examples/browser.erl89
-rw-r--r--lib/gs/examples/calc.erl108
-rw-r--r--lib/gs/examples/calc2.erl96
-rw-r--r--lib/gs/examples/color_demo.erl62
-rw-r--r--lib/gs/examples/color_demo2.erl108
-rw-r--r--lib/gs/examples/distrib_draw.erl116
-rw-r--r--lib/gs/examples/entry_demo.erl63
-rw-r--r--lib/gs/examples/event_test.erl48
-rw-r--r--lib/gs/examples/file_dialog.erl255
-rw-r--r--lib/gs/examples/focus_demo.erl97
-rw-r--r--lib/gs/examples/frac.erl154
-rw-r--r--lib/gs/examples/line_demo.erl75
-rw-r--r--lib/gs/examples/man.erl192
-rw-r--r--lib/gs/examples/menu_demo.erl74
-rw-r--r--lib/gs/examples/rubber.erl104
18 files changed, 1831 insertions, 0 deletions
diff --git a/lib/gs/examples/Makefile b/lib/gs/examples/Makefile
new file mode 100644
index 0000000000..10b166b207
--- /dev/null
+++ b/lib/gs/examples/Makefile
@@ -0,0 +1,95 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 1996-2009. All Rights Reserved.
+#
+# 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.
+#
+# %CopyrightEnd%
+#
+
+#
+include $(ERL_TOP)/make/target.mk
+include $(ERL_TOP)/make/$(TARGET)/otp.mk
+
+# ----------------------------------------------------
+# Application version
+# ----------------------------------------------------
+include ../vsn.mk
+VSN=$(GS_VSN)
+
+# ----------------------------------------------------
+# Release directory specification
+# ----------------------------------------------------
+RELSYSDIR = $(RELEASE_PATH)/lib/gs-$(VSN)/examples
+
+# ----------------------------------------------------
+# Target Specs
+# ----------------------------------------------------
+
+MODULES= \
+ ball \
+ browser \
+ calc \
+ calc2 \
+ color_demo \
+ color_demo2 \
+ distrib_draw \
+ entry_demo \
+ event_test \
+ file_dialog \
+ focus_demo \
+ frac \
+ line_demo \
+ man \
+ menu_demo \
+ rubber
+
+HRL_FILES=
+
+ERL_FILES= $(MODULES:%=%.erl)
+
+TARGET_FILES= $(MODULES:%=$(EBIN)/%.$(EMULATOR))
+
+# ----------------------------------------------------
+# FLAGS
+# ----------------------------------------------------
+ERL_COMPILE_FLAGS +=
+
+# ----------------------------------------------------
+# Targets
+# ----------------------------------------------------
+
+debug opt: $(TARGET_FILES)
+
+docs:
+
+clean:
+ rm -f $(TARGET_FILES)
+ rm -f core
+
+# ----------------------------------------------------
+# Special Build Targets
+# ----------------------------------------------------
+
+# ----------------------------------------------------
+# Release Target
+# ----------------------------------------------------
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+release_spec: opt
+ $(INSTALL_DIR) $(RELSYSDIR)/ebin
+ $(INSTALL_DATA) $(TARGET_FILES) $(RELSYSDIR)/ebin
+ $(INSTALL_DIR) $(RELSYSDIR)/src
+ $(INSTALL_DATA) $(ERL_FILES) $(HRL_FILES) $(RELSYSDIR)/src
+
+release_docs_spec:
diff --git a/lib/gs/examples/README b/lib/gs/examples/README
new file mode 100644
index 0000000000..07c2bcb005
--- /dev/null
+++ b/lib/gs/examples/README
@@ -0,0 +1,24 @@
+Purpose:
+ Provide short example programs
+
+
+File Description
+------------------------------------------------------------------------
+ball.erl A bouncing ball in a window. Demonstrates canvas and oval.
+browser.erl How to program a listbox.
+calc.erl Simple calculator. The example shows how silly it is to always
+ pass along object identifiers as arguments.
+calc2.erl Using the data field instead.
+color_demo.erl Shows hot to program scales.
+color_demo2.erl Using Motion events to select a color.
+distrib_draw.erl Simple drawing area shared by two nodes.
+entry_demo.erl How to use an entry object.
+event_test.erl Demonstration of events in gs.
+file_dialog.erl A complete(?) file browser using a listbox.
+focus_demo.erl A test for focus.
+frac.erl Joe's old pxw demo converted to gs.
+line_demo.erl A bouncing line in a canvas.
+man.erl A Manual page viewer.
+menu_demo.erl Menu Demo. How to create menues.
+rubber.erl Shows how to do rubberbanding (on a canvas) in Erlang.
+
diff --git a/lib/gs/examples/ball.erl b/lib/gs/examples/ball.erl
new file mode 100644
index 0000000000..3f91a7b379
--- /dev/null
+++ b/lib/gs/examples/ball.erl
@@ -0,0 +1,71 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%%
+%% 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.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% ------------------------------------------------------------
+%% A simple demo showing a ball
+%% bouncing in a window.
+%% ------------------------------------------------------------
+
+-module(ball).
+
+-export([start/0,init/0]).
+
+start() ->
+ spawn(ball,init,[]).
+
+init() ->
+ I= gs:start(),
+ W= gs:window(I,[{title,"Ball"},{width,300},{height,300},{map,true}]),
+ C= gs:canvas(W,[{width,300},{height,300},{bg,yellow}]),
+ gs:button(W,[{label, {text,"Quit Demo"}},{x,100}]),
+ Ball = gs:oval(C,[{coords,[{0,0},{50,50}]},{fill,red}]),
+ ball(Ball,0,0,5.5,4.1).
+
+ball(Ball,X,Y,DX,DY) ->
+ {NX,NDX} = cc(X,DX),
+ {NY,NDY} = cc(Y,DY),
+ gs:config(Ball,{move,{DX,DY}}),
+ receive
+ {gs,_,click,_,_} -> exit(normal);
+ {gs,_,destroy,_,_} -> exit(normal)
+ after 20 ->
+ true
+ end,
+ ball(Ball,NX,NY,NDX,NDY).
+
+cc(X,DX) ->
+ if
+ DX>0 ->
+ if
+ X=<250 ->
+ {X+DX,DX};
+ x>250 ->
+ {X-DX,-DX}
+ end;
+ DX<0 ->
+ if
+ X>=0 ->
+ {X+DX,DX};
+ X<0 ->
+ {X-DX,-DX}
+ end
+ end.
+
+%% ------------------------------------------------------------
diff --git a/lib/gs/examples/browser.erl b/lib/gs/examples/browser.erl
new file mode 100644
index 0000000000..1dba5a915b
--- /dev/null
+++ b/lib/gs/examples/browser.erl
@@ -0,0 +1,89 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%%
+%% 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.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% ------------------------------------------------------------
+%% Simple Browser
+%% ------------------------------------------------------------
+
+-module(browser).
+
+-export([start/0,start/2,init/3]).
+
+start() ->
+ spawn(browser,init,[self(),text(),items()]),
+ receive
+ {browser,Result} -> Result
+ end.
+
+text() -> "Pick an erlangian: ".
+
+items() ->
+ lists:sort(["marcus","bjorn","anders","dalle","henrik","mk",
+ "keisu","klas","patric","ola","torpvret","lelle",
+ "eklas","mbj","janne","martin","kent","pippi",
+ "gunilla","uwiger","macr"]).
+
+
+start(Text,Items) ->
+ spawn(browser,init,[self(),Text,Items]),
+ receive
+ {browser,Result} -> Result
+ end.
+
+init(Pid,Text,Items) ->
+ S=gs:start(),
+ Win=gs:window(S,[{width,250},{height,270},{title,"Browser"}]),
+ gs:label(Win,[{label,{text,Text}},{width,250}]),
+ Entry=gs:entry(Win,[{y,35},{width,240},{x,5},
+ {keypress,true},{setfocus,true}]),
+ Lb=gs:listbox(Win,[{x,5},{y,65},{width,160},{height,195},
+ {vscroll,right},{click,true},{doubleclick,true}]),
+ Ok=gs:button(Win,[{label,{text,"OK"}},{width,40},{x,185},{y,175}]),
+ Cancel=gs:button(Win,[{label,{text,"Cancel"}},{x,175},{y,225},{width,65}]),
+ gs:config(Lb,[{items,Items}]),
+ gs:config(Win,{map,true}),
+ browser_loop(Pid,Ok,Cancel,Entry,Lb).
+
+browser_loop(Pid,Ok,Cancel,Entry,Lb) ->
+ receive
+ {gs,Ok,click,_,_} ->
+ Txt=gs:read(Entry,text),
+ Pid ! {browser,{ok,Txt}};
+ {gs,Cancel,click,_,_} ->
+ Pid ! {browser,cancel};
+ {gs,Entry,keypress,_,['Return'|_]} ->
+ Txt=gs:read(Entry,text),
+ Pid ! {browser,{ok,Txt}};
+ {gs,Entry,keypress,_,_} ->
+ browser_loop(Pid,Ok,Cancel,Entry,Lb);
+ {gs,Lb,click,_,[_Idx, Txt|_]} ->
+ gs:config(Entry,{text,Txt}),
+ browser_loop(Pid,Ok,Cancel,Entry,Lb);
+ {gs,Lb,doubleclick,_,[_Idx, Txt|_]} ->
+ Pid ! {browser,{ok,Txt}};
+ {gs,_,destroy,_,_} ->
+ Pid ! {browser,cancel};
+ X ->
+ io:format("Got X=~w~n",[X]),
+ browser_loop(Pid,Ok,Cancel,Entry,Lb)
+ end.
+
+%% ------------------------------------------------------------
+%% end of browser.erl
diff --git a/lib/gs/examples/calc.erl b/lib/gs/examples/calc.erl
new file mode 100644
index 0000000000..992b8adb4e
--- /dev/null
+++ b/lib/gs/examples/calc.erl
@@ -0,0 +1,108 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%%
+%% 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.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% ------------------------------------------------------------
+%% A Simple Calculator demo in Erlang
+%% ------------------------------------------------------------
+
+-module(calc).
+
+-export([start/0,calc/0]).
+
+start() ->
+ spawn(calc,calc,[]).
+
+calc() ->
+ I = gs:start(),
+ Win = gs:window(I,[{title,"Calc1"},{width,120},{height,150}]),
+ Label = gs:label(Win,[{label,{text,"0"}},{width,120}]),
+ B1 = gs:button(Win,[{label,{text,"1"}},{width,30},{x,0},{y,30}]),
+ B2 = gs:button(Win,[{label,{text,"2"}},{width,30},{x,30},{y,30}]),
+ B3 = gs:button(Win,[{label,{text,"3"}},{width,30},{x,60},{y,30}]),
+ B4 = gs:button(Win,[{label,{text,"4"}},{width,30},{x,0},{y,60}]),
+ B5 = gs:button(Win,[{label,{text,"5"}},{width,30},{x,30},{y,60}]),
+ B6 = gs:button(Win,[{label,{text,"6"}},{width,30},{x,60},{y,60}]),
+ B7 = gs:button(Win,[{label,{text,"7"}},{width,30},{x,0},{y,90}]),
+ B8 = gs:button(Win,[{label,{text,"8"}},{width,30},{x,30},{y,90}]),
+ B9 = gs:button(Win,[{label,{text,"9"}},{width,30},{x,60},{y,90}]),
+ B0 = gs:button(Win,[{label,{text,"0"}},{width,60},{x,0},{y,120}]),
+ C = gs:button(Win,[{label,{text,"C"}},{width,30},{x,60},{y,120}]),
+ AC = gs:button(Win,[{label,{text,"AC"}},{width,30},{x,90},{y,120},{fg,red}]),
+ Plus = gs:button(Win,[{label,{text,"+"}},{width,30},{x,90},{y,30}]),
+ Times = gs:button(Win,[{label,{text,"*"}},{width,30},{x,90},{y,60}]),
+ Minus = gs:button(Win,[{label,{text,"-"}},{width,30},{x,90},{y,90}]),
+ gs:config(Win,{map,true}),
+ Ids = [Label,B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,Minus,Plus,Times,C,AC],
+ calc_loop(Ids,0,0,'+').
+
+calc_loop(Ids,M,V,Op) ->
+ [_Label,B0,B1,B2,B3,B4,B5,B6,B7,B8,B9,Minus,Plus,Times,C,AC] = Ids,
+ receive
+ {gs,B0,click,_,_} -> digit_press(Ids,M,V*10+0,Op);
+ {gs,B1,click,_,_} -> digit_press(Ids,M,V*10+1,Op);
+ {gs,B2,click,_,_} -> digit_press(Ids,M,V*10+2,Op);
+ {gs,B3,click,_,_} -> digit_press(Ids,M,V*10+3,Op);
+ {gs,B4,click,_,_} -> digit_press(Ids,M,V*10+4,Op);
+ {gs,B5,click,_,_} -> digit_press(Ids,M,V*10+5,Op);
+ {gs,B6,click,_,_} -> digit_press(Ids,M,V*10+6,Op);
+ {gs,B7,click,_,_} -> digit_press(Ids,M,V*10+7,Op);
+ {gs,B8,click,_,_} -> digit_press(Ids,M,V*10+8,Op);
+ {gs,B9,click,_,_} -> digit_press(Ids,M,V*10+9,Op);
+ {gs,Minus,click,_,_} -> calc(Ids,Op,M,V,'-');
+ {gs,Plus,click,_,_} -> calc(Ids,Op,M,V,'+');
+ {gs,Times,click,_,_} -> calc(Ids,Op,M,V,'*');
+ {gs,AC,click,_,_} -> ac(Ids,M,V,Op);
+ {gs,C,click,_,_} -> c(Ids,M,V,Op);
+ {gs,_,destroy,_,_} -> exit(normal);
+ _Other -> calc_loop(Ids,M,V,Op)
+ end.
+
+digit_press(Ids,M,V,Op) ->
+ [Label|_]=Ids,
+ gs:config(Label,[{label,{text,V}}]),
+ calc_loop(Ids,M,V,Op).
+
+calc(Ids,'+',M,V,Op) ->
+ NewM = M + V,
+ [Label|_]=Ids,
+ gs:config(Label,[{label,{text,NewM}}]),
+ calc_loop(Ids,NewM,0,Op);
+calc(Ids,'-',M,V,Op) ->
+ NewM = M - V,
+ [Label|_]=Ids,
+ gs:config(Label,[{label,{text,NewM}}]),
+ calc_loop(Ids,NewM,0,Op);
+calc(Ids,'*',M,V,Op) ->
+ NewM = M * V,
+ [Label|_]=Ids,
+ gs:config(Label,[{label,{text,NewM}}]),
+ calc_loop(Ids,NewM,0,Op).
+
+c(Ids,M,_V,Op) ->
+ [Label|_]=Ids,
+ gs:config(Label,[{label,{text,0}}]),
+ calc_loop(Ids,M,0,Op).
+
+ac(Ids,_M,_V,_Op) ->
+ [Label|_]=Ids,
+ gs:config(Label,[{label,{text,0}}]),
+ calc_loop(Ids,0,0,'+').
+
+%% ------------------------------------------------------------
diff --git a/lib/gs/examples/calc2.erl b/lib/gs/examples/calc2.erl
new file mode 100644
index 0000000000..d28780de01
--- /dev/null
+++ b/lib/gs/examples/calc2.erl
@@ -0,0 +1,96 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%%
+%% 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.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% ------------------------------------------------------------
+%% A Simple Calculator demo in Erlang
+%% Describes how to match against the data field.
+%% ------------------------------------------------------------
+
+-module(calc2).
+-export([start/0,calc/0]).
+
+start() ->
+ spawn(calc2,calc,[]).
+
+calc() ->
+ I = gs:start(),
+ Win = gs:window(I,[{title,"Calc2"},{width,120},{height,150}]),
+ Lbl = gs:label(Win,[{label,{text,"0"}},{width,120}]),
+ gs:button(Win,[{label,{text,"1"}},{width,30},{x,0},{y,30},{data,1}]),
+ gs:button(Win,[{label,{text,"2"}},{width,30},{x,30},{y,30},{data,2}]),
+ gs:button(Win,[{label,{text,"3"}},{width,30},{x,60},{y,30},{data,3}]),
+ gs:button(Win,[{label,{text,"4"}},{width,30},{x,0},{y,60},{data,4}]),
+ gs:button(Win,[{label,{text,"5"}},{width,30},{x,30},{y,60},{data,5}]),
+ gs:button(Win,[{label,{text,"6"}},{width,30},{x,60},{y,60},{data,6}]),
+ gs:button(Win,[{label,{text,"7"}},{width,30},{x,0},{y,90},{data,7}]),
+ gs:button(Win,[{label,{text,"8"}},{width,30},{x,30},{y,90},{data,8}]),
+ gs:button(Win,[{label,{text,"9"}},{width,30},{x,60},{y,90},{data,9}]),
+ gs:button(Win,[{label,{text,"0"}},{width,60},{x,0},{y,120},{data,0}]),
+ gs:button(Win,[{label,{text,"C"}},{width,30},{x,60},{y,120},{data,'C'}]),
+ gs:button(Win,[{label,{text,"AC"}},{width,30},{x,90},{y,120},{data,'AC'},
+ {fg,red}]),
+ gs:button(Win,[{label,{text,"+"}},{width,30},{x,90},{y,30},{data,'+'}]),
+ gs:button(Win,[{label,{text,"*"}},{width,30},{x,90},{y,60},{data,'*'}]),
+ gs:button(Win,[{label,{text,"-"}},{width,30},{x,90},{y,90},{data,'-'}]),
+ gs:config(Win,{map,true}),
+ calc_loop(Lbl,0,0,'+').
+
+calc_loop(Lbl,M,V,Op) ->
+ receive
+ {gs,_,click,D,_} when integer(D) ->
+ digit_press(Lbl,M,V*10+D,Op);
+ {gs,_,click,'C',_} ->
+ c(Lbl,M,V,Op);
+ {gs,_,click,'AC',_} ->
+ ac(Lbl,M,V,Op);
+ {gs,_,click,NewOp,_} ->
+ calc(Lbl,Op,M,V,NewOp);
+ {gs,_,destroy,_,_} ->
+ exit(normal);
+ _Other ->
+ calc_loop(Lbl,M,V,Op)
+ end.
+
+digit_press(Lbl,M,V,Op) ->
+ gs:config(Lbl,[{label,{text,V}}]),
+ calc_loop(Lbl,M,V,Op).
+
+calc(Lbl,'+',M,V,Op) ->
+ NewM = M + V,
+ gs:config(Lbl,[{label,{text,NewM}}]),
+ calc_loop(Lbl,NewM,0,Op);
+calc(Lbl,'-',M,V,Op) ->
+ NewM = M - V,
+ gs:config(Lbl,[{label,{text,NewM}}]),
+ calc_loop(Lbl,NewM,0,Op);
+calc(Lbl,'*',M,V,Op) ->
+ NewM = M * V,
+ gs:config(Lbl,[{label,{text,NewM}}]),
+ calc_loop(Lbl,NewM,0,Op).
+
+c(Lbl,M,_V,Op) ->
+ gs:config(Lbl,[{label,{text,0}}]),
+ calc_loop(Lbl,M,0,Op).
+
+ac(Lbl,_M,_V,_Op) ->
+ gs:config(Lbl,[{label,{text,0}}]),
+ calc_loop(Lbl,0,0,'+').
+
+%% ------------------------------------------------------------
diff --git a/lib/gs/examples/color_demo.erl b/lib/gs/examples/color_demo.erl
new file mode 100644
index 0000000000..650f853061
--- /dev/null
+++ b/lib/gs/examples/color_demo.erl
@@ -0,0 +1,62 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%%
+%% 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.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% ------------------------------------------------------------
+%% A simple demo for choosing
+%% colors in a window.
+%% ------------------------------------------------------------
+
+-module(color_demo).
+
+-export([start/0,init/0]).
+
+start() ->
+ spawn(color_demo,init,[]).
+
+init() ->
+ I= gs:start(),
+ W= gs:window(I,[{title,"Color Demo"},{width,300},{height,195}]),
+ B=gs:button(W,[{label,{text,"Quit"}},{x,261},{y,166},{width,40}]),
+ gs:config(B,[{bg,yellow},{fg,hotpink1},{data,quit}]),
+ gs:scale(W,[{text,"Red"},{y,0},{range,{0,255}},{orient,horizontal},
+ {height,65},{data,red},{pos,42}]),
+ gs:scale(W,[{text,"Blue"},{y,65},{range,{0,255}},{orient,horizontal},
+ {height,65},{data,blue},{pos,42}]),
+ gs:scale(W,[{text,"Green"},{y,130},{range,{0,255}},{orient,horizontal},
+ {height,65},{data,green},{pos,42}]),
+ gs:config(W,{map,true}),
+ loop(W,0,0,0).
+
+loop(W,R,G,B) ->
+ gs:config(W,{bg,{R,G,B}}),
+ receive
+ {gs,_,click,red,[New_R|_]} ->
+ loop(W,New_R,G,B);
+ {gs,_,click,green,[New_G|_]} ->
+ loop(W,R,New_G,B);
+ {gs,_,click,blue,[New_B|_]} ->
+ loop(W,R,G,New_B);
+ {gs,_,click,quit,_} ->
+ true;
+ {gs,W,destroy,_,_} ->
+ true
+ end.
+
+%% ------------------------------------------------------------
diff --git a/lib/gs/examples/color_demo2.erl b/lib/gs/examples/color_demo2.erl
new file mode 100644
index 0000000000..817cc9ed7d
--- /dev/null
+++ b/lib/gs/examples/color_demo2.erl
@@ -0,0 +1,108 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%%
+%% 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.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% ------------------------------------------------------------
+%% Another simple demo for choosing
+%% colors in a window.
+%% ------------------------------------------------------------
+
+-module(color_demo2).
+
+-export([start/0,init/0]).
+
+start() ->
+ spawn(color_demo2,init,[]).
+
+
+init() ->
+ S=gs:start(),
+ Win = gs:create(window,S,[{width,380},{height,430},{motion,true},
+ {buttonpress,true}]),
+ gs:create(button,b1,Win,[{x,200},{label,{text,""}}]),
+ gs:create(button,Win,[{data,quit},{label,{text,"Quit"}},{bg,yellow},
+ {width,40}]),
+ Side = 200,
+ Tri = equi_tri(100, 400, Side),
+ %% draw_lines(Win, Tri),
+ gs:config(Win,[{title,"Color Demo 2"},{map,true}]),
+ server(Win, Side, Tri, {0,0,0}).
+
+server(Win, Side, [Point1, Point2, Point3], OldCol) ->
+ receive
+ {gs,Win,motion,_,[X,Y|_]} ->
+ R = col({X,Y}, Point1, Side),
+ G = col({X,Y}, Point2, Side),
+ B = col({X,Y}, Point3, Side),
+ Txt = lists:flatten(io_lib:format("~w ~w ~w",[R,G,B])),
+ gs:config(b1,[{label,{text,Txt}}]),
+ Col = {R, G, B},
+ gs:config(Win, [{bg,Col}]),
+ server(Win, Side, [Point1, Point2, Point3], Col);
+ {gs,Win,buttonpress,_,[_X,_Y|_]} ->
+ io:format("{color, ~w}\n", [OldCol]),
+ server(Win, Side, [Point1, Point2, Point3], OldCol);
+ {gs,_,click,quit,_} ->
+ exit(die);
+ {gs,Win,destroy,_,_} ->
+ exit(die);
+ _Any ->
+ server(Win, Side, [Point1, Point2, Point3], OldCol)
+ end.
+
+
+col(Point1, Point2, Side) ->
+ D = dist(Point1, Point2),
+ %% All FFFFFF is white
+ %% when Col = 255 when D = Side
+ %% when Col = 0 when D = 0
+ %% Assume Col = A * D + B
+ B = 0,
+ A = (255 - B)/Side,
+ Col = trunc(A*D + B),
+ map(Col).
+
+map(X) ->
+ X band 255.
+
+equi_tri(X1, Y1, L) ->
+ X2 = trunc(X1 + L/2),
+ Y2 = trunc(Y1 - L * math:sqrt(3)),
+ [{X1,Y1},{X2,Y2},{X1+L,Y1}].
+
+%draw_line(Win, {X1, Y1}, {X2, Y2}) ->
+% gs:create(line,Win,[{coords,[{X1,Y1},{X2,Y2}]},{width,2}]).
+
+%draw_lines(Win, L) ->
+% draw1(Win, L),
+% draw_line(Win, hd(L), lists:last(L)).
+
+%draw1(Win, [X,Y|T]) ->
+% draw_line(Win, X, Y),
+% draw1(Win, [Y|T]);
+%draw1(Win, _) ->
+% [].
+
+dist({X1,Y1},{X2,Y2}) ->
+ XX = X1 - X2,
+ YY = Y1 - Y2,
+ math:sqrt(XX*XX+YY*YY).
+
+%% ------------------------------------------------------------
+%% end of color_demo2.erl
diff --git a/lib/gs/examples/distrib_draw.erl b/lib/gs/examples/distrib_draw.erl
new file mode 100644
index 0000000000..ecb1386c25
--- /dev/null
+++ b/lib/gs/examples/distrib_draw.erl
@@ -0,0 +1,116 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%%
+%% 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.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% ------------------------------------------------------------
+%% distrib_draw
+%% Shows one way of making two nodes draw on the same
+%% area.
+%%
+%% ------------------------------------------------------------
+
+%% HOW TO USE:
+%% 1) start up two nodes with same cookie.
+%% They can be on any machines.
+%%
+%% sid.ericsson.se> erl -cookie kaka -name hans
+%%
+%% ozzy.ericsson.se> erl -cookie kaka -name greta
+%%
+%%
+%% 2) Make them aware of each other.
+%%
+%% 3) Start up distrib_draw from either node.
+%%
+
+-module(distrib_draw).
+
+-export([start/2,init/0]).
+
+start(Node1,Node2) ->
+ Pid1=spawn(Node1,distrib_draw,init,[]),
+ Pid2=spawn(Node2,distrib_draw,init,[]),
+ Pid1 ! {connect,red,Pid2},
+ Pid2 ! {connect,green,Pid1}.
+
+init() ->
+ process_flag(trap_exit,true),
+ S=gs:start(),
+ receive
+ {connect,Color,Pid} ->
+ link(Pid),
+ gs:window(win,S,[{buttonpress,true},{buttonrelease,true},
+ {configure,true},{title,Color},{map,true}]),
+ gs:canvas(canvas,win,[{bg,grey},{width,300},{height,200}]),
+ draw0(0,0,Color,Pid)
+ after
+ 3000 -> exit(timeout)
+ end.
+
+%% not drawing state
+draw0(X0,Y0,Color,Pid) ->
+ receive
+ {gs,_,buttonpress,_,[1,X,Y|_]} ->
+ gs:config(win,{motion,true}),
+ draw1(X,Y,Color,Pid);
+ {draw,Coords,Col2} ->
+ gs:line(canvas,[{coords,Coords},{width,2},{fg,Col2}]),
+ draw0(X0,Y0,Color,Pid);
+ {gs,_,configure,_,[300,200|_]} ->
+ draw0(X0,Y0,Color,Pid);
+ {gs,_,configure,_,_} ->
+ gs:config(win,[{width,300},{height,200}]),
+ draw0(X0,Y0,Color,Pid);
+ {gs,_,destroy,_,_} ->
+ exit(normal);
+ {'EXIT',_,_} ->
+ exit(normal);
+ _X -> draw1(X0,Y0,Color,Pid)
+ end.
+
+%% i'm now drawing
+draw1(X0,Y0,Color,Pid) ->
+ receive
+ {gs,_,motion,_,[X,Y|_]} ->
+ Pid ! {draw,[{X0,Y0},{X,Y}],Color},
+ gs:line(canvas,[{coords,[{X0,Y0},{X,Y}]},{width,2},{fg,Color}]),
+ draw1(X,Y,Color,Pid);
+ {draw,Coords,Col2} ->
+ gs:line(canvas,[{coords,Coords},{width,2},{fg,Col2}]),
+ draw1(X0,Y0,Color,Pid);
+ {gs,_,buttonrelease,_,[1,X,Y|_]} ->
+ gs:config(win,{motion,false}),
+ draw0(X,Y,Color,Pid);
+ {gs,_,configure,_,[300,200|_]} ->
+ draw0(X0,Y0,Color,Pid);
+ {gs,_,configure,_,_} ->
+ gs:config(win,[{width,300},{height,200}]),
+ draw0(X0,Y0,Color,Pid);
+ {gs,_,destroy,_,_} ->
+ exit(normal);
+ {'EXIT',_,_} ->
+ exit(normal);
+ _X -> draw1(X0,Y0,Color,Pid)
+ end.
+
+%% ------------------------------------------------------------
+%% end of 'distrib_draw'
diff --git a/lib/gs/examples/entry_demo.erl b/lib/gs/examples/entry_demo.erl
new file mode 100644
index 0000000000..a5ecfbc4d3
--- /dev/null
+++ b/lib/gs/examples/entry_demo.erl
@@ -0,0 +1,63 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%%
+%% 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.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% ------------------------------------------------------------
+%% Entry Demo
+%% ------------------------------------------------------------
+
+-module(entry_demo).
+
+-export([start/0,init/1]).
+
+start() ->
+ spawn(entry_demo,init,[self()]),
+ receive
+ {entry_reply,Reply} -> Reply
+ end.
+
+init(Pid) ->
+ S=gs:start(),
+ Win=gs:window(S,[{title,"Entry Demo"},{width,150},{height,100}]),
+ gs:create(label,Win,[{width,150},{label,{text,"What's your name?"}}]),
+ gs:create(entry,entry,Win,[{x,10},{y,30},{width,130},{keypress,true}]),
+ gs:create(button,ok,Win,[{width,45},{y,60},{x,10},{label,{text,"Ok"}}]),
+ gs:create(button,cancel,Win,[{width,60},{y,60},{x,80},{label,{text,"Cancel"}}]),
+ gs:config(Win,{map,true}),
+ loop(Pid).
+
+loop(Pid) ->
+ receive
+ {gs,entry,keypress,_,['Return'|_]} ->
+ Text=gs:read(entry,text),
+ Pid ! {entry_reply,{name,Text}};
+ {gs,entry,keypress,_,_} ->
+ loop(Pid);
+ {gs,ok,click,_,_} ->
+ Text=gs:read(entry,text),
+ Pid ! {entry_reply,{name,Text}};
+ {gs,cancel,click,_,_} ->
+ Pid ! {entry_reply,cancel};
+ X ->
+ io:format("Got X=~w~n",[X]),
+ loop(Pid)
+ end.
+
+%% ----------------------------------------
+%% done
diff --git a/lib/gs/examples/event_test.erl b/lib/gs/examples/event_test.erl
new file mode 100644
index 0000000000..f6fcc9b4b9
--- /dev/null
+++ b/lib/gs/examples/event_test.erl
@@ -0,0 +1,48 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%%
+%% 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.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Demo for testing some events
+
+-module(event_test).
+
+-export([start/0,init/0]).
+
+
+
+start() ->
+ spawn(event_test,init,[]).
+
+init() ->
+ S=gs:start(),
+ W=gs:window(S,[{map,true},{keypress,true},{buttonpress,true}]),
+ gs:button(W,[{label,{text,"Press Me"}},{enter,true},{leave,true}]),
+ event_loop().
+
+
+event_loop() ->
+ receive
+ X ->
+ io:format("Got event: ~p~n",[X]),
+ event_loop()
+ end.
+
+
+
+
diff --git a/lib/gs/examples/file_dialog.erl b/lib/gs/examples/file_dialog.erl
new file mode 100644
index 0000000000..ff20321374
--- /dev/null
+++ b/lib/gs/examples/file_dialog.erl
@@ -0,0 +1,255 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%%
+%% 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.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% ------------------------------------------------------------
+%% File Selection Dialog
+%% ------------------------------------------------------------
+
+-module(file_dialog).
+
+-export([start/0,start/1,start/2,fs_init/3]).
+
+-include_lib("kernel/include/file.hrl").
+
+
+%% ----- File Selection ----
+start() ->
+ {ok,Dir}=file:get_cwd(),
+ start(Dir,[]).
+
+start(Dir) ->
+ start(Dir,[]).
+
+start(Dir,File) ->
+ Dir0 = case lists:last(Dir) of
+ $/ -> Dir;
+ _ -> lists:append(Dir,"/")
+ end,
+ Pid=spawn(file_dialog,fs_init,[Dir0,File,self()]),
+ receive
+ {file_dialog,Pid,Result} -> Result
+ end.
+
+
+%% ------------------------------------------------------------
+fs_init(Dir,File,Owner) ->
+ S=gs:start(),
+ gs:create(window,win,S,[{width,250},{height,265},{title,"File Dialog"},
+ {configure,true}]),
+ gs:create(label,label,win,[{y,0},{width,250},{label, {text,Dir}}]),
+ gs:label(win,[{width,50},{y,30},{x,5},{label, {text,"File:"}}]),
+ gs:create(entry,entry,win,[{y,30},{width,190},{x,55},
+ {keypress,true},{focus,true}]),
+ gs:create(listbox,lb,win,[{x,5},{y,60},{width,160},{height,199},
+ {vscroll,right},{click,true},{doubleclick,true}]),
+ gs:create(button,ok,win,[{label, {text,"OK"}},{width,40},{x,185},{y,170}]),
+ gs:create(button,cancel,win,[{label, {text,"Cancel"}},{x,175},{y,220},{width,65}]),
+ Items=refresh(Dir),
+ %% --- select File if it's given ---
+ case index_member(File,Items) of
+ {ok,Index} ->
+ gs:config(lb,{selection,clear}),
+ gs:config(lb,{selection,Index});
+ _ -> true
+ end,
+ gs:config(win,{map,true}),
+ fs_loop(Dir,Owner).
+
+fs_loop(Dir,Owner) ->
+ receive
+ {gs,ok,click,_,_} ->
+ entered_name(Dir,Owner);
+ {gs,cancel,click,_,_} ->
+ Owner ! {file_dialog,self(),cancel};
+ {gs,entry,keypress,_,['Return'|_]} ->
+ entered_name(Dir,Owner);
+ {gs,entry,keypress,_,[_Keysym|_]} ->
+ fs_loop(Dir,Owner);
+ {gs,lb,click,_,_} ->
+ clicked(Dir,Owner);
+ {gs,lb,doubleclick,_,_} ->
+ double_clicked(Dir,Owner);
+ {gs,win,configure,_,[250,265|_]} -> % already got that size
+ fs_loop(Dir,Owner);
+ {gs,win,configure,_,_} ->
+ gs:config(win,[{geometry,{250,265}}]),
+ fs_loop(Dir,Owner);
+ stop ->
+ exit(normal);
+ {gs,_,destroy,_,_} ->
+ Owner ! {file_dialog,self(),cancel};
+ X ->
+ io:format("file_dialog: got other: ~w.~n",[X]),
+ fs_loop(Dir,Owner)
+ end.
+
+
+
+refresh(Dir) ->
+ gs:config(lb,clear),
+ gs:config(label,{label, {text,Dir}}),
+ gs:config(entry,{text,""}),
+ Items=["../"|get_files(Dir)],
+ gs:config(lb,[{items,Items}]),
+ Items.
+
+
+entered_name(Dir,Owner) ->
+ File=gs:read(entry,text),
+ case check_file(Dir,File) of
+ {file,Dir2,File2} ->
+ Owner ! {file_dialog,self(),{ok,Dir2,File2}};
+ {dir,Dir2} ->
+ refresh(Dir2),
+ fs_loop(Dir2,Owner);
+ {error,no_file} ->
+ double_clicked(Dir,Owner);
+ _ ->
+ fs_loop(Dir,Owner)
+ end.
+
+
+clicked(Dir,Owner) ->
+ [Idx|_]=gs:read(lb,selection),
+ File=gs:read(lb,{get,Idx}),
+ case lists:last(File) of
+ $/ -> %it's a dir
+ true;
+ _ -> % it's a file
+ gs:config(entry,{text,File})
+ end,
+ fs_loop(Dir,Owner).
+
+
+double_clicked(Dir,Owner) ->
+ case gs:read(lb,selection) of
+ [0] -> % up one dir
+ NewDir=up_one_dir(Dir),
+ refresh(NewDir),
+ fs_loop(NewDir,Owner);
+ [] ->
+ fs_loop(Dir,Owner);
+ [Idx] ->
+ File=gs:read(lb,{get,Idx}),
+ case lists:last(File) of
+ $/ -> % down a dir
+ NewDir=lists:append(Dir,File),
+ refresh(NewDir),
+ fs_loop(NewDir,Owner);
+ _ -> % done
+ Owner!{file_dialog,self(),{ok,Dir,File}}
+ end
+ end.
+
+
+%% checks if a file exists
+%% returns {file,Dir,File}
+%% {dir,Dir}
+%% or {error,What}
+check_file(Dir,File) ->
+ case catch lists:last(File) of
+ $/ -> % File is a Dir
+ NewDir = case File of
+ [$/|_] -> %absolute path
+ File;
+ _ -> %relative path
+ lists:append(Dir,File)
+ end,
+ case file:list_dir(NewDir) of
+ {ok,_} -> {dir,NewDir};
+ _ -> {error,bad_dir}
+ end;
+ {'EXIT',_Why} -> {error,no_file};
+ _ ->
+ Words=string:tokens(File,[$/,$\\]),
+ NewFile=lists:last(Words),
+ NewDir = case File of
+ [$/|_] -> %absolute path
+ up_one_dir(File);
+ _ -> %relative path
+ case up_one_dir(File) of
+ [$/] -> Dir;
+ [$/|SubDir] -> lists:flatten([Dir,SubDir,$/])
+ end
+ end,
+ case file:read_file_info(lists:append(NewDir,NewFile)) of
+ {ok,_} ->
+ {file,NewDir,NewFile};
+ _ ->
+ {error,bad_file}
+ end
+ end.
+
+
+get_files(Dir) ->
+ {ok,Files} = file:list_dir(Dir),
+ add_slash(Dir,lists:sort(Files)).
+
+add_slash(_,[]) -> [];
+add_slash(Dir,[H|T]) ->
+ case file:read_file_info(lists:append(Dir,[$/|H])) of
+ {ok,FI} when FI#file_info.type==directory ->
+ [lists:append(H,"/")|add_slash(Dir,T)];
+ _ ->
+ [H|add_slash(Dir,T)]
+ end.
+
+
+%filter([H|T]) ->
+% case lists:last(H) of
+% $/ -> [H|filter(T)];
+% _ ->
+% Len =length(H),
+% if Len>4 ->
+% case lists:nthtail(Len-4,H) of
+% ".erl" -> [H|filter(T)];
+% _ -> filter(T)
+% end;
+% true -> filter(T)
+% end
+% end;
+%filter([]) ->
+% [].
+
+
+%% like member but also returns index
+index_member(Item,List) ->
+ i_m(0,Item,List).
+
+i_m(N,Item,[Item|_List]) ->
+ {ok,N};
+i_m(N,Item,[_|List]) ->
+ i_m(N+1,Item,List);
+i_m(_N,_Item,[]) ->
+ false.
+
+up_one_dir(Dir) ->
+ L =string:tokens(Dir,[$/,$\\]),
+ lists:flatten(rem_last(L)).
+
+rem_last([_Last]) ->
+ [$/];
+rem_last([Head|Tail]) ->
+ [$/,Head|rem_last(Tail)];
+rem_last([]) ->
+ [$/].
+
+%% ----------------------------------------
+%% done
diff --git a/lib/gs/examples/focus_demo.erl b/lib/gs/examples/focus_demo.erl
new file mode 100644
index 0000000000..b9d86866e6
--- /dev/null
+++ b/lib/gs/examples/focus_demo.erl
@@ -0,0 +1,97 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%%
+%% 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.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% ------------------------------------------------------------
+%% Focus Demo
+%% ------------------------------------------------------------
+
+-module(focus_demo).
+
+-export([start/0,init/0]).
+
+
+%% ----- File Selection ----
+start() ->
+ spawn(focus_demo,init,[]).
+
+
+init() ->
+ S=gs:start(),
+ Font = case gs:read(S,{choose_font,{screen,12}}) of
+ {screen,_,12} = Screen ->
+ Screen;
+ _ ->
+ gs:read(S,{choose_font,{courier,12}})
+ end,
+ Win=gs:window(S,[{title,"Focus Demo"},{width,200},{height,150}]),
+ gs:create(entry,e1,Win,[{y,0},{focus,true}]),
+ gs:create(entry,e2,Win,[{y,30},{focus,true}]),
+ gs:create(entry,e3,Win,[{y,60},{focus,true}]),
+ gs:create(entry,e4,Win,[{y,90},{focus,true}]),
+ gs:create(button,b1,Win,[{x,100},{width,30},
+ {label,{text,"e1"}},{font,Font}]),
+ gs:create(button,b2,Win,[{y,30},{x,100},{width,30},
+ {label,{text,"e2"}},{font,Font}]),
+ gs:create(button,b3,Win,[{y,60},{x,100},{width,30},
+ {label,{text,"e3"}},{font,Font}]),
+ gs:create(button,b4,Win,[{y,90},{x,100},{width,30},
+ {label,{text,"e4"}},{font,Font}]),
+ gs:create(button,clear,Win,[{y,120},{x,35},{width,50},
+ {label,{text,"Clear"}},{font,Font}]),
+ gs:create(button,ask,Win,[{y,120},{x,85},{width,30},
+ {label,{text,"?"}},{font,Font}]),
+ gs:create(button,quit,Win,[{y,120},{x,115},{width,50},
+ {label,{text,"Quit"}},{font,Font}]),
+ gs:config(Win,{map,true}),
+ loop().
+
+loop() ->
+ receive
+ {gs,quit,_,_,_} -> exit(normal);
+ {gs,ask,_,_,_} ->
+ R1=gs:read(e1,setfocus),R2=gs:read(e2,setfocus),
+ R3=gs:read(e3,setfocus),R4=gs:read(e4,setfocus),
+ R= if R1==true -> e1;
+ R2==true -> e2;
+ R3==true -> e3;
+ R4==true -> e4;
+ true -> nobody
+ end,
+ io:format("Focus status: ~w has focus.~n",[R]);
+ {gs,clear,_,_,_} ->
+ gs:config(clear,{setfocus,true}),
+ io:format("Focus is cleared.~n",[]);
+ {gs,b1,_,_,_} -> gs:config(e1,{setfocus,true});
+ {gs,b2,_,_,_} -> gs:config(e2,{setfocus,true});
+ {gs,b3,_,_,_} -> gs:config(e3,{setfocus,true});
+ {gs,b4,_,_,_} -> gs:config(e4,{setfocus,true});
+ {gs,Id,focus,_,[0|_]} ->
+ io:format("~w lost focus.~n",[Id]);
+ {gs,Id,focus,_,[1|_]} ->
+ io:format("~w gained focus.~n",[Id]);
+ {gs,_,destroy,_,_} ->
+ exit(normal);
+ X ->
+ io:format("Got X=~w~n",[X])
+ end,
+ loop().
+
+%% ----------------------------------------
+%% done
diff --git a/lib/gs/examples/frac.erl b/lib/gs/examples/frac.erl
new file mode 100644
index 0000000000..139a4be310
--- /dev/null
+++ b/lib/gs/examples/frac.erl
@@ -0,0 +1,154 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%%
+%% 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.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% Purpose : Fractal trees
+
+-module(frac).
+
+-export([start/0, go/0, test/0, grow/2, expand/3, subst/2]).
+
+%% 0L - grammer -- context insensitive lindenmayer grammer
+
+start() ->
+ spawn(frac,go,[]).
+
+go() ->
+ draw(),
+ receive
+ _X -> true
+ end.
+
+draw() ->
+ S=gs:start(),
+ Width = 800,
+ Ht = 520,
+ Title="Context Insensitive Lindenmayer Grammer (L0) Trees",
+ Win=gs:create(window,S,[{title,Title},{width,Width},{height,Ht}]),
+ Canvas=gs:create(canvas,Win,[{width,Width},{height,Ht},{bg,{237,224,189}}]),
+ gs:config(Win,[{iconname,"Plants"},{map,true}]),
+ draw(Canvas, 1, Width, Ht),
+ draw(Canvas, 2, Width, Ht),
+ draw(Canvas, 3, Width, Ht),
+ draw(Canvas, 4, Width, Ht).
+
+draw(Graph, Index, Width, Ht) ->
+ draw_frac(Graph, Index, Width, Ht).
+
+test() ->
+ grow(3,1).
+
+grow(NGens, RuleNumber) ->
+ lists:flatten(expand(NGens, RuleNumber, [a])).
+
+rule(1,a) -> [b,'[',a,']',b,'(',a,')',a];
+rule(1,b) -> [b,b];
+
+rule(2,a) -> [b,'[',a,'[',b,a,']',']'];
+rule(2,b) -> [b,'(','(',b,')',a,')',c];
+rule(2,c) -> [c,d];
+
+rule(3,a) -> [d,'[',d,b,e,']','(',d,c,e,')'];
+rule(3,b) -> [d,'[',d,a,f,']','(',d,c,f,')',f];
+rule(3,c) -> [d,'[',d,b,g,']','(',d,a,g,')',g];
+
+rule(4,a) -> [c,'(',b,a,'(',b,')',')',c,'[',b,a,'[',b,']',']'];
+rule(4,b) -> [c,'(',b,e,')',c,'[',b,f,']'];
+rule(4,c) -> [g,c,c];
+
+rule(_,X) -> X.
+
+
+step(a) -> 1.0;
+step(b) -> 0.8;
+step(c) -> 0.6;
+step(d) -> 0.7;
+step(e) -> 0.6;
+step(f) -> 0.65;
+step(g) -> 0.75;
+step(_) -> 1.0.
+
+start_coords(1) -> {0.8,0.8};
+start_coords(2) -> {0.6,0.8};
+start_coords(3) -> {0.4,0.8};
+start_coords(4) -> {0.2,0.8};
+start_coords(_) -> {0.5, 0.5}.
+
+gens(1) -> 5;
+gens(_) -> 5.
+
+scale(1) -> 5;
+scale(2) -> 40;
+scale(3) -> 40;
+scale(4) -> 4;
+scale(_) -> 5.
+
+expand(0,_,X) ->
+ X;
+expand(N,Index,X) ->
+ expand(N - 1, Index, lists:flatten(subst(X, Index))).
+
+
+subst([],_) -> [];
+subst([H|T],Index) ->
+ [rule(Index,H)|subst(T,Index)].
+
+
+draw_frac(Id, Index, Width, Ht) ->
+ X0 = 100,
+ Y0 = 100,
+ {XScale,YScale} = start_coords(Index),
+ Xstart = trunc(X0 + Width*XScale),
+ Ystart = trunc(Y0 + Ht*YScale),
+ Angle = 270.0 * 3.14159 / 180.0,
+ Scale = scale(Index),
+ N = gens(Index),
+ Tree = grow(N,Index),
+ drawit(Tree, Id, Xstart, Ystart, Angle, Scale, []).
+
+% drawit(Tree,S0,S).
+
+drawit([],_,_,_,_,_,_) ->
+ true;
+drawit(['('|T],Id,X0,Y0,Ang,Scale,Stack) ->
+ Ang1 = Ang + (20.0 * 3.14159 / 180.0),
+ Scale1 = Scale * 0.8,
+ drawit(T,Id,X0,Y0,Ang1,Scale1,[{X0,Y0,Ang,Scale}|Stack]);
+drawit(['['|T],Id,X0,Y0,Ang,Scale,Stack) ->
+ Ang1 = Ang - (40.0 * 3.14159 / 180.0),
+ Scale1 = Scale * 0.8,
+ drawit(T,Id,X0,Y0,Ang1,Scale1,[{X0,Y0,Ang,Scale}|Stack]);
+drawit([')'|T],Id,_,_,_,_,[{X1,Y1,Ang1,Scale1}|Stack]) ->
+ drawit(T,Id,X1,Y1,Ang1,Scale1,Stack);
+drawit([']'|T],Id,_,_,_,_,[{X1,Y1,Ang1,Scale1}|Stack]) ->
+ drawit(T,Id,X1,Y1,Ang1,Scale1,Stack);
+drawit([Symbol|T],Id,X0,Y0,Ang,Scale,Stack) ->
+ Size = step(Symbol),
+ L = Size * Scale,
+ {X1, Y1} = plotit(Id,X0,Y0,L,Ang),
+ drawit(T,Id,X1,Y1,Ang,Scale,Stack).
+
+plotit(Id,X0,Y0,L,A) ->
+ CosA = math:cos(A),
+ SinA = math:sin(A),
+ X = trunc(X0 + L*CosA),
+ Y = trunc(Y0 + L*SinA),
+ gs:create(line,Id,[{coords,[{X0,Y0},{X,Y}]}]),
+ {X,Y}.
+
diff --git a/lib/gs/examples/line_demo.erl b/lib/gs/examples/line_demo.erl
new file mode 100644
index 0000000000..c8a6a69e2e
--- /dev/null
+++ b/lib/gs/examples/line_demo.erl
@@ -0,0 +1,75 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%%
+%% 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.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% ------------------------------------------------------------
+%% A simple demo showing a line
+%% bouncing within a window.
+%% ------------------------------------------------------------
+
+-module(line_demo).
+
+-export([start/0,init/0,line/3]).
+
+start() ->
+ spawn(line_demo,init,[]).
+
+init() ->
+ I= gs:start(),
+ W= gs:window(I,[{title,"Line Demo"},{width,300},{height,300},{map,true}]),
+ C= gs:canvas(W,[{width,300},{height,300},{bg,blue}]),
+ gs:button(W,[{label,{text,"Quit"}},{width,40},{bg,yellow}]),
+ Line2 = gs:line(C,[{coords,[{0,0},{50,50}]},{fg,white},{width,3}]),
+ line(Line2,{100,100,9.5,5},{0,0,-6,-8.4}).
+
+
+
+line(Line,{X1,Y1,DX1,DY1},{X2,Y2,DX2,DY2}) ->
+ {NX1,NDX1} = cc(X1,DX1),
+ {NY1,NDY1} = cc(Y1,DY1),
+ {NX2,NDX2} = cc(X2,DX2),
+ {NY2,NDY2} = cc(Y2,DY2),
+ gs:config(Line,{coords,[{NX1,NY1},{NX2,NY2}]}),
+ receive
+ {gs,_,click,_,_} -> exit(normal);
+ {gs,_,destroy,_,_} -> exit(normal)
+ after 50 ->
+ true
+ end,
+ line(Line,{NX1,NY1,NDX1,NDY1},{NX2,NY2,NDX2,NDY2}).
+
+cc(X,DX) ->
+ if
+ DX>0 ->
+ if
+ X<300 ->
+ {X+DX,DX};
+ x>=300 ->
+ {X-DX,-DX}
+ end;
+ DX<0 ->
+ if
+ X>0 ->
+ {X+DX,DX};
+ X=<0 ->
+ {X-DX,-DX}
+ end
+ end.
+
+%% ------------------------------------------------------------
diff --git a/lib/gs/examples/man.erl b/lib/gs/examples/man.erl
new file mode 100644
index 0000000000..a0ffd3364e
--- /dev/null
+++ b/lib/gs/examples/man.erl
@@ -0,0 +1,192 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%%
+%% 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.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% ------------------------------------------------------------
+%% Simple Manual Page Browser
+%% ------------------------------------------------------------
+
+-module(man).
+
+-export([start/0,init/0]).
+-export([man_list/0]).
+-export([browser/1,browser_init/2]).
+
+
+start() ->
+ case whereis(man) of
+ undefined ->
+ register(man,Pid=spawn(man,init,[])),
+ Pid;
+ Pid ->
+ Pid
+ end.
+
+
+%% ---- Man Directories -----
+dirManual() ->
+ filename:join([code:root_dir(), "man", "cat3"]).
+
+
+%% ----- init -----
+init() ->
+ S=gs:start(),
+ Width=520,Height=520,
+ gs:create(window,win,S,[{title,"Manual Browser"},
+ {width,Width},{height,Height}]),
+ gs:create(button,quit,win,[{width,60},{label,{text,"Quit"}}]),
+ gs:create(button,select,win,[{x,60},{label,{text,"Select Page"}}]),
+ gs:create(editor,editor,win,[{y,30},{width,Width},{height,Height-30},
+ {hscroll,false},{vscroll,left}]),
+ gs:config(win,[{map,true},{configure,true}]),
+ man_loop(Width,Height).
+
+man_loop(Width0,Height0) ->
+ receive
+ {gs,_Win,configure,_,[Width0,Height0|_]} -> %% already got that size!
+ man_loop(Width0,Height0);
+ {gs,_Win,configure,_,[Width,Height|_]} ->
+ %%io:format("man: width=~w, height=~w ~n",[Width,Height]),
+ gs:config(editor,[{width,Width},{height,Height-30}]),
+ man_loop(Width,Height);
+ {gs,quit,click,_,_} ->
+ %%io:format("man: exiting.~n",[]),
+ exit(normal);
+ {gs,select,click,_,_} ->
+ case browser(man_list()) of
+ cancel -> true;
+ {ok,Page} -> load_page(Page);
+ O -> io:format("man: bad browser result: ~w~n",[O])
+ end,
+ man_loop(Width0,Height0);
+ {gs,_,destroy,_,_} ->
+ exit(normal);
+ X ->
+ io:format("man: got other: ~w~n",[X]),
+ man_loop(Width0,Height0)
+ end.
+
+
+%% ----- man_list ----
+%%
+man_list() ->
+ {ok,FirstList} = file:list_dir(dirManual()),
+ SecondList =
+ mapfilter(fun(File) ->
+ case filename:extension(File) of
+ ".3" ->
+ {true, filename:basename(File, ".3")};
+ _ -> false
+ end
+ end,
+ FirstList),
+ lists:sort(SecondList).
+
+mapfilter(Fun, [H|T]) ->
+ case Fun(H) of
+ {true, Val} ->
+ [Val|mapfilter(Fun, T)];
+ false ->
+ mapfilter(Fun, T)
+ end;
+mapfilter(_Fun, []) ->
+ [].
+
+
+%% ------------------------------------------------------------
+%% Load in the Page
+
+load_page(Page) ->
+ %%io:format("man: load page start ~p.~n",[Page]),
+ Filename = filename:join([dirManual(),Page++".3"]),
+ {ok,Bin}=file:read_file(Filename),
+ _Txt=binary_to_list(Bin),
+ gs:config(editor,{enable,true}),
+ gs:config(editor,{load,Filename}),
+ gs:config(editor,{enable,false}),
+ %%io:format("man: load page done.~n",[]),
+ true.
+
+
+%% ------------------------------------------------------------
+%% Simple Browser
+%% ------------------------------------------------------------
+
+browser(Items) ->
+ Browser=spawn_link(man,browser_init,[self(),Items]),
+ await_reply(Browser).
+
+await_reply(Browser) ->
+ receive
+ {browser,Result} ->
+ Result;
+ {gs,_,destroy,_,_} -> exit(normal);
+ {gs,quit,click,_,_} -> exit(normal);
+ {gs,select,click,_,_} ->
+ Browser ! wake_up,
+ await_reply(Browser)
+ end.
+
+browser_init(Pid,Items) ->
+ process_flag(trap_exit,true),
+ S=gs:start(),
+ Win=gs:window(win,S,[{width,250},{height,270},{title,"Browser"}]),
+ _Lbl=gs:label(Win,[{label,{text,"Select a Manual Page"}},{width,250}]),
+ gs:label(Win,[{width,40},{y,35},{label,{text,"Page:"}}]),
+ Entry=gs:entry(Win,[{y,35},{width,205},{x,40},
+ {keypress,true},{focus,true}]),
+ Lb=gs:listbox(Win,[{x,5},{y,65},{width,160},{height,195},
+ {vscroll,right},{click,true},{doubleclick,true}]),
+ Ok=gs:button(Win,[{label,{text,"OK"}},{width,40},{x,185},{y,175}]),
+ Cancel=gs:button(Win,[{label,{text,"Cancel"}},{x,175},{y,225},{width,65}]),
+ gs:config(Lb,[{items,Items}]),
+ gs:config(Win,{map,true}),
+ browser_loop(Pid,Ok,Cancel,Entry,Lb).
+
+browser_loop(Pid,Ok,Cancel,Entry,Lb) ->
+ receive
+ {gs,Ok,click,_,_} ->
+ Txt=gs:read(Entry,text),
+ Pid ! {browser,{ok,Txt}};
+ {gs,Cancel,click,_,_} ->
+ Pid ! {browser,cancel};
+ {gs,Entry,keypress,_,['Return'|_]} ->
+ Txt=gs:read(Entry,text),
+ Pid ! {browser,{ok,Txt}};
+ {gs,Entry,keypress,_,_} ->
+ browser_loop(Pid,Ok,Cancel,Entry,Lb);
+ {gs,Lb,click,_,[_Idx, Txt| _Rest]} ->
+ gs:config(Entry,{text,Txt}),
+ browser_loop(Pid,Ok,Cancel,Entry,Lb);
+ {gs,Lb,doubleclick,_,[_Idx, Txt| _Rest]} ->
+ Pid ! {browser,{ok,Txt}};
+ {gs,_,destroy,_,_} ->
+ Pid ! {browser,cancel};
+ wake_up ->
+ gs:config(win,[{iconify,false},raise]),
+ browser_loop(Pid,Ok,Cancel,Entry,Lb);
+ {'EXIT',_Man,Why} ->
+ exit(Why);
+ X ->
+ io:format("man: browser got other: ~w.~n",[X]),
+ browser_loop(Pid,Ok,Cancel,Entry,Lb)
+ end.
+
+%% ------------------------------------------------------------
+%% end of man.erl
diff --git a/lib/gs/examples/menu_demo.erl b/lib/gs/examples/menu_demo.erl
new file mode 100644
index 0000000000..c95fc33152
--- /dev/null
+++ b/lib/gs/examples/menu_demo.erl
@@ -0,0 +1,74 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%%
+%% 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.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+-module(menu_demo).
+
+-compile(export_all).
+
+start() -> spawn(menu_demo, init, []).
+
+init() ->
+ I=gs:start(),
+ Win=gs:window(I, [{title,"menu"},{width,200},{height,100}, {map, true}]),
+ Bar = gs:create(menubar, Win, []),
+ Fmb = gs:create(menubutton, Bar, [{label, {text, "File"}}]),
+ Emb = gs:create(menubutton, Bar, [{label, {text, "Edit"}}]),
+ Hmb = gs:create(menubutton, Bar, [{label, {text, "Help"}}, {side, right}]),
+ Fmnu = gs:create(menu, Fmb, []),
+ Emnu = gs:create(menu, Emb, []),
+ Hmnu = gs:create(menu, Hmb, []),
+ gs:create(menuitem, load, Fmnu, [{label,{text, "Load"}}]),
+ gs:create(menuitem, save, Fmnu, [{label,{text, "Save"}}]),
+ Exit = gs:create(menuitem, Fmnu, [{label,{text, "Exit"}}]),
+ Color=gs:create(menuitem,Emnu,[{label,{text,"Color"}},{itemtype,cascade}]),
+ Cmnu = gs:create(menu, Color, [{disabledfg,gray}]),
+ gs:create(menuitem, Cmnu, [{label, {text,"Red"}}, {data, {new_color, red}},
+ {fg,red}, {itemtype,radio},{group,gr1}]),
+ gs:create(menuitem, Cmnu, [{label, {text,"Blue"}},{data, {new_color, blue}},
+ {fg,blue}, {itemtype,radio},{group,gr1}]),
+ gs:create(menuitem,Cmnu,[{label, {text,"Black"}},{data, {new_color, black}},
+ {fg,black}, {itemtype,radio},{group,gr1}]),
+ Y = gs:create(menuitem, Hmnu, [{label, {text,"You"}}, {itemtype, check}]),
+ M = gs:create(menuitem,me,Hmnu,[{label,{text,"Me"}},{itemtype,check}]),
+ gs:create(menuitem, Hmnu, [{label, {text, "Other"}}, {itemtype, check},
+ {enable,false},{click,false}]),
+ gs:create(menuitem,doit,Hmnu,[{label,{text,"Doit!"}},{data,{doit,Y,M}}]),
+ loop(Exit, Win).
+
+loop(Exit, Win) ->
+ receive
+ {gs, save, click, _Data, [_Txt, _Index | _Rest]} ->
+ io:format("Save~n");
+ {gs, load, click, _Data, [_Txt, _Index | _Rest]} ->
+ io:format("Load~n");
+ {gs, Exit, click, _Data, [_Txt, _Index | _Rest]} ->
+ io:format("Exit~n"),
+ exit(normal);
+ {gs, _MnuItem, click, {new_color, Color}, Args} ->
+ io:format("Change color to ~w. Args:~p~n", [Color, Args]),
+ gs:config(Win, [{bg, Color}]);
+ {gs, doit, click, {doit, YouId, MeId}, Args} ->
+ HelpMe = gs:read(MeId, select),
+ HelpYou = gs:read(YouId, select),
+ io:format("Doit. HelpMe:~w, HelpYou:~w, Args:~p~n",
+ [HelpMe, HelpYou, Args]);
+ Other -> io:format("Other:~p~n",[Other])
+ end,
+ loop(Exit, Win).
diff --git a/lib/gs/examples/rubber.erl b/lib/gs/examples/rubber.erl
new file mode 100644
index 0000000000..ba263f07ac
--- /dev/null
+++ b/lib/gs/examples/rubber.erl
@@ -0,0 +1,104 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1996-2009. All Rights Reserved.
+%%
+%% 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.
+%%
+%% %CopyrightEnd%
+%%
+
+%%
+%% ------------------------------------------------------------
+%% A rubberbanding example in Erlang
+%% ------------------------------------------------------------
+
+-module(rubber).
+
+-export([start/0, init/0]).
+
+start() ->
+ spawn(rubber,init,[]).
+
+init() ->
+ I=gs:start(),
+ Win = gs:window(I,[{title,"Rubberbanding in Erlang"},
+ {width,300},{height,200}]),
+ C= gs:canvas(Win,[{width,300},{height,200},{bg,green}]),
+ gs:radiobutton(Win,[{width,100},{label,{text,"Oval"}},{align,w},
+ {data,oval},{y,0},{select,true}]),
+ gs:radiobutton(Win,[{width,100},{label,{text,"Rectangle"}},{align,w},
+ {data,rectangle},{y,30}]),
+ gs:radiobutton(Win,[{width,100},{label,{text,"Line"}},{align,w},
+ {data,line},{y,60}]),
+ gs:button(Win,[{label,{text,"Quit"}},{data,quit},{y,90}]),
+ gs:config(Win,[{motion,true},{buttonpress,true},{buttonrelease,true}]),
+ gs:config(Win,{map,true}),
+ loop(C,nil,oval,0,0).
+
+
+loop(Win,Obj,Objtype,X1,Y1) ->
+ receive
+ {gs,_,motion,_,[X2,Y2]} ->
+ flush(Win,Obj,Objtype,X1,Y1,X2,Y2);
+ {gs,_,buttonpress,_,[1,X2,Y2]} ->
+ down(Win,Obj,Objtype,X2,Y2);
+ {gs,_,buttonrelease,_,[1,X2,Y2]} ->
+ up(Win,Obj,Objtype,X1,Y1,X2,Y2);
+ {gs,_,click,quit,_} ->
+ exit(normal);
+ {gs,_,click,Newtype,_} ->
+ loop(Win,Obj,Newtype,X1,Y1);
+ {gs,_,destroy,_,_} ->
+ exit(normal);
+ Other ->
+ io:format("Other:~w~n",[Other]),
+ loop(Win,Obj,Objtype,X1,Y1)
+ end.
+
+
+down(Win,nil,oval,X1,Y1) ->
+ Obj = gs:create(oval,Win,[{coords,[{X1,Y1},{X1+1,Y1+1}]},{fill,red}]),
+ loop(Win,Obj,oval,X1,Y1);
+down(Win,nil,line,X1,Y1) ->
+ Obj = gs:create(line,Win,[{coords,[{X1,Y1},{X1+1,Y1+1}]},{width,3},{fg,black}]),
+ loop(Win,Obj,line,X1,Y1);
+down(Win,nil,Objtype,X1,Y1) ->
+ Obj = gs:create(Objtype,Win,[{coords,[{X1,Y1},{X1+1,Y1+1}]},{bw,2},{fg,blue}]),
+ loop(Win,Obj,Objtype,X1,Y1);
+down(Win,Obj,Objtype,X1,Y1) ->
+ gs:destroy(Obj),
+ down(Win,nil,Objtype,X1,Y1).
+
+up(Win,nil,Objtype,_X1,_Y1,X2,Y2) ->
+ loop(Win,nil,Objtype,X2,Y2);
+up(Win,Obj,Objtype,X1,Y1,X2,Y2) ->
+ gs:config(Obj,{coords,[{X1,Y1},{X2,Y2}]}),
+ loop(Win,nil,Objtype,X2,Y2).
+
+
+move(Win,nil,Objtype,X1,Y1,_X2,_Y2) ->
+ loop(Win,nil,Objtype,X1,Y1);
+move(Win,Obj,Objtype,X1,Y1,X2,Y2) ->
+ gs:config(Obj,{coords,[{X1,Y1},{X2,Y2}]}),
+ loop(Win,Obj,Objtype,X1,Y1).
+
+
+flush(Win,Obj,Objtype,X1,Y1,X2,Y2) ->
+ receive
+ {gs,_,motion,_,[XX2,YY2]} ->
+ flush(Win,Obj,Objtype,X1,Y1,XX2,YY2)
+ after
+ 0 -> move(Win,Obj,Objtype,X1,Y1,X2,Y2)
+ end.
+
+%% ------------------------------------------------------------