diff options
Diffstat (limited to 'lib/pman/src/pman_options.erl')
-rw-r--r-- | lib/pman/src/pman_options.erl | 395 |
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. |