aboutsummaryrefslogtreecommitdiffstats
path: root/lib/reltool/src
diff options
context:
space:
mode:
authorSiri Hansen <[email protected]>2012-02-29 16:30:13 +0100
committerSiri Hansen <[email protected]>2012-03-19 09:48:54 +0100
commit2be5415d4a5d024c223d340381ef74e3697fc7ea (patch)
treee7da5710fb75cbc064a3708be28d98f790feeef8 /lib/reltool/src
parenta3a7c3590f549c609749cff16da7d00af2c114d3 (diff)
downloadotp-2be5415d4a5d024c223d340381ef74e3697fc7ea.tar.gz
otp-2be5415d4a5d024c223d340381ef74e3697fc7ea.tar.bz2
otp-2be5415d4a5d024c223d340381ef74e3697fc7ea.zip
[reltool] Display warnings continously in GUI
OTP-9967 All active warnings are now displayed in a specific warning list at the bottom of the sys windows. Warnings do no longer cause popup dialogs during configuration. The reason for this is to avoid the same warning to pop up many times. This would happen since each configuration change now causes a fresh reading of the file system - and thus each warning would be detected each time the configuration was changed. reltool_manual_gui_SUITE is updated to test the new functionality.
Diffstat (limited to 'lib/reltool/src')
-rw-r--r--lib/reltool/src/reltool_sys_win.erl207
-rw-r--r--lib/reltool/src/reltool_utils.erl12
2 files changed, 182 insertions, 37 deletions
diff --git a/lib/reltool/src/reltool_sys_win.erl b/lib/reltool/src/reltool_sys_win.erl
index c75b302770..29a01b63d8 100644
--- a/lib/reltool/src/reltool_sys_win.erl
+++ b/lib/reltool/src/reltool_sys_win.erl
@@ -56,7 +56,9 @@
derived,
fgraph_wins,
app_box,
- mod_box
+ mod_box,
+ warning_list,
+ warning_wins
}).
-define(WIN_WIDTH, 800).
@@ -88,6 +90,10 @@
-define(blacklist, "Excluded").
-define(derived, "Derived").
+-define(WARNING_COL, 0).
+-define(DEFAULT_WARNING_TIP, "Warnings are listed in this window").
+-define(WARNING_POPUP_SIZE, {400,150}).
+
-define(safe_config,{sys,[{incl_cond,exclude},
{app,kernel,[{incl_cond,include}]},
{app,stdlib,[{incl_cond,include}]},
@@ -150,7 +156,8 @@ do_init([{safe_config, Safe}, {parent, Parent} | Options]) ->
target_dir = filename:absname("reltool_target_dir"),
app_wins = [],
sys = Sys,
- fgraph_wins = []},
+ fgraph_wins = [],
+ warning_wins = []},
S2 = create_window(S),
S5 = wx:batch(fun() ->
Title = atom_to_list(?APPLICATION),
@@ -235,10 +242,18 @@ loop(S) ->
lists:keydelete(ObjRef, #fgraph_win.frame, FWs),
?MODULE:loop(S#state{fgraph_wins = FWs2});
false ->
- error_logger:format("~p~p got unexpected "
- "message:\n\t~p\n",
- [?MODULE, self(), Msg]),
- ?MODULE:loop(S)
+ WWs = S#state.warning_wins,
+ case lists:member(ObjRef, WWs) of
+ true ->
+ wxFrame:destroy(ObjRef),
+ WWs2 = lists:delete(ObjRef, WWs),
+ ?MODULE:loop(S#state{warning_wins = WWs2});
+ false ->
+ error_logger:format("~p~p got unexpected "
+ "message:\n\t~p\n",
+ [?MODULE, self(), Msg]),
+ ?MODULE:loop(S)
+ end
end
end;
#wx{id = ?CLOSE_ITEM,
@@ -292,8 +307,8 @@ handle_child_exit({'EXIT', Pid, _Reason} = Exit, FWs, AWs) ->
msg_warning(Exit, application_window),
{FWs, lists:keydelete(Pid, #app_win.pid, AWs)};
false ->
- msg_warning(Exit, unknown),
- {FWs, AWs}
+ msg_warning(Exit, unknown),
+ {FWs, AWs}
end
end.
@@ -335,8 +350,12 @@ create_window(S) ->
fun create_main_release_page/1,
fun create_config_page/1
]),
+
+ S4 = create_warning_list(S3),
+
Sizer = wxBoxSizer:new(?wxVERTICAL),
wxSizer:add(Sizer, Book, [{flag, ?wxEXPAND}, {proportion, 1}]),
+ wxSizer:add(Sizer, S4#state.warning_list, [{flag, ?wxEXPAND}]),
wxPanel:setSizer(Panel, Sizer),
wxSizer:fit(Sizer, Frame),
@@ -344,7 +363,7 @@ create_window(S) ->
wxFrame:connect(Frame, close_window),
wxFrame:show(Frame),
- S3.
+ S4.
create_menubar(Frame) ->
MenuBar = wxMenuBar:new(),
@@ -637,6 +656,48 @@ redraw_config_page(#state{sys = Sys, app_box = AppBox, mod_box = ModBox} = S) ->
wxRadioBox:setSelection(ModBox, ModChoice),
S.
+create_warning_list(#state{panel = Panel} = S) ->
+ ListCtrl = wxListCtrl:new(Panel,
+ [{style,
+ ?wxLC_REPORT bor
+ ?wxLC_HRULES bor
+ ?wxVSCROLL},
+ {size, {?WIN_WIDTH,80}}]),
+ reltool_utils:assign_image_list(ListCtrl),
+ wxListCtrl:insertColumn(ListCtrl, ?WARNING_COL, "Warnings",
+ [{format,?wxLIST_FORMAT_LEFT}]),
+ wxListCtrl:setToolTip(ListCtrl, ?DEFAULT_WARNING_TIP),
+ wxEvtHandler:connect(ListCtrl, size,
+ [{skip, true}, {userData, warnings}]),
+ wxEvtHandler:connect(ListCtrl, command_list_item_activated,
+ [{userData, warnings}]),
+ wxEvtHandler:connect(ListCtrl, motion, [{userData, warnings}]),
+ wxEvtHandler:connect(ListCtrl, enter_window),
+ S#state{warning_list=ListCtrl}.
+
+redraw_warnings(S) ->
+ {ok,Warnings} = reltool_server:get_status(S#state.server_pid),
+ redraw_warnings(S#state.warning_list,Warnings),
+ length(Warnings).
+
+redraw_warnings(ListCtrl, []) ->
+ wxListCtrl:deleteAllItems(ListCtrl),
+ ok;
+redraw_warnings(ListCtrl, Warnings) ->
+ wxListCtrl:deleteAllItems(ListCtrl),
+ Show = fun(Warning, Row) ->
+ wxListCtrl:insertItem(ListCtrl, Row, ""),
+ wxListCtrl:setItem(ListCtrl,
+ Row,
+ ?WARNING_COL,
+ Warning,
+ [{imageId, ?WARN_IMAGE}]),
+ Row + 1
+ end,
+ wx:foldl(Show, 0, Warnings),
+ ok.
+
+
create_main_release_page(#state{book = Book} = S) ->
Panel = wxPanel:new(Book, []),
RelBook = wxNotebook:new(Panel, ?wxID_ANY, []),
@@ -778,6 +839,9 @@ escript_popup(S, File, Tree, Item) ->
handle_event(S, #wx{id = Id, obj= ObjRef, userData = UserData, event = Event} = _Wx) ->
%% io:format("wx: ~p\n", [Wx]),
case Event of
+ _ when UserData =:= warnings;
+ is_tuple(UserData), element(1,UserData)=:=warning ->
+ handle_warning_event(S, ObjRef, UserData, Event);
#wxSize{type = size, size = {W, _H}} when UserData =:= app_list_ctrl ->
wxListCtrl:setColumnWidth(ObjRef, ?APPS_APP_COL, W),
S;
@@ -855,6 +919,78 @@ handle_event(S, #wx{id = Id, obj= ObjRef, userData = UserData, event = Event} =
end
end.
+handle_warning_event(S, ObjRef, _, #wxSize{type = size}) ->
+ {Total, _} = wxWindow:getClientSize(ObjRef),
+ SBSize = scroll_size(ObjRef),
+ wxListCtrl:setColumnWidth(ObjRef, ?WARNING_COL, Total-SBSize),
+ S;
+handle_warning_event(S, ObjRef, _, #wxMouse{type = motion, x=X, y=Y}) ->
+ Pos = reltool_utils:wait_for_stop_motion(ObjRef, {X,Y}),
+ Index = wxListCtrl:findItem(ObjRef,-1,Pos,0),
+ Tip =
+ case wxListCtrl:getItemText(ObjRef,Index) of
+ "" ->
+ ?DEFAULT_WARNING_TIP;
+ Text ->
+ "WARNING:\n" ++ Text
+ end,
+ wxListCtrl:setToolTip(ObjRef, Tip),
+ S;
+handle_warning_event(S, ObjRef, _, #wxList{type = command_list_item_activated,
+ itemIndex = Pos}) ->
+ Text = wxListCtrl:getItemText(ObjRef, Pos),
+ S#state{warning_wins = [display_warning(S,Text) | S#state.warning_wins]};
+handle_warning_event(S, _ObjRef, {warning,Frame},
+ #wxCommand{type = command_button_clicked}) ->
+ wxFrame:destroy(Frame),
+ S#state{warning_wins = lists:delete(Frame,S#state.warning_wins)}.
+
+
+display_warning(S,Warning) ->
+ Pos = warning_popup_position(S,?WARNING_POPUP_SIZE),
+ Frame = wxFrame:new(wx:null(), ?wxID_ANY, "Warning",[{pos,Pos}]),
+ Panel = wxPanel:new(Frame, []),
+ TextStyle = ?wxTE_READONLY bor ?wxTE_WORDWRAP bor ?wxTE_MULTILINE,
+ Text = wxTextCtrl:new(Panel, ?wxID_ANY, [{value, Warning},
+ {style, TextStyle},
+ {size, ?WARNING_POPUP_SIZE}]),
+ Color = wxWindow:getBackgroundColour(Frame),
+ wxTextCtrl:setBackgroundColour(Text,Color),
+ Attr = wxTextAttr:new(),
+ wxTextAttr:setLeftIndent(Attr,10),
+ wxTextAttr:setRightIndent(Attr,10),
+ true = wxTextCtrl:setDefaultStyle(Text, Attr),
+ wxTextAttr:destroy(Attr),
+ Sizer = wxBoxSizer:new(?wxVERTICAL),
+ wxSizer:add(Sizer, Text, [{border, 2},
+ {flag, ?wxEXPAND bor ?wxALL},
+ {proportion, 1}]),
+
+ Close = wxButton:new(Panel, ?wxID_ANY, [{label, "Close"}]),
+ wxButton:setToolTip(Close, "Close window."),
+ wxButton:connect(Close, command_button_clicked, [{userData,{warning,Frame}}]),
+ wxSizer:add(Sizer, Close, [{flag, ?wxALIGN_CENTER_HORIZONTAL}]),
+
+ wxPanel:setSizer(Panel, Sizer),
+ wxSizer:fit(Sizer, Frame),
+ wxSizer:setSizeHints(Sizer, Frame),
+ wxFrame:connect(Frame, close_window),
+
+ wxFrame:show(Frame),
+ Frame.
+
+warning_popup_position(#state{frame=MF,warning_list=WL},{WFW,WFH}) ->
+ {MFX,MFY} = wxWindow:getPosition(MF),
+ {MFW,MFH} = wxWindow:getSize(MF),
+ {_WLW,WLH} = wxWindow:getSize(WL),
+
+ %% Position the popup in the middle of the main frame, above the
+ %% warning list, and with a small offset from the exact middle...
+ Offset = 50,
+ X = MFX + (MFW-WFW) div 2 - Offset,
+ Y = MFY + (MFH-WLH-WFH) div 2 - Offset,
+ {X,Y}.
+
handle_popup_event(S, _Type, 0, _ObjRef, _UserData, _Str) ->
S#state{popup_menu = undefined};
handle_popup_event(#state{popup_menu = #root_popup{dir = OldDir,
@@ -1079,11 +1215,8 @@ handle_app_button(#state{server_pid = ServerPid, app_wins = AppWins} = S,
Action) ->
NewApps = [move_app(S, Item, Action) || Item <- Items],
case reltool_server:set_apps(ServerPid, NewApps) of
- {ok, []} ->
+ {ok, _Warnings} ->
ok;
- {ok, Warnings} ->
- Msg = lists:flatten([[W, $\n] || W <- Warnings]),
- display_message(Msg, ?wxICON_WARNING);
{error, Reason} ->
display_message(Reason, ?wxICON_ERROR)
end,
@@ -1122,21 +1255,17 @@ move_app(S, {_ItemNo, AppBase}, Action) ->
do_set_app(#state{server_pid = ServerPid, app_wins = AppWins} = S, NewApp) ->
Result = reltool_server:set_app(ServerPid, NewApp),
- [ok = reltool_app_win:refresh(AW#app_win.pid) || AW <- AppWins],
- S2 = redraw_apps(S),
ReturnApp =
case Result of
- {ok, AnalysedApp, []} ->
- AnalysedApp;
- {ok, AnalysedApp, Warnings} ->
- Msg = lists:flatten([[W, $\n] || W <- Warnings]),
- display_message(Msg, ?wxICON_WARNING),
+ {ok, AnalysedApp, _Warnings} ->
AnalysedApp;
{error, Reason} ->
display_message(Reason, ?wxICON_ERROR),
{ok,OldApp} = reltool_server:get_app(ServerPid, NewApp#app.name),
OldApp
end,
+ [ok = reltool_app_win:refresh(AW#app_win.pid) || AW <- AppWins],
+ S2 = redraw_apps(S),
{ok, ReturnApp, S2}.
redraw_apps(#state{server_pid = ServerPid,
@@ -1159,8 +1288,14 @@ redraw_apps(#state{server_pid = ServerPid,
WhiteN = redraw_apps(WhiteApps, WhiteCtrl, ?TICK_IMAGE, ?ERR_IMAGE),
redraw_apps(BlackApps2, BlackCtrl, ?CROSS_IMAGE, ?WARN_IMAGE),
DerivedN = redraw_apps(DerivedApps, DerivedCtrl, ?TICK_IMAGE, ?ERR_IMAGE),
+
+ WarningsN = redraw_warnings(S),
+ WarningText = if WarningsN==1 -> "warning";
+ true -> "warnings"
+ end,
Status = lists:concat([WhiteN, " whitelisted modules and ",
- DerivedN, " derived modules."]),
+ DerivedN, " derived modules, ",
+ WarningsN, " ", WarningText, "."]),
wxStatusBar:setStatusText(S#state.status_bar, Status),
S.
@@ -1375,8 +1510,8 @@ check_and_refresh(S, Status) ->
case Status of
ok ->
true;
- {ok, Warnings} ->
- undo_dialog(S, Warnings);
+ {ok, _Warnings} ->
+ true;
{error, Reason} when is_list(Reason) ->
display_message(Reason, ?wxICON_ERROR),
false;
@@ -1430,19 +1565,6 @@ question_dialog(Question, Details) ->
wxDialog:destroy(Dialog),
Answer.
-undo_dialog(_S, []) ->
- true;
-undo_dialog(S, Warnings) ->
- Question = "Do you want to perform the update despite these warnings?",
- Details = lists:flatten([[W, $\n] || W <- Warnings]),
- case question_dialog(Question, Details) of
- ?wxID_OK ->
- true;
- ?wxID_CANCEL ->
- ok = reltool_server:undo_config(S#state.server_pid),
- false
- end.
-
display_message(Message, Icon) ->
Dialog = wxMessageDialog:new(wx:null(),
Message,
@@ -1486,6 +1608,19 @@ add_text(_,_,[]) ->
ok.
+scroll_size(ObjRef) ->
+ case os:type() of
+ {win32, nt} -> 0;
+ {unix, darwin} ->
+ %% I can't figure out is there is a visible scrollbar
+ %% Always make room for it
+ wxSystemSettings:getMetric(?wxSYS_VSCROLL_X);
+ _ ->
+ case wxWindow:hasScrollbar(ObjRef, ?wxVERTICAL) of
+ true -> wxSystemSettings:getMetric(?wxSYS_VSCROLL_X);
+ false -> 0
+ end
+ end.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
diff --git a/lib/reltool/src/reltool_utils.erl b/lib/reltool/src/reltool_utils.erl
index a9107355c7..2d766224d9 100644
--- a/lib/reltool/src/reltool_utils.erl
+++ b/lib/reltool/src/reltool_utils.erl
@@ -23,7 +23,7 @@
split_app_name/1, prim_consult/1,
default_rels/0, choose_default/3,
- assign_image_list/1, get_latest_resize/1,
+ assign_image_list/1, get_latest_resize/1, wait_for_stop_motion/2,
mod_conds/0, list_to_mod_cond/1, mod_cond_to_index/1,
incl_conds/0, list_to_incl_cond/1, incl_cond_to_index/1, elem_to_index/2,
app_dir_test/2, split_app_dir/1,
@@ -191,6 +191,16 @@ get_latest_resize(#wx{obj = ObjRef, event = #wxSize{}} = Wx) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+wait_for_stop_motion(ObjRef, {_,_}=Pos) ->
+ receive
+ #wx{obj = ObjRef, event = #wxMouse{type = motion, x=X, y=Y}} ->
+ wait_for_stop_motion(ObjRef, {X,Y})
+ after 100 ->
+ Pos
+ end.
+
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
mod_conds() ->
["all (ebin + app file)", "ebin + derived", "app file + derived", "derived", "none"].