diff options
Diffstat (limited to 'lib/wx/examples')
76 files changed, 10793 insertions, 0 deletions
diff --git a/lib/wx/examples/Makefile b/lib/wx/examples/Makefile new file mode 100644 index 0000000000..ae0ed687eb --- /dev/null +++ b/lib/wx/examples/Makefile @@ -0,0 +1,45 @@ +# +# %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 + +SUBDIRS = demo sudoku simple xrc + +ifeq ($(INSIDE_ERLSRC),true) +SUB_DIRECTORIES=$(SUBDIRS) +# ---------------------------------------------------- +# Default Subdir Targets +# ---------------------------------------------------- +include $(ERL_TOP)/make/otp_subdir.mk + +else +# standalone build +opt debug clean: + @for d in $(SUBDIRS); do \ + if test ! -d $$d ; then \ + echo "=== Skipping subdir $$d" ; \ + else \ + (cd $$d && $(MAKE) $@) ; \ + fi ; \ + done + +docs: + +endif 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) -> ["<"|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 Binary files differnew file mode 100644 index 0000000000..a5901103a3 --- /dev/null +++ b/lib/wx/examples/demo/erlang.png 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 © 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 Binary files differnew file mode 100644 index 0000000000..ce5bfc2629 --- /dev/null +++ b/lib/wx/examples/demo/image.jpg diff --git a/lib/wx/examples/simple/Makefile b/lib/wx/examples/simple/Makefile new file mode 100644 index 0000000000..41f0b46eb1 --- /dev/null +++ b/lib/wx/examples/simple/Makefile @@ -0,0 +1,65 @@ +# +# %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 = hello hello2 minimal menu +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 hello + +ifneq ($(INSIDE_ERLSRC),true) + +%.beam: %.erl + $(ERLC) -W -I$(ERLINC) -bbeam -o$(BIN) $< + +else +EXRELSYSDIR = $(RELSYSDIR)/examples/simple +include $(ERL_TOP)/make/otp_release_targets.mk + +docs: + +release_spec: + $(INSTALL_DIR) $(EXRELSYSDIR) + $(INSTALL_DATA) $(TESTSRC) $(EXRELSYSDIR) + $(INSTALL_DATA) copy.xpm sample.xpm $(TESTTARGETS) $(EXRELSYSDIR) + +release_tests_spec: + +release_docs_spec: + +endif + + diff --git a/lib/wx/examples/simple/copy.xpm b/lib/wx/examples/simple/copy.xpm new file mode 100644 index 0000000000..b14b414834 --- /dev/null +++ b/lib/wx/examples/simple/copy.xpm @@ -0,0 +1,44 @@ +/* XPM */ +static const char * copy_xpm[] = { +/* columns rows colors chars-per-pixel */ +"16 15 23 1", +"+ c #769CDA", +": c #DCE6F6", +"X c #3365B7", +"* c #FFFFFF", +"o c #9AB6E4", +"< c #EAF0FA", +"# c #B1C7EB", +". c #6992D7", +"3 c #F7F9FD", +", c #F0F5FC", +"$ c #A8C0E8", +" c None", +"- c #FDFEFF", +"& c #C4D5F0", +"1 c #E2EAF8", +"O c #89A9DF", +"= c #D2DFF4", +"4 c #FAFCFE", +"2 c #F5F8FD", +"; c #DFE8F7", +"% c #B8CCEC", +"> c #E5EDF9", +"@ c #648FD6", +/* pixels */ +" .....XX ", +" .oO+@X#X ", +" .$oO+X##X ", +" .%$o........ ", +" .&%$.*=&#o.-. ", +" .=&%.*;=&#.--. ", +" .:=&.*>;=&.... ", +" .>:=.*,>;=&#o. ", +" .<1:.*2,>:=&#. ", +" .2<1.*32,>:=&. ", +" .32<.*432,>:=. ", +" .32<.*-432,>:. ", +" .....**-432,>. ", +" .***-432,. ", +" .......... " +}; diff --git a/lib/wx/examples/simple/hello.erl b/lib/wx/examples/simple/hello.erl new file mode 100755 index 0000000000..dc845ddfbb --- /dev/null +++ b/lib/wx/examples/simple/hello.erl @@ -0,0 +1,69 @@ +%% +%% %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% +%% +%%%------------------------------------------------------------------- +%%% File : hello.erl +%%% Author : Matthew Harrison <harryhuk at users.sourceforge.net> +%%% Description : _really_ minimal example of a wxerlang app +%%% +%%% Created : 18 Sep 2008 by Matthew Harrison <harryhuk at users.sourceforge.net> +%%%------------------------------------------------------------------- +-module(hello). + +-include_lib("wx/include/wx.hrl"). + +-export([start/0]). +-compile(export_all). + +start() -> + Wx = wx:new(), + Frame = wx:batch(fun() -> create_window(Wx) end), + wxWindow:show(Frame), + loop(Frame), + wx:destroy(), + ok. + +create_window(Wx) -> + Frame = wxFrame:new(Wx, + -1, % window id + "Hello World", % window title + [{size, {600,400}}]), + + + wxFrame:createStatusBar(Frame,[]), + + %% if we don't handle this ourselves, wxwidgets will close the window + %% when the user clicks the frame's close button, but the event loop still runs + wxFrame:connect(Frame, close_window), + + ok = wxFrame:setStatusText(Frame, "Hello World!",[]), + Frame. + +loop(Frame) -> + receive + #wx{event=#wxClose{}} -> + io:format("~p Closing window ~n",[self()]), + ok = wxFrame:setStatusText(Frame, "Closing...",[]), + wxWindow:destroy(Frame), + ok; + Msg -> + io:format("Got ~p ~n", [Msg]), + loop(Frame) + end. + + diff --git a/lib/wx/examples/simple/hello2.erl b/lib/wx/examples/simple/hello2.erl new file mode 100644 index 0000000000..af825f2e3c --- /dev/null +++ b/lib/wx/examples/simple/hello2.erl @@ -0,0 +1,81 @@ +%% +%% %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% +%% +%%%------------------------------------------------------------------- +%%% File : hello.erl +%%% Author : Matthew Harrison <harryhuk at users.sourceforge.net> +%%% Description : _really_ minimal example of a wxerlang app +%%% implemented with wx_object behaviour +%%% +%%% Created : 18 Sep 2008 by Matthew Harrison <harryhuk at users.sourceforge.net> +%%% Dan rewrote it to show wx_object behaviour +%%%------------------------------------------------------------------- +-module(hello2). +-include_lib("wx/include/wx.hrl"). + +-export([start/0]). +-compile(export_all). + +-behavoiur(wx_object). + +-record(state, {win}). + +start() -> + wx_object:start_link(?MODULE, [], []). + +%% Init is called in the new process. +init([]) -> + wx:new(), + Frame = wxFrame:new(wx:null(), + -1, % window id + "Hello World", % window title + [{size, {600,400}}]), + + wxFrame:createStatusBar(Frame,[]), + + %% if we don't handle this ourselves, wxwidgets will close the window + %% when the user clicks the frame's close button, but the event loop still runs + wxFrame:connect(Frame, close_window), + + ok = wxFrame:setStatusText(Frame, "Hello World!",[]), + wxWindow:show(Frame), + {Frame, #state{win=Frame}}. + + +%% Handled as in normal gen_server callbacks +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=#wxClose{}}, State = #state{win=Frame}) -> + io:format("~p Closing window ~n",[self()]), + ok = wxFrame:setStatusText(Frame, "Closing...",[]), + wxWindow:destroy(Frame), + {stop, normal, State}. + +code_change(_, _, State) -> + {stop, not_yet_implemented, State}. + +terminate(_Reason, _State) -> + ok. + diff --git a/lib/wx/examples/simple/menu.erl b/lib/wx/examples/simple/menu.erl new file mode 100755 index 0000000000..d573fcf13a --- /dev/null +++ b/lib/wx/examples/simple/menu.erl @@ -0,0 +1,607 @@ +%% +%% %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% +%% +%%%------------------------------------------------------------------- +%%% File : menus.erl +%%% Author : Matthew Harrison <harryhuk at users.sourceforge.net> +%%% Description : Test of menus +%%% +%%% Created : 18 Sep 2008 by Matthew Harrison <harryhuk at users.sourceforge.net> +%%%------------------------------------------------------------------- +-module(menu). + +-include_lib("wx/include/wx.hrl"). + +-export([start/0]). +-compile(export_all). + +%%%Lots of IDs to declare! +-define(menuID_FILE_QUIT, ?wxID_EXIT). +-define(menuID_FILE_CLEAR_LOG, 100). + +-define(menuID_MENUBAR_TOGGLE, 200). +-define(menuID_MENUBAR_APPEND, 201). +-define(menuID_MENUBAR_INSERT, 202). +-define(menuID_MENUBAR_DELETE, 203). +-define(menuID_MENUBAR_ENABLE, 204). +-define(menuID_MENUBAR_GET_LABEL, 206). +-define(menuID_MENUBAR_SET_LABEL, 207). +-define(menuID_MENUBAR_FIND_MENU, 208). + +-define(menuID_MENU_APPEND, 300). +-define(menuID_MENU_APPEND_SUB, 301). +-define(menuID_MENU_INSERT, 302). +-define(menuID_MENU_DELETE, 303). +-define(menuID_MENU_ENABLE, 304). +-define(menuID_MENU_CHECK, 305). +-define(menuID_MENU_GET_LABEL, 306). +-define(menuID_MENU_SET_LABEL, 307). +-define(menuID_MENU_GET_INFO, 308). +-define(menuID_MENU_FIND_ITEM, 309). + +-define(menuID_TEST_NORMAL, 400). +-define(menuID_TEST_CHECK, 401). +-define(menuID_TEST_RADIO_1, 402). +-define(menuID_TEST_RADIO_2, 403). +-define(menuID_TEST_RADIO_3, 404). + +-define(menuID_SUBMENU, 450). +-define(menuID_SUBMENU_NORMAL, 451). +-define(menuID_SUBMENU_CHECK, 452). +-define(menuID_SUBMENU_RADIO_1, 453). +-define(menuID_SUBMENU_RADIO_2, 454). +-define(menuID_SUBMENU_RADIO_3, 455). + +-define(menuID_DUMMY_FIRST, 500). +-define(menuID_DUMMY_SECOND, 501). +-define(menuID_DUMMY_THIRD, 502). +-define(menuID_DUMMY_FOURTH, 503). +-define(menuID_DUMMY_LAST, 504). + +-define(menuID_HELP_ABOUT, ?wxID_ABOUT). + +-define(menuID_POPUP_TO_BE_DELETED, 2000). +-define(menuID_POPUP_TO_BE_GREYED, 2001). +-define(menuID_POPUP_TO_BE_CHECKED, 2002). +-define(menuID_POPUP_TO_BE_SUBMENU, 2003). + +-define(wID_LOG_TEXT_CTRL, 3000). + +-record(state, {dummyMenuCount=0, fileMenu=undefined}). + +%% +%% +%% +start() -> + Wx = wx:new(), + Frame = wx:batch(fun() -> create_frame(Wx) end), + wxWindow:show(Frame), + + State = #state{}, + + loop(State), + ok. + + +%% +%% +%% +create_frame(Wx) -> + Frame = wxFrame:new(Wx, -1, "wxErlang menu sample", [{size, {600,400}}]), + + Path = filename:dirname(code:which(?MODULE)), + wxFrame:setIcon(Frame, wxIcon:new(filename:join(Path,"sample.xpm"))), + + wxFrame:createStatusBar(Frame,[]), + wxFrame:connect(Frame, close_window), + + FileMenu = create_file_menu(), + MenuBarMenu = create_menubar_menu(), + MenuMenu = create_menu_menu(), + TestMenu = create_test_menu(), + HelpMenu = create_help_menu(), + + MenuBar = wxMenuBar:new(?wxMB_DOCKABLE), + + + wxMenuBar:append(MenuBar, FileMenu, "&File"), + wxMenuBar:append(MenuBar, MenuBarMenu, "Menu&bar"), + wxMenuBar:append(MenuBar, MenuMenu, "&Menu"), + wxMenuBar:append(MenuBar, TestMenu, "&Test"), + wxMenuBar:append(MenuBar, HelpMenu, "&Help"), + + wxFrame:setMenuBar(Frame, MenuBar), + + LogTextCtrl = wxTextCtrl:new(Frame, ?wID_LOG_TEXT_CTRL, + [{value, ""}, + %{pos, ?wxDefaultPosition}, + %{size, ?wxDefaultSize}, + {style, ?wxTE_MULTILINE}]), + wxTextCtrl:setEditable(LogTextCtrl, false), + + ok = wxFrame:setStatusText(Frame, "Welcome to wxErlang menu sample",[]), + + ok = wxFrame:connect(Frame, command_menu_selected), + + String = "Brief explanations:~n" + "the commands from the \"Menu\" menu append/insert/delete items to/from the last menu.~n" + "The commands from \"Menubar\" menu work with the menubar itself.~n~n", + %% "Right click the band below to test popup menus.~n", + logMessage(Frame, String), + Frame. + +%% +%% +%% +create_file_menu() -> + FileMenu = wxMenu:new(), + + wxMenu:append(FileMenu, wxMenuItem:new([ + {id, ?menuID_SUBMENU}, + {subMenu, create_stock_menu()}, + {text, "&Standard items demo"} + ])), + ClearLogBitmap = wxBitmap:new("copy.xpm"), + ClearLogItem = wxMenuItem:new([ + {id, ?menuID_FILE_CLEAR_LOG}, + {text, "Clear &log\tCtrl-L"} %% note mnemonic and accelerator + ]), + wxMenuItem:setBitmap(ClearLogItem, ClearLogBitmap), + + wxMenu:append(FileMenu, ClearLogItem ), + wxMenu:appendSeparator(FileMenu), + wxMenu:append(FileMenu, wxMenuItem:new([ + {id, ?menuID_FILE_QUIT} %, + %{text, "E&xit\tAlt-X"} + ])), + FileMenu. + +%% +%% +%% +create_menubar_menu() -> + MenuBarMenu = wxMenu:new(), + wxMenu:append(MenuBarMenu, wxMenuItem:new([ + {id, ?menuID_MENUBAR_APPEND}, + {text, "&Append menu\tCtrl-A"}, + {help, "Append a menu to the menubar"} + ])), + wxMenu:append(MenuBarMenu, wxMenuItem:new([ + {id, ?menuID_MENUBAR_INSERT}, + {text, "&Insert menu\tCtrl-I"}, + {help, "Insert a menu into the menubar"} + ])), + wxMenu:append(MenuBarMenu, wxMenuItem:new([ + {id, ?menuID_MENUBAR_DELETE}, + {text, "&Delete menu\tCtrl-D"}, + {help, "Insert a menu into the menubar"} + ])), + wxMenu:append(MenuBarMenu, wxMenuItem:new([ + {id, ?menuID_MENUBAR_TOGGLE}, + {text, "&Toggle menu\tCtrl-T"}, + {help, "Toggle the first menu in the menubar"}, + {kind, ?wxITEM_CHECK} + ])), + wxMenu:appendSeparator(MenuBarMenu), %% -------------------------- + wxMenu:append(MenuBarMenu, wxMenuItem:new([ + {id, ?menuID_MENUBAR_ENABLE}, + {text, "&Enable menu\tCtrl-E"}, + {help, "Enable or disable the last menu"}, + {kind, ?wxITEM_CHECK} + ])), + wxMenu:appendSeparator(MenuBarMenu), %% -------------------------- + wxMenu:append(MenuBarMenu, wxMenuItem:new([ + {id, ?menuID_MENUBAR_GET_LABEL}, + {text, "&Get menu label\tCtrl-G"}, + {help, "Get the label of the last menu"} + ])), + wxMenu:append(MenuBarMenu, wxMenuItem:new([ + {id, ?menuID_MENUBAR_SET_LABEL}, + {text, "&Set menu label\tCtrl-S"}, + {help, "Change the label of the last menu"} + ])), + wxMenu:appendSeparator(MenuBarMenu), %% -------------------------- + wxMenu:append(MenuBarMenu, wxMenuItem:new([ + {id, ?menuID_MENUBAR_FIND_MENU}, + {text, "&Find menu from label\tCtrl-F"}, + {help, "Find a menu by searching for its label"} + ])), + MenuBarMenu. + + +%% +%% +%% +create_submenu_menu() -> + SubMenuMenu = wxMenu:new(), + wxMenu:append(SubMenuMenu, wxMenuItem:new([ + {id, ?menuID_SUBMENU_NORMAL}, + {text, "&Normal submenu item"}, + {help, "Disabled submenu item"} + ])), + %% note different way of adding check menu item + wxMenu:appendCheckItem(SubMenuMenu, + ?menuID_SUBMENU_CHECK, + "&Check submenu item", + [{help, "Check submenu item"}]), + wxMenu:appendRadioItem(SubMenuMenu, + ?menuID_SUBMENU_RADIO_1, + "Radio item &1", + [{help, "Radio item"}]), + wxMenu:appendRadioItem(SubMenuMenu, + ?menuID_SUBMENU_RADIO_2, + "Radio item &2", + [{help, "Radio item"}]), + wxMenu:appendRadioItem(SubMenuMenu, + ?menuID_SUBMENU_RADIO_3, + "Radio item &3", + [{help, "Radio item"}]), + SubMenuMenu. + + +%% +%% +%% +create_menu_menu() -> + MenuMenu = wxMenu:new(), + wxMenu:append(MenuMenu, wxMenuItem:new([ + {id, ?menuID_MENU_APPEND}, + {text, "&Append menu item\tAlt-A"}, + {help, "Append a menu item to the last menu"} + ])), + wxMenu:append(MenuMenu, wxMenuItem:new([ + {id, ?menuID_MENU_APPEND_SUB}, + {text, "&Append sub menu\tAlt-S"}, + {help, "Append a sub menu to the last menu"} + ])), + wxMenu:append(MenuMenu, wxMenuItem:new([ + {id, ?menuID_MENU_INSERT}, + {text, "&Insert menu item\tAlt-I"}, + {help, "Insert a menu item in head of the last menu"} + ])), + wxMenu:append(MenuMenu, wxMenuItem:new([ + {id, ?menuID_MENU_DELETE}, + {text, "&Delete menu item\tAlt-D"}, + {help, "Delete the last menu item from the last menu"} + ])), + wxMenu:appendSeparator(MenuMenu), %% -------------------------- + wxMenu:append(MenuMenu, wxMenuItem:new([ + {id, ?menuID_MENU_ENABLE}, + {text, "&Enable menu item\tAlt-E"}, + {help, "Enable or disable the last menu item"}, + {kind, ?wxITEM_CHECK} + ])), + wxMenu:append(MenuMenu, wxMenuItem:new([ + {id, ?menuID_MENU_CHECK}, + {text, "&Check menu item\tAlt-C"}, + {help, "Check or uncheck the last menu item"}, + {kind, ?wxITEM_CHECK} + ])), + wxMenu:appendSeparator(MenuMenu), %% -------------------------- + wxMenu:append(MenuMenu, wxMenuItem:new([ + {id, ?menuID_MENU_GET_INFO}, + {text, "Get menu item in&fo\tAlt-F"}, + {help, "Show the state of the last menu item"} + ])), + wxMenu:append(MenuMenu, wxMenuItem:new([ + {id, ?menuID_MENU_SET_LABEL}, + {text, "&Set menu label\tCtrl-S"}, + {help, "Change the label of the last menu"} + ])), + wxMenu:appendSeparator(MenuMenu), %% -------------------------- + wxMenu:append(MenuMenu, wxMenuItem:new([ + {id, ?menuID_MENU_FIND_ITEM}, + {text, "Find menu item from label"}, + {help, "Find a menu item by searching for its label"} + ])), + MenuMenu. + + +%% +%% +%% +create_test_menu() -> + TestMenu = wxMenu:new(), + wxMenu:append(TestMenu, wxMenuItem:new([ + {id, ?menuID_TEST_NORMAL}, + {text, "&Normal submenu item"}, + {help, "Disabled submenu item"} + ])), + wxMenu:appendSeparator(TestMenu), %% -------------------------- + %% note different way of adding check menu item + wxMenu:appendCheckItem(TestMenu, ?menuID_TEST_CHECK, "&Check item"), + wxMenu:appendSeparator(TestMenu), %% -------------------------- + wxMenu:appendRadioItem(TestMenu, ?menuID_TEST_RADIO_1, "Radio item &1"), + wxMenu:appendRadioItem(TestMenu, ?menuID_TEST_RADIO_2, "Radio item &2"), + wxMenu:appendRadioItem(TestMenu, ?menuID_TEST_RADIO_3, "Radio item &3"), + TestMenu. + +%% +%% +%% +create_help_menu() -> + HelpMenu = wxMenu:new(), + % unlike wxwidgets the stock menu items still need text to be given, + % although help text does appear + % Note the keybord accelerator + wxMenu:append(HelpMenu, wxMenuItem:new([ + {id, ?menuID_HELP_ABOUT}, + %{text, "&About\tF1"}, + {help, "About menu sample"} + ])), + HelpMenu. + +%% +%% +%% +create_stock_menu() -> + % unlike wxwidgets the stock menu items still need text to be given, + % although help text does appear + StockSubMenu = wxMenu:new(), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_ADD }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_APPLY }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_BOLD }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_CANCEL }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_CLEAR }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_CLOSE }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_COPY }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_CUT }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_DELETE }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_FIND }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_REPLACE }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_BACKWARD }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_DOWN }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_FORWARD }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_UP }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_HELP }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_HOME }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_INDENT }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_INDEX }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_ITALIC }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_JUSTIFY_CENTER }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_JUSTIFY_FILL }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_JUSTIFY_LEFT }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_JUSTIFY_RIGHT }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_NEW }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_NO }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_OK }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_OPEN }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_PASTE }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_PREFERENCES }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_PRINT }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_PREVIEW }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_PROPERTIES }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_EXIT }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_REDO }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_REFRESH }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_REMOVE }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_REVERT_TO_SAVED }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_SAVE }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_SAVEAS }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_STOP }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_UNDELETE }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_UNDERLINE }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_UNDO }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_UNINDENT }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_YES }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_ZOOM_100 }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_ZOOM_FIT }])), + wxMenu:append(StockSubMenu, wxMenuItem:new([{id, ?wxID_ZOOM_OUT }])), + + StockSubMenu. + +create_dummy_menu() -> + DummyMenu = wxMenu:new(), + wxMenu:append(DummyMenu, ?menuID_DUMMY_FIRST, "&First item\tCtrl-F1"), + wxMenu:appendSeparator(DummyMenu), %% -------------------------- + wxMenu:append(DummyMenu, ?menuID_DUMMY_SECOND, "&Second item\tCtrl-F2"), + DummyMenu. + +loop(State) -> + receive + #wx{event=#wxClose{}, obj=Frame} -> + io:format("~p Closing window ~n",[self()]), + wxWindow:destroy(Frame); %onClose(Frame); + #wx{id=?menuID_FILE_QUIT, obj=Frame, event=#wxCommand{type=command_menu_selected}} -> + io:format("~p Closing window ~n",[self()]), + wxWindow:destroy(Frame); %onClose(Frame); + + #wx{obj=Frame, userData=UserData, event=#wxCommand{type=command_menu_selected}} = Wx-> + logMessage(Frame, "got wx:~p ud:~p~n", [Wx, UserData]), + State1 = onMenuAction(Wx, State), + loop(State1); + Msg -> + io:format("Got ~p ~n", [Msg]), + loop(State) + after 5000 -> + loop(State) + end. + + +onMenuAction(#wx{id=?menuID_FILE_CLEAR_LOG, obj=Frame}, #state{} = State) -> + wxTextCtrl:clear(findLogger(Frame)), + State; + + +onMenuAction(#wx{id=?menuID_MENUBAR_APPEND, obj=Frame}, #state{} = State) -> + MenuBar = wxFrame:getMenuBar(Frame), + wxMenuBar:append(MenuBar, create_dummy_menu(), "DummyMenu"), + State; + +onMenuAction(#wx{id=?menuID_MENUBAR_INSERT, obj=Frame}, #state{} = State) -> + MenuBar = wxFrame:getMenuBar(Frame), + wxMenuBar:insert(MenuBar, 0, create_dummy_menu(), "DummyMenu"), + State; + +onMenuAction(#wx{id=?menuID_MENUBAR_DELETE, obj=Frame}, #state{} = State) -> + MenuBar = wxFrame:getMenuBar(Frame), + Count = wxMenuBar:getMenuCount(MenuBar), + if + (Count > 2) -> + wxMenuBar:remove(MenuBar, Count -1); + true -> + logMessage(Frame, "Cannot delete any more menus~n") + end, + State; + +onMenuAction(#wx{id=?menuID_MENUBAR_TOGGLE, obj=Frame}, #state{fileMenu=FileMenu} = State) -> + logMessage(Frame, "onMenubarToggle ~p ~n", [FileMenu]), + MenuBar = wxFrame:getMenuBar(Frame), + if + FileMenu =:= undefined -> + Menu = wxMenuBar:remove(MenuBar, 0), + State#state{fileMenu=Menu}; + true -> + wxMenuBar:insert(MenuBar, 0, FileMenu, "&File"), + State#state{fileMenu=undefined} + end; + +onMenuAction( #wx{id=?menuID_MENUBAR_ENABLE=Id, obj=Frame}, #state{} = State) -> +%% logMessage(Frame, "onMenubarEnable ~n"), + MenuBar = wxFrame:getMenuBar(Frame), + MenuItem = wxMenuBar:findItem(MenuBar, Id), + Enable = (not wxMenuItem:isCheckable(MenuItem)) orelse wxMenuItem:isChecked(MenuItem), + + Count = wxMenuBar:getMenuCount(MenuBar), + wxMenuBar:enableTop(MenuBar, (Count - 1), Enable), + State; + + +onMenuAction( #wx{id=?menuID_MENUBAR_GET_LABEL, obj=Frame}, #state{} = State) -> + logMessage(Frame, "onMenubarGetLabel ~n"), + MenuBar = wxFrame:getMenuBar(Frame), + Count = wxMenuBar:getMenuCount(MenuBar), + Label = wxMenuBar:getLabelTop(MenuBar, (Count - 1)), + logMessage(Frame, "The label of the last menu item is ~p", [Label]), + State; + +onMenuAction( #wx{id=?menuID_MENUBAR_SET_LABEL, obj=Frame}, #state{} = State) -> +%% logMessage(Frame, "onMenubarGetLabel ~n"), + MenuBar = wxFrame:getMenuBar(Frame), + Count = wxMenuBar:getMenuCount(MenuBar), + Label = wxMenuBar:getLabelTop(MenuBar, (Count - 1)), + TextDialog = wxTextEntryDialog:new(Frame, + "Enter new label: ", + [{caption, "Change last menu text"}, {value, Label}]), + wxDialog:showModal(TextDialog), + NewLabel = wxTextEntryDialog:getValue(TextDialog), + wxMenuBar:setLabelTop(MenuBar, (Count - 1), NewLabel), + wxDialog:destroy(TextDialog), + State; + +onMenuAction( #wx{id=?menuID_MENUBAR_FIND_MENU, obj=Frame}, #state{} = State) -> +%% logMessage(Frame, "onMenubarFindMenu ~n"), + MenuBar = wxFrame:getMenuBar(Frame), + _Count = wxMenuBar:getMenuCount(MenuBar), +% Label = wxMenuBar:getLabelTop(MenuBar, (Count - 1)), + TextDialog = wxTextEntryDialog:new(Frame, + "Enter label to search for: ", + [{caption, "Find menu"}]), + wxDialog:showModal(TextDialog), + Label = wxTextEntryDialog:getValue(TextDialog), + Len = string:len(Label), + if + (Len > 0) -> + Index = wxMenuBar:findMenu(MenuBar, Label), + if + (Index =:= ?wxNOT_FOUND) -> + logMessage(Frame, "Warning: No menu with label ~p", [Label]); + true -> + logMessage(Frame, "Menu ~p has label ~p", [Index, Label]) + end; + true -> true + end, + + State; + +onMenuAction(#wx{id=?menuID_MENU_APPEND, obj=Frame}, #state{} = State) -> + MenuBar = wxFrame:getMenuBar(Frame), + Count = wxMenuBar:getMenuCount(MenuBar), + Menu = wxMenuBar:getMenu(MenuBar, Count - 1), + io:format("MenuBar ~p Menu ~p Count ~p ~n", [MenuBar, Menu, Count]), + wxMenu:appendSeparator(Menu), + wxMenu:append(Menu, wxMenuItem:new([ + {id, ?menuID_DUMMY_THIRD}, + {text, "&Third dummy item\tCtrl-F3"}, + {kind, ?wxITEM_CHECK} + ])), + + State; + +onMenuAction(#wx{id=?menuID_MENU_APPEND_SUB, obj=Frame}, #state{} = State) -> + MenuBar = wxFrame:getMenuBar(Frame), + Count = wxMenuBar:getMenuCount(MenuBar), + Menu = wxMenuBar:getMenu(MenuBar, Count - 2), + wxMenu:appendSeparator(Menu), + wxMenu:append(Menu, wxMenuItem:new([ + {id, ?menuID_DUMMY_LAST}, + {text, "&Dummy sub menu"}, + {help, "Dummy sub menu help"}, + {subMenu, create_dummy_menu()} + ])), + + State; + +onMenuAction(#wx{id=Id, obj=Frame}, #state{}=State) when ((Id >= ?menuID_DUMMY_FIRST) and (Id =< ?menuID_DUMMY_LAST)) -> + logMessage(Frame, "Dummy item #~p ~n", [Id - ?menuID_DUMMY_FIRST + 1]), + State; + +onMenuAction( #wx{id=?menuID_HELP_ABOUT=Id, obj=Frame}, #state{} = State) -> + showDialog(Id, Frame), + State; + +onMenuAction( #wx{obj=Frame} = Wx, State) -> + logMessage(Frame, "unimplemented menu item event ~p ~n", [Wx]), + State. + +logMessage(Frame, Msg) -> + logMessage(Frame, Msg, []). + +logMessage(Frame, Msg, ArgList) -> + String = lists:flatten(io_lib:format(Msg, ArgList)), + + wxTextCtrl:appendText(findLogger(Frame), String). + +findLogger(Frame) -> + LogWin = wxWindow:findWindowById(?wID_LOG_TEXT_CTRL, [{parent, Frame}]), + wx:typeCast(LogWin, wxTextCtrl). + + +showDialog(?menuID_HELP_ABOUT, Frame) -> + String = lists:flatten(io_lib:format("Welcome to wxErlang 0.97.5.26!~n~n" + "This is the minimal wxErlang sample~n" + "running under ~p.", + [wx_misc:getOsDescription()])), + MessageDialog = wxMessageDialog:new(Frame, + String, + [{style, ?wxOK bor ?wxICON_INFORMATION}, + {caption, "About wxErlang minimal sample"}]), + + wxDialog:showModal(MessageDialog), + wxDialog:destroy(MessageDialog); + +showDialog(Id, Frame) -> + String = lists:flatten(io_lib:format("Unimplemented Dialog ~p", [Id])), + MessageDialog = wxMessageDialog:new(Frame, + String, + [{style, ?wxOK bor ?wxICON_INFORMATION}, + {caption, "wxErlang minimal sample"}]), + + wxDialog:showModal(MessageDialog), + wxDialog:destroy(MessageDialog). + diff --git a/lib/wx/examples/simple/minimal.erl b/lib/wx/examples/simple/minimal.erl new file mode 100755 index 0000000000..dca4adc643 --- /dev/null +++ b/lib/wx/examples/simple/minimal.erl @@ -0,0 +1,109 @@ +%% +%% %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% +%% +%%%------------------------------------------------------------------- +%%% File : minimal.erl +%%% Author : Matthew Harrison <harryhuk at users.sourceforge.net> +%%% Description : Minimal example of a wxerlang application +%%% +%%% Created : 18 Sep 2008 by Matthew Harrison <harryhuk at users.sourceforge.net> +%%%------------------------------------------------------------------- +-module(minimal). + +-include_lib("wx/include/wx.hrl"). + +-export([start/0]). +-compile(export_all). + +start() -> + Wx = wx:new(), + Frame = wx:batch(fun() -> create_window(Wx) end), + wxWindow:show(Frame), + loop(Frame), + wx:destroy(), + ok. + +create_window(Wx) -> + Frame = wxFrame:new(Wx, -1, "Minimal wxErlang App", [{size, {600,400}}]), + + Path = filename:dirname(code:which(?MODULE)), + wxFrame:setIcon(Frame, wxIcon:new(filename:join(Path,"sample.xpm"))), + + wxFrame:createStatusBar(Frame,[]), + wxFrame:connect(Frame, close_window), + + MenuBar = wxMenuBar:new(), + FileM = wxMenu:new([]), + HelpM = wxMenu:new([]), + + % unlike wxwidgets the stock menu items still need text to be given, + % although help text does appear + _QuitMenuItem = wxMenu:append(FileM, ?wxID_EXIT, "&Quit"), + % Note the keybord accelerator + _AboutMenuItem = wxMenu:append(HelpM, ?wxID_ABOUT, "&About...\tF1"), + + wxMenu:appendSeparator(HelpM), + ContentsMenuItem = wxMenu:append(HelpM, ?wxID_HELP_CONTENTS, "&Contents"), + wxMenuItem:enable(ContentsMenuItem, [{enable, false}]), + + ok = wxFrame:connect(Frame, command_menu_selected), + + wxMenuBar:append(MenuBar, FileM, "&File"), + wxMenuBar:append(MenuBar, HelpM, "&Help"), + wxFrame:setMenuBar(Frame, MenuBar), + + ok = wxFrame:setStatusText(Frame, "Welcome to wxErlang!",[]), + Frame. + +loop(Frame) -> + receive + #wx{event=#wxClose{}} -> + io:format("~p Closing window ~n",[self()]), + wxFrame:destroy(Frame), + ok; + #wx{id=?wxID_EXIT, event=#wxCommand{type=command_menu_selected}} -> + wxWindow:destroy(Frame), + ok; + #wx{id=?wxID_ABOUT, event=#wxCommand{type=command_menu_selected}} -> + io:format("Got about ~n", []), + dialog(?wxID_ABOUT, Frame), + loop(Frame); + Msg -> + io:format("Got ~p ~n", [Msg]), + loop(Frame) + after 1000 -> + io:fwrite("."), + loop(Frame) + end. + +dialog(?wxID_ABOUT, Frame) -> + Str = string:join(["Welcome to wxErlang.", + "This is the minimal wxErlang sample\n", + "running under ", + wx_misc:getOsDescription(), + "."], + ""), + MD = wxMessageDialog:new(Frame, + Str, + [{style, ?wxOK bor ?wxICON_INFORMATION}, + {caption, "About wxErlang minimal sample"}]), + + wxDialog:showModal(MD), + wxDialog:destroy(MD). + + diff --git a/lib/wx/examples/simple/sample.xpm b/lib/wx/examples/simple/sample.xpm new file mode 100755 index 0000000000..3263b15f8a --- /dev/null +++ b/lib/wx/examples/simple/sample.xpm @@ -0,0 +1,44 @@ +/* XPM */
+static const char * sample_xpm[] = {
+/* columns rows colors chars-per-pixel */
+"32 32 6 1",
+" c black",
+". c navy",
+"X c red",
+"o c yellow",
+"O c gray100",
+"+ c None",
+/* pixels */
+"++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++",
+"++++++++ ++++++++++",
+"++++++++ ............ ++++++++++",
+"++++++++ ............ ++++++++++",
+"++++++++ .OO......... ++++++++++",
+"++++++++ .OO......... ++++++++++",
+"++++++++ .OO......... ++++++++++",
+"++++++++ .OO...... ",
+"++++++++ .OO...... oooooooooooo ",
+" .OO...... oooooooooooo ",
+" XXXXXXX .OO...... oOOooooooooo ",
+" XXXXXXX .OO...... oOOooooooooo ",
+" XOOXXXX ......... oOOooooooooo ",
+" XOOXXXX ......... oOOooooooooo ",
+" XOOXXXX oOOooooooooo ",
+" XOOXXXXXXXXX ++++ oOOooooooooo ",
+" XOOXXXXXXXXX ++++ oOOooooooooo ",
+" XOOXXXXXXXXX ++++ oOOooooooooo ",
+" XOOXXXXXXXXX ++++ oooooooooooo ",
+" XOOXXXXXXXXX ++++ oooooooooooo ",
+" XXXXXXXXXXXX ++++ ",
+" XXXXXXXXXXXX ++++++++++++++++++",
+" ++++++++++++++++++",
+"++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++",
+"++++++++++++++++++++++++++++++++"
+};
diff --git a/lib/wx/examples/sudoku/Makefile b/lib/wx/examples/sudoku/Makefile new file mode 100755 index 0000000000..b86c654fdd --- /dev/null +++ b/lib/wx/examples/sudoku/Makefile @@ -0,0 +1,66 @@ +# +# %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 = sudoku sudoku_board sudoku_game sudoku_gui +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 sudoku + +ifneq ($(INSIDE_ERLSRC),true) + +%.beam: %.erl + $(ERLC) -W -I$(ERLINC) -bbeam -o$(BIN) $< + +else +EXRELSYSDIR = $(RELSYSDIR)/examples/sudoku +include $(ERL_TOP)/make/otp_release_targets.mk + +docs: + +release_spec: + $(INSTALL_DIR) $(EXRELSYSDIR) + $(INSTALL_DATA) $(TESTSRC) sudoku.hrl $(EXRELSYSDIR) + $(INSTALL_DATA) $(TESTTARGETS) $(EXRELSYSDIR) + +release_tests_spec: + +release_docs_spec: + +endif + + + diff --git a/lib/wx/examples/sudoku/sudoku.erl b/lib/wx/examples/sudoku/sudoku.erl new file mode 100755 index 0000000000..01caeb9524 --- /dev/null +++ b/lib/wx/examples/sudoku/sudoku.erl @@ -0,0 +1,53 @@ +%% +%% %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% +%%%------------------------------------------------------------------- +%%% File : sudoku.erl +%%% Author : Dan Gudmundsson <[email protected]> +%%% Description : Sudoku +%%% +%%% Created : 13 Mar 2007 by Dan Gudmundsson <[email protected]> +%%%------------------------------------------------------------------- + +-module(sudoku). + +-export([go/0]). + +-compile(export_all). + +-include("sudoku.hrl"). + +start() -> + spawn_link(fun() -> init(halt) end). +go() -> + spawn_link(fun() -> init(keep) end). + +init(Halt) -> + ?TC(sudoku_gui:new(self())), + receive {gfx, GFX} -> ok end, + case sudoku_game:init(GFX) of + Halt -> erlang:halt(); + Stop -> exit(Stop) + end. + +tc(Fun,Mod,Line) -> + case timer:tc(erlang, apply, [Fun,[]]) of + {_,{'EXIT',Reason}} -> exit(Reason); + {T,R} -> + io:format("~p:~p: Time: ~p\n", [Mod, Line, T]), + R + end. diff --git a/lib/wx/examples/sudoku/sudoku.hrl b/lib/wx/examples/sudoku/sudoku.hrl new file mode 100755 index 0000000000..775b563bdc --- /dev/null +++ b/lib/wx/examples/sudoku/sudoku.hrl @@ -0,0 +1,44 @@ +%% +%% %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("../../include/wx.hrl"). + +-record(s,{gfx,gen,games=[],p,m,mr,mc,v}). +-define(TC(Cmd), tc(fun() -> Cmd end, ?MODULE, ?LINE)). + +-define(NEW, 121). +-define(EMPTY, 122). +-define(HINT, 123). + +-define(OPEN, 130). +-define(SAVE, 131). +-define(RULES, 132). +-define(CLEAR, 135). +-define(SHOW_ERROR, 136). +-define(PRINT, 137). +-define(PRINT_PRE, 138). +-define(PRINT_PAGE_SETUP, 139). + +-define(TRIVIAL, 240). +-define(EASY, 235). +-define(NORMAL, 230). +-define(HARD, 225). +-define(HARDEST, 210). + +-define(QUIT, ?wxID_EXIT). %% Use OS specific version if available +-define(ABOUT, ?wxID_ABOUT). %% Use OS specific diff --git a/lib/wx/examples/sudoku/sudoku_board.erl b/lib/wx/examples/sudoku/sudoku_board.erl new file mode 100755 index 0000000000..756837582f --- /dev/null +++ b/lib/wx/examples/sudoku/sudoku_board.erl @@ -0,0 +1,358 @@ +%% +%% %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% +%%%------------------------------------------------------------------- +%%% File : sud_board.erl +%%% Author : <[email protected]> +%%% Description : Manages the gui board +%%% +%%% Created : 9 Jan 2008 by <[email protected]> +%%%------------------------------------------------------------------- +-module(sudoku_board). + +-export([new/1, setup_board/2, clear_board/1, left/1, + get_board_data/1,set_board_data/2, + set_butt/3, butt_correct/3, + draw/3, + %% Callbacks + init/1, handle_sync_event/3, + handle_event/2, handle_info/2, handle_call/3, + code_change/3, terminate/2]). + +-include("sudoku.hrl"). + +-record(state, {win, parent, board=[], pen, fonts=[]}). +-record(sq, {key,val,correct=true,given=false}). +-define(BRD,10). +-define(ARC_R, 10). + +-behaviour(wx_object). + +%% API +new(ParentObj) -> + wx_object:start_link(?MODULE, [ParentObj, self()], []). + +setup_board(Board, Init) -> + wx_object:call(Board, {setup_board, Init}). + +clear_board(Board) -> + wx_object:call(Board, clear_board). + +butt_correct(Board, Key, Correct) -> + wx_object:call(Board, {butt_correct, Key, Correct}). + +set_butt(Board, Indx, Val) when is_integer(Indx) -> + {R,C,_} = sudoku_game:rcm(Indx), + set_butt(Board, {R,C}, Val); +set_butt(Board, Id, Val) -> + wx_object:call(Board, {set_butt, Id, Val}). + +left(Board) -> + wx_object:call(Board, left). + +get_board_data(Board) -> + wx_object:call(Board, get_board_data). +set_board_data(Board, List) -> + wx_object:call(Board, {set_board_data, List}). + + +draw(Board, DC, Size) -> + wx_object:call(Board, {draw, DC, Size}). + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +init([ParentObj, ParentPid]) -> + Win = wxPanel:new(ParentObj, [{style, ?wxFULL_REPAINT_ON_RESIZE}]), + wxWindow:setFocus(Win), %% Get keyboard focus + wxWindow:setSizeHints(Win, {250,250}), + wxWindow:connect(Win, paint, [callback]), + wxWindow:connect(Win, size, []), + wxWindow:connect(Win, erase_background, []), + wxWindow:connect(Win, key_up, [{skip, true}]), + wxWindow:connect(Win, left_down, [{skip, true}]), + wxWindow:connect(Win, enter_window, [{skip, true}]), + + %% Init pens and fonts + Pen = wxPen:new({0,0,0}, [{width, 3}]), + Fs0 = [{Sz,wxFont:new(Sz, ?wxSWISS, ?wxNORMAL, ?wxNORMAL,[])} || + Sz <- [8,9,10,11,12,13,14,16,18,20,22,24,26,28,30,34,38,42,44,46]], + TestDC = wxClientDC:new(Win), + CW = fun({Sz,Font},Acc) -> + case wxFont:ok(Font) of + true -> + wxDC:setFont(TestDC, Font), + CH = wxDC:getCharHeight(TestDC), + [{CH,Sz,Font} | Acc]; + false -> + Acc + end + end, + Fs = lists:foldl(CW, [], Fs0), + wxClientDC:destroy(TestDC), + {Win, #state{win=Win, board=[], pen=Pen, fonts=Fs, parent=ParentPid}}. + +handle_sync_event(#wx{event=#wxPaint{}}, _Obj, State = #state{win=Win}) -> + %% io:format("EPaint~n",[]), + Size = wxWindow:getSize(Win), + DC = wxPaintDC:new(Win), + wxDC:destroyClippingRegion(DC), + redraw(DC,Size,State), + wxPaintDC:destroy(DC), + %%io:format("...EPaint~n",[]), + ok. + +handle_event(#wx{event=#wxMouse{type=enter_window}}, State = #state{win=Win}) -> + wxWindow:setFocus(Win), %% Get keyboard focus + {noreply,State}; +handle_event(#wx{event=#wxKey{keyCode=KeyC, x=X,y=Y}}, + S = #state{parent=Pid, win=Win}) -> + Val = if KeyC > 47, KeyC < 58 -> KeyC - $0; + KeyC > 325, KeyC < 336 -> KeyC - 326; %% NUM LOCK + true -> 0 + end, + case get_butt(X,Y,S) of + error -> %% Mac don't get correct coordinates. + Global = wx_misc:getMousePosition(), + {CX,CY} = wxWindow:screenToClient(Win, Global), + case get_butt(CX,CY,S) of + error -> ignore; + Id -> Pid ! {set_val,Id,Val} + end; + Id -> + Pid ! {set_val,Id,Val} + end, + {noreply, S}; +handle_event(#wx{event=#wxMouse{type=left_down,x=X,y=Y}}, + S = #state{parent=Gui, win=F}) -> + Id = get_butt(X,Y,S), + case Id of + error -> ignore; + _ -> create_popup_menu(Gui,Id,X,Y,F) + end, + {noreply, S}; +handle_event(#wx{event=#wxSize{}}, State) -> + redraw(State), + {noreply,State}; +handle_event(_Ev, State) -> + {noreply,State}. + +%%%%%%%%%%%%%%%%%%% + +handle_call({set_butt, Key, 0},_From,S0=#state{board=B0}) -> %% Reset + B = lists:keydelete(Key,2,B0), + S = S0#state{board=B}, + redraw(S), + {reply, ok, S}; + +handle_call({set_butt, Key, Val},_From,S0=#state{board=B0}) -> + case lists:keysearch(Key,2,B0) of + {value, _} -> + B = lists:keyreplace(Key, 2, B0, #sq{key=Key,val=Val}); + false -> + B = [#sq{key=Key, val=Val}|B0] + end, + S = S0#state{board=B}, + redraw(S), + {reply, ok, S}; + +handle_call({butt_correct, Key, Correct},_From, S0=#state{board=B0}) -> + case lists:keysearch(Key,2,B0) of + {value, Butt} -> + B = lists:keyreplace(Key, 2, B0, Butt#sq{key=Key,correct=Correct}); + false -> + B = B0 + end, + S = S0#state{board=B}, + redraw(S), + {reply, ok, S}; + +handle_call({setup_board, Init},_From, State) -> + B = [#sq{given=true, correct=true, key=Key, val=Val} || {Key,Val} <- Init], + S = State#state{board=B}, + redraw(S), + {reply, ok, S}; + +handle_call(clear_board,_From, State = #state{board=B0}) -> + B = [Butt || Butt = #sq{given=true} <- B0], + S = State#state{board=B}, + redraw(S), + Given = [{Key, Val} || #sq{key=Key,val=Val,given=true} <- B], + {reply, Given, S}; +handle_call(get_board_data,_From, S=#state{board=B0}) -> + {reply, B0, S}; +handle_call({set_board_data, B},_From, S0) -> + S = S0#state{board=B}, + redraw(S), + G1 = [{Key, Val} || #sq{key=Key,val=Val,given=true} <- B], + G2 = [{Key, Val} || #sq{key=Key,val=Val,given=false,correct=true} <- B], + G3 = [{Key, Val} || #sq{key=Key,val=Val,given=false,correct=false} <- B], + {reply, G1 ++ G2 ++ G3, S}; +handle_call(left,_From, S = #state{board=B}) -> + Res = 81 - length([ok || #sq{correct=C} <- B, C /= false]), + {reply, Res, S}; +handle_call({draw, DC, Size},_From, S) -> + redraw(DC,Size,S), + {reply, ok, S}. + +code_change(_, _, State) -> + {stop, not_yet_implemented, State}. + +handle_info(Msg, State) -> + {stop, {info, Msg}, State}. + +terminate(_Reason, _State) -> + normal. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +get_butt(X, Y, #state{win=Win}) -> + {W0,H0} = wxWindow:getSize(Win), + BoxSz = getGeomSz(W0,H0), + %% io:format("~p ~p ~p ~p~n", [{X,Y}, {W0,H0}, BoxSz, calc_pos(X-?BRD,Y-?BRD, BoxSz)]), + case calc_pos(X-?BRD,Y-?BRD, BoxSz) of + Pos = {R,C} when 0 < R, R < 10, 0 < C, C < 10 -> Pos; + _ -> error + end. + +calc_pos(X,Y, BoxSz) -> + {1+(Y*3 div BoxSz), 1+(X*3 div BoxSz)}. + +redraw(S = #state{win=Win}) -> + DC0 = wxClientDC:new(Win), + DC = wxBufferedDC:new(DC0), + Size = wxWindow:getSize(Win), + redraw(DC, Size, S), + wxBufferedDC:destroy(DC), + wxClientDC:destroy(DC0), + ok. + +redraw(DC, Size, S) -> + wx:batch(fun() -> + wxDC:setBackground(DC, ?wxWHITE_BRUSH), + wxDC:clear(DC), + BoxSz = draw_board(DC,Size,S), + F = sel_font(BoxSz div 3,S#state.fonts), + [draw_number(DC,F,BoxSz,Sq) || Sq <- S#state.board] + end). + +sel_font(_BS,[{_H,_Sz,F}]) -> + %% io:format("Font sz ~p height ~p in BS ~p~n",[_Sz,_H, _BS]), + F; +sel_font(BS,[{H,_Sz,F}|_]) when BS > (H + 6) -> + %% io:format("Font sz ~p height ~p in BS ~p~n",[_Sz,H, BS]), + F; +sel_font(BS,[_|Fs]) -> + sel_font(BS,Fs). + +draw_number(DC,F,Sz,#sq{key={R,C},val=Num,given=Bold,correct=Correct}) -> + {X,Y} = get_coords(Sz,R-1,C-1), + TBox = Sz div 3, + if Bold -> + wxFont:setWeight(F,?wxBOLD), + wxDC:setTextForeground(DC,{0,0,0}); + Correct =:= false -> + wxFont:setWeight(F,?wxNORMAL), + wxDC:setTextForeground(DC,{255,40,40,255}); + true -> + wxFont:setWeight(F,?wxNORMAL), + wxDC:setTextForeground(DC,{50,50,100,255}) + end, + wxDC:setFont(DC,F), + CH = (TBox - wxDC:getCharHeight(DC)) div 2, + CW = (TBox - wxDC:getCharWidth(DC)) div 2, + wxDC:drawText(DC, integer_to_list(Num), {X+CW,Y+CH+1}), + ok. + +get_coords(Sz,R,C) -> + TBox = Sz div 3, + R1 = R div 3, + R2 = R rem 3, + C1 = C div 3, + C2 = C rem 3, + {?BRD + C1*Sz + C2*TBox, + ?BRD + R1*Sz + R2*TBox}. + +draw_board(DC,{W0,H0},#state{pen=Pen}) -> + BoxSz = getGeomSz(W0,H0), + BS = ?BRD+3*BoxSz, + + wxPen:setWidth(Pen, 3), + wxPen:setColour(Pen, {0,0,0}), + wxDC:setPen(DC,Pen), + + wxDC:drawRoundedRectangle(DC, {?BRD,?BRD,3*BoxSz+1,3*BoxSz+1}, + float(?ARC_R)), + %% Testing DrawLines + wxDC:drawLines(DC, [{?BRD+BoxSz, ?BRD}, {?BRD+BoxSz, BS}]), + wxDC:drawLine(DC, {?BRD+BoxSz*2, ?BRD}, {?BRD+BoxSz*2, BS}), + wxDC:drawLine(DC, {?BRD, ?BRD+BoxSz}, {BS, ?BRD+BoxSz}), + wxDC:drawLine(DC, {?BRD, ?BRD+BoxSz*2}, {BS, ?BRD+BoxSz*2}), + + %% Draw inside lines + wxPen:setWidth(Pen, 1), + wxDC:setPen(DC,Pen), + TBox = BoxSz div 3, + wxDC:drawLine(DC, {?BRD+TBox, ?BRD}, {?BRD+TBox, BS}), + wxDC:drawLine(DC, {?BRD+TBox*2, ?BRD}, {?BRD+TBox*2, BS}), + wxDC:drawLine(DC, {?BRD+TBox+BoxSz, ?BRD}, {?BRD+TBox+BoxSz, BS}), + wxDC:drawLine(DC, {?BRD+TBox*2+BoxSz, ?BRD}, {?BRD+TBox*2+BoxSz, BS}), + wxDC:drawLine(DC, {?BRD+TBox+BoxSz*2, ?BRD}, {?BRD+TBox+BoxSz*2, BS}), + wxDC:drawLine(DC, {?BRD+TBox*2+BoxSz*2, ?BRD}, {?BRD+TBox*2+BoxSz*2, BS}), + %% Vert + wxDC:drawLine(DC, {?BRD, ?BRD+TBox}, {BS, ?BRD+TBox}), + wxDC:drawLine(DC, {?BRD, ?BRD+TBox*2}, {BS, ?BRD+TBox*2}), + wxDC:drawLine(DC, {?BRD, ?BRD+TBox+BoxSz}, {BS, ?BRD+TBox+BoxSz}), + wxDC:drawLine(DC, {?BRD, ?BRD+TBox*2+BoxSz}, {BS, ?BRD+TBox*2+BoxSz}), + wxDC:drawLine(DC, {?BRD, ?BRD+TBox+BoxSz*2}, {BS, ?BRD+TBox+BoxSz*2}), + wxDC:drawLine(DC, {?BRD, ?BRD+TBox*2+BoxSz*2}, {BS, ?BRD+TBox*2+BoxSz*2}), + BoxSz. + +getGeomSz(W,H) -> + Small = if W < H -> W; true -> H end, + (Small - 2*?BRD) div 3. + + +%% popupmenu + +create_popup_menu(GFX,Butt,X,Y,Frame) -> + Port = wx:get_env(), + spawn_link(fun() -> create_popup_menu1(GFX,Butt,Port,X,Y,Frame) end). + +create_popup_menu1(GFX,Butt,Port,X,Y,Frame) -> + wx:set_env(Port), + PopupMenu = wxMenu:new(), + create_popup_menu2(1, PopupMenu), + + wxEvtHandler:connect(PopupMenu, command_menu_selected), + wxWindow:popupMenu(Frame,PopupMenu,X,Y), + receive + #wx{event=#wxCommand{type=command_menu_selected},id=10} -> + GFX ! {set_val,Butt,0}; + #wx{event=#wxCommand{type=command_menu_selected},id=What} -> + GFX ! {set_val,Butt,What} + end. + +create_popup_menu2(N,PP) when N > 9 -> + wxMenu:append(PP, 10, "Clear"); +create_popup_menu2(N,PP) -> + wxMenu:append(PP, N,integer_to_list(N)), + create_popup_menu2(N+1,PP). + diff --git a/lib/wx/examples/sudoku/sudoku_game.erl b/lib/wx/examples/sudoku/sudoku_game.erl new file mode 100755 index 0000000000..470aee0e3b --- /dev/null +++ b/lib/wx/examples/sudoku/sudoku_game.erl @@ -0,0 +1,503 @@ +%% +%% %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(sudoku_game). +-compile(export_all). +-include("sudoku.hrl"). + +init(GFX) -> + Empty = empty_table(#s{}), + Add = fun({Butt,Val},SN) -> + validate(rcm(Butt),Val,false,SN) + end, + + Game = test(), + GFX ! {init, Game}, + Self = self(), + Gen = spawn_opt(fun() -> create_games(levels(),Self) end, + [link, {priority,low}]), + loop(lists:foldl(Add,Empty#s{gfx=GFX, gen=Gen},Game)). + +%%%%%%%%%%%%%%%%%% Game Engine %%%%%%%%%%%%%%%%%% + +empty_table(S) -> + Nine = lists:seq(1,9), + D = gb_sets:from_ordset(Nine), + Mat = list_to_tuple([D || _ <- Nine]), + Poss = list_to_tuple([D || _ <- lists:seq(1,9*9)]), + Vals = list_to_tuple([0 || _ <- lists:seq(1,9*9)]), + Must = list_to_tuple([gb_sets:empty() || _ <- lists:seq(1,9*3)]), + S#s{p=Poss,m=Mat,mr=Must,mc=Must,v=Vals}. + +loop(S0 = #s{gfx = Gfx, v=Vs}) -> + receive + quit -> + halt; + {'EXIT', Gfx, Reason} -> + io:format("The GUI crashed: ~p~n", [Reason]); + {validate, Butt, Val} -> + Ix = indx(Butt), + case element(Ix,Vs) of + Val -> loop(S0); + 0 -> + S = validate(rcm(Butt),Val,true,S0), + loop(S); + _ -> + S1 = S0#s{v=setelement(Ix,Vs,0)}, + S2 = rebuild_all(rcm(Butt),S1), + S = validate(rcm(Butt),Val,true,S2), + loop(S) + end; + {loaded, Game} -> + S1 = empty_table(S0), + Add = fun({Butt,Val},SN) -> + validate(rcm(Butt),Val,true,SN) + end, + loop(lists:foldl(Add,S1,Game)); + {op,?EMPTY} -> + loop(empty_table(S0)); + {op,?NEW, Level} -> + case find_game(Level,S0) of + {Game, S1} -> + S0#s.gen ! {gen_game, Level}, + Gfx ! {busy,start}, + Gfx ! {init, Game}; + false -> + S1 = S0, + Gfx ! {busy,start}, + Temp = new_game(S0), + Game = pick_shown(Temp,Level,Gfx), + S0#s.gen ! {gen_game, Level}, + Game + end, + S2 = empty_table(S1), + Add = fun({Butt,Val},SN) -> + validate(rcm(Butt),Val,false, SN) + end, + Gfx ! {init, Game}, + Gfx ! {busy,stop}, + loop(lists:foldl(Add,S2,Game)); + {solve, All} -> + Res = solve(S0, All), + [Gfx ! {set_val, Ind, Val} || {Ind,Val} <- element(2,Res)], + loop(S0); + {get_game, Pid} -> + Pid ! {game, get_known(S0)}, + loop(S0); + {game, Game} -> + loop(S0#s{games=[Game|S0#s.games]}); + CMD -> + io:format("Game loop got ~p~n", [CMD]), + ?MODULE:loop(S0) + end. + +validate({R,C,_M},0,Send,St = #s{gfx=Gfx}) -> + if Send -> Gfx ! {correct, {R,C}}; true -> ok end, + St; +validate(RCM={R,C,_M},Val,Send,St = #s{gfx=Gfx,v=Vs}) -> + S = poss(RCM,St), + case gb_sets:is_member(Val,S) of + true -> + if Send -> Gfx ! {correct, {R,C}}; true -> ok end, + add(RCM,Val,St); + false -> + if Send -> Gfx ! {wrong, {R,C}}; true -> ok end, + St#s{v=setelement(indx(R,C),Vs,Val)} + end. + +rebuild_all(_, S0) -> + Solved = get_known(S0), + S1 = empty_table(S0), + lists:foldl(fun({Indx,Val},Acc) -> + add(rcm(Indx),Val,Acc) + end, S1, Solved). + +is_ok({RI,CI,MI}, Vals) -> + [Ri,Ci,Mi] = all(RI,CI,MI), + case element(indx(RI,CI),Vals) of + 0 -> true; + Val -> + Vs = [[element(indx(R,C),Vals)||{R,C} <- Obs, + not ((R == RI) and (C == CI))] + || Obs <- [Ri,Ci,Mi]], + not lists:member(Val,lists:flatten(Vs)) + end. + +test() -> %% Known to solvable + [{{1,2},6}, {{1,4},1}, {{1,6},4}, {{1,8},5}, + {{2,3},8}, {{2,4},3}, {{2,6},5}, {{2,7},6}, + {{3,1},2}, {{3,9},1}, + {{4,1},8}, {{4,4},4}, {{4,6},7}, {{4,9},6}, + {{5,3},6}, {{5,7},3}, + {{6,1},7}, {{6,4},9}, {{6,6},1}, {{6,9},4}, + {{7,1},5}, {{7,9},2}, + {{8,3},7}, {{8,4},2}, {{8,6},6}, {{8,7},9}, + {{9,2},4}, {{9,4},5}, {{9,6},8}, {{9,8},7}]. + +new_game(S) -> + {X,Y,Z} = erlang:now(), + random:seed(Y,X,Z), + case new_game(1,1,gb_sets:empty(),empty_table(S#s{}),[], 0) of + stop -> new_game(S); + Game -> Game + end. + + +new_game(_,_,_,_St,_Acc,Cnt) when Cnt > 200 -> + %% Backtracked 200 times, Bad path lets start over + stop; +new_game(R,C,BT,St,Acc,Cnt) when R < 10, C < 10 -> + M = mat(R,C), + U = poss({R,C,M},St), + S = gb_sets:difference(U,BT), + case gb_sets:size(S) of + 0 -> + [{{BR,BC},BVal,BBT,BST}|BAcc] = Acc, + new_game(BR,BC,gb_sets:add(BVal,BBT),BST,BAcc,Cnt+1); + Size -> + Ind = random:uniform(Size), + V = lists:nth(Ind,gb_sets:to_list(S)), + new_game(R,C+1,gb_sets:empty(), + add({R,C,M},V,St), + [{{R,C},V,BT,St}|Acc], Cnt) + end; +new_game(R,_C,Bt,S,Acc,Cnt) when R < 10 -> + new_game(R+1,1,Bt,S,Acc,Cnt); +new_game(_,_,_,S,_Acc,_Cnt) -> +%% io:format("Backtracked ~p ~n",[_Cnt]), + S. + +pick_shown(S0, Level, Gfx) -> + Given = gb_sets:from_ordset([I || I <- lists:seq(1,9*9)]), + get_known(pick_shown(Given,Given,S0,level(Level),Gfx)). + +get_known(#s{v=Vals}) -> + lists:foldl(fun(Index,Acc) -> + case element(Index,Vals) of + 0 -> Acc; + Val -> + {R,C,_} = rcm(Index), + [{{R,C},Val}|Acc] + end + end, [], lists:seq(1,9*9)). + +pick_shown(Given,Left,S0,Level,Gfx) -> + LeftSz = gb_sets:size(Left), + GivenSz = gb_sets:size(Given), + if LeftSz == 0 -> + io:format("No left ~p~n", [GivenSz]), + S0; + GivenSz < Level -> + io:format("Below level ~p ~p~n", [GivenSz,Level]), + S0; + true -> + Ran = random:uniform(LeftSz), + V = lists:nth(Ran,gb_sets:to_list(Left)), + S1 = rebuild_all(rcm(V),S0#s{v=setelement(V,S0#s.v,0)}), + case solve(S1, true) of + {true, _, _} -> + catch Gfx ! {working, 100-LeftSz}, + pick_shown(gb_sets:delete(V,Given), + gb_sets:delete(V,Left), + S1, Level,Gfx); + {false,_,_} -> + pick_shown(Given,gb_sets:delete(V,Left), + S0, Level,Gfx) + end + end. + +solve(St=#s{v=Vals},All) -> + Unsolved = [I || I <- lists:seq(1,9*9), element(I,Vals) == 0], + solve(Unsolved, All, St, [], [], lists:reverse(Unsolved)). + +solve(Rem, false, _St, [Solved|_], Unsolved, _) -> {true, [Solved], Rem ++ Unsolved}; +solve([], _, _St, Solved, [], _) -> {true, Solved, []}; +solve([], _, _St, Solved, Unsolved, Unsolved) -> {false, Solved, Unsolved}; +solve([], _, St, Solved, Unsolved, _Orig) -> + solve(Unsolved,true,St,Solved,[],lists:reverse(Unsolved)); +solve([Index|Rest],All, St, S, US, Orig) -> + RCM = rcm(Index), + Poss = poss(RCM,St), + case gb_sets:size(Poss) of + 1 -> + %% io:format("S1 ~n",[]), + [Val] = gb_sets:to_list(Poss), + solve(Rest, All, add(RCM,Val,St), [{Index,Val}|S],US,Orig); + _ -> + case solve_1(RCM, Poss, St) of + false -> + solve(Rest, All, St, S, [Index|US],Orig); + Val -> + solve(Rest, All, add(RCM,Val,St), [{Index,Val}|S],US,Orig) + end + end. + +solve_1(RCM={R,C,_M}, Avail, St) -> + All = all(RCM), + Poss = fun({RI,CI},Acc) when (RI == R) and (CI == C) -> Acc; + ({RI,CI},Acc) -> gb_sets:union(poss(rcm({RI,CI}),St),Acc) + end, + D = fun({RI,CI},Acc) when (RI == R) and (CI == C) -> + io:format("~p:~p: ignore~n",[RI,CI]), + Acc; + ({RI,CI},Acc) -> + Res = gb_sets:union(poss(rcm({RI,CI}),St),Acc), + io:format("~p:~p: ~p => ~p ~n",[RI,CI,gb_sets:to_list(poss(rcm({RI,CI}),St)),gb_sets:to_list(Res)]), + Res + end, + solve_2(All,{Poss,D},Avail). + +solve_2([],_, _) -> false; +solve_2([First|R],{Poss,D},Avail) -> + All = lists:foldl(Poss, gb_sets:empty(), First), + Res = gb_sets:difference(Avail, All), + case gb_sets:size(Res) of + 1 -> + %% lists:foldl(D, gb_sets:empty(), First), + %% io:format("Poss: ~w~nA: ~p O:~p ~n",[First,gb_sets:to_list(Avail),gb_sets:to_list(All)]), + [Val] = gb_sets:to_list(Res), + Val; + _ -> + solve_2(R,{Poss,D},Avail) + end. + +all({RI,CI,MI}) -> all(RI,CI,MI). +all(RI,CI,MI) -> + MR = ((MI-1) div 3)*3, + MC = ((MI-1) rem 3)*3, + Ri = [{RI,N} || N <- lists:seq(1,9)], + Ci = [{N,CI} || N <- lists:seq(1,9)], + Mi = [{1+MR,1+MC},{1+MR,2+MC},{1+MR,3+MC}, + {2+MR,1+MC},{2+MR,2+MC},{2+MR,3+MC}, + {3+MR,1+MC},{3+MR,2+MC},{3+MR,3+MC}], + [Ri,Ci,Mi]. + +other_mats(N) -> + if N < 4 -> P1=3, P2= 6; + N < 7 -> P1=-3,P2= 3; + true -> P1=-6,P2=-3 + end, + case (N-1) rem 3 of + 0 -> [N+1,N+2,N+P1,N+P2]; + 1 -> [N-1,N+1,N+P1,N+P2]; + 2 -> [N-2,N-1,N+P1,N+P2] + end. + +check_must(S=#s{p=Poss,m=MS,mr=MR0,mc=MC0}) -> + List = lists:seq(1,9), + {MR,MC} = lists:foldl(fun(Val,{MRT,MCT}) -> + check_must2(List,Val,Poss,MS,MRT,MCT) + end, {MR0,MC0}, List), + S#s{mr=MR,mc=MC}. + +check_must2([M|Rest],Val,Poss,Ms,MR0,MC0) -> + case gb_sets:is_member(Val, element(M,Ms)) of + true -> + {Rows,Cols} = rc_in_mat(M), + MR1 = check_must3(Rows,Val,Poss,row,MR0), + MC1 = check_must3(Cols,Val,Poss,col,MC0), + check_must2(Rest,Val,Poss,Ms,MR1,MC1); + false -> + check_must2(Rest,Val,Poss,Ms,MR0,MC0) + end; +check_must2([],_,_,_,MR,MC) -> {MR,MC}. + +check_must3({F1,F2,F3},Val,Check,Type,Must0) -> + R1 = not gb_sets:is_member(Val, get_poss(F1,Check,gb_sets:empty())), + R2 = not gb_sets:is_member(Val, get_poss(F2,Check,gb_sets:empty())), + R3 = not gb_sets:is_member(Val, get_poss(F3,Check,gb_sets:empty())), + %% io:format("M=~p ~p ~p ~p ~p~n",[M,[R1,R2,R3],gb_sets:to_list(element(F1,Check)),gb_sets:to_list(element(F2,Check)),gb_sets:to_list(element(F3,Check))]), + if R1,R2 -> update_must(Type,F3,Val,Must0); + R1,R3 -> update_must(Type,F2,Val,Must0); + R2,R3 -> update_must(Type,F1,Val,Must0); + true -> Must0 + end. + +update_must(Type,[Indx|_],Val,Must) -> + N = mindx(Type, Indx), + %% io:format("~p ~p ~p must contain ~p~n",[Type,N,rcm(Indx),Val]), + Set = element(N,Must), + setelement(N,Must, gb_sets:add(Val,Set)). + +add(RCM={R,C,M},Val,S=#s{p=P0,m=MS,v=Vals,mr=MR0,mc=MC0}) -> + Ri = mindx(R,M), + Ci = mindx(M,C), + MR = delete(Val,Ri,MR0), + MC = delete(Val,Ci,MC0), + P1 = setelement(indx(RCM),P0,gb_sets:empty()), + check_must(S#s{p=delete(Val,lists:flatten(all(RCM)),P1), + m=delete(Val,M,MS), + mr=MR,mc=MC, + v=setelement(indx(RCM),Vals,Val)}). + +poss(RCM={R,C,M}, #s{p=P,v=Vals,mr=MR,mc=MC}) -> + I = indx(R,C), + case element(I, Vals) of + 0 -> + Rm = mindx(R,M), + Cm = mindx(M,C), + T1 = gb_sets:intersection(element(Rm,MR),element(Cm,MC)), + case gb_sets:size(T1) of + 1 -> T1; + _ -> + Not = get_nots(RCM,MR,MC), + gb_sets:difference(element(I,P),Not) + end; + _ -> + gb_sets:empty() + end. + +get_nots({R,C,M},MR,MC) -> + [RM1,RM2,CM1,CM2] = other_mats(M), + R1 = get_poss([mindx(R,RM1),mindx(R,RM2)],MR,gb_sets:empty()), + R2 = get_poss([mindx(CM1,C),mindx(CM2,C)],MC,R1), + %% io:format("~p:~p:~p ~p ~p~n", + %% [C,CM1,CM2, + %% gb_sets:to_list(element(mindx(CM1,C),MC)), + %% gb_sets:to_list(element(mindx(CM2,C),MC))]), + R2. + +get_poss([],_,Tot) -> Tot; +get_poss([H|R],What,Tot) -> + %% io:format("~p~n",[H]), + get_poss(R,What, gb_sets:union(element(H,What),Tot)). + +r2rs(R) -> + R0 = (R-1)*3, + [R0+1,R0+2,R0+3]. + +c2cs(C) -> + C0 = (C-1) rem 9, + [C0+1, C0+10, C0+19]. + +mindx(row,Indx) -> + {R,_C,M} = rcm(Indx), + mindx(R,M); +mindx(col,Indx) -> + {_R,C,M} = rcm(Indx), + mindx(M,C); + +mindx(R,M) -> + 1+(R-1)*3 + (M-1) rem 3. + +rcm(Indx) when is_integer(Indx) -> + rcm({((Indx-1) div 9)+1, (Indx-1) rem 9+1}); +rcm({R,C}) -> + M = mat(R,C), + {R,C,M}. +mat(R,C) -> + 1+(C-1) div 3 + ((R-1) div 3)*3. + +rc_in_mat(M) -> + R1 = 1+3*((M-1) div 3), + C1 = 1+3*((M-1) rem 3), + {{[indx({R1+0,C1+0}),indx({R1+0,C1+1}),indx({R1+0,C1+2})], + [indx({R1+1,C1+0}),indx({R1+1,C1+1}),indx({R1+1,C1+2})], + [indx({R1+2,C1+0}),indx({R1+2,C1+1}),indx({R1+2,C1+2})]}, + + {[indx({R1+0,C1+0}),indx({R1+1,C1+0}),indx({R1+2,C1+0})], + [indx({R1+0,C1+1}),indx({R1+1,C1+1}),indx({R1+2,C1+1})], + [indx({R1+0,C1+2}),indx({R1+1,C1+2}),indx({R1+2,C1+2})]}}. + +indx(Indx) when is_integer(Indx) -> Indx; +indx({Row, Col}) -> + indx(Row,Col); +indx({Row, Col,_}) -> + indx(Row,Col). +indx(Row, Col) -> + (Row-1)*9+Col. + +delete(_Val,[],S0) -> S0; +delete(Val,[I1|R],S0) -> + I = if is_integer(I1) -> I1; + true -> indx(I1) + end, + S = setelement(I,S0,gb_sets:delete_any(Val, element(I,S0))), + delete(Val,R,S); +delete(Val,I,S) -> + setelement(I,S,gb_sets:delete_any(Val, element(I,S))). + +%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Pre generate games on low priority +create_games(Levels,Engine) -> + gen_loop(Levels, Engine, 5). + +gen_loop([], Engine,_) -> + receive + {gen_game, Level} -> + gen_loop([Level], Engine,5) + end; +gen_loop([Level|Ls], Engine, N) when N > 0 -> + Empty = empty_table(#s{}), + Temp = new_game(Empty), + Game = pick_shown(Temp,Level,undefined), + ResLev = length(Game), + Engine ! {game, {ResLev, Game}}, + case ResLev =< level(Level) of + true -> + gen_loop(Ls,Engine, 5); + false -> + gen_loop([Level|Ls],Engine, N-1) + end; +gen_loop([_|Ls],Engine, _) -> + gen_loop(Ls,Engine, 5). + +find_game(_, #s{games=[]}) -> false; +find_game(hardest, S = #s{games=Gs0}) -> + Hard = level(hard), + case lists:sort(Gs0) of + [{Level,G}|Gs] when Level < (Hard-5) -> + {G, S#s{games=Gs}}; + _ -> false + end; +find_game(Level, S = #s{games=Gs0}) -> + case find_game2(level(Level), lists:reverse(lists:sort(Gs0)), []) of + false -> false; + {Game, Gs} -> {Game,S#s{games=Gs}} + end. + +find_game2(Hard, [{Level,G}|Gs], Acc) when Level =< Hard, Level > (Hard-5) -> + {G, Gs ++ Acc}; +find_game2(Hard, [G|Gs], Acc) -> + find_game2(Hard, Gs, [G|Acc]); +find_game2(_Hard, [], _ ) -> false. + +levels() -> + [trivial,easy,normal,hard,hardest]. + +level(Level) when is_atom(Level) -> + case Level of + all -> 100; + trivial -> 40; + easy -> 35; + normal -> 30; + hard -> 25; + hardest -> 0 + end; +level(Int) when is_integer(Int) -> + if + Int =< 20 -> hardest; + Int =< 25 -> hard; + Int =< 30 -> normal; + Int =< 35 -> easy; + true -> trivial + end. + + + diff --git a/lib/wx/examples/sudoku/sudoku_gui.erl b/lib/wx/examples/sudoku/sudoku_gui.erl new file mode 100755 index 0000000000..4aaecfe086 --- /dev/null +++ b/lib/wx/examples/sudoku/sudoku_gui.erl @@ -0,0 +1,391 @@ +%% +%% %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% +%%%------------------------------------------------------------------- +%%% File : sudoku_gui.erl +%%% Author : <[email protected]> +%%% Description : The Gui and it's event loop +%%% +%%% Created : 9 Jan 2008 by <[email protected]> +%%%------------------------------------------------------------------- +-module(sudoku_gui). + +-export([init/1, handle_info/2, handle_call/3, handle_event/2, + terminate/2, code_change/3]). + +-compile(export_all). + +-behaviour(wx_object). + +-include("sudoku.hrl"). + +-import(sudoku_game, [indx/1]). + +%%%%%%%%%% Graphic engine %%%%%%%%%%%%%% + +-record(gs,{board,show_err=true,level=hard,game,frame,orig=[], print_d, print_psdd}). + +new(Game) -> + wx:new(), + wx_object:start_link(?MODULE, [Game], []). + +%%%%%%%%%%%%%%%%%%%%% Server callbacks %%%%%%%%%%%%% + +init([Game]) -> + {Frame, Board} = wx:batch(fun() -> create_window() end), + Game ! {gfx, self()}, + {Frame, init_printer(#gs{board=Board,game=Game,frame=Frame})}. + +create_window() -> + Frame = wxFrame:new(wx:null(), -1, "Sudoku", []), + + wxFrame:createStatusBar(Frame,[]), + wxFrame:connect(Frame, close_window), + + MenuBar = wxMenuBar:new(), + File = wxMenu:new([]), + Opt = wxMenu:new([]), + Help = wxMenu:new([]), + + wxMenu:append(File, ?NEW, "&New Game"), + wxMenu:append(File, ?OPEN, "&Open Game"), + wxMenu:append(File, ?SAVE, "&Save Game"), + wxMenu:appendSeparator(File), + wxMenu:append(File, ?PRINT, "Print"), + wxMenu:append(File, ?PRINT_PAGE_SETUP, "Page Setup"), + wxMenu:append(File, ?PRINT_PRE, "Print Preview"), + wxMenu:appendSeparator(File), + wxMenu:append(File, ?QUIT, "&Quit Game"), + + wxMenu:append(Help, ?RULES, "Rules"), + wxMenu:append(Help, ?ABOUT, "About"), + + wxMenu:appendRadioItem(Opt, ?TRIVIAL, "Level: Trivial"), + wxMenu:appendRadioItem(Opt, ?EASY, "Level: Easy"), + LItem = wxMenu:appendRadioItem(Opt, ?NORMAL, "Level: Normal"), + wxMenu:appendRadioItem(Opt, ?HARD, "Level: Hard"), + wxMenu:appendRadioItem(Opt, ?HARDEST, "Level: Hardest"), + wxMenu:appendSeparator(Opt), + EItem = wxMenu:appendCheckItem(Opt, ?SHOW_ERROR, "Show errors"), + + wxMenuBar:append(MenuBar, File, "&File"), + wxMenuBar:append(MenuBar, Opt, "O&ptions"), + wxMenuBar:append(MenuBar, Help, "&Help"), + + wxFrame:setMenuBar(Frame, MenuBar), + wxFrame:connect(Frame, command_menu_selected), + + MainSz = wxBoxSizer:new(?wxVERTICAL), + Top = wxBoxSizer:new(?wxHORIZONTAL), + + Panel = wxPanel:new(Frame), + NewGame = wxButton:new(Panel, ?NEW, [{label,"New Game"}]), + wxButton:connect(NewGame, command_button_clicked), + Empty = wxButton:new(Panel, ?EMPTY, [{label,"Empty Board "}]), + wxButton:connect(Empty, command_button_clicked), + Clean = wxButton:new(Panel, ?CLEAR, [{label,"Clear"}]), + wxButton:connect(Clean, command_button_clicked), + Hint = wxButton:new(Panel, ?HINT, [{label, "Hint"}]), + wxButton:connect(Hint, command_button_clicked), + + wxSizer:addSpacer(Top,2), + SF = wxSizerFlags:new(), + wxSizerFlags:proportion(SF,1), + wxSizer:add(Top, NewGame, wxSizerFlags:left(SF)), + wxSizer:addSpacer(Top,3), + wxSizer:add(Top, Empty, wxSizerFlags:center(SF)), + wxSizer:addSpacer(Top,3), + wxSizer:add(Top, Clean, wxSizerFlags:center(SF)), + wxSizer:addSpacer(Top,3), + wxSizer:add(Top, Hint, wxSizerFlags:right(SF)), + + wxSizer:addSpacer(MainSz,5), + wxSizer:add(MainSz, Top, wxSizerFlags:center(wxSizerFlags:proportion(SF,0))), + wxSizer:addSpacer(MainSz,10), + + Board = sudoku_board:new(Panel), + + wxSizer:add(MainSz, Board, wxSizerFlags:proportion(wxSizerFlags:expand(SF),1)), + wxWindow:setSizer(Panel,MainSz), + wxSizer:fit(MainSz, Frame), + wxSizer:setSizeHints(MainSz,Frame), + wxWindow:show(Frame), + %% Check after append so it's initialized on all platforms + wxMenuItem:check(LItem), + wxMenuItem:check(EItem), + {Frame, Board}. + +status(Win, F, A) -> + Str = lists:flatten(io_lib:format(F, A)), + wxFrame:setStatusText(Win, Str). + +%%%%%%%%%%%%%%%% Info i.e. messages %%%%%%%%%%%%%%%%%%%%% + +handle_info(quit, S=#gs{game=G,frame=F}) -> + wxWindow:close(F), + wx_core:quit(), + G ! quit, + {stop, shutdown, S}; + +handle_info({init, Init}, S = #gs{board=Board,frame=F}) -> + sudoku_board:setup_board(Board, Init), + status(F, "Given ~p Left ~p", [length(Init), sudoku_board:left(Board)]), + {noreply, S#gs{orig=[indx(Id)||{Id,_}<-Init]}}; +handle_info({correct, ButtI}, S = #gs{board=Board, orig=Orig,frame=F}) -> + sudoku_board:butt_correct(Board, ButtI, true), + case sudoku_board:left(Board) of + 0 -> + Str = "Congrats, now try a harder one", + MD = wxMessageDialog:new(F,Str, + [{style, ?wxOK bor ?wxICON_INFORMATION}, + {caption, "Complete"}]), + wxDialog:showModal(MD), + wxDialog:destroy(MD), + status(F, "Given ~p Left ~p", [length(Orig), 0]); + L -> + status(F, "Given ~p Left ~p", [length(Orig), L]) + end, + {noreply, S}; +handle_info({wrong, ButtI}, S = #gs{board=Board}) -> + case S#gs.show_err of + true -> + sudoku_board:butt_correct(Board, ButtI, false); + false -> + ignore + end, + {noreply, S}; +handle_info({set_val, ButtI, Val}, S = #gs{game=G,board=Board,orig=Orig}) -> + case lists:member(indx(ButtI), Orig) of + false -> set_val(ButtI, Val, Board, G); + true -> ignore + end, + {noreply, S}; +handle_info({working, Done}, S = #gs{frame=F}) -> + status(F, "Thinking: ~p%", [Done]), + {noreply, S}; +handle_info({busy, Mode},S) -> + case Mode of + start -> wx_misc:beginBusyCursor(); + stop -> wx_misc:endBusyCursor() + end, + {noreply, S}. + +%%%%%%%%%%%%%%%%% GUI-Events %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +handle_event(#wx{id=?HINT, event=#wxCommand{type=command_button_clicked}}, + S = #gs{game=G}) -> + G ! {solve,false}, + {noreply,S}; + +handle_event(#wx{event=#wxClose{}}, + S = #gs{game=G,frame=F}) -> + catch wxWindow:'Destroy'(F), + G ! quit, + {stop, shutdown, S}; + +handle_event(#wx{id=?QUIT, event=#wxCommand{type=command_menu_selected}}, + S = #gs{game=G,frame=F}) -> + wxWindow:close(F,[]), + G ! quit, + {stop, shutdown, S}; + +%% type=command_button_clicked, +handle_event(#wx{id=?NEW, event=#wxCommand{}}, + S = #gs{game=G, board=Board}) -> + G ! {op,?NEW,S#gs.level}, + sudoku_board:setup_board(Board,[]), + {noreply, S#gs{orig=[]}}; +handle_event(#wx{id=?EMPTY, event=#wxCommand{}}, + S = #gs{game=G, board=Board}) -> + G ! {op,?EMPTY}, + sudoku_board:setup_board(Board,[]), + {noreply, S#gs{orig=[]}}; +handle_event(#wx{id=?CLEAR, event=#wxCommand{}}, + S = #gs{game=G,board=Board}) -> + Vals = sudoku_board:clear_board(Board), + G ! {loaded, Vals}, + {noreply, S}; +handle_event(#wx{id=ID, event=#wxCommand{}}, S) when ID > 125 -> + New = dialog(ID, S), + {noreply, New}; +handle_event(Msg,S) -> + io:format("~p: Unhandled event ~p~n",[?MODULE, Msg]), + %%sudoku_board:event(Msg, Ids), + {noreply, S}. + +handle_call(What, _From, State) -> + {stop, {call, What}, State}. + +code_change(_, _, State) -> + {stop, not_yet_implemented, State}. + +terminate(_Reason, _State) -> + normal. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +dialog(?SHOW_ERROR, S=#gs{show_err=Show}) -> + S#gs{show_err = not Show}; +dialog(ID, S) when ID >= 210, ID =< 240 -> + Level = sudoku_game:level(ID-200), + S#gs{level = Level}; +dialog(?SAVE, S=#gs{frame=Frame, board=Board}) -> + FD = wxFileDialog:new(Frame, [{style, ?wxFD_SAVE bor + ?wxFD_OVERWRITE_PROMPT}]), + case wxFileDialog:showModal(FD) of + ?wxID_OK -> + Path = wxFileDialog:getPath(FD), + {ok,Fd} = file:open(Path, [write]), + List = sudoku_board:get_board_data(Board), + io:format(Fd, "~w.~n", [List]), + file:close(Fd); + _ -> + ignore + end, + wxDialog:destroy(FD), + S; +dialog(?OPEN, S=#gs{game=Server, frame=Frame, board=Board}) -> + FD = wxFileDialog:new(Frame,[{style, ?wxFD_OPEN bor ?wxFD_FILE_MUST_EXIST}]), + case wxDialog:showModal(FD) of + ?wxID_OK -> + Path = wxFileDialog:getPath(FD), + case file:consult(Path) of + {ok, [Game]} when is_list(Game) -> + Vals = sudoku_board:set_board_data(Board, Game), + Server ! {loaded, Vals}; + _ -> + ignore + end; + _ -> + ignore + end, + wxFileDialog:destroy(FD), + S; +dialog(?ABOUT, S=#gs{frame=Frame}) -> + Str = "I'm just testing WxWidgets.\n" + "Testing various features and usages.\n/Dgud", + MD = wxMessageDialog:new(Frame,Str, + [{style, ?wxOK bor ?wxICON_INFORMATION}, + {caption, "About box"}]), + wxDialog:showModal(MD), + wxDialog:destroy(MD), + S; +dialog(?RULES, S) -> + wx_misc:launchDefaultBrowser("http://www.sudoku.com"), + S; + +dialog(?PRINT_PAGE_SETUP, S = #gs{frame=Frame, print_psdd=PsDD0, print_d=PD0}) -> + wxPageSetupDialogData:setPrintData(PsDD0, PD0), + PSD = wxPageSetupDialog:new(Frame, [{data,PsDD0}]), + wxPageSetupDialog:showModal(PSD), + + PSDD1 = wxPageSetupDialog:getPageSetupData(PSD), + PD1 = wxPageSetupDialogData:getPrintData(PSDD1), + %% Create new objects using copy constr. + PD = wxPrintData:new(PD1), + PsDD = wxPageSetupDialogData:new(PSDD1), + wxPageSetupDialog:destroy(PSD), + wxPageSetupDialogData:destroy(PsDD0), + wxPrintData:destroy(PD0), + S#gs{print_psdd=PsDD, print_d=PD}; +dialog(?PRINT_PRE, S = #gs{frame=Frame, print_d=PD}) -> + PDD = wxPrintDialogData:new(PD), + Printout1 = wxPrintout:new("Print", fun(This,Page) -> printout(This,Page,S) end, + [{getPageInfo, fun getPageInfo/1}]), + Printout2 = wxPrintout:new("Print", fun(This,Page) -> printout(This,Page,S) end, + [{getPageInfo, fun getPageInfo/1}]), + Preview = wxPrintPreview:new(Printout1, [{printoutForPrinting,Printout2},{data,PDD}]), + case wxPrintPreview:isOk(Preview) of + true -> + PF = wxPreviewFrame:new(Preview, Frame, [{title, "Print Preview"}]), + wxPreviewFrame:centre(PF, [{dir, ?wxBOTH}]), + wxPreviewFrame:initialize(PF), + wxPreviewFrame:centre(PF), + wxPreviewFrame:show(PF); + false -> + io:format("Could not create preview window.\n" + "Perhaps your current printer is not set correctly?~n", []), + wxPrintPreview:destroy(Preview) + end, + S; +dialog(?PRINT, S = #gs{frame=Frame, print_d=PD}) -> + PDD = wxPrintDialogData:new(PD), + Printer = wxPrinter:new([{data,PDD}]), + Printout = wxPrintout:new("Print", fun(This,Page) -> printout(This,Page,S) end, + [{getPageInfo, fun getPageInfo/1}]), + + case wxPrinter:print(Printer, Frame, Printout, [{prompt,true}]) of + false -> + case wxPrinter:getLastError() of + ?wxPRINTER_ERROR -> + io:format("There was a problem printing.\n" + "Perhaps your current printer is not set correctly?~n", []); + _ -> + io:format("You canceled printing~n", []) + end, + wxPrinter:destroy(Printer), + S; + true -> + PDD2 = wxPrinter:getPrintDialogData(Printer), + PD2 = wxPrintDialogData:getPrintData(PDD2), + %% Copy data PD2 will be deleted when Printer is destroyed + PD3 = wxPrintData:new(PD2), + wxPrintData:destroy(PD), + wxPrinter:destroy(Printer), + S#gs{print_d = PD3} + end; + +dialog(Other, S) -> + io:format("other ~p~n",[Other]), + S. + +init_printer(S) -> + PD = wxPrintData:new(), + + %% You could set an initial paper size here + %% g_printData->SetPaperId(wxPAPER_LETTER); // for Americans + %% g_printData->SetPaperId(wxPAPER_A4); // for everyone else + + PSDD = wxPageSetupDialogData:new(PD), + wxPageSetupDialogData:setMarginTopLeft(PSDD,{15,15}), + wxPageSetupDialogData:setMarginBottomRight(PSDD,{15,15}), + + S#gs{print_d=PD, print_psdd=PSDD}. + +getPageInfo(_This) -> + {1,1,1,1}. + +printout(This, _Page, #gs{board=Board, print_psdd=PsDD}) -> + MX = MY = 500, + wxPrintout:fitThisSizeToPageMargins(This, {MX,MY}, PsDD), + + _DBG = {_X,_Y,W,H} = wxPrintout:getLogicalPageMarginsRect(This, PsDD), + wxPrintout:offsetLogicalOrigin(This,(W-MX) div 2, (H-MY) div 2), +%% io:format("~p ->{~p,~p} ~n", [_DBG, (W-MX) div 2, (H-MY) div 2]), + + DC = wxPrintout:getDC(This), + sudoku_board:draw(Board, DC, {500,500}), + true. + +set_val(Id, Val, Board, G) -> + sudoku_board:set_butt(Board, Id,Val), + G ! {validate, Id, Val}, + ok. + + + diff --git a/lib/wx/examples/xrc/Makefile b/lib/wx/examples/xrc/Makefile new file mode 100755 index 0000000000..1dfaae9689 --- /dev/null +++ b/lib/wx/examples/xrc/Makefile @@ -0,0 +1,76 @@ +# +# %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 = ../.. +EBIN = . +ERLINC = $(TOPDIR)/include +ERLC = erlc +TESTMODS = xrc +TESTTARGETS = $(TESTMODS:%=%.beam) +TESTSRC = $(TESTMODS:%=%.erl) + +RESOURCEFILES = appicon.ico basicdlg.xpm custclas.xpm fileopen.gif menu.xrc \ + resource.xrc uncenter.xpm variable.xrc appicon.xpm basicdlg.xrc \ + custclas.xrc filesave.gif platform.xpm stop.xpm uncenter.xrc \ + artprov.xpm controls.xpm derivdlg.xpm frame.xrc platform.xrc \ + throbber.gif update.gif artprov.xrc controls.xrc derivdlg.xrc \ + fuzzy.gif quotes.gif toolbar.xrc variable.xpm + +TESTRESOURCE = $(RESOURCEFILES:%=rc/%) + +# Targets +opt debug: $(TESTTARGETS) +clean: + rm -f $(TESTTARGETS) + rm -f *~ core erl_crash.dump + +docs: + +run: opt + erl -smp -detached -pa $(TOPDIR)/ebin -s xrc + +ifneq ($(INSIDE_ERLSRC),true) + +%.beam: %.erl + $(ERLC) -W -I$(ERLINC) -bbeam -o$(BIN) $< + +else +EXRELSYSDIR = $(RELSYSDIR)/examples/xrc +include $(ERL_TOP)/make/otp_release_targets.mk + +docs: + +release_spec: + $(INSTALL_DIR) $(EXRELSYSDIR) + $(INSTALL_DATA) $(TESTSRC) $(EXRELSYSDIR) + $(INSTALL_DATA) $(TESTTARGETS) $(EXRELSYSDIR) + $(INSTALL_DIR) $(EXRELSYSDIR)/rc + $(INSTALL_DATA) $(TESTRESOURCE) $(EXRELSYSDIR)/rc + +release_tests_spec: + +release_docs_spec: + +endif + + + diff --git a/lib/wx/examples/xrc/rc/appicon.ico b/lib/wx/examples/xrc/rc/appicon.ico Binary files differnew file mode 100644 index 0000000000..f3ef7918d2 --- /dev/null +++ b/lib/wx/examples/xrc/rc/appicon.ico diff --git a/lib/wx/examples/xrc/rc/appicon.xpm b/lib/wx/examples/xrc/rc/appicon.xpm new file mode 100644 index 0000000000..7c61a99318 --- /dev/null +++ b/lib/wx/examples/xrc/rc/appicon.xpm @@ -0,0 +1,52 @@ +/* XPM */ +static char * appicon_xpm[] = { +"32 32 17 1", +" c None", +". c #000000", +"+ c #800000", +"@ c #008000", +"# c #808000", +"$ c #000080", +"% c #800080", +"& c #008080", +"* c #C0C0C0", +"= c #808080", +"- c #FF0000", +"; c #00FF00", +"> c #FFFF00", +", c #0000FF", +"' c #FF00FF", +") c #00FFFF", +"! c #FFFFFF", +" ", +"===============================.", +"=*****************************=.", +"=*$$$$$$$$$$$$$$$$$$$$$$$$$$$$=.", +"=*$$$$$$$$$$$$$$$$$$$**.**.**.=.", +"=*$$$$$$$$$$$$$$$$$$$**.**.**.=.", +"=*$$$$$$$$$$$$$$$$$$$.........=.", +"=*****************************=.", +"=*=============================.", +"=*=!!!!!!!!!!!!!!!!!!!!!!!!!!*=.", +"=*=!!!!!!!!!!!!!!!!!!!!!!!!!!*=.", +"=*=!!!!!!!!!!!!!!!!!!!!!!!!!!*=.", +"=*=!!!!!!!,!!!!!!!!!!!,!!!!!!*=.", +"=*=!!!!!!,,!!!!!!!!!!!,,!!!!!*=.", +"=*=!!!!!,,!!!!!!!!!!!!!,,!!!!*=.", +"=*=!!!!,,!!...........!!,,!!!*=.", +"=*=!!!,,!!!.$$$$$$!!!.!!!,,!!*=.", +"=*=!!,,!!!!.$$$$$$!!!.!!!!,,!*=.", +"=*=!!,,!!!!.$$$$$$!!!.!!!!,,!*=.", +"=*=!!!,,!!!.$$$$$$!!!.!!!,,!!*=.", +"=*=!!!!,,!!...........!!,,!!!*=.", +"=*=!!!!!,,!!!!!!!!!!!!!,,!!!!*=.", +"=*=!!!!!!,,!!!!!!!!!!!,,!!!!!*=.", +"=*=!!!!!!!,!!!!!!!!!!!,!!!!!!*=.", +"=*=!!!!!!!!!!!!!!!!!!!!!!!!!!*=.", +"=*=!!!!!!!!!!!!!!!!!!!!!!!!!!*=.", +"=*=!!!!!!!!!!!!!!!!!!!!!!!!!!*=.", +"=*****************************=.", +"===============================.", +"................................", +" ", +" "}; diff --git a/lib/wx/examples/xrc/rc/artprov.xpm b/lib/wx/examples/xrc/rc/artprov.xpm new file mode 100644 index 0000000000..55e204881b --- /dev/null +++ b/lib/wx/examples/xrc/rc/artprov.xpm @@ -0,0 +1,23 @@ +/* XPM */ +static char * artprov_xpm[] = { +"16 16 4 1", +" c None", +". c #000000", +"+ c #0E2CEF", +"@ c #FFFFFF", +" . ", +" . . ", +" . . ", +"++++++++++++++++", +"+@@@@@@@@@@@@@@+", +"+@@@@@@++@@@@@@+", +"+@@@@@@@@@@@@@@+", +"+@@@@@+++@@@@@@+", +"+@@@@@@++@@@@@@+", +"+@@@@@@++@@@@@@+", +"+@@@@@@++@@@@@@+", +"+@@@@@++++@@@@@+", +"+@@@@@@@@@@@@@@+", +"++++++++++++++++", +" ", +" "}; diff --git a/lib/wx/examples/xrc/rc/artprov.xrc b/lib/wx/examples/xrc/rc/artprov.xrc new file mode 100644 index 0000000000..2256b73ebf --- /dev/null +++ b/lib/wx/examples/xrc/rc/artprov.xrc @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> + +<resource xmlns="http://www.wxwidgets.org/wxxrc" version="2.3.0.1"> + +<object class="wxDialog" name="art_provider_dialog"> + <title>wxArtProvider Example</title> + <centered>1</centered> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxGROW|wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxTextCtrl" name="message_textctrl"> + <size>500,150</size> + <style>wxTE_MULTILINE</style> + <value>You can specify wxArtProvider icons in your XRC resources. These icons will be retrieved from the active wxArtProvider (see wxArtProvider in docs and /samples/artprov for more information on wxArtProvider).\n\nThe most common usage for this is that you want a dialog, toolbar or menu item to have the correct platform-specific icon in your interface, such as a custom "Don't show this again" checkbox message dialog that has the appropriate icon, as shown below.\n\nYou can also use it to manage your own custom bitmaps though, too--instead of having to write multiple versions of an XRC file that only differ in their bitmaps, you can instead just write one XRC file with the bitmap to be retrieved from the wxArtProvider at runtime, having your custom wxArtProvider use some code to serve out the desired bitmap based on such things as a wxConfig n entry of a desired icon set, what OS the application is running on, what size or resolution the display is, and so on.\n\nNote that your application's custom bitmaps are the only thing that will differ between OS's in order to ensure proper Look And Feel, as everything else: windows decoration, colors, fonts, widgets, etc already match perfectly since wxWindows runs natively.\n\nTo use a wxArtProvider bitmap instead of usual bitmap, in your XRC, instead of <bitmap>somefile.png</bitmap>, use <bitmap stock__id="SOME__ART__ID" client="SOME__CLIENT__ID">somefile.png</bitmap>. The stock__id parameter is required for a bitmap to be read from wxArtProvider, stock__client is optional. The image filename is also optional, and is just used as a fallback in case the wxArtProvider couldn't return a bitmap for that particular stock__id (and particular stock__client if your wxArtProvider is set up to also filter stock__client).</value> + </object> + </object> + <object class="sizeritem"> + <flag>wxGROW|wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxFlexGridSizer"> + <cols>2</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>1</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxStaticBitmap" name="my_bitmap"> + <bitmap stock_id="wxART_INFORMATION" stock_client="wxART_MESSAGE_BOX">derivdlg.xpm</bitmap> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="message_statictext"> + <label>Your web connection is optimized perfectly.</label> + </object> + </object> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxCheckBox" name="dont_show_checkbox"> + <label>Don't show this message again</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxButton" name="wxID_OK"> + <label>OK</label> + </object> + </object> + </object> +</object> + +</resource> diff --git a/lib/wx/examples/xrc/rc/basicdlg.xpm b/lib/wx/examples/xrc/rc/basicdlg.xpm new file mode 100644 index 0000000000..19054822ba --- /dev/null +++ b/lib/wx/examples/xrc/rc/basicdlg.xpm @@ -0,0 +1,24 @@ +/* XPM */ +static char * basicdlg_xpm[] = { +"16 16 5 1", +" c None", +". c #000000", +"+ c #808080", +"@ c #0000FF", +"# c #FFFFFF", +" ", +"................", +".++++++++++++++.", +".+@@@@@@@@@@@@+.", +".++++++++++++++.", +".+############+.", +".+############+.", +".+############+.", +".+############+.", +".+############+.", +".+############+.", +".+############+.", +".+############+.", +".++++++++++++++.", +"................", +" "}; diff --git a/lib/wx/examples/xrc/rc/basicdlg.xrc b/lib/wx/examples/xrc/rc/basicdlg.xrc new file mode 100644 index 0000000000..ae632f6e10 --- /dev/null +++ b/lib/wx/examples/xrc/rc/basicdlg.xrc @@ -0,0 +1,44 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> + +<resource xmlns="http://www.wxwidgets.org/wxxrc" version="2.3.0.1"> + +<object class="wxDialog" name="non_derived_dialog"> + <title>Non-Derived Dialog Example</title> + <centered>1</centered> + <object class="wxBoxSizer"> + <orient>wxVERTICAL</orient> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxGROW|wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxTextCtrl" name="message_textctrl"> + <size>500,150</size> + <style>wxTE_MULTILINE</style> + <value>This is the basic non-derived XRC dialog. It is just an instance of wxDialog, not a instance of a class derived from wxDialog that was given some added functionality.\n\nYou can put whatever controls you want on these non-derived dialogs, but the dialog won't interact with the controls, nor do anything in response to any of their events. It only has the built-in functionality of a wxDialog, and that is it. A non-derived dialog can automatically close itself when you hit either the OK or Cancel button (returning a return code of what button you pressed), and not much else.\n\nThese are useful for an About dialog, or a message dialog popup, but that's about it. For the rest you will almost certainly use a derived dialog (see next example).</value> + </object> + </object> + <object class="sizeritem"> + <flag>wxEXPAND|wxALL</flag> + <border>5</border> + <object class="wxStdDialogButtonSizer"> + <object class="button"> + <object class="wxButton" name="wxID_OK"> + <label>OK</label> + </object> + </object> + <object class="button"> + <object class="wxButton" name="wxID_CANCEL"> + <label>Cancel</label> + </object> + </object> + </object> + </object> + </object> +</object> + +</resource> diff --git a/lib/wx/examples/xrc/rc/controls.xpm b/lib/wx/examples/xrc/rc/controls.xpm new file mode 100644 index 0000000000..2bbdd34857 --- /dev/null +++ b/lib/wx/examples/xrc/rc/controls.xpm @@ -0,0 +1,25 @@ +/* XPM */ +static char * controls_xpm[] = { +"16 16 6 1", +" c None", +". c #000000", +"+ c #808080", +"@ c #0000FF", +"# c #FFFFFF", +"$ c #0E2CEF", +" ", +" ", +" ", +" ", +" ", +"................", +".++++++++++++++.", +".+@@@@@@@@####+.", +".+$$$$$$$$####+.", +".+$$$$$$$$####+.", +".++++++++++++++.", +"................", +" ", +" ", +" ", +" "}; diff --git a/lib/wx/examples/xrc/rc/controls.xrc b/lib/wx/examples/xrc/rc/controls.xrc new file mode 100644 index 0000000000..77d5daac3e --- /dev/null +++ b/lib/wx/examples/xrc/rc/controls.xrc @@ -0,0 +1,1243 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> + +<!-- $Id: controls.xrc 43684 2006-11-27 15:02:49Z VZ $ --> + +<resource xmlns="http://www.wxwidgets.org/wxxrc" version="2.3.0.1"> + +<object class="wxDialog" name="controls_dialog"> + <title>Controls Example</title> + <style>wxCAPTION|wxSYSTEM_MENU|wxRESIZE_BORDER</style> + <exstyle>wxDIALOG_EX_CONTEXTHELP</exstyle> + <centered>1</centered> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxGROW|wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxNotebook" name="controls_notebook"> + <usenotebooksizer>1</usenotebooksizer> + <size>550,250</size> + <object class="notebookpage"> + <label>wxTreebook</label> + <object class="wxTreebook" name="controls_treebook"> + <size>350,280</size> + <style>wxSUNKEN_BORDER</style> + <object class="treebookpage"> + <label>Page 1</label> + <depth>0</depth> + <object class="wxButton" name="controls_treebook_button1"> + <size>200,180</size> + <label>Button N1</label> + </object> + </object> + <object class="treebookpage"> + <label>Empty Page 2</label> + <depth>1</depth> + </object> + <object class="treebookpage"> + <label>Page 3</label> + <depth>2</depth> + <object class="wxButton" name="controls_treebook_button3"> + <size>200,180</size> + <label>Button N3</label> + </object> + </object> + <object class="treebookpage"> + <label>Page 4</label> + <depth>1</depth> + <object class="wxButton" name="controls_treebook_button4"> + <size>200,180</size> + <label>Button N4</label> + </object> + </object> + </object> + </object> + <object class="notebookpage"> + <label>wxToolBar</label> + <object class="wxPanel" name="button"> + <object class="wxFlexGridSizer"> + <cols>2</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0,1</growablecols> + <growablerows>0,1</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="controls_normal_button"> + <label>Transparent background:</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <size>300,60</size> + <object class="wxToolBar"> + <style>wxTB_FLAT|wxTB_NODIVIDER</style> + <margins>2,2</margins> + <object class="tool" name="non_derived_dialog_tool_or_menuitem"> + <tooltip>Non-Derived Dialog Example</tooltip> + <bitmap>basicdlg.xpm</bitmap> + <longhelp>The basic instance of wxDialog loaded via XRC</longhelp> + </object> + <object class="tool" name="derived_tool_or_menuitem"> + <tooltip>Derived Dialog Example</tooltip> + <bitmap>derivdlg.xpm</bitmap> + <longhelp>The most important example: load an XRC for a derived dialog</longhelp> + </object> + <object class="tool" name="controls_tool_or_menuitem"> + <tooltip>Controls Example</tooltip> + <bitmap>controls.xpm</bitmap> + <longhelp>A notebook displaying all the wxWidgets controls</longhelp> + </object> + <object class="tool" name="uncentered_tool_or_menuitem"> + <tooltip>Uncentered Example</tooltip> + <bitmap>uncenter.xpm</bitmap> + <longhelp>Disable autocentering of a dialog on its parent</longhelp> + </object> + <separator/> + <object class="tool" name="custom_class_tool_or_menuitem"> + <tooltip>Custom Class Example</tooltip> + <bitmap>custclas.xpm</bitmap> + <longhelp>Embed your own custom classes into an XRC</longhelp> + </object> + <object class="tool" name="platform_property_tool_or_menuitem"> + <tooltip>Platform Specific Example</tooltip> + <bitmap>platform.xpm</bitmap> + <longhelp>Customize parts of an interface for a desired platform</longhelp> + </object> + <object class="tool" name="art_provider_tool_or_menuitem"> + <tooltip>wxArtProvider Example</tooltip> + <bitmap>artprov.xpm</bitmap> + <longhelp>Use wxArtProvider to insert desired icons at runtime</longhelp> + </object> + <object class="tool" name="variable_expansion_tool_or_menuitem"> + <tooltip>Variable Expansion Example</tooltip> + <bitmap>variable.xpm</bitmap> + <longhelp>Replace variables in the XRC file at runtime</longhelp> + </object> + <object class="wxComboBox"> + <content> + <item>Just</item> + <item>a combobox</item> + <item>in the toolbar</item> + </content> + </object> + <object class="wxOwnerDrawnComboBox"> + <content> + <item>Owner Drawn</item> + <item>combobox</item> + <item>in the toolbar</item> + </content> + </object> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="controls_statictext2_button"> + <label>Fixed color background:</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxToolBar"> + <style>wxTB_FLAT|wxTB_NODIVIDER</style> + <bg>#bbbbff</bg> + <margins>2,2</margins> + <object class="tool" name="non_derived_dialog_tool_or_menuitem"> + <tooltip>Non-Derived Dialog Example</tooltip> + <bitmap>basicdlg.xpm</bitmap> + <longhelp>The basic instance of wxDialog loaded via XRC</longhelp> + </object> + <object class="tool" name="derived_tool_or_menuitem"> + <tooltip>Derived Dialog Example</tooltip> + <bitmap>derivdlg.xpm</bitmap> + <longhelp>The most important example: load an XRC for a derived dialog</longhelp> + </object> + <object class="tool" name="controls_tool_or_menuitem"> + <tooltip>Controls Example</tooltip> + <bitmap>controls.xpm</bitmap> + <longhelp>A notebook displaying all the wxWidgets controls</longhelp> + </object> + <object class="tool" name="uncentered_tool_or_menuitem"> + <tooltip>Uncentered Example</tooltip> + <bitmap>uncenter.xpm</bitmap> + <longhelp>Disable autocentering of a dialog on its parent</longhelp> + </object> + <separator/> + <object class="tool" name="custom_class_tool_or_menuitem"> + <tooltip>Custom Class Example</tooltip> + <bitmap>custclas.xpm</bitmap> + <longhelp>Embed your own custom classes into an XRC</longhelp> + </object> + <object class="tool" name="platform_property_tool_or_menuitem"> + <tooltip>Platform Specific Example</tooltip> + <bitmap>platform.xpm</bitmap> + <longhelp>Customize parts of an interface for a desired platform</longhelp> + </object> + <object class="tool" name="art_provider_tool_or_menuitem"> + <tooltip>wxArtProvider Example</tooltip> + <bitmap>artprov.xpm</bitmap> + <longhelp>Use wxArtProvider to insert desired icons at runtime</longhelp> + </object> + <object class="tool" name="variable_expansion_tool_or_menuitem"> + <tooltip>Variable Expansion Example</tooltip> + <bitmap>variable.xpm</bitmap> + <longhelp>Replace variables in the XRC file at runtime</longhelp> + </object> + <object class="wxComboBox"> + <content> + <item>Just</item> + <item>a combobox</item> + <item>in the toolbar</item> + </content> + </object> + <object class="wxOwnerDrawnComboBox"> + <content> + <item>Owner Drawn</item> + <item>combobox</item> + <item>in the toolbar</item> + </content> + </object> + </object> + </object> + </object> + </object> + </object> + + + <object class="notebookpage"> + <label>wxBitmapButton</label> + <object class="wxPanel" name="bitmapbutton"> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxBitmapButton" name="controls_bitmapbutton"> + <bitmap>controls.xpm</bitmap> + </object> + </object> + </object> + </object> + </object> + <object class="notebookpage"> + <label>wxButton</label> + <object class="wxPanel" name="button"> + <object class="wxFlexGridSizer"> + <cols>2</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0,1</growablecols> + <growablerows>0,1</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="controls_normal_button"> + <label>Normal button:</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxButton" name="controls_normal_button"> + <label>OK</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="controls_statictext2_button"> + <label>wxNO_BORDER style:</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxButton" name="controls_flat_button"> + <style>wxNO_BORDER</style> + <label>OK</label> + </object> + </object> + </object> + </object> + </object> + <object class="notebookpage"> + <label>wxCalendarControl</label> + <object class="wxPanel" name="calendar"> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxCalendarCtrl" name="controls_calendarctrl"> + <size>-1,-1</size> + </object> + </object> + </object> + </object> + </object> + <object class="notebookpage"> + <label>wxCheckBox</label> + <object class="wxPanel" name="checkbox"> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxCheckBox" name="controls_unchecked_checkbox"> + <label>Unchecked initially</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxCheckBox" name="controls_checked_checkbox"> + <label>Checked initially</label> + <checked>1</checked> + </object> + </object> + </object> + </object> + </object> + <object class="notebookpage"> + <label>wxCheckListBox</label> + <object class="wxPanel" name="checklist"> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxCheckListBox" name="conrols_checklist"> + <size>180,180</size> + <content> + <item checked="1">Download library</item> + <item checked="1">Compile samples</item> + <item checked="1">Skim docs</item> + <item checked="1">Finish project</item> + <item>Wash car</item> + </content> + </object> + </object> + </object> + </object> + </object> + + <object class="notebookpage"> + <label>wxChoice</label> + <object class="wxPanel" name="choice"> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxChoice" name="controls_choice"> + <size>180,-1</size> + <content> + <item>See</item> + <item>Hear</item> + <item>Feel</item> + <item>Smell</item> + <item>Taste</item> + <item>The Sixth Sense!</item> + </content> + </object> + </object> + </object> + </object> + </object> + <object class="notebookpage"> + <label>wxComboBox</label> + <object class="wxPanel" name="combobox"> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxComboBox" name="controls_combobox"> + <size>200,-1</size> + <style>wxCB_DROPDOWN</style> + <selection>4</selection> + <content> + <item>vim</item> + <item>emacs</item> + <item>notepad.exe</item> + <item>bbedit</item> + <item>nedit</item> + </content> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_TOP|wxALIGN_CENTRE_HORIZONTAL|wxALL</flag> + <border>5</border> + <object class="wxBitmapComboBox"> + <size>200,-1</size> + <style>wxCB_READONLY</style> + <selection>2</selection> + <object class="ownerdrawnitem"> + <text>This is a</text> + <bitmap>basicdlg.xpm</bitmap> + </object> + <object class="ownerdrawnitem"> + <text>read-only</text> + <bitmap>derivdlg.xpm</bitmap> + </object> + <object class="ownerdrawnitem"> + <text>wxBitmapComboBox</text> + <bitmap>uncenter.xpm</bitmap> + </object> + <object class="ownerdrawnitem"> + <text>control</text> + <bitmap>custclas.xpm</bitmap> + </object> + </object> + </object> + </object> + </object> + </object> + <object class="notebookpage"> + <label>wxGauge</label> + <object class="wxPanel" name="gauge"> + <object class="wxFlexGridSizer"> + <cols>2</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0,1</growablecols> + <growablerows>0,1</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="controls_guage1_statictext"> + <label>Horizontal smooth:</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxGauge" name="controls_horizontal_gauge"> + <style>wxGA_SMOOTH</style> + <size>100,-1</size> + <max>100</max> + <value>50</value> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="controls_gauge2_statictext"> + <label>Vertical: custom width</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxGauge" name="controls_vertical_gauge"> + <style>wxGA_VERTICAL</style> + <size>40,60</size> + <max>100</max> + <value>40</value> + </object> + </object> + </object> + </object> + </object> + <object class="notebookpage"> + <label>wxGenericDirCtrl</label> + <object class="wxPanel" name="genericdirctrl"> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxGenericDirCtrl" name="controls_genericdirctrl"> + <size>200,200</size> + </object> + </object> + </object> + </object> + </object> + <object class="notebookpage"> + <label>wxHtmlWindow</label> + <object class="wxPanel" name="htmlwindow"> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxGROW|wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxHtmlWindow" name="controls_htmlwindow"> + <size>450,250</size> + <htmlcode> + <h2>XRC Resources HTML</h2> + <p><font color="#0000FF">XRC=Blue skies ahead.</font> + <p>Italics useful for quoted or emphasized text:<i>"Some see things as they are and say why. + I dream things that never were, and say why not"</i> + <p><pre>Fixed width for code snippets.</pre> + <p>Horizontal rules to organize sections: <hr> + <p>A wxImage is worth a thousand words and can be also used. + </htmlcode> + </object> + </object> + </object> + </object> + </object> + <object class="notebookpage"> + <label>wxListBox</label> + <object class="wxPanel" name="listbox"> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_CENTER|wxALL</flag> + <border>5</border> + <object class="wxListBox" name="controls_listbox"> + <size>250,160</size> + <style>wxLB_SINGLE</style> + <content> + <item>Milk</item> + <item>Pizza</item> + <item>Bread</item> + <item>Orange juice</item> + <item>Paper towels</item> + </content> + </object> + </object> + </object> + </object> + </object> + <object class="notebookpage"> + <label>wxSimpleHtmlListBox</label> + <object class="wxPanel" name="simplehtmllistbox"> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_CENTER|wxALL</flag> + <border>5</border> + <object class="wxSimpleHtmlListBox" name="controls_simplehtmllistbox"> + <size>250,160</size> + <style>wxHLB_MULTIPLE|wxHLB_DEFAULT_STYLE</style> + <content> + <item><b>Bold</b> Milk</item> + <item><i>Rainbow <font color="red">P</font><font color="blue">i</font><font color="yellow">z</font><font color="green">z</font><font color="purple">a</font></i></item> + <item><tt>Plain bread</tt></item> + <item><font color="orange" size="+1">Orange juice</font></item> + <item>Paper towels</item> + </content> + </object> + </object> + </object> + </object> + </object> + <object class="notebookpage"> + <label>wxListCtrl</label> + <object class="wxPanel" name="listctrl"> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_CENTER|wxALL</flag> + <border>5</border> + <object class="wxListCtrl" name="controls_listctrl"> + <size>220,160</size> + <style>wxLC_REPORT|wxSUNKEN_BORDER</style> + </object> + </object> + </object> + </object> + </object> + <object class="notebookpage"> + <label>wxPanel</label> + <object class="wxPanel" name="panel"> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxPanel" name="controls_panel"> + <size>200,160</size> + <bg>#0000FF</bg> + </object> + </object> + </object> + </object> + </object> + <object class="notebookpage"> + <label>wxSplitterWindow</label> + <object class="wxPanel" name="panel"> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxSplitterWindow"> + <minsize>50</minsize> + <sashpos>100</sashpos> + <size>400,200</size> + <object class="wxPanel" name="controls_panel"> + <bg>#0000FF</bg> + </object> + <object class="wxPanel" name="controls_panel"> + <bg>#00FF00</bg> + </object> + </object> + </object> + </object> + </object> + </object> + <object class="notebookpage"> + <label>wxRadioButton</label> + <object class="wxPanel" name="radiobutton"> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxRadioButton" name="controls_unselected_radiobutton"> + <label>Not selected</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxRadioButton" name="controls_selected_radiobutton"> + <label>Selected</label> + <value>1</value> + </object> + </object> + </object> + </object> + </object> + <object class="notebookpage"> + <label>wxRadioBox</label> + <object class="wxPanel" name="radiobox"> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxRadioBox" name="controls_radiobox"> + <style>wxRA_SPECIFY_COLS</style> + <label>Radio stations</label> + <dimension>1</dimension> + <selection>0</selection> + <content> + <item tooltip="Powerful radio station" helptext="This station is for amateurs of hard rock and heavy metal">Power 108</item> + <item tooltip="">WMMS 100.7</item> + <item tooltip="E=mc^2">Energy 98.3</item> + <item helptext="Favourite chukcha's radio">CHUM FM</item> + <item>92FM</item> + </content> + </object> + </object> + </object> + </object> + </object> + <object class="notebookpage"> + <label>wxScrollBar</label> + <object class="wxPanel" name="scrollbar"> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxScrollBar" name="controls_scrollbar"> + <size>-1,160</size> + <value>50</value> + <range>100</range> + <thumbsize>30</thumbsize> + <style>wxSB_VERTICAL</style> + </object> + </object> + </object> + </object> + </object> + <object class="notebookpage"> + <label>wxSlider</label> + <object class="wxPanel" name="slider"> + <object class="wxFlexGridSizer"> + <cols>2</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0,1</growablecols> + <growablerows>0,1</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="controls_slider1_statictext"> + <label>Without ticks:</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxSlider" name="controls_noticks_slider"> + <size>100,-1</size> + <style>wxSL_HORIZONTAL</style> + <max>100</max> + <value>0</value> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="controls_slider2_statictext"> + <label>With ticks:</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxSlider" name="controls_ticks_slider"> + <size>100,-1</size> + <style>wxSL_HORIZONTAL|wxSL_LABELS</style> + <max>100</max> + <value>0</value> + </object> + </object> + </object> + </object> + </object> + <object class="notebookpage"> + <label>wxSpinButton</label> + <object class="wxPanel" name="spinbutton"> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxSpinButton" name="controls_spinbutton"> + <style>wxSP_WRAP</style> + <max>100</max> + <value>0</value> + </object> + </object> + </object> + </object> + </object> + <object class="notebookpage"> + <label>wxSpinCtrl</label> + <object class="wxPanel" name="spinctrl"> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxSpinCtrl" name="controls_spinctrl"> + <size>100,-1</size> + <max>100</max> + <value>0</value> + </object> + </object> + </object> + </object> + </object> + <object class="notebookpage"> + <label>wxStaticBitmap</label> + <object class="wxPanel" name="staticbitmap"> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxStaticBitmap" name="controls_staticbitmap"> + <bitmap>appicon.xpm</bitmap> + </object> + </object> + </object> + </object> + </object> + <object class="notebookpage"> + <label>wxStaticBox</label> + <object class="wxPanel" name="staticbox"> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxGROW|wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxStaticBoxSizer"> + <orient>wxVERTICAL</orient> + <label>Internet options</label> + </object> + </object> + </object> + </object> + </object> + <object class="notebookpage"> + <label>wxStaticLine</label> + <object class="wxPanel" name="staticline"> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0,1</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxStaticLine" name="controls_v_staticline"> + <size>-1,100</size> + <style>wxLI_VERTICAL</style> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxStaticLine" name="controls_h_staticline"> + <size>150,-1</size> + <style>wxLI_HORIZONTAL</style> + </object> + </object> + </object> + </object> + </object> + <object class="notebookpage"> + <label>wxStaticText</label> + <object class="wxPanel" name="statictext"> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="controls_statictext"> + <label>It was a dark and stormy night.</label> + </object> + </object> + </object> + </object> + </object> + <object class="notebookpage"> + <label>wxTextCtrl</label> + <object class="wxPanel" name="textctrl"> + <object class="wxFlexGridSizer"> + <cols>2</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0,1</growablecols> + <growablerows>0,1,2</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="controls_textctrl1_statictext"> + <label>Single line:</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxTextCtrl" name="controls_single_textctrl"> + <size>180,-1</size> + <value>A.A. Milne</value> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="controls_textctrl2_statictext"> + <label>Password:</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxTextCtrl" name="controls_password_textctrl"> + <size>180,-1</size> + <style>wxTE_PASSWORD</style> + <value>TooManySecrets</value> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="controls_textctrl3_statictext"> + <label>Multiline:</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxTextCtrl" name="controls_multiline_textctrl"> + <size>180,90</size> + <style>wxTE_MULTILINE</style> + <value>"So many pretty widgets" said Pooh, said he. "So many pretty widgets", said Pooh.</value> + </object> + </object> + </object> + </object> + </object> + <object class="notebookpage"> + <label>wxTreeCtrl</label> + <object class="wxPanel" name="treectrl"> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxTreeCtrl" name="controls_treectrl"> + <size>280,180</size> + <style>wxTR_HAS_BUTTONS|wxSUNKEN_BORDER</style> + </object> + </object> + </object> + </object> + </object> + + <object class="notebookpage"> + <label>wx*PickerCtrl</label> + <object class="wxPanel" name="pickers"> + <object class="wxFlexGridSizer"> + <cols>2</cols> + <rows>0</rows> + <vgap>10</vgap> + <hgap>10</hgap> + <growablecols>0,1</growablecols> + <growablerows>0,1,2,3</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="controls_pickers_statictext"> + <label>wxColourPickerCtrl:</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxGROW|wxALL</flag> + <option>1</option> + <border>5</border> + <object class="wxColourPickerCtrl" name="controls_colourpicker"> + <value>#00ff00</value> + <style>wxCLRP_SHOW_LABEL</style> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="controls_pickers_statictext2"> + <label>wxFilePickerCtrl:</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxGROW|wxALL</flag> + <option>1</option> + <border>5</border> + <object class="wxFilePickerCtrl" name="controls_filepicker"> + <message>Here goes a message</message> + <style>wxFLP_OPEN</style> + <wildcard>*.png</wildcard> + <value/> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="controls_pickers_statictext3"> + <label>wxDirPickerCtrl:</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxGROW|wxALL</flag> + <option>1</option> + <border>5</border> + <object class="wxDirPickerCtrl" name="controls_dirpicker"> + <value/> + <style>wxDIRP_CHANGE_DIR</style> + <message>Here goes a message</message> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="controls_pickers_statictext4"> + <label>wxFontPickerCtrl:</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxGROW|wxALL</flag> + <option>1</option> + <border>5</border> + <object class="wxFontPickerCtrl" name="controls_fontpicker"> + <style>wxFNTP_USEFONT_FOR_LABEL</style> + <value> + <size>20</size> + <sysfont>wxSYS_DEFAULT_GUI_FONT</sysfont> + </value> + </object> + </object> + </object> + </object> + </object> + + <object class="notebookpage"> + <label>wxAnimationCtrl</label> + <object class="wxPanel" name="animctrl"> + <object class="wxFlexGridSizer"> + <cols>2</cols> + <rows>1</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0,1</growablecols> + <growablerows>0</growablerows> + + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxButton" name="controls_animation_button_play"> + <label>Play</label> + </object> + </object> + + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxAnimationCtrl" name="controls_animation_ctrl"> + <animation>throbber.gif</animation> + <inactive-bitmap>stop.xpm</inactive-bitmap> + </object> + </object> + + </object> + </object> + </object> + + <object class="notebookpage"> + <label>wxCollapsiblePane</label> + <object class="wxPanel" name="collpane"> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>1</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + + <object class="sizeritem"> + <flag>wxGROW|wxALL</flag> + <border>5</border> + <option>1</option> + <object class="wxCollapsiblePane" name="controls_collpane"> + <label>Details:</label> + <collapsed>0</collapsed> + <object class="panewindow"> + + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>1</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="controls_dialog_statictext"> + <label> +Inside a wxCollapsiblePane you can put everything you want and +lay them out using wxSizers, absolute positioning, everything you like! + </label> + </object> + </object> + </object> + + </object> + </object> + </object> + + </object> + </object> + </object> + + <object class="notebookpage"> + <label>The Rest</label> + <object class="wxPanel" name="Rest"> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0,1,2,3,4,5,6</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="controls_dialog_statictext"> + <label>wxDialog (This dialog is one)</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="controls_frame_statictext"> + <label>wxFrame (This application's main frame is one)</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="controls_menu_statictext"> + <label>wxMenu (This application's main frame uses one)</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="controls_notebook_statictextT"> + <label>wxNotebook (This dialog uses one)</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="controls_sizer"> + <label>wxSizer (Used throughout application)</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="controls_toolbar_statictext"> + <label>wxToolbar (This application's main frame uses one)</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="controls_unknown_statictext"> + <label>unknown controls (See Custom Class example)</label> + </object> + </object> + </object> + </object> + </object> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxButton" name="wxID_OK"> + <label>OK</label> + <default>1</default> + </object> + </object> + </object> +</object> + +</resource> diff --git a/lib/wx/examples/xrc/rc/custclas.xpm b/lib/wx/examples/xrc/rc/custclas.xpm new file mode 100644 index 0000000000..49e82d4587 --- /dev/null +++ b/lib/wx/examples/xrc/rc/custclas.xpm @@ -0,0 +1,26 @@ +/* XPM */ +static char * custclas_xpm[] = { +"16 16 7 1", +" c None", +". c #EBF70E", +"+ c #000000", +"@ c #808080", +"# c #0000FF", +"$ c #FFFFFF", +"% c #0E2CEF", +" ", +" . ", +" . ", +" . . . ", +" ... ", +"...+....++++++++", +"+@...@@@@@@@@@@+", +"+.#.#.####$$$$@+", +"+@%.%%%%%%$$$$@+", +"+@%.%%%%%%$$$$@+", +"+@@@@@@@@@@@@@@+", +"++++++++++++++++", +" ", +" ", +" ", +" "}; diff --git a/lib/wx/examples/xrc/rc/custclas.xrc b/lib/wx/examples/xrc/rc/custclas.xrc new file mode 100644 index 0000000000..4f0109a992 --- /dev/null +++ b/lib/wx/examples/xrc/rc/custclas.xrc @@ -0,0 +1,42 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> + +<resource xmlns="http://www.wxwidgets.org/wxxrc" version="2.3.0.1"> + +<object class="wxDialog" name="custom_class_dialog"> + <title>Custom Class Example</title> + <centered>1</centered> + <style>wxCAPTION|wxSYSTEM_MENU|wxRESIZE_BORDER</style> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxGROW|wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxTextCtrl" name="message_textctrl"> + <size>500,150</size> + <style>wxTE_MULTILINE</style> + <value>You can embed your own custom classes into an XRC file. This is referred to as attaching an unknown control.\n\nThere are 3 main cases when you would want to do this:\n\n(A) Most commonly: you have derived a class from one of the main wxWidgets controls, so that it can manage its own state and look after its own events, because it is better management to have a portable class with all the code for that control in there with the class, instead of being having many event handlers for that control scattered up in its parent dialog (which is allowed, but gets messy if a control has alot of methods). For example, if you require a wxListCtrl that popups a menu when right-clicked on an item, and you want the wxListCtrl to resize its columns in response to an OnSize(), and a few more methods, it makes better sourcecode logic to package all these methods into by a standalone derived wxListCtrl class, instead of having the parent dialog manage all these events and other functions. This is what the example below shows: it does a custom behaviour of resizing its first column to appropriately fill up the width of the control on a resize event, and it pops up a context-menu in response to a left click (and shades out popup menu item appropriately if there is no item currenty selected in the listctrl).\n\n(B)You have an utterly new widget that has no equivalent in the wxWindows class heirarchy, so you thus need to embed your class to get the needed functionality.\n\n(C) You are using one of the rarely used wxWindows controls that doesn't have an XRC handler in the XRC library. However, all of the major controls: wxButton, wxTextCtrl, etc have an XRC handler, so this is pretty rare, and you could always write your own XRC handler for that control if you wanted. You can choose the "Controls example" from the XRC demo menu to see all the controls that have an XRC handler.\n\nThe typical formula for attaching an unknown control is:\n\n(1) If you are deriving your own custom class to be embedded into the XRC, describe that class with its own .cpp and .h file. In this example it is custclass.cpp and custclass.h\n\n(2)Specify an "unknown" tag in the XRC file that you want to embed it into (see the unknown tag in custclass.xrc). This will be the placeholder of the new class.\n\n(3) Load the XRC dialog as usual, but before you show the dialog to the user, construct an instance of your custom control, and then use wxXmlResource::Get()->AttachUnknownControl() to put the custom class into its "unknown" placeholder in the XRC file.\n\nThe result is what you see below, a custom class control that fits in seemlessly with the whole dialog, the same as if it was read from XRC directly. Try out resizing this dialog, and watch the listctrl column resize, and right-click to call up its popup menu. By the way, if you look at the source of this XRC dialog, you will that this dialog node has a set of style flags that includes wxRESIZE__BORDER--that is why this dialog is resizable, whereas most of the rest of the dialogs in the XRC sample that don't include this tag, are not resizable.</value> + </object> + </object> + <object class="sizeritem"> + <flag>wxGROW|wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="unknown" name="custom_control_placeholder"> + <size>100,100</size> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxButton" name="wxID_OK"> + <label>OK</label> + </object> + </object> + </object> +</object> + +</resource> diff --git a/lib/wx/examples/xrc/rc/derivdlg.xpm b/lib/wx/examples/xrc/rc/derivdlg.xpm new file mode 100644 index 0000000000..ed1978b7f2 --- /dev/null +++ b/lib/wx/examples/xrc/rc/derivdlg.xpm @@ -0,0 +1,25 @@ +/* XPM */ +static char * derivdlg_xpm[] = { +"16 16 6 1", +" c None", +". c #EBF70E", +"+ c #000000", +"@ c #808080", +"# c #0000FF", +"$ c #FFFFFF", +" . ", +"+++.++++++++++++", +"+.@.@.@@@@@@@@@+", +"+@...#########@+", +"...@....@@@@@@@+", +"+@...$$$$$$$$$@+", +"+.$.@.@@@@@@$$@+", +"+@$.@@@@@@@@$$@+", +"+@$.$$$$$$$$$$@+", +"+@$$$$$$$$$$$$@+", +"+@$$$$@@@@$$$$@+", +"+@$$$$@@@@$$$$@+", +"+@$$$$$$$$$$$$@+", +"+@@@@@@@@@@@@@@+", +"++++++++++++++++", +" "}; diff --git a/lib/wx/examples/xrc/rc/derivdlg.xrc b/lib/wx/examples/xrc/rc/derivdlg.xrc new file mode 100644 index 0000000000..cb67b9ae87 --- /dev/null +++ b/lib/wx/examples/xrc/rc/derivdlg.xrc @@ -0,0 +1,78 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> + +<resource xmlns="http://www.wxwidgets.org/wxxrc" version="2.3.0.1"> + +<object class="wxDialog" name="derived_dialog"> + <title>Derived Dialog Example</title> + <centered>1</centered> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxGROW|wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxTextCtrl" name="message_textctrl"> + <size>500,150</size> + <style>wxTE_MULTILINE</style> + <value>This is a derived dialog using XRC. This type of derived dialog will likely be the heart of your project, and thus is the most important example in this demonstration.\n\nIt is recommended to open up derivdlg.cpp, derivdlg.h and derivdlg.xrc and follow along what is going on.\n\nThe steps to use a derived dialog are:\n\n(1) Derive your own dialog from wxDialog (derivdlg.cpp and derivdlg.h are an example).\n\n(2) In the source of the constructor of the derived dialog, load the XRC into the file, using the code as shown in the derivdlg.cpp\n\n(3)Add to the derived dilog's sourcecode some event handlers and other methods you want the dialog to do.\n\n(4)You can now just make an instance of the derived dialog and show it using ShowModal(), as is done in the MyFrame::OnDerivedDialogToolOrMenuCommand() method.\n\nThe remainder of this docuent will talk about how to use events with derived dialogs and XRC. There are 3 bits of an extra event functionality that this derived dialog can do, these will be described in turn:\n\n(A) Something to do when a user clicks on your custom button: This is straightforward. You name a control in the XRC file (in this example it is "my__button"). Then in the .cpp file, put an entry in the event table that will connect button clicks with that ID to a function that will be fired. The event table entry in the example is EVT__BUTTON( XRCID( "my__button" ), PreferencesDialog::OnMyButtonClicked ) This event table entry has 3 parts: The first part, EVT__BUTTON tells that you are describing a button click event. The final part, PreferencesDialog::OnMyButtonClicked() is what you want done in response to a button event. The middle part, XRCID( "my__button" ) is the restriction that only button events generated by a wxButton of that ID should trigger go on to do the function. This XRCID is the name of the wxButton in your XRC file. Now just describe, in the .h file and .cpp file, what you want your custom OnMyButtonClicked() function to do.\n\n(B) The second example is a very common requirement: that a checkbox or radiobutton disables some other control. The event table is set up the same as the "My Button" example above. However, it isn't an EVT__BUTTON event, it is an EVT__UPDATE__UI event: when the dialog does an updating of its UI (and thus fires this event) if the updating if of a control matching that XRCID, then it will do the specified function (which in this case looks at whether or not the checkbox is checked, and if it isn't checked, then disable the textctrl).\n\n(C) The last example shows how to handle the OK button. You will likely want to do something when the user presses OK, like save preferences or start some action (this example shows a simple case of just popping up a dialog and stopping a close). OK buttons are always named wxID__OK, so the XRC file should have it as wxID__OK also. The Event table has an EVT__BUTTON entry for wxID__OK (no XRCID though). Since this is a derived dialog with an event table, in response to an EVT__BUTTON event from a wxID__OK button, it will first look around in its own event table to see if there was any EVT__BUTTON entries, and since there is, it will do that one--if there wasn't it then checks out the base class's event table and sees if there was one there, and so on up the chain of inherited classes. Note that this is exactly what happens with the derived dialog's wxID__CANCEL button. You didn't put any EVT__BUTTON entries with an identifier of wxID__CANCEL, so after it scans your derived dialog's event table, it will then look at wxDialog's event table and see if there is one in that event table, and so on until it finds one. It will find a wxID__CANCEL handler, which will connect to the proper function (which causes the dialog to close). + </value> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxButton" name="my_button"> + <label>My Button</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxBoxSizer"> + <orient>wxHORIZONTAL</orient> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxCheckBox" name="my_checkbox"> + <label>Enable listbox</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxTextCtrl" name="my_textctrl"> + <size>80,-1</size> + <value></value> + </object> + </object> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxBoxSizer"> + <orient>wxHORIZONTAL</orient> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxButton" name="wxID_OK"> + <label>OK</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxButton" name="wxID_CANCEL"> + <label>Cancel</label> + </object> + </object> + </object> + </object> + </object> +</object> + +</resource> diff --git a/lib/wx/examples/xrc/rc/fileopen.gif b/lib/wx/examples/xrc/rc/fileopen.gif Binary files differnew file mode 100644 index 0000000000..bc51b401b9 --- /dev/null +++ b/lib/wx/examples/xrc/rc/fileopen.gif diff --git a/lib/wx/examples/xrc/rc/filesave.gif b/lib/wx/examples/xrc/rc/filesave.gif Binary files differnew file mode 100644 index 0000000000..6dd1fd98b5 --- /dev/null +++ b/lib/wx/examples/xrc/rc/filesave.gif diff --git a/lib/wx/examples/xrc/rc/frame.xrc b/lib/wx/examples/xrc/rc/frame.xrc new file mode 100644 index 0000000000..ad7b03f7d6 --- /dev/null +++ b/lib/wx/examples/xrc/rc/frame.xrc @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> + +<resource xmlns="http://www.wxwidgets.org/wxxrc" version="2.3.0.1"> + +<object class="wxFrame" name="main_frame"> + <title>XML Resources Demo</title> + <centered>1</centered> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxGROW|wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxTextCtrl" name="message_textctrl"> + <size>500,280</size> + <style>wxTE_MULTILINE</style> + <value>Welcome to the wxWidgets XmlResource (XRC) sample! Using wxWidgets XML resources makes your GUI C++ programming much faster and easier.\n\nView the examples under the "Basic" menu to learn how to get up and running with XRC quickly, and later have a look at the examples under the "Advanced" menu for advanced techniques.\n\nThe XML file that described this frame is the sample's frame.xrc file, with the menu in menu.xrc, and the toolbar in toolbar.xrc. The frame XRC file structure is exactly the same as the XRC files for the dialogs, except that the top level node is a wxFrame, not a wxDialog. Each of the other dialog in this example is a separate XRC file, each of which can be examined for how they work.</value> + </object> + </object> + </object> +</object> + +</resource> diff --git a/lib/wx/examples/xrc/rc/fuzzy.gif b/lib/wx/examples/xrc/rc/fuzzy.gif Binary files differnew file mode 100644 index 0000000000..b6296c5135 --- /dev/null +++ b/lib/wx/examples/xrc/rc/fuzzy.gif diff --git a/lib/wx/examples/xrc/rc/menu.xrc b/lib/wx/examples/xrc/rc/menu.xrc new file mode 100644 index 0000000000..91409e5c21 --- /dev/null +++ b/lib/wx/examples/xrc/rc/menu.xrc @@ -0,0 +1,84 @@ +<?xml version="1.0"?> + +<resource xmlns="http://www.wxwidgets.org/wxxrc" version="2.3.0.1"> + +<object class="wxMenuBar" name="main_menu"> +<style>wxMB_DOCKABLE</style> + <object class="wxMenu" name="file_tool_or_menuitem"> + <label>_File</label> + <style>wxMENU_TEAROFF</style> + <object class="wxMenuItem" name="unload_resource_menuitem"> + <label>_Unload resource\tCtrl-U</label> + <help>Unload basic dialog resource</help> + </object> + <object class="wxMenuItem" name="reload_resource_menuitem"> + <label>_Reload resource\tCtrl-R</label> + <help>Reload basic dialog resource</help> + </object> + + <!-- we use wxID_EXIT name here to get the default menu item stock icon --> + <object class="wxMenuItem" name="wxID_EXIT"> + <label>E_xit\tAlt-X</label> + <help>Exit this application</help> + </object> + </object> + <object class="wxMenu" name="basic_demos_menu"> + <label>_Basic</label> + <help>Basic techniques with XRC</help> + <object class="wxMenuItem" name="non_derived_dialog_tool_or_menuitem"> + <label>_Non-Derived Dialog Example</label> + <bitmap>basicdlg.xpm</bitmap> + <help>The basic instance of wxDialog loaded via XRC</help> + </object> + <object class="wxMenuItem" name="derived_tool_or_menuitem"> + <label>_Derived Dialog Example</label> + <bitmap>derivdlg.xpm</bitmap> + <help>The most important example: load an XRC for a derived dialog</help> + </object> + <object class="wxMenuItem" name="controls_tool_or_menuitem"> + <label>_Controls Example</label> + <bitmap>controls.xpm</bitmap> + <help>A notebook displaying all the wxWidgets controls</help> + </object> + <object class="wxMenuItem" name="uncentered_tool_or_menuitem"> + <label>_Uncentered Example</label> + <bitmap>uncenter.xpm</bitmap> + <help>Disable autocentering of a dialog on its parent</help> + </object> + </object> + <object class="wxMenu" name="advanced_demos_menu"> + <label>_Advanced</label> + <help>Advanced techniques with XRC</help> + <object class="wxMenuItem" name="custom_class_tool_or_menuitem"> + <label>_Custom Class Example</label> + <bitmap>custclas.xpm</bitmap> + <help>Embed your own custom classes into an XRC</help> + </object> + <object class="wxMenuItem" name="platform_property_tool_or_menuitem"> + <label>_Platform Specific Example</label> + <bitmap>platform.xpm</bitmap> + <help>Customize parts of an interface for a desired platform</help> + </object> + <object class="wxMenuItem" name="art_provider_tool_or_menuitem"> + <label>wx_ArtProvider Example</label> + <bitmap>artprov.xpm</bitmap> + <help>Use wxArtProvider to insert desired icons at runtime</help> + </object> + <object class="wxMenuItem" name="variable_expansion_tool_or_menuitem"> + <label>_Variable Expansion Example</label> + <bitmap>variable.xpm</bitmap> + <help>Replace variables in the XRC file at runtime</help> + </object> + </object> + <object class="wxMenu" name="help_menu"> + <label>_Help</label> + + <!-- we use wxID_ABOUT name here to get the default menu item stock icon --> + <object class="wxMenuItem" name="wxID_ABOUT"> + <label>_About...</label> + <help>About this application</help> + </object> + </object> +</object> + +</resource> diff --git a/lib/wx/examples/xrc/rc/platform.xpm b/lib/wx/examples/xrc/rc/platform.xpm new file mode 100644 index 0000000000..3737055fe7 --- /dev/null +++ b/lib/wx/examples/xrc/rc/platform.xpm @@ -0,0 +1,28 @@ +/* XPM */ +static char *platform_xpm[] = { +/* columns rows colors chars-per-pixel */ +"16 16 6 1", +". c Black", +"o c #FFFFFF", +"X c #000080", +"O c #FFFF00", +" c None", +"+ c #FF0000", +/* pixels */ +" ", +" ", +" ", +" ....... ", +" .XXXXX. ", +" .oXXXX. ", +" .oXXX.......", +".....oXXX.OOOOO.", +".+++.XXXX.oOOOO.", +".o++......oOOOO.", +".o++++. .oOOOO.", +".o++++. .OOOOO.", +".+++++. .......", +"....... ", +" ", +" " +}; diff --git a/lib/wx/examples/xrc/rc/platform.xrc b/lib/wx/examples/xrc/rc/platform.xrc new file mode 100644 index 0000000000..43313cb853 --- /dev/null +++ b/lib/wx/examples/xrc/rc/platform.xrc @@ -0,0 +1,145 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> + +<resource xmlns="http://www.wxwidgets.org/wxxrc" version="2.3.0.1"> + +<object class="wxDialog" name="platform_property_dialog"> + <title>Platform Property Example</title> + <centered>1</centered> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxGROW|wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxTextCtrl" name="message_textctrl"> + <size>500,150</size> + <style>wxTE_MULTILINE</style> + <value>You can specify certain nodes of an XRC file to only be used for a certain platform.\n\nTo do this, there is a "platform" property that can be placed in any node [ie inside an opening tag]. The value of the tag can be any combination of the following: mac, win, unix, or os2. Use a | symbol between multiple platforms, for example <label platform="win|mac">\n\nAt runtime, if there is a platform property in the tag, if it matches the current operating system, that node will be included, otherwise it won't.\n\nThe notebook example below shows how you can specify a high level node to only appear on a certain platform: the example here being a page of preferences that only make sense on a certain platform.\n\nThe second example shows how to replace a single attribute of a control: here the label of a download link. It is also very useful for specifying menu item accelerators keystrokes on the target platform.</value> + </object> + </object> + <object class="sizeritem"> + <flag>wxGROW|wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxNotebook" name="platform_notebook"> + <usenotebooksizer>1</usenotebooksizer> + <size>200,160</size> + <object class="notebookpage"> + <label>Shared options</label> + <object class="wxPanel" name="shared_tab"> + <object class="wxBoxSizer"> + <orient>wxVERTICAL</orient> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxCheckBox" name="shared_checkbox"> + <label>This preference is for all operating systems</label> + </object> + </object> + </object> + </object> + </object> + <object platform="mac" class="notebookpage"> + <label>Macintosh options</label> + <object class="wxPanel" name="mac_specific"> + <object class="wxBoxSizer"> + <orient>wxVERTICAL</orient> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxCheckBox" name="mac_checkbox"> + <label>Save output in iMovie compatible format</label> + </object> + </object> + </object> + </object> + </object> + <object platform="win" class="notebookpage"> + <label>Windows options</label> + <object class="wxPanel" name="win_specific"> + <object class="wxBoxSizer"> + <orient>wxVERTICAL</orient> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxCheckBox" name="win_checkbox"> + <label>Show application in icon tray instead of taskbar</label> + </object> + </object> + </object> + </object> + </object> + <object platform="unix" class="notebookpage"> + <label>Linux options</label> + <object class="wxPanel" name="unix_specific"> + <object class="wxBoxSizer"> + <orient>wxVERTICAL</orient> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxCheckBox" name="unix_checkbox"> + <label>Check my home directory for previous files</label> + </object> + </object> + </object> + </object> + </object> + <object platform="os2" class="notebookpage"> + <label>OS2 options</label> + <object class="wxPanel" name="os2_specific"> + <object class="wxBoxSizer"> + <orient>wxVERTICAL</orient> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxCheckBox" name="os2_checkbox"> + <label>Use WarpIn installer</label> + </object> + </object> + </object> + </object> + </object> + </object> + </object> + <object platform="mac" class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="download_mac_statictext"> + <label>Get latest update at www.mycompany.com/download/mac</label> + </object> + </object> + <object platform="win" class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="download_win_statictext"> + <label>Get latest update at www.mycompany.com/download/win</label> + </object> + </object> + <object platform="unix" class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="download_unix_statictext"> + <label>Get latest update at www.mycompany.com/download/unix</label> + </object> + </object> + <object platform="os2kurva" class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="download_os2_statictext"> + <label>Get latest update at www.mycompany.com/download/os2</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxButton" name="wxID_OK"> + <label>OK</label> + </object> + </object> + </object> +</object> + +</resource> diff --git a/lib/wx/examples/xrc/rc/quotes.gif b/lib/wx/examples/xrc/rc/quotes.gif Binary files differnew file mode 100644 index 0000000000..3ea61bde43 --- /dev/null +++ b/lib/wx/examples/xrc/rc/quotes.gif diff --git a/lib/wx/examples/xrc/rc/resource.xrc b/lib/wx/examples/xrc/rc/resource.xrc new file mode 100644 index 0000000000..6673e0e8f2 --- /dev/null +++ b/lib/wx/examples/xrc/rc/resource.xrc @@ -0,0 +1,154 @@ +<?xml version="1.0"?> +<resource xmlns="http://www.wxwidgets.org/wxxrc" version="2.3.0.1"> + <object class="wxMenuBar" name="mainmenu"> + <style>wxMB_DOCKABLE</style> + <object class="wxMenu" name="menu_file"> + <label>_File</label> + <style>wxMENU_TEAROFF</style> + <object class="wxMenuItem" name="menu_about"> + <label>_About...</label> + <bitmap>filesave.gif</bitmap> + </object> + <object class="separator"/> + <object class="wxMenuItem" name="menu_dlg1"> + <label>Dialog 1</label> + </object> + <object class="wxMenuItem" name="menu_dlg2"> + <label>Dialog 2</label> + </object> + <object class="separator"/> + <object class="wxMenuItem" name="menu_quit"> + <label>E_xit\tAlt-X</label> + </object> + </object> + </object> + <object class="wxToolBar" name="toolbar"> + <style>wxTB_FLAT|wxTB_DOCKABLE</style> + <margins>2,2</margins> + <object class="tool" name="menu_open"> + <bitmap>fileopen.gif</bitmap> + <tooltip>Open catalog</tooltip> + </object> + <object class="tool" name="menu_save"> + <bitmap>filesave.gif</bitmap> + <tooltip>Save catalog</tooltip> + </object> + <object class="tool" name="menu_update"> + <bitmap>update.gif</bitmap> + <tooltip>Update catalog - synchronize it with sources</tooltip> + </object> + <separator/> + <object class="tool" name="menu_quotes"> + <bitmap>quotes.gif</bitmap> + <toggle>1</toggle> + <tooltip>Display quotes around the string?</tooltip> + </object> + <object class="separator"/> + <object class="tool" name="menu_fuzzy"> + <bitmap>fuzzy.gif</bitmap> + <tooltip>Toggled if selected string is fuzzy translation</tooltip> + <toggle>1</toggle> + </object> + </object> + <object class="wxDialog" name="dlg1"> + <object class="wxBoxSizer"> + <object class="sizeritem"> + <object class="wxBitmapButton"> + <bitmap>fuzzy.gif</bitmap> + <focus>fileopen.gif</focus> + </object> + </object> + <object class="sizeritem"> + <object class="wxPanel"> + <object class="wxStaticText"> + <label>fdgdfgdfgdfg</label> + </object> + <style>wxSUNKEN_BORDER</style> + </object> + <flag>wxALIGN_CENTER</flag> + </object> + <object class="sizeritem"> + <object class="wxButton"> + <label>Buttonek</label> + </object> + <border>10d</border> + <flag>wxALL</flag> + </object> + <object class="sizeritem"> + <object class="wxHtmlWindow"> + <htmlcode><h1>Hi,</h1>man</htmlcode> + <size>100,45d</size> + </object> + </object> + <object class="sizeritem"> + <object class="wxNotebook"> + <object class="notebookpage"> + <object class="wxPanel"> + <object class="wxBoxSizer"> + <object class="sizeritem"> + <object class="wxHtmlWindow"> + <htmlcode>Hello, we are inside a <u>NOTEBOOK</u>...</htmlcode> + <size>50,50d</size> + </object> + <option>1</option> + </object> + </object> + </object> + <label>Page</label> + </object> + <object class="notebookpage"> + <object class="wxPanel"> + <object class="wxBoxSizer"> + <object class="sizeritem"> + <object class="wxHtmlWindow"> + <htmlcode>Hello, we are inside a <u>NOTEBOOK</u>...</htmlcode> + <size>50,50d</size> + </object> + </object> + </object> + </object> + <label>Page 2</label> + </object> + <usenotebooksizer>1</usenotebooksizer> + </object> + <flag>wxEXPAND</flag> + </object> + <orient>wxVERTICAL</orient> + </object> + </object> + <object class="wxDialog" name="dlg2"> + <object class="wxBoxSizer"> + <orient>wxVERTICAL</orient> + <object class="sizeritem" name="dfgdfg"> + <object class="wxTextCtrl"> + <size>200,200d</size> + <style>wxTE_MULTILINE|wxSUNKEN_BORDER</style> + <value>Hello, this is an ordinary multiline\n textctrl....</value> + </object> + <option>1</option> + <flag>wxEXPAND|wxALL</flag> + <border>10</border> + </object> + <object class="sizeritem"> + <object class="wxBoxSizer"> + <object class="sizeritem"> + <object class="wxButton" name="wxID_OK"> + <label>Ok</label> + <default>1</default> + </object> + </object> + <object class="sizeritem"> + <object class="wxButton" name="wxID_CANCEL"> + <label>Cancel</label> + </object> + <border>10</border> + <flag>wxLEFT</flag> + </object> + </object> + <flag>wxLEFT|wxRIGHT|wxBOTTOM|wxALIGN_RIGHT</flag> + <border>10</border> + </object> + </object> + <title>Second testing dialog</title> + </object> +</resource> diff --git a/lib/wx/examples/xrc/rc/stop.xpm b/lib/wx/examples/xrc/rc/stop.xpm new file mode 100644 index 0000000000..7c26312696 --- /dev/null +++ b/lib/wx/examples/xrc/rc/stop.xpm @@ -0,0 +1,164 @@ +/* XPM */ +static char * stop_xpm[] = { +"32 32 129 2", +" c None", +". c #C9CBC8", +"+ c #C3C4C1", +"@ c #C4C6C3", +"# c #C1C3C0", +"$ c #C3C5C2", +"% c #C3C3C0", +"& c #C4C4C1", +"* c #C2C4C1", +"= c #C6C6C3", +"- c #C0C2BF", +"; c #C7C9C6", +"> c #636662", +", c #201F1B", +"' c #242621", +") c #171B16", +"! c #1F221E", +"~ c #1E1B17", +"{ c #222621", +"] c #221F1B", +"^ c #1B1F1A", +"/ c #292622", +"( c #141713", +"_ c #5D605C", +": c #050904", +"< c #60635F", +"[ c #0F0904", +"} c #B50701", +"| c #E40600", +"1 c #850702", +"2 c #C8CAC7", +"3 c #616460", +"4 c #060A05", +"5 c #0E0904", +"6 c #A30701", +"7 c #FF0600", +"8 c #BB0701", +"9 c #0C0904", +"0 c #BC0701", +"a c #8E0702", +"b c #646763", +"c c #676A66", +"d c #AB0701", +"e c #FC0600", +"f c #9B0702", +"g c #5F625E", +"h c #0B0904", +"i c #B30701", +"j c #686B67", +"k c #5B5E5A", +"l c #090904", +"m c #9D0702", +"n c #FA0A04", +"o c #6C6F6B", +"p c #BABCB9", +"q c #AD0701", +"r c #F91B15", +"s c #E35651", +"t c #ED0600", +"u c #FE0802", +"v c #E95753", +"w c #EE211B", +"x c #CC6A66", +"y c #DA3630", +"z c #950702", +"A c #323631", +"B c #EC0600", +"C c #FE0903", +"D c #CAC8C5", +"E c #F23732", +"F c #EA524E", +"G c #CFB4B1", +"H c #FB150F", +"I c #E11D18", +"J c #EB4D48", +"K c #E85A55", +"L c #F62621", +"M c #F42D27", +"N c #E60903", +"O c #F2241E", +"P c #FA140E", +"Q c #EE433E", +"R c #EE1C16", +"S c #F50600", +"T c #FD0D07", +"U c #E6625D", +"V c #C48581", +"W c #F20B05", +"X c #CD6762", +"Y c #F03C36", +"Z c #FD0F09", +"` c #EF302A", +" . c #F62822", +".. c #E56661", +"+. c #FC100A", +"@. c #FA1A14", +"#. c #F91C16", +"$. c #F62823", +"%. c #F91D17", +"&. c #E70600", +"*. c #F03E39", +"=. c #FD0E08", +"-. c #DB534E", +";. c #BEC0BD", +">. c #10140F", +",. c #FD0C06", +"'. c #F90802", +"). c #D26A66", +"!. c #FB1510", +"~. c #FF0701", +"{. c #FE0600", +"]. c #110904", +"^. c #C50701", +"/. c #8A0702", +"(. c #1A0904", +"_. c #BF0701", +":. c #B60701", +"<. c #A40701", +"[. c #BA0701", +"}. c #080C07", +"|. c #1B0904", +"1. c #C70701", +"2. c #FD0600", +"3. c #920702", +"4. c #70736F", +"5. c #380803", +"6. c #340803", +"7. c #5C5F5B", +"8. c #BCBEBB", +". . . . . . . . . . + @ # $ $ % @ & * = - * . . . . . . . . . . ", +". . . . . . . . ; > , ' ) ! ! ~ { ] ^ / ( ^ > ; . . . . . . . . ", +". . . . . . . . _ : : : : : : : : : : : : : : _ . . . . . . . . ", +". . . . . . . < : [ } | | | | | | | | | | 1 [ : < . . . . . . . ", +". . . . . 2 3 4 5 6 7 7 7 7 7 7 7 7 7 7 7 7 8 9 4 3 2 . . . . . ", +". . . . 2 > : : 0 7 7 7 7 7 7 7 7 7 7 7 7 7 7 a : : > 2 . . . . ", +". . . . b : : 6 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 a [ : b . . . . ", +". . . c : 5 d e 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 f 5 : c . . . ", +". - g 4 h f 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 i h 4 j . . ", +"$ k : l m 7 7 7 7 7 7 7 7 7 7 7 7 7 n 7 7 7 7 7 7 7 7 7 l : o . ", +"p : : q 7 r . . s t . . . . . . u v . . w 7 7 . . . x y z : A . ", +"p : : B C . . . D E . . . . . . F . . . . 7 7 . . . . G B : A . ", +"p : : B H . . I . . J K . . K L . . . . . . 7 . . K . . B : A . ", +"p : : B H . . 7 . . 7 7 . . 7 M . . 7 N . . 7 . . 7 O . B : A . ", +"p : : B P . . . 7 7 7 7 . . 7 Q . . 7 7 . . 7 . . 7 R . B : A . ", +"p : : B S . . . . T 7 7 . . 7 Q . . 7 7 . . 7 . . U V . B : A . ", +"p : : B 7 W X . . . 7 7 . . 7 Q . . 7 7 . . 7 . . . . . B : A . ", +"p : : B 7 7 7 Y . . Z 7 . . 7 Q . . 7 7 . . 7 . . . . ` B : A . ", +"p : : B .. . 7 ... +.7 . . 7 @.. . 7 #.. . 7 . . 7 7 7 B : A . ", +"p : : B $.. . %.. . 7 7 . . 7 &.* . . . . *.7 . . 7 7 7 B : A . ", +"p : : B =.. . . . . 7 7 . . 7 7 -.. . . . 7 7 . . 7 7 7 B : A . ", +";.>.: q 7 r . . . ,.7 7 . . 7 7 '.).. . !.7 7 . . 7 7 7 z : A . ", +". o : l } 7 7 n 7 7 7 7 7 7 7 7 7 7 C ~.7 7 7 7 7 7 {.m l : o . ", +". . j 4 ].^.7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 /.: 4 j . . ", +". . . c : (._.7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 e d 5 : c . . . ", +". . . . b : [ :.7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 f : : b . . . . ", +". . . . 2 > : 9 0 7 7 7 7 7 7 7 7 7 7 7 7 7 7 <.9 : > 2 . . . . ", +". . . . . 2 3 4 5 8 7 7 7 7 7 7 7 7 7 7 7 {.[.5 }.3 2 . . . . . ", +". . . . . . . < : |.1.7 7 7 7 7 7 7 7 7 2.3.: : 4.. . . . . . . ", +". . . . . . . . _ : ].5.5.5.5.5.5.5.5.5.6.: : _ . . . . . . . . ", +". . . . . . . . ; 7.: : : : : : : : : : : : 7.; . . . . . . . . ", +". . . . . . . . . ; 8.8.8.8.8.8.8.8.8.8.8.8.; . . . . . . . . . "}; diff --git a/lib/wx/examples/xrc/rc/throbber.gif b/lib/wx/examples/xrc/rc/throbber.gif Binary files differnew file mode 100644 index 0000000000..82c2170acc --- /dev/null +++ b/lib/wx/examples/xrc/rc/throbber.gif diff --git a/lib/wx/examples/xrc/rc/toolbar.xrc b/lib/wx/examples/xrc/rc/toolbar.xrc new file mode 100644 index 0000000000..ee7833309b --- /dev/null +++ b/lib/wx/examples/xrc/rc/toolbar.xrc @@ -0,0 +1,51 @@ +<?xml version="1.0"?> + +<resource xmlns="http://www.wxwidgets.org/wxxrc" version="2.3.0.1"> + +<object class="wxToolBar" name="main_toolbar"> + <style>wxTB_FLAT|wxTB_DOCKABLE</style> + <margins>2,2</margins> + <object class="tool" name="non_derived_dialog_tool_or_menuitem"> + <tooltip>Non-Derived Dialog Example</tooltip> + <bitmap>basicdlg.xpm</bitmap> + <longhelp>The basic instance of wxDialog loaded via XRC</longhelp> + </object> + <object class="tool" name="derived_tool_or_menuitem"> + <tooltip>Derived Dialog Example</tooltip> + <bitmap>derivdlg.xpm</bitmap> + <longhelp>The most important example: load an XRC for a derived dialog</longhelp> + </object> + <object class="tool" name="controls_tool_or_menuitem"> + <tooltip>Controls Example</tooltip> + <bitmap>controls.xpm</bitmap> + <longhelp>A notebook displaying all the wxWidgets controls</longhelp> + </object> + <object class="tool" name="uncentered_tool_or_menuitem"> + <tooltip>Uncentered Example</tooltip> + <bitmap>uncenter.xpm</bitmap> + <longhelp>Disable autocentering of a dialog on its parent</longhelp> + </object> + <separator/> + <object class="tool" name="custom_class_tool_or_menuitem"> + <tooltip>Custom Class Example</tooltip> + <bitmap>custclas.xpm</bitmap> + <longhelp>Embed your own custom classes into an XRC</longhelp> + </object> + <object class="tool" name="platform_property_tool_or_menuitem"> + <tooltip>Platform Specific Example</tooltip> + <bitmap>platform.xpm</bitmap> + <longhelp>Customize parts of an interface for a desired platform</longhelp> + </object> + <object class="tool" name="art_provider_tool_or_menuitem"> + <tooltip>wxArtProvider Example</tooltip> + <bitmap>artprov.xpm</bitmap> + <longhelp>Use wxArtProvider to insert desired icons at runtime</longhelp> + </object> + <object class="tool" name="variable_expansion_tool_or_menuitem"> + <tooltip>Variable Expansion Example</tooltip> + <bitmap>variable.xpm</bitmap> + <longhelp>Replace variables in the XRC file at runtime</longhelp> + </object> +</object> + +</resource> diff --git a/lib/wx/examples/xrc/rc/uncenter.xpm b/lib/wx/examples/xrc/rc/uncenter.xpm new file mode 100644 index 0000000000..103b1cb301 --- /dev/null +++ b/lib/wx/examples/xrc/rc/uncenter.xpm @@ -0,0 +1,24 @@ +/* XPM */ +static char * uncenter_xpm[] = { +"16 16 5 1", +" c None", +". c #000000", +"+ c #808080", +"@ c #0000FF", +"# c #FFFFFF", +" ", +"................", +".++++++++++++++.", +".+@@@@@@@@@@@@+.", +".++++++++++++++.", +".+############+.", +".+###....#####+.", +".+###..#######+.", +".+###.#.######+.", +".+###.##.#####+.", +".+#######.####+.", +".+########.###+.", +".+############+.", +".++++++++++++++.", +"................", +" "}; diff --git a/lib/wx/examples/xrc/rc/uncenter.xrc b/lib/wx/examples/xrc/rc/uncenter.xrc new file mode 100644 index 0000000000..4f6f6ce532 --- /dev/null +++ b/lib/wx/examples/xrc/rc/uncenter.xrc @@ -0,0 +1,47 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> + +<resource xmlns="http://www.wxwidgets.org/wxxrc" version="2.3.0.1"> + +<object class="wxDialog" name="uncentered_dialog"> + <title>Uncentered Example</title> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxGROW|wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxTextCtrl" name="message_textctrl"> + <size>500,150</size> + <style>wxTE_MULTILINE</style> + <value>All of the dialogs in the XRC demo, except for this dialog, center themselves automatically on their parent window, since that is what is most commonly needed. The centering for the other dialogs was done automatically simply by including a <centered>1</centered> as a tag directly under the dialog node.\n\nHowever, there may be some times when you don't want autocentering. If you don't want the dialog centered, just don't use the <centered> tag and the dialog will be placed in the default window position (which is at screen coordinate 0,0 in the upper left corner of the screen). This dialog is an example of when centering is turned off.</value> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxBoxSizer"> + <orient>wxHORIZONTAL</orient> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxButton" name="wxID_OK"> + <label>OK</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxButton" name="wxID_CANCEL"> + <label>Cancel</label> + </object> + </object> + </object> + </object> + </object> +</object> + +</resource> diff --git a/lib/wx/examples/xrc/rc/update.gif b/lib/wx/examples/xrc/rc/update.gif Binary files differnew file mode 100644 index 0000000000..9b66868827 --- /dev/null +++ b/lib/wx/examples/xrc/rc/update.gif diff --git a/lib/wx/examples/xrc/rc/variable.xpm b/lib/wx/examples/xrc/rc/variable.xpm new file mode 100644 index 0000000000..3e95bd869d --- /dev/null +++ b/lib/wx/examples/xrc/rc/variable.xpm @@ -0,0 +1,21 @@ +/* XPM */ +static char * variable_xpm[] = { +"16 16 2 1", +" c None", +". c #0E2CEF", +" ", +" . ", +" ... .. ", +" .... .. ", +" ...... .. ", +" . ... .. ", +" . ..... ", +" ... ", +" .... ", +" ..... . ", +" .. ... . ", +" .. ..... ", +" .. ... ", +" . ... ", +" ", +" "}; diff --git a/lib/wx/examples/xrc/rc/variable.xrc b/lib/wx/examples/xrc/rc/variable.xrc new file mode 100644 index 0000000000..91d7d5cc24 --- /dev/null +++ b/lib/wx/examples/xrc/rc/variable.xrc @@ -0,0 +1,59 @@ +<?xml version="1.0" encoding="ISO-8859-1"?> + +<resource xmlns="http://www.wxwidgets.org/wxxrc" version="2.3.0.1"> + +<object class="wxDialog" name="variable_expansion_dialog"> + <title>Variable Expansion Example</title> + <centered>1</centered> + <object class="wxFlexGridSizer"> + <cols>1</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>0</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxGROW|wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxTextCtrl" name="message_textctrl"> + <size>500,150</size> + <style>wxTE_MULTILINE</style> + <value>VARIABLE EXPANSION ISN'T IMPLEMENTED CURRENTLY. You can use variable expansion in your XRC files. The steps to do this are:\n\n(1)Enclose a variable inside a dollarsign and round brackets, like this: dollarsign(version).\n\n(2) Set the XmlResource flags to allow expansion of variables.\n\n(3)Before you use that XML resource, inform the XmlResourceHandler what you want that variable's value to be, via wxResourceHandler::Get()->SetVariable( "version", "2.4.0")\n\n Now, at runtime, the variable will be automatically replace by its value before the control is constructed.\n\nThe number in the version at the bottom of this dialog is an example of this expansion in action.\n\nThis is very handy for things like replacing the text in a wxStaticText, since it is a much simpler way to make a wxStaticText be a proper size: by creating it the proper size. This is in contrast to the alternative way of having using some static non-variable value in your XRC, having XRC construct it, then your application having code to change the text of it, then your app getting its best size, then setting the statictext's size, then laying out the dialog's sizer again, and other work.</value> + </object> + </object> + <object class="sizeritem"> + <flag>wxGROW|wxALIGN_BOTTOM</flag> + <object class="wxFlexGridSizer"> + <cols>3</cols> + <rows>0</rows> + <vgap>0</vgap> + <hgap>0</hgap> + <growablecols>2</growablecols> + <growablerows>0</growablerows> + <object class="sizeritem"> + <flag>wxALIGN_CENTER_VERTICAL|wxLEFT|wxTOP|wxBOTTOM</flag> + <border>5</border> + <object class="wxStaticText" name="build_information_statictext"> + <label>This build is:</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_CENTRE|wxALL</flag> + <border>5</border> + <object class="wxStaticText" name="version_statictext"> + <label>$(version)</label> + </object> + </object> + <object class="sizeritem"> + <flag>wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL</flag> + <border>5</border> + <object class="wxButton" name="wxID_OK"> + <label>OK</label> + </object> + </object> + </object> + </object> + </object> +</object> + +</resource> diff --git a/lib/wx/examples/xrc/xrc.erl b/lib/wx/examples/xrc/xrc.erl new file mode 100644 index 0000000000..6478171b4f --- /dev/null +++ b/lib/wx/examples/xrc/xrc.erl @@ -0,0 +1,323 @@ +%% +%% %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% +%%% +%%% Description : Testing and demo xrc's +%%% This mimics the xrc demo from wxwidgets. +%%% Created : 4 Dec 2007 by Dan Gudmundsson <[email protected]> +%%%------------------------------------------------------------------- + +-module(xrc). +-compile(export_all). + +-include("../../include/wx.hrl"). + + +%% I've put all "classes" in the same file, but you can see the follow +%% the code in xrcdemo from the samples directory in wxWidgets src package + +start() -> + %% Starts wxwidgets + WX = wx:new(), + %% In erlang wx, all image handlers are initilized already. + %% wxImage::AddHandler(new wxXPMHandler); + + %% Initialize all the XRC handlers. Always required (unless you feel like + %% going through and initializing a handler of each control type you will + %% be using (ie initialize the spinctrl handler, initialize the textctrl + %% handler). However, if you are only using a few control types, it will + %% save some space to only initialize the ones you will be using. See + %% wxXRC docs for details. + + Xrc = wxXmlResource:get(), + wxXmlResource:initAllHandlers(Xrc), + true = wxXmlResource:load(Xrc, rc_dir("menu.xrc")), + true = wxXmlResource:load(Xrc, rc_dir("toolbar.xrc")), + true = wxXmlResource:load(Xrc, rc_dir("basicdlg.xrc")), + true = wxXmlResource:load(Xrc, rc_dir("derivdlg.xrc")), + true = wxXmlResource:load(Xrc, rc_dir("controls.xrc")), + true = wxXmlResource:load(Xrc, rc_dir("frame.xrc")), + true = wxXmlResource:load(Xrc, rc_dir("uncenter.xrc")), + true = wxXmlResource:load(Xrc, rc_dir("custclas.xrc")), + true = wxXmlResource:load(Xrc, rc_dir("artprov.xrc")), + true = wxXmlResource:load(Xrc, rc_dir("platform.xrc")), + true = wxXmlResource:load(Xrc, rc_dir("variable.xrc")), + Frame = wxFrame:new(), + myframe(WX,Frame), + wxFrame:show(Frame), + loop(Frame), + wx:destroy(). + +rc_dir(File) -> + SelfDir = filename:dirname(code:which(?MODULE)), + filename:join([SelfDir,rc,File]). + +loop(Frame) -> + receive + #wx{id=Id, event=#wxCommand{}} -> + handle_cmd(get(Id), Id, Frame), + loop(Frame); + #wx{event=#wxClose{}} -> + catch wxWindows:'Destroy'(Frame), + ok; + Ev = #wx{} -> + io:format("Got ~p ~n", [Ev]), + loop(Frame) + end. + +myframe(Parent, Frame) -> + Xrc = wxXmlResource:get(), + wxXmlResource:loadFrame(Xrc, Frame, Parent, "main_frame"), + %% wxTopLevelWindow:setIcon(Frame, wxXmlResource:loadIcon(Xrc,"appicon")), + %% Load and setup menubar + wxFrame:setMenuBar(Frame, wxXmlResource:loadMenuBar(Xrc, "main_menu")), + %% hmm wxSystemOptions::SetOption ( wxT("msw.remap"), 0 ); + wxFrame:setToolBar(Frame, wxXmlResource:loadToolBar(Xrc, Frame, "main_toolbar")), + wxFrame:createStatusBar(Frame, [{number,1}]), + ok = wxFrame:connect(Frame, close_window), + connect(Frame). + +connect(Frame) -> + Menues = [unload_resource_menuitem, reload_resource_menuitem, + non_derived_dialog_tool_or_menuitem, derived_tool_or_menuitem, + controls_tool_or_menuitem, uncentered_tool_or_menuitem, + custom_class_tool_or_menuitem, platform_property_tool_or_menuitem, + art_provider_tool_or_menuitem, variable_expansion_tool_or_menuitem + ], + wxFrame:connect(Frame,command_menu_selected, [{id, ?wxID_EXIT}]), + wxFrame:connect(Frame,command_menu_selected, [{id, ?wxID_ABOUT}]), + [connect_xrcid(Str,Frame) || Str <- Menues], + ok. + +connect_xrcid(Name,Frame) -> + ID = wxXmlResource:getXRCID(atom_to_list(Name)), + put(ID, Name), + wxFrame:connect(Frame,command_menu_selected,[{id,ID}]). + +%% Handle commands + +handle_cmd(unload_resource_menuitem, _, _Frame) -> + Xrc = wxXmlResource:get(), + case wxXmlResource:unload(Xrc, "rc/basicdlg") of + true -> + io:format("Basic dialog unloaded~n",[]); + false -> + io:format("Failed to unload basic dialog~n",[]) + end; + +handle_cmd(reload_resource_menuitem, _, _Frame) -> + Xrc = wxXmlResource:get(), + case wxXmlResource:reload(Xrc, "rc/basicdlg") of + true -> + io:format("Basic dialog reloaded~n",[]); + false -> + io:format("Failed to reload basic dialog~n",[]) + end; + +handle_cmd(_, ?wxID_EXIT, Frame) -> + wxFrame:close(Frame); + +handle_cmd(non_derived_dialog_tool_or_menuitem, _, Frame) -> + Xrc = wxXmlResource:get(), + Dlg = wxDialog:new(), + %% "non_derived_dialog" is the name of the wxDialog XRC node that should + %% be loaded. + case wxXmlResource:loadDialog(Xrc, Dlg, Frame, "non_derived_dialog") of + true -> + wxDialog:showModal(Dlg); + false -> + io:format("Failed to load non_derived_dialog~n",[]) + end, + %% In Erlang you should delete the dialog afterwards + wxDialog:destroy(Dlg); + +handle_cmd(derived_tool_or_menuitem, _, Frame) -> + Pref = prefDialog(Frame), + wxDialog:showModal(Pref); + +handle_cmd(animation_ctrl_play, _, _Frame) -> + %% Not yet implemented + ok; + +handle_cmd(controls_tool_or_menuitem,_,Frame) -> + Xrc = wxXmlResource:get(), + Dlg = wxDialog:new(), + true = wxXmlResource:loadDialog(Xrc, Dlg, Frame, "controls_dialog"), + + LCtrl = wxXmlResource:xrcctrl(Dlg, "controls_listctrl", wxListCtrl), + wxListCtrl:insertColumn(LCtrl, 0, "Name", [{width, 200}]), + wxListCtrl:insertItem(LCtrl, 0, "Todd Hope"), + wxListCtrl:insertItem(LCtrl, 1, "Kim Wynd"), + wxListCtrl:insertItem(LCtrl, 2, "Leon Li"), + + TCtrl = wxXmlResource:xrcctrl(Dlg, "controls_treectrl", wxTreeCtrl), + wxTreeCtrl:addRoot(TCtrl, "Godfather"), + TRoot = wxTreeCtrl:getRootItem(TCtrl), + wxTreeCtrl:appendItem(TCtrl,TRoot, "Evil henchmen 1"), + wxTreeCtrl:appendItem(TCtrl,TRoot, "Evil henchmen 2"), + wxTreeCtrl:appendItem(TCtrl,TRoot, "Evil accountant"), + + wxDialog:showModal(Dlg), + wxDialog:destroy(Dlg); + +handle_cmd(uncentered_tool_or_menuitem,_,Frame) -> + Xrc = wxXmlResource:get(), + Dlg = wxDialog:new(), + true = wxXmlResource:loadDialog(Xrc, Dlg, Frame, "uncentered_dialog"), + wxDialog:showModal(Dlg), + wxDialog:destroy(Dlg); + +handle_cmd(custom_class_tool_or_menuitem,_,Frame) -> + Xrc = wxXmlResource:get(), + Dlg = wxDialog:new(), + true = wxXmlResource:loadDialog(Xrc, Dlg, Frame, "custom_class_dialog"), + + ResizeableLC = myResizeableListCtrl(Dlg, ?wxID_ANY, {-1,-1}, {-1,-1},?wxLC_REPORT), + %% "custom_control_placeholder" is the name of the "unknown" tag in the + %% custctrl.xrc XRC file. + wxXmlResource:attachUnknownControl(Xrc, "custom_control_placeholder", ResizeableLC), + wxDialog:showModal(Dlg), + wxDialog:destroy(Dlg); + +handle_cmd(platform_property_tool_or_menuitem, _, Frame) -> + Xrc = wxXmlResource:get(), + Dlg = wxDialog:new(), + true = wxXmlResource:loadDialog(Xrc, Dlg, Frame, "platform_property_dialog"), + wxDialog:showModal(Dlg), + wxDialog:destroy(Dlg); + +handle_cmd(art_provider_tool_or_menuitem, _, Frame) -> + Xrc = wxXmlResource:get(), + Dlg = wxDialog:new(), + true = wxXmlResource:loadDialog(Xrc, Dlg, Frame, "art_provider_dialog"), + wxDialog:showModal(Dlg), + wxDialog:destroy(Dlg); + +handle_cmd(variable_expansion_tool_or_menuitem, _, Frame) -> + Xrc = wxXmlResource:get(), + Dlg = wxDialog:new(), + true = wxXmlResource:loadDialog(Xrc, Dlg, Frame, "variable_expansion_dialog"), + wxDialog:showModal(Dlg), + wxDialog:destroy(Dlg); +handle_cmd(_, ?wxID_ABOUT, Frame) -> + Msg = "This is the about dialog of XML resources demo.\n", + MD = wxMessageDialog:new(Frame,Msg, + [{style, ?wxOK bor ?wxICON_INFORMATION}, + {caption, "About"}]), + wxDialog:showModal(MD), + wxDialog:destroy(MD); +handle_cmd(Dialog, Id, _) -> + io:format("Not implemented yet ~p (~p) ~n",[Dialog, Id]). + + +%%%%%%%%%%%%%%%% +%% Trying to mimic the derived dialog example +%%%%%%%%%%%%%%%% + +prefDialog(Parent) -> + Xrc = wxXmlResource:get(), + Dlg = wxDialog:new(), + true = wxXmlResource:loadDialog(Xrc, Dlg, Parent, "derived_dialog"), + + %% Shows that callbacks can be used it doesn't need to though. + OnMyButtonClicked = fun(_EvRec, _wxEvent) -> + MD = wxMessageDialog:new(Dlg, "You clicked on My Button"), + wxMessageDialog:showModal(MD), + wxMessageDialog:destroy(MD) + end, + wxDialog:connect(Dlg, command_button_clicked, + [{id,wxXmlResource:getXRCID("my_button")}, + {callback,OnMyButtonClicked}]), + + OnMyCheckBox = fun(_EvRec, _Event) -> + CheckB = wxXmlResource:xrcctrl(Dlg, "my_checkbox", wxCheckBox), + Text = wxXmlResource:xrcctrl(Dlg, "my_textctrl", wxTextCtrl), + Bool = wxCheckBox:isChecked(CheckB), + wxTextCtrl:enable(Text, [{enable,Bool}]) + end, + wxDialog:connect(Dlg,update_ui,[{id,wxXmlResource:getXRCID("my_checkbox")}, + {callback,OnMyCheckBox}]), + + %% Keep updateUI event interval at 250ms + wxUpdateUIEvent:setUpdateInterval(250), + + OnOk = fun(_,_) -> + Str = + "Press Ok to close derived dialog, or Cancel to abort" + "Overriding base class ok button handler", + MD = wxMessageDialog:new(Dlg, Str, [{style, ?wxOK bor ?wxCANCEL bor ?wxCENTER}]), + case wxMessageDialog:showModal(MD) of + ?wxID_OK -> + wxMessageDialog:endModal(Dlg, ?wxID_OK); + _R -> + ignore + end, + wxMessageDialog:destroy(MD) + end, + wxDialog:connect(Dlg,command_button_clicked,[{id,?wxID_OK},{callback,OnOk}]), + Dlg. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +-define(RECORD_COLUMN, 0). +-define(ACTION_COLUMN, 1). +-define(PRIORITY_COLUMN,2). + +-define(PU_ADD_RECORD, ?wxID_HIGHEST+1). +-define(PU_EDIT_RECORD, ?wxID_HIGHEST+2). +-define(PU_DELETE_RECORD, ?wxID_HIGHEST+3). + +myResizeableListCtrl(Parent,Id,Pos,Size,Style) -> + LC = wxListCtrl:new(Parent, [{winid,Id}, {pos,Pos}, {size,Size}, {style,Style}]), + wxListCtrl:insertColumn(LC,?RECORD_COLUMN, "Record", [{width, 140}]), + wxListCtrl:insertColumn(LC,?ACTION_COLUMN, "Action", [{width, 70}]), + wxListCtrl:insertColumn(LC,?PRIORITY_COLUMN, "Priority", [{width, 70}]), + wxListCtrl:connect(LC, right_down, [{id,Id}, {callback, fun lc_onRightClick/2}]), + wxListCtrl:connect(LC, size, [{id,Id}, {callback, fun lc_onSize/2}]), + LC. + +lc_onRightClick(#wx{obj=ListCtrl, event=#wxMouse{x=X,y=Y}},_Ev) -> + Menu = wxMenu:new(), + wxMenu:append(Menu, ?PU_ADD_RECORD, "Add a new record"), + wxMenu:append(Menu, ?PU_EDIT_RECORD,"Edit selected record"), + wxMenu:append(Menu, ?PU_DELETE_RECORD, "Delete selected record"), + case wxListCtrl:getSelectedItemCount(ListCtrl) of + 0 -> + wxMenu:enable(Menu, ?PU_EDIT_RECORD, false), + wxMenu:enable(Menu, ?PU_DELETE_RECORD, false); + _ -> + ignore + end, + MenuCB = fun(_,_) -> io:format("Menu selected~n",[]) end, + wxWindow:connect(ListCtrl, command_menu_selected, [{callback, MenuCB}]), + wxWindow:popupMenu(ListCtrl, Menu, [{pos, {X,Y}}]), + wxMenu:destroy(Menu). + +lc_onSize(#wx{obj=ListCtrl},EvObj) -> + {LeftMostColW0,_} = wxListCtrl:getSize(ListCtrl), + LeftMostColW1 = LeftMostColW0 - wxListCtrl:getColumnWidth(ListCtrl, ?ACTION_COLUMN), + LeftMostColW2 = LeftMostColW1 - wxListCtrl:getColumnWidth(ListCtrl, ?PRIORITY_COLUMN), + %% Hmm missing wxSystemSettings::GetMetric( wxSYS_VSCROLL_X ); + LeftMostColW = LeftMostColW2 - 5, + wxListCtrl:setColumnWidth(ListCtrl, ?RECORD_COLUMN, LeftMostColW), + %% REQURED event.Skip() call to allow this event to propagate + %% upwards so others can do what they need to do in response to + %% this size event. + wxEvent:skip(EvObj), + io:format("Successfully set column width~n"). + +%%%%% |