aboutsummaryrefslogtreecommitdiffstats
path: root/lib/tv/src/tv_rec_edit.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_rec_edit.erl
downloadotp-84adefa331c4159d432d22840663c38f155cd4c1.tar.gz
otp-84adefa331c4159d432d22840663c38f155cd4c1.tar.bz2
otp-84adefa331c4159d432d22840663c38f155cd4c1.zip
The R13B03 release.OTP_R13B03
Diffstat (limited to 'lib/tv/src/tv_rec_edit.erl')
-rw-r--r--lib/tv/src/tv_rec_edit.erl744
1 files changed, 744 insertions, 0 deletions
diff --git a/lib/tv/src/tv_rec_edit.erl b/lib/tv/src/tv_rec_edit.erl
new file mode 100644
index 0000000000..e8f663073e
--- /dev/null
+++ b/lib/tv/src/tv_rec_edit.erl
@@ -0,0 +1,744 @@
+%%
+%% %CopyrightBegin%
+%%
+%% Copyright Ericsson AB 1998-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%
+-module(tv_rec_edit).
+
+
+
+-export([start/5,
+ start/6,
+ init/8
+ ]).
+
+
+-include("tv_int_def.hrl").
+
+
+
+-define(DEFAULT_BG_COLOR, {217,217,217}).
+
+-define(WIN_WIDTH, 375).
+-define(WIN_HEIGHT, 341).
+-define(ETS_WIN_HEIGHT, 154).
+
+-define(FRAME_WIDTH, 375).
+-define(FRAME_HEIGHT, 265).
+-define(ETS_FRAME_HEIGHT, 74).
+
+-define(MAX_LABEL_WIDTH, 165).
+-define(X0, 15).
+-define(Y0, 20).
+-define(LABEL_HEIGHT, 30).
+-define(ENTRY_HEIGHT, 30).
+-define(FONT, {screen,12}).
+-define(NEXT_BTN_WIDTH, 57).
+-define(NEXT_BTN_HEIGHT, 22).
+-define(NEXT_BTN_FG, {178,34,34}).
+-define(INSERT_BTN_WIDTH, 80).
+-define(INSERT_BTN_HEIGHT, 30).
+-define(INSERT_BTN_DIST_BETWEEN, 23).
+-define(INSERT_BTN_DIST_FROM_BOTTOM, 23).
+
+
+
+
+
+start(TableType, TableName, AttributeList, ListsAsStr, ErrMsgMode) ->
+ AttributeValues = lists:duplicate(length(AttributeList), undefined),
+ spawn_link(?MODULE, init, [TableType, TableName, AttributeList,
+ AttributeValues, ListsAsStr, ErrMsgMode, self(), true]).
+
+
+
+start(TableType, TableName, AttributeList, AttributeValues, ListsAsStr, ErrMsgMode) ->
+ spawn_link(?MODULE, init, [TableType, TableName, AttributeList,
+ AttributeValues, ListsAsStr, ErrMsgMode, self(), false]).
+
+
+
+
+init(TableType,TableName,AttributeList,AttributeValues,ListsAsStr,ErrMsgMode,MasterPid,Insert) ->
+ process_flag(trap_exit, true),
+ put(error_msg_mode, ErrMsgMode),
+ Frames = create_window(TableType, TableName, AttributeList, AttributeValues,
+ ListsAsStr, Insert),
+ loop(TableType, TableName, Frames, AttributeList, AttributeValues, MasterPid, ListsAsStr).
+
+
+
+
+
+loop(TabType, TabName, Frames, AttrList, AttrVals, MPid, ListsAsStr) ->
+ receive
+
+ {gs, insert, click, Insert, _Args} ->
+ gs:config(win, [{cursor, busy}]),
+ case get_record(TabType, TabName, AttrList, AttrList, Frames) of
+ {ok, NewRec} ->
+ case Insert of
+ insert ->
+ MPid ! {new_object, NewRec};
+ change ->
+ MPid ! {updated_object, NewRec}
+ end;
+ error ->
+ done
+ end,
+ gs:config(win, [{cursor, arrow}]),
+ loop(TabType, TabName, Frames, AttrList, AttrVals, MPid, ListsAsStr);
+
+
+ {gs, cancel, click, _Data, _Args} ->
+ exit(normal);
+
+
+ {gs, reset, click, _Data, _Args} ->
+ gs:config(win, [{cursor, busy}]),
+ set_entry_values(TabType, AttrList, AttrVals, ListsAsStr),
+ gs:config(win, [{cursor, arrow}]),
+ loop(TabType, TabName, Frames, AttrList, AttrVals, MPid, ListsAsStr);
+
+
+
+ {gs, EntryId, keypress, _Data, ['Tab', _No, 0 | _T]} ->
+ {_Term, {NextEntry, NextFrame}} =
+ check_entry_content(EntryId, AttrList, Frames, forward),
+ case NextEntry of
+ EntryId ->
+ gs:config(NextEntry, [{setfocus, true}]);
+ _OtherId ->
+ gs:config(NextFrame, [raise]),
+ gs:config(NextEntry, [{setfocus, true},
+ {select, {0,100000000}}])
+ end,
+ loop(TabType, TabName, Frames, AttrList, AttrVals, MPid, ListsAsStr);
+
+
+ {gs, EntryId, keypress, _Data, ['Down' | _T]} ->
+ {_Term, {NextEntry, NextFrame}} =
+ check_entry_content(EntryId, AttrList, Frames, forward),
+ case NextEntry of
+ EntryId ->
+ gs:config(NextEntry, [{setfocus, true}]);
+ _OtherId ->
+ gs:config(NextFrame, [raise]),
+ gs:config(NextEntry, [{setfocus, true},
+ {select, {0,100000000}}])
+ end,
+ loop(TabType, TabName, Frames, AttrList, AttrVals, MPid, ListsAsStr);
+
+
+ {gs, EntryId, keypress, _Data, ['Tab', _No, 1 | _T]} ->
+ {_Term, {NextEntry, NextFrame}} =
+ check_entry_content(EntryId, AttrList, Frames, backward),
+ gs:config(NextFrame, [raise]),
+ case NextEntry of
+ EntryId ->
+ gs:config(NextEntry, [{setfocus, true}]);
+ _OtherId ->
+ gs:config(NextFrame, [raise]),
+ gs:config(NextEntry, [{setfocus, true},
+ {select, {0,100000000}}])
+ end,
+ loop(TabType, TabName, Frames, AttrList, AttrVals, MPid, ListsAsStr);
+
+
+ {gs, EntryId, keypress, _Data, ['Up' | _T]} ->
+ {_Term, {NextEntry, NextFrame}} =
+ check_entry_content(EntryId, AttrList, Frames, backward),
+ gs:config(NextFrame, [raise]),
+ case NextEntry of
+ EntryId ->
+ gs:config(NextEntry, [{setfocus, true}]);
+ _OtherId ->
+ gs:config(NextFrame, [raise]),
+ gs:config(NextEntry, [{setfocus, true},
+ {select, {0,100000000}}])
+ end,
+ loop(TabType, TabName, Frames, AttrList, AttrVals, MPid, ListsAsStr);
+
+
+ {gs, Id, keypress, _Data, ['Return' | _T]} ->
+ OldCursor = gs:read(Id, cursor),
+ gs:config(Id, [{cursor, busy}]),
+ gs:config(win, [{cursor, busy}]),
+ Insert = gs:read(insert, data),
+ case get_record(TabType, TabName, AttrList, AttrList, Frames) of
+ {ok, NewRec} ->
+ case Insert of
+ insert ->
+ MPid ! {new_object, NewRec};
+ change ->
+ MPid ! {updated_object, NewRec}
+ end;
+ error ->
+ done
+ end,
+ gs:config(win, [{cursor, arrow}]),
+ gs:config(Id, [{cursor, OldCursor}]),
+ loop(TabType, TabName, Frames, AttrList, AttrVals, MPid, ListsAsStr);
+
+
+
+ {gs, _Id, click, FrameNo, _Args} ->
+ gs:config(lists:nth(FrameNo, Frames), [raise]),
+ loop(TabType, TabName, Frames, AttrList, AttrVals, MPid, ListsAsStr);
+
+
+ {gs, win, configure, _Data, [Width | _T]} ->
+ resize_window(TabType, lists:max([Width, ?WIN_WIDTH]), Frames, AttrList),
+ loop(TabType, TabName, Frames, AttrList, AttrVals, MPid, ListsAsStr);
+
+
+ {gs, win, destroy, _Data, _Args} ->
+ exit(normal);
+
+
+ insert_mode ->
+ NewAttrVals = lists:duplicate(length(AttrList), undefined),
+ set_entry_values(TabType, AttrList, NewAttrVals, ListsAsStr),
+ loop(TabType, TabName, Frames, AttrList, NewAttrVals, MPid, ListsAsStr);
+
+
+ {update_mode, Obj} ->
+ NewAttrVals =
+ case TabType of
+ mnesia ->
+ case Obj of
+ undefined ->
+ lists:duplicate(length(AttrList), undefined);
+ _AnyRec ->
+ tl(tuple_to_list(Obj))
+ end;
+ ets ->
+ [Obj]
+ end,
+ set_entry_values(TabType, AttrList, NewAttrVals, ListsAsStr),
+ loop(TabType, TabName, Frames, AttrList, NewAttrVals, MPid, ListsAsStr);
+
+
+ {reset_info, Obj} ->
+ %% Info to use, instead of old info, when reset button is pressed.
+ NewAttrVals =
+ case TabType of
+ mnesia ->
+ case Obj of
+ undefined ->
+ lists:duplicate(length(AttrList), undefined);
+ _AnyRec ->
+ tl(tuple_to_list(Obj))
+ end;
+ ets ->
+ [Obj]
+ end,
+ loop(TabType, TabName, Frames, AttrList, NewAttrVals, MPid, ListsAsStr);
+
+
+ raise ->
+ gs:config(win, [raise]),
+ loop(TabType, TabName, Frames, AttrList,AttrVals, MPid, ListsAsStr);
+
+
+ {'EXIT', _Pid, _Reason} ->
+ exit(normal);
+
+
+ _Other ->
+ loop(TabType, TabName, Frames, AttrList,AttrVals, MPid, ListsAsStr)
+ end.
+
+
+
+
+resize_window(TabType, WinWidth, Frames, AttrList) ->
+ WinHeight =
+ case TabType of
+ mnesia ->
+ get_window_height(length(AttrList));
+ ets ->
+ ?ETS_WIN_HEIGHT
+ end,
+ gs:config(win, [{width, WinWidth},
+ {height, WinHeight}
+ ]),
+ FrameWidth = WinWidth,
+ LblL = lists:map(fun(H) ->
+ gs:config(H, [{width, FrameWidth}]),
+ {LblW, BId, NId} = gs:read(H, data),
+ XNext = get_next_btn_xpos(FrameWidth),
+ XBack = XNext - ?NEXT_BTN_WIDTH,
+ gs:config(BId, [{x, XBack}]),
+ gs:config(NId, [{x, XNext}]),
+ LblW
+ end,
+ Frames),
+ LblW = hd(LblL),
+ EntryW = get_entry_width(TabType, FrameWidth, LblW),
+ lists:foreach(fun(H) ->
+ gs:config(H, [{width, EntryW}])
+ end,
+ AttrList),
+ gs:config(btnframe, [{width, FrameWidth}]),
+ {XInsert, XCancel, XReset} = get_insert_btn_coords(WinWidth),
+ gs:config(insert, [{x, XInsert}]),
+ gs:config(cancel, [{x, XCancel}]),
+ gs:config(reset, [{x, XReset}]).
+
+
+
+
+check_entry_content(EntryId, AttributeList, Frames, Direction) ->
+ EditedStr = gs:read(EntryId, text),
+ case tv_db_search:string_to_term(EditedStr) of
+ {error, {_Reason, Msg}} ->
+ gs:config(EntryId, [beep]),
+ tv_utils:notify(gs:start(), "TV Notification", Msg),
+ {error, {EntryId, no_matter}};
+ {ok, NewTerm} ->
+ {{ok,NewTerm}, get_next_entry_id(EntryId, AttributeList, Frames, Direction)}
+ end.
+
+
+
+
+get_next_entry_id(EntryId, AttributeList, Frames, Direction) ->
+ OldPos = get_pos(EntryId, AttributeList),
+ MaxPos = length(AttributeList),
+ NewPos = case Direction of
+ forward when OldPos < MaxPos ->
+ OldPos + 1;
+ forward ->
+ 1;
+ backward when OldPos > 1 ->
+ OldPos - 1;
+ backward ->
+ MaxPos;
+ stationary ->
+ OldPos
+ end,
+ FramePos = get_next_frame_id(NewPos),
+ {lists:nth(NewPos, AttributeList), lists:nth(FramePos, Frames)}.
+
+
+
+
+get_next_frame_id(Pos) ->
+ case Pos rem 5 of
+ 0 ->
+ Pos div 5;
+ _Other ->
+ (Pos div 5) + 1
+ end.
+
+
+
+
+get_record(TabType, TabName, AttrList, AttrList, Frames) ->
+ case get_record(AttrList, AttrList, Frames, []) of
+ {ok, RecList} ->
+ case TabType of
+ mnesia ->
+ NewRecList = [TabName | RecList],
+ {ok, list_to_tuple(NewRecList)};
+ ets ->
+ {ok, hd(RecList)} %% Only one element, a tuple!
+ end;
+ error ->
+ error
+ end.
+
+
+
+
+get_record([H | T], AttrList, Frames, Acc) ->
+ case check_entry_content(H, AttrList, Frames, forward) of
+ {{ok, NewTerm}, _PosTuple} ->
+ get_record(T, AttrList, Frames, [NewTerm | Acc]);
+ {error, _PosTuple} ->
+ {EntryId, FrameId} = get_next_entry_id(H, AttrList, Frames, stationary),
+ gs:config(FrameId, [raise]),
+ gs:config(EntryId, [{setfocus, true}]),
+ error
+ end;
+get_record([], _AttrList, _Frames, Acc) ->
+ {ok, lists:reverse(Acc)}.
+
+
+
+
+
+
+get_pos(Elem, L) ->
+ get_pos(Elem, L, 1).
+
+
+get_pos(Elem, [Elem | _T], N) ->
+ N;
+get_pos(Elem, [_H | T], N) ->
+ get_pos(Elem, T, N + 1).
+
+
+
+
+create_window(mnesia, TableName, AttrList, AttrValues, ListsAsStr, Insert) ->
+ NofAttr = length(AttrList),
+ NofFrames =
+ case NofAttr rem 5 of
+ 0 ->
+ NofAttr div 5;
+ _Rem ->
+ (NofAttr div 5) + 1
+ end,
+
+ WinHeight = get_window_height(NofAttr),
+ FrameHeight = get_frame_height(NofAttr),
+
+ Attr = get_longest_attribute_name(AttrList),
+ LabelWidth = lists:min([?MAX_LABEL_WIDTH,
+ element(1, gs:read(gs:start(),
+ {font_wh, {?FONT, atom_to_list(Attr)}}))]),
+
+ gs:window(win, gs:start(), [{width, ?WIN_WIDTH},
+ {height, WinHeight},
+ {title, "[TV] Record Editor: '" ++
+ atom_to_list(TableName) ++ "'"},
+ {bg, ?DEFAULT_BG_COLOR},
+ {configure, true},
+ {destroy, true},
+ {cursor, arrow}
+ ]),
+
+ create_insert_and_cancel_btns(Insert, WinHeight, FrameHeight),
+ FrameList = create_frames(NofFrames, LabelWidth, AttrList, AttrValues, NofFrames,
+ ListsAsStr, FrameHeight),
+ gs:config(hd(FrameList), [raise]),
+ gs:config(hd(AttrList), [{setfocus, true},
+ {select, {0,100000000}}]),
+ gs:config(win, [{map,true}]),
+ FrameList;
+create_window(ets, TableName, [Attr], [AttrVal], ListsAsStr, Insert) ->
+ gs:window(win, gs:start(), [{width, ?WIN_WIDTH},
+ {height, ?ETS_WIN_HEIGHT},
+ {title, "[TV] Tuple Editor, table '" ++
+ atom_to_list(TableName) ++ "'"},
+ {bg, ?DEFAULT_BG_COLOR},
+ {configure, true},
+ {destroy, true},
+ {cursor, arrow}
+ ]),
+
+ F = gs:frame(win, [{width, ?FRAME_WIDTH},
+ {height, ?ETS_FRAME_HEIGHT},
+ {x, 0},
+ {y, 0},
+ {bg, ?DEFAULT_BG_COLOR},
+ {bw,2},
+ {data, {0, undefined, undefined}}
+ ]),
+
+ create_insert_and_cancel_btns(Insert, ?ETS_WIN_HEIGHT, ?ETS_FRAME_HEIGHT),
+
+ EntryW = get_entry_width(ets, ?FRAME_WIDTH, 0),
+ EntryX = ?X0 - 2,
+
+ EntryText =
+ case AttrVal of
+ undefined ->
+ "";
+ _OtherVal ->
+ case ListsAsStr of
+ true ->
+ tv_io_lib:format("~p", [AttrVal]);
+ false ->
+ lists:flatten(io_lib:write(AttrVal))
+ end
+ end,
+ gs:entry(Attr, F, [{width, EntryW},
+ {height, ?LABEL_HEIGHT},
+ {x, EntryX},
+ {y, ?Y0},
+ {bg, {255,255,255}},
+ {fg, {0,0,0}},
+ {bw, 1},
+ {font, ?FONT},
+ {justify, left},
+ {text, EntryText},
+ {cursor, text},
+ {setfocus, true},
+ {enable, true},
+ {keypress,true},
+ {select, {0,100000000}}
+ ]),
+ gs:config(win, [{map,true}]),
+ [F].
+
+
+
+
+get_insert_btn_coords(WinWidth) ->
+ Middle = round(WinWidth / 2),
+ XInsert = Middle - round(1.5 * ?INSERT_BTN_WIDTH) - ?INSERT_BTN_DIST_BETWEEN,
+ XCancel = Middle - round(0.5 * ?INSERT_BTN_WIDTH),
+ XReset = Middle + round(0.5 * ?INSERT_BTN_WIDTH) + ?INSERT_BTN_DIST_BETWEEN,
+ {XInsert, XCancel, XReset}.
+
+
+
+
+create_insert_and_cancel_btns(Insert, WinHeight, FrameHeight) ->
+ LowerFrameHeight = WinHeight - FrameHeight,
+ Y = ?INSERT_BTN_DIST_FROM_BOTTOM,
+ {XInsert, XCancel, XReset} = get_insert_btn_coords(?WIN_WIDTH),
+
+ {InsertBtnText, InsertBtnData} =
+ case Insert of
+ true ->
+ {"Insert", insert};
+ false ->
+ {"Change", change}
+ end,
+
+ gs:frame(btnframe, win, [{width, ?FRAME_WIDTH},
+ {height, LowerFrameHeight},
+ {x, 0},
+ {y, FrameHeight},
+ {bg, ?DEFAULT_BG_COLOR},
+ {bw,2}
+ ]),
+ gs:button(insert, btnframe, [{width, ?INSERT_BTN_WIDTH},
+ {height, ?INSERT_BTN_HEIGHT},
+ {x, XInsert},
+ {y, Y},
+ {bg, ?DEFAULT_BG_COLOR},
+ {fg, {0,0,0}},
+ {font, ?FONT},
+ {label, {text, InsertBtnText}},
+ {align, center},
+ {data, InsertBtnData}
+ ]),
+ gs:button(cancel, btnframe, [{width, ?INSERT_BTN_WIDTH},
+ {height, ?INSERT_BTN_HEIGHT},
+ {x, XCancel},
+ {y, Y},
+ {bg, ?DEFAULT_BG_COLOR},
+ {fg, {0,0,0}},
+ {font, ?FONT},
+ {label, {text, "Cancel"}},
+ {align, center}
+ ]),
+ gs:button(reset, btnframe, [{width, ?INSERT_BTN_WIDTH},
+ {height, ?INSERT_BTN_HEIGHT},
+ {x, XReset},
+ {y, Y},
+ {bg, ?DEFAULT_BG_COLOR},
+ {fg, {0,0,0}},
+ {font, ?FONT},
+ {label, {text, "Reset"}},
+ {align, center}
+ ]).
+
+
+
+
+
+create_frames(0, _LblW, _AttrList, _AttrValues, _NofFrames, _ListsAsStr, _FrameHeight) ->
+ [];
+create_frames(N, LblW, AttrList, AttrValues, NofFrames, ListsAsStr, FrameHeight) ->
+ F = gs:frame(win, [{width, ?FRAME_WIDTH},
+ {height, FrameHeight},
+ {x, 0},
+ {y, 0},
+ {bg, ?DEFAULT_BG_COLOR},
+ {bw,2}
+ ]),
+ {BId, NId} = create_back_and_next_btns(F, 5, N, NofFrames),
+ gs:config(F, [{data, {LblW, BId, NId}}]),
+ {RemAttrList, RemAttrValues} =
+ create_labels_and_entries(5, AttrList, AttrValues, LblW, F, ListsAsStr),
+ [F | create_frames(N - 1,LblW,RemAttrList,RemAttrValues,NofFrames,ListsAsStr,FrameHeight)].
+
+
+
+
+
+
+create_back_and_next_btns(FrameId, NofEntries, FrameNo, NofFrames) ->
+ Y = ?Y0 + NofEntries * (?LABEL_HEIGHT + 10) + 8,
+ XNext = get_next_btn_xpos(?FRAME_WIDTH),
+ XBack = XNext - ?NEXT_BTN_WIDTH,
+ DataNext = (NofFrames - FrameNo + 1) + 1,
+ DataBack = (NofFrames - FrameNo + 1) - 1,
+ BId =
+ if
+ DataBack =< 0 ->
+ undefined;
+ true ->
+ gs:button(FrameId, [{width, ?NEXT_BTN_WIDTH},
+ {height, ?NEXT_BTN_HEIGHT},
+ {x, XBack},
+ {y, Y},
+ {bg, ?DEFAULT_BG_COLOR},
+ {fg, ?NEXT_BTN_FG},
+ {font, ?FONT},
+ {align, center},
+ {label, {text, "< Back"}},
+ %% {underline, 2},
+ {data, DataBack}
+ ])
+ end,
+ NId =
+ if
+ DataNext > NofFrames ->
+ undefined;
+ true ->
+ gs:button(FrameId, [{width, ?NEXT_BTN_WIDTH},
+ {height, ?NEXT_BTN_HEIGHT},
+ {x, XNext},
+ {y, Y},
+ {bg, ?DEFAULT_BG_COLOR},
+ {fg, ?NEXT_BTN_FG},
+ {font, ?FONT},
+ {align, center},
+ {label, {text, " Next >"}},
+ %% {underline, 1},
+ {data, DataNext}
+ ])
+ end,
+ {BId, NId}.
+
+
+
+
+get_next_btn_xpos(FrameWidth) ->
+ FrameWidth - ?X0 - ?NEXT_BTN_WIDTH.
+
+
+
+get_entry_width(TableType, FrameWidth, LblWidth) ->
+ HorizontalSpacing =
+ case TableType of
+ mnesia ->
+ 10;
+ ets ->
+ 0
+ end,
+ FrameWidth - LblWidth - 2 * ?X0 - HorizontalSpacing.
+
+
+
+create_labels_and_entries(N, [H | T], [VH | VT], LblW, F, ListsAsStr) when N > 0 ->
+ Y = ?Y0 + (5 - N) * (?LABEL_HEIGHT + 10),
+ EntryW = get_entry_width(mnesia, ?FRAME_WIDTH, LblW),
+ EntryX = ?FRAME_WIDTH - EntryW - ?X0 - 2,
+
+ EntryText =
+ case ListsAsStr of
+ true ->
+ tv_io_lib:format("~p", [VH]);
+ false ->
+ lists:flatten(io_lib:write(VH))
+ end,
+ gs:label(F, [{width, LblW},
+ {height, ?LABEL_HEIGHT},
+ {x, ?X0},
+ {y, Y},
+ {bg, ?DEFAULT_BG_COLOR},
+ {fg, {0,0,0}},
+ {align,w},
+ {font, ?FONT},
+ {label, {text, atom_to_list(H)}}
+ ]),
+ gs:entry(H, F, [{width, EntryW},
+ {height, ?LABEL_HEIGHT},
+ {x, EntryX},
+ {y, Y},
+ {bg, {255,255,255}},
+ {fg, {0,0,0}},
+ {bw, 1},
+ {font, ?FONT},
+ {justify, left},
+ {text, EntryText},
+ {cursor, text},
+ {setfocus, false},
+ {enable, true},
+ {keypress,true}
+ ]),
+ create_labels_and_entries(N - 1, T, VT, LblW, F, ListsAsStr);
+create_labels_and_entries(0, RemAttrList, RemAttrValues, _LblW, _F, _ListsAsStr) ->
+ {RemAttrList, RemAttrValues};
+create_labels_and_entries(_N, [], [], _LblW, _F, _ListsAsStr) ->
+ {[], []}.
+
+
+
+
+get_longest_attribute_name(AttrList) ->
+ get_longest_attribute_name(AttrList, 0, undefined).
+
+
+get_longest_attribute_name([H | T], Max, Attr) ->
+ CurrLength = length(atom_to_list(H)),
+ if
+ CurrLength >= Max ->
+ get_longest_attribute_name(T, CurrLength, H);
+ true ->
+ get_longest_attribute_name(T, Max, Attr)
+ end;
+get_longest_attribute_name([], _Max, Attr) ->
+ Attr.
+
+
+
+
+get_window_height(N) ->
+ if
+ N >= 5 ->
+ ?WIN_HEIGHT;
+ true ->
+ ?WIN_HEIGHT - ((5 - N) * (?LABEL_HEIGHT + 10) + ?NEXT_BTN_HEIGHT + 8)
+ end.
+
+
+
+get_frame_height(N) ->
+ if
+ N >= 5 ->
+ ?FRAME_HEIGHT;
+ true ->
+ ?FRAME_HEIGHT - ((5 - N) * (?LABEL_HEIGHT + 10) + ?NEXT_BTN_HEIGHT + 8)
+ end.
+
+
+
+
+set_entry_values(TabType, [H | T], [VH | VT], ListsAsStr) ->
+ EntryText =
+ case VH of
+ undefined when TabType =:= ets ->
+ "";
+ _AnyValue ->
+ case ListsAsStr of
+ true ->
+ tv_io_lib:format("~p", [VH]);
+ false ->
+ lists:flatten(io_lib:write(VH))
+ end
+ end,
+ gs:config(H, [{text, EntryText}]),
+ set_entry_values(TabType, T, VT, ListsAsStr);
+set_entry_values(_TabType, [], [], _ListsAsStr) ->
+ done.