aboutsummaryrefslogtreecommitdiffstats
path: root/lib/wx/examples/demo/demo.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/wx/examples/demo/demo.erl')
-rw-r--r--lib/wx/examples/demo/demo.erl363
1 files changed, 363 insertions, 0 deletions
diff --git a/lib/wx/examples/demo/demo.erl b/lib/wx/examples/demo/demo.erl
new file mode 100644
index 0000000000..59c20e09fb
--- /dev/null
+++ b/lib/wx/examples/demo/demo.erl
@@ -0,0 +1,363 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2009. All Rights Reserved.
+%%
+%% The contents of this file are subject to the Erlang Public License,
+%% Version 1.1, (the "License"); you may not use this file except in
+%% compliance with the License. You should have received a copy of the
+%% Erlang Public License along with this software. If not, it can be
+%% retrieved online at http://www.erlang.org/.
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and limitations
+%% under the License.
+%%
+%% %CopyrightEnd%
+
+%% This is example of the widgets and usage of wxErlang
+%% Hopefully it will contain all implemented widgets, it's event handling
+%% and some tutorials of how to use sizers and other stuff.
+
+-module(demo).
+
+-include_lib("wx/include/wx.hrl").
+
+-behaviour(wx_object).
+-export([start/0, start/1, start_link/0, start_link/1, format/3,
+ init/1, terminate/2, code_change/3,
+ handle_info/2, handle_call/3, handle_event/2]).
+
+
+-record(state, {win, demo, example, selector, log, code}).
+
+start() ->
+ start([]).
+
+start(Debug) ->
+ wx_object:start(?MODULE, Debug, []).
+
+start_link() ->
+ start_link([]).
+
+start_link(Debug) ->
+ wx_object:start_link(?MODULE, Debug, []).
+
+format(Config,Str,Args) ->
+ Log = proplists:get_value(log, Config),
+ wxTextCtrl:appendText(Log, io_lib:format(Str, Args)),
+ ok.
+
+-define(DEBUG_NONE, 101).
+-define(DEBUG_VERBOSE, 102).
+-define(DEBUG_TRACE, 103).
+-define(DEBUG_DRIVER, 104).
+
+init(Options) ->
+ wx:new(Options),
+ process_flag(trap_exit, true),
+
+ Frame = wxFrame:new(wx:null(), ?wxID_ANY, "wxErlang widgets", [{size,{1000,500}}]),
+ MB = wxMenuBar:new(),
+ File = wxMenu:new([]),
+ wxMenu:append(File, ?wxID_PRINT, "&Print code"),
+ wxMenu:appendSeparator(File),
+ wxMenu:append(File, ?wxID_EXIT, "&Quit"),
+ Debug = wxMenu:new([]),
+ wxMenu:appendRadioItem(Debug, ?DEBUG_NONE, "None"),
+ wxMenu:appendRadioItem(Debug, ?DEBUG_VERBOSE, "Verbose"),
+ wxMenu:appendRadioItem(Debug, ?DEBUG_TRACE, "Trace"),
+ wxMenu:appendRadioItem(Debug, ?DEBUG_DRIVER, "Driver"),
+ Help = wxMenu:new([]),
+ wxMenu:append(Help, ?wxID_HELP, "Help"),
+ wxMenu:append(Help, ?wxID_ABOUT, "About"),
+ wxMenuBar:append(MB, File, "&File"),
+ wxMenuBar:append(MB, Debug, "&Debug"),
+ wxMenuBar:append(MB, Help, "&Help"),
+ wxFrame:setMenuBar(Frame,MB),
+
+ wxFrame:connect(Frame, command_menu_selected),
+
+ _SB = wxFrame:createStatusBar(Frame,[]),
+
+ %% T Uppersplitter
+ %% O Left | Right
+ %% P Widgets|Code | Demo
+ %% S -------------------------------
+ %% P Log Window
+ TopSplitter = wxSplitterWindow:new(Frame, [{style, ?wxSP_NOBORDER}]),
+ UpperSplitter = wxSplitterWindow:new(TopSplitter, [{style, ?wxSP_NOBORDER}]),
+ LeftSplitter = wxSplitterWindow:new(UpperSplitter, [{style, ?wxSP_NOBORDER}]),
+ %% Setup so that sizers and initial sizes, resizes the windows correct
+ wxSplitterWindow:setSashGravity(TopSplitter, 0.5),
+ wxSplitterWindow:setSashGravity(UpperSplitter, 0.60),
+ wxSplitterWindow:setSashGravity(LeftSplitter, 0.20),
+
+ %% LeftSplitter:
+ Example = fun(Beam) ->
+ "ex_" ++ F = filename:rootname(Beam),
+ F
+ end,
+ Mods = [Example(F) || F <- filelib:wildcard("ex_*.beam")],
+
+ CreateLB = fun(Parent) ->
+ wxListBox:new(Parent, ?wxID_ANY,
+ [{style, ?wxLB_SINGLE},
+ {choices, Mods}])
+ end,
+ {LBPanel, [LB],_} = create_subwindow(LeftSplitter, "Example", [CreateLB]),
+ wxListBox:setSelection(LB, 0),
+ wxListBox:connect(LB, command_listbox_selected),
+
+ CreateCode = fun(Parent) ->
+ code_area(Parent)
+ end,
+ {CodePanel, [Code],_} = create_subwindow(LeftSplitter, "Code", [CreateCode]),
+
+ wxSplitterWindow:splitVertically(LeftSplitter, LBPanel, CodePanel,
+ [{sashPosition,150}]),
+
+ %% Demo:
+ {DemoPanel, [], DemoSz} = create_subwindow(UpperSplitter, "Demo", []),
+
+ %% UpperSplitter:
+ wxSplitterWindow:splitVertically(UpperSplitter, LeftSplitter, DemoPanel,
+ [{sashPosition,600}]),
+
+ %% TopSplitter:
+ AddEvent = fun(Parent) ->
+ EventText = wxTextCtrl:new(Parent,
+ ?wxID_ANY,
+ [{style, ?wxTE_DONTWRAP bor
+ ?wxTE_MULTILINE bor ?wxTE_READONLY}
+ ]),
+ wxTextCtrl:appendText(EventText, "Welcome\n"),
+ EventText
+ end,
+
+ {EvPanel, [EvCtrl],_} = create_subwindow(TopSplitter, "Events", [AddEvent]),
+
+ wxSplitterWindow:splitHorizontally(TopSplitter, UpperSplitter, EvPanel,
+ [{sashPosition,-100}]),
+
+ wxFrame:show(Frame),
+
+ State = #state{win=Frame, demo={DemoPanel,DemoSz}, selector=LB, log=EvCtrl, code=Code},
+ %% Load the first example:
+ Ex = wxListBox:getStringSelection(LB),
+ process_flag(trap_exit, true),
+ ExampleObj = load_example(Ex, State),
+ wxSizer:add(DemoSz, ExampleObj, [{proportion,1}, {flag, ?wxEXPAND}]),
+ wxSizer:layout(DemoSz),
+
+ %% The windows should be set up now, Reset Gravity so we get what we want
+ wxSplitterWindow:setSashGravity(TopSplitter, 1.0),
+ wxSplitterWindow:setSashGravity(UpperSplitter, 0.0),
+ wxSplitterWindow:setSashGravity(LeftSplitter, 0.0),
+ wxSplitterWindow:setMinimumPaneSize(TopSplitter, 1),
+ wxSplitterWindow:setMinimumPaneSize(UpperSplitter, 1),
+ wxSplitterWindow:setMinimumPaneSize(LeftSplitter, 1),
+
+ wxToolTip:enable(true),
+ wxToolTip:setDelay(500),
+
+ {Frame, State#state{example=ExampleObj}}.
+
+create_subwindow(Parent, BoxLabel, Funs) ->
+ Panel = wxPanel:new(Parent),
+ Sz = wxStaticBoxSizer:new(?wxVERTICAL, Panel, [{label, BoxLabel}]),
+ wxPanel:setSizer(Panel, Sz),
+ Ctrls = [Fun(Panel) || Fun <- Funs],
+ [wxSizer:add(Sz, Ctrl, [{proportion, 1}, {flag, ?wxEXPAND}])
+ || Ctrl <- Ctrls],
+ {Panel, Ctrls, Sz}.
+
+%%%%%%%%%%%%
+%% Callbacks
+
+%% Handled as in normal gen_server callbacks
+handle_info({'EXIT',_, wx_deleted}, State) ->
+ {noreply,State};
+handle_info({'EXIT',_, normal}, State) ->
+ {noreply,State};
+handle_info(Msg, State) ->
+ io:format("Got Info ~p~n",[Msg]),
+ {noreply,State}.
+
+handle_call(Msg, _From, State) ->
+ io:format("Got Call ~p~n",[Msg]),
+ {reply,ok,State}.
+
+%% Async Events are handled in handle_event as in handle_info
+handle_event(#wx{event=#wxCommand{type=command_listbox_selected, cmdString=Ex}},
+ State = #state{demo={_,DemoSz}, example=Example, code=Code}) ->
+ case Ex of
+ [] ->
+ {noreply, State};
+ _ ->
+ wxSizer:detach(DemoSz, Example),
+ wxWindow:destroy(Example),
+ unload_code(Code),
+ NewExample = load_example(Ex, State),
+ wxSizer:add(DemoSz, NewExample, [{proportion,1}, {flag, ?wxEXPAND}]),
+ wxSizer:layout(DemoSz),
+ {noreply, State#state{example=NewExample}}
+ end;
+handle_event(#wx{id = Id,
+ event = #wxCommand{type = command_menu_selected}},
+ State = #state{}) ->
+ case Id of
+ ?wxID_PRINT ->
+ %% If you are going to printout mainly text it is easier if
+ %% you generate HTML code and use a wxHtmlEasyPrint
+ %% instead of using DCs
+ Module = "ex_" ++ wxListBox:getStringSelection(State#state.selector) ++ ".erl",
+ HEP = wxHtmlEasyPrinting:new([{name, "Print"},
+ {parentWindow, State#state.win}]),
+ Html = demo_html_tagger:erl2htmltext(Module),
+ wxHtmlEasyPrinting:previewText(HEP, Html),
+ {noreply, State};
+ ?DEBUG_TRACE ->
+ wx:debug(trace),
+ {noreply, State};
+ ?DEBUG_DRIVER ->
+ wx:debug(driver),
+ {noreply, State};
+ ?DEBUG_VERBOSE ->
+ wx:debug(verbose),
+ {noreply, State};
+ ?DEBUG_NONE ->
+ wx:debug(none),
+ {noreply, State};
+ ?wxID_HELP ->
+ wx_misc:launchDefaultBrowser("http://www.erlang.org/doc/apps/wx/part_frame.html"),
+ {noreply, State};
+ ?wxID_ABOUT ->
+ AboutString =
+ "Demo of various widgets\n"
+ "Authors: Olle & Dan",
+ wxMessageDialog:showModal(wxMessageDialog:new(State#state.win, AboutString,
+ [{style,
+ ?wxOK bor
+ ?wxICON_INFORMATION bor
+ ?wxSTAY_ON_TOP},
+ {caption, "About"}])),
+ {noreply, State};
+ ?wxID_EXIT ->
+ wx_object:get_pid(State#state.example) ! stop,
+ {stop, normal, State};
+ _ ->
+ {noreply, State}
+ end;
+handle_event(#wx{event=#wxClose{}}, State = #state{win=Frame}) ->
+ io:format("~p Closing window ~n",[self()]),
+ ok = wxFrame:setStatusText(Frame, "Closing...",[]),
+ {stop, normal, State};
+handle_event(Ev,State) ->
+ io:format("~p Got event ~p ~n",[?MODULE, Ev]),
+ {noreply, State}.
+
+code_change(_, _, State) ->
+ {stop, not_yet_implemented, State}.
+
+terminate(_Reason, State) ->
+ wx_object:get_pid(State#state.example) ! stop,
+ timer:sleep(200), %% Give the example process some time to cleanup.
+ wx:destroy().
+
+%%%%%%%%%%%%%%%%% Internals %%%%%%%%%%
+
+load_example(Ex, #state{demo={DemoPanel,DemoSz}, log=EvCtrl, code=Code}) ->
+ ModStr = "ex_" ++ Ex,
+ Mod = list_to_atom(ModStr),
+%% WxDir = code:lib_dir(wx),
+%% ModFile = filename:join([WxDir, "examples","demo", ModStr ++ ".erl"]),
+ ModFile = ModStr ++ ".erl",
+ load_code(Code, file:read_file(ModFile)),
+ find(Code),
+ Mod:start([{parent, DemoPanel}, {demo_sz, DemoSz}, {log, EvCtrl}]).
+
+-define(stc, wxStyledTextCtrl).
+
+code_area(Parent) ->
+ FixedFont = wxFont:new(10, ?wxFONTFAMILY_TELETYPE, ?wxNORMAL, ?wxNORMAL,[]),
+ Ed = wxStyledTextCtrl:new(Parent),
+
+ ?stc:styleClearAll(Ed),
+ ?stc:styleSetFont(Ed, ?wxSTC_STYLE_DEFAULT, FixedFont),
+ ?stc:setLexer(Ed, ?wxSTC_LEX_ERLANG),
+ ?stc:setMarginType(Ed, 0, ?wxSTC_MARGIN_NUMBER),
+ LW = ?stc:textWidth(Ed, ?wxSTC_STYLE_LINENUMBER, "9"),
+ ?stc:setMarginWidth(Ed, 0, LW),
+ ?stc:setMarginWidth(Ed, 1, 0),
+
+ ?stc:setSelectionMode(Ed, ?wxSTC_SEL_LINES),
+ %%?stc:hideSelection(Ed, true),
+
+ Styles = [{?wxSTC_ERLANG_DEFAULT, {0,0,0}},
+ {?wxSTC_ERLANG_COMMENT, {160,53,35}},
+ {?wxSTC_ERLANG_VARIABLE, {150,100,40}},
+ {?wxSTC_ERLANG_NUMBER, {5,5,100}},
+ {?wxSTC_ERLANG_KEYWORD, {130,40,172}},
+ {?wxSTC_ERLANG_STRING, {170,45,132}},
+ {?wxSTC_ERLANG_OPERATOR, {30,0,0}},
+ {?wxSTC_ERLANG_ATOM, {0,0,0}},
+ {?wxSTC_ERLANG_FUNCTION_NAME, {64,102,244}},
+ {?wxSTC_ERLANG_CHARACTER,{236,155,172}},
+ {?wxSTC_ERLANG_MACRO, {40,144,170}},
+ {?wxSTC_ERLANG_RECORD, {40,100,20}},
+ {?wxSTC_ERLANG_SEPARATOR,{0,0,0}},
+ {?wxSTC_ERLANG_NODE_NAME,{0,0,0}}],
+ SetStyle = fun({Style, Color}) ->
+ ?stc:styleSetFont(Ed, Style, FixedFont),
+ ?stc:styleSetForeground(Ed, Style, Color)
+ end,
+ [SetStyle(Style) || Style <- Styles],
+ ?stc:setKeyWords(Ed, 0, keyWords()),
+
+ %% Scrolling
+ Policy = ?wxSTC_CARET_SLOP bor ?wxSTC_CARET_JUMPS bor ?wxSTC_CARET_EVEN,
+ ?stc:setYCaretPolicy(Ed, Policy, 3),
+ ?stc:setVisiblePolicy(Ed, Policy, 3),
+
+ %% ?stc:connect(Ed, stc_doubleclick),
+ ?stc:setReadOnly(Ed, true),
+ Ed.
+
+load_code(Ed, {ok, Code}) ->
+ ?stc:setReadOnly(Ed, false),
+ ?stc:setTextRaw(Ed, <<Code/binary, 0:8>>),
+ Lines = ?stc:getLineCount(Ed),
+ Sz = trunc(math:log10(Lines))+1,
+ LW = ?stc:textWidth(Ed, ?wxSTC_STYLE_LINENUMBER, lists:duplicate(Sz, $9)),
+ %%io:format("~p ~p ~p~n", [Lines, Sz, LW]),
+ ?stc:setMarginWidth(Ed, 0, LW+5),
+ ?stc:setReadOnly(Ed, true),
+ Ed.
+
+unload_code(Ed) ->
+ ?stc:setReadOnly(Ed, false),
+ ?stc:setTextRaw(Ed, <<0:8>>),
+ ?stc:setReadOnly(Ed, true),
+ Ed.
+
+find(Ed) ->
+ ?stc:searchAnchor(Ed),
+ Res = ?stc:searchNext(Ed, ?wxSTC_FIND_REGEXP, "^init"),
+ case Res >= 0 of
+ true ->
+ %% io:format("Found ~p ~n",[Res]),
+ ?stc:scrollToLine(Ed,?stc:lineFromPosition(Ed,Res) - 1),
+ true;
+ false ->
+ io:format("Not Found ~s ~n",["^init"]),
+ false
+ end.
+
+keyWords() ->
+ L = ["after","begin","case","try","cond","catch","andalso","orelse",
+ "end","fun","if","let","of","query","receive","when","bnot","not",
+ "div","rem","band","and","bor","bxor","bsl","bsr","or","xor"],
+ lists:flatten([K ++ " " || K <- L] ++ [0]).
+