aboutsummaryrefslogtreecommitdiffstats
path: root/lib/debugger/src/dbg_wx_mon_win.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/debugger/src/dbg_wx_mon_win.erl')
-rw-r--r--lib/debugger/src/dbg_wx_mon_win.erl586
1 files changed, 586 insertions, 0 deletions
diff --git a/lib/debugger/src/dbg_wx_mon_win.erl b/lib/debugger/src/dbg_wx_mon_win.erl
new file mode 100644
index 0000000000..dfb327fa6a
--- /dev/null
+++ b/lib/debugger/src/dbg_wx_mon_win.erl
@@ -0,0 +1,586 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 2008-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_wx_mon_win).
+
+%% External exports
+-export([init/0]).
+-export([create_win/3, get_window/1,
+ show_option/3,
+ enable/2, is_enabled/1, select/2,
+ add_module/3, delete_module/2,
+ add_process/6, update_process/4, clear_processes/1,
+ add_break/3, update_break/2, delete_break/2,
+ clear_breaks/1, clear_breaks/2,
+ handle_event/2
+ ]).
+
+-import(dbg_wx_win, [to_string/1, to_string/2]).
+
+-include_lib("wx/include/wx.hrl").
+
+-define(default_rows,10).
+
+-record(moduleInfo, {module, menubtn}).
+-record(procInfo, {pid, row}).
+-record(breakInfo, {point, status, break}).
+-record(break, {mb, smi, emi, dimi, demi}). %% BUGBUG defined in dbg_ui_win
+-record(winInfo, {window, % gsobj()
+ grid, % gsobj()
+ row, % int() Last row in grid
+
+ focus, % int() Selected row in grid
+
+ modules=[], % [#moduleInfo{}] Known modules
+ processes=[], % [#procInfo{}] Known processes
+ breaks=[], % [#breakInfo{}] Known breakpoints
+
+ listbox, % gsobj() Listinng known modules
+
+ %% Auto attach buttons
+ fbutton, % gsobj()
+ bbutton, % gsobj()
+ ebutton, % gsobj()
+ selected=[], % ['First Call'|'On Break'|'On Exit']
+
+ slabel, % showing Stack Trace option
+ blabel % showing Back Trace Size
+ }).
+
+%%====================================================================
+%% External exports
+%%====================================================================
+
+init() ->
+ dbg_wx_win:init().
+
+%%--------------------------------------------------------------------
+%% create_win(GS, Title, Menus) -> #winInfo{}
+%% GS = gsobj()
+%% Title = string()
+%% Menus = [menu()] See dbg_ui_win.erl
+%%--------------------------------------------------------------------
+
+-define(GRID,1000).
+
+-define(PAD, 5).
+-define(Wf, 150).
+-define(Wg, 770).
+-define(W, 800).
+-define(H, 390).
+
+create_win(_Wx, Title, Menus) ->
+ wx:batch(fun() -> create_win_batch(Title, Menus) end).
+
+create_win_batch(Title, Menus) ->
+ Win = wxFrame:new(wx:null(), ?wxID_ANY, Title,
+ [{size, {?W,?H}}]),
+ wxFrame:connect(Win, close_window, [{skip, true}]),
+ MenuBar = wxMenuBar:new(),
+ dbg_wx_win:create_menus(MenuBar, Menus, Win, 1),
+ wxFrame:setMenuBar(Win, MenuBar),
+
+ MainSz = wxBoxSizer:new(?wxHORIZONTAL),
+ LeftSz = wxBoxSizer:new(?wxVERTICAL),
+
+ Panel = wxPanel:new(Win),
+ Hlb = 200,
+ Listbox = wxListBox:new(Panel, ?wxID_ANY, [{size,{?Wf,Hlb}},
+ {style,?wxLB_SINGLE}]),
+ wxSizer:add(LeftSz,Listbox,[{border, 3}]),
+ wxListBox:connect(Listbox, command_listbox_doubleclicked),
+ wxListBox:connect(Listbox, right_down),
+
+ SBox = wxStaticBox:new(Panel, ?wxID_ANY, "Auto Attach:"),
+ SBS = wxStaticBoxSizer:new(SBox, ?wxVERTICAL),
+ Fbtn = wxCheckBox:new(Panel, ?wxID_ANY, "First Call"),
+ wxSizer:add(SBS,Fbtn),
+ Bbtn = wxCheckBox:new(Panel, ?wxID_ANY, "On Break"),
+ wxSizer:add(SBS,Bbtn),
+ Ebtn = wxCheckBox:new(Panel, ?wxID_ANY, "On Exit"),
+ wxSizer:add(SBS,Ebtn),
+ wxFrame:connect(Panel, command_checkbox_clicked),
+ wxSizer:add(LeftSz,SBS, [{flag,?wxEXPAND}]),
+
+ SLabel = wxStaticText:new(Panel, ?wxID_ANY, "Stack Trace:\n On (with tail)"),
+ wxSizer:add(LeftSz,SLabel),
+ BLabel = wxStaticText:new(Panel, ?wxID_ANY, "Back Trace Size:\n 50000"),
+ wxSizer:add(LeftSz,BLabel),
+
+ %% Create list_crtl / grid
+ Grid = wxListCtrl:new(Panel, [{winid, ?GRID},
+ {style, ?wxLC_REPORT bor ?wxLC_SINGLE_SEL
+ bor ?wxLC_HRULES },
+ {size, {600, -1}}]),
+ LI = wxListItem:new(),
+ wxListItem:setText(LI, "Pid"),
+ wxListItem:setAlign(LI, ?wxLIST_FORMAT_CENTRE),
+ wxListCtrl:insertColumn(Grid, 0, LI),
+ wxListItem:setText(LI, "Initial Call"),
+ wxListItem:setAlign(LI, ?wxLIST_FORMAT_LEFT),
+ wxListCtrl:insertColumn(Grid, 1, LI),
+ wxListItem:setText(LI, "Name"),
+ wxListCtrl:insertColumn(Grid, 2, LI),
+ wxListItem:setAlign(LI, ?wxLIST_FORMAT_CENTRE),
+ wxListItem:setText(LI, "Status"),
+ wxListCtrl:insertColumn(Grid, 3, LI),
+ wxListItem:setText(LI, "Information"),
+ wxListItem:setAlign(LI, ?wxLIST_FORMAT_LEFT),
+ wxListCtrl:insertColumn(Grid, 4, LI),
+ wxListItem:destroy(LI),
+
+ wxListCtrl:setColumnWidth(Grid, 0, 80),
+ wxListCtrl:setColumnWidth(Grid, 1, 150),
+ wxListCtrl:setColumnWidth(Grid, 2, 100),
+ wxListCtrl:setColumnWidth(Grid, 3, 70),
+ wxListCtrl:setColumnWidth(Grid, 4, 200),
+ wxListCtrl:connect(Grid, command_list_item_activated),
+ wxListCtrl:connect(Grid, command_list_item_selected),
+ wxListCtrl:connect(Grid, size, [{skip, true}]),
+ wxListCtrl:connect(Grid, key_up, [{id, ?GRID}, {skip,true}]),
+
+ wxWindow:connect(Win, enter_window, [{skip,true}]),
+ wxWindow:setFocus(Grid),
+
+ %% Put it in the window
+ wxSizer:add(MainSz, LeftSz, [{border, 3}, {flag,?wxALL bor ?wxEXPAND}]),
+ wxSizer:add(MainSz, Grid, [{border, 3}, {flag,?wxALL bor ?wxEXPAND},
+ {proportion, 1}]),
+
+ wxWindow:setSizer(Panel,MainSz),
+ wxSizer:fit(MainSz, Win),
+ wxSizer:setSizeHints(MainSz,Win),
+
+ IconFile = dbg_wx_win:find_icon("erlang_bug.png"),
+ Icon = wxIcon:new(IconFile, [{type,?wxBITMAP_TYPE_PNG}]),
+ wxFrame:setIcon(Win, Icon),
+ wxIcon:destroy(Icon),
+ wxFrame:show(Win),
+ dbg_wx_winman:raise(Win),
+ #winInfo{window=Win, grid=Grid, row=0, focus=0,
+ listbox=Listbox,
+ fbutton=Fbtn, bbutton=Bbtn, ebutton=Ebtn,
+ slabel=SLabel, blabel=BLabel}.
+
+%%--------------------------------------------------------------------
+%% get_window(WinInfo) -> Window
+%% WinInfo = #winInfo{}
+%% Window = wxobj()
+%%--------------------------------------------------------------------
+get_window(WinInfo) ->
+ WinInfo#winInfo.window.
+
+%%--------------------------------------------------------------------
+%% show_option(WinInfo, Option, Value) -> void()
+%% WinInfo = #winInfo{}
+%% Option = auto_attach | stack_trace | back_trace
+%% Value = [Flag] % Option==auto_attach
+%% Flag = init | break | exit
+%% | true | all | no_tail | false % Option==stack_trace
+%% | int() % Option==back_trace
+%%--------------------------------------------------------------------
+show_option(WinInfo, Option, Value) ->
+ case Option of
+ auto_attach ->
+ wx:foreach(fun(Button) ->
+ wxCheckBox:setValue(Button, false)
+ end,
+ option_buttons(WinInfo, [init, break, exit])),
+ wx:foreach(fun(Button) ->
+ wxCheckBox:setValue(Button, true)
+ end,
+ option_buttons(WinInfo, Value));
+
+ stack_trace ->
+ Text = case Value of
+ all -> "Stack Trace:\n On (with tail)";
+ true -> "Stack Trace:\n On (with tail)";
+ no_tail -> "Stack Trace:\n On (no tail)";
+ false -> "Stack Trace:\n Off"
+ end,
+ wxStaticText:setLabel(WinInfo#winInfo.slabel, Text);
+
+ back_trace ->
+ Text = "Back Trace Size:\n " ++ integer_to_list(Value),
+ wxStaticText:setLabel(WinInfo#winInfo.blabel, Text)
+ end.
+
+option_buttons(WinInfo, [init|Flags]) ->
+ [WinInfo#winInfo.fbutton|option_buttons(WinInfo, Flags)];
+option_buttons(WinInfo, [break|Flags]) ->
+ [WinInfo#winInfo.bbutton|option_buttons(WinInfo, Flags)];
+option_buttons(WinInfo, [exit|Flags]) ->
+ [WinInfo#winInfo.ebutton|option_buttons(WinInfo, Flags)];
+option_buttons(_WinInfo, []) ->
+ [].
+
+%%--------------------------------------------------------------------
+%% enable([MenuItem], Bool)
+%% is_enabled(MenuItem) -> Bool
+%% MenuItem = atom()
+%% Bool = boolean()
+%%--------------------------------------------------------------------
+enable(MenuItems, Bool) ->
+ lists:foreach(fun(MenuItem) ->
+ MI = get(MenuItem),
+ wxMenuItem:enable(MI, [{enable, Bool}])
+ end,
+ MenuItems).
+
+is_enabled(MenuItem) ->
+ MI = get(MenuItem),
+ wxMenuItem:isEnabled(MI).
+
+%%--------------------------------------------------------------------
+%% select(MenuItem, Bool)
+%% MenuItem = atom()
+%% Bool = boolean()
+%%--------------------------------------------------------------------
+select(MenuItem, Bool) ->
+ MI = get(MenuItem),
+ wxMenuItem:check(MI, [{check, Bool}]).
+
+%%--------------------------------------------------------------------
+%% add_module(WinInfo, Name, Mod) -> WinInfo
+%% WinInfo = #winInfo{}
+%% Name = atom()
+%% Mod = atom()
+%%--------------------------------------------------------------------
+add_module(WinInfo, MenuName, Mod) ->
+ Win = WinInfo#winInfo.window,
+ Modules = WinInfo#winInfo.modules,
+ case lists:keysearch(Mod, #moduleInfo.module, Modules) of
+ {value, _ModInfo} -> WinInfo;
+ false ->
+ %% Create a menu for the module
+ Menu = get(MenuName),
+ Sub = wxMenu:new([]),
+ ViewItem = wxMenu:append(Sub, ?wxID_ANY, "View"),
+ ViewId = wxMenuItem:getId(ViewItem),
+ wxMenu:connect(Win, command_menu_selected,
+ [{id,ViewId}, {userData, {module,Mod,view}}]),
+ DelItem = wxMenu:append(Sub, ?wxID_ANY, "Delete"),
+ DelId = wxMenuItem:getId(DelItem),
+ wxMenu:connect(Win, command_menu_selected,
+ [{id,DelId}, {userData, {module,Mod,delete}}]),
+ MenuBtn = wxMenu:append(Menu, ?wxID_ANY, atom_to_list(Mod), Sub),
+ wxListBox:append(WinInfo#winInfo.listbox, atom_to_list(Mod)),
+
+ ModInfo = #moduleInfo{module=Mod, menubtn={Menu,MenuBtn}},
+ WinInfo#winInfo{modules=[ModInfo | Modules]}
+ end.
+
+%%--------------------------------------------------------------------
+%% delete_module(WinInfo, Mod) -> WinInfo
+%% WinInfo = #winInfo{}
+%% Mod = atom()
+%%--------------------------------------------------------------------
+delete_module(WinInfo, Mod) ->
+ {value, ModInfo} = lists:keysearch(Mod, #moduleInfo.module,
+ WinInfo#winInfo.modules),
+ {Menu, MenuBtn} = ModInfo#moduleInfo.menubtn,
+ wxMenu:'Destroy'(Menu, MenuBtn),
+ ListBox = WinInfo#winInfo.listbox,
+ Id = wxListBox:findString(ListBox, atom_to_list(Mod)),
+ wxListBox:delete(ListBox,Id),
+ WinInfo#winInfo{modules=lists:keydelete(Mod, #moduleInfo.module,
+ WinInfo#winInfo.modules)}.
+
+%%--------------------------------------------------------------------
+%% add_process(WinInfo, Pid, Name, Function, Status, Info) -> WinInfo
+%% WinInfo = #winInfo{}
+%% Pid = pid()
+%% Name = undefined | atom()
+%% Function = {Mod, Func, Args}
+%% Status = idle | running | break | exit
+%% Info = {} | term()
+%%--------------------------------------------------------------------
+add_process(WinInfo, Pid, Name, {Mod,Func,Args}, Status, Info) ->
+ Grid = WinInfo#winInfo.grid,
+ Row = (WinInfo#winInfo.row),
+
+ Name2 = case Name of undefined -> ""; _ -> to_string(Name) end,
+ FuncS = to_string("~w:~w/~w", [Mod, Func, length(Args)]),
+ Info2 = case Info of {} -> ""; _ -> to_string(Info) end,
+ Pid2 = to_string("~p",[Pid]),
+
+ Add = fun() ->
+ _Dbg = wxListCtrl:insertItem(Grid, Row,""),
+ %%wxListCtrl:setItemData(Grid,Temp,Row),
+ if (Row rem 2) =:= 0 ->
+ wxListCtrl:setItemBackgroundColour(Grid, Row, {240,240,255});
+ true -> ignore
+ end,
+
+ wxListCtrl:setItem(Grid, Row, 0, Pid2),
+ wxListCtrl:setItem(Grid, Row, 1, FuncS),
+ wxListCtrl:setItem(Grid, Row, 2, Name2),
+ wxListCtrl:setItem(Grid, Row, 3, to_string(Status)),
+ wxListCtrl:setItem(Grid, Row, 4, Info2),
+ ok
+ end,
+ wx:batch(Add),
+
+ ProcInfo = #procInfo{pid=Pid, row=Row},
+ WinInfo#winInfo{processes=[ProcInfo|WinInfo#winInfo.processes],
+ row=Row+1}.
+
+%%--------------------------------------------------------------------
+%% update_process(WinInfo, Pid, Status, Info)
+%% WinInfo = #winInfo{}
+%% Pid = pid()
+%% Status = idle | running | break | exit
+%% Info = {} | term()
+%%--------------------------------------------------------------------
+update_process(WinInfo, Pid, Status, Info) ->
+ {value, ProcInfo} = lists:keysearch(Pid, #procInfo.pid,
+ WinInfo#winInfo.processes),
+
+ Grid = WinInfo#winInfo.grid,
+ Row = ProcInfo#procInfo.row,
+ Info2 = case Info of {} -> ""; _ -> Info end,
+ wxListCtrl:setItem(Grid, Row, 3, to_string(Status)),
+ wxListCtrl:setItem(Grid, Row, 4, to_string(Info2)).
+
+%%--------------------------------------------------------------------
+%% clear_processes(WinInfo) -> WinInfo
+%% WinInfo = #winInfo{}
+%%--------------------------------------------------------------------
+clear_processes(WinInfo) ->
+ Grid = WinInfo#winInfo.grid,
+ Max = WinInfo#winInfo.row,
+ wx:batch(fun() -> clear_processes(Grid, Max-1) end),
+ WinInfo#winInfo{row=0, focus=0, processes=[]}.
+
+clear_processes(Grid, Row) when Row >= 0 ->
+ Item = wxListItem:new(),
+ wxListItem:setId(Item,Row),
+ wxListItem:setColumn(Item, 3),
+ case wxListCtrl:getItem(Grid, Item) of
+ true ->
+ case wxListItem:getText(Item) of
+ "exit" ->
+ wxListItem:setColumn(Item, 0),
+ wxListCtrl:getItem(Grid, Item),
+ Pid = list_to_pid(wxListItem:getText(Item)),
+ dbg_wx_winman:clear_process(dbg_wx_trace:title(Pid));
+ _ ->
+ ok
+ end;
+ false ->
+ ignore
+ end,
+ wxListItem:destroy(Item),
+ wxListCtrl:deleteItem(Grid, Row),
+ clear_processes(Grid, Row-1);
+clear_processes(_Grid, _Row) ->
+ done.
+
+%%--------------------------------------------------------------------
+%% add_break(WinInfo, Name, {Point, Options}) -> WinInfo
+%% WinInfo = #winInfo{}
+%% Name = atom()
+%% Point = {Mod, Line}
+%% Options = [Status, Action, Mods, Cond]
+%% Status = active | inactive
+%% Action = enable | disable | delete
+%% Mods = null (not used)
+%% Cond = null | {Mod, Func}
+%%--------------------------------------------------------------------
+add_break(WinInfo, Menu, {Point, Options}) ->
+ Break = dbg_wx_win:add_break(WinInfo#winInfo.window, Menu, Point),
+ dbg_wx_win:update_break(Break, Options),
+ BreakInfo = #breakInfo{point=Point, break=Break},
+ WinInfo#winInfo{breaks=[BreakInfo|WinInfo#winInfo.breaks]}.
+
+%%--------------------------------------------------------------------
+%% update_break(WinInfo, {Point, Options})
+%% WinInfo = #winInfo{}
+%% Point = {Mod, Line}
+%% Options = [Status, Action, Mods, Cond]
+%% Status = active | inactive
+%% Action = enable | disable | delete
+%% Mods = null (not used)
+%% Cond = null | {Mod, Func}
+%%--------------------------------------------------------------------
+update_break(WinInfo, {Point, Options}) ->
+ {value, BreakInfo} = lists:keysearch(Point, #breakInfo.point,
+ WinInfo#winInfo.breaks),
+ dbg_wx_win:update_break(BreakInfo#breakInfo.break, Options).
+
+%%--------------------------------------------------------------------
+%% delete_break(WinInfo, Point) -> WinInfo
+%% WinInfo = #winInfo{}
+%% Point = {Mod, Line}
+%%--------------------------------------------------------------------
+delete_break(WinInfo, Point) ->
+ {value, BreakInfo} = lists:keysearch(Point, #breakInfo.point,
+ WinInfo#winInfo.breaks),
+ dbg_wx_win:delete_break(BreakInfo#breakInfo.break),
+ WinInfo#winInfo{breaks=lists:keydelete(Point, #breakInfo.point,
+ WinInfo#winInfo.breaks)}.
+
+%%--------------------------------------------------------------------
+%% clear_breaks(WinInfo) -> WinInfo
+%% clear_breaks(WinInfo, Mod) -> WinInfo
+%% WinInfo = #winInfo{}
+%%--------------------------------------------------------------------
+clear_breaks(WinInfo) ->
+ lists:foreach(fun(BreakInfo) ->
+ dbg_wx_win:delete_break(BreakInfo#breakInfo.break)
+ end,
+ WinInfo#winInfo.breaks),
+ WinInfo#winInfo{breaks=[]}.
+clear_breaks(WinInfo, Mod) ->
+ Fun =
+ fun(BreakInfo) ->
+ case BreakInfo#breakInfo.point of
+ {Mod, _Line} ->
+ dbg_wx_win:delete_break(BreakInfo#breakInfo.break),
+ false;
+ _ -> true
+ end
+ end,
+ Breaks = lists:filter(Fun, WinInfo#winInfo.breaks),
+ WinInfo#winInfo{breaks=Breaks}.
+
+%%--------------------------------------------------------------------
+%% handle_event(WxEvent, WinInfo) -> Command
+%% WxEvent = #wx{}
+%% WinInfo = #winInfo{}
+%% Command = ignore
+%% | stopped
+%% | {coords, {X,Y}}
+%%
+%% | {shortcut, Key}
+%% | MenuItem | {Menu, [MenuItem]}
+%% MenuItem = Menu = atom()
+%% | {break, Point, What}
+%% What = delete | {status, Status} | {trigger, Trigger}
+%% | {module, Mod, What}
+%% What = view | delete
+%%
+%% | {focus, Pid, WinInfo}
+%% | default
+%%--------------------------------------------------------------------
+%% Window events
+handle_event(#wx{event=#wxSize{size={W,_}}}, #winInfo{grid=Grid}) ->
+ wx:batch(fun() ->
+ Tot = wx:foldl(fun(C,Sum) ->
+ Sum + wxListCtrl:getColumnWidth(Grid, C)
+ end, 0, [0,1,2,3]),
+ wxListCtrl:setColumnWidth(Grid, 4, W-Tot-4)
+ end),
+ ignore;
+handle_event(_Ev=#wx{event=#wxClose{}}, _WinInfo) ->
+%% io:format("~p Received ~p close ~p~n", [?MODULE, self(), _Ev]),
+ stopped;
+
+%% Menus and keyboard shortcuts
+handle_event(#wx{userData={dbg_ui_winman, Win},
+ event=#wxCommand{type=command_menu_selected}}, _Wi) ->
+ dbg_wx_winman:raise(Win),
+ ignore;
+handle_event(_Ev = #wx{event=#wxKey{keyCode=Key, controlDown=true}}, _WinInfo) ->
+ if
+ Key/=?WXK_UP, Key/=?WXK_DOWN, Key /=? WXK_RETURN ->
+ try
+ {shortcut, list_to_atom([Key+($a-$A)])}
+ catch _:_ -> ignore
+ end;
+ true ->
+ ignore
+ end;
+
+handle_event(#wx{userData={break, Point, status},
+ event=#wxCommand{type=command_menu_selected}},
+ WinInfo) ->
+ {value, BreakInfo} = lists:keysearch(Point, #breakInfo.point,
+ WinInfo#winInfo.breaks),
+ %% This is a temporary hack !!
+ #breakInfo{break=#break{smi=Smi}} = BreakInfo,
+
+ case wxMenuItem:getText(Smi) of
+ "Enable" -> {break, Point, {status, active}};
+ "Disable" -> {break, Point, {status, inactive}}
+ end;
+
+%% Listbox
+handle_event(#wx{event=#wxCommand{type=command_listbox_doubleclicked, cmdString=ModS}},
+ _WinInfo) ->
+ {module, list_to_atom(ModS), view};
+handle_event(#wx{obj=ListBox, event=#wxMouse{type=right_down, x=X,y=Y}},
+ #winInfo{listbox=ListBox}) ->
+ case wxListBox:hitTest(ListBox, {X,Y}) of
+ ?wxNOT_FOUND -> ignore;
+ Row ->
+ ModS = wxListBox:getString(ListBox,Row),
+ io:format("Re-loading/interpreting: ~s~n", [ModS]),
+ int:i(list_to_atom(ModS)),
+ ignore
+ end;
+
+%% Auto attach buttons
+handle_event(#wx{event=#wxCommand{type=command_checkbox_clicked}},
+ WinInfo) ->
+ Check = fun(Button, NamesAcc) ->
+ case wxCheckBox:isChecked(Button) of
+ true ->
+ Name = wxCheckBox:getLabel(Button),
+ [list_to_atom(Name)|NamesAcc];
+ false ->
+ NamesAcc
+ end
+ end,
+ Names = wx:foldl(Check, [],
+ [WinInfo#winInfo.ebutton,
+ WinInfo#winInfo.bbutton,
+ WinInfo#winInfo.fbutton]),
+ {'Auto Attach', Names};
+
+%% Process grid
+handle_event(#wx{event=#wxList{type=command_list_item_selected,
+ itemIndex=Row}}, WinInfo) ->
+ #winInfo{processes=Pids} = WinInfo,
+ {value, #procInfo{pid=Pid}} =
+ lists:keysearch(Row, #procInfo.row, Pids),
+ {focus, Pid, WinInfo#winInfo{focus=Row}};
+handle_event(#wx{event=#wxList{type=command_list_item_activated}},
+ _WinInfo) ->
+ default;
+handle_event(#wx{event=#wxMouse{type=enter_window}}, #winInfo{grid=Grid}) ->
+ %% Keyboard focus
+ wxWindow:setFocus(Grid),
+ ignore;
+
+%% Menu Events
+handle_event(#wx{userData=Data,
+ event=_Cmd=#wxCommand{type=command_menu_selected}},
+ _WinInfo) ->
+ Data;
+handle_event(_Event, _WinInfo) ->
+%% io:format("Ev: ~p~n",[_Event]),
+ ignore.
+
+%%====================================================================
+%% Internal functions
+%%====================================================================
+
+