⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 et_viewer.erl

📁 OTP是开放电信平台的简称
💻 ERL
📖 第 1 页 / 共 4 页
字号:
            _ ->                10        end,    if        S#state.is_suspended == true ->            {noreply, S, infinity};        S#state.max_events == infinity ->            display_more_events(Try, S);        true ->            Needed = S#state.max_events - queue_length(S#state.events),            if                Needed =< 0  -> {noreply, S, infinity};                Needed > 10  -> display_more_events(Try, S);                Needed =< 10 -> display_more_events(Needed, S)            end    end;handle_info({'EXIT', Pid, Reason}, S) ->    if        Pid == S#state.collector_pid ->            unlink(Pid),            gs:destroy(S#state.win),            {stop, Reason, S};        Pid == S#state.parent_pid ->            unlink(Pid),            gs:destroy(S#state.win),            {stop, Reason, S};        true ->            noreply(S)    end;handle_info(Info, S) ->    ok = error_logger:format("~p(~p): handle_info(~p, ~p)~n",                             [?MODULE, self(), Info, S]),    noreply(S).%%----------------------------------------------------------------------%% Func: terminate/2%% Purpose: Shutdown the server%% Returns: any (ignored by gen_server)%%----------------------------------------------------------------------terminate(_Reason, _S) ->    ignore.%%----------------------------------------------------------------------%% Func: code_change/3%% Purpose: Convert process state when code is changed%% Returns: {ok, NewState}%%----------------------------------------------------------------------code_change(_OldVsn, S, _Extra) ->    {ok, S}.%%%----------------------------------------------------------------------%%% Handle suspend/resume%%%----------------------------------------------------------------------reply(Reply, S) ->    case queue_length(S#state.events) of        _ when S#state.is_suspended == true ->            {reply, Reply, S, infinity};        _ when S#state.max_events == infinity ->            {reply, Reply, S, 500};        N when N >= S#state.max_events ->            {reply, Reply, S, infinity};        _ ->            {reply, Reply, S, 0}    end.noreply(S) ->    case queue_length(S#state.events) of        _ when S#state.is_suspended == true ->            {noreply, S, infinity};        _ when S#state.max_events == infinity ->            {noreply, S, 500};        N when N >= S#state.max_events ->            {noreply, S, infinity};        _ ->            {noreply, S, 0}    end.do_suspend(S) ->    config_suspend(S#state{is_suspended = true}).do_resume(S) ->    config_suspend(S#state{is_suspended = false}).config_suspend(S) ->    Suspended = S#state.is_suspended,    gs:config(refresh,     [{enable, not Suspended}]),    gs:config(refresh_all, [{enable, not Suspended}]),    gs:config(clear_all,   [{enable, not Suspended}]),    S.refresh_main_window(S) ->    Pid = S#state.collector_pid,    Key = S#state.first_event,    case et_collector:iterate(Pid, Key, -1) of	Prev when Prev == Key ->	    scroll_first(S);	_Prev ->	    S2 = S#state{last_event = S#state.first_event},	    clear_canvas(S2)    end.    scroll_first(S) ->    S2 = S#state{first_event = first, last_event  = first},    clear_canvas(S2).scroll_prev(S) ->    Try =        case S#state.max_events of            infinity -> -10;            Max      -> -Max        end,    Key = et_collector:iterate(S#state.collector_pid, S#state.first_event, Try),    S2 = S#state{first_event = Key, last_event  = Key},    clear_canvas(S2).scroll_next(S) ->    S2 = S#state{first_event = S#state.last_event},    clear_canvas(S2).scroll_up(S) ->    Key = et_collector:iterate(S#state.collector_pid, S#state.first_event, -5),    S2 = S#state{first_event = Key, last_event  = Key},    clear_canvas(S2).scroll_down(S) ->    Key = et_collector:iterate(S#state.collector_pid, S#state.first_event, 5),    S2 = S#state{first_event = Key, last_event  = Key},    clear_canvas(S2).scroll_last(S) ->    S2 = S#state{first_event = last, last_event  = last},    clear_canvas(S2).change_display_mode(Mode, S) ->    case Mode of        all ->            S2 = S#state{display_mode = Mode},            refresh_main_window(S2);        {search_actors, _Dir, _Key, []}  ->            S2 = S#state{display_mode = all},            refresh_main_window(S2);        {search_actors, _Dir, Key, Actors} when list(Actors) ->            Pid = S#state.collector_pid,            Prev = et_collector:iterate(Pid, Key, -1),            S2 = S#state{first_event  = Prev,                         last_event   = Prev,                         display_mode = Mode},            clear_canvas(S2)    end.close_all(S) ->    et_collector:multicast(S#state.collector_pid, close),    timer:sleep(timer:seconds(1)),    spawn(et_collector, stop, [S#state.collector_pid]),    gs:destroy(S#state.win),    {stop, shutdown, S}.close_all_others(S) ->    Fun =        fun({{subscriber, Pid}, _}) ->                if                    Pid == self() ->                        ignore;                    true ->                        unlink(Pid),                        Pid ! {et, close}                end        end,    All = et_collector:dict_match(S#state.collector_pid,                                  {{subscriber, '_'}, '_'}),    lists:foreach(Fun, All),    noreply(S).click_error(Click, S) ->    gs:config(S#state.canvas, beep),    io:format("~p: ignored: ~p~n", [?MODULE, Click]).%%%----------------------------------------------------------------------%%% Clone viewer%%%----------------------------------------------------------------------open_viewer(Scale, FilterName, Actors, S) ->    Filters = [{dict_insert, {filter, F#filter.name}, F#filter.function}               || F <- S#state.filters],    Options =         [{parent_pid,    S#state.parent_pid},         {title,         S#state.title},         {collector_pid, S#state.collector_pid},         {is_suspended,  S#state.is_suspended},         {detail_level,  S#state.detail_level},         {active_filter, FilterName},         {event_order,   S#state.event_order},         {first_event,   S#state.first_event},         {max_events,    S#state.max_events},         {max_actors,    S#state.max_actors},         {hide_actions,  S#state.hide_actions},         {hide_unknown,  S#state.hide_unknown},         {is_suspended,  S#state.is_suspended},         {actors,        Actors},         {scale,         Scale},         {width,         S#state.width},         {height,        S#state.height} | Filters],    case start_link(Options) of        {ok, ViewerPid} ->            unlink(ViewerPid),            ok;        {error, Reason} ->            ok = error_logger:format("~p: Failed to start a new window: ~p~n",                                     [?MODULE, Reason])    end.%%%----------------------------------------------------------------------%%% Handle graphics%%%----------------------------------------------------------------------create_main_window(S) ->    Font    = select_font(S#state.scale),    GS      = gs:start(),    Name    = name_to_string(S#state.active_filter),    Title   = case S#state.title of                  undefined -> atom_to_list(?MODULE);                  Explicit  -> name_to_string(Explicit)              end,    WinOpt  = [{title, Title ++ " (filter: " ++ Name ++  ")"},               {configure, true},               {width, S#state.width},               {height, S#state.height}],    Win     = gs:window(GS, WinOpt),    Bar     = gs:menubar(Win, []),    create_file_menu(Bar),    create_viewer_menu(Bar),    create_collector_menu(Bar),    gs:menubutton(filter_button, Bar, [{label, {text, "Filter"}}]),    create_filter_menu(S#state.active_filter, S#state.filters),    create_help_menu(Bar),       config_suspend(S),    PackerOpt = [{packer_x, [{fixed, 5}, {fixed, 40}, {fixed, 40},                             {stretch, 1}, {fixed, 5}]},                 {packer_y, [{fixed, 30}, {fixed, 30},                             {stretch, 1}, {fixed, 30}]},                 {x, 0}, {y, 30}],    Packer = gs:frame(Win, PackerOpt),    gs:checkbutton(suspended, Packer, [{label,{text,"Freeze"}},                                       {x, 10}, {y, 0},                                       {width, 120}, {align, w},                                       {select, S#state.is_suspended}]),    gs:checkbutton(hide_actions, Packer, [{label,{text,"Hide From=To"}},                                          {x, 10}, {y, 20},                                          {width, 120}, {align, w},                                          {select, S#state.hide_actions}]),    gs:checkbutton(hide_unknown, Packer, [{label,{text,"Hide Unknown"}},                                          {x, 10}, {y, 40},                                          {width, 120}, {align, w},                                          {select, S#state.hide_unknown}]),    gs:scale(Packer, [{text,"Detail Level"},                      {range, {?detail_level_min, ?detail_level_max}},                      {orient, horizontal},                      {x, 150}, {y, 0}, {height, 65}, {width, 200},                      {pos, S#state.detail_level}, {data, detail_level}]),    CanvasW = calc_canvas_width(S),    CanvasH = calc_canvas_height(S),    CanOpt = [{pack_xy, {{2, 4}, 3}}, {vscroll, right}, {hscroll, bottom},              {scrollregion, {2, 2, CanvasW, CanvasH}}],    Canvas = gs:canvas(Packer, CanOpt),    gs:config(Canvas, [{buttonpress, true}, {buttonrelease, true}]),    gs:config(Packer, [{width, S#state.width}, {height, S#state.height}]),    gs:config(Win, [{map, true}, {keypress, true}]),    S2 = S#state{title = Title,                 win = Win, font = Font, packer = Packer,                 canvas_width = CanvasW, canvas_height = CanvasH,                 canvas = Canvas,                 y_pos = ?initial_y * S#state.scale},    draw_all_actors(S2).select_font(Scale) when integer(Scale) ->    case Scale of        1 -> {courier,  7};        2 -> {courier, 10};        3 -> {courier, 12};        4 -> {courier, 14};        S -> {courier, S * 4}    end.create_file_menu(Bar) ->    Button = gs:menubutton(Bar,  [{label, {text, "File"}}]),    Menu   = gs:menu(Button, []),    gs:menuitem(close_all, Menu,        [{label, {text, "Close Collector and all Viewers         (C) "}}]),    gs:menuitem(close_all_others, Menu, [{label, {text, "Close other Viewers, but keep Collector (c)"}}]),    gs:menuitem(close, Menu,            [{label, {text, "Close this  Viewer,  but keep Collector"}}]),    gs:menuitem(Menu, [{itemtype, separator}]),    gs:menuitem(clear_all, Menu, [{label, {text, "Clear Collector"}}]),    gs:menuitem(load_all, Menu,  [{label, {text, "Load  Collector from the file \"et_viewer.log\""}}]),    gs:menuitem(save_all, Menu,  [{label, {text, "Save  Collector to   the file \"et_viewer.log\""}}]).create_viewer_menu(Bar) ->    Button = gs:menubutton(Bar,  [{label, {text, "Viewer"}}]),    Menu   = gs:menu(Button, []),    gs:menuitem(Menu, [{label, {text, "Scroll this Viewer"}}, {bg, lightblue}, {enable,false}]),    gs:menuitem(Menu, [{itemtype, separator}]),    gs:menuitem(first, Menu,   [{label, {text, "First                     (f)"}}]),    gs:menuitem(prev, Menu,    [{label, {text, "Prev                      (p)"}}]),    gs:menuitem(next, Menu,    [{label, {text, "Next                      (n)"}}]),    gs:menuitem(last, Menu,    [{label, {text, "Last                      (l)"}}]),    gs:menuitem(refresh, Menu, [{label, {text, "Refresh                   (r)"}}]),    gs:menuitem(Menu, [{itemtype, separator}]),                      gs:menuitem(up,   Menu,    [{label, {text, "Up   5                    (Up)"}}]),    gs:menuitem(down, Menu,    [{label, {text, "Down 5                    (Down)"}}]),    gs:menuitem(Menu, [{itemtype, separator}]),    gs:menuitem(Menu, [{label, {text, "Search in this Viewer"}}, {bg, lightblue}, {enable,false}]),    gs:menuitem(Menu, [{itemtype, separator}]),    gs:menuitem({mode, all}, Menu,    [{label, {text, "Abort search. Display all (a)"}}]).create_collector_menu(Bar) ->    Button = gs:menubutton(Bar,  [{label, {text, "Collector"}}]),    Menu = gs:menu(Button, []),    gs:menuitem(Menu, [{label, {text, "Scroll all Viewers"}}, {bg, lightblue}, {enable,false}]),    gs:menuitem(Menu, [{itemtype, separator}]),    gs:menuitem(first_all, Menu,   [{label, {text, "First   (F)"}}]),    gs:menuitem(prev_all, Menu,    [{label, {text, "Prev    (P)"}}]),    gs:menuitem(next_all, Menu,    [{label, {text, "Next    (N)"}}]),    gs:menuitem(last_all, Menu,    [{label, {text, "Last    (L)"}}]),    gs:menuitem(refresh_all, Menu, [{label, {text, "Refresh (R)"}}]).create_filter_menu(ActiveFilterName, Filters) ->    Menu = gs:menu(filter_menu, filter_button, []),    Item = fun(F, N) when F#filter.name == collector ->                   Label = lists:concat([pad_string(F#filter.name, 20), "(0)"]),                   gs:menuitem(Menu, [{label, {text, Label}}, {data, F}]),                   N + 1;              (F, N) ->                   Label = lists:concat([pad_string(F#filter.name, 20), "(", N, ")"]),                   gs:menuitem(Menu, [{label, {text, Label}}, {data, F}]),                   N + 1           end,    gs:menuitem(Menu, [{label, {text, "Same Filter New Scale"}}, {bg, lightblue}, {enable,false}]),    gs:menuitem(Menu, [{itemtype, separator}]),    {value, Filter} = lists:keysearch(ActiveFilterName, #filter.name, Filters),    Same    = lists:concat([pad_string(ActiveFilterName, 20), "(=)"]),    Larger  = lists:concat([pad_string(ActiveFilterName, 20), "(+)"]),    Smaller = lists:concat([pad_string(ActiveFilterName, 20), "(-)"]),    gs:menuitem(Menu, [{label, {text, Same}}, {data, Filter}]),    gs:menuitem(Menu, [{label, {text, Smaller}}, {data, Filter}]),    gs:menuitem(Menu, [{label, {text, Larger}}, {data, Filter}]),    gs:menuitem(Menu, [{itemtype, separator}]),    gs:menuitem(Menu, [{label, {text, "New Filter Same Scale"}}, {bg, lightblue}, {enable,false}]),    gs:menuitem(Menu, [{itemtype, separator}]),    lists:foldl(Item, 1, Filters).create_help_menu(Bar) ->    Button = gs:menubutton(Bar,  [{label, {text, "Help"}}]),    Menu = gs:menu(Button, []),    gs:menuitem(Menu, [{label, {text, "Display details of an event"}},                       {bg, lightblue}, {enable,false}]),    gs:menuitem(Menu, [{label, {text, "    Single click on the name tag or the arrow (Mouse-1)"}},                       {enable,false}]),    gs:menuitem(Menu, [{itemtype, separator}]),    gs:menuitem(Menu, [{label, {text, "Toggle actor search"}},                       {bg, lightblue}, {enable,false}]),    gs:menuitem(Menu, [{label, {text, "    Single click on the name tag (Mouse-1)"}},                       {enable,false}]),    gs:menuitem(Menu, [{itemtype, separator}]),    gs:menuitem(Menu, [{label, {text, "Move actor"}},                       {bg, lightblue}, {enable,false}]),    gs:menuitem(Menu, [{label, {text, "    se drag and drop on name tag (Mouse-1)"}},                       {enable,false}]).clear_canvas(S) ->    gs:destroy(S#state.canvas),    CanvasW = calc_canvas_width(S),    CanvasH = calc_canvas_height(S),    CanOpt = [{pack_xy, {{2, 4}, 3}}, {vscroll, right}, {hscroll, bottom},              {scrollregion, {2, 2, CanvasW, CanvasH}}],    Canvas = gs:canvas(S#state.packer, CanOpt),    gs:config(S#state.packer, [{width, S#state.width}, {height, S#state.height}]),     gs:config(Canvas, [{buttonpress, true}, {buttonrelease, true}]),    S2 = S#state{refresh_needed = false,                 y_pos          = ?initial_y * S#state.scale,                 canvas         = Canvas,                 canvas_width   = CanvasW,                  canvas_height  = CanvasH,                 events         = queue_new()},    draw_all_actors(S2).calc_canvas_width(S) ->    Min = calc_min_actors(S),    CanvasW = ((2 * ?initial_x) + (Min * ?incr_x)) * S#state.scale,    lists:max([CanvasW, S#state.width - (15 * S#state.scale), S#state.canvas_width]).calc_canvas_height(S) ->    Min = calc_min_events(S),    CanvasH = ((2 * ?initial_y) + (Min * ?incr_y)) * S#state.scale,    lists:max([CanvasH, S#state.height - (4 * 30), S#state.canvas_height]).calc_min_actors(S) ->    Max = S#state.max_actors,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -