aboutsummaryrefslogtreecommitdiffstats
path: root/lib/pman/src/pman_options.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pman/src/pman_options.erl')
-rw-r--r--lib/pman/src/pman_options.erl395
1 files changed, 395 insertions, 0 deletions
diff --git a/lib/pman/src/pman_options.erl b/lib/pman/src/pman_options.erl
new file mode 100644
index 0000000000..0765458fdc
--- /dev/null
+++ b/lib/pman/src/pman_options.erl
@@ -0,0 +1,395 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-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(pman_options).
+
+%% Window with trace options settings (File->Options...)
+
+-export([dialog/3,
+ read_from_file/1, save_to_file/2]).
+
+-include("pman_options.hrl").
+
+-define(WIN_WIDTH, 350).
+-define(WIN_HEIGHT, 350).
+
+-define(TOP_WINDOW, xx_pman_option_window_xx).
+-define(TOP_FRAME, xx_pman_top_frame_xx).
+
+-record(state, {resize_frame, % GS identifier for the main frame
+ parent}). % Pid of parent
+
+%%--dialog/3------------------------------------------------------------
+%% Create a window, or return a value indicating that is is already
+%% created.
+
+dialog(ParentWin, Title, Options) ->
+ Self = self(),
+ Pid = spawn(fun() -> dialog(Self, ParentWin, Title, Options) end),
+ receive
+ {Pid, Value} ->
+ Value % Options2 | {error,destroyed} | {error,cancelled}
+ end.
+
+dialog(Parent, ParentWin, Title, Options) ->
+
+ %% Check if the dialog has already been created, in that
+ %% case, we can reuse it. Otherwise a new dialog is created.
+ case gse:name_occupied(?TOP_WINDOW) of
+ false -> make_window(ParentWin, Title);
+ true -> ok
+ end,
+
+ %% Window has now been created or may be re-used
+ update_window_from_options(Options),
+
+ gse:resize(?TOP_FRAME, ?WIN_WIDTH, ?WIN_HEIGHT),
+ gse:map(?TOP_WINDOW),
+
+ loop(#state{resize_frame=?TOP_FRAME, parent=Parent}).
+
+loop(State) ->
+ receive
+ {gs, _Id, destroy, _Data, _Arg} ->
+ State#state.parent ! {self(), {error,destroyed}};
+
+ {gs, ?TOP_WINDOW, configure, _Data, [W, H |_]} ->
+ gse:config(State#state.resize_frame,
+ [{width,W},{height,H}]), % repack
+ loop(State);
+
+ {gs, ok_button, click, _Data, _Arg} ->
+ Options = get_options_from_window(),
+ gse:unmap(?TOP_WINDOW),
+ State#state.parent ! {self(), Options};
+
+ {gs, cancel_button, click, _Data, _Arg} ->
+ gse:unmap(?TOP_WINDOW),
+ State#state.parent ! {self(), {error,cancelled}};
+
+ {gs, trace_spawn, click, _Data, [_Text,_,Value]} ->
+ group_radio(Value, trace_spawn_all, [trace_spawn_all,
+ trace_spawn_first]),
+ loop(State);
+
+ {gs, trace_link, click, _Data, [_Text,_,Value]} ->
+ group_radio(Value, trace_link_all, [trace_link_all,
+ trace_link_first]),
+ loop(State);
+
+ {gs, trace_in_window, click, _Data, _Arg} ->
+ lists:foreach(fun(X) -> gse:disable(X) end,
+ [trace_file, trace_file_browse]),
+ loop(State);
+
+ {gs, trace_to_file, click, _Data, [_Text,_,_Value]} ->
+ lists:foreach(fun(X) -> gse:enable(X) end,
+ [trace_file, trace_file_browse]),
+ loop(State);
+
+ {gs, trace_file_browse, click, _Data, _Arg} ->
+ Result = tool_utils:file_dialog([{type,save},
+ {file, "Untitled.log"}]),
+ case Result of
+ {error, _Reason} ->
+ loop(State);
+ {ok, Name,_State} ->
+ gse:config(trace_file, [{text, Name}]),
+ loop(State)
+ end
+ end.
+
+-define(LBLOPTS, [{justify,left}, {align,w}]).
+-define(BTNOPTS, [{justify,left}, {align,w}]).
+
+make_window(ParentWin, Title) ->
+
+ Font = pman_win:font(),
+
+ gse:named_window(?TOP_WINDOW, ParentWin, [{title,Title},
+ {configure,true},
+ {width, ?WIN_WIDTH},
+ {height, ?WIN_HEIGHT}]),
+
+ gse:named_frame(?TOP_FRAME, ?TOP_WINDOW,
+ [{bw,3},
+ {packer_x,[{stretch,1,175}, {stretch,1,175}]},
+ {packer_y,[{stretch,3},{stretch,2},{stretch,1}]}]),
+
+ F11 = gse:frame(?TOP_FRAME, [{bw,3},
+ {pack_xy,{1,1}},
+ {packer_x,[{stretch,1},
+ {stretch,20},
+ {stretch,2}]},
+ {packer_y,[{stretch,2},
+ {stretch,1},
+ {stretch,1},
+ {stretch,1},
+ {stretch,1},
+ {stretch,1},
+ {stretch,1},
+ {stretch,1}]}]),
+
+ gse:label(F11,[{pack_xy,{2,1}},
+ {label,{text,"Trace output options:"}},
+ {font,Font} | ?LBLOPTS]),
+
+ gse:named_checkbutton(trace_send, F11,
+ [{pack_xy,{2,2}},
+ {label,{text,"Trace send"}},
+ {font,Font} | ?BTNOPTS]),
+ gse:named_checkbutton(trace_receive, F11,
+ [{pack_xy,{2,3}},
+ {label,{text, "Trace receive"}},
+ {font,Font} | ?BTNOPTS]),
+ gse:named_checkbutton(trace_functions,F11,
+ [{pack_xy,{2,4}},
+ {label,{text, "Trace functions"}},
+ {font,Font} | ?BTNOPTS]),
+ gse:named_checkbutton(trace_events,F11,
+ [{pack_xy,{2,5}},
+ {label,{text, "Trace events"}},
+ {font,Font} | ?BTNOPTS]),
+
+ F21 = gse:frame(?TOP_FRAME, [{bw,3},
+ {pack_xy,{2,1}},
+ {packer_x,[{stretch,1},
+ {stretch,2},
+ {stretch,2},
+ {stretch,20},
+ {stretch,1}]},
+ {packer_y,[{stretch,2},
+ {stretch,1},
+ {stretch,1},
+ {stretch,1},
+ {stretch,1},
+ {stretch,1},
+ {stretch,1},
+ {stretch,1},
+ {stretch,1}]}]),
+
+ gse:label(F21, [{pack_xy,{{2,4},1}},
+ {label,{text,"Inheritance options:"}},
+ {font,Font} | ?LBLOPTS]),
+
+ gse:named_checkbutton(trace_spawn, F21,
+ [{pack_xy,{{2,4},2}},
+ {data,trace_send},
+ {label,{text,"Inherit on spawn"}},
+ {font,Font} | ?BTNOPTS]),
+ gse:named_radiobutton(trace_spawn_all, F21,
+ [{pack_xy,{{3,4},3}},
+ {group,spawn},
+ {data,trace_receive},
+ {label,{text, "All spawns"}},
+ {font,Font} | ?BTNOPTS]),
+ gse:named_radiobutton(trace_spawn_first, F21,
+ [{pack_xy,{{3,4},4}},
+ {group,spawn},
+ {data,trace_receive},
+ {label,{text,"First spawn only"}},
+ {font,Font} | ?BTNOPTS]),
+ gse:named_checkbutton(trace_link, F21,
+ [{pack_xy,{{2,4},6}},
+ {data,trace_send},
+ {label,{text,"Inherit on link"}},
+ {font,Font} | ?BTNOPTS]),
+ gse:named_radiobutton(trace_link_all, F21,
+ [{pack_xy,{{3,4},7}},
+ {group,link},
+ {data,trace_receive},
+ {label,{text,"All links"}},
+ {font,Font} | ?BTNOPTS]),
+
+ gse:named_radiobutton(trace_link_first, F21,
+ [{pack_xy,{{3,4},8}},
+ {group,link},
+ {data,trace_receive},
+ {label,{text,"First link only"}},
+ {font,Font} | ?BTNOPTS]),
+
+ F12 = gse:frame(?TOP_FRAME, [{bw,3},
+ {pack_xy,{{1,2},2}},
+ {packer_x,[{stretch,1},
+ {stretch,5}, % Label
+ {stretch,1},
+ {stretch,10}, % Field
+ {stretch,1},
+ {stretch,5}, % Button
+ {stretch,1}]},
+ {packer_y,[{stretch,2},
+ {stretch,1},
+ {stretch,1},
+ {stretch,1}]}]),
+
+ gse:label(F12, [{pack_xy,{{2,6},1}},
+ {label,{text,"Trace output options:"}},
+ {font,Font} | ?LBLOPTS]),
+ gse:named_radiobutton(trace_in_window, F12,
+ [{pack_xy,{{2,6},2}},
+ {group, trace_dest},
+ {label,{text,"In window"}},
+ {font,Font} | ?BTNOPTS]),
+ gse:named_radiobutton(trace_to_file, F12,
+ [{pack_xy,{2,3}},
+ {group, trace_dest},
+ {label,{text,"To file"}},
+ {font,Font} | ?BTNOPTS]),
+ gse:named_entry(trace_file, F12, [{pack_xy,{4,3}}, {font,Font}]),
+ gse:named_button(trace_file_browse, F12,
+ [{pack_xy,{6,3}},
+ {label,{text," Browse..."}},
+ {font,Font} | ?BTNOPTS]),
+
+ F13 = gse:frame(?TOP_FRAME, [{bw,3},
+ {pack_xy,{{1,2},3}},
+ {packer_x,[{stretch, 1},
+ {fixed, 60},
+ {stretch, 1},
+ {fixed, 60},
+ {stretch, 1}]},
+ {packer_y,[{stretch,1},
+ {fixed, 30},
+ {stretch,1}]}]),
+
+ gse:named_button(ok_button, F13, [{pack_xy,{2,2}},
+ {label,{text,"OK"}},
+ {font,Font}]),
+ gse:named_button(cancel_button, F13, [{pack_xy,{4,2}},
+ {label,{text,"Cancel"}},
+ {font,Font}]).
+
+update_window_from_options(Options) ->
+
+ %% Trace output
+ gse:config(trace_send, [{select,Options#trace_options.send}]),
+ gse:config(trace_receive,
+ [{select,Options#trace_options.treceive}]),
+ gse:config(trace_functions,
+ [{select,Options#trace_options.functions}]),
+ gse:config(trace_events, [{select,Options#trace_options.events}]),
+
+ %% Trace inheritance
+ case (Options#trace_options.inherit_on_all_spawn or
+ Options#trace_options.inherit_on_1st_spawn) of
+ true ->
+ gse:select(trace_spawn),
+ gse:config(trace_spawn_all,
+ [{select,Options#trace_options.inherit_on_all_spawn}]),
+ gse:config(trace_spawn_first,
+ [{select,Options#trace_options.inherit_on_1st_spawn}]);
+ false ->
+ lists:foreach(fun(X) -> gse:disable(X) end,
+ [trace_spawn_all,trace_spawn_first])
+ end,
+
+ case (Options#trace_options.inherit_on_all_link or
+ Options#trace_options.inherit_on_1st_link) of
+ true -> gse:select(trace_link),
+ gse:config(trace_link_all,
+ [{select,Options#trace_options.inherit_on_all_link}]),
+ gse:config(trace_link_first,
+ [{select, Options#trace_options.inherit_on_1st_link}]);
+ false ->
+ lists:foreach(fun(X) -> gse:disable(X) end,
+ [trace_link_all,trace_link_first])
+ end,
+
+ %% Trace ouput destinations
+ gse:config(trace_in_window,
+ [{select,(not Options#trace_options.to_file)}]),
+
+ gse:config(trace_to_file, [{select,Options#trace_options.to_file}]),
+ gse:config(trace_file, [{text,Options#trace_options.file}]),
+ case Options#trace_options.to_file of
+ true ->
+ ok;
+ false ->
+ lists:foreach(fun(X) -> gse:disable(X) end,
+ [trace_file, trace_file_browse])
+ end.
+
+get_options_from_window() ->
+ #trace_options{send = gse:read(trace_send,select),
+ treceive = gse:read(trace_receive,select),
+ functions = gse:read(trace_functions,select),
+ events = gse:read(trace_events,select),
+ inherit_on_1st_spawn = gse:read(trace_spawn_first,select),
+ inherit_on_all_spawn = gse:read(trace_spawn_all,select),
+ inherit_on_1st_link = gse:read(trace_link_first,select),
+ inherit_on_all_link = gse:read(trace_link_all,select),
+ to_file = gse:read(trace_to_file,select),
+ file = gse:read(trace_file,text)}.
+
+group_radio(Value, Default, GroupList) ->
+ case Value of
+ true ->
+ gse:select(Default),
+ lists:foreach(fun(X) -> gse:enable(X) end, GroupList);
+ false ->
+ lists:foreach(fun(X) -> gse:deselect(X) end, GroupList),
+ lists:foreach(fun(X) -> gse:disable(X) end, GroupList)
+ end.
+
+%%--read_from_file/(File)-----------------------------------------------
+%% Returns the options saved in File.
+%% If no options can be found, then the default options are
+%% returned.
+
+read_from_file(File) ->
+ case file:consult(File) of
+ {ok, [Term]} ->
+ if
+ is_record(Term, trace_options) ->
+ {ok, Term};
+ true ->
+ {error, "unexpected contents", #trace_options{}}
+ end;
+ {ok, _Terms} ->
+ {error, "unexpected contents", #trace_options{}};
+ {error, Tuple} when is_tuple(Tuple) -> % {Line,Mod,Term}
+ {error, "erroneous contents", #trace_options{}};
+ {error, _Posix} ->
+ %% The most probable reason is that the file does not
+ %% exist, this is not an error so we simply return
+ %% the default trace options instead
+ {ok, #trace_options{}}
+ end.
+
+%%--save_to_file(Options, File)-----------------------------------------
+
+save_to_file(Options, File) ->
+ case file:open(File, [write]) of
+ {ok, Fd} ->
+ {{Year,Month,Day},{H,M,S}} = calendar:local_time(),
+ io:format(Fd, "%%%~n", []),
+ io:format(Fd, "%%% File: ~s~n", [File]),
+ io:format(Fd, "%%% Date: ~w-~2..0w-~2..0w, ~2..0w:~2..0w:~2..0w~n",
+ [Year,Month,Day,H,M,S]),
+ io:format(Fd, "%%%~n", []),
+ io:format(Fd, "%%% This file was created by Pman. ~n", []),
+ io:format(Fd, "%%%~n", []),
+ io:format(Fd, "%%% DO NOT EDIT! ~n", []),
+ io:format(Fd, "%%%~n", []),
+ io:format(Fd, "%%%~n", []),
+ io:format(Fd, "~p.~n", [Options]),
+ file:close(Fd),
+ ok;
+ {error, Posix} ->
+ {error, file:format_error(Posix)}
+ end.