%% %% %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.