aboutsummaryrefslogtreecommitdiffstats
path: root/lib/debugger/src/dbg_ui_view.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/debugger/src/dbg_ui_view.erl')
-rw-r--r--lib/debugger/src/dbg_ui_view.erl256
1 files changed, 256 insertions, 0 deletions
diff --git a/lib/debugger/src/dbg_ui_view.erl b/lib/debugger/src/dbg_ui_view.erl
new file mode 100644
index 0000000000..075275f196
--- /dev/null
+++ b/lib/debugger/src/dbg_ui_view.erl
@@ -0,0 +1,256 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-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(dbg_ui_view).
+
+%% External exports
+-export([start/2]).
+
+%% Internal exports
+-export([init/3]).
+
+-record(state, {gs, % term() Graphics system id
+ win, % term() Attach process window data
+ coords, % {X,Y} Mouse point position
+ mod % atom() Module
+ }).
+
+%%====================================================================
+%% External exports
+%%====================================================================
+
+%%--------------------------------------------------------------------
+%% start(GS, Mod)
+%% Mod = atom()
+%%--------------------------------------------------------------------
+start(GS, Mod) ->
+ Title = "View Module " ++ atom_to_list(Mod),
+ case dbg_ui_winman:is_started(Title) of
+ true -> ignore;
+ false -> spawn(?MODULE, init, [GS, Mod, Title])
+ end.
+
+
+%%====================================================================
+%% Main loop and message handling
+%%====================================================================
+
+init(GS, Mod, Title) ->
+
+ %% Subscribe to messages from the interpreter
+ int:subscribe(),
+
+ %% Create attach process window
+ Win1 = dbg_ui_trace_win:create_win(GS, Title, ['Code Area'], menus()),
+ Window = dbg_ui_trace_win:get_window(Win1),
+ dbg_ui_winman:insert(Title, Window),
+
+ Win2 = gui_load_module(Win1, Mod),
+ Win3 =
+ lists:foldl(fun(Break, Win) ->
+ dbg_ui_trace_win:add_break(Win, 'Break', Break)
+ end,
+ Win2,
+ int:all_breaks(Mod)),
+
+ loop(#state{gs=GS, win=Win3, coords={0,0}, mod=Mod}).
+
+loop(State) ->
+ receive
+
+ %% From the GUI main window
+ GuiEvent when is_tuple(GuiEvent), element(1, GuiEvent)==gs ->
+ Cmd = dbg_ui_trace_win:handle_event(GuiEvent, State#state.win),
+ State2 = gui_cmd(Cmd, State),
+ loop(State2);
+
+ %% From the GUI help windows
+ {gui, Cmd} ->
+ State2 = gui_cmd(Cmd, State),
+ loop(State2);
+
+ %% From the interpreter
+ {int, Cmd} ->
+ State2 = int_cmd(Cmd, State),
+ loop(State2);
+
+ %% From the dbg_ui_winman process (Debugger window manager)
+ {dbg_ui_winman, update_windows_menu, Data} ->
+ dbg_ui_winman:update_windows_menu(Data),
+ loop(State);
+ {dbg_ui_winman, destroy} ->
+ exit(stop);
+
+ %% Help window termination -- ignore
+ {'EXIT', _Pid, _Reason} ->
+ loop(State)
+ end.
+
+%%--Commands from the GUI---------------------------------------------
+
+gui_cmd(ignore, State) ->
+ State;
+gui_cmd({win, Win}, State) ->
+ State#state{win=Win};
+gui_cmd(stopped, _State) ->
+ exit(stop);
+gui_cmd({coords, Coords}, State) ->
+ State#state{coords=Coords};
+
+gui_cmd({shortcut, Key}, State) ->
+ case shortcut(Key) of
+ false -> State;
+ Cmd -> gui_cmd(Cmd, State)
+ end;
+
+%% File menu
+gui_cmd('Close', State) ->
+ gui_cmd(stopped, State);
+
+%% Edit menu
+gui_cmd('Go To Line...', State) ->
+ %% Will result in message handled below: {gui, {gotoline, Line}}
+ dbg_ui_trace_win:helpwin(gotoline, State#state.win,
+ State#state.gs, State#state.coords),
+ State;
+gui_cmd({gotoline, Line}, State) ->
+ Win = dbg_ui_trace_win:select_line(State#state.win, Line),
+ State#state{win=Win};
+gui_cmd('Search...', State) ->
+ dbg_ui_trace_win:helpwin(search, State#state.win,
+ State#state.gs, State#state.coords),
+ State;
+
+%% Break menu
+gui_cmd('Line Break...', State) ->
+ add_break(State#state.gs, State#state.coords, line,
+ State#state.mod,
+ dbg_ui_trace_win:selected_line(State#state.win)),
+ State;
+gui_cmd('Conditional Break...', State) ->
+ add_break(State#state.gs, State#state.coords, conditional,
+ State#state.mod,
+ dbg_ui_trace_win:selected_line(State#state.win)),
+ State;
+gui_cmd('Function Break...', State) ->
+ add_break(State#state.gs, State#state.coords, function,
+ State#state.mod, undefined),
+ State;
+gui_cmd('Enable All', State) ->
+ Breaks = int:all_breaks(),
+ ThisMod = State#state.mod,
+ lists:foreach(fun ({{Mod, Line}, _Options}) when Mod==ThisMod ->
+ int:enable_break(Mod, Line);
+ (_Break) ->
+ ignore
+ end,
+ Breaks),
+ State;
+gui_cmd('Disable All', State) ->
+ Breaks = int:all_breaks(),
+ ThisMod = State#state.mod,
+ lists:foreach(fun ({{Mod, Line}, _Options}) when Mod==ThisMod ->
+ int:disable_break(Mod, Line);
+ (_Break) ->
+ ignore
+ end,
+ Breaks),
+ State;
+gui_cmd('Delete All', State) ->
+ int:no_break(State#state.mod),
+ State;
+gui_cmd({break, {Mod, Line}, What}, State) ->
+ case What of
+ add -> int:break(Mod, Line);
+ delete -> int:delete_break(Mod, Line);
+ {status, inactive} -> int:disable_break(Mod, Line);
+ {status, active} -> int:enable_break(Mod, Line);
+ {trigger, Action} -> int:action_at_break(Mod, Line, Action)
+ end,
+ State;
+
+%% Help menu
+gui_cmd('Debugger', State) ->
+ Window = dbg_ui_trace_win:get_window(State#state.win),
+ HelpFile = filename:join([code:lib_dir(debugger),
+ "doc", "html", "part_frame.html"]),
+ tool_utils:open_help(Window, HelpFile),
+ State.
+
+add_break(GS, Coords, Type, undefined, _Line) ->
+ dbg_ui_break:start(GS, Coords, Type);
+add_break(GS, Coords, Type, Mod, undefined) ->
+ dbg_ui_break:start(GS, Coords, Type, Mod);
+add_break(GS, Coords, Type, Mod, Line) ->
+ dbg_ui_break:start(GS, Coords, Type, Mod, Line).
+
+%%--Commands from the interpreter-------------------------------------
+
+int_cmd({new_break, {{Mod,_Line},_Options}=Break}, #state{mod=Mod}=State) ->
+ Win = dbg_ui_trace_win:add_break(State#state.win, 'Break', Break),
+ State#state{win=Win};
+int_cmd({delete_break, {Mod,_Line}=Point}, #state{mod=Mod}=State) ->
+ Win = dbg_ui_trace_win:delete_break(State#state.win, Point),
+ State#state{win=Win};
+int_cmd({break_options, {{Mod,_Line},_Options}=Break}, #state{mod=Mod}=State) ->
+ Win = dbg_ui_trace_win:update_break(State#state.win, Break),
+ State#state{win=Win};
+int_cmd(no_break, State) ->
+ Win = dbg_ui_trace_win:clear_breaks(State#state.win),
+ State#state{win=Win};
+int_cmd({no_break, _Mod}, State) ->
+ Win = dbg_ui_trace_win:clear_breaks(State#state.win),
+ State#state{win=Win};
+int_cmd(_, State) ->
+ State.
+
+
+%%====================================================================
+%% GUI auxiliary functions
+%%====================================================================
+
+menus() ->
+ [{'File', [{'Close', 0}]},
+ {'Edit', [{'Go To Line...', 0},
+ {'Search...', 0}]},
+ {'Break', [{'Line Break...', 5},
+ {'Conditional Break...', 13},
+ {'Function Break...', 0},
+ separator,
+ {'Enable All', no},
+ {'Disable All', no},
+ {'Delete All', 0},
+ separator]},
+ {'Help', [{'Debugger', no}]}].
+
+shortcut(c) -> 'Close';
+shortcut(g) -> 'Go To Line...';
+shortcut(s) -> 'Search...';
+shortcut(b) -> 'Line Break...';
+shortcut(r) -> 'Conditional Break...';
+shortcut(f) -> 'Function Break...';
+shortcut(d) -> 'Delete All';
+
+shortcut(_) -> false.
+
+gui_load_module(Win, Mod) ->
+ dbg_ui_trace_win:display({text, "Loading module..."}),
+ Contents = int:contents(Mod, any),
+ Win2 = dbg_ui_trace_win:show_code(Win, Mod, Contents),
+ dbg_ui_trace_win:display({text, ""}),
+ Win2.