From 84adefa331c4159d432d22840663c38f155cd4c1 Mon Sep 17 00:00:00 2001 From: Erlang/OTP Date: Fri, 20 Nov 2009 14:54:40 +0000 Subject: The R13B03 release. --- lib/wx/examples/demo/Makefile | 96 +++++ lib/wx/examples/demo/demo.erl | 363 +++++++++++++++++++ lib/wx/examples/demo/demo_html_tagger.erl | 534 ++++++++++++++++++++++++++++ lib/wx/examples/demo/erlang.png | Bin 0 -> 16065 bytes lib/wx/examples/demo/ex_aui.erl | 189 ++++++++++ lib/wx/examples/demo/ex_button.erl | 230 ++++++++++++ lib/wx/examples/demo/ex_canvas.erl | 177 +++++++++ lib/wx/examples/demo/ex_canvas_paint.erl | 248 +++++++++++++ lib/wx/examples/demo/ex_choices.erl | 159 +++++++++ lib/wx/examples/demo/ex_cursor.erl | 180 ++++++++++ lib/wx/examples/demo/ex_dialogs.erl | 171 +++++++++ lib/wx/examples/demo/ex_frame_utils.erl | 193 ++++++++++ lib/wx/examples/demo/ex_gauge.erl | 208 +++++++++++ lib/wx/examples/demo/ex_gl.erl | 409 +++++++++++++++++++++ lib/wx/examples/demo/ex_graphicsContext.erl | 146 ++++++++ lib/wx/examples/demo/ex_grid.erl | 142 ++++++++ lib/wx/examples/demo/ex_htmlWindow.erl | 93 +++++ lib/wx/examples/demo/ex_htmlWindow.html | 59 +++ lib/wx/examples/demo/ex_listCtrl.erl | 148 ++++++++ lib/wx/examples/demo/ex_notebook.erl | 147 ++++++++ lib/wx/examples/demo/ex_pickers.erl | 136 +++++++ lib/wx/examples/demo/ex_popupMenu.erl | 150 ++++++++ lib/wx/examples/demo/ex_radioBox.erl | 163 +++++++++ lib/wx/examples/demo/ex_sashWindow.erl | 128 +++++++ lib/wx/examples/demo/ex_sizers.erl | 436 +++++++++++++++++++++++ lib/wx/examples/demo/ex_slider.erl | 113 ++++++ lib/wx/examples/demo/ex_splitterWindow.erl | 102 ++++++ lib/wx/examples/demo/ex_static.erl | 117 ++++++ lib/wx/examples/demo/ex_textCtrl.erl | 104 ++++++ lib/wx/examples/demo/ex_treeCtrl.erl | 121 +++++++ lib/wx/examples/demo/image.jpg | Bin 0 -> 2333 bytes 31 files changed, 5462 insertions(+) create mode 100755 lib/wx/examples/demo/Makefile create mode 100644 lib/wx/examples/demo/demo.erl create mode 100644 lib/wx/examples/demo/demo_html_tagger.erl create mode 100644 lib/wx/examples/demo/erlang.png create mode 100644 lib/wx/examples/demo/ex_aui.erl create mode 100644 lib/wx/examples/demo/ex_button.erl create mode 100644 lib/wx/examples/demo/ex_canvas.erl create mode 100644 lib/wx/examples/demo/ex_canvas_paint.erl create mode 100644 lib/wx/examples/demo/ex_choices.erl create mode 100644 lib/wx/examples/demo/ex_cursor.erl create mode 100644 lib/wx/examples/demo/ex_dialogs.erl create mode 100644 lib/wx/examples/demo/ex_frame_utils.erl create mode 100644 lib/wx/examples/demo/ex_gauge.erl create mode 100644 lib/wx/examples/demo/ex_gl.erl create mode 100644 lib/wx/examples/demo/ex_graphicsContext.erl create mode 100644 lib/wx/examples/demo/ex_grid.erl create mode 100644 lib/wx/examples/demo/ex_htmlWindow.erl create mode 100644 lib/wx/examples/demo/ex_htmlWindow.html create mode 100644 lib/wx/examples/demo/ex_listCtrl.erl create mode 100644 lib/wx/examples/demo/ex_notebook.erl create mode 100644 lib/wx/examples/demo/ex_pickers.erl create mode 100644 lib/wx/examples/demo/ex_popupMenu.erl create mode 100644 lib/wx/examples/demo/ex_radioBox.erl create mode 100644 lib/wx/examples/demo/ex_sashWindow.erl create mode 100644 lib/wx/examples/demo/ex_sizers.erl create mode 100644 lib/wx/examples/demo/ex_slider.erl create mode 100644 lib/wx/examples/demo/ex_splitterWindow.erl create mode 100644 lib/wx/examples/demo/ex_static.erl create mode 100644 lib/wx/examples/demo/ex_textCtrl.erl create mode 100644 lib/wx/examples/demo/ex_treeCtrl.erl create mode 100644 lib/wx/examples/demo/image.jpg (limited to 'lib/wx/examples/demo') 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, <>), + 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}) -> + [""]; +anchor1({specification, F, 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) -> + ["", htmlquote(S), ""]. + +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}) -> + [""]; +to_html1({local,F,A,Str}) -> + ["", + htmlquote(Str),""]; +to_html1({remote,_M,_F,_A,Str}) -> + %%["",htmlquote(Str),""], + 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) -> + ["\n" + "\n" + "\n" + "\n" + ""]. + + +final({Tag, Toks}) -> + {Tag, {taggedToks, final1(Tag, Toks)}}. + +final1({Tag,_,_}, Toks) when Tag =:= func; Tag =:= func1 -> + %% io:format("fix_remote:~p~n",[Toks]), + fix_remote(Toks); +final1({export,_}, Toks) -> + fix_exports(Toks); +final1({import,_}, Toks) -> + fix_imports(Toks); +final1(_, Toks) -> + %% io:format("final:~p~n",[X]), + Toks. + + +fix_imports(Toks) -> + %% io:format("fix imports:~p~n",[Toks]), + Mod = find_imported_module(Toks), + %% io:format("Mod =~p~n",[Mod]), + fix_imports(Toks, Mod). + +fix_imports([{atom,A},{terminal,"/"},{integer,N}|T], Mod) -> + [{remote, Mod,A,list_to_integer(N),A++"/"++N}| + fix_imports(T, Mod)]; +fix_imports([H|T], Mod) -> + [H|fix_imports(T, Mod)]; +fix_imports([], _) -> + []. + +%% skip to the atom import, then take the first atom after import +find_imported_module([{atom,"import"}|T]) -> find_imported_module1(T); +find_imported_module([_|T]) -> find_imported_module(T). + +find_imported_module1([{atom,M}|_]) -> list_to_atom(M); +find_imported_module1([_|T]) -> find_imported_module1(T). + +%% won't work if there is white space between the symbols +%% fix later + +fix_exports([{atom,A},{terminal,"/"},{integer,N}|T]) -> + [{local,A,list_to_integer(N),A++"/"++N}|fix_exports(T)]; +fix_exports([H|T]) -> + [H|fix_exports(T)]; +fix_exports([]) -> + []. + +%% fix_remote merges Mod : Func into a single string +%% the problem is that +%% we only tag the first atom in a remote call mod:func(...) +%% mod is tagged as remote - but we want to +%% extend the tagging to include the entire mod:func +%% call ... + +fix_remote([{remote,M,F,A,Str},{terminal,":"},{atom,Str1}|T]) -> + [{remote,M,F,A,Str ++ ":" ++ Str1}|fix_remote(T)]; +fix_remote([{remote,M,F,A,Str},{white_space,S1},{terminal,":"},{atom,Str1}|T]) -> + [{remote,M,F,A,Str ++ S1 ++ ":" ++ Str1}|fix_remote(T)]; +fix_remote([{remote,M,F,A,Str},{white_space,S1},{terminal,":"},{white_space,S2},{atom,Str1}|T]) -> + [{remote,M,F,A,Str ++ S1 ++ ":" ++ S2 ++ Str1}|fix_remote(T)]; +fix_remote([{remote,M,F,A,Str},{terminal,":"},{white_space,S2},{atom,Str1}|T]) -> + [{remote,M,F,A,Str ++ ":" ++ S2 ++ Str1}|fix_remote(T)]; +fix_remote([H|T]) -> + [H|fix_remote(T)]; +fix_remote([]) -> + []. + +-spec is_keyword(atom()) -> bool(). + +is_keyword('after' ) -> true; +is_keyword('and') -> true; +is_keyword('andalso' ) -> true; +is_keyword('band' ) -> true; +is_keyword('begin' ) -> true; +is_keyword('bnot' ) -> true; +is_keyword('bor' ) -> true; +is_keyword('bsl' ) -> true; +is_keyword('bsr' ) -> true; +is_keyword('bxor' ) -> true; +is_keyword('case' ) -> true; +is_keyword('catch' ) -> true; +is_keyword('cond') -> true; +is_keyword('div' ) -> true; +is_keyword('end' ) -> true; +is_keyword('fun' ) -> true; +is_keyword('if' ) -> true; +is_keyword('not') -> true; +is_keyword('of' ) -> true; +is_keyword('or' ) -> true; +is_keyword('orelse' ) -> true; +is_keyword('query' ) -> true; +is_keyword('receive' ) -> true; +is_keyword('rem' ) -> true; +is_keyword('spec') -> true; +is_keyword('try' ) -> true; +is_keyword('when') -> true; +is_keyword('xor') -> true; +is_keyword(_) -> false. + +is_terminal('!') -> true; +is_terminal('#') -> true; +is_terminal('(') -> true; +is_terminal(')') -> true; +is_terminal('*') -> true; +is_terminal('+') -> true; +is_terminal('++') -> true; +is_terminal(',') -> true; +is_terminal('-') -> true; +is_terminal('--') -> true; +is_terminal('->') -> true; +is_terminal('.') -> true; +is_terminal('/') -> true; +is_terminal('/=') -> true; +is_terminal(':') -> true; +is_terminal(':-') -> true; +is_terminal('::') -> true; +is_terminal(';') -> true; +is_terminal('<') -> true; +is_terminal('<-') -> true; +is_terminal('<<') -> true; +is_terminal('<=') -> true; +is_terminal('=') -> true; +is_terminal('=/=') -> true; +is_terminal('=:=') -> true; +is_terminal('=<') -> true; +is_terminal('==') -> true; +is_terminal('>') -> true; +is_terminal('>=') -> true; +is_terminal('>>') -> true; +is_terminal('?') -> true; +is_terminal('[') -> true; +is_terminal(']') -> true; +is_terminal('{') -> true; +is_terminal('|') -> true; +is_terminal('||') -> true; +is_terminal('}') -> true; +is_terminal(_) -> false. diff --git a/lib/wx/examples/demo/erlang.png b/lib/wx/examples/demo/erlang.png new file mode 100644 index 0000000000..a5901103a3 Binary files /dev/null and b/lib/wx/examples/demo/erlang.png differ diff --git a/lib/wx/examples/demo/ex_aui.erl b/lib/wx/examples/demo/ex_aui.erl new file mode 100644 index 0000000000..6adfd970fc --- /dev/null +++ b/lib/wx/examples/demo/ex_aui.erl @@ -0,0 +1,189 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-module(ex_aui). + +-behaviour(wx_object). + +%% Client API +-export([start/1]). + +%% wx_object callbacks +-export([init/1, terminate/2, code_change/3, + handle_info/2, handle_call/3, handle_event/2]). + +-include("../../include/wx.hrl"). + +-record(state, + { + parent, + config + }). + +start(Config) -> + wx_object:start_link(?MODULE, Config, []). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +init(Config) -> + wx:batch(fun() -> do_init(Config) end). + +-define(pi, wxAuiPaneInfo). + +do_init(Config) -> + Parent = proplists:get_value(parent, Config), + Panel = wxPanel:new(Parent, []), + + %% Setup sizers + MainSizer = wxBoxSizer:new(?wxVERTICAL), + + Manager = wxAuiManager:new([{managed_wnd, Panel} + ]), + + Pane = ?pi:new(), + ?pi:closeButton(Pane), + ?pi:right(Pane), + ?pi:dockable(Pane, [{b, true}]), + ?pi:floatingSize(Pane, 300,200), + ?pi:minSize(Pane, {50,50}), + ?pi:paneBorder(Pane), + ?pi:floatable(Pane, [{b, true}]), + + create_pane(Panel, Manager, Pane), + create_pane(Panel, Manager, + ?pi:caption(?pi:top(?pi:new(Pane)), "One")), + create_pane(Panel, Manager, + ?pi:caption(?pi:left(?pi:new(Pane)), "two")), + create_pane(Panel, Manager, + ?pi:caption(?pi:bottom(?pi:new(Pane)), "Three")), + Pane2 = wxAuiPaneInfo:new(Pane), + ?pi:centrePane(Pane2), + create_notebook(Panel, Manager, ?pi:new(Pane2)), + + wxPanel:setSizer(Panel, MainSizer), + + wxAuiManager:connect(Manager, aui_pane_button, [{skip,true}]), + wxAuiManager:connect(Manager, aui_pane_maximize, [{skip,true}]), + wxAuiManager:update(Manager), + + {Panel, #state{parent=Panel, config=Config}}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Callbacks handled as normal gen_server callbacks +handle_info(Msg, State) -> + demo:format(State#state.config, "Got Info ~p\n", [Msg]), + {noreply, State}. + +handle_call(Msg, _From, State) -> + demo:format(State#state.config, "Got Call ~p\n", [Msg]), + {reply,{error, nyi}, State}. + +%% Async Events are handled in handle_event as in handle_info +handle_event(#wx{obj = Notebook, + event = #wxCommand{type = command_button_clicked}}, + State) -> + Tab = wxPanel:new(Notebook, []), + wxButton:new(Tab, ?wxID_ANY, [{label,"New tab"}]), + wxAuiNotebook:insertPage(Notebook, 1, Tab, "OMG TAB!! ", [{select, false}]), + {noreply, State}; +handle_event(#wx{obj = Notebook, + event = #wxAuiNotebook{type = command_auinotebook_page_changed, + selection = Sel}}, State) -> + demo:format(State#state.config, "You have changed page to ~p.\n", + [wxAuiNotebook:getPageText(Notebook, Sel)]), + {noreply, State}; +handle_event(#wx{event = #wxAuiNotebook{type = command_auinotebook_page_close}}, State) -> + demo:format(State#state.config, "You have closed a page.\n",[]), + {noreply, State}; +handle_event(#wx{event = #wxAuiManager{type = aui_pane_button, + button = Button}}, State) -> + case Button of + ?wxAUI_BUTTON_CLOSE -> + demo:format(State#state.config, "You have closed a pane.\n",[]); + ?wxAUI_BUTTON_MAXIMIZE_RESTORE -> + ok; + ?wxAUI_BUTTON_PIN -> + demo:format(State#state.config, "You have pinned a pane.\n",[]) + end, + {noreply, State}; +handle_event(#wx{event = #wxAuiManager{type = aui_pane_maximize}}, State) -> + demo:format(State#state.config, "You have maximized a pane.\n",[]), + {noreply, State}; +handle_event(#wx{event = #wxAuiManager{type = aui_pane_restore}}, State) -> + demo:format(State#state.config, "You have restored a pane.\n",[]), + {noreply, State}; +handle_event(Ev = #wx{}, State) -> + io:format("~p\n", [Ev]), + {noreply, State}. + + +code_change(_, _, State) -> + {stop, ignore, State}. + +terminate(_Reason, _State) -> + ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Local functions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +create_notebook(Parent, Manager, Pane) -> + Style = (0 + bor ?wxAUI_NB_DEFAULT_STYLE + bor ?wxAUI_NB_TOP + bor ?wxAUI_NB_WINDOWLIST_BUTTON + bor ?wxAUI_NB_CLOSE_ON_ACTIVE_TAB + bor ?wxAUI_NB_TAB_MOVE + bor ?wxAUI_NB_SCROLL_BUTTONS + ), + + Notebook = wxAuiNotebook:new(Parent, [{style, Style}]), + + Tab1 = wxPanel:new(Notebook, []), + wxPanel:setBackgroundColour(Tab1, ?wxBLACK), + wxButton:new(Tab1, ?wxID_ANY, [{label,"New tab"}]), + wxAuiNotebook:addPage(Notebook, Tab1, "You can", []), + + Tab2 = wxPanel:new(Notebook, []), + wxPanel:setBackgroundColour(Tab2, ?wxRED), + wxButton:new(Tab2, ?wxID_ANY, [{label,"New tab"}]), + wxAuiNotebook:addPage(Notebook, Tab2, "rearrange", []), + + Tab3 = wxPanel:new(Notebook, []), + wxPanel:setBackgroundColour(Tab3, ?wxGREEN), + wxButton:new(Tab3, ?wxID_ANY, [{label,"New tab"}]), + wxAuiNotebook:addPage(Notebook, Tab3, "these tabs", []), + + wxAuiManager:addPane(Manager, Notebook, Pane), + + wxAuiNotebook:connect(Notebook, command_button_clicked), + wxAuiNotebook:connect(Notebook, command_auinotebook_page_close, [{skip, false}]), + wxAuiNotebook:connect(Notebook, command_auinotebook_page_changed), + Notebook. + + +create_pane(Parent, Manager, Pane) -> + TextCtrl = wxTextCtrl:new(Parent, ?wxID_ANY, [{size, {300,200}}, + {value, "An empty pane"}, + {style, 0 + bor ?wxDEFAULT + bor ?wxTE_MULTILINE}]), + wxAuiManager:addPane(Manager, TextCtrl, Pane), + TextCtrl. + + diff --git a/lib/wx/examples/demo/ex_button.erl b/lib/wx/examples/demo/ex_button.erl new file mode 100644 index 0000000000..28c8273cb9 --- /dev/null +++ b/lib/wx/examples/demo/ex_button.erl @@ -0,0 +1,230 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +%% This is example of the widgets and usage of wxErlang +%% Hopefully it will contain all implemented widgets, it's event handling +%% and some tutorials of how to use sizers and other stuff. + +-module(ex_button). + +-include_lib("wx/include/wx.hrl"). + +-behaviour(wx_object). +-export([start/1, init/1, terminate/2, code_change/3, + handle_info/2, handle_call/3, handle_event/2]). + +-record(state, + { + parent, + config + }). + +start(Config) -> + wx_object:start_link(?MODULE, Config, []). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +init(Config) -> + wx:batch(fun() -> do_init(Config) end). + +do_init(Config) -> + Parent = proplists:get_value(parent, Config), + Panel = wxScrolledWindow:new(Parent), + + %% Setup sizers + Sz = wxBoxSizer:new(?wxVERTICAL), + ButtSz = wxStaticBoxSizer:new(?wxHORIZONTAL, Panel, + [{label, "wxButton"}]), + AlignSz = wxStaticBoxSizer:new(?wxHORIZONTAL, Panel, + [{label, "Alignment Style"}]), + OtherSz = wxStaticBoxSizer:new(?wxHORIZONTAL, Panel, + [{label, "Other Styles"}]), + StockTopSz = wxStaticBoxSizer:new(?wxHORIZONTAL, Panel, + [{label, "Stock Buttons"}]), + + B10 = wxButton:new(Panel, 10, [{label,"Normal"}]), + wxButton:setToolTip(B10, "Normal button with (default) centered label"), + + B11 = wxToggleButton:new(Panel, 11, "Toggle Button"), + wxToggleButton:connect(B11, command_togglebutton_clicked), + wxButton:setToolTip(B11, "A toggle button"), + + B12 = wxButton:new(Panel, 12, [{label,"Default"}]), + wxButton:setDefault(B12), + wxButton:setToolTip(B12, "Normal button set to be the default button"), + + B13 = wxButton:new(Panel, 13, [{label,"Disabled"}]), + wxButton:disable(B13), + wxButton:setToolTip(B13, "Disabled Normal button"), + + B14 = wxBitmapButton:new(Panel, 14, create_bitmap("A bitmap button")), + wxButton:setToolTip(B14, "A Bitmap button"), + + %% Alignment and NO_BORDER only works on Win and GTK + %% according to docs. + B20 = wxButton:new(Panel, 20, [{label,"Left Aligned"}, + {size, {100, -1}}, + {style,?wxBU_LEFT}]), + wxButton:setToolTip(B20, "Normal button with left aligned label"), + + B21 = wxButton:new(Panel, 21, [{label,"Top Aligned"}, + {size, {-1, 50}}, + {style,?wxBU_TOP}]), + wxButton:setToolTip(B21, "Normal button with top aligned label"), + + B22 = wxButton:new(Panel, 22, [{label,"Lower Right Aligned"}, + {size, {150, 50}}, + {style,?wxBU_BOTTOM bor ?wxBU_RIGHT}]), + wxButton:setToolTip(B22, "Normal button with top right aligned label"), + + %% Other types + B30 = wxButton:new(Panel, 30, [{label,"Flat Style"}, + {style, ?wxNO_BORDER}]), + wxButton:setToolTip(B30, "Flat style button, on some OS'es"), + + B31 = wxButton:new(Panel, 31, [{label,"Exact Fit"}, + {style, ?wxBU_EXACTFIT}]), + wxButton:setToolTip(B31, "Minimal Size button"), + + %% Stock Buttons + StockButts = [wxButton:new(Panel, Id) || Id <- stock_buttons()], + + StockSz = wxGridSizer:new(0,5,3,3), + + SzFlags = [{proportion, 0}, {border, 4}, {flag, ?wxALL}], + Expand = [{proportion, 0}, {border, 4}, {flag, ?wxALL bor + ?wxEXPAND}], + [wxSizer:add(ButtSz, Button, SzFlags) || + Button <- [B10, B11, B12, B13, B14]], + [wxSizer:add(AlignSz, Button, SzFlags) || Button <- [B20,B21,B22]], + [wxSizer:add(OtherSz, Button, SzFlags) || Button <- [B30,B31]], + [wxSizer:add(StockSz, Butt, SzFlags) || Butt <- StockButts], + wxSizer:add(StockTopSz, StockSz, SzFlags), + [wxSizer:add(Sz, Button, Flag) || + {Button, Flag} <- [{ButtSz,SzFlags},{AlignSz,Expand}, + {OtherSz,Expand}, {StockTopSz, Expand}]], + wxWindow:connect(Panel, command_button_clicked), + wxWindow:setSizer(Panel, Sz), + wxSizer:layout(Sz), + wxScrolledWindow:setScrollRate(Panel, 5, 5), + {Panel, #state{parent=Panel, config=Config}}. + + +%%%%%%%%%%%% +%% Async Events are handled in handle_event as in handle_info +handle_event(#wx{id=Id, event=#wxCommand{type=command_button_clicked}}, + State = #state{parent=Parent}) -> + B0 = wxWindow:findWindowById(Id, [{parent, Parent}]), + Butt = wx:typeCast(B0, wxButton), + Label = wxButton:getLabel(Butt), + demo:format(State#state.config,"Button: \'~ts\' clicked~n",[Label]), + {noreply,State}; + +handle_event(#wx{event=#wxCommand{type=command_togglebutton_clicked}}, + State = #state{}) -> + demo:format(State#state.config, + "Button: You toggled the 'Toggle button' ~n",[]), + {noreply,State}; + +handle_event(Ev = #wx{}, State = #state{}) -> + demo:format(State#state.config,"Got Event ~p~n",[Ev]), + {noreply,State}. + +%% Callbacks handled as normal gen_server callbacks +handle_info(Msg, State) -> + demo:format(State#state.config, "Got Info ~p~n",[Msg]), + {noreply,State}. + +handle_call(Msg, _From, State) -> + demo:format(State#state.config,"Got Call ~p~n",[Msg]), + {reply,ok,State}. + +code_change(_, _, State) -> + {stop, ignore, State}. + +terminate(_Reason, _State) -> + ok. + +%%%%% a copy from wxwidgets samples. +create_bitmap(Label) -> + Bmp = wxBitmap:new(140, 30), + DC = wxMemoryDC:new(), + wxMemoryDC:selectObject(DC, Bmp), + wxDC:setBackground(DC, ?wxWHITE_BRUSH), + wxDC:clear(DC), + wxDC:setTextForeground(DC, ?wxBLUE), + wxDC:drawLabel(DC, Label, {5,5,130,20}, [{alignment, ?wxALIGN_CENTER}]), + wxMemoryDC:destroy(DC), + Bmp. + + +stock_buttons() -> + [?wxID_ABOUT, + ?wxID_ADD, + ?wxID_APPLY, + ?wxID_BOLD, + ?wxID_CANCEL, + ?wxID_CLEAR, + ?wxID_CLOSE, + ?wxID_COPY, + ?wxID_CUT, + ?wxID_DELETE, + ?wxID_EDIT, + ?wxID_FIND, + ?wxID_FILE, + ?wxID_REPLACE, + ?wxID_BACKWARD, + ?wxID_DOWN, + ?wxID_FORWARD, + ?wxID_UP, + ?wxID_HELP, + ?wxID_HOME, + ?wxID_INDENT, + ?wxID_INDEX, + ?wxID_ITALIC, + ?wxID_JUSTIFY_CENTER, + ?wxID_JUSTIFY_FILL, + ?wxID_JUSTIFY_LEFT, + ?wxID_JUSTIFY_RIGHT, + ?wxID_NEW, + ?wxID_NO, + ?wxID_OK, + ?wxID_OPEN, + ?wxID_PASTE, + ?wxID_PREFERENCES, + ?wxID_PRINT, + ?wxID_PREVIEW, + ?wxID_PROPERTIES, + ?wxID_EXIT, + ?wxID_REDO, + ?wxID_REFRESH, + ?wxID_REMOVE, + ?wxID_REVERT_TO_SAVED, + ?wxID_SAVE, + ?wxID_SAVEAS, + ?wxID_SELECTALL, + ?wxID_STOP, + ?wxID_UNDELETE, + ?wxID_UNDERLINE, + ?wxID_UNDO, + ?wxID_UNINDENT, + ?wxID_YES, + ?wxID_ZOOM_100, + ?wxID_ZOOM_FIT, + ?wxID_ZOOM_IN, + ?wxID_ZOOM_OUT]. + diff --git a/lib/wx/examples/demo/ex_canvas.erl b/lib/wx/examples/demo/ex_canvas.erl new file mode 100644 index 0000000000..844c7eddf3 --- /dev/null +++ b/lib/wx/examples/demo/ex_canvas.erl @@ -0,0 +1,177 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-module(ex_canvas). + +-behaviour(wx_object). + +%% Client API +-export([start/1]). + +%% wx_object callbacks +-export([init/1, terminate/2, code_change/3, + handle_info/2, handle_call/3, handle_event/2, handle_sync_event/3]). + +-include_lib("wx/include/wx.hrl"). + +-record(state, + { + parent, + config, + canvas, + bitmap + }). + +start(Config) -> + wx_object:start_link(?MODULE, Config, []). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +init(Config) -> + wx:batch(fun() -> do_init(Config) end). + +do_init(Config) -> + Parent = proplists:get_value(parent, Config), + Panel = wxPanel:new(Parent, []), + + %% Setup sizers + MainSizer = wxBoxSizer:new(?wxVERTICAL), + Sizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "Various shapes"}]), + + Button = wxButton:new(Panel, ?wxID_ANY, [{label, "Redraw"}]), + + Canvas = wxPanel:new(Panel, [{style, ?wxFULL_REPAINT_ON_RESIZE}]), + + wxPanel:connect(Canvas, paint, [callback]), + wxPanel:connect(Canvas, size), + wxPanel:connect(Button, command_button_clicked), + + %% Add to sizers + wxSizer:add(Sizer, Button, [{border, 5}, {flag, ?wxALL}]), + wxSizer:addSpacer(Sizer, 5), + wxSizer:add(Sizer, Canvas, [{flag, ?wxEXPAND}, + {proportion, 1}]), + + wxSizer:add(MainSizer, Sizer, [{flag, ?wxEXPAND}, + {proportion, 1}]), + + wxPanel:setSizer(Panel, MainSizer), + wxSizer:layout(MainSizer), + + {W,H} = wxPanel:getSize(Canvas), + Bitmap = wxBitmap:new(erlang:max(W,30),erlang:max(30,H)), + + {Panel, #state{parent=Panel, config=Config, + canvas = Canvas, bitmap = Bitmap}}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Sync event from callback events, paint event must be handled in callbacks +%% otherwise nothing will be drawn on windows. +handle_sync_event(#wx{event = #wxPaint{}}, _wxObj, + #state{canvas=Canvas, bitmap=Bitmap}) -> + DC = wxPaintDC:new(Canvas), + redraw(DC, Bitmap), + wxPaintDC:destroy(DC), + ok. + +%% Async Events are handled in handle_event as in handle_info +handle_event(#wx{event = #wxCommand{type = command_button_clicked}}, + State = #state{}) -> + Image = wxImage:new("image.jpg"), + Image2 = wxImage:scale(Image, wxImage:getWidth(Image) div 3, + wxImage:getHeight(Image) div 3), + Bmp = wxBitmap:new(Image2), + wxImage:destroy(Image), + wxImage:destroy(Image2), + {W,H} = wxPanel:getSize(State#state.canvas), + Positions = lists:map(fun(_) -> + get_pos(W,H) + end, lists:seq(1,(W+H) div 20)), + Fun = fun(DC) -> + wxDC:clear(DC), + lists:foreach(fun({X,Y}=Pos) -> + wxDC:setBrush(DC, ?wxTRANSPARENT_BRUSH), + wxDC:setPen(DC, wxPen:new(?wxBLACK, [{width, 2}])), + case X rem 6 of + 0 -> wxDC:drawBitmap(DC, Bmp, Pos); + 1 -> wxDC:setBrush(DC, ?wxRED_BRUSH), + wxDC:drawRectangle(DC, Pos, {20,20}); + 2 -> wxDC:setBrush(DC, ?wxBLUE_BRUSH), + wxDC:drawCircle(DC, {X+10, Y+10}, 15); + 3 -> wxDC:setPen(DC, wxPen:new({200,200,0,255}, [{width, 4}])), + wxDC:drawLine(DC, Pos, get_pos(W,H)); + 4 -> wxDC:setBrush(DC, ?wxGREEN_BRUSH), + wxDC:drawEllipse(DC, Pos, {60,20}); + _ -> wxDC:drawLabel(DC, "Erlang /", {X,Y,60,20}), + wxDC:drawRotatedText(DC, "OTP", {X+60,Y}, 340.0) + end + end, Positions) + end, + draw(State#state.canvas, State#state.bitmap, Fun), + wxBitmap:destroy(Bmp), + {noreply, State}; +handle_event(#wx{event = #wxSize{size={W,H}}}, + State = #state{bitmap=Prev}) -> + Bitmap = wxBitmap:new(W,H), + draw(State#state.canvas, Bitmap, fun(DC) -> wxDC:clear(DC) end), + wxBitmap:destroy(Prev), + {noreply, State#state{bitmap = Bitmap}}; +handle_event(Ev = #wx{}, State = #state{}) -> + demo:format(State#state.config, "Got Event ~p\n", [Ev]), + {noreply, State}. + +%% Callbacks handled as normal gen_server callbacks +handle_info(Msg, State) -> + demo:format(State#state.config, "Got Info ~p\n", [Msg]), + {noreply, State}. + +handle_call(Msg, _From, State) -> + demo:format(State#state.config, "Got Call ~p\n", [Msg]), + {reply,{error, nyi}, State}. + +code_change(_, _, State) -> + {stop, ignore, State}. + +terminate(_Reason, _State) -> + ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Local functions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +%% Buffered makes it all appear on the screen at the same time +draw(Canvas, Bitmap, Fun) -> + MemoryDC = wxMemoryDC:new(Bitmap), + Fun(MemoryDC), + + CDC = wxWindowDC:new(Canvas), + wxDC:blit(CDC, {0,0}, + {wxBitmap:getWidth(Bitmap), wxBitmap:getHeight(Bitmap)}, + MemoryDC, {0,0}), + wxWindowDC:destroy(CDC), + wxMemoryDC:destroy(MemoryDC). + +redraw(DC, Bitmap) -> + MemoryDC = wxMemoryDC:new(Bitmap), + wxDC:blit(DC, {0,0}, + {wxBitmap:getWidth(Bitmap), wxBitmap:getHeight(Bitmap)}, + MemoryDC, {0,0}), + wxMemoryDC:destroy(MemoryDC). + +get_pos(W,H) -> + {random:uniform(W), random:uniform(H)}. diff --git a/lib/wx/examples/demo/ex_canvas_paint.erl b/lib/wx/examples/demo/ex_canvas_paint.erl new file mode 100644 index 0000000000..38d6b62f1d --- /dev/null +++ b/lib/wx/examples/demo/ex_canvas_paint.erl @@ -0,0 +1,248 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-module(ex_canvas_paint). + +-behaviour(wx_object). + +%% Client API +-export([start/1]). + +%% wx_object callbacks +-export([init/1, terminate/2, code_change/3, + handle_info/2, handle_call/3, handle_event/2, handle_sync_event/3]). + +-include_lib("wx/include/wx.hrl"). + +-record(state, + { + parent, + config, + canvas, + pen, + brush, + old_pos, + bitmap + }). + +start(Config) -> + wx_object:start_link(?MODULE, Config, []). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +init(Config) -> + wx:batch(fun() -> do_init(Config) end). + +do_init(Config) -> + Parent = proplists:get_value(parent, Config), + Panel = wxPanel:new(Parent, []), + + %% Setup sizers + MainSizer = wxBoxSizer:new(?wxVERTICAL), + Sizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "wxDC"}]), + + %% Create the window to paint on and make it repaint the whole window on resize + Canvas = wxPanel:new(Panel, [{style, ?wxFULL_REPAINT_ON_RESIZE}]), + wxPanel:setToolTip(Canvas, + "Left-click and hold to draw something - release to stop drawing.\n" + "Middle-click to fill with pink\n" + "Middle-dclick to fill with white.\n" + "Right-click to clear."), + + %% Create a wxPen and a WxBrush and set its colors to draw with + Brush = wxBrush:new(?wxWHITE), + Pen = wxPen:new(?wxBLACK, [{width, 2}]), + + PrintButton = wxButton:new(Panel, ?wxID_ANY, [{label, "Print"}]), + + Bitmap = wxBitmap:new(30,30), + + %% Add to sizers + wxSizer:add(Sizer, Canvas, [{flag, ?wxEXPAND}, + {proportion, 1}]), + + wxSizer:add(MainSizer, PrintButton, []), + wxSizer:add(MainSizer, Sizer, [{flag, ?wxEXPAND}, + {proportion, 1}]), + + wxPanel:connect(PrintButton, command_button_clicked), + wxPanel:connect(Canvas, paint, [callback]), + wxPanel:connect(Canvas, size), + wxPanel:connect(Canvas, left_down), + wxPanel:connect(Canvas, left_dclick), + wxPanel:connect(Canvas, left_up), + wxPanel:connect(Canvas, right_down), + wxPanel:connect(Canvas, middle_down), + wxPanel:connect(Canvas, middle_dclick), + wxPanel:setSizer(Panel, MainSizer), + wxSizer:layout(MainSizer), + {Panel, #state{parent=Panel, config=Config, + canvas = Canvas, pen = Pen, + brush = Brush, bitmap = Bitmap}}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Sync event from callback events, paint event must be handled in callbacks +%% otherwise nothing will be drawn on windows. +handle_sync_event(#wx{event = #wxPaint{}}, _wxObj, #state{canvas=Canvas, bitmap=Bitmap}) -> + DC = wxPaintDC:new(Canvas), + redraw(DC, Bitmap), + wxPaintDC:destroy(DC), + ok. + +%% Print what's drawn +handle_event(#wx{event = #wxCommand{type = command_button_clicked}}, + State = #state{bitmap=Bitmap}) -> + PD = wxPrintData:new(), + PDD = wxPrintDialogData:new(PD), + PSDD = wxPageSetupDialogData:new(PD), + Fun = + fun(This,_Page) -> + MX = MY = 500, + wxPrintout:fitThisSizeToPageMargins(This, {MX,MY}, PSDD), + {_X,_Y,W,H} = wxPrintout:getLogicalPageMarginsRect(This, PSDD), + wxPrintout:offsetLogicalOrigin(This,(W-MX) div 2, (H-MY) div 2), + DC = wxPrintout:getDC(This), + redraw(DC, Bitmap), + true + end, + Printout1 = wxPrintout:new("Print", Fun, + [{getPageInfo, fun getPageInfo/1}]), + Printout2 = wxPrintout:new("Print", Fun, + [{getPageInfo, fun getPageInfo/1}]), + Preview = wxPrintPreview:new(Printout1, [{printoutForPrinting,Printout2},{data,PDD}]), + case wxPrintPreview:isOk(Preview) of + true -> + Env = wx:get_env(), + spawn_link(fun() -> + wx:set_env(Env), + PF = wxPreviewFrame:new(Preview, State#state.parent, []), + wxPreviewFrame:centre(PF, [{dir, ?wxBOTH}]), + wxPreviewFrame:initialize(PF), + wxPreviewFrame:centre(PF), + wxPreviewFrame:show(PF) + end); + false -> + io:format("Could not create preview window.\n" + "Perhaps your current printer is not set correctly?~n", []), + wxPrintPreview:destroy(Preview) + end, + {noreply, State#state{}}; +%% Draw a line +handle_event(#wx{event = #wxMouse{type = motion, x = X, y = Y}}, + State = #state{canvas = Canvas, pen = Pen, brush = Brush}) -> + Fun = + fun(DC) -> + wxDC:setPen(DC, Pen), + wxBrush:setColour(Brush, ?wxBLACK), + wxDC:setBrush(DC, Brush), + wxDC:drawLine(DC, {X,Y}, State#state.old_pos) + end, + draw(Canvas,State#state.bitmap, Fun), + {noreply, State#state{old_pos = {X,Y}}}; +%% Resize event +handle_event(#wx{event = #wxSize{size = {W,H}}}, State = #state{bitmap=Prev}) -> + wxBitmap:destroy(Prev), + Bitmap = wxBitmap:new(W,H), + draw(State#state.canvas, Bitmap, fun(DC) -> wxDC:clear(DC) end), + {noreply, State#state{bitmap=Bitmap}}; +handle_event(#wx{event = #wxMouse{type = left_dclick,x = X,y = Y}}, State = #state{}) -> + wxPanel:connect(State#state.canvas, motion), + {noreply, State#state{old_pos = {X,Y}}}; +handle_event(#wx{event = #wxMouse{type = left_down,x = X,y = Y}}, State = #state{}) -> + wxPanel:connect(State#state.canvas, motion), + {noreply, State#state{old_pos = {X,Y}}}; +%% Fill with pink color +handle_event(#wx{event = #wxMouse{type = middle_down,x = X, y =Y}}, State = #state{}) -> + case os:type() of + {_, darwin} -> + io:format("Fill doesn't work on Darwin ~n",[]); + _ -> + ok + end, + Fun = + fun(DC) -> + wxBrush:setColour(State#state.brush, {255,125,255,255}), + wxDC:setBrush(DC, State#state.brush), + wxDC:floodFill(DC, {X,Y}, ?wxBLACK, [{style, ?wxFLOOD_BORDER}]) + end, + + draw(State#state.canvas, State#state.bitmap, Fun), + {noreply, State}; +%% Fill with white color +handle_event(#wx{event = #wxMouse{type = middle_dclick,x = X, y =Y}}, State = #state{}) -> + Fun = + fun(DC) -> + wxBrush:setColour(State#state.brush, ?wxWHITE), + wxDC:setBrush(DC, State#state.brush), + wxDC:floodFill(DC, {X,Y}, ?wxBLACK, [{style, ?wxFLOOD_BORDER}]) + end, + + draw(State#state.canvas, State#state.bitmap,Fun), + {noreply, State}; +handle_event(#wx{event = #wxMouse{type = left_up}}, State = #state{}) -> + wxPanel:disconnect(State#state.canvas, motion), + {noreply, State}; +%% Clear the DC +handle_event(#wx{event = #wxMouse{type = right_down}}, State = #state{}) -> + draw(State#state.canvas, State#state.bitmap, fun(DC) -> wxDC:clear(DC) end), + {noreply, State}. + +%% Callbacks handled as normal gen_server callbacks +handle_info(Msg, State) -> + demo:format(State#state.config, "Got Info ~p\n", [Msg]), + {noreply, State}. + +handle_call(Msg, _From, State) -> + demo:format(State#state.config, "Got Call ~p\n", [Msg]), + {reply,{error, nyi}, State}. + +code_change(_, _, State) -> + {stop, ignore, State}. + +terminate(_Reason, _State) -> + ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Local functions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +draw(Canvas, Bitmap, Fun) -> + MemoryDC = wxMemoryDC:new(Bitmap), + CDC = wxClientDC:new(Canvas), + + Fun(MemoryDC), + + wxDC:blit(CDC, {0,0}, + {wxBitmap:getWidth(Bitmap), wxBitmap:getHeight(Bitmap)}, + MemoryDC, {0,0}), + + wxClientDC:destroy(CDC), + wxMemoryDC:destroy(MemoryDC). + +redraw(DC, Bitmap) -> + MemoryDC = wxMemoryDC:new(Bitmap), + + wxDC:blit(DC, {0,0}, + {wxBitmap:getWidth(Bitmap), wxBitmap:getHeight(Bitmap)}, + MemoryDC, {0,0}), + + wxMemoryDC:destroy(MemoryDC). + + +getPageInfo(_This) -> + {1,1,1,1}. diff --git a/lib/wx/examples/demo/ex_choices.erl b/lib/wx/examples/demo/ex_choices.erl new file mode 100644 index 0000000000..75f8d22493 --- /dev/null +++ b/lib/wx/examples/demo/ex_choices.erl @@ -0,0 +1,159 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-module(ex_choices). + +-behaviour(wx_object). + +-export([start/1, init/1, terminate/2, code_change/3, + handle_info/2, handle_call/3, handle_event/2]). + +-include_lib("wx/include/wx.hrl"). + +-record(state, + { + parent, + config, + list_box + }). + + +start(Config) -> + wx_object:start_link(?MODULE, Config, []). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +init(Config) -> + wx:batch(fun() -> do_init(Config) end). + +do_init(Config) -> + Parent = proplists:get_value(parent, Config), + Panel = wxScrolledWindow:new(Parent, []), + + %% Setup sizers + MainSizer = wxBoxSizer:new(?wxVERTICAL), + ListBoxSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "wxListBox"}]), + + ChoiceSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "wxChoice"}]), + SpinSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "wxSpinCtrl"}]), + ComboSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "wxComboBox"}]), + Sizer = wxBoxSizer:new(?wxHORIZONTAL), + Sizer3 = wxBoxSizer:new(?wxHORIZONTAL), + + Choices = ["one","two","three", + "four","five","six", + "seven","eight","nine", + "ten", "eleven", "twelve"], + + %% Create a wxListBox that uses multiple selection + ListBox = wxListBox:new(Panel, 1, [{size, {-1,100}}, + {choices, ["Multiple selection"|Choices]}, + {style, ?wxLB_MULTIPLE}]), + wxListBox:setToolTip(ListBox, "A wxListBox with multiple selection"), + + %% Create a wxListBox that uses single selection + ListBox2 = wxListBox:new(Panel, 2, [{size, {-1,100}}, + {choices, ["Single selection"|Choices]}, + {style, ?wxLB_SINGLE}]), + wxListBox:setToolTip(ListBox2, "A wxListBox with single selection"), + + %% Create a wxChoice + Choice = wxChoice:new(Panel, 4, [{choices, Choices}]), + wxChoice:setToolTip(Choice, "A wxChoice"), + + %% Create a wxSpinCtrl with range between 0 and 100 + SpinCtrl = wxSpinCtrl:new(Panel, []), + wxSpinCtrl:setRange(SpinCtrl, 0, 100), + wxSpinCtrl:setToolTip(SpinCtrl, "A wxSpinCtrl with range from 0 to 100"), + + %% Create a wxComboBox and set the value to "Default value" + ComboBox = wxComboBox:new(Panel, 5, [{choices, Choices}]), + wxComboBox:setToolTip(ComboBox, "A wxComboBox"), + + + wxChoice:connect(Choice,command_choice_selected), + wxSpinCtrl:connect(SpinCtrl,command_spinctrl_updated), + wxComboBox:connect(ComboBox, command_combobox_selected), + + + %% Add to sizers + Options = [{border,4}, {flag, ?wxALL}], + wxSizer:add(Sizer, ListBox, Options), + wxSizer:add(Sizer, ListBox2, Options), + + wxSizer:add(ChoiceSizer, Choice, Options), + wxSizer:add(SpinSizer, SpinCtrl, Options), + wxSizer:add(Sizer3, ChoiceSizer, []), + wxSizer:add(Sizer3, SpinSizer, [{border, 4}, {flag, ?wxLEFT}]), + + wxSizer:add(ComboSizer, ComboBox, Options), + + wxSizer:add(ListBoxSizer, Sizer, Options), + wxSizer:add(MainSizer, ListBoxSizer, Options), + wxSizer:add(MainSizer, Sizer3, Options), + wxSizer:add(MainSizer, ComboSizer, Options), + + wxScrolledWindow:setScrollRate(Panel, 5, 5), + wxPanel:setSizer(Panel, MainSizer), + {Panel, #state{parent=Panel, config=Config, + list_box = ListBox}}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Async Events are handled in handle_event as in handle_info +handle_event(#wx{obj = ComboBox, + event = #wxCommand{type = command_combobox_selected}}, + State = #state{}) -> + Value = wxComboBox:getValue(ComboBox), + demo:format(State#state.config,"Selected wxComboBox ~p\n",[Value]), + {noreply, State}; +handle_event(#wx{event = #wxCommand{type = command_choice_selected, + cmdString = Value}}, + State = #state{}) -> + demo:format(State#state.config,"Selected wxChoice ~p\n",[Value]), + {noreply, State}; +handle_event(#wx{event = #wxSpin{type = command_spinctrl_updated, + commandInt = Int}}, + State = #state{}) -> + demo:format(State#state.config,"wxSpinCtrl changed to ~p\n",[Int]), + {noreply, State}; +handle_event(Ev = #wx{}, State = #state{}) -> + demo:format(State#state.config,"Got Event ~p\n",[Ev]), + {noreply, State}. + +%% Callbacks handled as normal gen_server callbacks +handle_info(Msg, State) -> + demo:format(State#state.config, "Got Info ~p\n",[Msg]), + {noreply, State}. + +handle_call(Msg, _From, State) -> + demo:format(State#state.config,"Got Call ~p\n",[Msg]), + {reply, {error,nyi}, State}. + +code_change(_, _, State) -> + {stop, ignore, State}. + +terminate(_Reason, _State) -> + ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Local functions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/lib/wx/examples/demo/ex_cursor.erl b/lib/wx/examples/demo/ex_cursor.erl new file mode 100644 index 0000000000..322bdcbb6c --- /dev/null +++ b/lib/wx/examples/demo/ex_cursor.erl @@ -0,0 +1,180 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-module(ex_cursor). + +-behaviour(wx_object). + +%% Client API +-export([start/1]). + +%% wx_object callbacks +-export([init/1, terminate/2, code_change/3, + handle_info/2, handle_call/3, handle_event/2]). + +-include_lib("wx/include/wx.hrl"). + +-record(state, + { + parent, + config, + cursors, + win + }). + +start(Config) -> + wx_object:start_link(?MODULE, Config, []). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +init(Config) -> + wx:batch(fun() -> do_init(Config) end). + +do_init(Config) -> + Parent = proplists:get_value(parent, Config), + Panel = wxScrolledWindow:new(Parent, []), + + %% Setup sizers + MainSizer = wxBoxSizer:new(?wxVERTICAL), + MiscSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "Misc"}]), + StaticBoxSizer = wxStaticBoxSizer:new(?wxHORIZONTAL, Panel, + [{label, "Test the cursor here"}]), + CursorSizer = wxBoxSizer:new(?wxHORIZONTAL), + + CursorLabels = [Cursor || {Cursor, _} <- cursors()], + StockCursors = wxRadioBox:new(Panel, ?wxID_ANY, "Stock cursors", + ?wxDefaultPosition, + ?wxDefaultSize, CursorLabels, + [{majorDim, 2}, + {style, ?wxHORIZONTAL}]), + + Fun = fun(Item, Int) -> + CursorId = proplists:get_value(Item, cursors()), + Cursor = wxCursor:new(CursorId), + case wxCursor:ok(Cursor) of + true -> + ok; + false -> + wxRadioBox:enable(StockCursors, Int, [{enable, false}]) + end, + Int+1 + end, + wx:foldl(Fun,0, CursorLabels), + + + + + Win = wxWindow:new(Panel, ?wxID_ANY, [{size, {300,300}}]), + + ToggleButton = wxToggleButton:new(Panel, ?wxID_ANY, "Begin busy cursor", []), + + %% Add to sizers + wxSizer:add(CursorSizer, StockCursors), + wxSizer:add(StaticBoxSizer, Win), + wxSizer:add(CursorSizer, StaticBoxSizer), + wxSizer:add(MiscSizer, ToggleButton), + + wxSizer:add(MainSizer, CursorSizer), + wxSizer:add(MainSizer, MiscSizer), + + wxToggleButton:connect(ToggleButton, command_togglebutton_clicked, []), + wxRadioBox:connect(StockCursors, command_radiobox_selected, []), + wxScrolledWindow:setScrollRate(Panel, 5,5), + wxPanel:setSizer(Panel, MainSizer), + {Panel, #state{parent=Panel, config=Config, + win = Win}}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Async Events are handled in handle_event as in handle_info +handle_event(#wx{event = #wxCommand{type = command_radiobox_selected, + cmdString = String}}, + State = #state{}) -> + wxWindow:refresh(State#state.parent), + CursorId = proplists:get_value(String, cursors()), + Cursor = wxCursor:new(CursorId), + wxWindow:setCursor(State#state.win, Cursor), + {noreply, State#state{}}; +handle_event(#wx{obj = ToggleButton, + event = #wxCommand{type = command_togglebutton_clicked, + commandInt = Int}}, + State = #state{}) -> + case Int of + 1 -> + wx_misc:beginBusyCursor(), + wxToggleButton:setLabel(ToggleButton, "End busy cursor"); + 0 -> + wx_misc:endBusyCursor(), + wxToggleButton:setLabel(ToggleButton, "Begin busy cursor") + end, + {noreply, State}; +handle_event(Ev = #wx{}, State = #state{}) -> + demo:format(State#state.config, "Got Event ~p\n", [Ev]), + {noreply, State}. + +%% Callbacks handled as normal gen_server callbacks +handle_info(Msg, State) -> + demo:format(State#state.config, "Got Info ~p\n", [Msg]), + {noreply, State}. + +handle_call(Msg, _From, State) -> + demo:format(State#state.config, "Got Call ~p\n", [Msg]), + {reply,{error, nyi}, State}. + +code_change(_, _, State) -> + {stop, ignore, State}. + +terminate(_Reason, _State) -> + case wx_misc:isBusy() of + true -> + wx_misc:endBusyCursor(); + false -> + ignore + end. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Local functions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +cursors() -> + [{"Arrow", ?wxCURSOR_ARROW}, + {"Right arrow", ?wxCURSOR_RIGHT_ARROW}, + {"Blank", ?wxCURSOR_BLANK}, + {"Bullseye", ?wxCURSOR_BULLSEYE}, + {"Char", ?wxCURSOR_CHAR}, + {"Cross", ?wxCURSOR_CROSS}, + {"Hand", ?wxCURSOR_HAND}, + {"I-beam", ?wxCURSOR_IBEAM}, + {"Left button", ?wxCURSOR_LEFT_BUTTON}, + {"Magnifier", ?wxCURSOR_MAGNIFIER}, + {"Middle button", ?wxCURSOR_MIDDLE_BUTTON}, + {"No entry", ?wxCURSOR_NO_ENTRY}, + {"Paint brush", ?wxCURSOR_PAINT_BRUSH}, + {"Pencil", ?wxCURSOR_PENCIL}, + {"Point left", ?wxCURSOR_POINT_LEFT}, + {"Point right", ?wxCURSOR_POINT_RIGHT}, + {"Question arrow", ?wxCURSOR_QUESTION_ARROW}, + {"Right button", ?wxCURSOR_RIGHT_BUTTON}, + {"Size NE-SW", ?wxCURSOR_SIZENESW}, + {"Size N-S", ?wxCURSOR_SIZENS}, + {"Size NW-SE", ?wxCURSOR_SIZENWSE}, + {"Size W-E", ?wxCURSOR_SIZEWE}, + {"Sizing", ?wxCURSOR_SIZING}, + {"Spraycan", ?wxCURSOR_SPRAYCAN}, + {"Wait", ?wxCURSOR_WAIT}, + {"Watch", ?wxCURSOR_WATCH}, + {"Arrow wait", ?wxCURSOR_ARROWWAIT}]. diff --git a/lib/wx/examples/demo/ex_dialogs.erl b/lib/wx/examples/demo/ex_dialogs.erl new file mode 100644 index 0000000000..020e9eeb14 --- /dev/null +++ b/lib/wx/examples/demo/ex_dialogs.erl @@ -0,0 +1,171 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-module(ex_dialogs). + +-behaviour(wx_object). + +%% Client API +-export([start/1]). + +%% wx_object callbacks +-export([init/1, terminate/2, code_change/3, + handle_info/2, handle_call/3, handle_event/2]). + +-include_lib("wx/include/wx.hrl"). + +-record(state, + { + parent, + config, + dialogs, + choices + }). + + +start(Config) -> + wx_object:start_link(?MODULE, Config, []). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +init(Config) -> + wx:batch(fun() -> do_init(Config) end). + +do_init(Config) -> + Parent = proplists:get_value(parent, Config), + Panel = wxScrolledWindow:new(Parent, []), + wxScrolledWindow:setScrollRate(Panel, 5, 5), + + %% Setup sizers + MainSizer = wxBoxSizer:new(?wxVERTICAL), + Sizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "Dialogs"}]), + + Buttons = + [wxButton:new(Panel, 1, [{label, "wxDirDialog"}]), + wxButton:new(Panel, 2, [{label, "wxFileDialog"}]), + wxButton:new(Panel, 3, [{label, "wxColourDialog"}]), + wxButton:new(Panel, 4, [{label, "wxMessageDialog"}]), + wxButton:new(Panel, 5, [{label, "wxTextEntryDialog"}]), + wxButton:new(Panel, 6, [{label, "wxSingleChoiceDialog"}]), + wxButton:new(Panel, 7, [{label, "wxMultiChoiceDialog"}]), + wxButton:new(Panel, 10, [{label, "wxFontDialog"}])], + + Choices = ["Orange","Banana", "Apple", "Lemon", "Pear", + "Carrot", "Potato", "Peach", "Tomato", "Grape", + "Pineapple", "Blueberry"], + Dialogs = [{wxDirDialog, [Panel, []]}, + {wxFileDialog, [Panel, []]}, + {wxColourDialog, [Panel, []]}, + {wxSingleChoiceDialog, [Panel, "wxSingleChoiceDialog\n" + "Feel free to pick one of " + "these items !", "Caption", + Choices]}, + {wxMultiChoiceDialog, [Panel, "wxMultiChoiceDialog\n" + "Feel free to pick one of " + "these items !", "Caption", + Choices]}, + {wxMessageDialog, [Panel, "This is a wxMessageDialog !"]}, + {wxTextEntryDialog, [Panel, "This is a wxTextEntryDialog !", + [{value, "Erlang is the best !"}]]}, + {wxFontDialog, [get_parent(Parent), wxFontData:new()]}], + + %% Add to sizers + Fun = fun(Button) -> + Label = list_to_atom(wxButton:getLabel(Button)), + wxSizer:add(Sizer, Button, [{border, 4}, {flag, ?wxALL bor ?wxEXPAND}]), + wxButton:connect(Button, command_button_clicked, [{userData, Label}]) + end, + wx:foreach(Fun, Buttons), + + wxSizer:add(MainSizer, Sizer), + + wxPanel:setSizer(Panel, MainSizer), + {Panel, #state{parent=Panel, config=Config, + dialogs = Dialogs, choices = Choices}}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Async Events are handled in handle_event as in handle_info +handle_event(#wx{event = #wxCommand{type = command_button_clicked}, + userData = Module}, + State = #state{dialogs = Dialogs, choices = Choices}) -> + Args = proplists:get_value(Module, Dialogs), + Dialog = apply(Module, new, Args), + + case Module:showModal(Dialog) of + ?wxID_OK -> + case Module of + wxColourDialog -> + Colour = wxColourData:getColour(Module:getColourData(Dialog)), + demo:format(State#state.config, "Colour: ~p\n", [Colour]); + wxSingleChoiceDialog -> + Selection = Module:getStringSelection(Dialog), + demo:format(State#state.config, "Selection: ~p\n", [Selection]); + wxTextEntryDialog -> + Value = Module:getValue(Dialog), + demo:format(State#state.config, "Value: ~p\n", [Value]); + wxFontDialog -> + Font = wxFontData:getChosenFont(Module:getFontData(Dialog)), + FontDesc = wxFont:getNativeFontInfoUserDesc(Font), + demo:format(State#state.config, + "Font: ~p\n", + [FontDesc]); + wxFileDialog -> + demo:format(State#state.config, "File path: ~p\n", [Module:getPath(Dialog)]); + wxDirDialog -> + demo:format(State#state.config, "Dir path: ~p\n", [Module:getPath(Dialog)]); + wxMultiChoiceDialog -> + Selected = [lists:nth(Num+1, Choices) || + Num <- Module:getSelections(Dialog)], + demo:format(State#state.config, "Selections: ~p\n", [Selected]); + wxMessageDialog -> + ok + end; + ?wxID_CANCEL -> cancel; + Any -> io:format("Any: ~p\n", [Any]) + end, + Module:destroy(Dialog), + {noreply, State}; +handle_event(Ev = #wx{}, State = #state{}) -> + demo:format(State#state.config, "Got Event ~p\n", [Ev]), + {noreply, State}. + +%% Callbacks handled as normal gen_server callbacks +handle_info(Msg, State) -> + demo:format(State#state.config, "Got Info ~p\n", [Msg]), + {noreply, State}. + +handle_call(Msg, _From, State) -> + demo:format(State#state.config, "Got Call ~p\n", [Msg]), + {reply,{error, nyi}, State}. + +code_change(_, _, State) -> + {stop, ignore, State}. + +terminate(_Reason, _State) -> + ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Local functions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +get_parent(Window) -> + Parent = wxWindow:getParent(Window), + case wx:is_null(Parent) of + false -> get_parent(Parent); + true -> Window + end. diff --git a/lib/wx/examples/demo/ex_frame_utils.erl b/lib/wx/examples/demo/ex_frame_utils.erl new file mode 100644 index 0000000000..3064c9f3b7 --- /dev/null +++ b/lib/wx/examples/demo/ex_frame_utils.erl @@ -0,0 +1,193 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-module(ex_frame_utils). + +-behaviour(wx_object). + +%% Client API +-export([start/1]). + +%% wx_object callbacks +-export([init/1, terminate/2, code_change/3, + handle_info/2, handle_call/3, handle_event/2]). + +-include_lib("wx/include/wx.hrl"). + +-record(state, + { + parent, + config + }). + +start(Config) -> + wx_object:start_link(?MODULE, Config, []). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +init(Config) -> + wx:batch(fun() -> do_init(Config) end). + +do_init(Config) -> + Parent = proplists:get_value(parent, Config), + Panel = wxPanel:new(Parent, []), + + %% Setup sizers + MainSizer = wxBoxSizer:new(?wxVERTICAL), + Sizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "Utilities"}]), + + Labels = [{"Open window",1}, {"Open wxMiniFrame",2}, {"Open erlang.org",3}], + Buttons = [wxButton:new(Panel, Id, [{label, L}])|| {L,Id} <- Labels], + + %% Add to sizers + [wxSizer:add(Sizer, Button) || Button <- Buttons], + wxPanel:connect(Panel, command_button_clicked), + wxSizer:add(MainSizer, Sizer), + wxPanel:setSizer(Panel, MainSizer), + {Panel, #state{parent=Panel, config=Config}}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Async Events are handled in handle_event as in handle_info +handle_event(#wx{id = Id, + event = #wxCommand{type = command_menu_selected}}, + State = #state{}) -> + case Id of + ?wxID_NEW -> demo:format(State#state.config, "New\n", []); + ?wxID_OPEN -> demo:format(State#state.config, "Open\n", []); + ?wxID_COPY -> demo:format(State#state.config, "Copy\n", []); + ?wxID_PASTE -> demo:format(State#state.config, "Paste\n", []); + ?wxID_HELP -> + wx_misc:launchDefaultBrowser("http://erlang.org/doc/apps/wx/part_frame.html"); + _ -> ignore + end, + {noreply, State}; +handle_event(#wx{id = Id, + event = #wxCommand{type = command_button_clicked}}, + State = #state{}) -> + case Id of + 1 -> new_win(State#state.parent); + 2 -> new_mini_frame(State#state.parent); + 3 -> wx_misc:launchDefaultBrowser("http://erlang.org/"); + _ -> ignore + end, + {noreply, State}; +handle_event(#wx{userData = StatusBar, + event = #wxMouse{type = motion, x = X, y = Y}}, + State) -> + wxStatusBar:setStatusText(StatusBar, io_lib:format("Mouse position: ~p", [{X,Y}]), + [{number, 1}]), + {noreply, State}. + +%% Callbacks handled as normal gen_server callbacks +handle_info(Msg, State) -> + demo:format(State#state.config, "Got Info ~p\n", [Msg]), + {noreply, State}. + +handle_call(Msg, _From, State) -> + demo:format(State#state.config, "Got Call ~p\n", [Msg]), + {reply,{error, nyi}, State}. + +code_change(_, _, State) -> + {stop, ignore, State}. + +terminate(_Reason, _State) -> + ok. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Local functions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +new_win(Panel) -> + Frame = wxFrame:new(Panel, ?wxID_ANY, "Utilities", [{style, + ?wxCAPTION bor + ?wxCLIP_CHILDREN bor + ?wxCLOSE_BOX bor + ?wxFRAME_FLOAT_ON_PARENT bor + %%?wxFRAME_NO_TASKBAR bor + ?wxMAXIMIZE_BOX bor + ?wxMINIMIZE_BOX bor + ?wxRESIZE_BORDER bor + %%?wxSTAY_ON_TOP bor + ?wxSYSTEM_MENU + }]), + + %% Setup wxMenuBar + MB = wxMenuBar:new(), + File = wxMenu:new([]), + Help = wxMenu:new([]), + Mbar = wxMenu:new([]), + wxMenu:append(File, ?wxID_NEW, "New"), + wxMenu:append(File, ?wxID_OPEN, "Open"), + wxMenu:appendSeparator(File), + wxMenu:append(File, ?wxID_EXIT, "&Quit"), + wxMenu:append(Help, ?wxID_HELP, "Help"), + wxMenu:append(Mbar, ?wxID_ANY, "Test item 1"), + wxMenu:append(Mbar, ?wxID_ANY, "Test item 2"), + wxMenu:append(Mbar, ?wxID_ANY, "Test item 3"), + + wxMenuBar:append(MB, File, "&File"), + wxMenuBar:append(MB, Help, "&Help"), + wxMenuBar:append(MB, Mbar, "This is a menu bar"), + wxFrame:setMenuBar(Frame,MB), + + %% Setup wxStatusBar + StatusBar = wxFrame:createStatusBar(Frame, []), + wxStatusBar:setFieldsCount(StatusBar, 2), + wxStatusBar:setStatusText(StatusBar, "This is a status bar", [{number, 0}]), + + %% Setup wxToolBar + ToolBar = wxFrame:createToolBar(Frame, []), + wxToolBar:addTool(ToolBar, ?wxID_NEW, "New", wxArtProvider:getBitmap("wxART_NEW"), + [{shortHelp, "New"}]), + wxToolBar:setToolLongHelp(ToolBar, ?wxID_NEW, "This is long help for 'New'"), + wxToolBar:addTool(ToolBar, ?wxID_OPEN, "Open", wxArtProvider:getBitmap("wxART_FILE_OPEN"), + [{shortHelp, "Open"}]), + wxToolBar:setToolLongHelp(ToolBar, ?wxID_OPEN, "This is long help for 'Open'"), + wxToolBar:addSeparator(ToolBar), + wxToolBar:addTool(ToolBar, ?wxID_COPY, "Copy", wxArtProvider:getBitmap("wxART_COPY"), + [{shortHelp, "Copy"}]), + wxToolBar:setToolLongHelp(ToolBar, ?wxID_COPY, "This is long help for 'Copy'"), + wxToolBar:addTool(ToolBar, ?wxID_PASTE, "Paste", wxArtProvider:getBitmap("wxART_PASTE"), + [{shortHelp, "Paste"}]), + wxToolBar:setToolLongHelp(ToolBar, ?wxID_PASTE, "This is long help for 'Paste'"), + + wxToolBar:addControl(ToolBar,wxStaticText:new(ToolBar, 5, "This is a tool bar")), + + + wxToolBar:realize(ToolBar), + wxFrame:setToolBar(Frame,ToolBar), + + wxFrame:connect(Frame, motion, [{userData, StatusBar}]), + wxFrame:connect(Frame, command_menu_selected, []), + wxFrame:center(Frame), + wxFrame:show(Frame). + + +new_mini_frame(Parent) -> + MiniFrame = wxMiniFrame:new(Parent, ?wxID_ANY, "wxMiniFrame", [{style, + ?wxDEFAULT_FRAME_STYLE bor + ?wxFRAME_FLOAT_ON_PARENT}]), + Panel = wxPanel:new(MiniFrame, []), + + Text = "This is a wxMiniFrame", + + wxStaticText:new(Panel, ?wxID_ANY, Text, [{style, ?wxALIGN_CENTER}]), + wxMiniFrame:setSize(MiniFrame, {200,200}), + wxMiniFrame:center(MiniFrame), + wxMiniFrame:show(MiniFrame). + + diff --git a/lib/wx/examples/demo/ex_gauge.erl b/lib/wx/examples/demo/ex_gauge.erl new file mode 100644 index 0000000000..d30c3fea58 --- /dev/null +++ b/lib/wx/examples/demo/ex_gauge.erl @@ -0,0 +1,208 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-module(ex_gauge). + +-behaviour(wx_object). + +-include_lib("wx/include/wx.hrl"). + +-export([start/1, init/1, terminate/2, code_change/3, + handle_info/2, handle_call/3, handle_event/2]). + +-record(gauge, {obj, + value, + timer, + range + }). + +-record(state, + { + parent, + config, + normal_gauge, + undeterminate_gauge, + simulate_button, + simulate_undet_button + }). + +-define(ID_START_STOP, 1). +-define(ID_START_STOP_UNDET, 2). +-define(SET_VALUE, 3). +-define(VERTICAL, 4). + +start(Config) -> + wx_object:start_link(?MODULE, Config, []). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +init(Config) -> + wx:batch(fun() -> do_init(Config) end). +do_init(Config) -> + Parent = proplists:get_value(parent, Config), + Panel = wxPanel:new(Parent, []), + + %% Setup sizers + MainSizer = wxBoxSizer:new(?wxVERTICAL), + AlignSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "wxGauge"}]), + + %% Create two horizontal gauges with range 0-100 + Range = 100, + NormalGauge = wxGauge:new(Panel, 1, Range, [{size, {200, -1}}, + {style, ?wxGA_HORIZONTAL}]), + UndetGauge = wxGauge:new(Panel, 2, Range, [{size, {200, -1}}, + {style, ?wxGA_HORIZONTAL}]), + + %% Add to sizers + wxSizer:add(AlignSizer, NormalGauge, [{flag, ?wxEXPAND}]), + wxSizer:add(AlignSizer, UndetGauge, [{flag, ?wxEXPAND}]), + {OptSizer, SimulateButton, SimulateUndetermButton} + = create_option_sizer(Panel), + + wxSizer:add(MainSizer, AlignSizer, [{flag, ?wxEXPAND}]), + wxSizer:add(MainSizer, OptSizer, []), + + wxWindow:connect(Panel, command_togglebutton_clicked), + wxWindow:connect(Panel, command_button_clicked), + + wxPanel:setSizer(Panel, MainSizer), + {Panel, #state{parent=Panel, config=Config, + normal_gauge = #gauge{obj=NormalGauge, value = 0, + range = Range}, + undeterminate_gauge = #gauge{obj=UndetGauge, value = 0, + range = Range}, + simulate_button = SimulateButton, + simulate_undet_button = SimulateUndetermButton}}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Callbacks handled as normal gen_server callbacks +handle_info(tick, State=#state{normal_gauge = Gauge=#gauge{obj = Obj, + value = Value, + timer = Timer, + range = Range}, + simulate_button = Button}) -> + Timer2 = + if Value >= Range -> + wxToggleButton:setValue(Button, false), + wxToggleButton:setLabel(Button, "Simulate load"), + wxGauge:setValue(Obj, Range), + demo:format(State#state.config, "Simulation finished.\n", []), + Timer; + true -> + simulate_load(Obj, Value) + + end, + {noreply, State#state{normal_gauge = Gauge#gauge{value = Value+5, + timer = Timer2}}}; +handle_info(pulse, State=#state{undeterminate_gauge = Gauge=#gauge{obj = Obj}}) -> + wxGauge:pulse(Obj), + Timer = erlang:send_after(300, self(), pulse), + {noreply, State#state{undeterminate_gauge = Gauge#gauge{timer = Timer}}}. + +handle_call(Msg, _From, State) -> + demo:format(State#state.config,"Got Call ~p\n",[Msg]), + {reply,ok, State}. + +%% Async Events are handled in handle_event as in handle_info +handle_event(#wx{id = ?ID_START_STOP, + event = #wxCommand{type = command_togglebutton_clicked, + commandInt = Int}}, + State = #state{normal_gauge = #gauge{obj=Gauge, + value = Value, + timer = Timer}, + simulate_button = Button}) -> + case Int of + 1 -> + wxToggleButton:setLabel(Button, "Stop simulation"), + simulate_load(Gauge, Value); + 0 -> + erlang:cancel_timer(Timer), + wxToggleButton:setLabel(Button, "Simulate load"), + ok + end, + {noreply, State}; +handle_event(#wx{id = ?ID_START_STOP_UNDET, + event = #wxCommand{type = command_togglebutton_clicked, + commandInt = Int}}, + State = #state{undeterminate_gauge = G = #gauge{obj=Gauge, + timer = Timer}, + simulate_undet_button = Button}) -> + Timer2 = + case Int of + 1 -> + wxToggleButton:setLabel(Button, "Stop simulation"), + wxGauge:pulse(Gauge), + erlang:send_after(300, self(), pulse); + 0 -> + wxToggleButton:setLabel(Button, "Simulate undeterminate load"), + reset(G), + undefined + end, + case Timer of + undefined -> ok; + _ -> erlang:cancel_timer(Timer) + end, + {noreply, State#state{undeterminate_gauge = G#gauge{timer = Timer2}}}; +handle_event(#wx{id = ?wxID_CLEAR, + event = #wxCommand{type = command_button_clicked}}, + State = #state{normal_gauge = Gauge, + undeterminate_gauge = Gauge2}) -> + reset(Gauge), + reset(Gauge2), + {noreply, State#state{normal_gauge = Gauge#gauge{value = 0}}}; +handle_event(Ev = #wx{}, State = #state{}) -> + demo:format(State#state.config,"Got Event ~p\n",[Ev]), + {noreply, State}. + +code_change(_, _, State) -> + {stop, ignore, State}. + +terminate(_Reason, _State) -> + ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Local functions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +simulate_load(Gauge, Value) -> + wxGauge:setValue(Gauge, Value), + erlang:send_after(300, self(), tick). + +reset(#gauge{obj = Gauge}) -> + wxGauge:setValue(Gauge, 0). + + +create_option_sizer(Panel) -> + OptSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "Options"}]), + + SimulateButton = wxToggleButton:new(Panel, ?ID_START_STOP, "Simulate load", + [{size, {200, 35}}]), + SimulateUndetermButton = wxToggleButton:new(Panel, ?ID_START_STOP_UNDET, + "Simulate Undeterminate load", + [{size, {200, 35}}]), + ClearButton = wxButton:new(Panel, ?wxID_CLEAR, + [{size, {200, 35}}]), + + wxSizer:add(OptSizer, SimulateButton), + wxSizer:add(OptSizer, SimulateUndetermButton), + wxSizer:add(OptSizer, ClearButton), + + wxWindow:connect(Panel, command_checkbox_clicked), + + {OptSizer, SimulateButton, SimulateUndetermButton}. diff --git a/lib/wx/examples/demo/ex_gl.erl b/lib/wx/examples/demo/ex_gl.erl new file mode 100644 index 0000000000..53f1eda847 --- /dev/null +++ b/lib/wx/examples/demo/ex_gl.erl @@ -0,0 +1,409 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-module(ex_gl). + +-behaviour(wx_object). + +-export([init/1, code_change/3, handle_info/2, handle_event/2, + handle_call/3, terminate/2, + start/1]). + +-include_lib("wx/include/wx.hrl"). +-include_lib("wx/include/gl.hrl"). +-include_lib("wx/include/glu.hrl"). + +-record(state, + { + parent, + config, + gl, + canvas, + timer, + time + }). + +-record(gl, {win, data, deg, mat, alpha, text, font, brush, clock, sphere}). + +-record(texture, {tid, w, h, minx, miny, maxx, maxy}). + +start(Config) -> + wx_object:start_link(?MODULE, Config, []). + +-define(PAD, fun(Int) -> string:right(integer_to_list(Int), 2, $0) end). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +init(Config) -> + wx:batch(fun() -> do_init(Config) end). + +do_init(Config) -> + Parent = proplists:get_value(parent, Config), + Panel = wxPanel:new(Parent, []), + + %% Setup sizer + Sizer = wxStaticBoxSizer:new(?wxHORIZONTAL, Panel, [{label, "wxGLCanvas"}]), + + Opts = [{size, {300,300}}, {style, ?wxSUNKEN_BORDER}], + GLAttrib = [{attribList, [?WX_GL_RGBA, + ?WX_GL_DOUBLEBUFFER, + ?WX_GL_MIN_RED,8, + ?WX_GL_MIN_GREEN,8, + ?WX_GL_MIN_BLUE,8, + ?WX_GL_DEPTH_SIZE,24,0]}], + Canvas = wxGLCanvas:new(Panel,Opts ++ GLAttrib), + wxGLCanvas:connect(Canvas, size), + + wxGLCanvas:setCurrent(Canvas), + Image = wxImage:scale(wxImage:new("image.jpg"), 128,128), + GL = setup_gl(Canvas,Image), + Timer = timer:send_interval(20, self(), update), + + %% Add to sizers + wxSizer:add(Sizer, Canvas, [{flag, ?wxEXPAND},{proportion, 1}]), + wxWindow:setSizer(Panel,Sizer), + wxSizer:layout(Sizer), + {Panel, #state{parent = Panel, config = Config, + canvas = Canvas, + gl = GL, timer = Timer}}. + +%% Event handling +handle_event(#wx{event = #wxSize{size = {W,H}}}, State) -> + case W =:= 0 orelse H =:= 0 of + true -> skip; + _ -> + gl:viewport(0,0,W,H), + gl:matrixMode(?GL_PROJECTION), + gl:loadIdentity(), + gl:ortho( -2.0, 2.0, -2.0*H/W, 2.0*H/W, -20.0, 20.0), + gl:matrixMode(?GL_MODELVIEW), + gl:loadIdentity() + end, + {noreply, State}. + +handle_info(update, State) -> + S1 = update_rotation(State), + GL = S1#state.gl, + S2 = if S1#state.time > State#state.time -> + gl:deleteTextures([(GL#gl.clock)#texture.tid]), + {Hour,Min,Sec} = S1#state.time, + Clock = load_texture_by_string(GL#gl.font, GL#gl.brush, {40,40,40}, + [?PAD(Hour), $:, ?PAD(Min), $:, ?PAD(Sec)], false), + S1#state{gl = GL#gl{clock = Clock}}; + true -> + S1 + end, + wx:batch(fun() -> drawBox(S2#state.gl) end), + {noreply, S2}; +handle_info(stop, State) -> + timer:cancel(State#state.timer), + catch wxGLCanvas:destroy(State#state.canvas), + {stop, normal, State}. + +handle_call(Msg, _From, State) -> + io:format("Got Call ~p~n",[Msg]), + {reply,ok,State}. + +code_change(_, _, State) -> + {stop, not_yet_implemented, State}. + +terminate(_Reason, State) -> + catch wxGLCanvas:destroy(State#state.canvas), + timer:cancel(State#state.timer), + timer:sleep(300). + + + +-define(VS, {{-0.5, -0.5, -0.5}, %1 + { 0.5, -0.5, -0.5}, %2 + { 0.5, 0.5, -0.5}, + {-0.5, 0.5, -0.5}, %4 + {-0.5, 0.5, 0.5}, + { 0.5, 0.5, 0.5}, %6 + { 0.5, -0.5, 0.5}, + {-0.5, -0.5, 0.5}}).%8 + +-define(FACES, + %% Faces Normal U-axis V-axis + [{{1,2,3,4},{0,0,-1},{-1,0,0}, {0,1,0}}, % + {{8,1,4,5},{-1,0,0},{0,0,1}, {0,1,0}}, % + {{2,7,6,3},{1,0,0}, {0,0,-1}, {0,1,0}}, % + {{7,8,5,6},{0,0,1}, {1,0,0}, {0,1,0}}, % + {{4,3,6,5},{0,1,0}, {-1,0,0}, {0,0,1}}, % + {{1,2,7,8},{0,-1,0},{1,0,0}, {0,0,1}}]). + +-define(COLORS,{{ 0.0, 0.0, 0.0}, + { 1.0, 0.0, 0.0}, + { 1.0, 1.0, 0.0}, + { 0.0, 1.0, 0.0}, + { 0.0, 1.0, 1.0}, + { 1.0, 1.0, 1.0}, + { 1.0, 0.0, 1.0}, + { 0.0, 0.0, 1.0}}). + + +update_rotation(S=#state{gl=GL=#gl{deg=Rot}}) -> + {_, Time} = calendar:local_time(), + S#state{gl=GL#gl{deg = Rot + 1.0}, time = Time}. + +%% Needs to setup opengl after window is shown... +%% GL context is created when shown first time. +setup_gl(Win, Image) -> + {W,H} = wxWindow:getClientSize(Win), + gl:viewport(0,0,W,H), + gl:matrixMode(?GL_PROJECTION), + gl:loadIdentity(), + gl:ortho( -2.0, 2.0, -2.0*H/W, 2.0*H/W, -20.0, 20.0), + gl:matrixMode(?GL_MODELVIEW), + gl:loadIdentity(), + gl:enable(?GL_DEPTH_TEST), + gl:depthFunc(?GL_LESS), + gl:clearColor(1.0,1.0,1.0,1.0), + MatTexture = load_texture_by_image(Image), + ImgTexture = load_texture_by_image( + wxImage:new("erlang.png")), + Font = wxFont:new(32, ?wxFONTFAMILY_DEFAULT, ?wxFONTSTYLE_NORMAL, ?wxFONTWEIGHT_BOLD), + Brush = wxBrush:new({0,0,0}), + StrTexture = load_texture_by_string(Font, Brush, {40,40,40}, "Text from wxFont", true), + {_, {Hour,Min,Sec}} = calendar:local_time(), + Clock = load_texture_by_string(Font, Brush, {40, 40, 40}, + [?PAD(Hour), $:, ?PAD(Min), $:, ?PAD(Sec)], false), + Sphere = glu:newQuadric(), + gl:enable(?GL_TEXTURE_2D), + #gl{win=Win,data={?FACES,?VS,?COLORS},deg=0.0, + mat=MatTexture, alpha=ImgTexture, text=StrTexture, font = Font, + brush = Brush, clock = Clock, sphere = Sphere}. + +drawBox(#gl{win=Win,deg=Deg,data={Fs,Vs,Colors},mat=MatT,alpha=ImgA, + text=Text, clock = Clock, sphere=Sphere}) -> + gl:matrixMode(?GL_MODELVIEW), + gl:loadIdentity(), + gl:pushMatrix(), + gl:translatef(0,0.5,0), + gl:rotatef(Deg, 1.0, 1.0, 1.0), + gl:clear(?GL_COLOR_BUFFER_BIT bor ?GL_DEPTH_BUFFER_BIT), + gl:bindTexture(?GL_TEXTURE_2D, MatT#texture.tid), + gl:disable(?GL_BLEND), + gl:texEnvf(?GL_TEXTURE_ENV, ?GL_TEXTURE_ENV_MODE, ?GL_MODULATE), + gl:disable(?GL_CULL_FACE), + gl:'begin'(?GL_QUADS), + wx:foreach(fun(Face) -> drawFace(Face,Vs,Colors) end, Fs), + gl:'end'(), + gl:popMatrix(), + + gl:texEnvf(?GL_TEXTURE_ENV, ?GL_TEXTURE_ENV_MODE, ?GL_REPLACE), + + enter_2d_mode(Win), + {W,H} = wxWindow:getClientSize(Win), + Move = abs(90 - (trunc(Deg) rem 180)), + draw_texture((W div 2) - 50, (H div 2)-130+Move, Clock), + draw_texture((W div 2) - 80, (H div 2)-Move, ImgA), + leave_2d_mode(), + + gl:pushMatrix(), + gl:enable(?GL_CULL_FACE), + gl:enable(?GL_BLEND), + gl:blendFunc(?GL_SRC_ALPHA, ?GL_ONE_MINUS_SRC_ALPHA), + gl:translatef(0,-0.8,0), + gl:bindTexture(?GL_TEXTURE_2D, Text#texture.tid), + glu:quadricTexture(Sphere, ?GLU_TRUE), + glu:quadricNormals(Sphere, ?GLU_SMOOTH), + glu:quadricDrawStyle(Sphere, ?GLU_FILL), + glu:quadricOrientation(Sphere, ?GLU_OUTSIDE), + %%gl:scalef(2.0, 0.5, 1.0), + gl:rotatef(-90, 1.0, 0.0, 0.0), + gl:rotatef(-Deg, 0.0, 0.0, 1.0), + glu:sphere(Sphere, 0.8, 50,40), + gl:popMatrix(), + + wxGLCanvas:swapBuffers(Win). + +drawFace({{V1,V2,V3,V4},N,_Ut,_Vt}, Cube, Colors) -> + gl:normal3fv(N), + gl:color3fv(element(V1, Colors)), + gl:texCoord2f(0.0, 0.0), gl:vertex3fv(element(V1, Cube)), + gl:color3fv(element(V2, Colors)), + gl:texCoord2f(1.0, 0.0), gl:vertex3fv(element(V2, Cube)), + gl:color3fv(element(V3, Colors)), + gl:texCoord2f(1.0, 1.0), gl:vertex3fv(element(V3, Cube)), + gl:color3fv(element(V4, Colors)), + gl:texCoord2f(0.0, 1.0), gl:vertex3fv(element(V4, Cube)). + + +draw_texture(X, Y, #texture{tid = TId, w = W, h = H, + miny = MinY, minx = MinX, + maxx = MaxX, maxy = MaxY}) -> + gl:bindTexture(?GL_TEXTURE_2D, TId), + gl:'begin'(?GL_TRIANGLE_STRIP), + gl:texCoord2f(MinX, MinY), gl:vertex2i(X, Y ), + gl:texCoord2f(MaxX, MinY), gl:vertex2i(X+W div 2, Y ), + gl:texCoord2f(MinX, MaxY), gl:vertex2i(X, Y+H div 2), + gl:texCoord2f(MaxX, MaxY), gl:vertex2i(X+W div 2, Y+H div 2), + gl:'end'(). + +load_texture_by_image(Image) -> + ImgW = wxImage:getWidth(Image), + ImgH = wxImage:getHeight(Image), + W = get_power_of_two_roof(ImgW), + H = get_power_of_two_roof(ImgH), + Data = get_data_for_use_with_teximage2d(Image), + %% Create an OpenGL texture for the image + [TId] = gl:genTextures(1), + gl:bindTexture(?GL_TEXTURE_2D, TId), + gl:texParameteri(?GL_TEXTURE_2D, ?GL_TEXTURE_MAG_FILTER, ?GL_NEAREST), + gl:texParameteri(?GL_TEXTURE_2D, ?GL_TEXTURE_MIN_FILTER, ?GL_NEAREST), + Format = case wxImage:hasAlpha(Image) of + true -> ?GL_RGBA; + false -> ?GL_RGB + end, + gl:texImage2D(?GL_TEXTURE_2D, 0, + Format, W, H, 0, + Format, ?GL_UNSIGNED_BYTE, Data), + #texture{tid = TId, w = ImgW, h = ImgH, + minx = 0, miny = 0, maxx = ImgW / W, maxy = ImgH / H}. + + +%% This algorithm (based on http://d0t.dbclan.de/snippets/gltext.html) +%% prints a string to a bitmap and loads that onto an opengl texture. +%% Comments for the createTexture function: +%% +%% "Creates a texture from the settings saved in TextElement, to be +%% able to use normal system fonts conviently a wx.MemoryDC is +%% used to draw on a wx.Bitmap. As wxwidgets device contexts don't +%% support alpha at all it is necessary to apply a little hack to +%% preserve antialiasing without sticking to a fixed background +%% color: +%% +%% We draw the bmp in b/w mode so we can use its data as a alpha +%% channel for a solid color bitmap which after GL_ALPHA_TEST and +%% GL_BLEND will show a nicely antialiased text on any surface. +%% +%% To access the raw pixel data the bmp gets converted to a +%% wx.Image. Now we just have to merge our foreground color with +%% the alpha data we just created and push it all into a OpenGL +%% texture and we are DONE *inhalesdelpy*" +load_texture_by_string(Font, Brush, Color, String, Flip) -> + TmpBmp = wxBitmap:new(200, 200), + Tmp = wxMemoryDC:new(TmpBmp), + wxMemoryDC:setFont(Tmp, Font), + {StrW, StrH} = wxDC:getTextExtent(Tmp, String), + wxMemoryDC:destroy(Tmp), + wxBitmap:destroy(TmpBmp), + + W = get_power_of_two_roof(StrW), + H = get_power_of_two_roof(StrH), + + Bmp = wxBitmap:new(W, H), + DC = wxMemoryDC:new(Bmp), + wxMemoryDC:setFont(DC, Font), + wxMemoryDC:setBackground(DC, Brush), + wxMemoryDC:clear(DC), + wxMemoryDC:setTextForeground(DC, {255, 255, 255}), + wxMemoryDC:drawText(DC, String, {0, 0}), + + Img0 = wxBitmap:convertToImage(Bmp), + case Flip of + true -> + Img = wxImage:mirror(Img0, [{horizontally, false}]), + wxImage:destroy(Img0), + Img; + false -> + Img = Img0 + end, + + Alpha = wxImage:getData(Img), + Data = colourize_image(Alpha, Color), + wxImage:destroy(Img), + wxBitmap:destroy(Bmp), + wxMemoryDC:destroy(DC), + + [TId] = gl:genTextures(1), + gl:bindTexture(?GL_TEXTURE_2D, TId), + gl:texParameteri(?GL_TEXTURE_2D, ?GL_TEXTURE_MAG_FILTER, ?GL_LINEAR), + gl:texParameteri(?GL_TEXTURE_2D, ?GL_TEXTURE_MIN_FILTER, ?GL_LINEAR), + gl:texEnvf(?GL_TEXTURE_ENV, ?GL_TEXTURE_ENV_MODE, ?GL_REPLACE), + %%gl:pixelStorei(?GL_UNPACK_ROW_LENGTH, 0), + %%gl:pixelStorei(?GL_UNPACK_ALIGNMENT, 2), + gl:texImage2D(?GL_TEXTURE_2D, 0, ?GL_RGBA, + W, H, 0, ?GL_RGBA, ?GL_UNSIGNED_BYTE, Data), + #texture{tid = TId, w = StrW, h = StrH, + minx = 0, miny = 0, maxx = StrW / W, maxy = StrH / H}. + +colourize_image(Alpha, {R,G,B}) -> + << <> || <> <= 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) -> + <> + end, + [{R,G,B} || <> <= RGB], + [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 @@ + + +

