aboutsummaryrefslogtreecommitdiffstats
path: root/lib/wx/examples/demo
diff options
context:
space:
mode:
Diffstat (limited to 'lib/wx/examples/demo')
-rwxr-xr-xlib/wx/examples/demo/Makefile96
-rw-r--r--lib/wx/examples/demo/demo.erl363
-rw-r--r--lib/wx/examples/demo/demo_html_tagger.erl534
-rw-r--r--lib/wx/examples/demo/erlang.pngbin0 -> 16065 bytes
-rw-r--r--lib/wx/examples/demo/ex_aui.erl189
-rw-r--r--lib/wx/examples/demo/ex_button.erl230
-rw-r--r--lib/wx/examples/demo/ex_canvas.erl177
-rw-r--r--lib/wx/examples/demo/ex_canvas_paint.erl248
-rw-r--r--lib/wx/examples/demo/ex_choices.erl159
-rw-r--r--lib/wx/examples/demo/ex_cursor.erl180
-rw-r--r--lib/wx/examples/demo/ex_dialogs.erl171
-rw-r--r--lib/wx/examples/demo/ex_frame_utils.erl193
-rw-r--r--lib/wx/examples/demo/ex_gauge.erl208
-rw-r--r--lib/wx/examples/demo/ex_gl.erl409
-rw-r--r--lib/wx/examples/demo/ex_graphicsContext.erl146
-rw-r--r--lib/wx/examples/demo/ex_grid.erl142
-rw-r--r--lib/wx/examples/demo/ex_htmlWindow.erl93
-rw-r--r--lib/wx/examples/demo/ex_htmlWindow.html59
-rw-r--r--lib/wx/examples/demo/ex_listCtrl.erl148
-rw-r--r--lib/wx/examples/demo/ex_notebook.erl147
-rw-r--r--lib/wx/examples/demo/ex_pickers.erl136
-rw-r--r--lib/wx/examples/demo/ex_popupMenu.erl150
-rw-r--r--lib/wx/examples/demo/ex_radioBox.erl163
-rw-r--r--lib/wx/examples/demo/ex_sashWindow.erl128
-rw-r--r--lib/wx/examples/demo/ex_sizers.erl436
-rw-r--r--lib/wx/examples/demo/ex_slider.erl113
-rw-r--r--lib/wx/examples/demo/ex_splitterWindow.erl102
-rw-r--r--lib/wx/examples/demo/ex_static.erl117
-rw-r--r--lib/wx/examples/demo/ex_textCtrl.erl104
-rw-r--r--lib/wx/examples/demo/ex_treeCtrl.erl121
-rw-r--r--lib/wx/examples/demo/image.jpgbin0 -> 2333 bytes
31 files changed, 5462 insertions, 0 deletions
diff --git a/lib/wx/examples/demo/Makefile b/lib/wx/examples/demo/Makefile
new file mode 100755
index 0000000000..98d7c6a130
--- /dev/null
+++ b/lib/wx/examples/demo/Makefile
@@ -0,0 +1,96 @@
+#
+# %CopyrightBegin%
+#
+# Copyright Ericsson AB 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 ../../vsn.mk
+include ../../config.mk
+
+TOPDIR = ../..
+SRC = .
+BIN = .
+ERLINC = $(TOPDIR)/include
+ERLC = erlc
+TESTMODS = \
+ demo \
+ demo_html_tagger \
+ ex_aui \
+ ex_button \
+ ex_canvas \
+ ex_canvas_paint \
+ ex_choices \
+ ex_cursor \
+ ex_dialogs \
+ ex_frame_utils \
+ ex_gauge \
+ ex_gl \
+ ex_grid \
+ ex_htmlWindow \
+ ex_listCtrl \
+ ex_notebook \
+ ex_pickers \
+ ex_popupMenu \
+ ex_radioBox \
+ ex_sashWindow \
+ ex_sizers \
+ ex_slider \
+ ex_splitterWindow \
+ ex_static \
+ ex_textCtrl \
+ ex_treeCtrl \
+ ex_graphicsContext
+
+
+TESTTARGETS = $(TESTMODS:%=%.beam)
+TESTSRC = $(TESTMODS:%=%.erl)
+
+# Targets
+opt debug: $(TESTTARGETS)
+clean:
+ rm -f $(TESTTARGETS)
+ rm -f *~ core erl_crash.dump
+
+docs:
+
+run: opt
+ erl -smp -detached -pa $(TOPDIR)/ebin -s demo
+
+ifneq ($(INSIDE_ERLSRC),true)
+
+%.beam: %.erl
+ $(ERLC) -W -I$(ERLINC) -bbeam -o$(BIN) $<
+
+else
+EXRELSYSDIR = $(RELSYSDIR)/examples/demo
+include $(ERL_TOP)/make/otp_release_targets.mk
+
+docs:
+
+release_spec:
+ $(INSTALL_DIR) $(EXRELSYSDIR)
+ $(INSTALL_DATA) $(TESTSRC) $(EXRELSYSDIR)
+ $(INSTALL_DATA) $(TESTTARGETS) $(EXRELSYSDIR)
+ $(INSTALL_DATA) image.jpg erlang.png ex_htmlWindow.html $(EXRELSYSDIR)
+
+release_tests_spec:
+
+release_docs_spec:
+
+endif
+
+
+
diff --git a/lib/wx/examples/demo/demo.erl b/lib/wx/examples/demo/demo.erl
new file mode 100644
index 0000000000..59c20e09fb
--- /dev/null
+++ b/lib/wx/examples/demo/demo.erl
@@ -0,0 +1,363 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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%
+
+%% This is example of the widgets and usage of wxErlang
+%% Hopefully it will contain all implemented widgets, it's event handling
+%% and some tutorials of how to use sizers and other stuff.
+
+-module(demo).
+
+-include_lib("wx/include/wx.hrl").
+
+-behaviour(wx_object).
+-export([start/0, start/1, start_link/0, start_link/1, format/3,
+ init/1, terminate/2, code_change/3,
+ handle_info/2, handle_call/3, handle_event/2]).
+
+
+-record(state, {win, demo, example, selector, log, code}).
+
+start() ->
+ start([]).
+
+start(Debug) ->
+ wx_object:start(?MODULE, Debug, []).
+
+start_link() ->
+ start_link([]).
+
+start_link(Debug) ->
+ wx_object:start_link(?MODULE, Debug, []).
+
+format(Config,Str,Args) ->
+ Log = proplists:get_value(log, Config),
+ wxTextCtrl:appendText(Log, io_lib:format(Str, Args)),
+ ok.
+
+-define(DEBUG_NONE, 101).
+-define(DEBUG_VERBOSE, 102).
+-define(DEBUG_TRACE, 103).
+-define(DEBUG_DRIVER, 104).
+
+init(Options) ->
+ wx:new(Options),
+ process_flag(trap_exit, true),
+
+ Frame = wxFrame:new(wx:null(), ?wxID_ANY, "wxErlang widgets", [{size,{1000,500}}]),
+ MB = wxMenuBar:new(),
+ File = wxMenu:new([]),
+ wxMenu:append(File, ?wxID_PRINT, "&Print code"),
+ wxMenu:appendSeparator(File),
+ wxMenu:append(File, ?wxID_EXIT, "&Quit"),
+ Debug = wxMenu:new([]),
+ wxMenu:appendRadioItem(Debug, ?DEBUG_NONE, "None"),
+ wxMenu:appendRadioItem(Debug, ?DEBUG_VERBOSE, "Verbose"),
+ wxMenu:appendRadioItem(Debug, ?DEBUG_TRACE, "Trace"),
+ wxMenu:appendRadioItem(Debug, ?DEBUG_DRIVER, "Driver"),
+ Help = wxMenu:new([]),
+ wxMenu:append(Help, ?wxID_HELP, "Help"),
+ wxMenu:append(Help, ?wxID_ABOUT, "About"),
+ wxMenuBar:append(MB, File, "&File"),
+ wxMenuBar:append(MB, Debug, "&Debug"),
+ wxMenuBar:append(MB, Help, "&Help"),
+ wxFrame:setMenuBar(Frame,MB),
+
+ wxFrame:connect(Frame, command_menu_selected),
+
+ _SB = wxFrame:createStatusBar(Frame,[]),
+
+ %% T Uppersplitter
+ %% O Left | Right
+ %% P Widgets|Code | Demo
+ %% S -------------------------------
+ %% P Log Window
+ TopSplitter = wxSplitterWindow:new(Frame, [{style, ?wxSP_NOBORDER}]),
+ UpperSplitter = wxSplitterWindow:new(TopSplitter, [{style, ?wxSP_NOBORDER}]),
+ LeftSplitter = wxSplitterWindow:new(UpperSplitter, [{style, ?wxSP_NOBORDER}]),
+ %% Setup so that sizers and initial sizes, resizes the windows correct
+ wxSplitterWindow:setSashGravity(TopSplitter, 0.5),
+ wxSplitterWindow:setSashGravity(UpperSplitter, 0.60),
+ wxSplitterWindow:setSashGravity(LeftSplitter, 0.20),
+
+ %% LeftSplitter:
+ Example = fun(Beam) ->
+ "ex_" ++ F = filename:rootname(Beam),
+ F
+ end,
+ Mods = [Example(F) || F <- filelib:wildcard("ex_*.beam")],
+
+ CreateLB = fun(Parent) ->
+ wxListBox:new(Parent, ?wxID_ANY,
+ [{style, ?wxLB_SINGLE},
+ {choices, Mods}])
+ end,
+ {LBPanel, [LB],_} = create_subwindow(LeftSplitter, "Example", [CreateLB]),
+ wxListBox:setSelection(LB, 0),
+ wxListBox:connect(LB, command_listbox_selected),
+
+ CreateCode = fun(Parent) ->
+ code_area(Parent)
+ end,
+ {CodePanel, [Code],_} = create_subwindow(LeftSplitter, "Code", [CreateCode]),
+
+ wxSplitterWindow:splitVertically(LeftSplitter, LBPanel, CodePanel,
+ [{sashPosition,150}]),
+
+ %% Demo:
+ {DemoPanel, [], DemoSz} = create_subwindow(UpperSplitter, "Demo", []),
+
+ %% UpperSplitter:
+ wxSplitterWindow:splitVertically(UpperSplitter, LeftSplitter, DemoPanel,
+ [{sashPosition,600}]),
+
+ %% TopSplitter:
+ AddEvent = fun(Parent) ->
+ EventText = wxTextCtrl:new(Parent,
+ ?wxID_ANY,
+ [{style, ?wxTE_DONTWRAP bor
+ ?wxTE_MULTILINE bor ?wxTE_READONLY}
+ ]),
+ wxTextCtrl:appendText(EventText, "Welcome\n"),
+ EventText
+ end,
+
+ {EvPanel, [EvCtrl],_} = create_subwindow(TopSplitter, "Events", [AddEvent]),
+
+ wxSplitterWindow:splitHorizontally(TopSplitter, UpperSplitter, EvPanel,
+ [{sashPosition,-100}]),
+
+ wxFrame:show(Frame),
+
+ State = #state{win=Frame, demo={DemoPanel,DemoSz}, selector=LB, log=EvCtrl, code=Code},
+ %% Load the first example:
+ Ex = wxListBox:getStringSelection(LB),
+ process_flag(trap_exit, true),
+ ExampleObj = load_example(Ex, State),
+ wxSizer:add(DemoSz, ExampleObj, [{proportion,1}, {flag, ?wxEXPAND}]),
+ wxSizer:layout(DemoSz),
+
+ %% The windows should be set up now, Reset Gravity so we get what we want
+ wxSplitterWindow:setSashGravity(TopSplitter, 1.0),
+ wxSplitterWindow:setSashGravity(UpperSplitter, 0.0),
+ wxSplitterWindow:setSashGravity(LeftSplitter, 0.0),
+ wxSplitterWindow:setMinimumPaneSize(TopSplitter, 1),
+ wxSplitterWindow:setMinimumPaneSize(UpperSplitter, 1),
+ wxSplitterWindow:setMinimumPaneSize(LeftSplitter, 1),
+
+ wxToolTip:enable(true),
+ wxToolTip:setDelay(500),
+
+ {Frame, State#state{example=ExampleObj}}.
+
+create_subwindow(Parent, BoxLabel, Funs) ->
+ Panel = wxPanel:new(Parent),
+ Sz = wxStaticBoxSizer:new(?wxVERTICAL, Panel, [{label, BoxLabel}]),
+ wxPanel:setSizer(Panel, Sz),
+ Ctrls = [Fun(Panel) || Fun <- Funs],
+ [wxSizer:add(Sz, Ctrl, [{proportion, 1}, {flag, ?wxEXPAND}])
+ || Ctrl <- Ctrls],
+ {Panel, Ctrls, Sz}.
+
+%%%%%%%%%%%%
+%% Callbacks
+
+%% Handled as in normal gen_server callbacks
+handle_info({'EXIT',_, wx_deleted}, State) ->
+ {noreply,State};
+handle_info({'EXIT',_, normal}, State) ->
+ {noreply,State};
+handle_info(Msg, State) ->
+ io:format("Got Info ~p~n",[Msg]),
+ {noreply,State}.
+
+handle_call(Msg, _From, State) ->
+ io:format("Got Call ~p~n",[Msg]),
+ {reply,ok,State}.
+
+%% Async Events are handled in handle_event as in handle_info
+handle_event(#wx{event=#wxCommand{type=command_listbox_selected, cmdString=Ex}},
+ State = #state{demo={_,DemoSz}, example=Example, code=Code}) ->
+ case Ex of
+ [] ->
+ {noreply, State};
+ _ ->
+ wxSizer:detach(DemoSz, Example),
+ wxWindow:destroy(Example),
+ unload_code(Code),
+ NewExample = load_example(Ex, State),
+ wxSizer:add(DemoSz, NewExample, [{proportion,1}, {flag, ?wxEXPAND}]),
+ wxSizer:layout(DemoSz),
+ {noreply, State#state{example=NewExample}}
+ end;
+handle_event(#wx{id = Id,
+ event = #wxCommand{type = command_menu_selected}},
+ State = #state{}) ->
+ case Id of
+ ?wxID_PRINT ->
+ %% If you are going to printout mainly text it is easier if
+ %% you generate HTML code and use a wxHtmlEasyPrint
+ %% instead of using DCs
+ Module = "ex_" ++ wxListBox:getStringSelection(State#state.selector) ++ ".erl",
+ HEP = wxHtmlEasyPrinting:new([{name, "Print"},
+ {parentWindow, State#state.win}]),
+ Html = demo_html_tagger:erl2htmltext(Module),
+ wxHtmlEasyPrinting:previewText(HEP, Html),
+ {noreply, State};
+ ?DEBUG_TRACE ->
+ wx:debug(trace),
+ {noreply, State};
+ ?DEBUG_DRIVER ->
+ wx:debug(driver),
+ {noreply, State};
+ ?DEBUG_VERBOSE ->
+ wx:debug(verbose),
+ {noreply, State};
+ ?DEBUG_NONE ->
+ wx:debug(none),
+ {noreply, State};
+ ?wxID_HELP ->
+ wx_misc:launchDefaultBrowser("http://www.erlang.org/doc/apps/wx/part_frame.html"),
+ {noreply, State};
+ ?wxID_ABOUT ->
+ AboutString =
+ "Demo of various widgets\n"
+ "Authors: Olle & Dan",
+ wxMessageDialog:showModal(wxMessageDialog:new(State#state.win, AboutString,
+ [{style,
+ ?wxOK bor
+ ?wxICON_INFORMATION bor
+ ?wxSTAY_ON_TOP},
+ {caption, "About"}])),
+ {noreply, State};
+ ?wxID_EXIT ->
+ wx_object:get_pid(State#state.example) ! stop,
+ {stop, normal, State};
+ _ ->
+ {noreply, State}
+ end;
+handle_event(#wx{event=#wxClose{}}, State = #state{win=Frame}) ->
+ io:format("~p Closing window ~n",[self()]),
+ ok = wxFrame:setStatusText(Frame, "Closing...",[]),
+ {stop, normal, State};
+handle_event(Ev,State) ->
+ io:format("~p Got event ~p ~n",[?MODULE, Ev]),
+ {noreply, State}.
+
+code_change(_, _, State) ->
+ {stop, not_yet_implemented, State}.
+
+terminate(_Reason, State) ->
+ wx_object:get_pid(State#state.example) ! stop,
+ timer:sleep(200), %% Give the example process some time to cleanup.
+ wx:destroy().
+
+%%%%%%%%%%%%%%%%% Internals %%%%%%%%%%
+
+load_example(Ex, #state{demo={DemoPanel,DemoSz}, log=EvCtrl, code=Code}) ->
+ ModStr = "ex_" ++ Ex,
+ Mod = list_to_atom(ModStr),
+%% WxDir = code:lib_dir(wx),
+%% ModFile = filename:join([WxDir, "examples","demo", ModStr ++ ".erl"]),
+ ModFile = ModStr ++ ".erl",
+ load_code(Code, file:read_file(ModFile)),
+ find(Code),
+ Mod:start([{parent, DemoPanel}, {demo_sz, DemoSz}, {log, EvCtrl}]).
+
+-define(stc, wxStyledTextCtrl).
+
+code_area(Parent) ->
+ FixedFont = wxFont:new(10, ?wxFONTFAMILY_TELETYPE, ?wxNORMAL, ?wxNORMAL,[]),
+ Ed = wxStyledTextCtrl:new(Parent),
+
+ ?stc:styleClearAll(Ed),
+ ?stc:styleSetFont(Ed, ?wxSTC_STYLE_DEFAULT, FixedFont),
+ ?stc:setLexer(Ed, ?wxSTC_LEX_ERLANG),
+ ?stc:setMarginType(Ed, 0, ?wxSTC_MARGIN_NUMBER),
+ LW = ?stc:textWidth(Ed, ?wxSTC_STYLE_LINENUMBER, "9"),
+ ?stc:setMarginWidth(Ed, 0, LW),
+ ?stc:setMarginWidth(Ed, 1, 0),
+
+ ?stc:setSelectionMode(Ed, ?wxSTC_SEL_LINES),
+ %%?stc:hideSelection(Ed, true),
+
+ Styles = [{?wxSTC_ERLANG_DEFAULT, {0,0,0}},
+ {?wxSTC_ERLANG_COMMENT, {160,53,35}},
+ {?wxSTC_ERLANG_VARIABLE, {150,100,40}},
+ {?wxSTC_ERLANG_NUMBER, {5,5,100}},
+ {?wxSTC_ERLANG_KEYWORD, {130,40,172}},
+ {?wxSTC_ERLANG_STRING, {170,45,132}},
+ {?wxSTC_ERLANG_OPERATOR, {30,0,0}},
+ {?wxSTC_ERLANG_ATOM, {0,0,0}},
+ {?wxSTC_ERLANG_FUNCTION_NAME, {64,102,244}},
+ {?wxSTC_ERLANG_CHARACTER,{236,155,172}},
+ {?wxSTC_ERLANG_MACRO, {40,144,170}},
+ {?wxSTC_ERLANG_RECORD, {40,100,20}},
+ {?wxSTC_ERLANG_SEPARATOR,{0,0,0}},
+ {?wxSTC_ERLANG_NODE_NAME,{0,0,0}}],
+ SetStyle = fun({Style, Color}) ->
+ ?stc:styleSetFont(Ed, Style, FixedFont),
+ ?stc:styleSetForeground(Ed, Style, Color)
+ end,
+ [SetStyle(Style) || Style <- Styles],
+ ?stc:setKeyWords(Ed, 0, keyWords()),
+
+ %% Scrolling
+ Policy = ?wxSTC_CARET_SLOP bor ?wxSTC_CARET_JUMPS bor ?wxSTC_CARET_EVEN,
+ ?stc:setYCaretPolicy(Ed, Policy, 3),
+ ?stc:setVisiblePolicy(Ed, Policy, 3),
+
+ %% ?stc:connect(Ed, stc_doubleclick),
+ ?stc:setReadOnly(Ed, true),
+ Ed.
+
+load_code(Ed, {ok, Code}) ->
+ ?stc:setReadOnly(Ed, false),
+ ?stc:setTextRaw(Ed, <<Code/binary, 0:8>>),
+ Lines = ?stc:getLineCount(Ed),
+ Sz = trunc(math:log10(Lines))+1,
+ LW = ?stc:textWidth(Ed, ?wxSTC_STYLE_LINENUMBER, lists:duplicate(Sz, $9)),
+ %%io:format("~p ~p ~p~n", [Lines, Sz, LW]),
+ ?stc:setMarginWidth(Ed, 0, LW+5),
+ ?stc:setReadOnly(Ed, true),
+ Ed.
+
+unload_code(Ed) ->
+ ?stc:setReadOnly(Ed, false),
+ ?stc:setTextRaw(Ed, <<0:8>>),
+ ?stc:setReadOnly(Ed, true),
+ Ed.
+
+find(Ed) ->
+ ?stc:searchAnchor(Ed),
+ Res = ?stc:searchNext(Ed, ?wxSTC_FIND_REGEXP, "^init"),
+ case Res >= 0 of
+ true ->
+ %% io:format("Found ~p ~n",[Res]),
+ ?stc:scrollToLine(Ed,?stc:lineFromPosition(Ed,Res) - 1),
+ true;
+ false ->
+ io:format("Not Found ~s ~n",["^init"]),
+ false
+ end.
+
+keyWords() ->
+ L = ["after","begin","case","try","cond","catch","andalso","orelse",
+ "end","fun","if","let","of","query","receive","when","bnot","not",
+ "div","rem","band","and","bor","bxor","bsl","bsr","or","xor"],
+ lists:flatten([K ++ " " || K <- L] ++ [0]).
+
diff --git a/lib/wx/examples/demo/demo_html_tagger.erl b/lib/wx/examples/demo/demo_html_tagger.erl
new file mode 100644
index 0000000000..9b6d1fd950
--- /dev/null
+++ b/lib/wx/examples/demo/demo_html_tagger.erl
@@ -0,0 +1,534 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(demo_html_tagger).
+
+%% You will notice that this program has very few type declarations
+%% That's because this program uses some pretty dodgy techniques to
+%% get at the data it requires.
+
+%% I use epp_dodger to parse the file and the new imporved erl_scan
+%% find the exact values of the tokens
+
+%% epp_dodger returns an objects of type erl_syntax which are pretty
+%% nasty buggers. We could write the types out but it would hardly
+%% help.
+
+%% to test run
+
+%%-compile(export_all).
+
+
+-export([erl2htmltext/1, erl2htmlfile/1]).
+
+erl2htmltext(File) ->
+ try
+ erl2html0(File)
+ catch
+ What:Why ->
+ io:format("error in:~s ~p ~p~n",[File,What,Why])
+ end.
+
+erl2htmlfile(File) ->
+ try
+ Text = erl2html0(File),
+ Root = filename:basename(filename:rootname(File)),
+ Out = "./html/" ++ Root ++ ".html",
+ file:write_file(Out, [Text])
+ catch
+ What:Why ->
+ io:format("error in:~s ~p ~p~n",[File,What,Why])
+ end.
+
+
+splitErlang(File) ->
+ {ok, Forms} = dodge_file(File),
+ {Anchors, Patches} = analyse(Forms),
+ Raw = read_raw_forms(File),
+ Raw1 = merge_anchors(Anchors, Raw),
+ Raw2 = merge_forms(Raw1, Patches, []),
+ Rtf = [final(I) || I <- Raw2],
+ {taggedBlocks, Rtf}.
+
+erl2html0(File) ->
+ Tb = splitErlang(File),
+ Html = to_html(Tb),
+ prelude(Html).
+
+merge_forms([{Tag,L1}|T], Patches, L) ->
+ {L2, Patches1} = apply_patches(L1, Patches),
+ merge_forms(T, Patches1, [{Tag,L2}|L]);
+merge_forms([], _, L) ->
+ lists:reverse(L).
+
+apply_patches(Toks, []) ->
+ %% we've run out of patches but we must still simplify
+ %% every term
+ {[simplify(I) || I <- Toks], []};
+apply_patches(Toks, Patches) ->
+ apply_patches(Toks, Patches, []).
+
+apply_patches([{atom,Ln,Val}=A|T], Patches, L) ->
+ case do_patch(Ln, Patches) of
+ {yes, New, Patches1} ->
+ New1 = reformat(New, Val),
+ apply_patches(T, Patches1, [New1|L]);
+ {no, Patches1} ->
+ apply_patches(T, Patches1, [simplify(A)|L])
+ end;
+apply_patches([H|T], Patches, L) ->
+ apply_patches(T, Patches, [simplify(H)|L]);
+apply_patches([], Patches, L) ->
+ {lists:reverse(L), Patches}.
+
+
+simplify({atom,_,Str}) ->
+ case (catch list_to_existing_atom(Str)) of
+ {'EXIT', _} ->
+ {atom, Str};
+ A ->
+ case is_keyword(A) of
+ true -> {keyword, Str};
+ false ->
+ {atom, Str}
+ end
+ end;
+simplify({dot,_,Str}) ->
+ {terminal, Str};
+simplify({Tag,_,Str}) ->
+ case is_keyword(Tag) of
+ true ->
+ {keyword, Str};
+ false ->
+ case is_terminal(Tag) of
+ true ->
+ {terminal, Str};
+ false ->
+ {Tag, Str}
+ end
+ end;
+simplify(X) ->
+ io:format("simplify wtfit:~p~n",[X]),
+ X.
+
+do_patch(Ln, [{Ln,Tag}|P]) -> {yes, Tag, P};
+do_patch(Ln, [{Ln1,_}|_] = P) when Ln1 > Ln -> {no, P};
+do_patch(Ln, [_|T]) -> do_patch(Ln, T);
+do_patch(_, []) -> {no, []}.
+
+reformat({local,{F,A}}, Str) -> {local,F,A,Str};
+reformat({remote,M,F,A}, Str) -> {remote,M,F,A,Str};
+reformat({remote,{M,F,A}}, Str) -> {remote,M,F,A,Str};
+reformat({bif,{F,A}}, Str) -> {bif,F,A,Str};
+reformat(Tag, Str) ->
+ io:format("reformat*:~p ~p~n",[Tag,Str]),
+ {Tag,Str}.
+
+to_html({taggedBlocks, L}) ->
+ [[anchor1(Anchor),to_html(Body)] || {Anchor,Body} <- L];
+to_html({taggedToks, L}) ->
+ [to_html1(I) || I <- L].
+
+anchor1({func, F, A}) ->
+ ["<a name='",linkname(F,A),"'></a>"];
+anchor1({specification, F, A}) ->
+ ["<a name='",linkname(F,A),"'></a>"];
+anchor1(_X) ->
+ "".
+
+linkname(F, A) when is_atom(F) ->
+ a2s(F) ++ "-" ++ integer_to_list(A);
+linkname(F, A) when is_list(F) ->
+ F ++ "-" ++ integer_to_list(A).
+
+a2s(A) ->
+ atom_to_list(A).
+
+font(C, S) ->
+ ["<font color=\"", C, "\">", htmlquote(S), "</font>"].
+
+htmlquote("<" ++ T) -> ["&lt;"|htmlquote(T)];
+htmlquote([H|T]) -> [H|htmlquote(T)];
+htmlquote([]) -> [].
+
+to_html1({white_space,V}) -> V;
+to_html1({comment, V}) -> font("#B22222", V);
+to_html1({var,V}) -> font("orange", V);
+to_html1({string,V}) -> font("#FA8072", V);
+to_html1({integer,V}) -> font("#1111AA", V);
+to_html1({bif,_F,_A,Str}) -> font("#FF00FF", Str);
+to_html1({keyword, V}) -> font("#FF00FF", V);
+to_html1({atom, V}) -> V;
+to_html1({terminal,V}) -> V;
+to_html1({char,V}) -> V;
+to_html1({float,V}) -> V;
+to_html1({anchor,F,A}) ->
+ ["<a name='",linkname(F,A),"'></a>"];
+to_html1({local,F,A,Str}) ->
+ ["<a href='#",linkname(F,A),"'>",
+ htmlquote(Str),"</a>"];
+to_html1({remote,_M,_F,_A,Str}) ->
+ %%["<a href='",htmlname(M), "#",linkname(F,A),"'>",htmlquote(Str),"</a>"],
+ Str.
+
+%% merge the anchors
+%% there should be one block per anchor
+%% we check the containing form (for safety)
+
+%% merge_anchors([{_,{file,_}}|A], B) ->
+%% merge_anchors(A, B);
+merge_anchors([{Tag,Val}=H|A], [B|T]) ->
+ case contains(Tag, B) of
+ true ->
+ [{Val,B}|merge_anchors(A, T)];
+ false ->
+ io:format("Logic error: H=~p B=~p~n",[H,B]),
+ exit(1)
+ end;
+merge_anchors([], []) -> [];
+merge_anchors([], [X]) ->
+ %% this is the last block -
+ %% trailing white space and comments have no tag
+ %% because eos is not a tag ...
+ [{eof, X}];
+merge_anchors(X, Y) ->
+ io:format("ops:~p~n",[{X,Y}]),
+ [].
+
+contains(Loc, [{_,Loc,_}|_]) -> true;
+contains(Loc, [_|T]) -> contains(Loc, T);
+contains(_, []) -> false.
+
+
+dodge_file(File) ->
+ case file:open(File, [read]) of
+ {ok, Handle} ->
+ {ok, F} = epp_dodger:parse(Handle, {1,1}),
+ file:close(Handle),
+ L = [revert_forms(I) || I <- F],
+ {ok, L};
+ Error ->
+ Error
+ end.
+
+revert_forms(F) ->
+ case erl_syntax:is_form(F) of
+ true ->
+ %% revert fails on ifdef ... etc
+ case (catch erl_syntax:revert(F)) of
+ {'EXIT', _Why} ->
+ io:format("error reverting:~p=~p~n",[F,_Why]),
+ F;
+ Other ->
+ Other
+ end;
+ false ->
+ io:format("uugh:~p~n",[F])
+ end.
+
+%% read up to dot
+%% read_raw_forms(File) -> [form()]
+%% form() = [tok()]
+%% tok() = {Type,{Line::int,Col::int},string}
+%% Type = atom | int | var | string ...
+
+read_raw_forms(File) ->
+ {ok, Bin} = file:read_file(File),
+ Str = binary_to_list(Bin),
+ loop(erl_scan:tokens([], Str, {1,1}, [return,text]), []).
+
+loop({done, {eof,_}, eof}, L) ->
+ lists:reverse(L);
+loop({done, {ok, Toks, _}, eof}, L) ->
+ lists:reverse([normalize_toks(Toks)|L]);
+loop({done, {ok, Toks, Ln}, Str1}, L) ->
+ loop(erl_scan:tokens([], Str1, Ln, [return,text]),
+ [normalize_toks(Toks)|L]);
+loop({more, X}, L) ->
+ loop(erl_scan:tokens(X, eof, {1,1}, [return,text]), L).
+
+normalize_toks(Toks) ->
+ [normalize_tok(I) || I <- Toks].
+
+normalize_tok(Tok) ->
+ %% this is the portable way ...
+ [{_,Type},{_,Line},{_,Col},{_,Txt}] =
+ erl_scan:token_info(Tok, [category,line,column,text]),
+ Val = {Type,{Line,Col},Txt},
+ %% io:format("here:X=~p ~p~n",[Tok,Val]),
+ Val.
+
+
+%% analse the result of dodge_file
+
+analyse(Forms) ->
+ Calls = calls(Forms),
+ Anchors = compute_anchors(Forms),
+ Imports = [{{F,A},Mod} ||
+ {attribute,_,import,{Mod,L}} <- Forms, {F,A} <- L],
+ D = dict:from_list(Imports),
+ Patches = [{Loc, resolve(X, D)} || {Loc, X} <- Calls],
+ {Anchors, Patches}.
+
+%% An anchor is something that is placed at the start of every form
+%% The anchor is named after the first item in the form
+%% compute_anchors(Forms) -> [{{Line,Col}, anchor()}]
+%% {Line,Col} is the line and column of where the
+%% form starts - this is not the same as the first token in
+%% the form since we might have skipped comments and white space
+%% at the start of the form.
+%% anchor() is a term decscribing the anchor
+%% anchor(() = {func,Name,Aritry} (for functions)
+%% |
+%% | {Type,{Line,Col}} anythis else
+
+compute_anchors(Forms) ->
+ A1 = [anchor0(I) || I <- Forms],
+ merge_specs(A1).
+
+%% If a specification is immediately followed by
+%% a function when we promote the function anchor to point
+%% at the specification.
+%% We change the second tag to func2 - because we still want a
+%% tag for every block
+
+merge_specs([{_Ln1,{specification,F,A}}=H,{Ln2, {func,F,A}}|T]) ->
+ [H,{Ln2,{func1,F,A}}|merge_specs(T)];
+merge_specs([H|T]) ->
+ [H|merge_specs(T)];
+merge_specs([]) ->
+ [].
+
+anchor0(I) ->
+ case anchor(I) of
+ {{Line,Col,_,_}, Val} ->
+ {{Line,Col}, Val};
+ {{_,_}, _} = X ->
+ X
+ end.
+
+anchor({function, Ln, F, A, _}) -> {Ln, {func, F, A}};
+anchor({attribute,Ln,'spec', {{F,A},_}}) ->
+ {Ln, {specification,F,A}};
+anchor({attribute,Ln,module, M}) ->
+ {Ln, {module,M}};
+anchor({attribute,Ln,Type,_}) -> {Ln, {Type, Ln}};
+anchor({eof,Ln}) -> {Ln, eof};
+anchor({error,{Ln,_,_}}) ->
+ %% Ln is in a different format in errors (sigh)
+ {Line, Col} = Ln,
+ Ln1 = {Line,Col,0,""},
+ {Ln1, {error, Ln}};
+anchor({tree,attribute,{attr,{_,_,_,Type}=Ln,_,_},_}) ->
+ {Ln, {attribute,Type,Ln}};
+anchor({tree,attribute,_,
+ {attribute, {atom,Ln,Type}, _}}) ->
+ {Ln, {attribute,Type,Ln}};
+anchor({tree,attribute,
+ {attr,Ln,[],none},
+ _}=X) ->
+ io:format("FIX ME this is a bug????:~p~n",[X]),
+ {Ln, {other, Ln}};
+anchor(X) ->
+ %% this is some syntactic form that I don't know
+ %% about yet ...
+ io:format("FIX ME this is a bug????:~p~n",[X]),
+ exit(1).
+
+resolve({F,A}=Tup, D) ->
+ case dict:find({F,A}, D) of
+ {ok, Mod} ->
+ {remote,Mod,F,A};
+ error ->
+ case erlang:is_builtin(erlang, F, A) of
+ true -> {bif, {F,A}};
+ false -> {local,Tup}
+ end
+ end;
+resolve({erlang,F,A}, _) ->
+ {bif,{F,A}};
+resolve({anchor,_,_}=A, _) ->
+ A;
+resolve(X, _D) ->
+ {remote, X}.
+
+calls(X) -> lists:reverse(calls(X, [])).
+
+calls({call,_,{atom,Ln,Func},Args}, L) ->
+ calls(Args, [{normalise(Ln),{Func,length(Args)}}|L]);
+calls({call,_,{remote,_,{atom,Ln1,Mod},{atom,_Ln2,Func}}, Args}, L) ->
+ calls(Args, [{normalise(Ln1),{Mod,Func,length(Args)}}|L]);
+calls(T, L) when is_tuple(T) ->
+ calls(tuple_to_list(T), L);
+calls([], L) ->
+ L;
+calls(T, L) when is_list(T) ->
+ lists:foldl(fun calls/2, L, T);
+calls(_, L) ->
+ L.
+
+normalise({_Line,_Col}=X) ->
+ X;
+normalise({Line,Col,_Len,_Text}) ->
+ {Line, Col}.
+
+
+prelude(L) ->
+ ["<html>\n"
+ "<head>\n"
+ "</head>\n"
+ "<body>\n"
+ "<ul><pre>\n",L,"\n</pre></ul></body>"].
+
+
+final({Tag, Toks}) ->
+ {Tag, {taggedToks, final1(Tag, Toks)}}.
+
+final1({Tag,_,_}, Toks) when Tag =:= func; Tag =:= func1 ->
+ %% io:format("fix_remote:~p~n",[Toks]),
+ fix_remote(Toks);
+final1({export,_}, Toks) ->
+ fix_exports(Toks);
+final1({import,_}, Toks) ->
+ fix_imports(Toks);
+final1(_, Toks) ->
+ %% io:format("final:~p~n",[X]),
+ Toks.
+
+
+fix_imports(Toks) ->
+ %% io:format("fix imports:~p~n",[Toks]),
+ Mod = find_imported_module(Toks),
+ %% io:format("Mod =~p~n",[Mod]),
+ fix_imports(Toks, Mod).
+
+fix_imports([{atom,A},{terminal,"/"},{integer,N}|T], Mod) ->
+ [{remote, Mod,A,list_to_integer(N),A++"/"++N}|
+ fix_imports(T, Mod)];
+fix_imports([H|T], Mod) ->
+ [H|fix_imports(T, Mod)];
+fix_imports([], _) ->
+ [].
+
+%% skip to the atom import, then take the first atom after import
+find_imported_module([{atom,"import"}|T]) -> find_imported_module1(T);
+find_imported_module([_|T]) -> find_imported_module(T).
+
+find_imported_module1([{atom,M}|_]) -> list_to_atom(M);
+find_imported_module1([_|T]) -> find_imported_module1(T).
+
+%% won't work if there is white space between the symbols
+%% fix later
+
+fix_exports([{atom,A},{terminal,"/"},{integer,N}|T]) ->
+ [{local,A,list_to_integer(N),A++"/"++N}|fix_exports(T)];
+fix_exports([H|T]) ->
+ [H|fix_exports(T)];
+fix_exports([]) ->
+ [].
+
+%% fix_remote merges Mod : Func into a single string
+%% the problem is that
+%% we only tag the first atom in a remote call mod:func(...)
+%% mod is tagged as remote - but we want to
+%% extend the tagging to include the entire mod:func
+%% call ...
+
+fix_remote([{remote,M,F,A,Str},{terminal,":"},{atom,Str1}|T]) ->
+ [{remote,M,F,A,Str ++ ":" ++ Str1}|fix_remote(T)];
+fix_remote([{remote,M,F,A,Str},{white_space,S1},{terminal,":"},{atom,Str1}|T]) ->
+ [{remote,M,F,A,Str ++ S1 ++ ":" ++ Str1}|fix_remote(T)];
+fix_remote([{remote,M,F,A,Str},{white_space,S1},{terminal,":"},{white_space,S2},{atom,Str1}|T]) ->
+ [{remote,M,F,A,Str ++ S1 ++ ":" ++ S2 ++ Str1}|fix_remote(T)];
+fix_remote([{remote,M,F,A,Str},{terminal,":"},{white_space,S2},{atom,Str1}|T]) ->
+ [{remote,M,F,A,Str ++ ":" ++ S2 ++ Str1}|fix_remote(T)];
+fix_remote([H|T]) ->
+ [H|fix_remote(T)];
+fix_remote([]) ->
+ [].
+
+-spec is_keyword(atom()) -> bool().
+
+is_keyword('after' ) -> true;
+is_keyword('and') -> true;
+is_keyword('andalso' ) -> true;
+is_keyword('band' ) -> true;
+is_keyword('begin' ) -> true;
+is_keyword('bnot' ) -> true;
+is_keyword('bor' ) -> true;
+is_keyword('bsl' ) -> true;
+is_keyword('bsr' ) -> true;
+is_keyword('bxor' ) -> true;
+is_keyword('case' ) -> true;
+is_keyword('catch' ) -> true;
+is_keyword('cond') -> true;
+is_keyword('div' ) -> true;
+is_keyword('end' ) -> true;
+is_keyword('fun' ) -> true;
+is_keyword('if' ) -> true;
+is_keyword('not') -> true;
+is_keyword('of' ) -> true;
+is_keyword('or' ) -> true;
+is_keyword('orelse' ) -> true;
+is_keyword('query' ) -> true;
+is_keyword('receive' ) -> true;
+is_keyword('rem' ) -> true;
+is_keyword('spec') -> true;
+is_keyword('try' ) -> true;
+is_keyword('when') -> true;
+is_keyword('xor') -> true;
+is_keyword(_) -> false.
+
+is_terminal('!') -> true;
+is_terminal('#') -> true;
+is_terminal('(') -> true;
+is_terminal(')') -> true;
+is_terminal('*') -> true;
+is_terminal('+') -> true;
+is_terminal('++') -> true;
+is_terminal(',') -> true;
+is_terminal('-') -> true;
+is_terminal('--') -> true;
+is_terminal('->') -> true;
+is_terminal('.') -> true;
+is_terminal('/') -> true;
+is_terminal('/=') -> true;
+is_terminal(':') -> true;
+is_terminal(':-') -> true;
+is_terminal('::') -> true;
+is_terminal(';') -> true;
+is_terminal('<') -> true;
+is_terminal('<-') -> true;
+is_terminal('<<') -> true;
+is_terminal('<=') -> true;
+is_terminal('=') -> true;
+is_terminal('=/=') -> true;
+is_terminal('=:=') -> true;
+is_terminal('=<') -> true;
+is_terminal('==') -> true;
+is_terminal('>') -> true;
+is_terminal('>=') -> true;
+is_terminal('>>') -> true;
+is_terminal('?') -> true;
+is_terminal('[') -> true;
+is_terminal(']') -> true;
+is_terminal('{') -> true;
+is_terminal('|') -> true;
+is_terminal('||') -> true;
+is_terminal('}') -> true;
+is_terminal(_) -> false.
diff --git a/lib/wx/examples/demo/erlang.png b/lib/wx/examples/demo/erlang.png
new file mode 100644
index 0000000000..a5901103a3
--- /dev/null
+++ b/lib/wx/examples/demo/erlang.png
Binary files differ
diff --git a/lib/wx/examples/demo/ex_aui.erl b/lib/wx/examples/demo/ex_aui.erl
new file mode 100644
index 0000000000..6adfd970fc
--- /dev/null
+++ b/lib/wx/examples/demo/ex_aui.erl
@@ -0,0 +1,189 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(ex_aui).
+
+-behaviour(wx_object).
+
+%% Client API
+-export([start/1]).
+
+%% wx_object callbacks
+-export([init/1, terminate/2, code_change/3,
+ handle_info/2, handle_call/3, handle_event/2]).
+
+-include("../../include/wx.hrl").
+
+-record(state,
+ {
+ parent,
+ config
+ }).
+
+start(Config) ->
+ wx_object:start_link(?MODULE, Config, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init(Config) ->
+ wx:batch(fun() -> do_init(Config) end).
+
+-define(pi, wxAuiPaneInfo).
+
+do_init(Config) ->
+ Parent = proplists:get_value(parent, Config),
+ Panel = wxPanel:new(Parent, []),
+
+ %% Setup sizers
+ MainSizer = wxBoxSizer:new(?wxVERTICAL),
+
+ Manager = wxAuiManager:new([{managed_wnd, Panel}
+ ]),
+
+ Pane = ?pi:new(),
+ ?pi:closeButton(Pane),
+ ?pi:right(Pane),
+ ?pi:dockable(Pane, [{b, true}]),
+ ?pi:floatingSize(Pane, 300,200),
+ ?pi:minSize(Pane, {50,50}),
+ ?pi:paneBorder(Pane),
+ ?pi:floatable(Pane, [{b, true}]),
+
+ create_pane(Panel, Manager, Pane),
+ create_pane(Panel, Manager,
+ ?pi:caption(?pi:top(?pi:new(Pane)), "One")),
+ create_pane(Panel, Manager,
+ ?pi:caption(?pi:left(?pi:new(Pane)), "two")),
+ create_pane(Panel, Manager,
+ ?pi:caption(?pi:bottom(?pi:new(Pane)), "Three")),
+ Pane2 = wxAuiPaneInfo:new(Pane),
+ ?pi:centrePane(Pane2),
+ create_notebook(Panel, Manager, ?pi:new(Pane2)),
+
+ wxPanel:setSizer(Panel, MainSizer),
+
+ wxAuiManager:connect(Manager, aui_pane_button, [{skip,true}]),
+ wxAuiManager:connect(Manager, aui_pane_maximize, [{skip,true}]),
+ wxAuiManager:update(Manager),
+
+ {Panel, #state{parent=Panel, config=Config}}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Callbacks handled as normal gen_server callbacks
+handle_info(Msg, State) ->
+ demo:format(State#state.config, "Got Info ~p\n", [Msg]),
+ {noreply, State}.
+
+handle_call(Msg, _From, State) ->
+ demo:format(State#state.config, "Got Call ~p\n", [Msg]),
+ {reply,{error, nyi}, State}.
+
+%% Async Events are handled in handle_event as in handle_info
+handle_event(#wx{obj = Notebook,
+ event = #wxCommand{type = command_button_clicked}},
+ State) ->
+ Tab = wxPanel:new(Notebook, []),
+ wxButton:new(Tab, ?wxID_ANY, [{label,"New tab"}]),
+ wxAuiNotebook:insertPage(Notebook, 1, Tab, "OMG TAB!! ", [{select, false}]),
+ {noreply, State};
+handle_event(#wx{obj = Notebook,
+ event = #wxAuiNotebook{type = command_auinotebook_page_changed,
+ selection = Sel}}, State) ->
+ demo:format(State#state.config, "You have changed page to ~p.\n",
+ [wxAuiNotebook:getPageText(Notebook, Sel)]),
+ {noreply, State};
+handle_event(#wx{event = #wxAuiNotebook{type = command_auinotebook_page_close}}, State) ->
+ demo:format(State#state.config, "You have closed a page.\n",[]),
+ {noreply, State};
+handle_event(#wx{event = #wxAuiManager{type = aui_pane_button,
+ button = Button}}, State) ->
+ case Button of
+ ?wxAUI_BUTTON_CLOSE ->
+ demo:format(State#state.config, "You have closed a pane.\n",[]);
+ ?wxAUI_BUTTON_MAXIMIZE_RESTORE ->
+ ok;
+ ?wxAUI_BUTTON_PIN ->
+ demo:format(State#state.config, "You have pinned a pane.\n",[])
+ end,
+ {noreply, State};
+handle_event(#wx{event = #wxAuiManager{type = aui_pane_maximize}}, State) ->
+ demo:format(State#state.config, "You have maximized a pane.\n",[]),
+ {noreply, State};
+handle_event(#wx{event = #wxAuiManager{type = aui_pane_restore}}, State) ->
+ demo:format(State#state.config, "You have restored a pane.\n",[]),
+ {noreply, State};
+handle_event(Ev = #wx{}, State) ->
+ io:format("~p\n", [Ev]),
+ {noreply, State}.
+
+
+code_change(_, _, State) ->
+ {stop, ignore, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Local functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+create_notebook(Parent, Manager, Pane) ->
+ Style = (0
+ bor ?wxAUI_NB_DEFAULT_STYLE
+ bor ?wxAUI_NB_TOP
+ bor ?wxAUI_NB_WINDOWLIST_BUTTON
+ bor ?wxAUI_NB_CLOSE_ON_ACTIVE_TAB
+ bor ?wxAUI_NB_TAB_MOVE
+ bor ?wxAUI_NB_SCROLL_BUTTONS
+ ),
+
+ Notebook = wxAuiNotebook:new(Parent, [{style, Style}]),
+
+ Tab1 = wxPanel:new(Notebook, []),
+ wxPanel:setBackgroundColour(Tab1, ?wxBLACK),
+ wxButton:new(Tab1, ?wxID_ANY, [{label,"New tab"}]),
+ wxAuiNotebook:addPage(Notebook, Tab1, "You can", []),
+
+ Tab2 = wxPanel:new(Notebook, []),
+ wxPanel:setBackgroundColour(Tab2, ?wxRED),
+ wxButton:new(Tab2, ?wxID_ANY, [{label,"New tab"}]),
+ wxAuiNotebook:addPage(Notebook, Tab2, "rearrange", []),
+
+ Tab3 = wxPanel:new(Notebook, []),
+ wxPanel:setBackgroundColour(Tab3, ?wxGREEN),
+ wxButton:new(Tab3, ?wxID_ANY, [{label,"New tab"}]),
+ wxAuiNotebook:addPage(Notebook, Tab3, "these tabs", []),
+
+ wxAuiManager:addPane(Manager, Notebook, Pane),
+
+ wxAuiNotebook:connect(Notebook, command_button_clicked),
+ wxAuiNotebook:connect(Notebook, command_auinotebook_page_close, [{skip, false}]),
+ wxAuiNotebook:connect(Notebook, command_auinotebook_page_changed),
+ Notebook.
+
+
+create_pane(Parent, Manager, Pane) ->
+ TextCtrl = wxTextCtrl:new(Parent, ?wxID_ANY, [{size, {300,200}},
+ {value, "An empty pane"},
+ {style, 0
+ bor ?wxDEFAULT
+ bor ?wxTE_MULTILINE}]),
+ wxAuiManager:addPane(Manager, TextCtrl, Pane),
+ TextCtrl.
+
+
diff --git a/lib/wx/examples/demo/ex_button.erl b/lib/wx/examples/demo/ex_button.erl
new file mode 100644
index 0000000000..28c8273cb9
--- /dev/null
+++ b/lib/wx/examples/demo/ex_button.erl
@@ -0,0 +1,230 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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%
+
+%% This is example of the widgets and usage of wxErlang
+%% Hopefully it will contain all implemented widgets, it's event handling
+%% and some tutorials of how to use sizers and other stuff.
+
+-module(ex_button).
+
+-include_lib("wx/include/wx.hrl").
+
+-behaviour(wx_object).
+-export([start/1, init/1, terminate/2, code_change/3,
+ handle_info/2, handle_call/3, handle_event/2]).
+
+-record(state,
+ {
+ parent,
+ config
+ }).
+
+start(Config) ->
+ wx_object:start_link(?MODULE, Config, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init(Config) ->
+ wx:batch(fun() -> do_init(Config) end).
+
+do_init(Config) ->
+ Parent = proplists:get_value(parent, Config),
+ Panel = wxScrolledWindow:new(Parent),
+
+ %% Setup sizers
+ Sz = wxBoxSizer:new(?wxVERTICAL),
+ ButtSz = wxStaticBoxSizer:new(?wxHORIZONTAL, Panel,
+ [{label, "wxButton"}]),
+ AlignSz = wxStaticBoxSizer:new(?wxHORIZONTAL, Panel,
+ [{label, "Alignment Style"}]),
+ OtherSz = wxStaticBoxSizer:new(?wxHORIZONTAL, Panel,
+ [{label, "Other Styles"}]),
+ StockTopSz = wxStaticBoxSizer:new(?wxHORIZONTAL, Panel,
+ [{label, "Stock Buttons"}]),
+
+ B10 = wxButton:new(Panel, 10, [{label,"Normal"}]),
+ wxButton:setToolTip(B10, "Normal button with (default) centered label"),
+
+ B11 = wxToggleButton:new(Panel, 11, "Toggle Button"),
+ wxToggleButton:connect(B11, command_togglebutton_clicked),
+ wxButton:setToolTip(B11, "A toggle button"),
+
+ B12 = wxButton:new(Panel, 12, [{label,"Default"}]),
+ wxButton:setDefault(B12),
+ wxButton:setToolTip(B12, "Normal button set to be the default button"),
+
+ B13 = wxButton:new(Panel, 13, [{label,"Disabled"}]),
+ wxButton:disable(B13),
+ wxButton:setToolTip(B13, "Disabled Normal button"),
+
+ B14 = wxBitmapButton:new(Panel, 14, create_bitmap("A bitmap button")),
+ wxButton:setToolTip(B14, "A Bitmap button"),
+
+ %% Alignment and NO_BORDER only works on Win and GTK
+ %% according to docs.
+ B20 = wxButton:new(Panel, 20, [{label,"Left Aligned"},
+ {size, {100, -1}},
+ {style,?wxBU_LEFT}]),
+ wxButton:setToolTip(B20, "Normal button with left aligned label"),
+
+ B21 = wxButton:new(Panel, 21, [{label,"Top Aligned"},
+ {size, {-1, 50}},
+ {style,?wxBU_TOP}]),
+ wxButton:setToolTip(B21, "Normal button with top aligned label"),
+
+ B22 = wxButton:new(Panel, 22, [{label,"Lower Right Aligned"},
+ {size, {150, 50}},
+ {style,?wxBU_BOTTOM bor ?wxBU_RIGHT}]),
+ wxButton:setToolTip(B22, "Normal button with top right aligned label"),
+
+ %% Other types
+ B30 = wxButton:new(Panel, 30, [{label,"Flat Style"},
+ {style, ?wxNO_BORDER}]),
+ wxButton:setToolTip(B30, "Flat style button, on some OS'es"),
+
+ B31 = wxButton:new(Panel, 31, [{label,"Exact Fit"},
+ {style, ?wxBU_EXACTFIT}]),
+ wxButton:setToolTip(B31, "Minimal Size button"),
+
+ %% Stock Buttons
+ StockButts = [wxButton:new(Panel, Id) || Id <- stock_buttons()],
+
+ StockSz = wxGridSizer:new(0,5,3,3),
+
+ SzFlags = [{proportion, 0}, {border, 4}, {flag, ?wxALL}],
+ Expand = [{proportion, 0}, {border, 4}, {flag, ?wxALL bor
+ ?wxEXPAND}],
+ [wxSizer:add(ButtSz, Button, SzFlags) ||
+ Button <- [B10, B11, B12, B13, B14]],
+ [wxSizer:add(AlignSz, Button, SzFlags) || Button <- [B20,B21,B22]],
+ [wxSizer:add(OtherSz, Button, SzFlags) || Button <- [B30,B31]],
+ [wxSizer:add(StockSz, Butt, SzFlags) || Butt <- StockButts],
+ wxSizer:add(StockTopSz, StockSz, SzFlags),
+ [wxSizer:add(Sz, Button, Flag) ||
+ {Button, Flag} <- [{ButtSz,SzFlags},{AlignSz,Expand},
+ {OtherSz,Expand}, {StockTopSz, Expand}]],
+ wxWindow:connect(Panel, command_button_clicked),
+ wxWindow:setSizer(Panel, Sz),
+ wxSizer:layout(Sz),
+ wxScrolledWindow:setScrollRate(Panel, 5, 5),
+ {Panel, #state{parent=Panel, config=Config}}.
+
+
+%%%%%%%%%%%%
+%% Async Events are handled in handle_event as in handle_info
+handle_event(#wx{id=Id, event=#wxCommand{type=command_button_clicked}},
+ State = #state{parent=Parent}) ->
+ B0 = wxWindow:findWindowById(Id, [{parent, Parent}]),
+ Butt = wx:typeCast(B0, wxButton),
+ Label = wxButton:getLabel(Butt),
+ demo:format(State#state.config,"Button: \'~ts\' clicked~n",[Label]),
+ {noreply,State};
+
+handle_event(#wx{event=#wxCommand{type=command_togglebutton_clicked}},
+ State = #state{}) ->
+ demo:format(State#state.config,
+ "Button: You toggled the 'Toggle button' ~n",[]),
+ {noreply,State};
+
+handle_event(Ev = #wx{}, State = #state{}) ->
+ demo:format(State#state.config,"Got Event ~p~n",[Ev]),
+ {noreply,State}.
+
+%% Callbacks handled as normal gen_server callbacks
+handle_info(Msg, State) ->
+ demo:format(State#state.config, "Got Info ~p~n",[Msg]),
+ {noreply,State}.
+
+handle_call(Msg, _From, State) ->
+ demo:format(State#state.config,"Got Call ~p~n",[Msg]),
+ {reply,ok,State}.
+
+code_change(_, _, State) ->
+ {stop, ignore, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%%%% a copy from wxwidgets samples.
+create_bitmap(Label) ->
+ Bmp = wxBitmap:new(140, 30),
+ DC = wxMemoryDC:new(),
+ wxMemoryDC:selectObject(DC, Bmp),
+ wxDC:setBackground(DC, ?wxWHITE_BRUSH),
+ wxDC:clear(DC),
+ wxDC:setTextForeground(DC, ?wxBLUE),
+ wxDC:drawLabel(DC, Label, {5,5,130,20}, [{alignment, ?wxALIGN_CENTER}]),
+ wxMemoryDC:destroy(DC),
+ Bmp.
+
+
+stock_buttons() ->
+ [?wxID_ABOUT,
+ ?wxID_ADD,
+ ?wxID_APPLY,
+ ?wxID_BOLD,
+ ?wxID_CANCEL,
+ ?wxID_CLEAR,
+ ?wxID_CLOSE,
+ ?wxID_COPY,
+ ?wxID_CUT,
+ ?wxID_DELETE,
+ ?wxID_EDIT,
+ ?wxID_FIND,
+ ?wxID_FILE,
+ ?wxID_REPLACE,
+ ?wxID_BACKWARD,
+ ?wxID_DOWN,
+ ?wxID_FORWARD,
+ ?wxID_UP,
+ ?wxID_HELP,
+ ?wxID_HOME,
+ ?wxID_INDENT,
+ ?wxID_INDEX,
+ ?wxID_ITALIC,
+ ?wxID_JUSTIFY_CENTER,
+ ?wxID_JUSTIFY_FILL,
+ ?wxID_JUSTIFY_LEFT,
+ ?wxID_JUSTIFY_RIGHT,
+ ?wxID_NEW,
+ ?wxID_NO,
+ ?wxID_OK,
+ ?wxID_OPEN,
+ ?wxID_PASTE,
+ ?wxID_PREFERENCES,
+ ?wxID_PRINT,
+ ?wxID_PREVIEW,
+ ?wxID_PROPERTIES,
+ ?wxID_EXIT,
+ ?wxID_REDO,
+ ?wxID_REFRESH,
+ ?wxID_REMOVE,
+ ?wxID_REVERT_TO_SAVED,
+ ?wxID_SAVE,
+ ?wxID_SAVEAS,
+ ?wxID_SELECTALL,
+ ?wxID_STOP,
+ ?wxID_UNDELETE,
+ ?wxID_UNDERLINE,
+ ?wxID_UNDO,
+ ?wxID_UNINDENT,
+ ?wxID_YES,
+ ?wxID_ZOOM_100,
+ ?wxID_ZOOM_FIT,
+ ?wxID_ZOOM_IN,
+ ?wxID_ZOOM_OUT].
+
diff --git a/lib/wx/examples/demo/ex_canvas.erl b/lib/wx/examples/demo/ex_canvas.erl
new file mode 100644
index 0000000000..844c7eddf3
--- /dev/null
+++ b/lib/wx/examples/demo/ex_canvas.erl
@@ -0,0 +1,177 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(ex_canvas).
+
+-behaviour(wx_object).
+
+%% Client API
+-export([start/1]).
+
+%% wx_object callbacks
+-export([init/1, terminate/2, code_change/3,
+ handle_info/2, handle_call/3, handle_event/2, handle_sync_event/3]).
+
+-include_lib("wx/include/wx.hrl").
+
+-record(state,
+ {
+ parent,
+ config,
+ canvas,
+ bitmap
+ }).
+
+start(Config) ->
+ wx_object:start_link(?MODULE, Config, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init(Config) ->
+ wx:batch(fun() -> do_init(Config) end).
+
+do_init(Config) ->
+ Parent = proplists:get_value(parent, Config),
+ Panel = wxPanel:new(Parent, []),
+
+ %% Setup sizers
+ MainSizer = wxBoxSizer:new(?wxVERTICAL),
+ Sizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "Various shapes"}]),
+
+ Button = wxButton:new(Panel, ?wxID_ANY, [{label, "Redraw"}]),
+
+ Canvas = wxPanel:new(Panel, [{style, ?wxFULL_REPAINT_ON_RESIZE}]),
+
+ wxPanel:connect(Canvas, paint, [callback]),
+ wxPanel:connect(Canvas, size),
+ wxPanel:connect(Button, command_button_clicked),
+
+ %% Add to sizers
+ wxSizer:add(Sizer, Button, [{border, 5}, {flag, ?wxALL}]),
+ wxSizer:addSpacer(Sizer, 5),
+ wxSizer:add(Sizer, Canvas, [{flag, ?wxEXPAND},
+ {proportion, 1}]),
+
+ wxSizer:add(MainSizer, Sizer, [{flag, ?wxEXPAND},
+ {proportion, 1}]),
+
+ wxPanel:setSizer(Panel, MainSizer),
+ wxSizer:layout(MainSizer),
+
+ {W,H} = wxPanel:getSize(Canvas),
+ Bitmap = wxBitmap:new(erlang:max(W,30),erlang:max(30,H)),
+
+ {Panel, #state{parent=Panel, config=Config,
+ canvas = Canvas, bitmap = Bitmap}}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Sync event from callback events, paint event must be handled in callbacks
+%% otherwise nothing will be drawn on windows.
+handle_sync_event(#wx{event = #wxPaint{}}, _wxObj,
+ #state{canvas=Canvas, bitmap=Bitmap}) ->
+ DC = wxPaintDC:new(Canvas),
+ redraw(DC, Bitmap),
+ wxPaintDC:destroy(DC),
+ ok.
+
+%% Async Events are handled in handle_event as in handle_info
+handle_event(#wx{event = #wxCommand{type = command_button_clicked}},
+ State = #state{}) ->
+ Image = wxImage:new("image.jpg"),
+ Image2 = wxImage:scale(Image, wxImage:getWidth(Image) div 3,
+ wxImage:getHeight(Image) div 3),
+ Bmp = wxBitmap:new(Image2),
+ wxImage:destroy(Image),
+ wxImage:destroy(Image2),
+ {W,H} = wxPanel:getSize(State#state.canvas),
+ Positions = lists:map(fun(_) ->
+ get_pos(W,H)
+ end, lists:seq(1,(W+H) div 20)),
+ Fun = fun(DC) ->
+ wxDC:clear(DC),
+ lists:foreach(fun({X,Y}=Pos) ->
+ wxDC:setBrush(DC, ?wxTRANSPARENT_BRUSH),
+ wxDC:setPen(DC, wxPen:new(?wxBLACK, [{width, 2}])),
+ case X rem 6 of
+ 0 -> wxDC:drawBitmap(DC, Bmp, Pos);
+ 1 -> wxDC:setBrush(DC, ?wxRED_BRUSH),
+ wxDC:drawRectangle(DC, Pos, {20,20});
+ 2 -> wxDC:setBrush(DC, ?wxBLUE_BRUSH),
+ wxDC:drawCircle(DC, {X+10, Y+10}, 15);
+ 3 -> wxDC:setPen(DC, wxPen:new({200,200,0,255}, [{width, 4}])),
+ wxDC:drawLine(DC, Pos, get_pos(W,H));
+ 4 -> wxDC:setBrush(DC, ?wxGREEN_BRUSH),
+ wxDC:drawEllipse(DC, Pos, {60,20});
+ _ -> wxDC:drawLabel(DC, "Erlang /", {X,Y,60,20}),
+ wxDC:drawRotatedText(DC, "OTP", {X+60,Y}, 340.0)
+ end
+ end, Positions)
+ end,
+ draw(State#state.canvas, State#state.bitmap, Fun),
+ wxBitmap:destroy(Bmp),
+ {noreply, State};
+handle_event(#wx{event = #wxSize{size={W,H}}},
+ State = #state{bitmap=Prev}) ->
+ Bitmap = wxBitmap:new(W,H),
+ draw(State#state.canvas, Bitmap, fun(DC) -> wxDC:clear(DC) end),
+ wxBitmap:destroy(Prev),
+ {noreply, State#state{bitmap = Bitmap}};
+handle_event(Ev = #wx{}, State = #state{}) ->
+ demo:format(State#state.config, "Got Event ~p\n", [Ev]),
+ {noreply, State}.
+
+%% Callbacks handled as normal gen_server callbacks
+handle_info(Msg, State) ->
+ demo:format(State#state.config, "Got Info ~p\n", [Msg]),
+ {noreply, State}.
+
+handle_call(Msg, _From, State) ->
+ demo:format(State#state.config, "Got Call ~p\n", [Msg]),
+ {reply,{error, nyi}, State}.
+
+code_change(_, _, State) ->
+ {stop, ignore, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Local functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+%% Buffered makes it all appear on the screen at the same time
+draw(Canvas, Bitmap, Fun) ->
+ MemoryDC = wxMemoryDC:new(Bitmap),
+ Fun(MemoryDC),
+
+ CDC = wxWindowDC:new(Canvas),
+ wxDC:blit(CDC, {0,0},
+ {wxBitmap:getWidth(Bitmap), wxBitmap:getHeight(Bitmap)},
+ MemoryDC, {0,0}),
+ wxWindowDC:destroy(CDC),
+ wxMemoryDC:destroy(MemoryDC).
+
+redraw(DC, Bitmap) ->
+ MemoryDC = wxMemoryDC:new(Bitmap),
+ wxDC:blit(DC, {0,0},
+ {wxBitmap:getWidth(Bitmap), wxBitmap:getHeight(Bitmap)},
+ MemoryDC, {0,0}),
+ wxMemoryDC:destroy(MemoryDC).
+
+get_pos(W,H) ->
+ {random:uniform(W), random:uniform(H)}.
diff --git a/lib/wx/examples/demo/ex_canvas_paint.erl b/lib/wx/examples/demo/ex_canvas_paint.erl
new file mode 100644
index 0000000000..38d6b62f1d
--- /dev/null
+++ b/lib/wx/examples/demo/ex_canvas_paint.erl
@@ -0,0 +1,248 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(ex_canvas_paint).
+
+-behaviour(wx_object).
+
+%% Client API
+-export([start/1]).
+
+%% wx_object callbacks
+-export([init/1, terminate/2, code_change/3,
+ handle_info/2, handle_call/3, handle_event/2, handle_sync_event/3]).
+
+-include_lib("wx/include/wx.hrl").
+
+-record(state,
+ {
+ parent,
+ config,
+ canvas,
+ pen,
+ brush,
+ old_pos,
+ bitmap
+ }).
+
+start(Config) ->
+ wx_object:start_link(?MODULE, Config, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init(Config) ->
+ wx:batch(fun() -> do_init(Config) end).
+
+do_init(Config) ->
+ Parent = proplists:get_value(parent, Config),
+ Panel = wxPanel:new(Parent, []),
+
+ %% Setup sizers
+ MainSizer = wxBoxSizer:new(?wxVERTICAL),
+ Sizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "wxDC"}]),
+
+ %% Create the window to paint on and make it repaint the whole window on resize
+ Canvas = wxPanel:new(Panel, [{style, ?wxFULL_REPAINT_ON_RESIZE}]),
+ wxPanel:setToolTip(Canvas,
+ "Left-click and hold to draw something - release to stop drawing.\n"
+ "Middle-click to fill with pink\n"
+ "Middle-dclick to fill with white.\n"
+ "Right-click to clear."),
+
+ %% Create a wxPen and a WxBrush and set its colors to draw with
+ Brush = wxBrush:new(?wxWHITE),
+ Pen = wxPen:new(?wxBLACK, [{width, 2}]),
+
+ PrintButton = wxButton:new(Panel, ?wxID_ANY, [{label, "Print"}]),
+
+ Bitmap = wxBitmap:new(30,30),
+
+ %% Add to sizers
+ wxSizer:add(Sizer, Canvas, [{flag, ?wxEXPAND},
+ {proportion, 1}]),
+
+ wxSizer:add(MainSizer, PrintButton, []),
+ wxSizer:add(MainSizer, Sizer, [{flag, ?wxEXPAND},
+ {proportion, 1}]),
+
+ wxPanel:connect(PrintButton, command_button_clicked),
+ wxPanel:connect(Canvas, paint, [callback]),
+ wxPanel:connect(Canvas, size),
+ wxPanel:connect(Canvas, left_down),
+ wxPanel:connect(Canvas, left_dclick),
+ wxPanel:connect(Canvas, left_up),
+ wxPanel:connect(Canvas, right_down),
+ wxPanel:connect(Canvas, middle_down),
+ wxPanel:connect(Canvas, middle_dclick),
+ wxPanel:setSizer(Panel, MainSizer),
+ wxSizer:layout(MainSizer),
+ {Panel, #state{parent=Panel, config=Config,
+ canvas = Canvas, pen = Pen,
+ brush = Brush, bitmap = Bitmap}}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Sync event from callback events, paint event must be handled in callbacks
+%% otherwise nothing will be drawn on windows.
+handle_sync_event(#wx{event = #wxPaint{}}, _wxObj, #state{canvas=Canvas, bitmap=Bitmap}) ->
+ DC = wxPaintDC:new(Canvas),
+ redraw(DC, Bitmap),
+ wxPaintDC:destroy(DC),
+ ok.
+
+%% Print what's drawn
+handle_event(#wx{event = #wxCommand{type = command_button_clicked}},
+ State = #state{bitmap=Bitmap}) ->
+ PD = wxPrintData:new(),
+ PDD = wxPrintDialogData:new(PD),
+ PSDD = wxPageSetupDialogData:new(PD),
+ Fun =
+ fun(This,_Page) ->
+ MX = MY = 500,
+ wxPrintout:fitThisSizeToPageMargins(This, {MX,MY}, PSDD),
+ {_X,_Y,W,H} = wxPrintout:getLogicalPageMarginsRect(This, PSDD),
+ wxPrintout:offsetLogicalOrigin(This,(W-MX) div 2, (H-MY) div 2),
+ DC = wxPrintout:getDC(This),
+ redraw(DC, Bitmap),
+ true
+ end,
+ Printout1 = wxPrintout:new("Print", Fun,
+ [{getPageInfo, fun getPageInfo/1}]),
+ Printout2 = wxPrintout:new("Print", Fun,
+ [{getPageInfo, fun getPageInfo/1}]),
+ Preview = wxPrintPreview:new(Printout1, [{printoutForPrinting,Printout2},{data,PDD}]),
+ case wxPrintPreview:isOk(Preview) of
+ true ->
+ Env = wx:get_env(),
+ spawn_link(fun() ->
+ wx:set_env(Env),
+ PF = wxPreviewFrame:new(Preview, State#state.parent, []),
+ wxPreviewFrame:centre(PF, [{dir, ?wxBOTH}]),
+ wxPreviewFrame:initialize(PF),
+ wxPreviewFrame:centre(PF),
+ wxPreviewFrame:show(PF)
+ end);
+ false ->
+ io:format("Could not create preview window.\n"
+ "Perhaps your current printer is not set correctly?~n", []),
+ wxPrintPreview:destroy(Preview)
+ end,
+ {noreply, State#state{}};
+%% Draw a line
+handle_event(#wx{event = #wxMouse{type = motion, x = X, y = Y}},
+ State = #state{canvas = Canvas, pen = Pen, brush = Brush}) ->
+ Fun =
+ fun(DC) ->
+ wxDC:setPen(DC, Pen),
+ wxBrush:setColour(Brush, ?wxBLACK),
+ wxDC:setBrush(DC, Brush),
+ wxDC:drawLine(DC, {X,Y}, State#state.old_pos)
+ end,
+ draw(Canvas,State#state.bitmap, Fun),
+ {noreply, State#state{old_pos = {X,Y}}};
+%% Resize event
+handle_event(#wx{event = #wxSize{size = {W,H}}}, State = #state{bitmap=Prev}) ->
+ wxBitmap:destroy(Prev),
+ Bitmap = wxBitmap:new(W,H),
+ draw(State#state.canvas, Bitmap, fun(DC) -> wxDC:clear(DC) end),
+ {noreply, State#state{bitmap=Bitmap}};
+handle_event(#wx{event = #wxMouse{type = left_dclick,x = X,y = Y}}, State = #state{}) ->
+ wxPanel:connect(State#state.canvas, motion),
+ {noreply, State#state{old_pos = {X,Y}}};
+handle_event(#wx{event = #wxMouse{type = left_down,x = X,y = Y}}, State = #state{}) ->
+ wxPanel:connect(State#state.canvas, motion),
+ {noreply, State#state{old_pos = {X,Y}}};
+%% Fill with pink color
+handle_event(#wx{event = #wxMouse{type = middle_down,x = X, y =Y}}, State = #state{}) ->
+ case os:type() of
+ {_, darwin} ->
+ io:format("Fill doesn't work on Darwin ~n",[]);
+ _ ->
+ ok
+ end,
+ Fun =
+ fun(DC) ->
+ wxBrush:setColour(State#state.brush, {255,125,255,255}),
+ wxDC:setBrush(DC, State#state.brush),
+ wxDC:floodFill(DC, {X,Y}, ?wxBLACK, [{style, ?wxFLOOD_BORDER}])
+ end,
+
+ draw(State#state.canvas, State#state.bitmap, Fun),
+ {noreply, State};
+%% Fill with white color
+handle_event(#wx{event = #wxMouse{type = middle_dclick,x = X, y =Y}}, State = #state{}) ->
+ Fun =
+ fun(DC) ->
+ wxBrush:setColour(State#state.brush, ?wxWHITE),
+ wxDC:setBrush(DC, State#state.brush),
+ wxDC:floodFill(DC, {X,Y}, ?wxBLACK, [{style, ?wxFLOOD_BORDER}])
+ end,
+
+ draw(State#state.canvas, State#state.bitmap,Fun),
+ {noreply, State};
+handle_event(#wx{event = #wxMouse{type = left_up}}, State = #state{}) ->
+ wxPanel:disconnect(State#state.canvas, motion),
+ {noreply, State};
+%% Clear the DC
+handle_event(#wx{event = #wxMouse{type = right_down}}, State = #state{}) ->
+ draw(State#state.canvas, State#state.bitmap, fun(DC) -> wxDC:clear(DC) end),
+ {noreply, State}.
+
+%% Callbacks handled as normal gen_server callbacks
+handle_info(Msg, State) ->
+ demo:format(State#state.config, "Got Info ~p\n", [Msg]),
+ {noreply, State}.
+
+handle_call(Msg, _From, State) ->
+ demo:format(State#state.config, "Got Call ~p\n", [Msg]),
+ {reply,{error, nyi}, State}.
+
+code_change(_, _, State) ->
+ {stop, ignore, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Local functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+draw(Canvas, Bitmap, Fun) ->
+ MemoryDC = wxMemoryDC:new(Bitmap),
+ CDC = wxClientDC:new(Canvas),
+
+ Fun(MemoryDC),
+
+ wxDC:blit(CDC, {0,0},
+ {wxBitmap:getWidth(Bitmap), wxBitmap:getHeight(Bitmap)},
+ MemoryDC, {0,0}),
+
+ wxClientDC:destroy(CDC),
+ wxMemoryDC:destroy(MemoryDC).
+
+redraw(DC, Bitmap) ->
+ MemoryDC = wxMemoryDC:new(Bitmap),
+
+ wxDC:blit(DC, {0,0},
+ {wxBitmap:getWidth(Bitmap), wxBitmap:getHeight(Bitmap)},
+ MemoryDC, {0,0}),
+
+ wxMemoryDC:destroy(MemoryDC).
+
+
+getPageInfo(_This) ->
+ {1,1,1,1}.
diff --git a/lib/wx/examples/demo/ex_choices.erl b/lib/wx/examples/demo/ex_choices.erl
new file mode 100644
index 0000000000..75f8d22493
--- /dev/null
+++ b/lib/wx/examples/demo/ex_choices.erl
@@ -0,0 +1,159 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(ex_choices).
+
+-behaviour(wx_object).
+
+-export([start/1, init/1, terminate/2, code_change/3,
+ handle_info/2, handle_call/3, handle_event/2]).
+
+-include_lib("wx/include/wx.hrl").
+
+-record(state,
+ {
+ parent,
+ config,
+ list_box
+ }).
+
+
+start(Config) ->
+ wx_object:start_link(?MODULE, Config, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init(Config) ->
+ wx:batch(fun() -> do_init(Config) end).
+
+do_init(Config) ->
+ Parent = proplists:get_value(parent, Config),
+ Panel = wxScrolledWindow:new(Parent, []),
+
+ %% Setup sizers
+ MainSizer = wxBoxSizer:new(?wxVERTICAL),
+ ListBoxSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "wxListBox"}]),
+
+ ChoiceSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "wxChoice"}]),
+ SpinSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "wxSpinCtrl"}]),
+ ComboSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "wxComboBox"}]),
+ Sizer = wxBoxSizer:new(?wxHORIZONTAL),
+ Sizer3 = wxBoxSizer:new(?wxHORIZONTAL),
+
+ Choices = ["one","two","three",
+ "four","five","six",
+ "seven","eight","nine",
+ "ten", "eleven", "twelve"],
+
+ %% Create a wxListBox that uses multiple selection
+ ListBox = wxListBox:new(Panel, 1, [{size, {-1,100}},
+ {choices, ["Multiple selection"|Choices]},
+ {style, ?wxLB_MULTIPLE}]),
+ wxListBox:setToolTip(ListBox, "A wxListBox with multiple selection"),
+
+ %% Create a wxListBox that uses single selection
+ ListBox2 = wxListBox:new(Panel, 2, [{size, {-1,100}},
+ {choices, ["Single selection"|Choices]},
+ {style, ?wxLB_SINGLE}]),
+ wxListBox:setToolTip(ListBox2, "A wxListBox with single selection"),
+
+ %% Create a wxChoice
+ Choice = wxChoice:new(Panel, 4, [{choices, Choices}]),
+ wxChoice:setToolTip(Choice, "A wxChoice"),
+
+ %% Create a wxSpinCtrl with range between 0 and 100
+ SpinCtrl = wxSpinCtrl:new(Panel, []),
+ wxSpinCtrl:setRange(SpinCtrl, 0, 100),
+ wxSpinCtrl:setToolTip(SpinCtrl, "A wxSpinCtrl with range from 0 to 100"),
+
+ %% Create a wxComboBox and set the value to "Default value"
+ ComboBox = wxComboBox:new(Panel, 5, [{choices, Choices}]),
+ wxComboBox:setToolTip(ComboBox, "A wxComboBox"),
+
+
+ wxChoice:connect(Choice,command_choice_selected),
+ wxSpinCtrl:connect(SpinCtrl,command_spinctrl_updated),
+ wxComboBox:connect(ComboBox, command_combobox_selected),
+
+
+ %% Add to sizers
+ Options = [{border,4}, {flag, ?wxALL}],
+ wxSizer:add(Sizer, ListBox, Options),
+ wxSizer:add(Sizer, ListBox2, Options),
+
+ wxSizer:add(ChoiceSizer, Choice, Options),
+ wxSizer:add(SpinSizer, SpinCtrl, Options),
+ wxSizer:add(Sizer3, ChoiceSizer, []),
+ wxSizer:add(Sizer3, SpinSizer, [{border, 4}, {flag, ?wxLEFT}]),
+
+ wxSizer:add(ComboSizer, ComboBox, Options),
+
+ wxSizer:add(ListBoxSizer, Sizer, Options),
+ wxSizer:add(MainSizer, ListBoxSizer, Options),
+ wxSizer:add(MainSizer, Sizer3, Options),
+ wxSizer:add(MainSizer, ComboSizer, Options),
+
+ wxScrolledWindow:setScrollRate(Panel, 5, 5),
+ wxPanel:setSizer(Panel, MainSizer),
+ {Panel, #state{parent=Panel, config=Config,
+ list_box = ListBox}}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Async Events are handled in handle_event as in handle_info
+handle_event(#wx{obj = ComboBox,
+ event = #wxCommand{type = command_combobox_selected}},
+ State = #state{}) ->
+ Value = wxComboBox:getValue(ComboBox),
+ demo:format(State#state.config,"Selected wxComboBox ~p\n",[Value]),
+ {noreply, State};
+handle_event(#wx{event = #wxCommand{type = command_choice_selected,
+ cmdString = Value}},
+ State = #state{}) ->
+ demo:format(State#state.config,"Selected wxChoice ~p\n",[Value]),
+ {noreply, State};
+handle_event(#wx{event = #wxSpin{type = command_spinctrl_updated,
+ commandInt = Int}},
+ State = #state{}) ->
+ demo:format(State#state.config,"wxSpinCtrl changed to ~p\n",[Int]),
+ {noreply, State};
+handle_event(Ev = #wx{}, State = #state{}) ->
+ demo:format(State#state.config,"Got Event ~p\n",[Ev]),
+ {noreply, State}.
+
+%% Callbacks handled as normal gen_server callbacks
+handle_info(Msg, State) ->
+ demo:format(State#state.config, "Got Info ~p\n",[Msg]),
+ {noreply, State}.
+
+handle_call(Msg, _From, State) ->
+ demo:format(State#state.config,"Got Call ~p\n",[Msg]),
+ {reply, {error,nyi}, State}.
+
+code_change(_, _, State) ->
+ {stop, ignore, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Local functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
diff --git a/lib/wx/examples/demo/ex_cursor.erl b/lib/wx/examples/demo/ex_cursor.erl
new file mode 100644
index 0000000000..322bdcbb6c
--- /dev/null
+++ b/lib/wx/examples/demo/ex_cursor.erl
@@ -0,0 +1,180 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(ex_cursor).
+
+-behaviour(wx_object).
+
+%% Client API
+-export([start/1]).
+
+%% wx_object callbacks
+-export([init/1, terminate/2, code_change/3,
+ handle_info/2, handle_call/3, handle_event/2]).
+
+-include_lib("wx/include/wx.hrl").
+
+-record(state,
+ {
+ parent,
+ config,
+ cursors,
+ win
+ }).
+
+start(Config) ->
+ wx_object:start_link(?MODULE, Config, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init(Config) ->
+ wx:batch(fun() -> do_init(Config) end).
+
+do_init(Config) ->
+ Parent = proplists:get_value(parent, Config),
+ Panel = wxScrolledWindow:new(Parent, []),
+
+ %% Setup sizers
+ MainSizer = wxBoxSizer:new(?wxVERTICAL),
+ MiscSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "Misc"}]),
+ StaticBoxSizer = wxStaticBoxSizer:new(?wxHORIZONTAL, Panel,
+ [{label, "Test the cursor here"}]),
+ CursorSizer = wxBoxSizer:new(?wxHORIZONTAL),
+
+ CursorLabels = [Cursor || {Cursor, _} <- cursors()],
+ StockCursors = wxRadioBox:new(Panel, ?wxID_ANY, "Stock cursors",
+ ?wxDefaultPosition,
+ ?wxDefaultSize, CursorLabels,
+ [{majorDim, 2},
+ {style, ?wxHORIZONTAL}]),
+
+ Fun = fun(Item, Int) ->
+ CursorId = proplists:get_value(Item, cursors()),
+ Cursor = wxCursor:new(CursorId),
+ case wxCursor:ok(Cursor) of
+ true ->
+ ok;
+ false ->
+ wxRadioBox:enable(StockCursors, Int, [{enable, false}])
+ end,
+ Int+1
+ end,
+ wx:foldl(Fun,0, CursorLabels),
+
+
+
+
+ Win = wxWindow:new(Panel, ?wxID_ANY, [{size, {300,300}}]),
+
+ ToggleButton = wxToggleButton:new(Panel, ?wxID_ANY, "Begin busy cursor", []),
+
+ %% Add to sizers
+ wxSizer:add(CursorSizer, StockCursors),
+ wxSizer:add(StaticBoxSizer, Win),
+ wxSizer:add(CursorSizer, StaticBoxSizer),
+ wxSizer:add(MiscSizer, ToggleButton),
+
+ wxSizer:add(MainSizer, CursorSizer),
+ wxSizer:add(MainSizer, MiscSizer),
+
+ wxToggleButton:connect(ToggleButton, command_togglebutton_clicked, []),
+ wxRadioBox:connect(StockCursors, command_radiobox_selected, []),
+ wxScrolledWindow:setScrollRate(Panel, 5,5),
+ wxPanel:setSizer(Panel, MainSizer),
+ {Panel, #state{parent=Panel, config=Config,
+ win = Win}}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Async Events are handled in handle_event as in handle_info
+handle_event(#wx{event = #wxCommand{type = command_radiobox_selected,
+ cmdString = String}},
+ State = #state{}) ->
+ wxWindow:refresh(State#state.parent),
+ CursorId = proplists:get_value(String, cursors()),
+ Cursor = wxCursor:new(CursorId),
+ wxWindow:setCursor(State#state.win, Cursor),
+ {noreply, State#state{}};
+handle_event(#wx{obj = ToggleButton,
+ event = #wxCommand{type = command_togglebutton_clicked,
+ commandInt = Int}},
+ State = #state{}) ->
+ case Int of
+ 1 ->
+ wx_misc:beginBusyCursor(),
+ wxToggleButton:setLabel(ToggleButton, "End busy cursor");
+ 0 ->
+ wx_misc:endBusyCursor(),
+ wxToggleButton:setLabel(ToggleButton, "Begin busy cursor")
+ end,
+ {noreply, State};
+handle_event(Ev = #wx{}, State = #state{}) ->
+ demo:format(State#state.config, "Got Event ~p\n", [Ev]),
+ {noreply, State}.
+
+%% Callbacks handled as normal gen_server callbacks
+handle_info(Msg, State) ->
+ demo:format(State#state.config, "Got Info ~p\n", [Msg]),
+ {noreply, State}.
+
+handle_call(Msg, _From, State) ->
+ demo:format(State#state.config, "Got Call ~p\n", [Msg]),
+ {reply,{error, nyi}, State}.
+
+code_change(_, _, State) ->
+ {stop, ignore, State}.
+
+terminate(_Reason, _State) ->
+ case wx_misc:isBusy() of
+ true ->
+ wx_misc:endBusyCursor();
+ false ->
+ ignore
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Local functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+cursors() ->
+ [{"Arrow", ?wxCURSOR_ARROW},
+ {"Right arrow", ?wxCURSOR_RIGHT_ARROW},
+ {"Blank", ?wxCURSOR_BLANK},
+ {"Bullseye", ?wxCURSOR_BULLSEYE},
+ {"Char", ?wxCURSOR_CHAR},
+ {"Cross", ?wxCURSOR_CROSS},
+ {"Hand", ?wxCURSOR_HAND},
+ {"I-beam", ?wxCURSOR_IBEAM},
+ {"Left button", ?wxCURSOR_LEFT_BUTTON},
+ {"Magnifier", ?wxCURSOR_MAGNIFIER},
+ {"Middle button", ?wxCURSOR_MIDDLE_BUTTON},
+ {"No entry", ?wxCURSOR_NO_ENTRY},
+ {"Paint brush", ?wxCURSOR_PAINT_BRUSH},
+ {"Pencil", ?wxCURSOR_PENCIL},
+ {"Point left", ?wxCURSOR_POINT_LEFT},
+ {"Point right", ?wxCURSOR_POINT_RIGHT},
+ {"Question arrow", ?wxCURSOR_QUESTION_ARROW},
+ {"Right button", ?wxCURSOR_RIGHT_BUTTON},
+ {"Size NE-SW", ?wxCURSOR_SIZENESW},
+ {"Size N-S", ?wxCURSOR_SIZENS},
+ {"Size NW-SE", ?wxCURSOR_SIZENWSE},
+ {"Size W-E", ?wxCURSOR_SIZEWE},
+ {"Sizing", ?wxCURSOR_SIZING},
+ {"Spraycan", ?wxCURSOR_SPRAYCAN},
+ {"Wait", ?wxCURSOR_WAIT},
+ {"Watch", ?wxCURSOR_WATCH},
+ {"Arrow wait", ?wxCURSOR_ARROWWAIT}].
diff --git a/lib/wx/examples/demo/ex_dialogs.erl b/lib/wx/examples/demo/ex_dialogs.erl
new file mode 100644
index 0000000000..020e9eeb14
--- /dev/null
+++ b/lib/wx/examples/demo/ex_dialogs.erl
@@ -0,0 +1,171 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(ex_dialogs).
+
+-behaviour(wx_object).
+
+%% Client API
+-export([start/1]).
+
+%% wx_object callbacks
+-export([init/1, terminate/2, code_change/3,
+ handle_info/2, handle_call/3, handle_event/2]).
+
+-include_lib("wx/include/wx.hrl").
+
+-record(state,
+ {
+ parent,
+ config,
+ dialogs,
+ choices
+ }).
+
+
+start(Config) ->
+ wx_object:start_link(?MODULE, Config, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init(Config) ->
+ wx:batch(fun() -> do_init(Config) end).
+
+do_init(Config) ->
+ Parent = proplists:get_value(parent, Config),
+ Panel = wxScrolledWindow:new(Parent, []),
+ wxScrolledWindow:setScrollRate(Panel, 5, 5),
+
+ %% Setup sizers
+ MainSizer = wxBoxSizer:new(?wxVERTICAL),
+ Sizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "Dialogs"}]),
+
+ Buttons =
+ [wxButton:new(Panel, 1, [{label, "wxDirDialog"}]),
+ wxButton:new(Panel, 2, [{label, "wxFileDialog"}]),
+ wxButton:new(Panel, 3, [{label, "wxColourDialog"}]),
+ wxButton:new(Panel, 4, [{label, "wxMessageDialog"}]),
+ wxButton:new(Panel, 5, [{label, "wxTextEntryDialog"}]),
+ wxButton:new(Panel, 6, [{label, "wxSingleChoiceDialog"}]),
+ wxButton:new(Panel, 7, [{label, "wxMultiChoiceDialog"}]),
+ wxButton:new(Panel, 10, [{label, "wxFontDialog"}])],
+
+ Choices = ["Orange","Banana", "Apple", "Lemon", "Pear",
+ "Carrot", "Potato", "Peach", "Tomato", "Grape",
+ "Pineapple", "Blueberry"],
+ Dialogs = [{wxDirDialog, [Panel, []]},
+ {wxFileDialog, [Panel, []]},
+ {wxColourDialog, [Panel, []]},
+ {wxSingleChoiceDialog, [Panel, "wxSingleChoiceDialog\n"
+ "Feel free to pick one of "
+ "these items !", "Caption",
+ Choices]},
+ {wxMultiChoiceDialog, [Panel, "wxMultiChoiceDialog\n"
+ "Feel free to pick one of "
+ "these items !", "Caption",
+ Choices]},
+ {wxMessageDialog, [Panel, "This is a wxMessageDialog !"]},
+ {wxTextEntryDialog, [Panel, "This is a wxTextEntryDialog !",
+ [{value, "Erlang is the best !"}]]},
+ {wxFontDialog, [get_parent(Parent), wxFontData:new()]}],
+
+ %% Add to sizers
+ Fun = fun(Button) ->
+ Label = list_to_atom(wxButton:getLabel(Button)),
+ wxSizer:add(Sizer, Button, [{border, 4}, {flag, ?wxALL bor ?wxEXPAND}]),
+ wxButton:connect(Button, command_button_clicked, [{userData, Label}])
+ end,
+ wx:foreach(Fun, Buttons),
+
+ wxSizer:add(MainSizer, Sizer),
+
+ wxPanel:setSizer(Panel, MainSizer),
+ {Panel, #state{parent=Panel, config=Config,
+ dialogs = Dialogs, choices = Choices}}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Async Events are handled in handle_event as in handle_info
+handle_event(#wx{event = #wxCommand{type = command_button_clicked},
+ userData = Module},
+ State = #state{dialogs = Dialogs, choices = Choices}) ->
+ Args = proplists:get_value(Module, Dialogs),
+ Dialog = apply(Module, new, Args),
+
+ case Module:showModal(Dialog) of
+ ?wxID_OK ->
+ case Module of
+ wxColourDialog ->
+ Colour = wxColourData:getColour(Module:getColourData(Dialog)),
+ demo:format(State#state.config, "Colour: ~p\n", [Colour]);
+ wxSingleChoiceDialog ->
+ Selection = Module:getStringSelection(Dialog),
+ demo:format(State#state.config, "Selection: ~p\n", [Selection]);
+ wxTextEntryDialog ->
+ Value = Module:getValue(Dialog),
+ demo:format(State#state.config, "Value: ~p\n", [Value]);
+ wxFontDialog ->
+ Font = wxFontData:getChosenFont(Module:getFontData(Dialog)),
+ FontDesc = wxFont:getNativeFontInfoUserDesc(Font),
+ demo:format(State#state.config,
+ "Font: ~p\n",
+ [FontDesc]);
+ wxFileDialog ->
+ demo:format(State#state.config, "File path: ~p\n", [Module:getPath(Dialog)]);
+ wxDirDialog ->
+ demo:format(State#state.config, "Dir path: ~p\n", [Module:getPath(Dialog)]);
+ wxMultiChoiceDialog ->
+ Selected = [lists:nth(Num+1, Choices) ||
+ Num <- Module:getSelections(Dialog)],
+ demo:format(State#state.config, "Selections: ~p\n", [Selected]);
+ wxMessageDialog ->
+ ok
+ end;
+ ?wxID_CANCEL -> cancel;
+ Any -> io:format("Any: ~p\n", [Any])
+ end,
+ Module:destroy(Dialog),
+ {noreply, State};
+handle_event(Ev = #wx{}, State = #state{}) ->
+ demo:format(State#state.config, "Got Event ~p\n", [Ev]),
+ {noreply, State}.
+
+%% Callbacks handled as normal gen_server callbacks
+handle_info(Msg, State) ->
+ demo:format(State#state.config, "Got Info ~p\n", [Msg]),
+ {noreply, State}.
+
+handle_call(Msg, _From, State) ->
+ demo:format(State#state.config, "Got Call ~p\n", [Msg]),
+ {reply,{error, nyi}, State}.
+
+code_change(_, _, State) ->
+ {stop, ignore, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Local functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+get_parent(Window) ->
+ Parent = wxWindow:getParent(Window),
+ case wx:is_null(Parent) of
+ false -> get_parent(Parent);
+ true -> Window
+ end.
diff --git a/lib/wx/examples/demo/ex_frame_utils.erl b/lib/wx/examples/demo/ex_frame_utils.erl
new file mode 100644
index 0000000000..3064c9f3b7
--- /dev/null
+++ b/lib/wx/examples/demo/ex_frame_utils.erl
@@ -0,0 +1,193 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(ex_frame_utils).
+
+-behaviour(wx_object).
+
+%% Client API
+-export([start/1]).
+
+%% wx_object callbacks
+-export([init/1, terminate/2, code_change/3,
+ handle_info/2, handle_call/3, handle_event/2]).
+
+-include_lib("wx/include/wx.hrl").
+
+-record(state,
+ {
+ parent,
+ config
+ }).
+
+start(Config) ->
+ wx_object:start_link(?MODULE, Config, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init(Config) ->
+ wx:batch(fun() -> do_init(Config) end).
+
+do_init(Config) ->
+ Parent = proplists:get_value(parent, Config),
+ Panel = wxPanel:new(Parent, []),
+
+ %% Setup sizers
+ MainSizer = wxBoxSizer:new(?wxVERTICAL),
+ Sizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "Utilities"}]),
+
+ Labels = [{"Open window",1}, {"Open wxMiniFrame",2}, {"Open erlang.org",3}],
+ Buttons = [wxButton:new(Panel, Id, [{label, L}])|| {L,Id} <- Labels],
+
+ %% Add to sizers
+ [wxSizer:add(Sizer, Button) || Button <- Buttons],
+ wxPanel:connect(Panel, command_button_clicked),
+ wxSizer:add(MainSizer, Sizer),
+ wxPanel:setSizer(Panel, MainSizer),
+ {Panel, #state{parent=Panel, config=Config}}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Async Events are handled in handle_event as in handle_info
+handle_event(#wx{id = Id,
+ event = #wxCommand{type = command_menu_selected}},
+ State = #state{}) ->
+ case Id of
+ ?wxID_NEW -> demo:format(State#state.config, "New\n", []);
+ ?wxID_OPEN -> demo:format(State#state.config, "Open\n", []);
+ ?wxID_COPY -> demo:format(State#state.config, "Copy\n", []);
+ ?wxID_PASTE -> demo:format(State#state.config, "Paste\n", []);
+ ?wxID_HELP ->
+ wx_misc:launchDefaultBrowser("http://erlang.org/doc/apps/wx/part_frame.html");
+ _ -> ignore
+ end,
+ {noreply, State};
+handle_event(#wx{id = Id,
+ event = #wxCommand{type = command_button_clicked}},
+ State = #state{}) ->
+ case Id of
+ 1 -> new_win(State#state.parent);
+ 2 -> new_mini_frame(State#state.parent);
+ 3 -> wx_misc:launchDefaultBrowser("http://erlang.org/");
+ _ -> ignore
+ end,
+ {noreply, State};
+handle_event(#wx{userData = StatusBar,
+ event = #wxMouse{type = motion, x = X, y = Y}},
+ State) ->
+ wxStatusBar:setStatusText(StatusBar, io_lib:format("Mouse position: ~p", [{X,Y}]),
+ [{number, 1}]),
+ {noreply, State}.
+
+%% Callbacks handled as normal gen_server callbacks
+handle_info(Msg, State) ->
+ demo:format(State#state.config, "Got Info ~p\n", [Msg]),
+ {noreply, State}.
+
+handle_call(Msg, _From, State) ->
+ demo:format(State#state.config, "Got Call ~p\n", [Msg]),
+ {reply,{error, nyi}, State}.
+
+code_change(_, _, State) ->
+ {stop, ignore, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Local functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+new_win(Panel) ->
+ Frame = wxFrame:new(Panel, ?wxID_ANY, "Utilities", [{style,
+ ?wxCAPTION bor
+ ?wxCLIP_CHILDREN bor
+ ?wxCLOSE_BOX bor
+ ?wxFRAME_FLOAT_ON_PARENT bor
+ %%?wxFRAME_NO_TASKBAR bor
+ ?wxMAXIMIZE_BOX bor
+ ?wxMINIMIZE_BOX bor
+ ?wxRESIZE_BORDER bor
+ %%?wxSTAY_ON_TOP bor
+ ?wxSYSTEM_MENU
+ }]),
+
+ %% Setup wxMenuBar
+ MB = wxMenuBar:new(),
+ File = wxMenu:new([]),
+ Help = wxMenu:new([]),
+ Mbar = wxMenu:new([]),
+ wxMenu:append(File, ?wxID_NEW, "New"),
+ wxMenu:append(File, ?wxID_OPEN, "Open"),
+ wxMenu:appendSeparator(File),
+ wxMenu:append(File, ?wxID_EXIT, "&Quit"),
+ wxMenu:append(Help, ?wxID_HELP, "Help"),
+ wxMenu:append(Mbar, ?wxID_ANY, "Test item 1"),
+ wxMenu:append(Mbar, ?wxID_ANY, "Test item 2"),
+ wxMenu:append(Mbar, ?wxID_ANY, "Test item 3"),
+
+ wxMenuBar:append(MB, File, "&File"),
+ wxMenuBar:append(MB, Help, "&Help"),
+ wxMenuBar:append(MB, Mbar, "This is a menu bar"),
+ wxFrame:setMenuBar(Frame,MB),
+
+ %% Setup wxStatusBar
+ StatusBar = wxFrame:createStatusBar(Frame, []),
+ wxStatusBar:setFieldsCount(StatusBar, 2),
+ wxStatusBar:setStatusText(StatusBar, "This is a status bar", [{number, 0}]),
+
+ %% Setup wxToolBar
+ ToolBar = wxFrame:createToolBar(Frame, []),
+ wxToolBar:addTool(ToolBar, ?wxID_NEW, "New", wxArtProvider:getBitmap("wxART_NEW"),
+ [{shortHelp, "New"}]),
+ wxToolBar:setToolLongHelp(ToolBar, ?wxID_NEW, "This is long help for 'New'"),
+ wxToolBar:addTool(ToolBar, ?wxID_OPEN, "Open", wxArtProvider:getBitmap("wxART_FILE_OPEN"),
+ [{shortHelp, "Open"}]),
+ wxToolBar:setToolLongHelp(ToolBar, ?wxID_OPEN, "This is long help for 'Open'"),
+ wxToolBar:addSeparator(ToolBar),
+ wxToolBar:addTool(ToolBar, ?wxID_COPY, "Copy", wxArtProvider:getBitmap("wxART_COPY"),
+ [{shortHelp, "Copy"}]),
+ wxToolBar:setToolLongHelp(ToolBar, ?wxID_COPY, "This is long help for 'Copy'"),
+ wxToolBar:addTool(ToolBar, ?wxID_PASTE, "Paste", wxArtProvider:getBitmap("wxART_PASTE"),
+ [{shortHelp, "Paste"}]),
+ wxToolBar:setToolLongHelp(ToolBar, ?wxID_PASTE, "This is long help for 'Paste'"),
+
+ wxToolBar:addControl(ToolBar,wxStaticText:new(ToolBar, 5, "This is a tool bar")),
+
+
+ wxToolBar:realize(ToolBar),
+ wxFrame:setToolBar(Frame,ToolBar),
+
+ wxFrame:connect(Frame, motion, [{userData, StatusBar}]),
+ wxFrame:connect(Frame, command_menu_selected, []),
+ wxFrame:center(Frame),
+ wxFrame:show(Frame).
+
+
+new_mini_frame(Parent) ->
+ MiniFrame = wxMiniFrame:new(Parent, ?wxID_ANY, "wxMiniFrame", [{style,
+ ?wxDEFAULT_FRAME_STYLE bor
+ ?wxFRAME_FLOAT_ON_PARENT}]),
+ Panel = wxPanel:new(MiniFrame, []),
+
+ Text = "This is a wxMiniFrame",
+
+ wxStaticText:new(Panel, ?wxID_ANY, Text, [{style, ?wxALIGN_CENTER}]),
+ wxMiniFrame:setSize(MiniFrame, {200,200}),
+ wxMiniFrame:center(MiniFrame),
+ wxMiniFrame:show(MiniFrame).
+
+
diff --git a/lib/wx/examples/demo/ex_gauge.erl b/lib/wx/examples/demo/ex_gauge.erl
new file mode 100644
index 0000000000..d30c3fea58
--- /dev/null
+++ b/lib/wx/examples/demo/ex_gauge.erl
@@ -0,0 +1,208 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(ex_gauge).
+
+-behaviour(wx_object).
+
+-include_lib("wx/include/wx.hrl").
+
+-export([start/1, init/1, terminate/2, code_change/3,
+ handle_info/2, handle_call/3, handle_event/2]).
+
+-record(gauge, {obj,
+ value,
+ timer,
+ range
+ }).
+
+-record(state,
+ {
+ parent,
+ config,
+ normal_gauge,
+ undeterminate_gauge,
+ simulate_button,
+ simulate_undet_button
+ }).
+
+-define(ID_START_STOP, 1).
+-define(ID_START_STOP_UNDET, 2).
+-define(SET_VALUE, 3).
+-define(VERTICAL, 4).
+
+start(Config) ->
+ wx_object:start_link(?MODULE, Config, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init(Config) ->
+ wx:batch(fun() -> do_init(Config) end).
+do_init(Config) ->
+ Parent = proplists:get_value(parent, Config),
+ Panel = wxPanel:new(Parent, []),
+
+ %% Setup sizers
+ MainSizer = wxBoxSizer:new(?wxVERTICAL),
+ AlignSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "wxGauge"}]),
+
+ %% Create two horizontal gauges with range 0-100
+ Range = 100,
+ NormalGauge = wxGauge:new(Panel, 1, Range, [{size, {200, -1}},
+ {style, ?wxGA_HORIZONTAL}]),
+ UndetGauge = wxGauge:new(Panel, 2, Range, [{size, {200, -1}},
+ {style, ?wxGA_HORIZONTAL}]),
+
+ %% Add to sizers
+ wxSizer:add(AlignSizer, NormalGauge, [{flag, ?wxEXPAND}]),
+ wxSizer:add(AlignSizer, UndetGauge, [{flag, ?wxEXPAND}]),
+ {OptSizer, SimulateButton, SimulateUndetermButton}
+ = create_option_sizer(Panel),
+
+ wxSizer:add(MainSizer, AlignSizer, [{flag, ?wxEXPAND}]),
+ wxSizer:add(MainSizer, OptSizer, []),
+
+ wxWindow:connect(Panel, command_togglebutton_clicked),
+ wxWindow:connect(Panel, command_button_clicked),
+
+ wxPanel:setSizer(Panel, MainSizer),
+ {Panel, #state{parent=Panel, config=Config,
+ normal_gauge = #gauge{obj=NormalGauge, value = 0,
+ range = Range},
+ undeterminate_gauge = #gauge{obj=UndetGauge, value = 0,
+ range = Range},
+ simulate_button = SimulateButton,
+ simulate_undet_button = SimulateUndetermButton}}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Callbacks handled as normal gen_server callbacks
+handle_info(tick, State=#state{normal_gauge = Gauge=#gauge{obj = Obj,
+ value = Value,
+ timer = Timer,
+ range = Range},
+ simulate_button = Button}) ->
+ Timer2 =
+ if Value >= Range ->
+ wxToggleButton:setValue(Button, false),
+ wxToggleButton:setLabel(Button, "Simulate load"),
+ wxGauge:setValue(Obj, Range),
+ demo:format(State#state.config, "Simulation finished.\n", []),
+ Timer;
+ true ->
+ simulate_load(Obj, Value)
+
+ end,
+ {noreply, State#state{normal_gauge = Gauge#gauge{value = Value+5,
+ timer = Timer2}}};
+handle_info(pulse, State=#state{undeterminate_gauge = Gauge=#gauge{obj = Obj}}) ->
+ wxGauge:pulse(Obj),
+ Timer = erlang:send_after(300, self(), pulse),
+ {noreply, State#state{undeterminate_gauge = Gauge#gauge{timer = Timer}}}.
+
+handle_call(Msg, _From, State) ->
+ demo:format(State#state.config,"Got Call ~p\n",[Msg]),
+ {reply,ok, State}.
+
+%% Async Events are handled in handle_event as in handle_info
+handle_event(#wx{id = ?ID_START_STOP,
+ event = #wxCommand{type = command_togglebutton_clicked,
+ commandInt = Int}},
+ State = #state{normal_gauge = #gauge{obj=Gauge,
+ value = Value,
+ timer = Timer},
+ simulate_button = Button}) ->
+ case Int of
+ 1 ->
+ wxToggleButton:setLabel(Button, "Stop simulation"),
+ simulate_load(Gauge, Value);
+ 0 ->
+ erlang:cancel_timer(Timer),
+ wxToggleButton:setLabel(Button, "Simulate load"),
+ ok
+ end,
+ {noreply, State};
+handle_event(#wx{id = ?ID_START_STOP_UNDET,
+ event = #wxCommand{type = command_togglebutton_clicked,
+ commandInt = Int}},
+ State = #state{undeterminate_gauge = G = #gauge{obj=Gauge,
+ timer = Timer},
+ simulate_undet_button = Button}) ->
+ Timer2 =
+ case Int of
+ 1 ->
+ wxToggleButton:setLabel(Button, "Stop simulation"),
+ wxGauge:pulse(Gauge),
+ erlang:send_after(300, self(), pulse);
+ 0 ->
+ wxToggleButton:setLabel(Button, "Simulate undeterminate load"),
+ reset(G),
+ undefined
+ end,
+ case Timer of
+ undefined -> ok;
+ _ -> erlang:cancel_timer(Timer)
+ end,
+ {noreply, State#state{undeterminate_gauge = G#gauge{timer = Timer2}}};
+handle_event(#wx{id = ?wxID_CLEAR,
+ event = #wxCommand{type = command_button_clicked}},
+ State = #state{normal_gauge = Gauge,
+ undeterminate_gauge = Gauge2}) ->
+ reset(Gauge),
+ reset(Gauge2),
+ {noreply, State#state{normal_gauge = Gauge#gauge{value = 0}}};
+handle_event(Ev = #wx{}, State = #state{}) ->
+ demo:format(State#state.config,"Got Event ~p\n",[Ev]),
+ {noreply, State}.
+
+code_change(_, _, State) ->
+ {stop, ignore, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Local functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+simulate_load(Gauge, Value) ->
+ wxGauge:setValue(Gauge, Value),
+ erlang:send_after(300, self(), tick).
+
+reset(#gauge{obj = Gauge}) ->
+ wxGauge:setValue(Gauge, 0).
+
+
+create_option_sizer(Panel) ->
+ OptSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "Options"}]),
+
+ SimulateButton = wxToggleButton:new(Panel, ?ID_START_STOP, "Simulate load",
+ [{size, {200, 35}}]),
+ SimulateUndetermButton = wxToggleButton:new(Panel, ?ID_START_STOP_UNDET,
+ "Simulate Undeterminate load",
+ [{size, {200, 35}}]),
+ ClearButton = wxButton:new(Panel, ?wxID_CLEAR,
+ [{size, {200, 35}}]),
+
+ wxSizer:add(OptSizer, SimulateButton),
+ wxSizer:add(OptSizer, SimulateUndetermButton),
+ wxSizer:add(OptSizer, ClearButton),
+
+ wxWindow:connect(Panel, command_checkbox_clicked),
+
+ {OptSizer, SimulateButton, SimulateUndetermButton}.
diff --git a/lib/wx/examples/demo/ex_gl.erl b/lib/wx/examples/demo/ex_gl.erl
new file mode 100644
index 0000000000..53f1eda847
--- /dev/null
+++ b/lib/wx/examples/demo/ex_gl.erl
@@ -0,0 +1,409 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(ex_gl).
+
+-behaviour(wx_object).
+
+-export([init/1, code_change/3, handle_info/2, handle_event/2,
+ handle_call/3, terminate/2,
+ start/1]).
+
+-include_lib("wx/include/wx.hrl").
+-include_lib("wx/include/gl.hrl").
+-include_lib("wx/include/glu.hrl").
+
+-record(state,
+ {
+ parent,
+ config,
+ gl,
+ canvas,
+ timer,
+ time
+ }).
+
+-record(gl, {win, data, deg, mat, alpha, text, font, brush, clock, sphere}).
+
+-record(texture, {tid, w, h, minx, miny, maxx, maxy}).
+
+start(Config) ->
+ wx_object:start_link(?MODULE, Config, []).
+
+-define(PAD, fun(Int) -> string:right(integer_to_list(Int), 2, $0) end).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init(Config) ->
+ wx:batch(fun() -> do_init(Config) end).
+
+do_init(Config) ->
+ Parent = proplists:get_value(parent, Config),
+ Panel = wxPanel:new(Parent, []),
+
+ %% Setup sizer
+ Sizer = wxStaticBoxSizer:new(?wxHORIZONTAL, Panel, [{label, "wxGLCanvas"}]),
+
+ Opts = [{size, {300,300}}, {style, ?wxSUNKEN_BORDER}],
+ GLAttrib = [{attribList, [?WX_GL_RGBA,
+ ?WX_GL_DOUBLEBUFFER,
+ ?WX_GL_MIN_RED,8,
+ ?WX_GL_MIN_GREEN,8,
+ ?WX_GL_MIN_BLUE,8,
+ ?WX_GL_DEPTH_SIZE,24,0]}],
+ Canvas = wxGLCanvas:new(Panel,Opts ++ GLAttrib),
+ wxGLCanvas:connect(Canvas, size),
+
+ wxGLCanvas:setCurrent(Canvas),
+ Image = wxImage:scale(wxImage:new("image.jpg"), 128,128),
+ GL = setup_gl(Canvas,Image),
+ Timer = timer:send_interval(20, self(), update),
+
+ %% Add to sizers
+ wxSizer:add(Sizer, Canvas, [{flag, ?wxEXPAND},{proportion, 1}]),
+ wxWindow:setSizer(Panel,Sizer),
+ wxSizer:layout(Sizer),
+ {Panel, #state{parent = Panel, config = Config,
+ canvas = Canvas,
+ gl = GL, timer = Timer}}.
+
+%% Event handling
+handle_event(#wx{event = #wxSize{size = {W,H}}}, State) ->
+ case W =:= 0 orelse H =:= 0 of
+ true -> skip;
+ _ ->
+ gl:viewport(0,0,W,H),
+ gl:matrixMode(?GL_PROJECTION),
+ gl:loadIdentity(),
+ gl:ortho( -2.0, 2.0, -2.0*H/W, 2.0*H/W, -20.0, 20.0),
+ gl:matrixMode(?GL_MODELVIEW),
+ gl:loadIdentity()
+ end,
+ {noreply, State}.
+
+handle_info(update, State) ->
+ S1 = update_rotation(State),
+ GL = S1#state.gl,
+ S2 = if S1#state.time > State#state.time ->
+ gl:deleteTextures([(GL#gl.clock)#texture.tid]),
+ {Hour,Min,Sec} = S1#state.time,
+ Clock = load_texture_by_string(GL#gl.font, GL#gl.brush, {40,40,40},
+ [?PAD(Hour), $:, ?PAD(Min), $:, ?PAD(Sec)], false),
+ S1#state{gl = GL#gl{clock = Clock}};
+ true ->
+ S1
+ end,
+ wx:batch(fun() -> drawBox(S2#state.gl) end),
+ {noreply, S2};
+handle_info(stop, State) ->
+ timer:cancel(State#state.timer),
+ catch wxGLCanvas:destroy(State#state.canvas),
+ {stop, normal, State}.
+
+handle_call(Msg, _From, State) ->
+ io:format("Got Call ~p~n",[Msg]),
+ {reply,ok,State}.
+
+code_change(_, _, State) ->
+ {stop, not_yet_implemented, State}.
+
+terminate(_Reason, State) ->
+ catch wxGLCanvas:destroy(State#state.canvas),
+ timer:cancel(State#state.timer),
+ timer:sleep(300).
+
+
+
+-define(VS, {{-0.5, -0.5, -0.5}, %1
+ { 0.5, -0.5, -0.5}, %2
+ { 0.5, 0.5, -0.5},
+ {-0.5, 0.5, -0.5}, %4
+ {-0.5, 0.5, 0.5},
+ { 0.5, 0.5, 0.5}, %6
+ { 0.5, -0.5, 0.5},
+ {-0.5, -0.5, 0.5}}).%8
+
+-define(FACES,
+ %% Faces Normal U-axis V-axis
+ [{{1,2,3,4},{0,0,-1},{-1,0,0}, {0,1,0}}, %
+ {{8,1,4,5},{-1,0,0},{0,0,1}, {0,1,0}}, %
+ {{2,7,6,3},{1,0,0}, {0,0,-1}, {0,1,0}}, %
+ {{7,8,5,6},{0,0,1}, {1,0,0}, {0,1,0}}, %
+ {{4,3,6,5},{0,1,0}, {-1,0,0}, {0,0,1}}, %
+ {{1,2,7,8},{0,-1,0},{1,0,0}, {0,0,1}}]).
+
+-define(COLORS,{{ 0.0, 0.0, 0.0},
+ { 1.0, 0.0, 0.0},
+ { 1.0, 1.0, 0.0},
+ { 0.0, 1.0, 0.0},
+ { 0.0, 1.0, 1.0},
+ { 1.0, 1.0, 1.0},
+ { 1.0, 0.0, 1.0},
+ { 0.0, 0.0, 1.0}}).
+
+
+update_rotation(S=#state{gl=GL=#gl{deg=Rot}}) ->
+ {_, Time} = calendar:local_time(),
+ S#state{gl=GL#gl{deg = Rot + 1.0}, time = Time}.
+
+%% Needs to setup opengl after window is shown...
+%% GL context is created when shown first time.
+setup_gl(Win, Image) ->
+ {W,H} = wxWindow:getClientSize(Win),
+ gl:viewport(0,0,W,H),
+ gl:matrixMode(?GL_PROJECTION),
+ gl:loadIdentity(),
+ gl:ortho( -2.0, 2.0, -2.0*H/W, 2.0*H/W, -20.0, 20.0),
+ gl:matrixMode(?GL_MODELVIEW),
+ gl:loadIdentity(),
+ gl:enable(?GL_DEPTH_TEST),
+ gl:depthFunc(?GL_LESS),
+ gl:clearColor(1.0,1.0,1.0,1.0),
+ MatTexture = load_texture_by_image(Image),
+ ImgTexture = load_texture_by_image(
+ wxImage:new("erlang.png")),
+ Font = wxFont:new(32, ?wxFONTFAMILY_DEFAULT, ?wxFONTSTYLE_NORMAL, ?wxFONTWEIGHT_BOLD),
+ Brush = wxBrush:new({0,0,0}),
+ StrTexture = load_texture_by_string(Font, Brush, {40,40,40}, "Text from wxFont", true),
+ {_, {Hour,Min,Sec}} = calendar:local_time(),
+ Clock = load_texture_by_string(Font, Brush, {40, 40, 40},
+ [?PAD(Hour), $:, ?PAD(Min), $:, ?PAD(Sec)], false),
+ Sphere = glu:newQuadric(),
+ gl:enable(?GL_TEXTURE_2D),
+ #gl{win=Win,data={?FACES,?VS,?COLORS},deg=0.0,
+ mat=MatTexture, alpha=ImgTexture, text=StrTexture, font = Font,
+ brush = Brush, clock = Clock, sphere = Sphere}.
+
+drawBox(#gl{win=Win,deg=Deg,data={Fs,Vs,Colors},mat=MatT,alpha=ImgA,
+ text=Text, clock = Clock, sphere=Sphere}) ->
+ gl:matrixMode(?GL_MODELVIEW),
+ gl:loadIdentity(),
+ gl:pushMatrix(),
+ gl:translatef(0,0.5,0),
+ gl:rotatef(Deg, 1.0, 1.0, 1.0),
+ gl:clear(?GL_COLOR_BUFFER_BIT bor ?GL_DEPTH_BUFFER_BIT),
+ gl:bindTexture(?GL_TEXTURE_2D, MatT#texture.tid),
+ gl:disable(?GL_BLEND),
+ gl:texEnvf(?GL_TEXTURE_ENV, ?GL_TEXTURE_ENV_MODE, ?GL_MODULATE),
+ gl:disable(?GL_CULL_FACE),
+ gl:'begin'(?GL_QUADS),
+ wx:foreach(fun(Face) -> drawFace(Face,Vs,Colors) end, Fs),
+ gl:'end'(),
+ gl:popMatrix(),
+
+ gl:texEnvf(?GL_TEXTURE_ENV, ?GL_TEXTURE_ENV_MODE, ?GL_REPLACE),
+
+ enter_2d_mode(Win),
+ {W,H} = wxWindow:getClientSize(Win),
+ Move = abs(90 - (trunc(Deg) rem 180)),
+ draw_texture((W div 2) - 50, (H div 2)-130+Move, Clock),
+ draw_texture((W div 2) - 80, (H div 2)-Move, ImgA),
+ leave_2d_mode(),
+
+ gl:pushMatrix(),
+ gl:enable(?GL_CULL_FACE),
+ gl:enable(?GL_BLEND),
+ gl:blendFunc(?GL_SRC_ALPHA, ?GL_ONE_MINUS_SRC_ALPHA),
+ gl:translatef(0,-0.8,0),
+ gl:bindTexture(?GL_TEXTURE_2D, Text#texture.tid),
+ glu:quadricTexture(Sphere, ?GLU_TRUE),
+ glu:quadricNormals(Sphere, ?GLU_SMOOTH),
+ glu:quadricDrawStyle(Sphere, ?GLU_FILL),
+ glu:quadricOrientation(Sphere, ?GLU_OUTSIDE),
+ %%gl:scalef(2.0, 0.5, 1.0),
+ gl:rotatef(-90, 1.0, 0.0, 0.0),
+ gl:rotatef(-Deg, 0.0, 0.0, 1.0),
+ glu:sphere(Sphere, 0.8, 50,40),
+ gl:popMatrix(),
+
+ wxGLCanvas:swapBuffers(Win).
+
+drawFace({{V1,V2,V3,V4},N,_Ut,_Vt}, Cube, Colors) ->
+ gl:normal3fv(N),
+ gl:color3fv(element(V1, Colors)),
+ gl:texCoord2f(0.0, 0.0), gl:vertex3fv(element(V1, Cube)),
+ gl:color3fv(element(V2, Colors)),
+ gl:texCoord2f(1.0, 0.0), gl:vertex3fv(element(V2, Cube)),
+ gl:color3fv(element(V3, Colors)),
+ gl:texCoord2f(1.0, 1.0), gl:vertex3fv(element(V3, Cube)),
+ gl:color3fv(element(V4, Colors)),
+ gl:texCoord2f(0.0, 1.0), gl:vertex3fv(element(V4, Cube)).
+
+
+draw_texture(X, Y, #texture{tid = TId, w = W, h = H,
+ miny = MinY, minx = MinX,
+ maxx = MaxX, maxy = MaxY}) ->
+ gl:bindTexture(?GL_TEXTURE_2D, TId),
+ gl:'begin'(?GL_TRIANGLE_STRIP),
+ gl:texCoord2f(MinX, MinY), gl:vertex2i(X, Y ),
+ gl:texCoord2f(MaxX, MinY), gl:vertex2i(X+W div 2, Y ),
+ gl:texCoord2f(MinX, MaxY), gl:vertex2i(X, Y+H div 2),
+ gl:texCoord2f(MaxX, MaxY), gl:vertex2i(X+W div 2, Y+H div 2),
+ gl:'end'().
+
+load_texture_by_image(Image) ->
+ ImgW = wxImage:getWidth(Image),
+ ImgH = wxImage:getHeight(Image),
+ W = get_power_of_two_roof(ImgW),
+ H = get_power_of_two_roof(ImgH),
+ Data = get_data_for_use_with_teximage2d(Image),
+ %% Create an OpenGL texture for the image
+ [TId] = gl:genTextures(1),
+ gl:bindTexture(?GL_TEXTURE_2D, TId),
+ gl:texParameteri(?GL_TEXTURE_2D, ?GL_TEXTURE_MAG_FILTER, ?GL_NEAREST),
+ gl:texParameteri(?GL_TEXTURE_2D, ?GL_TEXTURE_MIN_FILTER, ?GL_NEAREST),
+ Format = case wxImage:hasAlpha(Image) of
+ true -> ?GL_RGBA;
+ false -> ?GL_RGB
+ end,
+ gl:texImage2D(?GL_TEXTURE_2D, 0,
+ Format, W, H, 0,
+ Format, ?GL_UNSIGNED_BYTE, Data),
+ #texture{tid = TId, w = ImgW, h = ImgH,
+ minx = 0, miny = 0, maxx = ImgW / W, maxy = ImgH / H}.
+
+
+%% This algorithm (based on http://d0t.dbclan.de/snippets/gltext.html)
+%% prints a string to a bitmap and loads that onto an opengl texture.
+%% Comments for the createTexture function:
+%%
+%% "Creates a texture from the settings saved in TextElement, to be
+%% able to use normal system fonts conviently a wx.MemoryDC is
+%% used to draw on a wx.Bitmap. As wxwidgets device contexts don't
+%% support alpha at all it is necessary to apply a little hack to
+%% preserve antialiasing without sticking to a fixed background
+%% color:
+%%
+%% We draw the bmp in b/w mode so we can use its data as a alpha
+%% channel for a solid color bitmap which after GL_ALPHA_TEST and
+%% GL_BLEND will show a nicely antialiased text on any surface.
+%%
+%% To access the raw pixel data the bmp gets converted to a
+%% wx.Image. Now we just have to merge our foreground color with
+%% the alpha data we just created and push it all into a OpenGL
+%% texture and we are DONE *inhalesdelpy*"
+load_texture_by_string(Font, Brush, Color, String, Flip) ->
+ TmpBmp = wxBitmap:new(200, 200),
+ Tmp = wxMemoryDC:new(TmpBmp),
+ wxMemoryDC:setFont(Tmp, Font),
+ {StrW, StrH} = wxDC:getTextExtent(Tmp, String),
+ wxMemoryDC:destroy(Tmp),
+ wxBitmap:destroy(TmpBmp),
+
+ W = get_power_of_two_roof(StrW),
+ H = get_power_of_two_roof(StrH),
+
+ Bmp = wxBitmap:new(W, H),
+ DC = wxMemoryDC:new(Bmp),
+ wxMemoryDC:setFont(DC, Font),
+ wxMemoryDC:setBackground(DC, Brush),
+ wxMemoryDC:clear(DC),
+ wxMemoryDC:setTextForeground(DC, {255, 255, 255}),
+ wxMemoryDC:drawText(DC, String, {0, 0}),
+
+ Img0 = wxBitmap:convertToImage(Bmp),
+ case Flip of
+ true ->
+ Img = wxImage:mirror(Img0, [{horizontally, false}]),
+ wxImage:destroy(Img0),
+ Img;
+ false ->
+ Img = Img0
+ end,
+
+ Alpha = wxImage:getData(Img),
+ Data = colourize_image(Alpha, Color),
+ wxImage:destroy(Img),
+ wxBitmap:destroy(Bmp),
+ wxMemoryDC:destroy(DC),
+
+ [TId] = gl:genTextures(1),
+ gl:bindTexture(?GL_TEXTURE_2D, TId),
+ gl:texParameteri(?GL_TEXTURE_2D, ?GL_TEXTURE_MAG_FILTER, ?GL_LINEAR),
+ gl:texParameteri(?GL_TEXTURE_2D, ?GL_TEXTURE_MIN_FILTER, ?GL_LINEAR),
+ gl:texEnvf(?GL_TEXTURE_ENV, ?GL_TEXTURE_ENV_MODE, ?GL_REPLACE),
+ %%gl:pixelStorei(?GL_UNPACK_ROW_LENGTH, 0),
+ %%gl:pixelStorei(?GL_UNPACK_ALIGNMENT, 2),
+ gl:texImage2D(?GL_TEXTURE_2D, 0, ?GL_RGBA,
+ W, H, 0, ?GL_RGBA, ?GL_UNSIGNED_BYTE, Data),
+ #texture{tid = TId, w = StrW, h = StrH,
+ minx = 0, miny = 0, maxx = StrW / W, maxy = StrH / H}.
+
+colourize_image(Alpha, {R,G,B}) ->
+ << <<R:8,G:8,B:8,A:8>> || <<A:8,_:8,_:8>> <= Alpha >>.
+
+get_data_for_use_with_teximage2d(Image) ->
+ RGB = wxImage:getData(Image),
+ case wxImage:hasAlpha(Image) of
+ true ->
+ Alpha = wxImage:getAlpha(Image),
+ interleave_rgb_and_alpha(RGB, Alpha);
+ false ->
+ RGB
+ end.
+
+interleave_rgb_and_alpha(RGB, Alpha) ->
+ list_to_binary(
+ lists:zipwith(fun({R, G, B}, A) ->
+ <<R, G, B, A>>
+ end,
+ [{R,G,B} || <<R, G, B>> <= RGB],
+ [A || <<A>> <= Alpha])).
+
+
+enter_2d_mode(Win) ->
+ {W, H} = wxWindow:getClientSize(Win),
+
+ %% Note, there may be other things you need to change,
+ %% depending on how you have your OpenGL state set up.
+ gl:pushAttrib(?GL_ENABLE_BIT),
+ gl:disable(?GL_DEPTH_TEST),
+ gl:disable(?GL_CULL_FACE),
+ gl:enable(?GL_TEXTURE_2D),
+
+ %% This allows alpha blending of 2D textures with the scene
+ gl:enable(?GL_BLEND),
+ gl:blendFunc(?GL_SRC_ALPHA, ?GL_ONE_MINUS_SRC_ALPHA),
+
+ gl:matrixMode(?GL_PROJECTION),
+ gl:pushMatrix(),
+ gl:loadIdentity(),
+
+ %% SDL coordinates will be upside-down in the OpenGL world. We'll
+ %% therefore flip the bottom and top coordinates in the orthogonal
+ %% projection to correct this.
+ %% Note: We could flip the texture/image itself, but this will
+ %% also work for mouse coordinates.
+ gl:ortho(0.0, W, H, 0.0, 0.0, 1.0),
+
+ gl:matrixMode(?GL_MODELVIEW),
+ gl:pushMatrix(),
+ gl:loadIdentity().
+
+leave_2d_mode() ->
+ gl:matrixMode(?GL_MODELVIEW),
+ gl:popMatrix(),
+ gl:matrixMode(?GL_PROJECTION),
+ gl:popMatrix(),
+ gl:popAttrib().
+
+get_power_of_two_roof(X) ->
+ get_power_of_two_roof_2(1, X).
+
+get_power_of_two_roof_2(N, X) when N >= X -> N;
+get_power_of_two_roof_2(N, X) -> get_power_of_two_roof_2(N*2, X).
+
diff --git a/lib/wx/examples/demo/ex_graphicsContext.erl b/lib/wx/examples/demo/ex_graphicsContext.erl
new file mode 100644
index 0000000000..bcd7a75be0
--- /dev/null
+++ b/lib/wx/examples/demo/ex_graphicsContext.erl
@@ -0,0 +1,146 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(ex_graphicsContext).
+
+-behaviour(wx_object).
+
+%% Client API
+-export([start/1]).
+
+%% wx_object callbacks
+-export([init/1, terminate/2, code_change/3,
+ handle_info/2, handle_call/3,
+ handle_event/2, handle_sync_event/3]).
+
+-include_lib("wx/include/wx.hrl").
+
+-record(state,
+ {
+ parent,
+ config,
+ win,
+ pen,
+ brush,
+ font
+ }).
+
+start(Config) ->
+ wx_object:start_link(?MODULE, Config, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init(Config) ->
+ wx:batch(fun() -> do_init(Config) end).
+
+do_init(Config) ->
+ Parent = proplists:get_value(parent, Config),
+ Panel = wxPanel:new(Parent, []),
+
+ %% Setup sizers
+ MainSizer = wxBoxSizer:new(?wxVERTICAL),
+ Sizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "wxGrapicsContext"}]),
+
+ Win = wxPanel:new(Panel, []),
+ Pen = wxPen:new(),
+ Brush = wxBrush:new(?wxBLACK),
+ Font = wxFont:new(),
+ wxFont:setWeight(Font, ?wxBOLD),
+
+ wxPanel:connect(Win, paint, [callback]),
+
+ %% Add to sizers
+ wxSizer:add(Sizer, Win, [{flag, ?wxEXPAND},
+ {proportion, 1}]),
+ wxSizer:add(MainSizer, Sizer, [{flag, ?wxEXPAND},
+ {proportion, 1}]),
+
+ wxPanel:setSizer(Panel, MainSizer),
+ {Panel, #state{parent=Panel, config=Config, win = Win,
+ pen = Pen, brush = Brush, font = Font}}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Sync events i.e. from callbacks must return ok, it can not return a new state.
+%% Do the redrawing here.
+handle_sync_event(#wx{event = #wxPaint{}},_,
+ #state{win=Win, pen = Pen, brush = Brush, font = Font}) ->
+ %% PaintDC must be created in a callback to work on windows.
+ DC = wxPaintDC:new(Win),
+ %% Nothing is drawn until wxPaintDC is destroyed.
+ draw(DC, Pen, Brush, Font),
+ wxPaintDC:destroy(DC),
+ ok.
+%% Async Events are handled in handle_event as in handle_info
+handle_event(#wx{}, State) ->
+ {noreply, State}.
+
+%% Callbacks handled as normal gen_server callbacks
+handle_info(Msg, State) ->
+ demo:format(State#state.config, "Got Info ~p\n", [Msg]),
+ {noreply, State}.
+
+handle_call(Msg, _From, State) ->
+ demo:format(State#state.config, "Got Call ~p\n", [Msg]),
+ {reply,{error, nyi}, State}.
+
+code_change(_, _, State) ->
+ {stop, ignore, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Local functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+draw(Win, Pen0, _Brush0, Font0) ->
+ try
+ Canvas = wxGraphicsContext:create(Win),
+ Pen = wxGraphicsContext:createPen(Canvas, Pen0),
+ wxGraphicsContext:setPen(Canvas, Pen),
+ Brush = wxGraphicsContext:createLinearGradientBrush(Canvas, 0.0,0.0, 30.0,30.0,
+ {200,50,50,50},
+ {200,50,50,200}),
+ wxGraphicsContext:setBrush(Canvas, Brush),
+ Font = wxGraphicsContext:createFont(Canvas, Font0),
+ wxGraphicsContext:setFont(Canvas, Font),
+
+ wxGraphicsContext:drawRoundedRectangle(Canvas, 35.0,35.0, 100.0, 50.0, 10.0),
+ wxGraphicsContext:drawText(Canvas, "Welcome", 60.0, 55.0),
+ Path = wxGraphicsContext:createPath(Canvas),
+ wxGraphicsPath:addCircle(Path, 0.0, 0.0, 40.0),
+ wxGraphicsPath:closeSubpath(Path),
+ wxGraphicsContext:translate(Canvas, 100.0, 100.0),
+
+ Brush2 = wxGraphicsContext:createLinearGradientBrush(Canvas, 0.0,0.0, 30.0,30.0,
+ {50,200,50,50},
+ {50,50,200,50}),
+ wxGraphicsContext:setBrush(Canvas, Brush2),
+
+ F = fun(_) ->
+ wxGraphicsContext:scale(Canvas, 1.1, 1.1),
+ wxGraphicsContext:translate(Canvas, 3.0,3.0),
+ wxGraphicsContext:drawPath(Canvas, Path)
+ end,
+ wx:foreach(F, lists:seq(1,5)),
+ ok
+ catch _:{not_supported, _} ->
+ Err = "wxGraphicsContext not available in this build of wxwidgets",
+ io:format(Err,[])
+ end.
+
diff --git a/lib/wx/examples/demo/ex_grid.erl b/lib/wx/examples/demo/ex_grid.erl
new file mode 100644
index 0000000000..2169c818ff
--- /dev/null
+++ b/lib/wx/examples/demo/ex_grid.erl
@@ -0,0 +1,142 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(ex_grid).
+
+-behaviour(wx_object).
+
+%% Client API
+-export([start/1]).
+
+%% wx_object callbacks
+-export([init/1, terminate/2, code_change/3,
+ handle_info/2, handle_call/3, handle_event/2]).
+
+-include_lib("wx/include/wx.hrl").
+
+-record(state,
+ {
+ parent,
+ config,
+ grid
+ }).
+
+start(Config) ->
+ wx_object:start_link(?MODULE, Config, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init(Config) ->
+ wx:batch(fun() -> do_init(Config) end).
+
+do_init(Config) ->
+ Parent = proplists:get_value(parent, Config),
+ Panel = wxPanel:new(Parent, []),
+
+ %% Setup sizers
+ MainSizer = wxBoxSizer:new(?wxVERTICAL),
+ Sizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "wxGrid"}]),
+
+ Grid = create_grid(Panel),
+
+ %% Add to sizers
+ Options = [{flag, ?wxEXPAND}, {proportion, 1}],
+
+ wxSizer:add(Sizer, Grid, Options),
+ wxSizer:add(MainSizer, Sizer, Options),
+
+ wxPanel:setSizer(Panel, MainSizer),
+ {Panel, #state{parent=Panel, config=Config,
+ grid = Grid}}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Async Events are handled in handle_event as in handle_info
+handle_event(#wx{event = #wxGrid{type = grid_cell_change,
+ row = Row, col = Col}},
+ State = #state{}) ->
+ Val = wxGrid:getCellValue(State#state.grid, Row, Col),
+ demo:format(State#state.config, "Cell {~p,~p} changed to ~p.\n",
+ [Row,Col,Val]),
+ {noreply, State}.
+
+%% Callbacks handled as normal gen_server callbacks
+handle_info(_Msg, State) ->
+ {noreply, State}.
+
+handle_call(_Msg, _From, State) ->
+ {reply,{error, nyi}, State}.
+
+code_change(_, _, State) ->
+ {stop, ignore, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Local functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+create_grid(Panel) ->
+ %% Create the grid with 100 * 5 cells
+ Grid = wxGrid:new(Panel, 2, []),
+ wxGrid:createGrid(Grid, 100, 5),
+
+ Font = wxFont:new(16, ?wxFONTFAMILY_SWISS,
+ ?wxFONTSTYLE_NORMAL,
+ ?wxFONTWEIGHT_NORMAL, []),
+ %% Fun to set the values and flags of the cells
+ Fun =
+ fun(Row) ->
+ wxGrid:setCellValue(Grid, Row, 0, "Editable"),
+ wxGrid:setCellValue(Grid, Row, 1, "Editable"),
+ wxGrid:setCellValue(Grid, Row, 2, "Editable"),
+ wxGrid:setCellValue(Grid, Row, 3, "Read only"),
+ wxGrid:setCellTextColour(Grid, Row, 3, ?wxWHITE),
+ wxGrid:setReadOnly(Grid, Row, 3, [{isReadOnly,true}]),
+ wxGrid:setCellValue(Grid, Row, 4, "Editable"),
+ case Row rem 4 of
+ 0 -> wxGrid:setCellBackgroundColour(Grid, Row, 3, ?wxRED);
+ 1 -> wxGrid:setCellBackgroundColour(Grid, Row, 3, ?wxGREEN),
+ wxGrid:setCellTextColour(Grid, Row, 2, {255,215,0,255});
+ 2 -> wxGrid:setCellBackgroundColour(Grid, Row, 3, ?wxBLUE);
+ _ -> wxGrid:setCellBackgroundColour(Grid, Row, 1, ?wxCYAN),
+ wxGrid:setCellValue(Grid, Row, 1,
+ "Centered\nhorizontally"),
+ wxGrid:setCellAlignment(Grid, Row, 4,
+ 0,?wxALIGN_CENTER),
+ wxGrid:setCellValue(Grid, Row, 4,
+ "Centered\nvertically"),
+ wxGrid:setCellAlignment(Grid, Row, 1,
+ ?wxALIGN_CENTER,0),
+ wxGrid:setCellTextColour(Grid, Row, 3, ?wxBLACK),
+ wxGrid:setCellAlignment(Grid, Row, 2,
+ ?wxALIGN_CENTER,
+ ?wxALIGN_CENTER),
+ wxGrid:setCellFont(Grid, Row, 0, Font),
+ wxGrid:setCellValue(Grid, Row, 2,
+ "Centered vertically\nand horizontally"),
+ wxGrid:setRowSize(Grid, Row, 80)
+ end
+ end,
+ %% Apply the fun to each row
+ wx:foreach(Fun, lists:seq(0,99)),
+ wxGrid:setColSize(Grid, 2, 150),
+ wxGrid:connect(Grid, grid_cell_change),
+ Grid.
+
+
diff --git a/lib/wx/examples/demo/ex_htmlWindow.erl b/lib/wx/examples/demo/ex_htmlWindow.erl
new file mode 100644
index 0000000000..b864cd10b2
--- /dev/null
+++ b/lib/wx/examples/demo/ex_htmlWindow.erl
@@ -0,0 +1,93 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(ex_htmlWindow).
+
+-behaviour(wx_object).
+
+%% Client API
+-export([start/1]).
+
+%% wx_object callbacks
+-export([init/1, terminate/2, code_change/3,
+ handle_info/2, handle_call/3, handle_event/2]).
+
+-include("../../include/wx.hrl").
+
+-record(state,
+ {
+ parent,
+ config
+ }).
+
+start(Config) ->
+ wx_object:start_link(?MODULE, Config, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init(Config) ->
+ wx:batch(fun() -> do_init(Config) end).
+
+do_init(Config) ->
+ Parent = proplists:get_value(parent, Config),
+ Panel = wxPanel:new(Parent, []),
+
+ %% Setup sizers
+ MainSizer = wxBoxSizer:new(?wxVERTICAL),
+ Sizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "wxHtmlWindow"}]),
+
+ %% Create the wxHtmlWindow
+ HtmlWin = wxHtmlWindow:new(Panel, []),
+ %% Load a file and display it
+ wxHtmlWindow:loadFile(HtmlWin, "ex_htmlWindow.html"),
+
+ %% Add to sizers
+ wxSizer:add(Sizer, HtmlWin, [{flag, ?wxEXPAND}, {proportion, 1}]),
+ wxSizer:add(MainSizer, Sizer, [{flag, ?wxEXPAND}, {proportion, 1}]),
+
+ wxHtmlWindow:connect(HtmlWin, command_html_link_clicked, [{skip,true}]),
+
+ wxPanel:setSizer(Panel, MainSizer),
+ {Panel, #state{parent=Panel, config=Config}}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Async Events are handled in handle_event as in handle_info
+handle_event(#wx{event = #wxHtmlLink{linkInfo = #wxHtmlLinkInfo{href=Link}}},
+ State = #state{}) ->
+ demo:format(State#state.config, "You clicked link ~p.\n", [Link]),
+ {noreply, State}.
+
+%% Callbacks handled as normal gen_server callbacks
+handle_info(Msg, State) ->
+ demo:format(State#state.config, "Got Info ~p\n", [Msg]),
+ {noreply, State}.
+
+handle_call(Msg, _From, State) ->
+ demo:format(State#state.config, "Got Call ~p\n", [Msg]),
+ {reply,{error, nyi}, State}.
+
+code_change(_, _, State) ->
+ {stop, ignore, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Local functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
diff --git a/lib/wx/examples/demo/ex_htmlWindow.html b/lib/wx/examples/demo/ex_htmlWindow.html
new file mode 100644
index 0000000000..c22800606c
--- /dev/null
+++ b/lib/wx/examples/demo/ex_htmlWindow.html
@@ -0,0 +1,59 @@
+<html>
+ <a name="top" />
+ <h3>Erlang is the best.</h3>
+ <ul>
+ <li><font color="blue">Text1</font></li>
+ <li><font color="red">Text2</font></li>
+ </ul>
+ <p>You can insert whatever HTML you want... although wxHtmlWindow doesn't support css or scripts</p>
+ <br />
+ <img src="image.jpg" />
+ <table border="1">
+ <tr>
+ <td>This</td>
+ <td>is</td>
+ </tr>
+ <tr>
+ <td>a</td>
+ <td>table</td>
+ </tr>
+ </table>
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <br />
+ <a href="#top">Top</a><br />
+<center>
+<small>
+ Copyright &copy; 2009 Ericsson AB
+ </small>
+</center>
+</html> \ No newline at end of file
diff --git a/lib/wx/examples/demo/ex_listCtrl.erl b/lib/wx/examples/demo/ex_listCtrl.erl
new file mode 100644
index 0000000000..c574c7247a
--- /dev/null
+++ b/lib/wx/examples/demo/ex_listCtrl.erl
@@ -0,0 +1,148 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(ex_listCtrl).
+
+-include_lib("wx/include/wx.hrl").
+
+-behaviour(wx_object).
+
+-export([start/1, init/1, terminate/2, code_change/3,
+ handle_info/2, handle_call/3, handle_event/2]).
+
+-record(state,
+ {
+ parent,
+ config,
+ notebook
+ }).
+
+start(Config) ->
+ wx_object:start_link(?MODULE, Config, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init(Config) ->
+ wx:batch(fun() -> do_init(Config) end).
+
+do_init(Config) ->
+ Parent = proplists:get_value(parent, Config),
+ Panel = wxPanel:new(Parent, []),
+
+ %% Setup sizers
+ MainSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "wxListCtrl"}]),
+
+ Notebook = wxNotebook:new(Panel, 1, [{style, ?wxBK_DEFAULT}]),
+
+
+ ListCtrl1 = wxListCtrl:new(Notebook, [{style, ?wxLC_LIST}]),
+ [wxListCtrl:insertItem(ListCtrl1, Int, "Item "++integer_to_list(Int)) ||
+ Int <- lists:seq(0,50)],
+ ListCtrl2 = create_list_ctrl(Notebook, [{style, ?wxLC_REPORT bor
+ ?wxLC_SINGLE_SEL}]),
+ IL = wxImageList:new(16,16),
+ wxImageList:add(IL, wxArtProvider:getBitmap("wxART_COPY", [{size, {16,16}}])),
+ wxImageList:add(IL, wxArtProvider:getBitmap("wxART_MISSING_IMAGE", [{size, {16,16}}])),
+ wxImageList:add(IL, wxArtProvider:getBitmap("wxART_TICK_MARK", [{size, {16,16}}])),
+ wxImageList:add(IL, wxArtProvider:getBitmap("wxART_CROSS_MARK", [{size, {16,16}}])),
+ wxListCtrl:assignImageList(ListCtrl2, IL, ?wxIMAGE_LIST_SMALL),
+ Fun =
+ fun(Item) ->
+ case Item rem 4 of
+ 0 ->
+ wxListCtrl:setItemBackgroundColour(ListCtrl2, Item, {240,240,240,255}),
+ wxListCtrl:setItemImage(ListCtrl2, Item, 0);
+ 1 -> wxListCtrl:setItemImage(ListCtrl2, Item, 1);
+ 2 -> wxListCtrl:setItemImage(ListCtrl2, Item, 2),
+ wxListCtrl:setItemBackgroundColour(ListCtrl2, Item, {240,240,240,255});
+ _ -> wxListCtrl:setItemImage(ListCtrl2, Item, 3)
+ end
+ end,
+ wx:foreach(Fun, lists:seq(0,50)),
+
+ ListCtrl3 = create_list_ctrl(Notebook, [{style, ?wxLC_REPORT}]),
+ wxListCtrl:setTextColour(ListCtrl3, ?wxBLUE),
+ wxListCtrl:setItemBackgroundColour(ListCtrl3,5,?wxRED),
+ wxListCtrl:setItemBackgroundColour(ListCtrl3,3,?wxGREEN),
+ wxListCtrl:setItemBackgroundColour(ListCtrl3,0,?wxCYAN),
+
+ wxListCtrl:connect(ListCtrl1, command_list_item_selected, []),
+ wxListCtrl:connect(ListCtrl2, command_list_item_selected, []),
+ wxListCtrl:connect(ListCtrl3, command_list_item_selected, []),
+
+ %% Add to sizers
+ wxNotebook:addPage(Notebook, ListCtrl1, "List", []),
+ wxNotebook:addPage(Notebook, ListCtrl2, "Report", []),
+ wxNotebook:addPage(Notebook, ListCtrl3, "Colored multiselect", []),
+
+ wxSizer:add(MainSizer, Notebook, [{proportion, 1},
+ {flag, ?wxEXPAND}]),
+
+ wxPanel:setSizer(Panel, MainSizer),
+ {Panel, #state{parent=Panel, config=Config,
+ notebook = Notebook}}.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Async Events are handled in handle_event as in handle_info
+handle_event(#wx{obj = _ListCtrl,
+ event = #wxList{itemIndex = Item}},
+ State = #state{}) ->
+ demo:format(State#state.config,"Item ~p selected.\n",[Item]),
+ {noreply,State}.
+
+%% Callbacks handled as normal gen_server callbacks
+handle_info(Msg, State) ->
+ demo:format(State#state.config, "Got Info ~p\n",[Msg]),
+ {noreply,State}.
+
+handle_call(Msg, _From, State) ->
+ demo:format(State#state.config,"Got Call ~p\n",[Msg]),
+ {reply,ok,State}.
+
+code_change(_, _, State) ->
+ {stop, ignore, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%% Local functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+-define(FIRST_COL, 0).
+-define(SECOND_COL, 1).
+-define(THIRD_COL, 2).
+
+create_list_ctrl(Win, Options) ->
+ ListCtrl = wxListCtrl:new(Win, Options),
+ wxListCtrl:insertColumn(ListCtrl, ?FIRST_COL, "First Col", []),
+ wxListCtrl:insertColumn(ListCtrl, ?SECOND_COL, "Second Col", []),
+ wxListCtrl:insertColumn(ListCtrl, ?THIRD_COL, "Third Col", []),
+ Fun =
+ fun(Int) ->
+ Name = integer_to_list(Int),
+ wxListCtrl:insertItem(ListCtrl, Int, ""),
+ wxListCtrl:setItem(ListCtrl, Int, ?FIRST_COL, "First "++Name),
+ wxListCtrl:setItem(ListCtrl, Int, ?SECOND_COL, "Second "++Name),
+ wxListCtrl:setItem(ListCtrl, Int, ?THIRD_COL, "Third "++Name)
+ end,
+ wx:foreach(Fun, lists:seq(0,50)),
+
+ ListCtrl.
+
+
diff --git a/lib/wx/examples/demo/ex_notebook.erl b/lib/wx/examples/demo/ex_notebook.erl
new file mode 100644
index 0000000000..2e16ccfffa
--- /dev/null
+++ b/lib/wx/examples/demo/ex_notebook.erl
@@ -0,0 +1,147 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(ex_notebook).
+
+-include_lib("wx/include/wx.hrl").
+
+-behaviour(wx_object).
+
+-export([start/1, init/1, terminate/2, code_change/3,
+ handle_info/2, handle_call/3, handle_event/2]).
+
+-record(state,
+ {
+ parent,
+ config,
+ notebook
+ }).
+
+start(Config) ->
+ wx_object:start_link(?MODULE, Config, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init(Config) ->
+ wx:batch(fun() -> do_init(Config) end).
+do_init(Config) ->
+ Parent = proplists:get_value(parent, Config),
+ Panel = wxPanel:new(Parent, []),
+
+ %% Setup sizers
+ MainSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "wxNotebook"}]),
+
+ Notebook = wxNotebook:new(Panel, 1, [{style, ?wxBK_DEFAULT%,
+ %?wxBK_ALIGN_MASK,
+ %?wxBK_TOP,
+ %?wxBK_BOTTOM,
+ %?wxBK_LEFT,
+ %?wxBK_RIGHT,
+ %?wxNB_MULTILINE % windows only
+ }]),
+
+ %% Make a wxImageList to be able to display icons in the tab field
+ IL = wxImageList:new(16,16),
+ wxImageList:add(IL, wxArtProvider:getBitmap("wxART_INFORMATION", [{size, {16,16}}])),
+ wxImageList:add(IL, wxArtProvider:getBitmap("wxART_MISSING_IMAGE", [{size, {16,16}}])),
+ wxNotebook:assignImageList(Notebook, IL),
+
+
+
+ Win1 = wxPanel:new(Notebook, []),
+ wxPanel:setBackgroundColour(Win1, ?wxRED),
+ Win1Text = wxStaticText:new(Win1, ?wxID_ANY, "This is a red tab.",
+ [{pos, {50, 100}}]),
+ wxStaticText:setForegroundColour(Win1Text, ?wxGREEN),
+ Sizer1 = wxBoxSizer:new(?wxHORIZONTAL),
+ wxSizer:add(Sizer1, Win1Text),
+ wxPanel:setSizer(Win1, Sizer1),
+ wxNotebook:addPage(Notebook, Win1, "Red", []),
+
+ Win2 = wxPanel:new(Notebook, []),
+ wxPanel:setBackgroundColour(Win2, ?wxBLUE),
+ Win2Text = wxStaticText:new(Win2, ?wxID_ANY, "This is a blue tab.",
+ [{pos, {50, 100}}]),
+ wxStaticText:setForegroundColour(Win2Text, {255,255,0,255}),
+ Sizer2 = wxBoxSizer:new(?wxHORIZONTAL),
+ wxSizer:add(Sizer2, Win2Text),
+ wxPanel:setSizer(Win2, Sizer2),
+ wxNotebook:addPage(Notebook, Win2, "Blue", []),
+
+ Win3 = wxPanel:new(Notebook, []),
+ wxNotebook:addPage(Notebook, Win3, "No color", []),
+ wxNotebook:setPageImage(Notebook, 2, 1),
+
+ Win4 = wxPanel:new(Notebook, []),
+ wxPanel:setBackgroundColour(Win4, ?wxBLACK),
+ Win4Text = wxStaticText:new(Win4, ?wxID_ANY, "This is a black tab.",
+ [{pos, {50, 100}}]),
+ wxStaticText:setForegroundColour(Win4Text, ?wxWHITE),
+ Sizer4 = wxBoxSizer:new(?wxHORIZONTAL),
+ wxSizer:add(Sizer4, Win4Text),
+ wxPanel:setSizer(Win4, Sizer4),
+ wxNotebook:addPage(Notebook, Win4, "Black", []),
+
+ Win5 = wxPanel:new(Notebook, []),
+ wxNotebook:addPage(Notebook, Win5, "Tab with icon", []),
+ wxNotebook:setPageImage(Notebook, 4, 0),
+
+ %% Add to sizers
+ wxSizer:add(MainSizer, Notebook, [{proportion, 1},
+ {flag, ?wxEXPAND}]),
+
+ wxNotebook:connect(Notebook, command_notebook_page_changed,
+ [{skip, true}]), % {skip, true} has to be set on windows
+ wxPanel:setSizer(Panel, MainSizer),
+ {Panel, #state{parent=Panel, config=Config,
+ notebook = Notebook}}.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Async Events are handled in handle_event as in handle_info
+handle_event(#wx{event = #wxNotebook{type = command_notebook_page_changed}},
+ State = #state{notebook = Notebook}) ->
+ Selection = wxNotebook:getSelection(Notebook),
+ Title = wxNotebook:getPageText(Notebook, Selection),
+ demo:format(State#state.config,"You have selected the tab ~p\n",[Title]),
+ {noreply,State};
+handle_event(Ev = #wx{}, State = #state{}) ->
+ demo:format(State#state.config,"Got Event ~p\n",[Ev]),
+ {noreply,State}.
+
+%% Callbacks handled as normal gen_server callbacks
+handle_info(Msg, State) ->
+ demo:format(State#state.config, "Got Info ~p\n",[Msg]),
+ {noreply,State}.
+
+handle_call(Msg, _From, State) ->
+ demo:format(State#state.config,"Got Call ~p\n",[Msg]),
+ {reply,ok,State}.
+
+code_change(_, _, State) ->
+ {stop, ignore, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%%%% Local functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+
+
diff --git a/lib/wx/examples/demo/ex_pickers.erl b/lib/wx/examples/demo/ex_pickers.erl
new file mode 100644
index 0000000000..892c5b449d
--- /dev/null
+++ b/lib/wx/examples/demo/ex_pickers.erl
@@ -0,0 +1,136 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(ex_pickers).
+
+-behaviour(wx_object).
+
+%% Client API
+-export([start/1]).
+
+%% wx_object callbacks
+-export([init/1, terminate/2, code_change/3,
+ handle_info/2, handle_call/3, handle_event/2]).
+
+-include_lib("wx/include/wx.hrl").
+
+-record(state,
+ {
+ parent,
+ config
+ }).
+
+start(Config) ->
+ wx_object:start_link(?MODULE, Config, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init(Config) ->
+ wx:batch(fun() -> do_init(Config) end).
+
+do_init(Config) ->
+ Parent = proplists:get_value(parent, Config),
+ Panel = wxPanel:new(Parent, []),
+
+ %% Setup sizers
+ MainSizer = wxBoxSizer:new(?wxVERTICAL),
+ DirPickerSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "wxDirPickerCtrl"}]),
+ FilePickerSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "wxFilePickerCtrl"}]),
+ FontPickerSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "wxFontPickerCtrl"}]),
+ DatePickerSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "wxDatePickerCtrl"}]),
+ ColourPickerSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "wxColourPickerCtrl"}]),
+
+ DirPicker = wxDirPickerCtrl:new(Panel, 1, [{path, "/"}]),
+ FilePicker = wxFilePickerCtrl:new(Panel, 2, [{path, "/"}]),
+ FontPicker = wxFontPickerCtrl:new(Panel, 3, []),
+ DatePicker = wxDatePickerCtrl:new(Panel, 4, []),
+ ColourPicker = wxColourPickerCtrl:new(Panel, 5, []),
+
+ wxColourPickerCtrl:connect(ColourPicker, command_colourpicker_changed, []),
+ wxDirPickerCtrl:connect(DirPicker, command_dirpicker_changed, []),
+ wxFilePickerCtrl:connect(FilePicker, command_filepicker_changed, []),
+ wxFontPickerCtrl:connect(FontPicker, command_fontpicker_changed, []),
+ wxDatePickerCtrl:connect(DatePicker, date_changed, []),
+
+ %% Add to sizers
+ PickerOptions = [{border, 4},{flag, ?wxALL bor ?wxEXPAND}],
+ wxSizer:add(DirPickerSizer, DirPicker, PickerOptions),
+ wxSizer:add(FilePickerSizer, FilePicker, PickerOptions),
+ wxSizer:add(FontPickerSizer, FontPicker, PickerOptions),
+ wxSizer:add(DatePickerSizer, DatePicker, PickerOptions),
+ wxSizer:add(ColourPickerSizer, ColourPicker, PickerOptions),
+
+ SizerOptions = [{flag, ?wxEXPAND}],
+ wxSizer:add(MainSizer, DirPickerSizer, SizerOptions),
+ wxSizer:add(MainSizer, FilePickerSizer, SizerOptions),
+ wxSizer:add(MainSizer, FontPickerSizer, SizerOptions),
+ wxSizer:add(MainSizer, DatePickerSizer, SizerOptions),
+ wxSizer:add(MainSizer, ColourPickerSizer, SizerOptions),
+
+ wxPanel:setSizer(Panel, MainSizer),
+ {Panel, #state{parent=Panel, config=Config}}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Async Events are handled in handle_event as in handle_info
+handle_event(#wx{event = #wxFontPicker{font = Font}}, State = #state{}) ->
+ demo:format(State#state.config, "Font changed to ~p.\n", [Font]),
+ {noreply, State};
+handle_event(#wx{event = #wxColourPicker{colour = Colour}}, State = #state{}) ->
+ demo:format(State#state.config, "Colour changed to ~p.\n", [Colour]),
+ {noreply, State};
+handle_event(#wx{event = #wxFileDirPicker{type = command_filepicker_changed,
+ path = Path}},
+ State = #state{}) ->
+ demo:format(State#state.config, "Filepicker changed to ~p.\n", [Path]),
+ {noreply, State};
+handle_event(#wx{event = #wxFileDirPicker{type = command_dirpicker_changed,
+ path = Path}},
+ State = #state{}) ->
+ demo:format(State#state.config, "Dirpicker changed to ~p.\n", [Path]),
+ {noreply, State};
+handle_event(#wx{event = #wxDate{date = Date}},
+ State = #state{}) ->
+ demo:format(State#state.config, "Datepicker changed to ~p.\n", [Date]),
+ {noreply, State};
+handle_event(Ev = #wx{}, State = #state{}) ->
+ demo:format(State#state.config, "Got Event ~p\n", [Ev]),
+ {noreply, State}.
+
+%% Callbacks handled as normal gen_server callbacks
+handle_info(Msg, State) ->
+ demo:format(State#state.config, "Got Info ~p\n", [Msg]),
+ {noreply, State}.
+
+handle_call(Msg, _From, State) ->
+ demo:format(State#state.config, "Got Call ~p\n", [Msg]),
+ {reply,{error, nyi}, State}.
+
+code_change(_, _, State) ->
+ {stop, ignore, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Local functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
diff --git a/lib/wx/examples/demo/ex_popupMenu.erl b/lib/wx/examples/demo/ex_popupMenu.erl
new file mode 100644
index 0000000000..8774dbef7b
--- /dev/null
+++ b/lib/wx/examples/demo/ex_popupMenu.erl
@@ -0,0 +1,150 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(ex_popupMenu).
+
+-behaviour(wx_object).
+
+%% Client API
+-export([start/1]).
+
+%% wx_object callbacks
+-export([init/1, terminate/2, code_change/3,
+ handle_info/2, handle_call/3, handle_event/2]).
+
+-include_lib("wx/include/wx.hrl").
+
+-record(state,
+ {
+ parent,
+ config,
+ menu
+ }).
+
+start(Config) ->
+ wx_object:start_link(?MODULE, Config, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init(Config) ->
+ wx:batch(fun() -> do_init(Config) end).
+
+do_init(Config) ->
+ Root = proplists:get_value(parent, Config),
+ Parent = wxPanel:new(Root,[]),
+ MainSizer = wxBoxSizer:new(?wxVERTICAL),
+ Box = wxStaticBox:new(Parent, ?wxID_ANY, "Popup Menu"),
+ Sz = wxStaticBoxSizer:new(Box, ?wxVERTICAL),
+ Text = wxStaticText:new(Parent, ?wxID_ANY, "Right click to open popup menu", []),
+ Panel = wxPanel:new(Parent),
+ wxPanel:connect(Panel, right_up),
+ Sizer = wxBoxSizer:new(?wxVERTICAL),
+ wxSizer:add(Sizer, Text, [{border, 20}, {flag, ?wxALL}]),
+ wxPanel:setSizer(Panel, Sizer),
+ wxSizer:add(Sz, Panel, [{proportion,1}, {flag, ?wxEXPAND}]),
+ wxSizer:layout(Sz),
+ PopupMenu = create_menu(),
+ wxSizer:add(MainSizer, Sz, [{proportion,1}, {flag, ?wxEXPAND}]),
+ wxWindow:setSizer(Parent, MainSizer),
+ {Parent, #state{parent=Parent, config=Config, menu=PopupMenu}}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Async Events are handled in handle_event as in handle_info
+handle_event(#wx{obj = Panel,
+ event = #wxMouse{type = right_up}},
+ State = #state{menu = Menu}) ->
+ %% Open the popup menu
+ wxWindow:popupMenu(Panel, Menu),
+ {noreply, State};
+handle_event(#wx{obj = Menu, id = Id,
+ event = #wxCommand{type = command_menu_selected}},
+ State = #state{}) ->
+ %% Get the selected item label
+ Label = wxMenu:getLabel(Menu, Id),
+ demo:format(State#state.config, "wxMenu clicked ~p\n", [Label]),
+ {noreply, State};
+handle_event(Ev, State) ->
+ demo:format(State#state.config, "Unexpected Event ~p\n", [Ev]),
+ {noreply, State}.
+
+%% Callbacks handled as normal gen_server callbacks
+handle_info(Msg, State) ->
+ demo:format(State#state.config, "Got Info ~p\n", [Msg]),
+ {noreply, State}.
+
+handle_call(Msg, _From, State) ->
+ demo:format(State#state.config, "Got Call ~p\n", [Msg]),
+ {reply,{error, nyi}, State}.
+
+code_change(_, _, State) ->
+ {stop, ignore, State}.
+
+terminate(_Reason, #state{menu=Popup}) ->
+ wxMenu:destroy(Popup),
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Local functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+create_menu() ->
+ Menu = wxMenu:new([]),
+ SubMenu = wxMenu:new([]),
+ SubMenu2 = wxMenu:new([]),
+
+ wxMenu:append(Menu, ?wxID_UNDO, "Undo", []),
+ wxMenu:append(Menu, ?wxID_REDO, "Redo", []),
+ wxMenu:append(Menu, ?wxID_HELP, "Help", []),
+ wxMenu:appendSeparator(Menu),
+ wxMenu:appendCheckItem(Menu, ?wxID_ANY, "Check item", []),
+ wxMenu:appendSeparator(Menu),
+ wxMenu:appendRadioItem(Menu, ?wxID_ANY, "Radio item 1", []),
+ wxMenu:appendRadioItem(Menu, ?wxID_ANY, "Radio item 2", []),
+ wxMenu:appendRadioItem(Menu, ?wxID_ANY, "Radio item 3", []),
+ wxMenu:appendRadioItem(Menu, ?wxID_ANY, "Radio item 4", []),
+
+ wxMenu:appendSeparator(Menu),
+ wxMenuItem:enable(wxMenu:append(Menu, ?wxID_ANY, "Disabled", []), [{enable,false}]),
+ wxMenu:appendSeparator(Menu),
+
+ wxMenu:append(SubMenu, ?wxID_ABOUT, "About", []),
+ wxMenu:append(SubMenu, ?wxID_ANY, "Sub Item2", []),
+ wxMenu:append(SubMenu, ?wxID_SAVE, "Save", []),
+ wxMenu:break(SubMenu),
+ wxMenu:append(SubMenu, ?wxID_EXIT, "Exit", []),
+ wxMenu:append(SubMenu, ?wxID_OPEN, "Open", []),
+ wxMenu:append(SubMenu, ?wxID_NEW, "New", []),
+ wxMenu:append(Menu, ?wxID_ANY, "Sub menu", SubMenu, []),
+
+ wxMenu:appendCheckItem(SubMenu2, ?wxID_ANY, "Check Item", []),
+ wxMenu:appendSeparator(SubMenu2),
+ wxMenu:append(SubMenu2, ?wxID_CLEAR, "Clear", []),
+ wxMenu:append(SubMenu2, ?wxID_ANY, "Sub Item", []),
+
+ Bitmap = wxArtProvider:getBitmap("wxART_NEW"),
+ AnotherSubMenu = wxMenuItem:new([{parentMenu, Menu},
+ {id, ?wxID_ANY},
+ {text, "Another sub menu"},
+ {subMenu, SubMenu2},
+ {kind, ?wxITEM_NORMAL}]),
+ wxMenuItem:setBitmap(AnotherSubMenu, Bitmap),
+ wxMenu:append(Menu, AnotherSubMenu),
+
+ wxMenu:connect(Menu, command_menu_selected),
+ wxMenu:connect(SubMenu, command_menu_selected),
+ wxMenu:connect(SubMenu2, command_menu_selected),
+ Menu.
diff --git a/lib/wx/examples/demo/ex_radioBox.erl b/lib/wx/examples/demo/ex_radioBox.erl
new file mode 100644
index 0000000000..8211aec4a2
--- /dev/null
+++ b/lib/wx/examples/demo/ex_radioBox.erl
@@ -0,0 +1,163 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(ex_radioBox).
+
+-behaviour(wx_object).
+
+-export([start/1, init/1, terminate/2, code_change/3,
+ handle_info/2, handle_call/3, handle_event/2]).
+
+-include_lib("wx/include/wx.hrl").
+
+-record(state,
+ {
+ parent,
+ config,
+ radio_box
+ }).
+
+start(Config) ->
+ wx_object:start_link(?MODULE, Config, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init(Config) ->
+ wx:batch(fun() -> do_init(Config) end).
+
+do_init(Config) ->
+ Parent = proplists:get_value(parent, Config),
+ Panel = wxPanel:new(Parent, []),
+
+ %% Setup sizers
+ MainSizer = wxBoxSizer:new(?wxVERTICAL),
+ Sizer = wxBoxSizer:new(?wxHORIZONTAL),
+
+ Choices = ["Item " ++ integer_to_list(Int) || Int <- lists:seq(1,12)],
+ RadioBox = wxRadioBox:new(Panel, 1, "wxRadioBox Horizontal",
+ ?wxDefaultPosition,
+ ?wxDefaultSize,
+ Choices,
+ [{majorDim, 3},
+ {style, ?wxHORIZONTAL}]),
+ wxRadioBox:connect(RadioBox, command_radiobox_selected),
+
+ RadioButtonSizer = create_radio_buttons(Panel),
+
+ CheckSizer = create_checkboxes(Panel),
+
+ %% Add to sizers
+ wxSizer:add(Sizer, RadioButtonSizer),
+ wxSizer:addSpacer(Sizer, 20),
+ wxSizer:add(Sizer, CheckSizer),
+
+ wxSizer:add(MainSizer, RadioBox),
+ wxSizer:addSpacer(MainSizer, 20),
+ wxSizer:add(MainSizer, Sizer),
+
+ wxPanel:setSizer(Panel, MainSizer),
+ {Panel, #state{parent=Panel, config=Config,
+ radio_box = RadioBox}}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Async Events are handled in handle_event as in handle_info
+handle_event(#wx{event = #wxCommand{type = command_radiobox_selected,
+ cmdString = Item}},
+ State = #state{}) ->
+ demo:format(State#state.config,"wxRadioBox selected ~p\n",[Item]),
+ {noreply, State};
+handle_event(#wx{obj = Checkbox,
+ event = #wxCommand{type = command_checkbox_clicked,
+ commandInt = Int}},
+ State = #state{config = Config}) ->
+ Label = wxCheckBox:getLabel(Checkbox),
+ case Int of
+ 0 -> demo:format(Config,"wxCheckBox deselected ~p\n",[Label]);
+ 1 -> demo:format(Config,"wxCheckBox selected ~p \n",[Label]);
+ 2 -> demo:format(Config,"wxCheckBox middle-state ~p\n",[Label])
+ end,
+ {noreply, State};
+handle_event(#wx{obj = RadioButton,
+ event = #wxCommand{type = command_radiobutton_selected}},
+ State = #state{}) ->
+ Label = wxRadioButton:getLabel(RadioButton),
+ demo:format(State#state.config,"wxRadioButton selected ~p\n",[Label]),
+ {noreply, State}.
+
+%% Callbacks handled as normal gen_server callbacks
+handle_info(Msg, State) ->
+ demo:format(State#state.config, "Got Info ~p\n",[Msg]),
+ {noreply, State}.
+
+handle_call(Msg, _From, State) ->
+ demo:format(State#state.config,"Got Call ~p\n",[Msg]),
+ {reply, {error, nyi}, State}.
+
+
+code_change(_, _, State) ->
+ {stop, ignore, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Local functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+create_checkboxes(Panel) ->
+ CheckSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "wxCheckBox"}]),
+
+ CheckBoxes =
+ [wxCheckBox:new(Panel, ?wxID_ANY, "Label1", []),
+ wxCheckBox:new(Panel, ?wxID_ANY, "Label2", []),
+ wxCheckBox:new(Panel, ?wxID_ANY, "Label3", []),
+ wxCheckBox:new(Panel, ?wxID_ANY, "3-state checkbox",
+ [{style, ?wxCHK_3STATE bor
+ ?wxCHK_ALLOW_3RD_STATE_FOR_USER}]),
+ wxCheckBox:new(Panel, ?wxID_ANY, "Right aligned",
+ [{style, ?wxALIGN_RIGHT}])],
+ Fun =
+ fun(Item) ->
+ wxCheckBox:connect(Item, command_checkbox_clicked),
+ wxSizer:add(CheckSizer, Item)
+ end,
+ wx:foreach(Fun, CheckBoxes),
+ CheckSizer.
+
+
+create_radio_buttons(Panel) ->
+ RadioButtonSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "wxRadioButton"}]),
+
+ Buttons =
+ [wxRadioButton:new(Panel, ?wxID_ANY, "Group1 Radio1",
+ [{style, ?wxRB_GROUP}]),
+ wxRadioButton:new(Panel, ?wxID_ANY, "Group1 Radio2", []),
+ wxRadioButton:new(Panel, ?wxID_ANY, "Group1 Radio3", []),
+ wxRadioButton:new(Panel, ?wxID_ANY, "Group2 Radio1",
+ [{style, ?wxRB_GROUP}]),
+ wxRadioButton:new(Panel, ?wxID_ANY, "Group2 Radio2", []),
+ wxRadioButton:new(Panel, ?wxID_ANY, "Group2 Radio3", [])],
+ Fun =
+ fun(Item) ->
+ wxRadioButton:connect(Item, command_radiobutton_selected),
+ wxSizer:add(RadioButtonSizer, Item)
+ end,
+
+ wx:foreach(Fun, Buttons),
+ RadioButtonSizer.
diff --git a/lib/wx/examples/demo/ex_sashWindow.erl b/lib/wx/examples/demo/ex_sashWindow.erl
new file mode 100644
index 0000000000..dd05f4e45f
--- /dev/null
+++ b/lib/wx/examples/demo/ex_sashWindow.erl
@@ -0,0 +1,128 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(ex_sashWindow).
+
+-behaviour(wx_object).
+
+%% Client API
+-export([start/1]).
+
+%% wx_object callbacks
+-export([init/1, terminate/2, code_change/3,
+ handle_info/2, handle_call/3, handle_event/2]).
+
+-include_lib("wx/include/wx.hrl").
+
+-record(state,
+ {
+ parent,
+ config,
+ top_sash,
+ bottom_sash
+ }).
+
+-define(TOP_SASH, 1).
+-define(BOTTOM_SASH, 2).
+
+start(Config) ->
+ wx_object:start_link(?MODULE, Config, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init(Config) ->
+ wx:batch(fun() -> do_init(Config) end).
+
+do_init(Config) ->
+ Parent = proplists:get_value(parent, Config),
+ Panel = wxPanel:new(Parent, []),
+
+ %% Setup sizers
+ MainSizer = wxBoxSizer:new(?wxVERTICAL),
+ Sizer = wxBoxSizer:new(?wxVERTICAL),
+
+ TopSash = wxSashWindow:new(Panel, [{id, ?TOP_SASH},
+ {style, ?wxSW_3D}]),
+ Win1 = wxPanel:new(TopSash, []),
+ wxStaticText:new(Win1, ?wxID_ANY, "This is the top sash", []),
+ BottomSash = wxSashWindow:new(Panel, [{id, ?BOTTOM_SASH},
+ {style, ?wxSW_3D}]),
+ Win2 = wxPanel:new(BottomSash, []),
+ wxStaticText:new(Win2, ?wxID_ANY, "This is the bottom sash", []),
+
+ %% Make the bottom edge of the top sash dragable
+ wxSashWindow:setSashVisible(TopSash, ?wxSASH_BOTTOM, true),
+ wxPanel:connect(Panel, sash_dragged),
+ wxPanel:connect(Panel, size),
+
+ %% Add to sizers
+ Options = [{flag, ?wxEXPAND}, {proportion, 1}],
+ wxSizer:add(Sizer, TopSash, Options),
+ wxSizer:add(Sizer, BottomSash, Options),
+ wxSizer:add(MainSizer, Sizer, Options),
+ wxPanel:setSizer(Panel, MainSizer),
+ wxSizer:fit(MainSizer, Panel),
+ wxSizer:setSizeHints(MainSizer, Panel),
+ {Panel, #state{parent=Panel, config=Config,
+ top_sash = TopSash, bottom_sash = BottomSash}}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Async Events are handled in handle_event as in handle_info
+handle_event(#wx{event = #wxSash{dragRect = {_X,Y, _W, H}}},
+ State = #state{top_sash = TopSash,
+ bottom_sash = BottomSash}) ->
+ {OldW, OldH} = wxPanel:getSize(State#state.parent),
+ Diff = OldH - H,
+ {OldX, _} = wxSashWindow:getPosition(BottomSash),
+ wxSashWindow:setMinSize(BottomSash, {OldW,Diff}),
+ wxSashWindow:setMinSize(TopSash, {OldW,H}),
+ wxSashWindow:setSize(BottomSash, {OldX, Y,OldW,Diff}),
+ wxSashWindow:setSize(TopSash, {OldW,H}),
+ wxPanel:refresh(State#state.parent),
+ {noreply, State};
+handle_event(#wx{event = #wxSize{size = {W, H}}},
+ State = #state{top_sash = TopSash,
+ bottom_sash = BottomSash}) ->
+ wxSashWindow:setMinSize(TopSash, {W, H div 2}),
+ wxSashWindow:setMinSize(BottomSash, {W, H div 2}),
+ wxSashWindow:setSize(TopSash, {W, H div 2}),
+ wxSashWindow:setSize(BottomSash, {0,H div 2,W,H div 2}),
+ wxPanel:refresh(State#state.parent),
+ {noreply, State};
+handle_event(Ev = #wx{}, State = #state{}) ->
+ demo:format(State#state.config, "Got Event ~p\n", [Ev]),
+ {noreply, State}.
+
+%% Callbacks handled as normal gen_server callbacks
+handle_info(Msg, State) ->
+ demo:format(State#state.config, "Got Info ~p\n", [Msg]),
+ {noreply, State}.
+
+handle_call(Msg, _From, State) ->
+ demo:format(State#state.config, "Got Call ~p\n", [Msg]),
+ {reply,{error, nyi}, State}.
+
+code_change(_, _, State) ->
+ {stop, ignore, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Local functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
diff --git a/lib/wx/examples/demo/ex_sizers.erl b/lib/wx/examples/demo/ex_sizers.erl
new file mode 100644
index 0000000000..2cc6efd503
--- /dev/null
+++ b/lib/wx/examples/demo/ex_sizers.erl
@@ -0,0 +1,436 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(ex_sizers).
+
+-behaviour(wx_object).
+
+%% Client API
+-export([start/1]).
+
+%% wx_object callbacks
+-export([init/1, terminate/2, code_change/3,
+ handle_info/2, handle_call/3, handle_event/2]).
+
+-include_lib("wx/include/wx.hrl").
+
+-record(state,
+ {
+ parent,
+ config
+ }).
+
+start(Config) ->
+ wx_object:start_link(?MODULE, Config, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init(Config) ->
+ wx:batch(fun() -> do_init(Config) end).
+
+do_init(Config) ->
+ Parent = proplists:get_value(parent, Config),
+ Panel = wxPanel:new(Parent, []),
+
+ %% Setup sizers
+ MainSizer = wxBoxSizer:new(?wxVERTICAL),
+ Sizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "wxSizer"}]),
+
+ Choices = ["Vertical Example",
+ "Horizontal Example",
+ "Add A Strechable",
+ "More Than One Strechable",
+ "Weighting Factor",
+ "Edge Affinity",
+ "Spacer",
+ "Centering In Avalible Space",
+ "Simple Border",
+ "East And West Border",
+ "North And South Border",
+ "Box In Box",
+ "Boxes Inside A Border",
+ "Border In A Box",
+ "Simple Grid",
+ "More Grid Features",
+ "Flexible Grid",
+ "Grid With Alignment",
+ "Proportional Resize With Alignments"],
+
+ ListBox = wxListBox:new(Panel, ?wxID_ANY, [{choices, Choices}]),
+ wxListBox:connect(ListBox, command_listbox_doubleclicked),
+
+ %% Add to sizers
+ wxSizer:add(Sizer, ListBox, [{flag, ?wxEXPAND}]),
+ wxSizer:add(MainSizer, Sizer, [{flag, ?wxEXPAND}, {proportion, 1}]),
+
+ wxPanel:setSizer(Panel, MainSizer),
+ {Panel, #state{parent=Panel, config=Config}}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Async Events are handled in handle_event as in handle_info
+handle_event(#wx{event = #wxCommand{type = command_listbox_doubleclicked,
+ cmdString = Choice}},
+ State = #state{}) ->
+ create_example(State#state.parent, Choice),
+ {noreply, State};
+handle_event(Ev = #wx{}, State = #state{}) ->
+ demo:format(State#state.config, "Got Event ~p\n", [Ev]),
+ {noreply, State}.
+
+%% Callbacks handled as normal gen_server callbacks
+handle_info(Msg, State) ->
+ demo:format(State#state.config, "Got Info ~p\n", [Msg]),
+ {noreply, State}.
+
+handle_call(Msg, _From, State) ->
+ demo:format(State#state.config, "Got Call ~p\n", [Msg]),
+ {reply,{error, nyi}, State}.
+
+code_change(_, _, State) ->
+ {stop, ignore, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Local functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+create_example(Parent, Example) ->
+ Frame = wxFrame:new(Parent, ?wxID_ANY, Example,
+ [{style, ?wxDEFAULT_FRAME_STYLE bor ?wxFRAME_FLOAT_ON_PARENT}]),
+ wxFrame:center(Frame),
+ Panel = wxPanel:new(Frame, []),
+ Sizer =
+ case Example of
+ "Proportional Resize With Alignments" ->
+ proportional_resize_with_alignments(Panel);
+ "Grid With Alignment" ->
+ grid_with_alignment(Panel);
+ "Flexible Grid" ->
+ flexible_grid(Panel);
+ "More Grid Features" ->
+ more_grid_features(Panel);
+ "Simple Grid" ->
+ simple_grid(Panel);
+ "Border In A Box" ->
+ border_in_a_box(Panel);
+ "Boxes Inside A Border" ->
+ boxes_inside_a_border(Panel);
+ "Box In Box" ->
+ box_in_box(Panel);
+ "East And West Border" ->
+ east_and_west_border(Panel);
+ "North And South Border" ->
+ north_and_south_border(Panel);
+ "Simple Border" ->
+ simple_border(Panel);
+ "Centering In Avalible Space" ->
+ centering_in_avalible_space(Panel);
+ "Spacer" ->
+ spacer(Panel);
+ "Edge Affinity" ->
+ edge_affinity(Panel);
+ "Weighting Factor" ->
+ weighting_factor(Panel);
+ "More Than One Strechable" ->
+ more_than_one_strechable(Panel);
+ "Add A Strechable" ->
+ add_a_strechable(Panel);
+ "Vertical Example" ->
+ vertical(Panel);
+ "Horizontal Example" ->
+ horizontal(Panel)
+ end,
+ wxPanel:setSizer(Panel, Sizer),
+ wxSizer:fit(Sizer, Panel),
+ wxFrame:createStatusBar(Frame),
+ wxFrame:setStatusText(Frame, "Resize window to see how the sizers respond.."),
+ wxFrame:fit(Frame),
+ wxFrame:show(Frame).
+
+create_box(Parent) ->
+ Win = wxWindow:new(Parent, ?wxID_ANY, [{style, ?wxBORDER_SIMPLE},
+ {size, {50,25}}]),
+ wxWindow:setBackgroundColour(Win, ?wxWHITE),
+ Win.
+
+
+vertical(Parent) ->
+ Sizer = wxBoxSizer:new(?wxVERTICAL),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ Sizer.
+
+
+horizontal(Parent) ->
+ Sizer = wxBoxSizer:new(?wxHORIZONTAL),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ Sizer.
+
+add_a_strechable(Parent) ->
+ Sizer = wxBoxSizer:new(?wxHORIZONTAL),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]),
+ Sizer.
+
+more_than_one_strechable(Parent) ->
+ Sizer = wxBoxSizer:new(?wxHORIZONTAL),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]),
+ Sizer.
+
+weighting_factor(Parent) ->
+ Sizer = wxBoxSizer:new(?wxHORIZONTAL),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 3}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]),
+ Sizer.
+
+edge_affinity(Parent) ->
+ Sizer = wxBoxSizer:new(?wxHORIZONTAL),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 1}, {flag, ?wxALIGN_TOP}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 1}, {flag, ?wxALIGN_CENTER}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 1}, {flag, ?wxALIGN_BOTTOM}]),
+ Sizer.
+
+spacer(Parent) ->
+ Sizer = wxBoxSizer:new(?wxHORIZONTAL),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, 60,20, [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]),
+ Sizer.
+
+centering_in_avalible_space(Parent) ->
+ Sizer = wxBoxSizer:new(?wxVERTICAL),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, 0,0, [{proportion, 1}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxALIGN_CENTER}]),
+ wxSizer:add(Sizer, 0,0, [{proportion, 1}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ Sizer.
+
+simple_border(Parent) ->
+ Sizer = wxBoxSizer:new(?wxHORIZONTAL),
+ Win = create_box(Parent),
+ wxWindow:setSize(Win, 80,80),
+ wxSizer:add(Sizer, Win, [{proportion, 1}, {flag, ?wxEXPAND bor ?wxALL},
+ {border, 15}]),
+ Sizer.
+
+east_and_west_border(Parent) ->
+ Sizer = wxBoxSizer:new(?wxHORIZONTAL),
+ Win = create_box(Parent),
+ wxWindow:setSize(Win, 80,80),
+ wxSizer:add(Sizer, Win, [{proportion, 1}, {flag, ?wxEXPAND bor ?wxEAST bor ?wxWEST},
+ {border, 15}]),
+ Sizer.
+
+north_and_south_border(Parent) ->
+ Sizer = wxBoxSizer:new(?wxHORIZONTAL),
+ Win = create_box(Parent),
+ wxWindow:setSize(Win, 80,80),
+ wxSizer:add(Sizer, Win, [{proportion, 1}, {flag, ?wxEXPAND bor ?wxNORTH bor ?wxSOUTH},
+ {border, 15}]),
+ Sizer.
+
+
+box_in_box(Parent) ->
+ Sizer = wxBoxSizer:new(?wxVERTICAL),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+
+ Sizer2 = wxBoxSizer:new(?wxHORIZONTAL),
+ wxSizer:add(Sizer2, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer2, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer2, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer2, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+
+ Sizer3 = wxBoxSizer:new(?wxVERTICAL),
+ wxSizer:add(Sizer3, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer3, create_box(Parent), [{proportion, 2}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer3, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer3, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]),
+
+ wxSizer:add(Sizer2, Sizer3, [{proportion, 1}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, Sizer2, [{proportion, 1}, {flag, ?wxEXPAND}]),
+
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ Sizer.
+
+boxes_inside_a_border(Parent) ->
+ Border = wxBoxSizer:new(?wxHORIZONTAL),
+ Sizer = add_a_strechable(Parent),
+ wxSizer:add(Border, Sizer, [{proportion, 1}, {flag, ?wxEXPAND bor ?wxALL},
+ {border, 15}]),
+ Border.
+
+border_in_a_box(Parent) ->
+ InsideBox = wxBoxSizer:new(?wxHORIZONTAL),
+
+ Sizer2 = wxBoxSizer:new(?wxHORIZONTAL),
+ wxSizer:add(Sizer2, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer2, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer2, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer2, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer2, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+
+ wxSizer:add(InsideBox, Sizer2, [{proportion, 0}, {flag, ?wxEXPAND}]),
+
+ Border = wxBoxSizer:new(?wxHORIZONTAL),
+ wxSizer:add(Border, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND bor ?wxALL}]),
+ wxSizer:add(InsideBox, Border, [{proportion, 1}, {flag, ?wxEXPAND bor ?wxALL},
+ {border, 20}]),
+
+
+ Sizer3 = wxBoxSizer:new(?wxVERTICAL),
+ wxSizer:add(Sizer3, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer3, create_box(Parent), [{proportion, 2}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer3, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer3, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]),
+
+ wxSizer:add(InsideBox, Sizer3, [{proportion, 1}, {flag, ?wxEXPAND}]),
+
+ OutsideBox = wxBoxSizer:new(?wxVERTICAL),
+ wxSizer:add(OutsideBox, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(OutsideBox, InsideBox, [{proportion, 1}, {flag, ?wxEXPAND}]),
+ wxSizer:add(OutsideBox, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ OutsideBox.
+
+simple_grid(Parent) ->
+ GridSizer = wxGridSizer:new(3, 3, 2, 2),
+
+ wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ GridSizer.
+
+more_grid_features(Parent) ->
+ GridSizer = wxGridSizer:new(3, 3, 1, 1), % rows, cols, vgap, hgap
+
+ Sizer = wxBoxSizer:new(?wxVERTICAL),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]),
+
+ GridSizer2 = wxGridSizer:new(2, 2, 4, 4),
+ wxSizer:add(GridSizer2, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(GridSizer2, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(GridSizer2, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(GridSizer2, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+
+ wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxALIGN_RIGHT bor ?wxALIGN_BOTTOM}]),
+ wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxALIGN_LEFT bor ?wxALIGN_BOTTOM}]),
+ wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxALIGN_CENTER}]),
+ wxSizer:add(GridSizer, Sizer, [{proportion, 0}, {flag, ?wxEXPAND bor ?wxALL},
+ {border, 10}]),
+ wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(GridSizer, GridSizer2, [{proportion, 0}, {flag, ?wxEXPAND bor ?wxALL},
+ {border, 4}]),
+ GridSizer.
+
+
+flexible_grid(Parent) ->
+ FlexGridSizer = wxFlexGridSizer:new(3, 3, 2, 2), % rows, cols, vgap, hgap
+ wxSizer:add(FlexGridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(FlexGridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(FlexGridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(FlexGridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(FlexGridSizer, 175, 50, []),
+ wxSizer:add(FlexGridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(FlexGridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(FlexGridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+ wxSizer:add(FlexGridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]),
+
+ wxFlexGridSizer:addGrowableRow(FlexGridSizer, 0),
+ wxFlexGridSizer:addGrowableRow(FlexGridSizer, 2),
+ wxFlexGridSizer:addGrowableCol(FlexGridSizer, 1),
+ FlexGridSizer.
+
+grid_with_alignment(Parent) ->
+ GridSizer = wxGridSizer:new(3, 3, 2, 2), % rows, cols, vgap, hgap
+
+ wxSizer:add(GridSizer, create_box(Parent),
+ [{proportion, 0}, {flag, ?wxALIGN_TOP bor ?wxALIGN_LEFT}]),
+ wxSizer:add(GridSizer, create_box(Parent),
+ [{proportion, 0}, {flag, ?wxALIGN_TOP bor ?wxALIGN_CENTER_HORIZONTAL}]),
+ wxSizer:add(GridSizer, create_box(Parent),
+ [{proportion, 0}, {flag, ?wxALIGN_TOP bor ?wxALIGN_RIGHT}]),
+ wxSizer:add(GridSizer, create_box(Parent),
+ [{proportion, 0}, {flag, ?wxALIGN_CENTER_VERTICAL bor ?wxALIGN_LEFT}]),
+ wxSizer:add(GridSizer, create_box(Parent),
+ [{proportion, 0}, {flag, ?wxALIGN_CENTER}]),
+ wxSizer:add(GridSizer, create_box(Parent),
+ [{proportion, 0}, {flag, ?wxALIGN_CENTER_VERTICAL bor ?wxALIGN_RIGHT}]),
+ wxSizer:add(GridSizer, create_box(Parent),
+ [{proportion, 0}, {flag, ?wxALIGN_BOTTOM bor ?wxALIGN_LEFT}]),
+ wxSizer:add(GridSizer, create_box(Parent),
+ [{proportion, 0}, {flag, ?wxALIGN_BOTTOM bor ?wxALIGN_CENTER_HORIZONTAL}]),
+ wxSizer:add(GridSizer, create_box(Parent),
+ [{proportion, 0}, {flag, ?wxALIGN_BOTTOM bor ?wxALIGN_RIGHT}]),
+ GridSizer.
+
+proportional_resize_with_alignments(Parent) ->
+ GridSizer = wxGridSizer:new(3, 3, 2, 2), % rows, cols, vgap, hgap
+
+ wxSizer:add(GridSizer, create_box(Parent),
+ [{proportion, 0}, {flag, ?wxSHAPED bor ?wxALIGN_TOP bor ?wxALIGN_LEFT}]),
+ wxSizer:add(GridSizer, create_box(Parent),
+ [{proportion, 0}, {flag, ?wxSHAPED bor ?wxALIGN_TOP bor ?wxALIGN_CENTER_HORIZONTAL}]),
+ wxSizer:add(GridSizer, create_box(Parent),
+ [{proportion, 0}, {flag, ?wxSHAPED bor ?wxALIGN_TOP bor ?wxALIGN_RIGHT}]),
+ wxSizer:add(GridSizer, create_box(Parent),
+ [{proportion, 0}, {flag, ?wxSHAPED bor ?wxALIGN_CENTER_VERTICAL bor ?wxALIGN_LEFT}]),
+ wxSizer:add(GridSizer, create_box(Parent),
+ [{proportion, 0}, {flag, ?wxSHAPED bor ?wxALIGN_CENTER}]),
+ wxSizer:add(GridSizer, create_box(Parent),
+ [{proportion, 0}, {flag, ?wxSHAPED bor ?wxALIGN_CENTER_VERTICAL bor ?wxALIGN_RIGHT}]),
+ wxSizer:add(GridSizer, create_box(Parent),
+ [{proportion, 0}, {flag, ?wxSHAPED bor ?wxALIGN_BOTTOM bor ?wxALIGN_LEFT}]),
+ wxSizer:add(GridSizer, create_box(Parent),
+ [{proportion, 0}, {flag, ?wxSHAPED bor ?wxALIGN_BOTTOM bor ?wxALIGN_CENTER_HORIZONTAL}]),
+ wxSizer:add(GridSizer, create_box(Parent),
+ [{proportion, 0}, {flag, ?wxSHAPED bor ?wxALIGN_BOTTOM bor ?wxALIGN_RIGHT}]),
+ GridSizer.
+
diff --git a/lib/wx/examples/demo/ex_slider.erl b/lib/wx/examples/demo/ex_slider.erl
new file mode 100644
index 0000000000..7b669d96f6
--- /dev/null
+++ b/lib/wx/examples/demo/ex_slider.erl
@@ -0,0 +1,113 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(ex_slider).
+
+-behaviour(wx_object).
+
+-export([start/1, init/1, terminate/2, code_change/3,
+ handle_info/2, handle_call/3, handle_event/2]).
+
+-include_lib("wx/include/wx.hrl").
+
+-record(state,
+ {
+ parent,
+ config
+ }).
+
+start(Config) ->
+ wx_object:start_link(?MODULE, Config, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init(Config) ->
+ wx:batch(fun() -> do_init(Config) end).
+
+do_init(Config) ->
+ Parent = proplists:get_value(parent, Config),
+ Panel = wxPanel:new(Parent, []),
+
+ %% Setup sizers
+ MainSizer = wxBoxSizer:new(?wxVERTICAL),
+ Sizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "Horizontal wxSlider"}]),
+ Sizer2 = wxStaticBoxSizer:new(?wxHORIZONTAL, Panel,
+ [{label, "Vertical wxSlider"}]),
+
+ %% Setup slider with range from 0 to 100
+ %% and a start value of 25
+ Min = 0,
+ Max = 100,
+ StartValue = 25,
+ %% Horizontal slider (default) with label
+ Slider = wxSlider:new(Panel, 1, StartValue, Min, Max,
+ [{style, ?wxSL_HORIZONTAL bor
+ ?wxSL_LABELS}]),
+ %% Horizontal inverse slider with label
+ InverseSlider = wxSlider:new(Panel, 2, StartValue, Min, Max,
+ [{style, ?wxSL_HORIZONTAL bor
+ ?wxSL_LABELS bor
+ ?wxSL_INVERSE}]),
+ VerticalSlider = wxSlider:new(Panel, 3, StartValue, Min, Max,
+ [{style, ?wxSL_VERTICAL bor
+ ?wxSL_LABELS}]),
+ InverseVerticalSlider = wxSlider:new(Panel, 4, StartValue, Min, Max,
+ [{style, ?wxSL_VERTICAL bor
+ ?wxSL_LABELS bor
+ ?wxSL_INVERSE}]),
+
+ %% Add to sizers
+ wxSizer:add(Sizer, Slider, [{flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer, InverseSlider, [{flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer2, VerticalSlider, [{flag, ?wxEXPAND},
+ {proportion, 1}]),
+ wxSizer:add(Sizer2, InverseVerticalSlider, [{flag, ?wxEXPAND},
+ {proportion, 1}]),
+
+ wxSizer:add(MainSizer, Sizer, [{flag, ?wxEXPAND}]),
+ wxSizer:add(MainSizer, Sizer2, [{flag, ?wxEXPAND},
+ {proportion, 1}]),
+
+ wxPanel:setSizer(Panel, MainSizer),
+ {Panel, #state{parent=Panel, config=Config}}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Async Events are handled in handle_event as in handle_info
+handle_event(Ev = #wx{}, State = #state{}) ->
+ demo:format(State#state.config,"Got Event ~p\n",[Ev]),
+ {noreply, State}.
+
+%% Callbacks handled as normal gen_server callbacks
+handle_info(Msg, State) ->
+ demo:format(State#state.config, "Got Info ~p\n",[Msg]),
+ {noreply, State}.
+
+handle_call(Msg, _From, State) ->
+ demo:format(State#state.config,"Got Call ~p\n",[Msg]),
+ {reply, {error, nyi},State}.
+
+code_change(_, _, State) ->
+ {stop, ignore, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Local functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
diff --git a/lib/wx/examples/demo/ex_splitterWindow.erl b/lib/wx/examples/demo/ex_splitterWindow.erl
new file mode 100644
index 0000000000..c135f298fa
--- /dev/null
+++ b/lib/wx/examples/demo/ex_splitterWindow.erl
@@ -0,0 +1,102 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(ex_splitterWindow).
+
+-behaviour(wx_object).
+
+%% Client API
+-export([start/1]).
+
+%% wx_object callbacks
+-export([init/1, terminate/2, code_change/3,
+ handle_info/2, handle_call/3, handle_event/2]).
+
+-include_lib("wx/include/wx.hrl").
+
+-record(state,
+ {
+ parent,
+ config
+ }).
+
+start(Config) ->
+ wx_object:start_link(?MODULE, Config, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init(Config) ->
+ wx:batch(fun() -> do_init(Config) end).
+
+do_init(Config) ->
+ Parent = proplists:get_value(parent, Config),
+ Panel = wxPanel:new(Parent, [{size, {100, 100}}]),
+
+ %% Setup sizers
+ MainSizer = wxBoxSizer:new(?wxVERTICAL),
+ Sizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "wxSplitterWindow"}]),
+
+ Splitter = wxSplitterWindow:new(Panel, []),
+
+ Win1 = wxTextCtrl:new(Splitter, 1, [{value, "Splitted Window 1"},
+ {style, ?wxDEFAULT bor ?wxTE_MULTILINE}]),
+ Win2 = wxTextCtrl:new(Splitter, 1, [{value, "Splitted Window 1"},
+ {style, ?wxDEFAULT bor ?wxTE_MULTILINE}]),
+
+ wxSplitterWindow:splitVertically(Splitter, Win1, Win2),
+ wxSplitterWindow:setSashGravity(Splitter, 0.5),
+ %% Set pane-size =/= 0 to not unsplit on doubleclick
+ %% on the splitter
+ wxSplitterWindow:setMinimumPaneSize(Splitter,50),
+
+ %% Add to sizers
+ wxSizer:add(Sizer, Splitter, [{flag, ?wxEXPAND},
+ {proportion, 1}]),
+
+ wxSizer:add(MainSizer, Sizer, [{proportion, 1},
+ {flag, ?wxEXPAND}]),
+ wxPanel:connect(Panel, command_splitter_sash_pos_changed),
+ wxPanel:setSizer(Panel, MainSizer),
+ {Panel, #state{parent=Panel, config=Config}}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Async Events are handled in handle_event as in handle_info
+handle_event(#wx{event = #wxSplitter{type = command_splitter_sash_pos_changed}},
+ State = #state{}) ->
+ demo:format(State#state.config, "Splitter pos changed.\n", []),
+ {noreply, State}.
+
+%% Callbacks handled as normal gen_server callbacks
+handle_info(Msg, State) ->
+ demo:format(State#state.config, "Got Info ~p\n", [Msg]),
+ {noreply, State}.
+
+handle_call(Msg, _From, State) ->
+ demo:format(State#state.config, "Got Call ~p\n", [Msg]),
+ {reply,{error, nyi}, State}.
+
+code_change(_, _, State) ->
+ {stop, ignore, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Local functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
diff --git a/lib/wx/examples/demo/ex_static.erl b/lib/wx/examples/demo/ex_static.erl
new file mode 100644
index 0000000000..67061520c4
--- /dev/null
+++ b/lib/wx/examples/demo/ex_static.erl
@@ -0,0 +1,117 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(ex_static).
+
+-behaviour(wx_object).
+
+%% Client API
+-export([start/1]).
+
+%% wx_object callbacks
+-export([init/1, terminate/2, code_change/3,
+ handle_info/2, handle_call/3, handle_event/2]).
+
+-include_lib("wx/include/wx.hrl").
+
+-record(state,
+ {
+ parent,
+ config
+ }).
+
+start(Config) ->
+ wx_object:start_link(?MODULE, Config, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init(Config) ->
+ wx:batch(fun() -> do_init(Config) end).
+
+do_init(Config) ->
+ Parent = proplists:get_value(parent, Config),
+ Panel = wxScrolledWindow:new(Parent, []),
+ wxScrolledWindow:setScrollRate(Panel, 5, 5),
+
+ %% Setup sizers
+ MainSizer = wxBoxSizer:new(?wxVERTICAL),
+ TextSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "wxStaticText"}]),
+ BitmapSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "wxStaticBitmap"}]),
+ LineSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "wxStaticLine"}]),
+
+ %% Create static texts
+ Texts = [wxStaticText:new(Panel, 1, "This is a regular text (left aligned)", []),
+ wxStaticText:new(Panel, 2, "This is a centered text",
+ [{style, ?wxALIGN_CENTER bor ?wxST_NO_AUTORESIZE}]),
+ wxStaticText:new(Panel, 3, "This is a right aligned text",
+ [{style, ?wxALIGN_RIGHT bor ?wxST_NO_AUTORESIZE}])],
+
+
+ Image = wxImage:new("image.jpg", []),
+ Bitmap = wxBitmap:new(wxImage:scale(Image,
+ round(wxImage:getWidth(Image)*1.5),
+ round(wxImage:getHeight(Image)*1.5),
+ [{quality, ?wxIMAGE_QUALITY_HIGH}])),
+ StaticBitmap = wxStaticBitmap:new(Panel, 1, Bitmap),
+
+ Line = wxStaticLine:new(Panel, [{style, ?wxLI_HORIZONTAL}]),
+ Line2 = wxStaticLine:new(Panel, [{style, ?wxLI_VERTICAL},
+ {size, {-1, 100}}]),
+
+ %% Add to sizers
+ [wxSizer:add(TextSizer, Text, [{flag, ?wxEXPAND bor ?wxALL},
+ {border, 10}]) || Text <- Texts],
+ wxSizer:add(BitmapSizer, StaticBitmap, []),
+ wxSizer:add(LineSizer, Line, [{flag, ?wxTOP bor ?wxBOTTOM bor ?wxEXPAND},
+ {border, 10}]),
+ wxSizer:add(LineSizer, Line2, [{flag, ?wxLEFT},
+ {border, 50}]),
+
+ wxSizer:add(MainSizer, TextSizer, [{flag, ?wxEXPAND}]),
+ wxSizer:add(MainSizer, BitmapSizer, []),
+ wxSizer:add(MainSizer, LineSizer, [{flag, ?wxEXPAND}]),
+
+ wxPanel:setSizer(Panel, MainSizer),
+ {Panel, #state{parent=Panel, config=Config}}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Async Events are handled in handle_event as in handle_info
+handle_event(#wx{}, State = #state{}) ->
+ {noreply, State}.
+
+%% Callbacks handled as normal gen_server callbacks
+handle_info(Msg, State) ->
+ demo:format(State#state.config, "Got Info ~p\n", [Msg]),
+ {noreply, State}.
+
+handle_call(Msg, _From, State) ->
+ demo:format(State#state.config, "Got Call ~p\n", [Msg]),
+ {reply,{error, nyi}, State}.
+
+code_change(_, _, State) ->
+ {stop, ignore, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Local functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
diff --git a/lib/wx/examples/demo/ex_textCtrl.erl b/lib/wx/examples/demo/ex_textCtrl.erl
new file mode 100644
index 0000000000..95837c7c4c
--- /dev/null
+++ b/lib/wx/examples/demo/ex_textCtrl.erl
@@ -0,0 +1,104 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(ex_textCtrl).
+
+-behaviour(wx_object).
+
+-export([start/1, init/1, terminate/2, code_change/3,
+ handle_info/2, handle_call/3, handle_event/2]).
+
+-include_lib("wx/include/wx.hrl").
+
+-record(state,
+ {
+ parent,
+ config
+ }).
+
+start(Config) ->
+ wx_object:start_link(?MODULE, Config, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init(Config) ->
+ wx:batch(fun() -> do_init(Config) end).
+
+do_init(Config) ->
+ Parent = proplists:get_value(parent, Config),
+ Panel = wxPanel:new(Parent, []),
+
+ %% Setup sizers
+ MainSizer = wxBoxSizer:new(?wxVERTICAL),
+ Sizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "wxTextCtrl single line"}]),
+ Sizer2 = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "wxTextCtrl single line password"}]),
+ Sizer3 = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "wxTextCtrl multiline"}]),
+
+ TextCtrl = wxTextCtrl:new(Panel, 1, [{value, "This is a single line wxTextCtrl"},
+ {style, ?wxDEFAULT}]),
+ TextCtrl2 = wxTextCtrl:new(Panel, 2, [{value, "password"},
+ {style, ?wxDEFAULT bor
+ ?wxTE_PASSWORD}]),
+ TextCtrl3 = wxTextCtrl:new(Panel, 3, [{value, "This is a\n"
+ "multiline\n"
+ "wxTextCtrl"},
+ {style, ?wxDEFAULT bor
+ ?wxTE_MULTILINE}]),
+
+ %% Add to sizers
+ wxSizer:add(Sizer, TextCtrl, [{flag, ?wxEXPAND}]),
+ wxSizer:add(Sizer2, TextCtrl2, []),
+ wxSizer:add(Sizer3, TextCtrl3, [{flag, ?wxEXPAND}]),
+
+ wxSizer:add(MainSizer, Sizer, [{flag, ?wxEXPAND}]),
+ wxSizer:addSpacer(MainSizer, 10),
+ wxSizer:add(MainSizer, Sizer2, [{flag, ?wxEXPAND}]),
+ wxSizer:addSpacer(MainSizer, 10),
+ wxSizer:add(MainSizer, Sizer3, [{flag, ?wxEXPAND}]),
+
+ wxPanel:setSizer(Panel, MainSizer),
+ {Panel, #state{parent=Panel, config=Config}}.
+
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Async Events are handled in handle_event as in handle_info
+handle_event(Ev = #wx{}, State = #state{}) ->
+ demo:format(State#state.config,"Got Event ~p\n",[Ev]),
+ {noreply, State}.
+
+%% Callbacks handled as normal gen_server callbacks
+handle_info(Msg, State) ->
+ demo:format(State#state.config, "Got Info ~p\n",[Msg]),
+ {noreply, State}.
+
+handle_call(Msg, _From, State) ->
+ demo:format(State#state.config,"Got Call ~p\n",[Msg]),
+ {reply, {error,nyi}, State}.
+
+code_change(_, _, State) ->
+ {stop, ignore, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Local functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
diff --git a/lib/wx/examples/demo/ex_treeCtrl.erl b/lib/wx/examples/demo/ex_treeCtrl.erl
new file mode 100644
index 0000000000..fa40795393
--- /dev/null
+++ b/lib/wx/examples/demo/ex_treeCtrl.erl
@@ -0,0 +1,121 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 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(ex_treeCtrl).
+
+-behaviour(wx_object).
+
+%% Client API
+-export([start/1]).
+
+%% wx_object callbacks
+-export([init/1, terminate/2, code_change/3,
+ handle_info/2, handle_call/3, handle_event/2]).
+
+-include_lib("wx/include/wx.hrl").
+
+-record(state,
+ {
+ parent,
+ config
+ }).
+
+start(Config) ->
+ wx_object:start_link(?MODULE, Config, []).
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+init(Config) ->
+ wx:batch(fun() -> do_init(Config) end).
+
+do_init(Config) ->
+ Parent = proplists:get_value(parent, Config),
+ Panel = wxPanel:new(Parent, []),
+
+ %% Setup sizers
+ MainSizer = wxBoxSizer:new(?wxVERTICAL),
+ Sizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel,
+ [{label, "wxTreeCtrl"}]),
+
+ %% Setup treeCtrl
+ TreeCtrl = wxTreeCtrl:new(Panel, []),
+ RootId = wxTreeCtrl:addRoot(TreeCtrl, "Root"),
+ %% Name the first items
+ Items = ["item "++integer_to_list(Int)||
+ Int <- lists:seq(1,10)],
+ %% Create the first items in the treeCtrl
+ SubItems = [{wxTreeCtrl:appendItem(TreeCtrl, RootId, Item), Item}||
+ Item <- Items],
+ %% Create sub items
+ [wxTreeCtrl:appendItem(TreeCtrl, ItemId, Item++" sub item "++integer_to_list(Int))||
+ {ItemId, Item} <- SubItems, Int <- lists:seq(1,10)],
+ wxTreeCtrl:expand(TreeCtrl, RootId),
+
+ %% Add to sizers
+ Options = [{flag, ?wxEXPAND}, {proportion, 1}],
+ wxSizer:add(Sizer, TreeCtrl, Options),
+ wxSizer:add(MainSizer, Sizer, Options),
+
+ wxTreeCtrl:connect(TreeCtrl, command_tree_item_collapsed),
+ wxTreeCtrl:connect(TreeCtrl, command_tree_item_expanded),
+ wxTreeCtrl:connect(TreeCtrl, command_tree_sel_changed),
+ wxPanel:setSizer(Panel, MainSizer),
+ {Panel, #state{parent=Panel, config=Config}}.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Async Events are handled in handle_event as in handle_info
+handle_event(#wx{event = #wxTree{type = command_tree_item_collapsed,
+ item = Item},
+ obj = TreeCtrl},
+ State = #state{}) ->
+ ItemText = wxTreeCtrl:getItemText(TreeCtrl, Item),
+ demo:format(State#state.config, "You have collapsed ~p.\n", [ItemText]),
+ {noreply, State};
+handle_event(#wx{event = #wxTree{type = command_tree_item_expanded,
+ item = Item},
+ obj = TreeCtrl},
+ State = #state{}) ->
+ ItemText = wxTreeCtrl:getItemText(TreeCtrl, Item),
+ demo:format(State#state.config, "You have expanded ~p.\n", [ItemText]),
+ {noreply, State};
+handle_event(#wx{event = #wxTree{type = command_tree_sel_changed,
+ item = Item},
+ obj = TreeCtrl},
+ State = #state{}) ->
+ ItemText = wxTreeCtrl:getItemText(TreeCtrl, Item),
+ demo:format(State#state.config, "You have selected ~p.\n", [ItemText]),
+ {noreply, State}.
+
+%% Callbacks handled as normal gen_server callbacks
+handle_info(Msg, State) ->
+ demo:format(State#state.config, "Got Info ~p\n", [Msg]),
+ {noreply, State}.
+
+handle_call(Msg, _From, State) ->
+ demo:format(State#state.config, "Got Call ~p\n", [Msg]),
+ {reply,{error, nyi}, State}.
+
+code_change(_, _, State) ->
+ {stop, ignore, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+%% Local functions
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
diff --git a/lib/wx/examples/demo/image.jpg b/lib/wx/examples/demo/image.jpg
new file mode 100644
index 0000000000..ce5bfc2629
--- /dev/null
+++ b/lib/wx/examples/demo/image.jpg
Binary files differ