%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 1998-2012. 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%k
-module(tv_new_table).
-compile([{nowarn_deprecated_function,{gs,button,3}},
{nowarn_deprecated_function,{gs,checkbutton,3}},
{nowarn_deprecated_function,{gs,config,2}},
{nowarn_deprecated_function,{gs,entry,3}},
{nowarn_deprecated_function,{gs,frame,3}},
{nowarn_deprecated_function,{gs,label,2}},
{nowarn_deprecated_function,{gs,radiobutton,3}},
{nowarn_deprecated_function,{gs,read,2}},
{nowarn_deprecated_function,{gs,start,0}},
{nowarn_deprecated_function,{gs,window,3}}]).
-export([start/2,
init/3
]).
-define(DEFAULT_BG_COLOR, {217, 217, 217}).
-define(FONT, {screen, 12}).
-define(WIN_WIDTH, 400).
-define(WIN_HEIGHT, 555). %% 510
-define(FRAME_WIDTH, 400).
-define(FRAME1_HEIGHT, 170).
-define(FRAME2_HEIGHT, 260).
-define(FRAME3_HEIGHT, 125). %% 80
-define(BW, 2).
-define(FRAME_X, 0).
-define(FRAME1_Y, 0).
-define(FRAME2_Y, 170).
-define(FRAME3_Y, 430).
-define(LBL_HEIGHT, 30).
-define(NODE_LBL_WIDTH, 45).
-define(NAME_LBL_WIDTH, 85).
-define(TYPE_LBL_WIDTH, 45).
-define(PROT_LBL_WIDTH, 85).
-define(KEYPOS_LBL_WIDTH, 95).
-define(LBL_X, 10).
-define(NODE_LBL_Y, 20).
-define(NAME_LBL_Y, 80).
-define(TYPE_LBL_Y, 10).
-define(PROT_LBL_Y, 100).
-define(KEYPOS_LBL_Y, 200).
-define(ENTRY_HEIGHT, 30).
-define(NODE_ENTRY_WIDTH, 275).
-define(NAME_ENTRY_WIDTH, 275).
-define(KEYPOS_ENTRY_WIDTH, 50).
-define(ENTRY_X1, 110).
-define(ENTRY_X2, 110).
-define(NODE_ENTRY_Y, 20).
-define(NAME_ENTRY_Y, 80).
-define(KEYPOS_ENTRY_Y, 200).
-define(RBTN_HEIGHT, 30).
-define(RBTN_WIDTH1, 105).
-define(RBTN_WIDTH2, 115).
-define(RBTN_X1, 60).
-define(RBTN_X2, 165).
-define(RBTN_X3, 270).
-define(RBTN_Y1, 40).
-define(RBTN_Y1PLUS, 70).
-define(RBTN_Y2, 130).
-define(CBTN_HEIGHT, 30).
-define(NAMED_TABLE_CBTN_WIDTH, 100).
-define(OPEN_BROWSER_CBTN_WIDTH, 105).
-define(NAMED_TABLE_CBTN_X, 110).
-define(NAMED_TABLE_CBTN_Y, 120).
-define(OPEN_BROWSER_CBTN_X, 85). %% 215
-define(OPEN_BROWSER_CBTN_Y, 10). %% 200
-define(BTN_WIDTH, 100).
-define(BTN_HEIGHT, 30).
-define(BTN_X1, 85).
-define(BTN_X2, 225).
-define(BTN_Y, 65). %% 30
-define(VLINE_LBL_WIDTH, (380 - 2 * ?BW)).
-define(VLINE_LBL_HEIGHT, 1).
-define(HLINE_LBL_WIDTH, 1).
-define(HLINE_LBL_HEIGHT, 70).
-define(VLINE_LBL_X, (10 - ?BW)).
-define(VLINE_LBL_Y1, 85).
-define(VLINE_LBL_Y2, 180).
-define(HLINE_LBL_X, 188).
-define(HLINE_LBL_Y, 180).
-define(DEFAULT_NAME, my_table).
-define(DEFAULT_TYPE, set).
-define(DEFAULT_PROT, public).
-define(DEFAULT_KEYPOS, 1).
start(Node, ErrMsgMode) ->
spawn_link(?MODULE, init, [Node, ErrMsgMode, self()]).
init(Node, ErrMsgMode, MPid) ->
process_flag(trap_exit, true),
put(error_msg_mode, ErrMsgMode),
create_window(Node),
loop(false, ?DEFAULT_TYPE, ?DEFAULT_PROT, true, MPid).
loop(NamedTab, Type, Prot, OpenBrowser, MPid) ->
receive
{gs, ok, click, _Data, _Args} ->
gs:config(win, [{cursor, busy}]),
case create_table(NamedTab, Type, Prot, OpenBrowser, MPid) of
ok ->
exit(normal);
error ->
gs:config(win, [{cursor, arrow}]),
loop(NamedTab, Type, Prot, OpenBrowser, MPid)
end;
{gs, cancel, click, _Data, _Args} ->
exit(normal);
{gs, set, click, _Data, _Args} ->
loop(NamedTab, set, Prot, OpenBrowser, MPid);
{gs, ordered_set, click, _Data, _Args} ->
loop(NamedTab, ordered_set, Prot, OpenBrowser, MPid);
{gs, bag, click, _Data, _Args} ->
loop(NamedTab, bag, Prot, OpenBrowser, MPid);
{gs, duplicate_bag, click, _Data, _Args} ->
loop(NamedTab, duplicate_bag, Prot, OpenBrowser, MPid);
{gs, public, click, _Data, _Args} ->
gs:config(open_browser, [{enable, true}, {select, OpenBrowser}]),
loop(NamedTab, Type, public, OpenBrowser, MPid);
{gs, protected, click, _Data, _Args} ->
gs:config(open_browser, [{enable, true}, {select, OpenBrowser}]),
loop(NamedTab, Type, protected, OpenBrowser, MPid);
{gs, private, click, _Data, _Args} ->
gs:config(open_browser, [{select, false}, {enable, false}]),
loop(NamedTab, Type, private, OpenBrowser, MPid);
{gs, named_table, click, Data, _Args} ->
gs:config(named_table, [{data, not(Data)}]),
loop(Data, Type, Prot, OpenBrowser, MPid);
{gs, open_browser, click, Data, _Args} ->
gs:config(open_browser, [{data, not(Data)}]),
loop(Data, Type, Prot, Data, MPid);
{gs, EntryId, keypress, _Data, ['Tab', _No, 0 | _T]} ->
case get_entry_term(EntryId) of
{ok, _Term} ->
gs:config(next_entry(EntryId, forward), [{setfocus, true},
{select, {0, 100000000}}]);
error ->
done
end,
loop(NamedTab, Type, Prot, OpenBrowser, MPid);
{gs, EntryId, keypress, _Data, ['Tab', _No, 1 | _T]} ->
case get_entry_term(EntryId) of
{ok, _Term} ->
gs:config(next_entry(EntryId, backward), [{setfocus, true},
{select, {0, 100000000}}]);
error ->
done
end,
loop(NamedTab, Type, Prot, OpenBrowser, MPid);
{gs, EntryId, keypress, _Data, ['Down' | _T]} ->
case get_entry_term(EntryId) of
{ok, _Term} ->
gs:config(next_entry(EntryId, forward), [{setfocus, true},
{select, {0, 100000000}}]);
error ->
done
end,
loop(NamedTab, Type, Prot, OpenBrowser, MPid);
{gs, EntryId, keypress, _Data, ['Up' | _T]} ->
case get_entry_term(EntryId) of
{ok, _Term} ->
gs:config(next_entry(EntryId, backward), [{setfocus, true},
{select, {0, 100000000}}]);
error ->
done
end,
loop(NamedTab, Type, Prot, OpenBrowser, MPid);
{gs, _EntryId, keypress, _Data, ['Return' | _T]} ->
gs:config(win, [{cursor, busy}]),
case create_table(NamedTab, Type, Prot, OpenBrowser, MPid) of
ok ->
exit(normal);
error ->
gs:config(win, [{cursor, arrow}]),
loop(NamedTab, Type, Prot, OpenBrowser, MPid)
end;
{gs, win, configure, _Data, _Args} ->
gs:config(win, [{width, ?WIN_WIDTH},
{height, ?WIN_HEIGHT}]),
loop(NamedTab, Type, Prot, OpenBrowser, MPid);
{gs, win, destroy, _Data, _Args} ->
exit(normal);
raise ->
gs:config(win, [raise]),
loop(NamedTab, Type, Prot, OpenBrowser, MPid);
{error_msg_mode, ErrMsgMode} ->
put(error_msg_mode, ErrMsgMode),
loop(NamedTab, Type, Prot, OpenBrowser, MPid);
{'EXIT', _Pid, _Reason} ->
exit(normal);
_Other ->
loop(NamedTab, Type, Prot, OpenBrowser, MPid)
end.
create_table(NamedTab, Type, Prot, OpenBrowser, MPid) ->
case get_entry_term(node_entry) of
error ->
error;
{ok, Node} ->
case get_entry_term(name_entry) of
error ->
error;
{ok, TabName} ->
case get_entry_term(keypos_entry) of
error ->
error;
{ok, KeyPos} ->
Options =
[Type, Prot, {keypos, KeyPos}] ++
case NamedTab of
true ->
[named_table];
false ->
[]
end,
{Readable, NewOpenBrowser} =
case Prot of
private ->
{false, false};
_Other ->
{true, OpenBrowser}
end,
MPid ! {tv_new_table, self(), Node, TabName, Options, ets,
Readable, NewOpenBrowser},
receive
ok ->
ok;
error ->
show_error_msg(),
error
after
5000 ->
show_error_msg(),
error
end
end
end
end.
show_error_msg() ->
Msg =
case get(error_msg_mode) of
normal ->
["Couldn't create a table using",
"the specified settings!"];
haiku ->
["The table you want",
"Could maybe be created.",
"But I don't know how."]
end,
tv_utils:notify(win, "TV Notification", Msg).
get_entry_term(Id) ->
EditedStr = gs:read(Id, text),
case tv_db_search:string_to_term(EditedStr) of
{ok, NewTerm} when Id =:= node_entry, is_atom(NewTerm) ->
{ok,NewTerm};
{ok, NewTerm} when Id =:= name_entry, is_atom(NewTerm) ->
{ok,NewTerm};
{ok, NewTerm} when Id =:= keypos_entry, is_integer(NewTerm), NewTerm > 0 ->
{ok,NewTerm};
_Other ->
NewMsg =
case get(error_msg_mode) of
normal ->
case Id of
node_entry ->
["Please enter a valid node name!"];
name_entry ->
["Please enter a valid table name!"];
keypos_entry ->
["Please enter a valid key position!"]
end;
haiku ->
E1 = "Aborted effort",
L =
case Id of
node_entry ->
["Reflect, repent and retype:",
"Enter valid node."];
name_entry ->
["Reflect, repent and retype:",
"Enter valid name."];
keypos_entry ->
["Reflect, repent and retype",
"Key position, please."]
end,
[E1 | L]
end,
gs:config(Id, [beep, {select, {0, 100000000}}, {setfocus, true}]),
tv_utils:notify(win, "TV Notification", NewMsg),
error
end.
next_entry(node_entry, forward) ->
name_entry;
next_entry(node_entry, backward) ->
keypos_entry;
next_entry(name_entry, forward) ->
keypos_entry;
next_entry(name_entry, backward) ->
node_entry;
next_entry(keypos_entry, forward) ->
node_entry;
next_entry(keypos_entry, backward) ->
name_entry.
create_window(Node) ->
gs:window(win, gs:start(), [{width, ?WIN_WIDTH},
{height, ?WIN_HEIGHT},
{bg, ?DEFAULT_BG_COLOR},
{title, "[TV] Create New ETS Table"},
{configure, true},
{destroy, true},
{cursor, arrow}
]),
gs:frame(frame1, win, [{width, ?FRAME_WIDTH},
{height, ?FRAME1_HEIGHT},
{x, ?FRAME_X},
{y, ?FRAME1_Y},
{bg, ?DEFAULT_BG_COLOR},
{bw, ?BW}]),
gs:frame(frame2, win, [{width, ?FRAME_WIDTH},
{height, ?FRAME2_HEIGHT},
{x, ?FRAME_X},
{y, ?FRAME2_Y},
{bg, ?DEFAULT_BG_COLOR},
{bw, ?BW}]),
gs:frame(frame3, win, [{width, ?FRAME_WIDTH},
{height, ?FRAME3_HEIGHT},
{x, ?FRAME_X},
{y, ?FRAME3_Y},
{bg, ?DEFAULT_BG_COLOR},
{bw, ?BW}]),
gs:label(frame1, [{width, ?NODE_LBL_WIDTH},
{height, ?LBL_HEIGHT},
{x, ?LBL_X},
{y, ?NODE_LBL_Y},
{bg, ?DEFAULT_BG_COLOR},
{fg, {0,0,0}},
{align, w},
{font, ?FONT},
{label, {text, "Node:"}}
]),
gs:label(frame1, [{width, ?NAME_LBL_WIDTH},
{height, ?LBL_HEIGHT},
{x, ?LBL_X},
{y, ?NAME_LBL_Y},
{bg, ?DEFAULT_BG_COLOR},
{fg, {0,0,0}},
{align, w},
{font, ?FONT},
{label, {text, "Table name:"}}
]),
gs:label(frame2, [{width, ?TYPE_LBL_WIDTH},
{height, ?LBL_HEIGHT},
{x, ?LBL_X},
{y, ?TYPE_LBL_Y},
{bg, ?DEFAULT_BG_COLOR},
{fg, {0,0,0}},
{align, w},
{font, ?FONT},
{label, {text, "Type:"}}
]),
gs:label(frame2, [{width, ?PROT_LBL_WIDTH},
{height, ?LBL_HEIGHT},
{x, ?LBL_X},
{y, ?PROT_LBL_Y},
{bg, ?DEFAULT_BG_COLOR},
{fg, {0,0,0}},
{align, w},
{font, ?FONT},
{label, {text, "Protection:"}}
]),
gs:label(frame2, [{width, ?KEYPOS_LBL_WIDTH},
{height, ?LBL_HEIGHT},
{x, ?LBL_X},
{y, ?KEYPOS_LBL_Y},
{bg, ?DEFAULT_BG_COLOR},
{fg, {0,0,0}},
{align, w},
{font, ?FONT},
{label, {text, "Key position:"}}
]),
gs:entry(node_entry, frame1, [{width, ?NODE_ENTRY_WIDTH},
{height, ?ENTRY_HEIGHT},
{x, ?ENTRY_X1},
{y, ?NODE_ENTRY_Y},
{bg, {255,255,255}},
{fg, {0,0,0}},
{font, ?FONT},
{enable, true},
{text, "'" ++ atom_to_list(Node) ++ "'"},
{keypress, true}
]),
gs:entry(name_entry, frame1, [{width, ?NAME_ENTRY_WIDTH},
{height, ?ENTRY_HEIGHT},
{x, ?ENTRY_X1},
{y, ?NAME_ENTRY_Y},
{bg, {255,255,255}},
{fg, {0,0,0}},
{font, ?FONT},
{enable, true},
{text, atom_to_list(?DEFAULT_NAME)},
{keypress, true},
{setfocus, true},
{select, {0,100000000}}
]),
gs:entry(keypos_entry, frame2, [{width, ?KEYPOS_ENTRY_WIDTH},
{height, ?ENTRY_HEIGHT},
{x, ?ENTRY_X2},
{y, ?KEYPOS_ENTRY_Y},
{bg, {255,255,255}},
{fg, {0,0,0}},
{font, ?FONT},
{enable, true},
{keypress, true},
{text, integer_to_list(?DEFAULT_KEYPOS)}
]),
gs:radiobutton(set, frame2, [{width, ?RBTN_WIDTH1},
{height, ?RBTN_HEIGHT},
{x, ?RBTN_X1},
{y, ?RBTN_Y1},
{align, w},
{label, {text, "set"}},
{group, type}
]),
gs:radiobutton(ordered_set, frame2, [{width, ?RBTN_WIDTH1},
{height, ?RBTN_HEIGHT},
{x, ?RBTN_X2},
{y, ?RBTN_Y1},
{align, w},
{label, {text, "ordered_set"}},
{group, type}
]),
gs:radiobutton(bag, frame2, [{width, ?RBTN_WIDTH1},
{height, ?RBTN_HEIGHT},
{x, ?RBTN_X1},
{y, ?RBTN_Y1PLUS},
{align, w},
{label, {text, "bag"}},
{group, type}
]),
gs:radiobutton(duplicate_bag, frame2, [{width, ?RBTN_WIDTH2},
{height, ?RBTN_HEIGHT},
{x, ?RBTN_X2},
{y, ?RBTN_Y1PLUS},
{align, w},
{label, {text, "duplicate_bag"}},
{group, type}
]),
gs:radiobutton(public, frame2, [{width, ?RBTN_WIDTH1},
{height, ?RBTN_HEIGHT},
{x, ?RBTN_X1},
{y, ?RBTN_Y2},
{align, w},
{label, {text, "public"}},
{group, protection}
]),
gs:radiobutton(protected, frame2, [{width, ?RBTN_WIDTH1},
{height, ?RBTN_HEIGHT},
{x, ?RBTN_X2},
{y, ?RBTN_Y2},
{align, w},
{label, {text, "protected"}},
{group, protection}
]),
gs:radiobutton(private, frame2, [{width, ?RBTN_WIDTH2},
{height, ?RBTN_HEIGHT},
{x, ?RBTN_X3},
{y, ?RBTN_Y2},
{align, w},
{label, {text, "private"}},
{group, protection}
]),
gs:checkbutton(named_table, frame1, [{width, ?NAMED_TABLE_CBTN_WIDTH},
{height, ?CBTN_HEIGHT},
{x, ?NAMED_TABLE_CBTN_X},
{y, ?NAMED_TABLE_CBTN_Y},
{align, w},
{label, {text, "Named table"}},
{select, false},
{data, true}
]),
gs:checkbutton(open_browser, frame3, [{width, ?OPEN_BROWSER_CBTN_WIDTH},
{height, ?CBTN_HEIGHT},
{x, ?OPEN_BROWSER_CBTN_X},
{y, ?OPEN_BROWSER_CBTN_Y},
{align, w},
{label, {text, "Open browser"}},
{select, true},
{data, false}
]),
%% gs:label(frame2, [{width, ?VLINE_LBL_WIDTH},
%% {height, ?VLINE_LBL_HEIGHT},
%% {x, ?VLINE_LBL_X},
%% {y, ?VLINE_LBL_Y1},
%% {bg, {0,0,0}}
%% ]),
%% gs:label(frame2, [{width, ?VLINE_LBL_WIDTH},
%% {height, ?VLINE_LBL_HEIGHT},
%% {x, ?VLINE_LBL_X},
%% {y, ?VLINE_LBL_Y2},
%% {bg, {0,0,0}}
%% ]),
%% gs:label(frame2, [{width, ?HLINE_LBL_WIDTH},
%% {height, ?HLINE_LBL_HEIGHT},
%% {x, ?HLINE_LBL_X},
%% {y, ?HLINE_LBL_Y},
%% {bg, {0,0,0}}
%% ]),
%%
gs:button(ok, frame3, [{width, ?BTN_WIDTH},
{height, ?BTN_HEIGHT},
{x, ?BTN_X1},
{y, ?BTN_Y},
{bg, ?DEFAULT_BG_COLOR},
{fg, {0,0,0}},
{label, {text, "OK"}}
]),
gs:button(cancel, frame3, [{width, ?BTN_WIDTH},
{height, ?BTN_HEIGHT},
{x, ?BTN_X2},
{y, ?BTN_Y},
{bg, ?DEFAULT_BG_COLOR},
{fg, {0,0,0}},
{label, {text, "Cancel"}}
]),
gs:config(?DEFAULT_TYPE, [{select, true}]),
gs:config(?DEFAULT_PROT, [{select, true}]),
gs:config(win, [{map, true}]).