Erlang is the best.

+
    +
  • Text1
  • +
  • Text2
  • +
+

You can insert whatever HTML you want... although wxHtmlWindow doesn't support css or scripts

+
+ + + + + + + + + + +
Thisis
atable
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Top
+
+ + Copyright © 2009 Ericsson AB + +
+ \ No newline at end of file diff --git a/lib/wx/examples/demo/ex_listCtrl.erl b/lib/wx/examples/demo/ex_listCtrl.erl new file mode 100644 index 0000000000..c574c7247a --- /dev/null +++ b/lib/wx/examples/demo/ex_listCtrl.erl @@ -0,0 +1,148 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-module(ex_listCtrl). + +-include_lib("wx/include/wx.hrl"). + +-behaviour(wx_object). + +-export([start/1, init/1, terminate/2, code_change/3, + handle_info/2, handle_call/3, handle_event/2]). + +-record(state, + { + parent, + config, + notebook + }). + +start(Config) -> + wx_object:start_link(?MODULE, Config, []). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +init(Config) -> + wx:batch(fun() -> do_init(Config) end). + +do_init(Config) -> + Parent = proplists:get_value(parent, Config), + Panel = wxPanel:new(Parent, []), + + %% Setup sizers + MainSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "wxListCtrl"}]), + + Notebook = wxNotebook:new(Panel, 1, [{style, ?wxBK_DEFAULT}]), + + + ListCtrl1 = wxListCtrl:new(Notebook, [{style, ?wxLC_LIST}]), + [wxListCtrl:insertItem(ListCtrl1, Int, "Item "++integer_to_list(Int)) || + Int <- lists:seq(0,50)], + ListCtrl2 = create_list_ctrl(Notebook, [{style, ?wxLC_REPORT bor + ?wxLC_SINGLE_SEL}]), + IL = wxImageList:new(16,16), + wxImageList:add(IL, wxArtProvider:getBitmap("wxART_COPY", [{size, {16,16}}])), + wxImageList:add(IL, wxArtProvider:getBitmap("wxART_MISSING_IMAGE", [{size, {16,16}}])), + wxImageList:add(IL, wxArtProvider:getBitmap("wxART_TICK_MARK", [{size, {16,16}}])), + wxImageList:add(IL, wxArtProvider:getBitmap("wxART_CROSS_MARK", [{size, {16,16}}])), + wxListCtrl:assignImageList(ListCtrl2, IL, ?wxIMAGE_LIST_SMALL), + Fun = + fun(Item) -> + case Item rem 4 of + 0 -> + wxListCtrl:setItemBackgroundColour(ListCtrl2, Item, {240,240,240,255}), + wxListCtrl:setItemImage(ListCtrl2, Item, 0); + 1 -> wxListCtrl:setItemImage(ListCtrl2, Item, 1); + 2 -> wxListCtrl:setItemImage(ListCtrl2, Item, 2), + wxListCtrl:setItemBackgroundColour(ListCtrl2, Item, {240,240,240,255}); + _ -> wxListCtrl:setItemImage(ListCtrl2, Item, 3) + end + end, + wx:foreach(Fun, lists:seq(0,50)), + + ListCtrl3 = create_list_ctrl(Notebook, [{style, ?wxLC_REPORT}]), + wxListCtrl:setTextColour(ListCtrl3, ?wxBLUE), + wxListCtrl:setItemBackgroundColour(ListCtrl3,5,?wxRED), + wxListCtrl:setItemBackgroundColour(ListCtrl3,3,?wxGREEN), + wxListCtrl:setItemBackgroundColour(ListCtrl3,0,?wxCYAN), + + wxListCtrl:connect(ListCtrl1, command_list_item_selected, []), + wxListCtrl:connect(ListCtrl2, command_list_item_selected, []), + wxListCtrl:connect(ListCtrl3, command_list_item_selected, []), + + %% Add to sizers + wxNotebook:addPage(Notebook, ListCtrl1, "List", []), + wxNotebook:addPage(Notebook, ListCtrl2, "Report", []), + wxNotebook:addPage(Notebook, ListCtrl3, "Colored multiselect", []), + + wxSizer:add(MainSizer, Notebook, [{proportion, 1}, + {flag, ?wxEXPAND}]), + + wxPanel:setSizer(Panel, MainSizer), + {Panel, #state{parent=Panel, config=Config, + notebook = Notebook}}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Async Events are handled in handle_event as in handle_info +handle_event(#wx{obj = _ListCtrl, + event = #wxList{itemIndex = Item}}, + State = #state{}) -> + demo:format(State#state.config,"Item ~p selected.\n",[Item]), + {noreply,State}. + +%% Callbacks handled as normal gen_server callbacks +handle_info(Msg, State) -> + demo:format(State#state.config, "Got Info ~p\n",[Msg]), + {noreply,State}. + +handle_call(Msg, _From, State) -> + demo:format(State#state.config,"Got Call ~p\n",[Msg]), + {reply,ok,State}. + +code_change(_, _, State) -> + {stop, ignore, State}. + +terminate(_Reason, _State) -> + ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%% Local functions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +-define(FIRST_COL, 0). +-define(SECOND_COL, 1). +-define(THIRD_COL, 2). + +create_list_ctrl(Win, Options) -> + ListCtrl = wxListCtrl:new(Win, Options), + wxListCtrl:insertColumn(ListCtrl, ?FIRST_COL, "First Col", []), + wxListCtrl:insertColumn(ListCtrl, ?SECOND_COL, "Second Col", []), + wxListCtrl:insertColumn(ListCtrl, ?THIRD_COL, "Third Col", []), + Fun = + fun(Int) -> + Name = integer_to_list(Int), + wxListCtrl:insertItem(ListCtrl, Int, ""), + wxListCtrl:setItem(ListCtrl, Int, ?FIRST_COL, "First "++Name), + wxListCtrl:setItem(ListCtrl, Int, ?SECOND_COL, "Second "++Name), + wxListCtrl:setItem(ListCtrl, Int, ?THIRD_COL, "Third "++Name) + end, + wx:foreach(Fun, lists:seq(0,50)), + + ListCtrl. + + diff --git a/lib/wx/examples/demo/ex_notebook.erl b/lib/wx/examples/demo/ex_notebook.erl new file mode 100644 index 0000000000..2e16ccfffa --- /dev/null +++ b/lib/wx/examples/demo/ex_notebook.erl @@ -0,0 +1,147 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-module(ex_notebook). + +-include_lib("wx/include/wx.hrl"). + +-behaviour(wx_object). + +-export([start/1, init/1, terminate/2, code_change/3, + handle_info/2, handle_call/3, handle_event/2]). + +-record(state, + { + parent, + config, + notebook + }). + +start(Config) -> + wx_object:start_link(?MODULE, Config, []). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +init(Config) -> + wx:batch(fun() -> do_init(Config) end). +do_init(Config) -> + Parent = proplists:get_value(parent, Config), + Panel = wxPanel:new(Parent, []), + + %% Setup sizers + MainSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "wxNotebook"}]), + + Notebook = wxNotebook:new(Panel, 1, [{style, ?wxBK_DEFAULT%, + %?wxBK_ALIGN_MASK, + %?wxBK_TOP, + %?wxBK_BOTTOM, + %?wxBK_LEFT, + %?wxBK_RIGHT, + %?wxNB_MULTILINE % windows only + }]), + + %% Make a wxImageList to be able to display icons in the tab field + IL = wxImageList:new(16,16), + wxImageList:add(IL, wxArtProvider:getBitmap("wxART_INFORMATION", [{size, {16,16}}])), + wxImageList:add(IL, wxArtProvider:getBitmap("wxART_MISSING_IMAGE", [{size, {16,16}}])), + wxNotebook:assignImageList(Notebook, IL), + + + + Win1 = wxPanel:new(Notebook, []), + wxPanel:setBackgroundColour(Win1, ?wxRED), + Win1Text = wxStaticText:new(Win1, ?wxID_ANY, "This is a red tab.", + [{pos, {50, 100}}]), + wxStaticText:setForegroundColour(Win1Text, ?wxGREEN), + Sizer1 = wxBoxSizer:new(?wxHORIZONTAL), + wxSizer:add(Sizer1, Win1Text), + wxPanel:setSizer(Win1, Sizer1), + wxNotebook:addPage(Notebook, Win1, "Red", []), + + Win2 = wxPanel:new(Notebook, []), + wxPanel:setBackgroundColour(Win2, ?wxBLUE), + Win2Text = wxStaticText:new(Win2, ?wxID_ANY, "This is a blue tab.", + [{pos, {50, 100}}]), + wxStaticText:setForegroundColour(Win2Text, {255,255,0,255}), + Sizer2 = wxBoxSizer:new(?wxHORIZONTAL), + wxSizer:add(Sizer2, Win2Text), + wxPanel:setSizer(Win2, Sizer2), + wxNotebook:addPage(Notebook, Win2, "Blue", []), + + Win3 = wxPanel:new(Notebook, []), + wxNotebook:addPage(Notebook, Win3, "No color", []), + wxNotebook:setPageImage(Notebook, 2, 1), + + Win4 = wxPanel:new(Notebook, []), + wxPanel:setBackgroundColour(Win4, ?wxBLACK), + Win4Text = wxStaticText:new(Win4, ?wxID_ANY, "This is a black tab.", + [{pos, {50, 100}}]), + wxStaticText:setForegroundColour(Win4Text, ?wxWHITE), + Sizer4 = wxBoxSizer:new(?wxHORIZONTAL), + wxSizer:add(Sizer4, Win4Text), + wxPanel:setSizer(Win4, Sizer4), + wxNotebook:addPage(Notebook, Win4, "Black", []), + + Win5 = wxPanel:new(Notebook, []), + wxNotebook:addPage(Notebook, Win5, "Tab with icon", []), + wxNotebook:setPageImage(Notebook, 4, 0), + + %% Add to sizers + wxSizer:add(MainSizer, Notebook, [{proportion, 1}, + {flag, ?wxEXPAND}]), + + wxNotebook:connect(Notebook, command_notebook_page_changed, + [{skip, true}]), % {skip, true} has to be set on windows + wxPanel:setSizer(Panel, MainSizer), + {Panel, #state{parent=Panel, config=Config, + notebook = Notebook}}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Async Events are handled in handle_event as in handle_info +handle_event(#wx{event = #wxNotebook{type = command_notebook_page_changed}}, + State = #state{notebook = Notebook}) -> + Selection = wxNotebook:getSelection(Notebook), + Title = wxNotebook:getPageText(Notebook, Selection), + demo:format(State#state.config,"You have selected the tab ~p\n",[Title]), + {noreply,State}; +handle_event(Ev = #wx{}, State = #state{}) -> + demo:format(State#state.config,"Got Event ~p\n",[Ev]), + {noreply,State}. + +%% Callbacks handled as normal gen_server callbacks +handle_info(Msg, State) -> + demo:format(State#state.config, "Got Info ~p\n",[Msg]), + {noreply,State}. + +handle_call(Msg, _From, State) -> + demo:format(State#state.config,"Got Call ~p\n",[Msg]), + {reply,ok,State}. + +code_change(_, _, State) -> + {stop, ignore, State}. + +terminate(_Reason, _State) -> + ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%% Local functions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + + diff --git a/lib/wx/examples/demo/ex_pickers.erl b/lib/wx/examples/demo/ex_pickers.erl new file mode 100644 index 0000000000..892c5b449d --- /dev/null +++ b/lib/wx/examples/demo/ex_pickers.erl @@ -0,0 +1,136 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-module(ex_pickers). + +-behaviour(wx_object). + +%% Client API +-export([start/1]). + +%% wx_object callbacks +-export([init/1, terminate/2, code_change/3, + handle_info/2, handle_call/3, handle_event/2]). + +-include_lib("wx/include/wx.hrl"). + +-record(state, + { + parent, + config + }). + +start(Config) -> + wx_object:start_link(?MODULE, Config, []). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +init(Config) -> + wx:batch(fun() -> do_init(Config) end). + +do_init(Config) -> + Parent = proplists:get_value(parent, Config), + Panel = wxPanel:new(Parent, []), + + %% Setup sizers + MainSizer = wxBoxSizer:new(?wxVERTICAL), + DirPickerSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "wxDirPickerCtrl"}]), + FilePickerSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "wxFilePickerCtrl"}]), + FontPickerSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "wxFontPickerCtrl"}]), + DatePickerSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "wxDatePickerCtrl"}]), + ColourPickerSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "wxColourPickerCtrl"}]), + + DirPicker = wxDirPickerCtrl:new(Panel, 1, [{path, "/"}]), + FilePicker = wxFilePickerCtrl:new(Panel, 2, [{path, "/"}]), + FontPicker = wxFontPickerCtrl:new(Panel, 3, []), + DatePicker = wxDatePickerCtrl:new(Panel, 4, []), + ColourPicker = wxColourPickerCtrl:new(Panel, 5, []), + + wxColourPickerCtrl:connect(ColourPicker, command_colourpicker_changed, []), + wxDirPickerCtrl:connect(DirPicker, command_dirpicker_changed, []), + wxFilePickerCtrl:connect(FilePicker, command_filepicker_changed, []), + wxFontPickerCtrl:connect(FontPicker, command_fontpicker_changed, []), + wxDatePickerCtrl:connect(DatePicker, date_changed, []), + + %% Add to sizers + PickerOptions = [{border, 4},{flag, ?wxALL bor ?wxEXPAND}], + wxSizer:add(DirPickerSizer, DirPicker, PickerOptions), + wxSizer:add(FilePickerSizer, FilePicker, PickerOptions), + wxSizer:add(FontPickerSizer, FontPicker, PickerOptions), + wxSizer:add(DatePickerSizer, DatePicker, PickerOptions), + wxSizer:add(ColourPickerSizer, ColourPicker, PickerOptions), + + SizerOptions = [{flag, ?wxEXPAND}], + wxSizer:add(MainSizer, DirPickerSizer, SizerOptions), + wxSizer:add(MainSizer, FilePickerSizer, SizerOptions), + wxSizer:add(MainSizer, FontPickerSizer, SizerOptions), + wxSizer:add(MainSizer, DatePickerSizer, SizerOptions), + wxSizer:add(MainSizer, ColourPickerSizer, SizerOptions), + + wxPanel:setSizer(Panel, MainSizer), + {Panel, #state{parent=Panel, config=Config}}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Async Events are handled in handle_event as in handle_info +handle_event(#wx{event = #wxFontPicker{font = Font}}, State = #state{}) -> + demo:format(State#state.config, "Font changed to ~p.\n", [Font]), + {noreply, State}; +handle_event(#wx{event = #wxColourPicker{colour = Colour}}, State = #state{}) -> + demo:format(State#state.config, "Colour changed to ~p.\n", [Colour]), + {noreply, State}; +handle_event(#wx{event = #wxFileDirPicker{type = command_filepicker_changed, + path = Path}}, + State = #state{}) -> + demo:format(State#state.config, "Filepicker changed to ~p.\n", [Path]), + {noreply, State}; +handle_event(#wx{event = #wxFileDirPicker{type = command_dirpicker_changed, + path = Path}}, + State = #state{}) -> + demo:format(State#state.config, "Dirpicker changed to ~p.\n", [Path]), + {noreply, State}; +handle_event(#wx{event = #wxDate{date = Date}}, + State = #state{}) -> + demo:format(State#state.config, "Datepicker changed to ~p.\n", [Date]), + {noreply, State}; +handle_event(Ev = #wx{}, State = #state{}) -> + demo:format(State#state.config, "Got Event ~p\n", [Ev]), + {noreply, State}. + +%% Callbacks handled as normal gen_server callbacks +handle_info(Msg, State) -> + demo:format(State#state.config, "Got Info ~p\n", [Msg]), + {noreply, State}. + +handle_call(Msg, _From, State) -> + demo:format(State#state.config, "Got Call ~p\n", [Msg]), + {reply,{error, nyi}, State}. + +code_change(_, _, State) -> + {stop, ignore, State}. + +terminate(_Reason, _State) -> + ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Local functions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/lib/wx/examples/demo/ex_popupMenu.erl b/lib/wx/examples/demo/ex_popupMenu.erl new file mode 100644 index 0000000000..8774dbef7b --- /dev/null +++ b/lib/wx/examples/demo/ex_popupMenu.erl @@ -0,0 +1,150 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-module(ex_popupMenu). + +-behaviour(wx_object). + +%% Client API +-export([start/1]). + +%% wx_object callbacks +-export([init/1, terminate/2, code_change/3, + handle_info/2, handle_call/3, handle_event/2]). + +-include_lib("wx/include/wx.hrl"). + +-record(state, + { + parent, + config, + menu + }). + +start(Config) -> + wx_object:start_link(?MODULE, Config, []). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +init(Config) -> + wx:batch(fun() -> do_init(Config) end). + +do_init(Config) -> + Root = proplists:get_value(parent, Config), + Parent = wxPanel:new(Root,[]), + MainSizer = wxBoxSizer:new(?wxVERTICAL), + Box = wxStaticBox:new(Parent, ?wxID_ANY, "Popup Menu"), + Sz = wxStaticBoxSizer:new(Box, ?wxVERTICAL), + Text = wxStaticText:new(Parent, ?wxID_ANY, "Right click to open popup menu", []), + Panel = wxPanel:new(Parent), + wxPanel:connect(Panel, right_up), + Sizer = wxBoxSizer:new(?wxVERTICAL), + wxSizer:add(Sizer, Text, [{border, 20}, {flag, ?wxALL}]), + wxPanel:setSizer(Panel, Sizer), + wxSizer:add(Sz, Panel, [{proportion,1}, {flag, ?wxEXPAND}]), + wxSizer:layout(Sz), + PopupMenu = create_menu(), + wxSizer:add(MainSizer, Sz, [{proportion,1}, {flag, ?wxEXPAND}]), + wxWindow:setSizer(Parent, MainSizer), + {Parent, #state{parent=Parent, config=Config, menu=PopupMenu}}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Async Events are handled in handle_event as in handle_info +handle_event(#wx{obj = Panel, + event = #wxMouse{type = right_up}}, + State = #state{menu = Menu}) -> + %% Open the popup menu + wxWindow:popupMenu(Panel, Menu), + {noreply, State}; +handle_event(#wx{obj = Menu, id = Id, + event = #wxCommand{type = command_menu_selected}}, + State = #state{}) -> + %% Get the selected item label + Label = wxMenu:getLabel(Menu, Id), + demo:format(State#state.config, "wxMenu clicked ~p\n", [Label]), + {noreply, State}; +handle_event(Ev, State) -> + demo:format(State#state.config, "Unexpected Event ~p\n", [Ev]), + {noreply, State}. + +%% Callbacks handled as normal gen_server callbacks +handle_info(Msg, State) -> + demo:format(State#state.config, "Got Info ~p\n", [Msg]), + {noreply, State}. + +handle_call(Msg, _From, State) -> + demo:format(State#state.config, "Got Call ~p\n", [Msg]), + {reply,{error, nyi}, State}. + +code_change(_, _, State) -> + {stop, ignore, State}. + +terminate(_Reason, #state{menu=Popup}) -> + wxMenu:destroy(Popup), + ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Local functions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +create_menu() -> + Menu = wxMenu:new([]), + SubMenu = wxMenu:new([]), + SubMenu2 = wxMenu:new([]), + + wxMenu:append(Menu, ?wxID_UNDO, "Undo", []), + wxMenu:append(Menu, ?wxID_REDO, "Redo", []), + wxMenu:append(Menu, ?wxID_HELP, "Help", []), + wxMenu:appendSeparator(Menu), + wxMenu:appendCheckItem(Menu, ?wxID_ANY, "Check item", []), + wxMenu:appendSeparator(Menu), + wxMenu:appendRadioItem(Menu, ?wxID_ANY, "Radio item 1", []), + wxMenu:appendRadioItem(Menu, ?wxID_ANY, "Radio item 2", []), + wxMenu:appendRadioItem(Menu, ?wxID_ANY, "Radio item 3", []), + wxMenu:appendRadioItem(Menu, ?wxID_ANY, "Radio item 4", []), + + wxMenu:appendSeparator(Menu), + wxMenuItem:enable(wxMenu:append(Menu, ?wxID_ANY, "Disabled", []), [{enable,false}]), + wxMenu:appendSeparator(Menu), + + wxMenu:append(SubMenu, ?wxID_ABOUT, "About", []), + wxMenu:append(SubMenu, ?wxID_ANY, "Sub Item2", []), + wxMenu:append(SubMenu, ?wxID_SAVE, "Save", []), + wxMenu:break(SubMenu), + wxMenu:append(SubMenu, ?wxID_EXIT, "Exit", []), + wxMenu:append(SubMenu, ?wxID_OPEN, "Open", []), + wxMenu:append(SubMenu, ?wxID_NEW, "New", []), + wxMenu:append(Menu, ?wxID_ANY, "Sub menu", SubMenu, []), + + wxMenu:appendCheckItem(SubMenu2, ?wxID_ANY, "Check Item", []), + wxMenu:appendSeparator(SubMenu2), + wxMenu:append(SubMenu2, ?wxID_CLEAR, "Clear", []), + wxMenu:append(SubMenu2, ?wxID_ANY, "Sub Item", []), + + Bitmap = wxArtProvider:getBitmap("wxART_NEW"), + AnotherSubMenu = wxMenuItem:new([{parentMenu, Menu}, + {id, ?wxID_ANY}, + {text, "Another sub menu"}, + {subMenu, SubMenu2}, + {kind, ?wxITEM_NORMAL}]), + wxMenuItem:setBitmap(AnotherSubMenu, Bitmap), + wxMenu:append(Menu, AnotherSubMenu), + + wxMenu:connect(Menu, command_menu_selected), + wxMenu:connect(SubMenu, command_menu_selected), + wxMenu:connect(SubMenu2, command_menu_selected), + Menu. diff --git a/lib/wx/examples/demo/ex_radioBox.erl b/lib/wx/examples/demo/ex_radioBox.erl new file mode 100644 index 0000000000..8211aec4a2 --- /dev/null +++ b/lib/wx/examples/demo/ex_radioBox.erl @@ -0,0 +1,163 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-module(ex_radioBox). + +-behaviour(wx_object). + +-export([start/1, init/1, terminate/2, code_change/3, + handle_info/2, handle_call/3, handle_event/2]). + +-include_lib("wx/include/wx.hrl"). + +-record(state, + { + parent, + config, + radio_box + }). + +start(Config) -> + wx_object:start_link(?MODULE, Config, []). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +init(Config) -> + wx:batch(fun() -> do_init(Config) end). + +do_init(Config) -> + Parent = proplists:get_value(parent, Config), + Panel = wxPanel:new(Parent, []), + + %% Setup sizers + MainSizer = wxBoxSizer:new(?wxVERTICAL), + Sizer = wxBoxSizer:new(?wxHORIZONTAL), + + Choices = ["Item " ++ integer_to_list(Int) || Int <- lists:seq(1,12)], + RadioBox = wxRadioBox:new(Panel, 1, "wxRadioBox Horizontal", + ?wxDefaultPosition, + ?wxDefaultSize, + Choices, + [{majorDim, 3}, + {style, ?wxHORIZONTAL}]), + wxRadioBox:connect(RadioBox, command_radiobox_selected), + + RadioButtonSizer = create_radio_buttons(Panel), + + CheckSizer = create_checkboxes(Panel), + + %% Add to sizers + wxSizer:add(Sizer, RadioButtonSizer), + wxSizer:addSpacer(Sizer, 20), + wxSizer:add(Sizer, CheckSizer), + + wxSizer:add(MainSizer, RadioBox), + wxSizer:addSpacer(MainSizer, 20), + wxSizer:add(MainSizer, Sizer), + + wxPanel:setSizer(Panel, MainSizer), + {Panel, #state{parent=Panel, config=Config, + radio_box = RadioBox}}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Async Events are handled in handle_event as in handle_info +handle_event(#wx{event = #wxCommand{type = command_radiobox_selected, + cmdString = Item}}, + State = #state{}) -> + demo:format(State#state.config,"wxRadioBox selected ~p\n",[Item]), + {noreply, State}; +handle_event(#wx{obj = Checkbox, + event = #wxCommand{type = command_checkbox_clicked, + commandInt = Int}}, + State = #state{config = Config}) -> + Label = wxCheckBox:getLabel(Checkbox), + case Int of + 0 -> demo:format(Config,"wxCheckBox deselected ~p\n",[Label]); + 1 -> demo:format(Config,"wxCheckBox selected ~p \n",[Label]); + 2 -> demo:format(Config,"wxCheckBox middle-state ~p\n",[Label]) + end, + {noreply, State}; +handle_event(#wx{obj = RadioButton, + event = #wxCommand{type = command_radiobutton_selected}}, + State = #state{}) -> + Label = wxRadioButton:getLabel(RadioButton), + demo:format(State#state.config,"wxRadioButton selected ~p\n",[Label]), + {noreply, State}. + +%% Callbacks handled as normal gen_server callbacks +handle_info(Msg, State) -> + demo:format(State#state.config, "Got Info ~p\n",[Msg]), + {noreply, State}. + +handle_call(Msg, _From, State) -> + demo:format(State#state.config,"Got Call ~p\n",[Msg]), + {reply, {error, nyi}, State}. + + +code_change(_, _, State) -> + {stop, ignore, State}. + +terminate(_Reason, _State) -> + ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Local functions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +create_checkboxes(Panel) -> + CheckSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "wxCheckBox"}]), + + CheckBoxes = + [wxCheckBox:new(Panel, ?wxID_ANY, "Label1", []), + wxCheckBox:new(Panel, ?wxID_ANY, "Label2", []), + wxCheckBox:new(Panel, ?wxID_ANY, "Label3", []), + wxCheckBox:new(Panel, ?wxID_ANY, "3-state checkbox", + [{style, ?wxCHK_3STATE bor + ?wxCHK_ALLOW_3RD_STATE_FOR_USER}]), + wxCheckBox:new(Panel, ?wxID_ANY, "Right aligned", + [{style, ?wxALIGN_RIGHT}])], + Fun = + fun(Item) -> + wxCheckBox:connect(Item, command_checkbox_clicked), + wxSizer:add(CheckSizer, Item) + end, + wx:foreach(Fun, CheckBoxes), + CheckSizer. + + +create_radio_buttons(Panel) -> + RadioButtonSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "wxRadioButton"}]), + + Buttons = + [wxRadioButton:new(Panel, ?wxID_ANY, "Group1 Radio1", + [{style, ?wxRB_GROUP}]), + wxRadioButton:new(Panel, ?wxID_ANY, "Group1 Radio2", []), + wxRadioButton:new(Panel, ?wxID_ANY, "Group1 Radio3", []), + wxRadioButton:new(Panel, ?wxID_ANY, "Group2 Radio1", + [{style, ?wxRB_GROUP}]), + wxRadioButton:new(Panel, ?wxID_ANY, "Group2 Radio2", []), + wxRadioButton:new(Panel, ?wxID_ANY, "Group2 Radio3", [])], + Fun = + fun(Item) -> + wxRadioButton:connect(Item, command_radiobutton_selected), + wxSizer:add(RadioButtonSizer, Item) + end, + + wx:foreach(Fun, Buttons), + RadioButtonSizer. diff --git a/lib/wx/examples/demo/ex_sashWindow.erl b/lib/wx/examples/demo/ex_sashWindow.erl new file mode 100644 index 0000000000..dd05f4e45f --- /dev/null +++ b/lib/wx/examples/demo/ex_sashWindow.erl @@ -0,0 +1,128 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-module(ex_sashWindow). + +-behaviour(wx_object). + +%% Client API +-export([start/1]). + +%% wx_object callbacks +-export([init/1, terminate/2, code_change/3, + handle_info/2, handle_call/3, handle_event/2]). + +-include_lib("wx/include/wx.hrl"). + +-record(state, + { + parent, + config, + top_sash, + bottom_sash + }). + +-define(TOP_SASH, 1). +-define(BOTTOM_SASH, 2). + +start(Config) -> + wx_object:start_link(?MODULE, Config, []). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +init(Config) -> + wx:batch(fun() -> do_init(Config) end). + +do_init(Config) -> + Parent = proplists:get_value(parent, Config), + Panel = wxPanel:new(Parent, []), + + %% Setup sizers + MainSizer = wxBoxSizer:new(?wxVERTICAL), + Sizer = wxBoxSizer:new(?wxVERTICAL), + + TopSash = wxSashWindow:new(Panel, [{id, ?TOP_SASH}, + {style, ?wxSW_3D}]), + Win1 = wxPanel:new(TopSash, []), + wxStaticText:new(Win1, ?wxID_ANY, "This is the top sash", []), + BottomSash = wxSashWindow:new(Panel, [{id, ?BOTTOM_SASH}, + {style, ?wxSW_3D}]), + Win2 = wxPanel:new(BottomSash, []), + wxStaticText:new(Win2, ?wxID_ANY, "This is the bottom sash", []), + + %% Make the bottom edge of the top sash dragable + wxSashWindow:setSashVisible(TopSash, ?wxSASH_BOTTOM, true), + wxPanel:connect(Panel, sash_dragged), + wxPanel:connect(Panel, size), + + %% Add to sizers + Options = [{flag, ?wxEXPAND}, {proportion, 1}], + wxSizer:add(Sizer, TopSash, Options), + wxSizer:add(Sizer, BottomSash, Options), + wxSizer:add(MainSizer, Sizer, Options), + wxPanel:setSizer(Panel, MainSizer), + wxSizer:fit(MainSizer, Panel), + wxSizer:setSizeHints(MainSizer, Panel), + {Panel, #state{parent=Panel, config=Config, + top_sash = TopSash, bottom_sash = BottomSash}}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Async Events are handled in handle_event as in handle_info +handle_event(#wx{event = #wxSash{dragRect = {_X,Y, _W, H}}}, + State = #state{top_sash = TopSash, + bottom_sash = BottomSash}) -> + {OldW, OldH} = wxPanel:getSize(State#state.parent), + Diff = OldH - H, + {OldX, _} = wxSashWindow:getPosition(BottomSash), + wxSashWindow:setMinSize(BottomSash, {OldW,Diff}), + wxSashWindow:setMinSize(TopSash, {OldW,H}), + wxSashWindow:setSize(BottomSash, {OldX, Y,OldW,Diff}), + wxSashWindow:setSize(TopSash, {OldW,H}), + wxPanel:refresh(State#state.parent), + {noreply, State}; +handle_event(#wx{event = #wxSize{size = {W, H}}}, + State = #state{top_sash = TopSash, + bottom_sash = BottomSash}) -> + wxSashWindow:setMinSize(TopSash, {W, H div 2}), + wxSashWindow:setMinSize(BottomSash, {W, H div 2}), + wxSashWindow:setSize(TopSash, {W, H div 2}), + wxSashWindow:setSize(BottomSash, {0,H div 2,W,H div 2}), + wxPanel:refresh(State#state.parent), + {noreply, State}; +handle_event(Ev = #wx{}, State = #state{}) -> + demo:format(State#state.config, "Got Event ~p\n", [Ev]), + {noreply, State}. + +%% Callbacks handled as normal gen_server callbacks +handle_info(Msg, State) -> + demo:format(State#state.config, "Got Info ~p\n", [Msg]), + {noreply, State}. + +handle_call(Msg, _From, State) -> + demo:format(State#state.config, "Got Call ~p\n", [Msg]), + {reply,{error, nyi}, State}. + +code_change(_, _, State) -> + {stop, ignore, State}. + +terminate(_Reason, _State) -> + ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Local functions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/lib/wx/examples/demo/ex_sizers.erl b/lib/wx/examples/demo/ex_sizers.erl new file mode 100644 index 0000000000..2cc6efd503 --- /dev/null +++ b/lib/wx/examples/demo/ex_sizers.erl @@ -0,0 +1,436 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-module(ex_sizers). + +-behaviour(wx_object). + +%% Client API +-export([start/1]). + +%% wx_object callbacks +-export([init/1, terminate/2, code_change/3, + handle_info/2, handle_call/3, handle_event/2]). + +-include_lib("wx/include/wx.hrl"). + +-record(state, + { + parent, + config + }). + +start(Config) -> + wx_object:start_link(?MODULE, Config, []). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +init(Config) -> + wx:batch(fun() -> do_init(Config) end). + +do_init(Config) -> + Parent = proplists:get_value(parent, Config), + Panel = wxPanel:new(Parent, []), + + %% Setup sizers + MainSizer = wxBoxSizer:new(?wxVERTICAL), + Sizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "wxSizer"}]), + + Choices = ["Vertical Example", + "Horizontal Example", + "Add A Strechable", + "More Than One Strechable", + "Weighting Factor", + "Edge Affinity", + "Spacer", + "Centering In Avalible Space", + "Simple Border", + "East And West Border", + "North And South Border", + "Box In Box", + "Boxes Inside A Border", + "Border In A Box", + "Simple Grid", + "More Grid Features", + "Flexible Grid", + "Grid With Alignment", + "Proportional Resize With Alignments"], + + ListBox = wxListBox:new(Panel, ?wxID_ANY, [{choices, Choices}]), + wxListBox:connect(ListBox, command_listbox_doubleclicked), + + %% Add to sizers + wxSizer:add(Sizer, ListBox, [{flag, ?wxEXPAND}]), + wxSizer:add(MainSizer, Sizer, [{flag, ?wxEXPAND}, {proportion, 1}]), + + wxPanel:setSizer(Panel, MainSizer), + {Panel, #state{parent=Panel, config=Config}}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Async Events are handled in handle_event as in handle_info +handle_event(#wx{event = #wxCommand{type = command_listbox_doubleclicked, + cmdString = Choice}}, + State = #state{}) -> + create_example(State#state.parent, Choice), + {noreply, State}; +handle_event(Ev = #wx{}, State = #state{}) -> + demo:format(State#state.config, "Got Event ~p\n", [Ev]), + {noreply, State}. + +%% Callbacks handled as normal gen_server callbacks +handle_info(Msg, State) -> + demo:format(State#state.config, "Got Info ~p\n", [Msg]), + {noreply, State}. + +handle_call(Msg, _From, State) -> + demo:format(State#state.config, "Got Call ~p\n", [Msg]), + {reply,{error, nyi}, State}. + +code_change(_, _, State) -> + {stop, ignore, State}. + +terminate(_Reason, _State) -> + ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Local functions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +create_example(Parent, Example) -> + Frame = wxFrame:new(Parent, ?wxID_ANY, Example, + [{style, ?wxDEFAULT_FRAME_STYLE bor ?wxFRAME_FLOAT_ON_PARENT}]), + wxFrame:center(Frame), + Panel = wxPanel:new(Frame, []), + Sizer = + case Example of + "Proportional Resize With Alignments" -> + proportional_resize_with_alignments(Panel); + "Grid With Alignment" -> + grid_with_alignment(Panel); + "Flexible Grid" -> + flexible_grid(Panel); + "More Grid Features" -> + more_grid_features(Panel); + "Simple Grid" -> + simple_grid(Panel); + "Border In A Box" -> + border_in_a_box(Panel); + "Boxes Inside A Border" -> + boxes_inside_a_border(Panel); + "Box In Box" -> + box_in_box(Panel); + "East And West Border" -> + east_and_west_border(Panel); + "North And South Border" -> + north_and_south_border(Panel); + "Simple Border" -> + simple_border(Panel); + "Centering In Avalible Space" -> + centering_in_avalible_space(Panel); + "Spacer" -> + spacer(Panel); + "Edge Affinity" -> + edge_affinity(Panel); + "Weighting Factor" -> + weighting_factor(Panel); + "More Than One Strechable" -> + more_than_one_strechable(Panel); + "Add A Strechable" -> + add_a_strechable(Panel); + "Vertical Example" -> + vertical(Panel); + "Horizontal Example" -> + horizontal(Panel) + end, + wxPanel:setSizer(Panel, Sizer), + wxSizer:fit(Sizer, Panel), + wxFrame:createStatusBar(Frame), + wxFrame:setStatusText(Frame, "Resize window to see how the sizers respond.."), + wxFrame:fit(Frame), + wxFrame:show(Frame). + +create_box(Parent) -> + Win = wxWindow:new(Parent, ?wxID_ANY, [{style, ?wxBORDER_SIMPLE}, + {size, {50,25}}]), + wxWindow:setBackgroundColour(Win, ?wxWHITE), + Win. + + +vertical(Parent) -> + Sizer = wxBoxSizer:new(?wxVERTICAL), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + Sizer. + + +horizontal(Parent) -> + Sizer = wxBoxSizer:new(?wxHORIZONTAL), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + Sizer. + +add_a_strechable(Parent) -> + Sizer = wxBoxSizer:new(?wxHORIZONTAL), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]), + Sizer. + +more_than_one_strechable(Parent) -> + Sizer = wxBoxSizer:new(?wxHORIZONTAL), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]), + Sizer. + +weighting_factor(Parent) -> + Sizer = wxBoxSizer:new(?wxHORIZONTAL), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 3}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]), + Sizer. + +edge_affinity(Parent) -> + Sizer = wxBoxSizer:new(?wxHORIZONTAL), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 1}, {flag, ?wxALIGN_TOP}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 1}, {flag, ?wxALIGN_CENTER}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 1}, {flag, ?wxALIGN_BOTTOM}]), + Sizer. + +spacer(Parent) -> + Sizer = wxBoxSizer:new(?wxHORIZONTAL), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, 60,20, [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]), + Sizer. + +centering_in_avalible_space(Parent) -> + Sizer = wxBoxSizer:new(?wxVERTICAL), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, 0,0, [{proportion, 1}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxALIGN_CENTER}]), + wxSizer:add(Sizer, 0,0, [{proportion, 1}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + Sizer. + +simple_border(Parent) -> + Sizer = wxBoxSizer:new(?wxHORIZONTAL), + Win = create_box(Parent), + wxWindow:setSize(Win, 80,80), + wxSizer:add(Sizer, Win, [{proportion, 1}, {flag, ?wxEXPAND bor ?wxALL}, + {border, 15}]), + Sizer. + +east_and_west_border(Parent) -> + Sizer = wxBoxSizer:new(?wxHORIZONTAL), + Win = create_box(Parent), + wxWindow:setSize(Win, 80,80), + wxSizer:add(Sizer, Win, [{proportion, 1}, {flag, ?wxEXPAND bor ?wxEAST bor ?wxWEST}, + {border, 15}]), + Sizer. + +north_and_south_border(Parent) -> + Sizer = wxBoxSizer:new(?wxHORIZONTAL), + Win = create_box(Parent), + wxWindow:setSize(Win, 80,80), + wxSizer:add(Sizer, Win, [{proportion, 1}, {flag, ?wxEXPAND bor ?wxNORTH bor ?wxSOUTH}, + {border, 15}]), + Sizer. + + +box_in_box(Parent) -> + Sizer = wxBoxSizer:new(?wxVERTICAL), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + + Sizer2 = wxBoxSizer:new(?wxHORIZONTAL), + wxSizer:add(Sizer2, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer2, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer2, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer2, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + + Sizer3 = wxBoxSizer:new(?wxVERTICAL), + wxSizer:add(Sizer3, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer3, create_box(Parent), [{proportion, 2}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer3, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer3, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]), + + wxSizer:add(Sizer2, Sizer3, [{proportion, 1}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, Sizer2, [{proportion, 1}, {flag, ?wxEXPAND}]), + + wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + Sizer. + +boxes_inside_a_border(Parent) -> + Border = wxBoxSizer:new(?wxHORIZONTAL), + Sizer = add_a_strechable(Parent), + wxSizer:add(Border, Sizer, [{proportion, 1}, {flag, ?wxEXPAND bor ?wxALL}, + {border, 15}]), + Border. + +border_in_a_box(Parent) -> + InsideBox = wxBoxSizer:new(?wxHORIZONTAL), + + Sizer2 = wxBoxSizer:new(?wxHORIZONTAL), + wxSizer:add(Sizer2, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer2, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer2, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer2, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer2, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + + wxSizer:add(InsideBox, Sizer2, [{proportion, 0}, {flag, ?wxEXPAND}]), + + Border = wxBoxSizer:new(?wxHORIZONTAL), + wxSizer:add(Border, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND bor ?wxALL}]), + wxSizer:add(InsideBox, Border, [{proportion, 1}, {flag, ?wxEXPAND bor ?wxALL}, + {border, 20}]), + + + Sizer3 = wxBoxSizer:new(?wxVERTICAL), + wxSizer:add(Sizer3, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer3, create_box(Parent), [{proportion, 2}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer3, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer3, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]), + + wxSizer:add(InsideBox, Sizer3, [{proportion, 1}, {flag, ?wxEXPAND}]), + + OutsideBox = wxBoxSizer:new(?wxVERTICAL), + wxSizer:add(OutsideBox, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(OutsideBox, InsideBox, [{proportion, 1}, {flag, ?wxEXPAND}]), + wxSizer:add(OutsideBox, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + OutsideBox. + +simple_grid(Parent) -> + GridSizer = wxGridSizer:new(3, 3, 2, 2), + + wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + GridSizer. + +more_grid_features(Parent) -> + GridSizer = wxGridSizer:new(3, 3, 1, 1), % rows, cols, vgap, hgap + + Sizer = wxBoxSizer:new(?wxVERTICAL), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(Sizer, create_box(Parent), [{proportion, 1}, {flag, ?wxEXPAND}]), + + GridSizer2 = wxGridSizer:new(2, 2, 4, 4), + wxSizer:add(GridSizer2, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(GridSizer2, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(GridSizer2, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(GridSizer2, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + + wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxALIGN_RIGHT bor ?wxALIGN_BOTTOM}]), + wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxALIGN_LEFT bor ?wxALIGN_BOTTOM}]), + wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxALIGN_CENTER}]), + wxSizer:add(GridSizer, Sizer, [{proportion, 0}, {flag, ?wxEXPAND bor ?wxALL}, + {border, 10}]), + wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(GridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(GridSizer, GridSizer2, [{proportion, 0}, {flag, ?wxEXPAND bor ?wxALL}, + {border, 4}]), + GridSizer. + + +flexible_grid(Parent) -> + FlexGridSizer = wxFlexGridSizer:new(3, 3, 2, 2), % rows, cols, vgap, hgap + wxSizer:add(FlexGridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(FlexGridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(FlexGridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(FlexGridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(FlexGridSizer, 175, 50, []), + wxSizer:add(FlexGridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(FlexGridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(FlexGridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + wxSizer:add(FlexGridSizer, create_box(Parent), [{proportion, 0}, {flag, ?wxEXPAND}]), + + wxFlexGridSizer:addGrowableRow(FlexGridSizer, 0), + wxFlexGridSizer:addGrowableRow(FlexGridSizer, 2), + wxFlexGridSizer:addGrowableCol(FlexGridSizer, 1), + FlexGridSizer. + +grid_with_alignment(Parent) -> + GridSizer = wxGridSizer:new(3, 3, 2, 2), % rows, cols, vgap, hgap + + wxSizer:add(GridSizer, create_box(Parent), + [{proportion, 0}, {flag, ?wxALIGN_TOP bor ?wxALIGN_LEFT}]), + wxSizer:add(GridSizer, create_box(Parent), + [{proportion, 0}, {flag, ?wxALIGN_TOP bor ?wxALIGN_CENTER_HORIZONTAL}]), + wxSizer:add(GridSizer, create_box(Parent), + [{proportion, 0}, {flag, ?wxALIGN_TOP bor ?wxALIGN_RIGHT}]), + wxSizer:add(GridSizer, create_box(Parent), + [{proportion, 0}, {flag, ?wxALIGN_CENTER_VERTICAL bor ?wxALIGN_LEFT}]), + wxSizer:add(GridSizer, create_box(Parent), + [{proportion, 0}, {flag, ?wxALIGN_CENTER}]), + wxSizer:add(GridSizer, create_box(Parent), + [{proportion, 0}, {flag, ?wxALIGN_CENTER_VERTICAL bor ?wxALIGN_RIGHT}]), + wxSizer:add(GridSizer, create_box(Parent), + [{proportion, 0}, {flag, ?wxALIGN_BOTTOM bor ?wxALIGN_LEFT}]), + wxSizer:add(GridSizer, create_box(Parent), + [{proportion, 0}, {flag, ?wxALIGN_BOTTOM bor ?wxALIGN_CENTER_HORIZONTAL}]), + wxSizer:add(GridSizer, create_box(Parent), + [{proportion, 0}, {flag, ?wxALIGN_BOTTOM bor ?wxALIGN_RIGHT}]), + GridSizer. + +proportional_resize_with_alignments(Parent) -> + GridSizer = wxGridSizer:new(3, 3, 2, 2), % rows, cols, vgap, hgap + + wxSizer:add(GridSizer, create_box(Parent), + [{proportion, 0}, {flag, ?wxSHAPED bor ?wxALIGN_TOP bor ?wxALIGN_LEFT}]), + wxSizer:add(GridSizer, create_box(Parent), + [{proportion, 0}, {flag, ?wxSHAPED bor ?wxALIGN_TOP bor ?wxALIGN_CENTER_HORIZONTAL}]), + wxSizer:add(GridSizer, create_box(Parent), + [{proportion, 0}, {flag, ?wxSHAPED bor ?wxALIGN_TOP bor ?wxALIGN_RIGHT}]), + wxSizer:add(GridSizer, create_box(Parent), + [{proportion, 0}, {flag, ?wxSHAPED bor ?wxALIGN_CENTER_VERTICAL bor ?wxALIGN_LEFT}]), + wxSizer:add(GridSizer, create_box(Parent), + [{proportion, 0}, {flag, ?wxSHAPED bor ?wxALIGN_CENTER}]), + wxSizer:add(GridSizer, create_box(Parent), + [{proportion, 0}, {flag, ?wxSHAPED bor ?wxALIGN_CENTER_VERTICAL bor ?wxALIGN_RIGHT}]), + wxSizer:add(GridSizer, create_box(Parent), + [{proportion, 0}, {flag, ?wxSHAPED bor ?wxALIGN_BOTTOM bor ?wxALIGN_LEFT}]), + wxSizer:add(GridSizer, create_box(Parent), + [{proportion, 0}, {flag, ?wxSHAPED bor ?wxALIGN_BOTTOM bor ?wxALIGN_CENTER_HORIZONTAL}]), + wxSizer:add(GridSizer, create_box(Parent), + [{proportion, 0}, {flag, ?wxSHAPED bor ?wxALIGN_BOTTOM bor ?wxALIGN_RIGHT}]), + GridSizer. + diff --git a/lib/wx/examples/demo/ex_slider.erl b/lib/wx/examples/demo/ex_slider.erl new file mode 100644 index 0000000000..7b669d96f6 --- /dev/null +++ b/lib/wx/examples/demo/ex_slider.erl @@ -0,0 +1,113 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-module(ex_slider). + +-behaviour(wx_object). + +-export([start/1, init/1, terminate/2, code_change/3, + handle_info/2, handle_call/3, handle_event/2]). + +-include_lib("wx/include/wx.hrl"). + +-record(state, + { + parent, + config + }). + +start(Config) -> + wx_object:start_link(?MODULE, Config, []). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +init(Config) -> + wx:batch(fun() -> do_init(Config) end). + +do_init(Config) -> + Parent = proplists:get_value(parent, Config), + Panel = wxPanel:new(Parent, []), + + %% Setup sizers + MainSizer = wxBoxSizer:new(?wxVERTICAL), + Sizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "Horizontal wxSlider"}]), + Sizer2 = wxStaticBoxSizer:new(?wxHORIZONTAL, Panel, + [{label, "Vertical wxSlider"}]), + + %% Setup slider with range from 0 to 100 + %% and a start value of 25 + Min = 0, + Max = 100, + StartValue = 25, + %% Horizontal slider (default) with label + Slider = wxSlider:new(Panel, 1, StartValue, Min, Max, + [{style, ?wxSL_HORIZONTAL bor + ?wxSL_LABELS}]), + %% Horizontal inverse slider with label + InverseSlider = wxSlider:new(Panel, 2, StartValue, Min, Max, + [{style, ?wxSL_HORIZONTAL bor + ?wxSL_LABELS bor + ?wxSL_INVERSE}]), + VerticalSlider = wxSlider:new(Panel, 3, StartValue, Min, Max, + [{style, ?wxSL_VERTICAL bor + ?wxSL_LABELS}]), + InverseVerticalSlider = wxSlider:new(Panel, 4, StartValue, Min, Max, + [{style, ?wxSL_VERTICAL bor + ?wxSL_LABELS bor + ?wxSL_INVERSE}]), + + %% Add to sizers + wxSizer:add(Sizer, Slider, [{flag, ?wxEXPAND}]), + wxSizer:add(Sizer, InverseSlider, [{flag, ?wxEXPAND}]), + wxSizer:add(Sizer2, VerticalSlider, [{flag, ?wxEXPAND}, + {proportion, 1}]), + wxSizer:add(Sizer2, InverseVerticalSlider, [{flag, ?wxEXPAND}, + {proportion, 1}]), + + wxSizer:add(MainSizer, Sizer, [{flag, ?wxEXPAND}]), + wxSizer:add(MainSizer, Sizer2, [{flag, ?wxEXPAND}, + {proportion, 1}]), + + wxPanel:setSizer(Panel, MainSizer), + {Panel, #state{parent=Panel, config=Config}}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Async Events are handled in handle_event as in handle_info +handle_event(Ev = #wx{}, State = #state{}) -> + demo:format(State#state.config,"Got Event ~p\n",[Ev]), + {noreply, State}. + +%% Callbacks handled as normal gen_server callbacks +handle_info(Msg, State) -> + demo:format(State#state.config, "Got Info ~p\n",[Msg]), + {noreply, State}. + +handle_call(Msg, _From, State) -> + demo:format(State#state.config,"Got Call ~p\n",[Msg]), + {reply, {error, nyi},State}. + +code_change(_, _, State) -> + {stop, ignore, State}. + +terminate(_Reason, _State) -> + ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Local functions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/lib/wx/examples/demo/ex_splitterWindow.erl b/lib/wx/examples/demo/ex_splitterWindow.erl new file mode 100644 index 0000000000..c135f298fa --- /dev/null +++ b/lib/wx/examples/demo/ex_splitterWindow.erl @@ -0,0 +1,102 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-module(ex_splitterWindow). + +-behaviour(wx_object). + +%% Client API +-export([start/1]). + +%% wx_object callbacks +-export([init/1, terminate/2, code_change/3, + handle_info/2, handle_call/3, handle_event/2]). + +-include_lib("wx/include/wx.hrl"). + +-record(state, + { + parent, + config + }). + +start(Config) -> + wx_object:start_link(?MODULE, Config, []). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +init(Config) -> + wx:batch(fun() -> do_init(Config) end). + +do_init(Config) -> + Parent = proplists:get_value(parent, Config), + Panel = wxPanel:new(Parent, [{size, {100, 100}}]), + + %% Setup sizers + MainSizer = wxBoxSizer:new(?wxVERTICAL), + Sizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "wxSplitterWindow"}]), + + Splitter = wxSplitterWindow:new(Panel, []), + + Win1 = wxTextCtrl:new(Splitter, 1, [{value, "Splitted Window 1"}, + {style, ?wxDEFAULT bor ?wxTE_MULTILINE}]), + Win2 = wxTextCtrl:new(Splitter, 1, [{value, "Splitted Window 1"}, + {style, ?wxDEFAULT bor ?wxTE_MULTILINE}]), + + wxSplitterWindow:splitVertically(Splitter, Win1, Win2), + wxSplitterWindow:setSashGravity(Splitter, 0.5), + %% Set pane-size =/= 0 to not unsplit on doubleclick + %% on the splitter + wxSplitterWindow:setMinimumPaneSize(Splitter,50), + + %% Add to sizers + wxSizer:add(Sizer, Splitter, [{flag, ?wxEXPAND}, + {proportion, 1}]), + + wxSizer:add(MainSizer, Sizer, [{proportion, 1}, + {flag, ?wxEXPAND}]), + wxPanel:connect(Panel, command_splitter_sash_pos_changed), + wxPanel:setSizer(Panel, MainSizer), + {Panel, #state{parent=Panel, config=Config}}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Async Events are handled in handle_event as in handle_info +handle_event(#wx{event = #wxSplitter{type = command_splitter_sash_pos_changed}}, + State = #state{}) -> + demo:format(State#state.config, "Splitter pos changed.\n", []), + {noreply, State}. + +%% Callbacks handled as normal gen_server callbacks +handle_info(Msg, State) -> + demo:format(State#state.config, "Got Info ~p\n", [Msg]), + {noreply, State}. + +handle_call(Msg, _From, State) -> + demo:format(State#state.config, "Got Call ~p\n", [Msg]), + {reply,{error, nyi}, State}. + +code_change(_, _, State) -> + {stop, ignore, State}. + +terminate(_Reason, _State) -> + ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Local functions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/lib/wx/examples/demo/ex_static.erl b/lib/wx/examples/demo/ex_static.erl new file mode 100644 index 0000000000..67061520c4 --- /dev/null +++ b/lib/wx/examples/demo/ex_static.erl @@ -0,0 +1,117 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-module(ex_static). + +-behaviour(wx_object). + +%% Client API +-export([start/1]). + +%% wx_object callbacks +-export([init/1, terminate/2, code_change/3, + handle_info/2, handle_call/3, handle_event/2]). + +-include_lib("wx/include/wx.hrl"). + +-record(state, + { + parent, + config + }). + +start(Config) -> + wx_object:start_link(?MODULE, Config, []). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +init(Config) -> + wx:batch(fun() -> do_init(Config) end). + +do_init(Config) -> + Parent = proplists:get_value(parent, Config), + Panel = wxScrolledWindow:new(Parent, []), + wxScrolledWindow:setScrollRate(Panel, 5, 5), + + %% Setup sizers + MainSizer = wxBoxSizer:new(?wxVERTICAL), + TextSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "wxStaticText"}]), + BitmapSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "wxStaticBitmap"}]), + LineSizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "wxStaticLine"}]), + + %% Create static texts + Texts = [wxStaticText:new(Panel, 1, "This is a regular text (left aligned)", []), + wxStaticText:new(Panel, 2, "This is a centered text", + [{style, ?wxALIGN_CENTER bor ?wxST_NO_AUTORESIZE}]), + wxStaticText:new(Panel, 3, "This is a right aligned text", + [{style, ?wxALIGN_RIGHT bor ?wxST_NO_AUTORESIZE}])], + + + Image = wxImage:new("image.jpg", []), + Bitmap = wxBitmap:new(wxImage:scale(Image, + round(wxImage:getWidth(Image)*1.5), + round(wxImage:getHeight(Image)*1.5), + [{quality, ?wxIMAGE_QUALITY_HIGH}])), + StaticBitmap = wxStaticBitmap:new(Panel, 1, Bitmap), + + Line = wxStaticLine:new(Panel, [{style, ?wxLI_HORIZONTAL}]), + Line2 = wxStaticLine:new(Panel, [{style, ?wxLI_VERTICAL}, + {size, {-1, 100}}]), + + %% Add to sizers + [wxSizer:add(TextSizer, Text, [{flag, ?wxEXPAND bor ?wxALL}, + {border, 10}]) || Text <- Texts], + wxSizer:add(BitmapSizer, StaticBitmap, []), + wxSizer:add(LineSizer, Line, [{flag, ?wxTOP bor ?wxBOTTOM bor ?wxEXPAND}, + {border, 10}]), + wxSizer:add(LineSizer, Line2, [{flag, ?wxLEFT}, + {border, 50}]), + + wxSizer:add(MainSizer, TextSizer, [{flag, ?wxEXPAND}]), + wxSizer:add(MainSizer, BitmapSizer, []), + wxSizer:add(MainSizer, LineSizer, [{flag, ?wxEXPAND}]), + + wxPanel:setSizer(Panel, MainSizer), + {Panel, #state{parent=Panel, config=Config}}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Async Events are handled in handle_event as in handle_info +handle_event(#wx{}, State = #state{}) -> + {noreply, State}. + +%% Callbacks handled as normal gen_server callbacks +handle_info(Msg, State) -> + demo:format(State#state.config, "Got Info ~p\n", [Msg]), + {noreply, State}. + +handle_call(Msg, _From, State) -> + demo:format(State#state.config, "Got Call ~p\n", [Msg]), + {reply,{error, nyi}, State}. + +code_change(_, _, State) -> + {stop, ignore, State}. + +terminate(_Reason, _State) -> + ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Local functions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/lib/wx/examples/demo/ex_textCtrl.erl b/lib/wx/examples/demo/ex_textCtrl.erl new file mode 100644 index 0000000000..95837c7c4c --- /dev/null +++ b/lib/wx/examples/demo/ex_textCtrl.erl @@ -0,0 +1,104 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-module(ex_textCtrl). + +-behaviour(wx_object). + +-export([start/1, init/1, terminate/2, code_change/3, + handle_info/2, handle_call/3, handle_event/2]). + +-include_lib("wx/include/wx.hrl"). + +-record(state, + { + parent, + config + }). + +start(Config) -> + wx_object:start_link(?MODULE, Config, []). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +init(Config) -> + wx:batch(fun() -> do_init(Config) end). + +do_init(Config) -> + Parent = proplists:get_value(parent, Config), + Panel = wxPanel:new(Parent, []), + + %% Setup sizers + MainSizer = wxBoxSizer:new(?wxVERTICAL), + Sizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "wxTextCtrl single line"}]), + Sizer2 = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "wxTextCtrl single line password"}]), + Sizer3 = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "wxTextCtrl multiline"}]), + + TextCtrl = wxTextCtrl:new(Panel, 1, [{value, "This is a single line wxTextCtrl"}, + {style, ?wxDEFAULT}]), + TextCtrl2 = wxTextCtrl:new(Panel, 2, [{value, "password"}, + {style, ?wxDEFAULT bor + ?wxTE_PASSWORD}]), + TextCtrl3 = wxTextCtrl:new(Panel, 3, [{value, "This is a\n" + "multiline\n" + "wxTextCtrl"}, + {style, ?wxDEFAULT bor + ?wxTE_MULTILINE}]), + + %% Add to sizers + wxSizer:add(Sizer, TextCtrl, [{flag, ?wxEXPAND}]), + wxSizer:add(Sizer2, TextCtrl2, []), + wxSizer:add(Sizer3, TextCtrl3, [{flag, ?wxEXPAND}]), + + wxSizer:add(MainSizer, Sizer, [{flag, ?wxEXPAND}]), + wxSizer:addSpacer(MainSizer, 10), + wxSizer:add(MainSizer, Sizer2, [{flag, ?wxEXPAND}]), + wxSizer:addSpacer(MainSizer, 10), + wxSizer:add(MainSizer, Sizer3, [{flag, ?wxEXPAND}]), + + wxPanel:setSizer(Panel, MainSizer), + {Panel, #state{parent=Panel, config=Config}}. + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Async Events are handled in handle_event as in handle_info +handle_event(Ev = #wx{}, State = #state{}) -> + demo:format(State#state.config,"Got Event ~p\n",[Ev]), + {noreply, State}. + +%% Callbacks handled as normal gen_server callbacks +handle_info(Msg, State) -> + demo:format(State#state.config, "Got Info ~p\n",[Msg]), + {noreply, State}. + +handle_call(Msg, _From, State) -> + demo:format(State#state.config,"Got Call ~p\n",[Msg]), + {reply, {error,nyi}, State}. + +code_change(_, _, State) -> + {stop, ignore, State}. + +terminate(_Reason, _State) -> + ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Local functions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/lib/wx/examples/demo/ex_treeCtrl.erl b/lib/wx/examples/demo/ex_treeCtrl.erl new file mode 100644 index 0000000000..fa40795393 --- /dev/null +++ b/lib/wx/examples/demo/ex_treeCtrl.erl @@ -0,0 +1,121 @@ +%% +%% %CopyrightBegin% +%% +%% Copyright Ericsson AB 2009. All Rights Reserved. +%% +%% The contents of this file are subject to the Erlang Public License, +%% Version 1.1, (the "License"); you may not use this file except in +%% compliance with the License. You should have received a copy of the +%% Erlang Public License along with this software. If not, it can be +%% retrieved online at http://www.erlang.org/. +%% +%% Software distributed under the License is distributed on an "AS IS" +%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See +%% the License for the specific language governing rights and limitations +%% under the License. +%% +%% %CopyrightEnd% + +-module(ex_treeCtrl). + +-behaviour(wx_object). + +%% Client API +-export([start/1]). + +%% wx_object callbacks +-export([init/1, terminate/2, code_change/3, + handle_info/2, handle_call/3, handle_event/2]). + +-include_lib("wx/include/wx.hrl"). + +-record(state, + { + parent, + config + }). + +start(Config) -> + wx_object:start_link(?MODULE, Config, []). + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +init(Config) -> + wx:batch(fun() -> do_init(Config) end). + +do_init(Config) -> + Parent = proplists:get_value(parent, Config), + Panel = wxPanel:new(Parent, []), + + %% Setup sizers + MainSizer = wxBoxSizer:new(?wxVERTICAL), + Sizer = wxStaticBoxSizer:new(?wxVERTICAL, Panel, + [{label, "wxTreeCtrl"}]), + + %% Setup treeCtrl + TreeCtrl = wxTreeCtrl:new(Panel, []), + RootId = wxTreeCtrl:addRoot(TreeCtrl, "Root"), + %% Name the first items + Items = ["item "++integer_to_list(Int)|| + Int <- lists:seq(1,10)], + %% Create the first items in the treeCtrl + SubItems = [{wxTreeCtrl:appendItem(TreeCtrl, RootId, Item), Item}|| + Item <- Items], + %% Create sub items + [wxTreeCtrl:appendItem(TreeCtrl, ItemId, Item++" sub item "++integer_to_list(Int))|| + {ItemId, Item} <- SubItems, Int <- lists:seq(1,10)], + wxTreeCtrl:expand(TreeCtrl, RootId), + + %% Add to sizers + Options = [{flag, ?wxEXPAND}, {proportion, 1}], + wxSizer:add(Sizer, TreeCtrl, Options), + wxSizer:add(MainSizer, Sizer, Options), + + wxTreeCtrl:connect(TreeCtrl, command_tree_item_collapsed), + wxTreeCtrl:connect(TreeCtrl, command_tree_item_expanded), + wxTreeCtrl:connect(TreeCtrl, command_tree_sel_changed), + wxPanel:setSizer(Panel, MainSizer), + {Panel, #state{parent=Panel, config=Config}}. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Async Events are handled in handle_event as in handle_info +handle_event(#wx{event = #wxTree{type = command_tree_item_collapsed, + item = Item}, + obj = TreeCtrl}, + State = #state{}) -> + ItemText = wxTreeCtrl:getItemText(TreeCtrl, Item), + demo:format(State#state.config, "You have collapsed ~p.\n", [ItemText]), + {noreply, State}; +handle_event(#wx{event = #wxTree{type = command_tree_item_expanded, + item = Item}, + obj = TreeCtrl}, + State = #state{}) -> + ItemText = wxTreeCtrl:getItemText(TreeCtrl, Item), + demo:format(State#state.config, "You have expanded ~p.\n", [ItemText]), + {noreply, State}; +handle_event(#wx{event = #wxTree{type = command_tree_sel_changed, + item = Item}, + obj = TreeCtrl}, + State = #state{}) -> + ItemText = wxTreeCtrl:getItemText(TreeCtrl, Item), + demo:format(State#state.config, "You have selected ~p.\n", [ItemText]), + {noreply, State}. + +%% Callbacks handled as normal gen_server callbacks +handle_info(Msg, State) -> + demo:format(State#state.config, "Got Info ~p\n", [Msg]), + {noreply, State}. + +handle_call(Msg, _From, State) -> + demo:format(State#state.config, "Got Call ~p\n", [Msg]), + {reply,{error, nyi}, State}. + +code_change(_, _, State) -> + {stop, ignore, State}. + +terminate(_Reason, _State) -> + ok. + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Local functions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + diff --git a/lib/wx/examples/demo/image.jpg b/lib/wx/examples/demo/image.jpg new file mode 100644 index 0000000000..ce5bfc2629 Binary files /dev/null and b/lib/wx/examples/demo/image.jpg differ -- cgit v1.2.3