4
%% Copyright Ericsson AB 2009. All Rights Reserved.
4
%% Copyright Ericsson AB 2009-2010. All Rights Reserved.
6
6
%% The contents of this file are subject to the Erlang Public License,
7
7
%% Version 1.1, (the "License"); you may not use this file except in
8
8
%% compliance with the License. You should have received a copy of the
9
9
%% Erlang Public License along with this software. If not, it can be
10
10
%% retrieved online at http://www.erlang.org/.
12
12
%% Software distributed under the License is distributed on an "AS IS"
13
13
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
14
14
%% the License for the specific language governing rights and limitations
15
15
%% under the License.
19
19
-module(reltool_sys_win).
146
150
S3 = S2#state{sys = Sys2},
147
151
S5 = wx:batch(fun() ->
148
152
Title = atom_to_list(?APPLICATION),
149
wxFrame:setTitle(S3#state.frame, Title),
150
%% wxFrame:setMinSize(Frame, {?WIN_WIDTH, ?WIN_HEIGHT}),
151
wxStatusBar:setStatusText(S3#state.status_bar, "Done."),
153
wxFrame:setTitle(S3#state.frame,
155
%% wxFrame:setMinSize(Frame,
156
%% {?WIN_WIDTH, ?WIN_HEIGHT}),
157
wxStatusBar:setStatusText(
152
160
S4 = redraw_apps(S3),
193
206
FWs = S#state.fgraph_wins,
194
207
case lists:keysearch(ObjRef, #fgraph_win.frame, FWs) of
196
reltool_fgraph_win:stop(FW#fgraph_win.pid, shutdown),
209
reltool_fgraph_win:stop(FW#fgraph_win.pid,
197
211
wxFrame:destroy(ObjRef),
198
FWs2 = lists:keydelete(ObjRef, #fgraph_win.frame, FWs),
213
lists:keydelete(ObjRef, #fgraph_win.frame, FWs),
199
214
?MODULE:loop(S#state{fgraph_wins = FWs2});
201
error_logger:format("~p~p got unexpected message:\n\t~p\n",
202
[?MODULE, self(), Msg]),
216
error_logger:format("~p~p got unexpected "
218
[?MODULE, self(), Msg]),
206
#wx{id = ?CLOSE_ITEM, event = #wxCommand{type = command_menu_selected}, userData = main_window} ->
222
#wx{id = ?CLOSE_ITEM,
223
event = #wxCommand{type = command_menu_selected},
224
userData = main_window} ->
207
225
wxFrame:destroy(S#state.frame),
209
227
#wx{event = #wxSize{}} = Wx ->
222
240
?MODULE:loop(S2);
223
241
{call, ReplyTo, Ref, {open_app, AppName}} ->
224
242
S2 = do_open_app(S, AppName),
225
{value, #app_win{pid = AppPid}} = lists:keysearch(AppName, #app_win.name, S2#state.app_wins),
243
{value, #app_win{pid = AppPid}} =
244
lists:keysearch(AppName, #app_win.name, S2#state.app_wins),
226
245
reltool_utils:reply(ReplyTo, Ref, {ok, AppPid}),
227
246
?MODULE:loop(S2);
228
247
{'EXIT', Pid, Reason} when Pid =:= S#state.parent_pid ->
229
[reltool_fgraph_win:stop(FW#fgraph_win.pid, Reason) || FW <- S#state.fgraph_wins],
248
[reltool_fgraph_win:stop(FW#fgraph_win.pid, Reason) ||
249
FW <- S#state.fgraph_wins],
231
251
{'EXIT', _Pid, _Reason} = Exit ->
232
{FWs, AWs} = handle_child_exit(Exit, S#state.fgraph_wins, S#state.app_wins),
252
{FWs, AWs} = handle_child_exit(Exit,
233
255
?MODULE:loop(S#state{fgraph_wins = FWs, app_wins = AWs});
235
257
error_logger:format("~p~p got unexpected message:\n\t~p\n",
262
284
create_window(S) ->
263
285
Title = lists:concat([?APPLICATION, " - starting up"]),
264
Frame = wxFrame:new(wx:null(), ?wxID_ANY, Title, [{size, {?WIN_WIDTH, ?WIN_HEIGHT}}]),
286
Frame = wxFrame:new(wx:null(), ?wxID_ANY, Title,
287
[{size, {?WIN_WIDTH, ?WIN_HEIGHT}}]),
265
288
%%wxFrame:setSize(Frame, {?WIN_WIDTH, ?WIN_HEIGHT}),
266
289
%% wxFrame:setMinSize(Frame, {?WIN_WIDTH, ?WIN_HEIGHT}),
267
290
Bar = wxFrame:createStatusBar(Frame,[]),
306
329
File = wxMenu:new([]),
307
330
Help = wxMenu:new([]),
308
331
wxMenuBar:append(MenuBar, File, "File" ),
309
wxMenu:append(File, ?APP_GRAPH_ITEM, "Display application dependency graph" ),
310
wxMenu:append(File, ?MOD_GRAPH_ITEM, "Display module dependency graph" ),
332
wxMenu:append(File, ?APP_GRAPH_ITEM,
333
"Display application dependency graph" ),
334
wxMenu:append(File, ?MOD_GRAPH_ITEM,
335
"Display module dependency graph" ),
311
336
wxMenu:appendSeparator(File),
312
337
wxMenu:append(File, ?RESET_CONFIG_ITEM, "Reset configuration to default" ),
313
338
wxMenu:append(File, ?UNDO_CONFIG_ITEM, "Undo configuration (toggle)" ),
314
339
wxMenu:append(File, ?LOAD_CONFIG_ITEM, "Load configuration" ),
315
340
Save = wxMenu:new(),
316
wxMenu:append(Save, ?SAVE_CONFIG_NODEF_NODER_ITEM, "Save explicit configuration (neither defaults nor derivates)"),
317
wxMenu:append(Save, ?SAVE_CONFIG_DEF_NODER_ITEM , "Save configuration defaults (defaults only)"),
318
wxMenu:append(Save, ?SAVE_CONFIG_NODEF_DER_ITEM, "Save configuration derivates (derivates only))"),
319
wxMenu:append(Save, ?SAVE_CONFIG_DEF_DER_ITEM, "Save extended configuration (both defaults and derivates)"),
341
wxMenu:append(Save, ?SAVE_CONFIG_NODEF_NODER_ITEM,
342
"Save explicit configuration "
343
"(neither defaults nor derivates)"),
344
wxMenu:append(Save, ?SAVE_CONFIG_DEF_NODER_ITEM,
345
"Save configuration defaults (defaults only)"),
346
wxMenu:append(Save, ?SAVE_CONFIG_NODEF_DER_ITEM,
347
"Save configuration derivates (derivates only))"),
348
wxMenu:append(Save, ?SAVE_CONFIG_DEF_DER_ITEM,
349
"Save extended configuration (both defaults and derivates)"),
321
351
wxMenu:append(File, ?wxID_ANY, "Save configuration", Save),
322
352
wxMenu:appendSeparator(File),
323
wxMenu:append(File, ?GEN_REL_FILES_ITEM, "Generate rel, script and boot files" ),
353
wxMenu:append(File, ?GEN_REL_FILES_ITEM,
354
"Generate rel, script and boot files" ),
324
355
wxMenu:append(File, ?GEN_TARGET_ITEM, "Generate target system" ),
325
356
wxMenu:appendSeparator(File),
326
357
wxMenu:append(File, ?CLOSE_ITEM, "Close" ),
375
406
%% ?wxLC_SINGLE_SEL bor
377
408
{size, {Width, Height}}]),
378
ToolTip = "Select application(s) or open separate application window with a double click.",
409
ToolTip = "Select application(s) or open separate "
410
"application window with a double click.",
379
411
wxListCtrl:setToolTip(ListCtrl, ToolTip),
382
414
reltool_utils:assign_image_list(ListCtrl),
384
416
%% Prep column label
385
417
ListItem = wxListItem:new(),
386
418
wxListItem:setAlign(ListItem, ?wxLIST_FORMAT_LEFT),
408
440
[{flag, ?wxEXPAND}, {proportion, 1}]),
410
442
%% Subscribe on events
411
wxEvtHandler:connect(ListCtrl, size, [{skip, true}, {userData, app_list_ctrl}]),
443
wxEvtHandler:connect(ListCtrl, size,
444
[{skip, true}, {userData, app_list_ctrl}]),
412
445
wxEvtHandler:connect(ListCtrl, command_list_item_activated),
413
wxWindow:connect(ListCtrl, enter_window),
446
wxWindow:connect(ListCtrl, enter_window),
448
481
create_lib_page(#state{book = Book} = S) ->
449
482
Panel = wxPanel:new(Book, []),
450
483
Sizer = wxBoxSizer:new(?wxHORIZONTAL),
452
Tree = wxTreeCtrl:new(Panel, [{style , ?wxTR_HAS_BUTTONS bor ?wxTR_HIDE_ROOT}]),
485
Tree = wxTreeCtrl:new(Panel,
486
[{style , ?wxTR_HAS_BUTTONS bor ?wxTR_HIDE_ROOT}]),
453
487
ToolTip = "Edit application sources.",
454
488
wxBitmapButton:setToolTip(Tree, ToolTip),
478
512
[append_lib(Tree, LibItem, Dir) || Dir <- Sys#sys.lib_dirs],
480
514
EscriptItem = append_item(Tree, Top, "Escript files", undefined),
481
EscriptData = #escript_data{file = undefined, tree = Tree, item = EscriptItem},
515
EscriptData = #escript_data{file = undefined,
482
518
wxTreeCtrl:setItemData(Tree,EscriptItem, EscriptData),
483
519
[append_escript(Tree, EscriptItem, File) || File <- Sys#sys.escripts],
484
520
wxTreeCtrl:expand(Tree, LibItem),
529
565
Panel = wxPanel:new(Book, []),
530
566
Sizer = wxBoxSizer:new(?wxHORIZONTAL),
531
567
AppConds = reltool_utils:incl_conds(),
532
AppBox = wxRadioBox:new(Panel,
568
AppBox = wxRadioBox:new(Panel,
534
"Application inclusion policy",
570
"Application inclusion policy",
535
571
?wxDefaultPosition,
543
579
wxEvtHandler:connect(AppBox, command_radiobox_selected,
544
580
[{userData, config_incl_cond}]),
545
581
ModConds = reltool_utils:mod_conds(),
546
ModBox = wxRadioBox:new(Panel,
582
ModBox = wxRadioBox:new(Panel,
548
"Module inclusion policy",
584
"Module inclusion policy",
549
585
?wxDefaultPosition,
582
618
wxButton:setToolTip(Create, "Create a new release."),
583
619
wxButton:connect(Create, command_button_clicked, [{userData, create_rel}]),
584
620
wxSizer:add(ButtonSizer, Create),
586
622
Delete = wxButton:new(Panel, ?wxID_ANY, [{label, "Delete"}]),
587
623
wxButton:setToolTip(Delete, "Delete a release."),
588
624
wxButton:connect(Delete, command_button_clicked, [{userData, delete_rel}]),
589
625
wxSizer:add(ButtonSizer, Delete),
591
627
View = wxButton:new(Panel, ?wxID_ANY, [{label, "View script"}]),
592
628
wxButton:setToolTip(View, "View generated script file."),
593
629
wxButton:connect(View, command_button_clicked, [{userData, view_script}]),
594
630
wxSizer:add(ButtonSizer, View),
596
632
[add_release_page(RelBook, Rel) || Rel <- (S#state.sys)#sys.rels],
598
634
wxSizer:add(Sizer, RelBook, [{flag, ?wxEXPAND}, {proportion, 1}]),
599
635
wxSizer:add(Sizer, ButtonSizer, [{flag, ?wxEXPAND}]),
600
636
wxPanel:setSizer(Panel, Sizer),
604
640
add_release_page(Book, #rel{name = RelName, rel_apps = RelApps}) ->
605
641
Panel = wxPanel:new(Book, []),
606
642
Sizer = wxBoxSizer:new(?wxHORIZONTAL),
607
RelBox = wxRadioBox:new(Panel,
643
RelBox = wxRadioBox:new(Panel,
609
"Applications included in the release " ++ RelName,
645
"Applications included in the release " ++ RelName,
610
646
?wxDefaultPosition,
612
648
[atom_to_list(RA#rel_app.name) || RA <- RelApps],
614
650
%% wxRadioBox:setSelection(RelBox, 2), % mandatory
615
wxEvtHandler:connect(RelBox, command_radiobox_selected, [{userData, {config_rel_cond, RelName}}]),
616
RelToolTip = "Choose which applications that shall be included in the release resource file.",
651
wxEvtHandler:connect(RelBox, command_radiobox_selected,
652
[{userData, {config_rel_cond, RelName}}]),
653
RelToolTip = "Choose which applications that shall "
654
"be included in the release resource file.",
617
655
wxBitmapButton:setToolTip(RelBox, RelToolTip),
619
657
wxSizer:add(Sizer,
629
667
do_open_app(S, AppName);
630
668
do_open_app(S, '') ->
632
do_open_app(#state{server_pid = ServerPid, common = C, app_wins = AppWins} = S, AppName) when is_atom(AppName) ->
670
do_open_app(#state{server_pid = ServerPid, common = C, app_wins = AppWins} = S,
672
when is_atom(AppName) ->
633
673
case lists:keysearch(AppName, #app_win.name, AppWins) of
635
675
WxEnv = wx:get_env(),
636
{ok, Pid} = reltool_app_win:start_link(WxEnv, ServerPid, C, AppName),
677
reltool_app_win:start_link(WxEnv, ServerPid, C, AppName),
637
678
AW = #app_win{name = AppName, pid = Pid},
638
679
S#state{app_wins = [AW | AppWins]};
651
692
wxEvtHandler:connect(PopupMenu, menu_close),
652
693
wxWindow:popupMenu(S#state.frame, PopupMenu),
654
Popup = #root_popup{dir = Root, choices = Choices, tree = Tree, item = Item},
695
Popup = #root_popup{dir = Root,
655
699
S#state{popup_menu = Popup}.
657
701
lib_popup(S, Lib, Tree, Item) ->
705
752
#wxSize{type = size, size = {W, _H}} when UserData =:= app_list_ctrl ->
706
753
wxListCtrl:setColumnWidth(ObjRef, ?APPS_APP_COL, W),
708
#wxCommand{type = command_menu_selected} when Id =:= ?APP_GRAPH_ITEM ->
755
#wxCommand{type = command_menu_selected}
756
when Id =:= ?APP_GRAPH_ITEM ->
709
757
update_app_graph(S);
710
#wxCommand{type = command_menu_selected} when Id =:= ?MOD_GRAPH_ITEM ->
758
#wxCommand{type = command_menu_selected}
759
when Id =:= ?MOD_GRAPH_ITEM ->
711
760
update_mod_graph(S);
712
#wxCommand{type = command_menu_selected} when Id =:= ?RESET_CONFIG_ITEM ->
761
#wxCommand{type = command_menu_selected}
762
when Id =:= ?RESET_CONFIG_ITEM ->
714
#wxCommand{type = command_menu_selected} when Id =:= ?UNDO_CONFIG_ITEM ->
764
#wxCommand{type = command_menu_selected}
765
when Id =:= ?UNDO_CONFIG_ITEM ->
716
#wxCommand{type = command_menu_selected} when Id =:= ?LOAD_CONFIG_ITEM ->
767
#wxCommand{type = command_menu_selected}
768
when Id =:= ?LOAD_CONFIG_ITEM ->
718
#wxCommand{type = command_menu_selected} when Id =:= ?SAVE_CONFIG_NODEF_NODER_ITEM ->
770
#wxCommand{type = command_menu_selected}
771
when Id =:= ?SAVE_CONFIG_NODEF_NODER_ITEM ->
719
772
save_config(S, false, false);
720
#wxCommand{type = command_menu_selected} when Id =:= ?SAVE_CONFIG_NODEF_DER_ITEM ->
773
#wxCommand{type = command_menu_selected}
774
when Id =:= ?SAVE_CONFIG_NODEF_DER_ITEM ->
721
775
save_config(S, false, true);
722
776
#wxCommand{type = command_menu_selected} when Id =:= ?SAVE_CONFIG_DEF_NODER_ITEM ->
723
777
save_config(S, true, false);
724
#wxCommand{type = command_menu_selected} when Id =:= ?SAVE_CONFIG_DEF_DER_ITEM ->
778
#wxCommand{type = command_menu_selected}
779
when Id =:= ?SAVE_CONFIG_DEF_DER_ITEM ->
725
780
save_config(S, true, true);
726
#wxCommand{type = command_menu_selected} when Id =:= ?GEN_REL_FILES_ITEM ->
781
#wxCommand{type = command_menu_selected}
782
when Id =:= ?GEN_REL_FILES_ITEM ->
727
783
gen_rel_files(S);
728
#wxCommand{type = command_menu_selected} when Id =:= ?GEN_TARGET_ITEM ->
784
#wxCommand{type = command_menu_selected}
785
when Id =:= ?GEN_TARGET_ITEM ->
730
#wxCommand{type = command_menu_selected} when UserData =:= main_window, Id =:= ?CONTENTS_ITEM ->
787
#wxCommand{type = command_menu_selected}
788
when UserData =:= main_window, Id =:= ?CONTENTS_ITEM ->
731
789
{file, BeamFile} = code:is_loaded(?MODULE),
732
790
EbinDir = filename:dirname(BeamFile),
733
791
AppDir = filename:dirname(EbinDir),
735
793
Url = "file://" ++ filename:absname(HelpFile),
736
794
wx_misc:launchDefaultBrowser(Url),
738
#wxCommand{type = command_menu_selected} when UserData =:= main_window, Id =:= ?ABOUT_ITEM ->
739
AboutStr = "Reltool is a release management tool. It analyses a given"
740
" Erlang/OTP installation and determines various dependencies"
741
" between applications. The graphical frontend depicts the"
742
" dependencies and enables interactive customization of a"
743
" target system. The backend provides a batch interface"
744
" for generation of customized target systems.",
745
MD = wxMessageDialog:new(S#state.frame,
796
#wxCommand{type = command_menu_selected}
797
when UserData =:= main_window, Id =:= ?ABOUT_ITEM ->
798
AboutStr = "Reltool is a release management tool. It analyses a "
799
" given Erlang/OTP installation and determines various "
800
" dependencies between applications. The graphical frontend "
801
" depicts the dependencies and enables interactive "
802
" customization of a target system. The backend provides a "
803
" batch interface for generation of customized target systems.",
804
MD = wxMessageDialog:new(S#state.frame,
747
[{style, ?wxOK bor ?wxICON_INFORMATION},
806
[{style, ?wxOK bor ?wxICON_INFORMATION},
748
807
{caption, "About Reltool"}]),
749
808
wxMessageDialog:showModal(MD),
750
809
wxMessageDialog:destroy(MD),
758
817
wxWindow:setFocus(ObjRef),
761
case wxNotebook:getPageText(S#state.book, wxNotebook:getSelection(S#state.book)) of
820
case wxNotebook:getPageText(S#state.book,
821
wxNotebook:getSelection(S#state.book)) of
762
822
?APP_PAGE -> handle_app_event(S, Event, ObjRef, UserData);
763
823
?LIB_PAGE -> handle_source_event(S, Event, ObjRef, UserData);
764
824
?SYS_PAGE -> handle_system_event(S, Event, ObjRef, UserData);
769
829
handle_popup_event(S, _Type, 0, _ObjRef, _UserData, _Str) ->
770
830
S#state{popup_menu = undefined};
771
handle_popup_event(#state{popup_menu = #root_popup{dir = OldDir, choices = Choices},
831
handle_popup_event(#state{popup_menu = #root_popup{dir = OldDir,
773
834
_Type, Pos, _ObjRef, _UserData, _Str) ->
774
835
case lists:nth(Pos, Choices) of
776
837
Style = ?wxFD_OPEN bor ?wxFD_FILE_MUST_EXIST,
777
case select_dir(S#state.frame, "Change root directory", OldDir, Style) of
838
case select_dir(S#state.frame,
839
"Change root directory",
778
842
{ok, NewDir} when NewDir =:= OldDir ->
779
843
%% Same dir.Ignore.
780
844
S#state{popup_menu = undefined};
802
867
LibDirs = Sys#sys.lib_dirs ++ [NewDir],
803
868
Sys2 = Sys#sys{lib_dirs = LibDirs},
804
do_set_sys(S#state{popup_menu = undefined, sys = Sys2})
869
do_set_sys(S#state{popup_menu = undefined,
807
873
S#state{popup_menu = undefined}
810
876
Style = ?wxFD_OPEN bor ?wxFD_FILE_MUST_EXIST,
811
case select_dir(S#state.frame, "Change library directory", OldDir, Style) of
877
case select_dir(S#state.frame,
878
"Change library directory",
813
882
case lists:member(NewDir, Sys#sys.lib_dirs) of
829
899
LibDirs = Sys#sys.lib_dirs -- [OldDir],
830
900
Sys2 = Sys#sys{lib_dirs = LibDirs},
831
do_set_sys(S#state{popup_menu = undefined, sys = Sys2})
901
do_set_sys(S#state{popup_menu = undefined, sys = Sys2})
833
handle_popup_event(#state{popup_menu = #escript_popup{file = OldFile, choices = Choices},
903
handle_popup_event(#state{popup_menu = #escript_popup{file = OldFile,
835
906
_Type, Pos, _ObjRef, _UserData, _Str) ->
836
907
case lists:nth(Pos, Choices) of
841
912
{ok, Cwd} = file:get_cwd(),
868
945
S#state{popup_menu = undefined};
870
947
Pred = fun(E) -> E =/= OldFile end,
871
{Before, [_| After]} = lists:splitwith(Pred, Sys#sys.escripts),
948
{Before, [_| After]} =
949
lists:splitwith(Pred, Sys#sys.escripts),
872
950
Escripts2 = Before ++ [NewFile | After],
873
951
Sys2 = Sys#sys{escripts = Escripts2},
874
do_set_sys(S#state{popup_menu = undefined, sys = Sys2})
952
do_set_sys(S#state{popup_menu = undefined,
877
956
S#state{popup_menu = undefined}
880
959
Escripts = Sys#sys.escripts -- [OldFile],
881
960
Sys2 = Sys#sys{escripts = Escripts},
882
do_set_sys(S#state{popup_menu = undefined, sys = Sys2})
961
do_set_sys(S#state{popup_menu = undefined, sys = Sys2})
885
964
handle_system_event(#state{sys = Sys} = S,
886
#wxCommand{type = command_radiobox_selected, cmdString = Choice},
965
#wxCommand{type = command_radiobox_selected,
888
968
config_mod_cond) ->
889
969
ModCond = reltool_utils:list_to_mod_cond(Choice),
890
970
Sys2 = Sys#sys{mod_cond = ModCond},
891
971
do_set_sys(S#state{sys = Sys2});
892
972
handle_system_event(#state{sys = Sys} = S,
893
#wxCommand{type = command_radiobox_selected, cmdString = Choice},
973
#wxCommand{type = command_radiobox_selected,
895
976
config_incl_cond) ->
896
977
AppCond = reltool_utils:list_to_incl_cond(Choice),
897
978
Sys2 = Sys#sys{incl_cond = AppCond},
898
979
do_set_sys(S#state{sys = Sys2});
899
980
handle_system_event(S, Event, ObjRef, UserData) ->
900
error_logger:format("~p~p got unexpected wx sys event to ~p with user data: ~p\n\t ~p\n",
981
error_logger:format("~p~p got unexpected wx sys event to ~p "
982
"with user data: ~p\n\t ~p\n",
901
983
[?MODULE, self(), ObjRef, UserData, Event]),
905
987
io:format("Release data: ~p\n", [UserData]),
908
handle_source_event(S, #wxTree{type = command_tree_item_activated, item = Item}, ObjRef, _UserData) ->
990
handle_source_event(S,
991
#wxTree{type = command_tree_item_activated,
909
995
case wxTreeCtrl:getItemData(ObjRef, Item) of
910
996
#root_data{dir = _Dir} ->
911
997
%% io:format("Root dialog: ~p\n", [Dir]),
939
handle_app_event(S, #wxList{type = command_list_item_activated, itemIndex = Pos}, ListCtrl, _UserData) ->
1030
#wxList{type = command_list_item_activated,
940
1034
AppName = wxListCtrl:getItemText(ListCtrl, Pos),
941
1035
do_open_app(S, AppName);
942
handle_app_event(S, #wxCommand{type = command_button_clicked}, _ObjRef, {app_button, Action, ListCtrl}) ->
1037
#wxCommand{type = command_button_clicked},
1039
{app_button, Action, ListCtrl}) ->
943
1040
Items = reltool_utils:get_items(ListCtrl),
944
1041
handle_app_button(S, Items, Action);
945
1042
handle_app_event(S, Event, ObjRef, UserData) ->
946
error_logger:format("~p~p got unexpected wx app event to ~p with user data: ~p\n\t ~p\n",
1043
error_logger:format("~p~p got unexpected wx app event to "
1044
"~p with user data: ~p\n\t ~p\n",
947
1045
[?MODULE, self(), ObjRef, UserData, Event]),
950
handle_app_button(#state{server_pid = ServerPid, app_wins = AppWins} = S, Items, Action) ->
1048
handle_app_button(#state{server_pid = ServerPid, app_wins = AppWins} = S,
951
1051
NewApps = [move_app(S, Item, Action) || Item <- Items],
952
1052
case reltool_server:set_apps(ServerPid, NewApps) of
967
1067
check_and_refresh(S, Status).
969
1069
move_app(S, {_ItemNo, AppBase}, Action) ->
970
{AppName, _Vsn} = reltool_utils:split_app_name(AppBase),
1070
{AppName, _Vsn} = reltool_utils:split_app_name(AppBase),
971
1071
{ok, OldApp} = reltool_server:get_app(S#state.server_pid, AppName),
974
1074
whitelist_add ->
975
1075
case OldApp#app.incl_cond of
1047
1148
ImageApps = lists:map(AddImage, Apps),
1049
1150
fun({ImageId, Text, App}, {Row, ModCount, Items}) ->
1050
wxListCtrl:insertItem(ListCtrl, Row, ""),
1051
if (Row rem 2) =:= 0 ->
1052
wxListCtrl:setItemBackgroundColour(ListCtrl, Row, {240,240,255});
1151
wxListCtrl:insertItem(ListCtrl, Row, ""),
1152
if (Row rem 2) =:= 0 ->
1153
wxListCtrl:setItemBackgroundColour(ListCtrl,
1056
wxListCtrl:setItem(ListCtrl, Row, ?APPS_APP_COL, Text, [{imageId, ImageId}]),
1057
N = length([M || M <- App#app.mods, M#mod.is_included =:= true]),
1159
wxListCtrl:setItem(ListCtrl,
1163
[{imageId, ImageId}]),
1164
N = length([M || M <- App#app.mods,
1165
M#mod.is_included =:= true]),
1058
1166
{Row + 1, ModCount + N, [{Row, Text} | Items]}
1060
1168
{_, N, NewItems} = wx:foldl(Show, {0, 0, []}, lists:sort(ImageApps)),
1068
1176
WhiteNames = [A#app.name || A <- WhiteApps],
1069
1177
DerivedNames = [A#app.name || A <- DerivedApps],
1070
1178
Nodes = WhiteNames ++ DerivedNames,
1071
%% WhiteUses = [N || A <- WhiteApps, N <- A#app.uses_apps, lists:member(N, Nodes)],
1072
%% DerivedUses = [N || A <- DerivedApps, N <- A#app.uses_apps, lists:member(N, Nodes)],
1179
%% WhiteUses = [N || A <- WhiteApps,
1180
%% N <- A#app.uses_apps, lists:member(N, Nodes)],
1181
%% DerivedUses = [N || A <- DerivedApps,
1182
%% N <- A#app.uses_apps, lists:member(N, Nodes)],
1074
1184
WhiteLinks = [[A#app.name, U] || A <- WhiteApps,
1075
1185
U <- A#app.uses_apps,
1087
1197
update_mod_graph(S) ->
1088
1198
{ok, WhiteApps} = reltool_server:get_apps(S#state.server_pid, whitelist),
1089
1199
{ok, DerivedApps} = reltool_server:get_apps(S#state.server_pid, derived),
1090
WhiteMods = lists:usort([M || A <- WhiteApps, M <- A#app.mods, M#mod.is_included =:= true]),
1091
DerivedMods = lists:usort([M || A <- DerivedApps, M <- A#app.mods, M#mod.is_included =:= true]),
1200
WhiteMods = lists:usort([M || A <- WhiteApps,
1202
M#mod.is_included =:= true]),
1203
DerivedMods = lists:usort([M || A <- DerivedApps,
1205
M#mod.is_included =:= true]),
1093
1207
WhiteNames = [M#mod.name || M <- WhiteMods],
1094
1208
DerivedNames = [M#mod.name || M <- DerivedMods],
1113
1227
Panel = wxPanel:new(Frame, []),
1114
1228
Options = [{size, {lists:max([100, ?WIN_WIDTH - 100]), ?WIN_HEIGHT}}],
1115
1229
{Server, Fgraph} = reltool_fgraph_win:new(Panel, Options),
1116
Choose = fun(?MISSING_APP) -> alternate;
1230
Choose = fun(?MISSING_APP_NAME) -> alternate;
1119
1233
[reltool_fgraph_win:add_node(Server, N, Choose(N)) || N <- Nodes],
1142
1256
load_config(#state{status_bar = Bar, config_file = OldFile} = S) ->
1143
1257
Style = ?wxFD_OPEN bor ?wxFD_FILE_MUST_EXIST,
1144
case select_file(S#state.frame, "Select a file to load the configuration from", OldFile, Style) of
1258
case select_file(S#state.frame,
1259
"Select a file to load the configuration from",
1145
1262
{ok, NewFile} ->
1146
1263
wxStatusBar:setStatusText(Bar, "Processing libraries..."),
1147
1264
Status = reltool_server:load_config(S#state.server_pid, NewFile),
1153
1270
save_config(#state{config_file = OldFile} = S, InclDefaults, InclDerivates) ->
1154
Style = ?wxFD_SAVE bor ?wxFD_OVERWRITE_PROMPT,
1155
case select_file(S#state.frame, "Select a file to save the configuration to", OldFile, Style) of
1271
Style = ?wxFD_SAVE bor ?wxFD_OVERWRITE_PROMPT,
1272
case select_file(S#state.frame,
1273
"Select a file to save the configuration to",
1156
1276
{ok, NewFile} ->
1157
Status = reltool_server:save_config(S#state.server_pid, NewFile, InclDefaults, InclDerivates),
1277
Status = reltool_server:save_config(S#state.server_pid,
1158
1281
check_and_refresh(S#state{config_file = NewFile}, Status);
1163
1286
gen_rel_files(#state{target_dir = OldDir} = S) ->
1164
Style = ?wxFD_SAVE bor ?wxFD_OVERWRITE_PROMPT,
1165
case select_dir(S#state.frame, "Select a directory to generate rel, script and boot files to", OldDir, Style) of
1287
Style = ?wxFD_SAVE bor ?wxFD_OVERWRITE_PROMPT,
1288
case select_dir(S#state.frame,
1289
"Select a directory to generate rel, script and boot files to",
1166
1292
{ok, NewDir} ->
1167
1293
Status = reltool_server:gen_rel_files(S#state.server_pid, NewDir),
1168
1294
check_and_refresh(S, Status);
1173
1299
gen_target(#state{target_dir = OldDir} = S) ->
1174
Style = ?wxFD_SAVE bor ?wxFD_OVERWRITE_PROMPT,
1175
case select_dir(S#state.frame, "Select a directory to generate a target system to", OldDir, Style) of
1300
Style = ?wxFD_SAVE bor ?wxFD_OVERWRITE_PROMPT,
1301
case select_dir(S#state.frame,
1302
"Select a directory to generate a target system to",
1176
1305
{ok, NewDir} ->
1177
1306
Status = reltool_server:gen_target(S#state.server_pid, NewDir),
1178
1307
check_and_refresh(S#state{target_dir = NewDir}, Status);
1229
1358
S2 = S#state{sys = Sys},
1230
1359
S3 = redraw_libs(S2),
1231
1360
redraw_apps(S3).
1233
1362
question_dialog(Question, Details) ->
1234
1363
%% Parent = S#state.frame,
1235
1364
Parent = wx:typeCast(wx:null(), wxWindow),
1236
1365
%% [{style, ?wxYES_NO bor ?wxICON_ERROR bor ?wx}]),
1237
1366
DialogStyle = ?wxRESIZE_BORDER bor ?wxCAPTION bor ?wxSYSTEM_MENU bor
1238
1367
?wxMINIMIZE_BOX bor ?wxMAXIMIZE_BOX bor ?wxCLOSE_BOX,
1239
Dialog = wxDialog:new(Parent, ?wxID_ANY, "Undo dialog", [{style, DialogStyle}]),
1368
Dialog = wxDialog:new(Parent, ?wxID_ANY, "Undo dialog",
1369
[{style, DialogStyle}]),
1240
1370
Color = wxWindow:getBackgroundColour(Dialog),
1241
1371
TextStyle = ?wxTE_READONLY bor ?wxTE_MULTILINE bor ?wxHSCROLL,
1242
Text1 = wxTextCtrl:new(Dialog, ?wxID_ANY, [{style, ?wxTE_READONLY bor ?wxBORDER_NONE}]),
1372
Text1 = wxTextCtrl:new(Dialog, ?wxID_ANY,
1373
[{style, ?wxTE_READONLY bor ?wxBORDER_NONE}]),
1243
1374
wxWindow:setBackgroundColour(Text1, Color),
1244
1375
wxTextCtrl:appendText(Text1, Question),
1245
Text2 = wxTextCtrl:new(Dialog, ?wxID_ANY, [{size, {600, 400}}, {style, TextStyle}]),
1376
Text2 = wxTextCtrl:new(Dialog, ?wxID_ANY,
1377
[{size, {600, 400}}, {style, TextStyle}]),
1246
1378
wxWindow:setBackgroundColour(Text2, Color),
1247
1379
wxTextCtrl:appendText(Text2, Details),
1248
1380
%% wxDialog:setAffirmativeId(Dialog, ?wxID_YES),
1249
1381
%% wxDialog:setEscapeId(Dialog, ?wxID_NO),
1250
1382
Sizer = wxBoxSizer:new(?wxVERTICAL),
1251
1383
wxSizer:add(Sizer, Text1, [{border, 2}, {flag, ?wxEXPAND}]),
1252
wxSizer:add(Sizer, Text2, [{border, 2}, {flag, ?wxEXPAND}, {proportion, 1}]),
1253
ButtSizer = wxDialog:createStdDialogButtonSizer(Dialog, ?wxOK bor ?wxCANCEL),
1384
wxSizer:add(Sizer, Text2, [{border, 2},
1387
ButtSizer = wxDialog:createStdDialogButtonSizer(Dialog,
1388
?wxOK bor ?wxCANCEL),
1254
1389
wxSizer:add(Sizer, ButtSizer, [{border, 2}, {flag, ?wxEXPAND}]),
1255
1390
wxPanel:setSizer(Dialog, Sizer),
1256
1391
wxSizer:fit(Sizer, Dialog),