aboutsummaryrefslogtreecommitdiffstats
path: root/lib/tv/src/tv_pc_menu_handling.erl
diff options
context:
space:
mode:
authorErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
committerErlang/OTP <[email protected]>2009-11-20 14:54:40 +0000
commit84adefa331c4159d432d22840663c38f155cd4c1 (patch)
treebff9a9c66adda4df2106dfd0e5c053ab182a12bd /lib/tv/src/tv_pc_menu_handling.erl
downloadotp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz
otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2
otp-84adefa331c4159d432d22840663c38f155cd4c1.zip
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/tv/src/tv_pc_menu_handling.erl')
-rw-r--r--lib/tv/src/tv_pc_menu_handling.erl485
1 files changed, 485 insertions, 0 deletions
diff --git a/lib/tv/src/tv_pc_menu_handling.erl b/lib/tv/src/tv_pc_menu_handling.erl
new file mode 100644
index 0000000000..16195bf91f
--- /dev/null
+++ b/lib/tv/src/tv_pc_menu_handling.erl
@@ -0,0 +1,485 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1997-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%
+%%%*********************************************************************
+%%%
+%%% Description: Part of pc handling the creation of menus, as well as
+%%% treating the signals these menus results in,
+%%% when chosen.
+%%%
+%%%*********************************************************************
+
+
+-module(tv_pc_menu_handling).
+
+
+
+-export([create_menus/1,
+ exit_button/1,
+ insert_object/1,
+ delete_object/1,
+ search_object/1,
+ open_table/7,
+ set_poll_interval/1,
+ poll_table/1,
+ sort_rising_order/1,
+ sort_falling_order/1,
+ no_sorting/1,
+ lists_as_strings/1,
+ lists_as_lists/1,
+ table_info/1,
+ help_button/1,
+ otp_help_button/1,
+ get_window_title/4]).
+
+
+
+
+
+-include("tv_int_def.hrl").
+-include("tv_int_msg.hrl").
+-include("tv_pc_int_def.hrl").
+
+
+
+
+
+
+
+
+%%%*********************************************************************
+%%% EXTERNAL FUNCTIONS
+%%%*********************************************************************
+
+
+%% Shortcuts currently used, in alphabetical order:
+%%
+%% c -> "Exit"
+%% d -> "Delete Object"
+%% f -> "Sort Falling Order"
+%% h -> "Help"
+%% i -> "Table Info"
+%% n -> "No Sorting"
+%% o -> "Edit Object"
+%% p -> "Poll Table"
+%% r -> "Sort Rising Order"
+%% s -> "Search Object"
+%% v -> "Set Poll Interval"
+%% x -> "Exit"
+
+
+create_menus(PwPid) ->
+ %% Due to a bug (or some other reason), only one of the radiobuttons belonging
+ %% to a specified group can be selected, even if different processes have created
+ %% the radiobuttons! This means that, if we have started more than one tv_main
+ %% process, selecting one radiobutton will affect the radiobuttons in the other
+ %% tv_main process(es)!!! Since this is a highly undesirable bahaviour, we have to
+ %% create unique group names (i.e., atoms).
+ %% (We need to group the radiobuttons, since otherwise all created by one process
+ %% belongs to the same group, which also is undesirable...)
+ SelfStr = pid_to_list(self()),
+ SortGroup = list_to_atom("sorting" ++ SelfStr),
+ ListGroup = list_to_atom("lists" ++ SelfStr),
+
+ % Order pw to create the 'File' menu.
+ ?GRAPH_FUNC_FILE:create_menu(PwPid,
+ " File ",
+ 1,
+ [{" Table Info ", normal, table_info, 7, i},
+ separator,
+ {" Close ", normal, exit_button, 1, c}
+ ]),
+ ?GRAPH_FUNC_FILE:create_menu(PwPid,
+ " Edit ",
+ 1,
+ [{" Edit Object... ", normal, insert_object, 1, o},
+ {" Delete Object ", normal, delete_object, 1, d}
+ ]),
+ ?GRAPH_FUNC_FILE:create_menu(PwPid,
+ " View ",
+ 1,
+ [{" Lists as Lists ",{radio,false,ListGroup},lists_as_lists,10,no_char},
+ {" Lists as Strings ",{radio,true,ListGroup},lists_as_strings,10,no_char}
+ ]),
+ % Order pw to create the 'Options' menu.
+ ?GRAPH_FUNC_FILE:create_menu(PwPid,
+ " Options ",
+ 1,
+ [{" Poll Table ", normal, poll_table, 1, p},
+ {" Poll Interval... ",normal,set_poll_interval,6,no_char},
+ separator,
+ {" Search Object ", normal, search_object, 1, s},
+ separator,
+ {" Sort Ascending Order ",{radio,false,SortGroup},sort_rising_order,6,no_char},
+ {" Sort Descending Order ",{radio,false,SortGroup},sort_falling_order,6,no_char},
+ {" No Sorting ",{radio,true,SortGroup},no_sorting,1,no_char}
+ ]).
+
+
+
+
+
+exit_button(_ProcVars) ->
+ exit(normal).
+
+
+
+help_button(ProcVars) ->
+ WinP = ProcVars#process_variables.window_params,
+ HelpFile = filename:join([code:lib_dir(tv), "doc", "html", "index.html"]),
+ tool_utils:open_help(WinP#window_params.window_id, HelpFile),
+ ProcVars.
+
+
+
+
+otp_help_button(ProcVars) ->
+ WinP = ProcVars#process_variables.window_params,
+ IndexFile = filename:join([code:root_dir(), "doc", "index.html"]),
+
+ tool_utils:open_help(WinP#window_params.window_id, IndexFile),
+ ProcVars.
+
+
+
+
+table_info(ProcVars) ->
+ #process_variables{table_id = TableId,
+ current_node = Node,
+ local_node = LocalNode,
+ table_type = Type,
+ parent_pid = ParentPid} = ProcVars,
+
+ case TableId of
+ undefined ->
+ done;
+ _OtherValue ->
+ ParentPid ! {tv_start_infowin, TableId, Node, LocalNode, Type}
+ end,
+ ProcVars.
+
+
+
+sort_rising_order(ProcVars) ->
+ request_sort_settings(ProcVars#process_variables.pd_pid, true, false),
+ ProcVars.
+
+
+sort_falling_order(ProcVars) ->
+ request_sort_settings(ProcVars#process_variables.pd_pid, true, true),
+ ProcVars.
+
+
+no_sorting(ProcVars) ->
+ request_sort_settings(ProcVars#process_variables.pd_pid, false, false),
+ ProcVars.
+
+
+set_poll_interval(ProcVars) ->
+ #process_variables{etsread_pid = EtsreadPid,
+ poll_interval = PollInterval} = ProcVars,
+
+ case tv_poll_dialog:start(PollInterval) of
+ cancel ->
+ ProcVars;
+ NewPollInterval ->
+ EtsreadPid ! #etsread_set_poll_interval{sender = self(),
+ interval = NewPollInterval},
+ ProcVars#process_variables{poll_interval = NewPollInterval}
+ end.
+
+
+
+poll_table(ProcVars) ->
+ EtsreadPid = ProcVars#process_variables.etsread_pid,
+ EtsreadPid ! #etsread_poll_table{sender = self()},
+ ProcVars.
+
+
+search_object(ProcVars) ->
+ DbsPid = ProcVars#process_variables.dbs_pid,
+ DbsPid ! #dbs_search_req{sender=self()},
+ ProcVars.
+
+
+
+lists_as_strings(ProcVars) ->
+ PdPid = ProcVars#process_variables.pd_pid,
+ PdPid ! #pc_list_info{sender=self(), lists_as_strings=true},
+ DbsPid = ProcVars#process_variables.dbs_pid,
+ DbsPid ! #pc_list_info{sender=self(), lists_as_strings=true},
+ ProcVars#process_variables{lists_as_strings=true}.
+
+
+
+
+lists_as_lists(ProcVars) ->
+ PdPid = ProcVars#process_variables.pd_pid,
+ PdPid ! #pc_list_info{sender=self(), lists_as_strings=false},
+ DbsPid = ProcVars#process_variables.dbs_pid,
+ DbsPid ! #pc_list_info{sender=self(), lists_as_strings=false},
+ ProcVars#process_variables{lists_as_strings=false}.
+
+
+
+
+
+
+insert_object(ProcVars) ->
+ #process_variables{pd_pid = PdPid,
+ current_node = Node,
+ local_node = LocalNode,
+ table_type = TabType,
+ table_name = TabName,
+ table_protection = Protection,
+ window_params = WinP} = ProcVars,
+
+ case Protection of
+ public ->
+ case TabType of
+ mnesia ->
+ case catch tv_mnesia_rpc:table_info(Node, LocalNode, TabName, attributes) of
+ nodedown ->
+ handle_error(nodedown);
+ no_table ->
+ handle_error(nodedown);
+ mnesia_not_started ->
+ handle_error(mnesia_not_started);
+ {unexpected_error,Reason} ->
+ handle_error({unexpected_error,Reason});
+ AttrList ->
+ PdPid ! #pd_rec_edit{sender = self(),
+ attributes = AttrList
+ }
+ end;
+ ets ->
+ PdPid ! #pd_rec_edit{sender = self(),
+ attributes = [tuple]
+ }
+ end;
+ _OtherProtection ->
+ WinId = WinP#window_params.window_id,
+ gs:config(WinId, [beep]),
+ ErrMsg =
+ case get(error_msg_mode) of
+ normal ->
+ ["The table is protected and",
+ " cannot be edited."];
+ haiku ->
+ ["The table you see",
+ "Is cunningly protected:",
+ "You can only watch."]
+ end,
+ tv_utils:notify(WinId, "TV Notification", ErrMsg)
+ end,
+ ProcVars.
+
+
+
+
+
+
+delete_object(ProcVars) ->
+ #process_variables{dbs_pid = DbsPid,
+ table_protection = Protection,
+ marked_row = MarkedRow,
+ marked_object = MarkedObject,
+ marked_color = MarkedColor,
+ window_params = WinP} = ProcVars,
+
+ case MarkedRow of
+ undefined ->
+ done;
+ _AnyRow ->
+ case Protection of
+ public ->
+ DbsPid ! #dbs_delete_object{sender = self(),
+ object = MarkedObject,
+ color = MarkedColor,
+ obj_no = MarkedRow};
+ _OtherProtection ->
+ WinId = WinP#window_params.window_id,
+ gs:config(WinId, [beep]),
+ ErrMsg =
+ case get(error_msg_mode) of
+ normal ->
+ ["The table is protected and",
+ " cannot be edited."];
+ haiku ->
+ ["The table you see",
+ "Is cunningly protected:",
+ "You can only watch."]
+ end,
+ tv_utils:notify(WinId, "TV Notification", ErrMsg)
+ end
+ end,
+ ProcVars.
+
+
+
+
+
+
+open_table(CurrNode, LocalNode, TableId, TableType, TableName, Raise, ProcVars) ->
+ #process_variables{dbs_pid = DbsPid,
+ etsread_pid = EtsreadPid,
+ pw_pid = PwPid,
+ pd_pid = PdPid,
+ poll_interval = PollInterval,
+ window_params = WinP} = ProcVars,
+
+ case Raise of
+ true ->
+ gs:config(WinP#window_params.window_id, [raise]);
+ false ->
+ done
+ end,
+
+ {Type, KeyPos, Protection} = init_etsread(EtsreadPid, DbsPid, CurrNode, LocalNode, TableId,
+ TableType, PollInterval),
+ WinTitle = get_window_title(TableType, CurrNode, TableId, TableName),
+ PwPid ! #pw_set_window_title{sender = self(),
+ win_title = WinTitle},
+ Writable =
+ case Protection of
+ public ->
+ true;
+ _Other ->
+ false
+ end,
+ RecordName =
+ case TableType of
+ mnesia ->
+ tv_mnesia_rpc:table_info(CurrNode, LocalNode, TableId, record_name);
+ ets ->
+ undefined
+ end,
+ PdPid ! #pd_new_table{sender = self(),
+ table_type = TableType,
+ table_name = TableName,
+ record_name = RecordName,
+ writable = Writable},
+ init_dbs(DbsPid, Type, KeyPos, EtsreadPid),
+ ProcVars#process_variables{current_node = CurrNode,
+ local_node = LocalNode,
+ table_id = TableId,
+ table_type = TableType,
+ table_name = TableName,
+ table_protection = Protection}.
+
+
+
+
+
+
+get_window_title(ets, Node, TableId, TableName) ->
+ NameStr = lists:flatten(io_lib:write(TableName)),
+ TableStr = case TableId of
+ {TableName, _Pid} ->
+ NameStr;
+ TableName ->
+ NameStr;
+ _Other ->
+ lists:flatten(io_lib:write(TableId)) ++ " (" ++ NameStr ++ ")"
+ end,
+
+ WinTitleSuffix = " Node: " ++ atom_to_list(Node),
+ "ETS: " ++ TableStr ++ WinTitleSuffix;
+get_window_title(mnesia, Node, _TableId, TableName) ->
+ TableNameStr = lists:flatten(io_lib:write(TableName)),
+ WinTitleSuffix = " Node: " ++ atom_to_list(Node),
+ "Mnesia: " ++ TableNameStr ++ WinTitleSuffix.
+
+
+
+
+%%%*********************************************************************
+%%% INTERNAL FUNCTIONS
+%%%*********************************************************************
+
+
+
+init_etsread(EtsreadPid, DbsPid, Node, LocalNode, TableId, TableType, PollInterval) ->
+ EtsreadPid ! #etsread_deblock{sender = self(),
+ dbs_pid = DbsPid,
+ node = Node,
+ local_node = LocalNode,
+ table_id = TableId,
+ table_type = TableType,
+ poll_interval = PollInterval
+ },
+ receive
+ #etsread_deblock_cfm{type=Type, keypos=KeyPos, protection=Protection} ->
+ {Type, KeyPos, Protection}
+ after 10000 ->
+ exit(error)
+ end.
+
+
+
+
+init_dbs(DbsPid, Type, KeyPos, EtsreadPid) ->
+ DbsPid ! #dbs_deblock{sender = self(),
+ etsread_pid = EtsreadPid,
+ type = Type,
+ keypos = KeyPos,
+ sublist_length = ?ITEMS_TO_DISPLAY
+ },
+ receive
+ #dbs_deblock_cfm{} ->
+ done
+ after 10000 ->
+ exit(error)
+ end.
+
+
+
+
+
+
+request_sort_settings(PdPid, Sorting, Reverse) ->
+ PdPid ! #pd_get_sort_settings{sender = self(),
+ sorting = Sorting,
+ reverse = Reverse
+ }.
+
+
+
+
+
+
+handle_error(mnesia_not_started) ->
+ gs:window(errorwin, gs:start(), []),
+ gs:config(errorwin, [beep]),
+ case get(error_msg_mode) of
+ normal ->
+ tv_utils:notify(errorwin, "TV Notification", ["Mnesia not started!"]);
+ haiku ->
+ tv_utils:notify(errorwin, "TV Notification", ["Mnesia is stopped.",
+ "We wish to reach all data",
+ "But we never will."])
+ end,
+ gs:destroy(errorwin);
+handle_error(nodedown) ->
+ done; %% Main process handles this!
+handle_error({unexpected_error,Cause}) ->
+ gs:window(errorwin, gs:start(), []),
+ io:format("Unexpected error: ~p~n", [Cause]),
+ gs:config(errorwin, [beep]),
+ gs:destroy(errorwin).
+
+