1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2008-2017. All Rights Reserved. 5%% 6%% Licensed under the Apache License, Version 2.0 (the "License"); 7%% you may not use this file except in compliance with the License. 8%% You may obtain a copy of the License at 9%% 10%% http://www.apache.org/licenses/LICENSE-2.0 11%% 12%% Unless required by applicable law or agreed to in writing, software 13%% distributed under the License is distributed on an "AS IS" BASIS, 14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15%% See the License for the specific language governing permissions and 16%% limitations under the License. 17%% 18%% %CopyrightEnd% 19%% 20 21%% 22-module(dbg_wx_break_win). 23 24%% External exports 25-export([create_win/5, 26 update_functions/2, 27 handle_event/2]). 28 29-include_lib("wx/include/wx.hrl"). 30 31-record(winInfo, {type, % line | conditional | function 32 win, % wxobj() 33 entries, % [{atom|integer, wxobj()}] 34 trigger, % [{wxobj(),enable | disable | delete}] 35 listbox, % wxobj() 36 text, % wxobj() 37 ok, % wxobj() 38 funcs=[] % [[Name, Arity]] 39 }). 40 41%%==================================================================== 42%% External exports 43%%==================================================================== 44 45%%-------------------------------------------------------------------- 46%% create_win(Win, Pos, Type, Mod, Line) -> #winInfo{} 47%% Win = Top level window 48%% Pos = {X, Y} 49%% X = Y = integer() 50%% Type = line | conditional | function 51%% Mod = atom() | "" 52%% Line = integer() | "" 53%%-------------------------------------------------------------------- 54 55create_win(Parent, Pos, function, Mod, _Line) -> 56 Win = wxDialog:new(Parent, ?wxID_ANY, "Function Break", 57 [{pos, Pos}, 58 {style, ?wxDEFAULT_DIALOG_STYLE bor ?wxRESIZE_BORDER}]), 59 MainS = wxBoxSizer:new(?wxVERTICAL), 60 Label = wxStaticText:new(Win, ?wxID_ANY, "Module:"), 61 Int = int:interpreted(), 62 IntStrs = [atom_to_list(M) || M <- Int], 63 Text = wxComboBox:new(Win, ?wxID_ANY, 64 [{value, dbg_wx_win:to_string(Mod)}, 65 {choices, IntStrs}]), 66 67 Expand = [{border, 5}, {flag,?wxLEFT bor ?wxRIGHT bor ?wxEXPAND}], 68 _ = wxSizer:add(MainS, Label, [{border,5}, 69 {flag,?wxTOP bor ?wxLEFT bor ?wxRIGHT}]), 70 _ = wxSizer:add(MainS, Text, Expand), 71 FunLabel = wxStaticText:new(Win, ?wxID_ANY, "Function:"), 72 LB = wxListBox:new(Win, ?wxID_ANY, [{size,{-1, 100}},{style,?wxLB_MULTIPLE}]), 73 _ = wxSizer:add(MainS, FunLabel, Expand), 74 _ = wxSizer:add(MainS, LB, [{proportion,1}|Expand]), 75 wxSizer:setMinSize(MainS, 300, 400), 76 OK = wxDialog:createStdDialogButtonSizer(Win, ?wxOK bor ?wxCANCEL), 77 _ = wxSizer:add(MainS, OK, [{border,5},{flag,?wxALL}]), 78 wxDialog:setSizer(Win,MainS), 79 _ = wxSizer:fit(MainS, Win), 80 wxSizer:setSizeHints(MainS,Win), 81 wxComboBox:setFocus(Text), 82 wxDialog:connect(Win, command_button_clicked), 83 wxComboBox:connect(Text, command_text_updated), 84 wxListBox:connect(LB, command_listbox_selected), 85 wxListBox:connect(LB, command_listbox_doubleclicked), 86 OKId = wxDialog:getAffirmativeId(Win), 87 OKButt = wxWindow:findWindowById(OKId, [{parent, Win}]), 88 wxWindow:disable(OKButt), 89 wxDialog:centreOnParent(Win), 90 wxDialog:show(Win), 91 92 #winInfo{type=function, win=Win, text=Text, ok=OKButt, 93 entries=[], trigger=enable, 94 listbox=LB, funcs=[]}; 95 96create_win(Parent, Pos, Type, Mod, Line) -> 97 Title = case Type of 98 line -> "Line Break"; 99 conditional -> "Conditional Break" 100 end, 101 Style = ?wxDEFAULT_DIALOG_STYLE bor ?wxRESIZE_BORDER, 102 Win = wxDialog:new(Parent, ?wxID_ANY, Title, 103 [{pos, Pos}, 104 {style, Style}]), 105 %% Create Sizers 106 MainS = wxBoxSizer:new(?wxVERTICAL), 107 108 %% Add module 109 Int = int:interpreted(), 110 IntStrs = [atom_to_list(M) || M <- Int], 111 ModT = wxComboBox:new(Win, ?wxID_ANY, [{choices,IntStrs}]), 112 ModSz = create_label_of_control(Win, "Module:", ModT, Mod), 113 _ = wxSizer:add(MainS,ModSz,[{flag, ?wxEXPAND}]), 114 %% Create rest of text input fields 115 Add = fun({IType, Label, Def}) -> 116 {Sz, Text} = create_sizer_with_text(Win, Label, Def), 117 _ = wxSizer:add(MainS, Sz, [{flag, ?wxEXPAND}]), 118 {Text, IType} 119 end, 120 Inputs = case Type of 121 line -> 122 [{integer,"Line:",Line}]; 123 conditional -> 124 [{integer,"Line:",Line}, 125 {atom,"C-Module:",""}, 126 {atom,"C-Function:",""}] 127 end, 128 %% Add the rest of the entries 129 Entries = wx:map(Add, Inputs), 130 %% Create and add radio box 131 {TriggerBox,Trigger} = create_trigger_box(Win), 132 _ = wxSizer:add(MainS, TriggerBox, [{border,5},{flag,?wxALL bor ?wxEXPAND}]), 133 134 _ = wxSizer:addStretchSpacer(MainS), 135 %% Put it together 136 OK = wxDialog:createStdDialogButtonSizer(Win, ?wxOK bor ?wxCANCEL), 137 _ = wxSizer:add(MainS, OK, [{border,5},{flag,?wxALL}]), 138 wxSizer:setMinSize(MainS, 300, -1), 139 wxDialog:setSizer(Win,MainS), 140 _ = wxSizer:fit(MainS, Win), 141 wxSizer:setSizeHints(MainS,Win), 142 wxComboBox:setFocus(ModT), 143 wxDialog:connect(Win, command_button_clicked), 144 wxDialog:connect(Win, command_text_updated), 145 OKId = wxDialog:getAffirmativeId(Win), 146 OKButt = wxWindow:findWindowById(OKId), 147 wxWindow:disable(OKButt), 148 wxDialog:centreOnParent(Win), 149 wxDialog:show(Win), 150 #winInfo{type=Type, win=Win, text=ModT, 151 entries=Entries, trigger=Trigger, ok=OKButt}. 152 153%%-------------------------------------------------------------------- 154%% update_functions(WinInfo, Funcs) -> WinInfo 155%% WinInfo = #winInfo{} 156%% Funcs = [{Name, Arity}] 157%% Name = atom() 158%% Arity = integer() 159%%-------------------------------------------------------------------- 160update_functions(WinInfo, Funcs) -> 161 Items = lists:map(fun([N, A]) -> 162 lists:flatten(io_lib:format("~tw/~w", [N,A])) 163 end, 164 Funcs), 165 wxListBox:set(WinInfo#winInfo.listbox, Items), 166 WinInfo#winInfo{funcs=Funcs}. 167 168%%-------------------------------------------------------------------- 169%% handle_event(WxEvent, WinInfo) -> Command 170%% WxEvent = #wx{} 171%% WinInfo = #winInfo{} 172%% Command = ignore 173%% | stopped 174%% | {win, WinInfo} 175%% | {module, Mod} 176%% | {break, [[Mod, Line]], Action} 177%% | {break, [[Mod, Line, CMod, CFunc]], Action} 178%% | {break, [[Mod, Func, Arity]], Action} 179%%-------------------------------------------------------------------- 180handle_event(#wx{id=?wxID_CANCEL}, #winInfo{win=Win}) -> 181 wxDialog:destroy(Win), 182 stopped; 183handle_event(#wx{event=#wxCommand{type=command_text_updated}}, 184 #winInfo{type=function, text=Text, ok=OK}) -> 185 Module = wxComboBox:getValue(Text), 186 wxWindow:disable(OK), 187 {module, list_to_atom(Module)}; 188handle_event(#wx{event=#wxCommand{type=command_text_updated}}, 189 #winInfo{text=Text, ok=OK, entries=Es}) -> 190 Module = wxComboBox:getValue(Text), 191 case check_input(Es) of 192 error -> wxWindow:disable(OK); 193 _Data when Module =/= "" -> wxWindow:enable(OK); 194 _ -> wxWindow:disable(OK) 195 end, 196 ignore; 197handle_event(#wx{event=#wxCommand{type=command_listbox_selected}}, 198 #winInfo{type=function, listbox=LB, ok=OK}) -> 199 case wxListBox:getSelections(LB) of 200 {N,_} when N > 0 -> wxWindow:enable(OK); 201 _ -> wxWindow:disable(OK) 202 end, 203 ignore; 204handle_event(#wx{id=OKorListBox, event=#wxCommand{type=OKorDoubleClick}}, 205 #winInfo{type=function,win=Win,listbox=LB,funcs=Funcs,text=Text}) 206 when OKorListBox =:= ?wxID_OK; 207 OKorDoubleClick =:= command_listbox_doubleclicked -> 208 Mod = wxComboBox:getValue(Text), 209 {_, IndexL} = wxListBox:getSelections(LB), 210 Breaks = [[list_to_atom(Mod)|lists:nth(Index+1, Funcs)] || Index <- IndexL], 211 wxDialog:destroy(Win), 212 {break, Breaks, enable}; 213handle_event(#wx{id=?wxID_OK},#winInfo{win=Win,text=Text, entries=Es, trigger=Trigger}) -> 214 %% Non function box 215 Mod = wxComboBox:getValue(Text), 216 Data = check_input(Es), 217 Trigged = get_trigger(Trigger), 218 wxDialog:destroy(Win), 219 {break, [[list_to_atom(Mod)|Data]], Trigged}; 220 221handle_event(_WxEvent, _WinInfo) -> 222 %% io:format("Ev: ~p ~n", [_WxEvent]), 223 ignore. 224 225check_input(Entries) -> 226 check_input(Entries, []). 227check_input([{Entry, Type} | Entries], Data) -> 228 Str = wxTextCtrl:getValue(Entry), 229 case erl_scan:string(Str) of 230 {ok, [{Type, _Line, Val}], _EndLine} -> 231 check_input(Entries, [Val|Data]); 232 _Error -> error 233 end; 234check_input([], Data) -> lists:reverse(Data). 235 236create_sizer_with_text(Parent,Label,Def) -> 237 Text = wxTextCtrl:new(Parent, ?wxID_ANY), 238 Sz = create_label_of_control(Parent, Label, Text, Def), 239 {Sz, Text}. 240 241create_label_of_control(Parent, Label, Control, Def) -> 242 Sizer = wxBoxSizer:new(?wxHORIZONTAL), 243 Text = wxStaticText:new(Parent, ?wxID_ANY, Label), 244 Border = {border, 5}, 245 Flag = ?wxRIGHT bor ?wxLEFT bor ?wxALIGN_CENTRE_VERTICAL, 246 _ = wxSizer:add(Sizer, Text, [{proportion,1}, {flag,Flag}, Border]), 247 _ = wxSizer:add(Sizer, Control, [{proportion,3}, {flag,Flag bor ?wxEXPAND}, Border]), 248 wxControl:setLabel(Control, dbg_wx_win:to_string(Def)), 249 Sizer. 250 251create_trigger_box(Win) -> 252 SBox = wxStaticBox:new(Win, ?wxID_ANY, "Trigger Action:"), 253 SBS = wxStaticBoxSizer:new(SBox, ?wxVERTICAL), 254 Ebtn = wxRadioButton:new(Win, ?wxID_ANY, "Enable"), 255 _ = wxSizer:add(SBS,Ebtn), 256 Dibtn = wxRadioButton:new(Win, ?wxID_ANY, "Disable"), 257 _ = wxSizer:add(SBS,Dibtn), 258 Debtn = wxRadioButton:new(Win, ?wxID_ANY, "Delete"), 259 _ = wxSizer:add(SBS,Debtn), 260 wxRadioButton:setValue(Ebtn, true), 261 {SBS, [{Ebtn,enable},{Dibtn,disable},{Debtn,delete}]}. 262 263get_trigger([{Btn,Op}|R]) -> 264 case wxRadioButton:getValue(Btn) of 265 true -> Op; 266 false -> get_trigger(R) 267 end. 268 269 270