📄 et_viewer.erl
字号:
%% %% ViewerPid = pid()%%----------------------------------------------------------------------stop(ViewerPid) -> call(ViewerPid, stop).call(ViewerPid, Request) -> gen_server:call(ViewerPid, Request, infinity).%%%----------------------------------------------------------------------%%% Callback functions from gen_server%%%----------------------------------------------------------------------%%----------------------------------------------------------------------%% Func: init/1%% Returns: {ok, State} |%% {ok, State, Timeout} |%% ignore |%% {stop, Reason}%%----------------------------------------------------------------------init([S]) when record(S, state) -> process_flag(trap_exit, true), InitialTimeout = 0, case S#state.parent_pid of undefined -> ignore; Pid when pid(Pid) -> link(Pid) end, et_collector:dict_insert(S#state.collector_pid, {subscriber, self()}, ?MODULE), {ok, create_main_window(S), InitialTimeout}.%%----------------------------------------------------------------------%% Func: handle_call/3%% Returns: {reply, Reply, State} |%% {reply, Reply, State, Timeout} |%% {noreply, State} |%% {noreply, State, Timeout} |%% {stop, Reason, Reply, State} | (terminate/2 is called)%% {stop, Reason, State} (terminate/2 is called)%%----------------------------------------------------------------------handle_call(get_collector_pid, _From, S) -> Reply = S#state.collector_pid, reply(Reply, S);handle_call(stop, _From, S) -> gs:destroy(S#state.win), {stop, shutdown, ok, S};handle_call(Request, From, S) -> ok = error_logger:format("~p(~p): handle_call(~p, ~p, ~p)~n", [?MODULE, self(), Request, From, S]), Reply = {error, {bad_request, Request}}, reply(Reply, S).%%----------------------------------------------------------------------%% Func: handle_cast/2%% Returns: {noreply, State} |%% {noreply, State, Timeout} |%% {stop, Reason, State} (terminate/2 is called)%%----------------------------------------------------------------------handle_cast(Msg, S) -> ok = error_logger:format("~p(~p): handle_cast(~p, ~p)~n", [?MODULE, self(), Msg, S]), noreply(S).%%----------------------------------------------------------------------%% Func: handle_info/2%% Returns: {noreply, State} |%% {noreply, State, Timeout} |%% {stop, Reason, State} (terminate/2 is called)%%----------------------------------------------------------------------handle_info({et, {insert_actors, ActorNames}}, S) when list(ActorNames) -> Fun = fun(N, Actors) -> case lists:keymember(N, #actor.name, Actors) of true -> Actors; false -> Actors ++ [create_actor(N)] end end, Actors = lists:foldl(Fun, S#state.actors, ActorNames), S2 = refresh_main_window(S#state{actors = Actors}), noreply(S2);handle_info({et, {delete_actors, ActorNames}}, S) when list(ActorNames)-> Fun = fun(N, Actors) when N == ?unknown -> Actors; (N, Actors) -> lists:keydelete(N, #actor.name, Actors) end, New = lists:foldl(Fun, S#state.actors, ActorNames), S2 = refresh_main_window(S#state{actors = New}), noreply(S2);handle_info({et, {dict_insert, Key, Val}}, S) -> S2 = do_dict_insert(Key, Val, S), noreply(S2);handle_info({et, {dict_delete, Key}}, S) -> S2 = do_dict_delete(Key, S), noreply(S2);handle_info({et, first}, S) -> S2 = scroll_first(S), noreply(S2);handle_info({et, prev}, S) -> S2 = scroll_prev(S), noreply(S2);handle_info({et, next}, S) -> S2 = scroll_next(S), noreply(S2);handle_info({et, last}, S) -> S2 = scroll_last(S), noreply(S2);handle_info({et, refresh}, S) -> S2 = refresh_main_window(S), noreply(S2);handle_info({et, {display_mode, Mode}}, S) -> S2 = change_display_mode(Mode, S), noreply(S2);handle_info({et, close}, S) -> gs:destroy(S#state.win), {stop, shutdown, S};handle_info({gs, Button, click, Data, Other} = Click, S) -> CollectorPid = S#state.collector_pid, case Button of close -> gs:destroy(S#state.win), {stop, shutdown, S}; suspended -> case Other of [_Text, _Group, Bool | _] when Bool == true -> S2 = do_suspend(S), noreply(S2); [_Text, _Group, Bool | _] when Bool == false -> S2 = do_resume(S), noreply(S2); _ -> click_error(Click, S), noreply(S) end; hide_actions -> case Other of [_Text, _Group, Bool | _] when Bool == true -> S2 = refresh_main_window(S#state{hide_actions = Bool}), noreply(S2); [_Text, _Group, Bool | _] when Bool == false -> S2 = refresh_main_window(S#state{hide_actions = Bool}), noreply(S2); _ -> click_error(Click, S), noreply(S) end; hide_unknown -> case Other of [_Text, _Group, Bool | _] when Bool == true -> S2 = refresh_main_window(S#state{hide_unknown = Bool}), noreply(S2); [_Text, _Group, Bool | _] when Bool == false -> S2 = refresh_main_window(S#state{hide_unknown = Bool}), noreply(S2); _ -> click_error(Click, S), noreply(S) end; up -> S2 = scroll_up(S), noreply(S2); down -> S2 = scroll_down(S), noreply(S2); first -> S2 = scroll_first(S), noreply(S2); prev -> S2 = scroll_prev(S), noreply(S2); next -> S2 = scroll_next(S), noreply(S2); last -> S2 = scroll_last(S), noreply(S2); refresh -> S2 = refresh_main_window(S), noreply(S2); {display_mode, Mode} -> S2 = change_display_mode(Mode, S), noreply(S2); close_all -> close_all(S); close_all_others -> close_all_others(S); first_all -> et_collector:multicast(CollectorPid, first), noreply(S); prev_all -> et_collector:multicast(CollectorPid, prev), noreply(S); next_all -> et_collector:multicast(CollectorPid, next), noreply(S); last_all -> et_collector:multicast(CollectorPid, last), noreply(S); refresh_all -> et_collector:multicast(CollectorPid, refresh), noreply(S); clear_all -> et_collector:clear_table(CollectorPid), et_collector:multicast(CollectorPid, refresh), noreply(S); load_all -> et_collector:start_trace_client(CollectorPid, event_file, "et_viewer.log"), noreply(S); save_all -> et_collector:save_event_file(CollectorPid, "et_viewer.log", [existing, write, keep]), noreply(S); {open_viewer, Scale} -> Actors = [A#actor.name || A <- S#state.actors], open_viewer(Scale, S#state.active_filter, Actors, S), noreply(S); _Level when Data == detail_level, integer(hd(Other)), hd(Other) >= ?detail_level_min, hd(Other) =< ?detail_level_max -> S2 = S#state{detail_level = hd(Other)}, noreply(S2); _PopupMenuItem when record(Data, filter) -> open_viewer(S#state.scale, Data#filter.name, [?unknown], S), noreply(S); _ -> click_error(Click, S), noreply(S) end;handle_info({gs, _Obj, destroy,_, _}, S) -> gs:destroy(S#state.win), {stop, shutdown, S};handle_info({gs, _Obj, buttonpress, _, [_Button, X, Y | _]}, S) -> S3 = case y_to_n(Y, S) of actor -> %% Actor click case S#state.actors of [] -> S; _ -> N = x_to_n(X, S), A = lists:nth(N, S#state.actors), S#state{selected_actor = A} end; {event, N} -> %% Event click List = queue_to_list(S#state.events), S2 = S#state{events = list_to_queue(List)}, Key = lists:nth(N, List), Pid = S#state.collector_pid, Fun = fun create_contents_window/2, case et_collector:iterate(Pid, Key, -1) of Prev when Prev == Key -> et_collector:iterate(Pid, first, 1, Fun, S2); Prev -> et_collector:iterate(Pid, Prev, 1, Fun, S2) end end, noreply(S3);handle_info({gs, _Obj, buttonrelease, _, [_Button, X, Y | _]}, S) -> S2 = case y_to_n(Y, S) of actor -> %% Actor click case S#state.actors of [] -> S; Actors -> N = x_to_n(X, S), New = lists:nth(N, S#state.actors), Old = S#state.selected_actor, case New#actor.name == Old#actor.name of true -> A = S#state.selected_actor, toggle_search_for_actor(A#actor.name, S); false -> move_actor(Old, New, Actors, S) end end; {event, _N} -> %% Event click ignored S end, noreply(S2);handle_info({gs, _Obj, keypress, _, [KeySym, _Keycode, _Shift, _Control | _]} = Key, S) -> case KeySym of 'c' -> close_all_others(S); 'C' -> close_all(S); 'Up' -> S2 = scroll_up(S), noreply(S2); 'Down' -> S2 = scroll_down(S), noreply(S2); 'f' -> S2 = scroll_first(S), noreply(S2); 'p' -> S2 = scroll_prev(S), noreply(S2); 'Prior' -> S2 = scroll_prev(S), noreply(S2); 'n' -> S2 = scroll_next(S), noreply(S2); 'Next' -> S2 = scroll_next(S), noreply(S2); 'l' -> S2 = scroll_last(S), noreply(S2); 'r' -> S2 = refresh_main_window(S), noreply(S2); 'F' -> et_collector:multicast(S#state.collector_pid, first), noreply(S); 'P' -> et_collector:multicast(S#state.collector_pid, prev), noreply(S); 'N' -> et_collector:multicast(S#state.collector_pid, next), noreply(S); 'L' -> et_collector:multicast(S#state.collector_pid, last), noreply(S); 'R' -> et_collector:multicast(S#state.collector_pid, refresh), noreply(S); 'a' -> S2 = S#state{display_mode = all}, S3 = refresh_main_window(S2), noreply(S3); 'equal' -> Scale = S#state.scale, Actors = [A#actor.name || A <- S#state.actors], open_viewer(Scale, S#state.active_filter, Actors, S), noreply(S); 'plus' -> Scale = S#state.scale + 1, Actors = [A#actor.name || A <- S#state.actors], open_viewer(Scale, S#state.active_filter, Actors, S), noreply(S); 'minus' -> case S#state.scale of 1 -> gs:config(S#state.canvas, beep); Scale -> Actors = [A#actor.name || A <- S#state.actors], open_viewer(Scale - 1, S#state.active_filter, Actors, S) end, noreply(S); 0 -> case lists:keysearch(collector, #filter.name, S#state.filters) of {value, F} when record(F, filter) -> open_viewer(S#state.scale, F#filter.name, [?unknown], S); false -> gs:config(S#state.canvas, beep) end, noreply(S); Int when integer(Int), Int > 0, Int =< 9 -> case catch lists:nth(Int, S#state.filters) of F when record(F, filter) -> open_viewer(S#state.scale, F#filter.name, [?unknown], S); {'EXIT', _} -> gs:config(S#state.canvas, beep) end, noreply(S); 'Shift_L' -> noreply(S); 'Shift_R' -> noreply(S); 'Caps_Lock' -> noreply(S); _ -> click_error(Key, S), noreply(S) end;handle_info({gs, _Obj,configure, [], [W, H | _]}, S) -> gs:config(S#state.packer, [{width, W}, {height, H}]), S2 = S#state{width = W, height = H}, noreply(S2);handle_info(timeout, S) -> Try = case S#state.display_mode of {search_actors, reverse, _, _} -> -10;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -