📄 et_viewer.erl
字号:
N = length(S#state.actors), if Max == infinity -> N * 2; Max < N -> N; true -> Max end. calc_min_events(S) -> Max = S#state.max_events, N = queue_length(S#state.events), if Max == infinity -> N * 2; Max < N -> N; true -> Max end.display_more_events(Try, S) -> Name = S#state.active_filter, {value, F} = lists:keysearch(Name, #filter.name, S#state.filters), FilterFun = F#filter.function, Fun = fun(Event, State) -> case catch FilterFun(Event) of true -> State2 = ensure_key(Event, State), opt_display_event(Event, State2); {true, Event2} -> State2 = ensure_key(Event2, State), opt_display_event(Event2, State2); false -> ensure_key(Event, State); Bad -> Contents = {bad_filter, Name, Bad, Event}, Event2 = Event#event{contents = Contents, from = bad_filter, to = bad_filter}, State2 = ensure_key(Event2, State), opt_display_event(Event2, State2) end end, Pid = S#state.collector_pid, S2 = et_collector:iterate(Pid, S#state.last_event, Try, Fun, S), case queue_length(S2#state.events) - queue_length(S#state.events) of Diff when Diff == Try -> %% Got as much as requested, look for more %% io:format("Done: ~p~n", [{Try, Diff}]), {noreply, S2, 0}; _Diff when S2#state.first_event == S#state.first_event, S2#state.last_event == S#state.last_event -> %% Got lesser than requested, wait a while before looking for more %% io:format("More: ~p~n", [{Try, Diff}]), {noreply, S2, 500}; _Diff -> %% Got lesser than requested, look for more %% io:format("More2: ~p~n", [{Try, Diff}]), {noreply, S2, 0} end.ensure_key(E, S) when record(E, event), record(S, state) -> Key = et_collector:make_key(S#state.event_order, E), case S#state.first_event of first -> S#state{first_event = Key, last_event = Key}; last -> S#state{first_event = Key, last_event = Key}; _ -> S#state{last_event = Key} end.opt_display_event(E, S) -> case S#state.display_mode of all -> display_event(E, S); {search_actors, _Dir, _FirstKey, Actors} -> %% Key = S#state.last_event, From = select_actor_name(E#event.from, S), case lists:member(From, Actors) of true -> display_event(E, S); false -> To = select_actor_name(E#event.to, S), case lists:member(To, Actors) of true -> display_event(E, S); false -> S end end end.select_actor_name(Name, S) -> case lists:keymember(Name, #actor.name, S#state.actors) of true -> Name; false -> ?unknown end.display_event(E, S) when E#event.detail_level < S#state.detail_level -> {FromRefresh, From} = ensure_actor(E#event.from, S), {FromName, FromPos, S2} = From, {ToRefresh, To} = ensure_actor(E#event.to, S2), {ToName, ToPos, S3} = To, if FromRefresh /= false, ToRefresh /= false -> Key = S#state.last_event, refresh_beep(S), S3#state{refresh_needed = true, events = queue_in(Key, S3#state.events)}; FromName == ToName -> case S#state.hide_actions of true -> S3; false -> Label = name_to_string(E#event.label), draw_named_arrow(Label, FromName, FromPos, ToName, ToPos, S3) end; true -> Label = name_to_string(E#event.label), draw_named_arrow(Label, FromName, FromPos, ToName, ToPos, S3) end;display_event(_, S) -> S.draw_named_arrow(Label, FromName, FromPos, ToName, ToPos, S) -> Key = S#state.last_event, case S#state.y_pos + (?incr_y * S#state.scale) of _ when S#state.hide_unknown == true, FromName == ?unknown -> S; _ when S#state.hide_unknown == true, ToName == ?unknown -> S; Y when Y > S#state.canvas_height -> refresh_beep(S), S#state{refresh_needed = true, events = queue_in(Key, S#state.events)}; Y -> S2 = S#state{y_pos = Y, events = queue_in(Key, S#state.events)}, S3 = draw_arrow(FromPos, ToPos, S2), draw_label(Label, FromName, ToName, FromPos, ToPos, S3) end.refresh_beep(S) -> case S#state.refresh_needed of false -> gs:config(S#state.canvas, beep), gs:config(S#state.canvas, beep), gs:config(S#state.canvas, beep); true -> ignore end.draw_arrow(Pos, Pos, S) -> S;draw_arrow(FromPos, ToPos, S) -> Y = S#state.y_pos, CanOpts = [{coords, [{FromPos , Y}, {ToPos, Y}]}, {arrow, last},{width, 1}, {fg, black}], gs:line(S#state.canvas, CanOpts), S.draw_label(Label, FromName, ToName, FromPos, ToPos, S) -> Colour = if FromName == ?unknown, ToName == ?unknown -> blue; %turquoise; FromName == ?unknown -> orange; ToName == ?unknown -> orange; FromPos == ToPos -> blue; true -> red end, Scale = S#state.scale, X = lists:min([FromPos, ToPos]) + (6 * Scale), Y = S#state.y_pos, write_text(Label, X, Y, Colour, S), S.draw_all_actors(State) -> Scale = State#state.scale, Fun = fun(A, X) -> draw_actor(A, X, State), X + (?incr_x * Scale) end, lists:foldl(Fun, ?initial_x * Scale, State#state.actors), State.%% Returns: {NeedsRefreshBool, {ActorPos, NewsS, NewActors}}ensure_actor(Name, S) -> do_ensure_actor(Name, S, S#state.actors, 0).do_ensure_actor(Name, S, [H | _], N) when H#actor.name == Name -> Pos = (?initial_x + (N * ?incr_x)) * S#state.scale, {false, {Name, Pos, S}};do_ensure_actor(Name, S, [_ | T], N) -> do_ensure_actor(Name, S, T, N + 1);do_ensure_actor(Name, S, [], N) -> %% A brand new actor, let's see if it does fit Pos = (?initial_x + (N * ?incr_x)) * S#state.scale, MaxActors = S#state.max_actors, if integer(MaxActors), N > MaxActors -> %% Failed on max_actors limit, put into unknown %% Assume that unknown always is in actor list ensure_actor(?unknown, S); Pos > (S#state.canvas_width - ((?initial_x - 15) * S#state.scale)) -> %% New actor does not fit in canvas, refresh needed A = create_actor(Name), draw_actor(A, Pos, S), {true, {Name, Pos, S#state{actors = S#state.actors ++ [A]}}}; true -> %% New actor fits in canvas. Draw the new actor. A = create_actor(Name), draw_actor(A, Pos, S), {false, {Name, Pos, S#state{actors = S#state.actors ++ [A]}}} end.draw_actor(A, LineX, S) -> Scale = S#state.scale, TextX = LineX - (5 * Scale), TextY = ?initial_y * Scale, LineTopY = TextY + ((?incr_y / 2) * Scale), LineBotY = S#state.canvas_height - ((?incr_y / 2) * Scale), Colour = case A#actor.name of ?unknown -> orange; _ -> red end, write_text(A#actor.string, TextX, TextY, Colour, S), LineOpt = [{coords, [{LineX, LineTopY}, {LineX, LineBotY}]}, {width, 1}, {fg, Colour}], gs:line(S#state.canvas, LineOpt).toggle_search_for_actor(ActorName,S) -> case S#state.display_mode of all -> io:format("~p: search for: ~p ++ ~p~n", [?MODULE, [], [ActorName]]), %% Search for this actor Key = S#state.first_event, Actors = [ActorName], Mode = {search_actors, forward, Key, Actors}, change_display_mode(Mode, S); {search_actors, Dir, Key, Actors}-> Actors2 = case lists:member(ActorName, Actors) of true -> io:format("~p: search for: ~p -- ~p~n", [?MODULE, Actors, [ActorName]]), %% Remove actor from search list Actors -- [ActorName]; false -> io:format("~p: search for: ~p ++ ~p~n", [?MODULE, Actors, [ActorName]]), %% Add actor from search list [ActorName | Actors] end, Mode2 = {search_actors, Dir, Key, Actors2}, change_display_mode(Mode2, S) end.move_actor(From, To, Actors, S) -> Pos = #actor.name, ToName = To#actor.name, FromName = From#actor.name, ToIx = actor_index(ToName, Pos, Actors), FromIx = actor_index(FromName, Pos, Actors), if FromIx /= 0, ToIx /= 0, ToIx > FromIx -> Actors2 = lists:keydelete(FromName, Pos, Actors), Actors3 = insert_actor_after(From, To, Actors2), S2 = S#state{actors = Actors3}, refresh_main_window(S2); FromIx /= 0, ToIx /= 0 -> Actors2 = lists:keydelete(FromName, Pos, Actors), Actors3 = insert_actor_before(From, To, Actors2), S2 = S#state{actors = Actors3}, refresh_main_window(S2); true -> %% Ignore S end.insert_actor_after(From, To, [H | T]) -> case To#actor.name == H#actor.name of true -> [H, From | T]; false -> [H | insert_actor_after(From, To, T)] end;insert_actor_after(_From, _To, []) -> [].insert_actor_before(From, To, [H | T]) -> case To#actor.name == H#actor.name of true -> [From, H | T]; false -> [H | insert_actor_before(From, To, T)] end;insert_actor_before(_From, _To, []) -> [].actor_index(_Key, _Pos, []) -> 0;actor_index(Key, Pos, [H | T]) -> case Key == element(Pos, H) of false -> actor_index(Key, Pos, T) + 1; true -> 1 end.y_to_n(Y, S) -> Y2 = ((Y / S#state.scale) - ?initial_y + (?incr_y / 2)), N = round(Y2 / ?incr_y - 0.2), MaxN = queue_length(S#state.events), if N =< 0 -> actor; N > MaxN -> actor; true -> {event, N} end.x_to_n(X, S) -> Scale = S#state.scale, Len = length(S#state.actors), X2 = X - (?initial_x * Scale), N = X2 / (?incr_x * Scale), N2 = trunc(N + 1.5), if N2 > Len -> Len; N2 < 1 -> 1; true -> N2 end.write_text(Text, X, Y, Colour, S) -> Opt = [{coords, [{X, Y - (?incr_y * S#state.scale / 2)}]}, {font, S#state.font}, {fg, Colour}, {text, Text}], gs:text(S#state.canvas, Opt).create_contents_window(Event, S) -> Options = [{viewer_pid, self()}, {event, Event}, {event_order, S#state.event_order}, {active_filter, S#state.active_filter} | S#state.filters], case et_contents_viewer:start_link(Options) of {ok, _Pid} -> S; {error, Reason} -> ok = error_logger:format("~p(~p): create_contents_window(~p) ->~n ~p~n", [?MODULE, self(), Options, Reason]), S end.%%%----------------------------------------------------------------------%%% String padding of actors%%%----------------------------------------------------------------------create_actor(Name) -> String = name_to_string(Name), PaddedString = pad_string(String, 8), #actor{name = Name, string = PaddedString}.name_to_string(Name) -> case catch io_lib:format("~s", [Name]) of {'EXIT', _} -> lists:flatten(io_lib:format("~w", [Name])); GoodString -> lists:flatten(GoodString) end.pad_string(Atom, MinLen) when atom(Atom) -> pad_string(atom_to_list(Atom), MinLen);pad_string(String, MinLen) when integer(MinLen), MinLen >= 0 -> Len = length(String), case Len >= MinLen of true -> String; false -> String ++ lists:duplicate(MinLen - Len, $ ) end.%%%----------------------------------------------------------------------%%% Queue management%%%----------------------------------------------------------------------queue_new() -> {0, [], []}.queue_in(X, {Size, In, Out}) -> {Size + 1, [X | In], Out}.%% queue_out(Q) ->%% case Q of%% {Size, In, [H | Out]} -> {{value, H}, {Size - 1, In, Out}};%% {Size, [], []} -> {empty, {Size, [], []}};%% {Size, In, _} -> queue_out({Size, [], lists:reverse(In)})%% end.queue_to_list({_Size, [], Out}) -> Out;queue_to_list({_Size, In, Out}) -> Out ++ lists:reverse(In).queue_length({Size, _In, _Out}) -> Size.list_to_queue(List) when list(List) -> {length(List), [], List}.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -