aboutsummaryrefslogtreecommitdiffstats
path: root/lib/observer/src/observer_tv_table.erl
diff options
context:
space:
mode:
Diffstat (limited to 'lib/observer/src/observer_tv_table.erl')
-rw-r--r--lib/observer/src/observer_tv_table.erl123
1 files changed, 69 insertions, 54 deletions
diff --git a/lib/observer/src/observer_tv_table.erl b/lib/observer/src/observer_tv_table.erl
index b4832d9599..59fe5b5670 100644
--- a/lib/observer/src/observer_tv_table.erl
+++ b/lib/observer/src/observer_tv_table.erl
@@ -98,7 +98,7 @@ init([Parent, Opts]) ->
ets -> "TV Ets: " ++ Title0;
mnesia -> "TV Mnesia: " ++ Title0
end,
- Frame = wxFrame:new(Parent, ?wxID_ANY, Title, [{size, {800, 300}}]),
+ Frame = wxFrame:new(Parent, ?wxID_ANY, Title, [{size, {800, 600}}]),
IconFile = filename:join(code:priv_dir(observer), "erlang_observer.png"),
Icon = wxIcon:new(IconFile, [{type,?wxBITMAP_TYPE_PNG}]),
wxFrame:setIcon(Frame, Icon),
@@ -261,11 +261,12 @@ handle_event(#wx{id=?ID_EDIT}, State = #state{selected=Index}) ->
handle_event(#wx{id=?ID_DELETE}, State = #state{selected=undefined}) ->
{noreply, State};
handle_event(#wx{id=?ID_DELETE},
- State = #state{pid=Pid, status=StatusBar, selected=Index}) ->
+ State = #state{grid=Grid, pid=Pid, status=StatusBar, selected=Index}) ->
Str = get_row(Pid, Index, all),
Pid ! {delete, Index},
wxStatusBar:setStatusText(StatusBar, io_lib:format("Deleted object: ~s",[Str])),
- {noreply, State};
+ wxListCtrl:setItemState(Grid, Index, 0, ?wxLIST_STATE_FOCUSED),
+ {noreply, State#state{selected=undefined}};
handle_event(#wx{id=?wxID_CLOSE}, State = #state{frame=Frame}) ->
wxFrame:destroy(Frame),
@@ -279,8 +280,8 @@ handle_event(#wx{id=?GOTO_ENTRY, event=#wxCommand{cmdString=Str}},
State = #state{grid=Grid}) ->
try
Row0 = list_to_integer(Str),
- Row1 = min(0, Row0),
- Row = max(wxListCtrl:getItemCount(Grid)-1,Row1),
+ Row1 = max(0, Row0),
+ Row = min(wxListCtrl:getItemCount(Grid)-1,Row1),
wxListCtrl:ensureVisible(Grid, Row),
ok
catch _:_ -> ok
@@ -289,7 +290,9 @@ handle_event(#wx{id=?GOTO_ENTRY, event=#wxCommand{cmdString=Str}},
%% Search functionality
handle_event(#wx{id=?ID_SEARCH},
- State = #state{sizer=Sz, search=Search}) ->
+ State = #state{grid=Grid, sizer=Sz, search=Search, selected=Index}) ->
+ is_integer(Index) andalso
+ wxListCtrl:setItemState(Grid, Index, 0, ?wxLIST_STATE_FOCUSED),
wxSizer:show(Sz, Search#search.win),
wxWindow:setFocus(Search#search.search),
wxSizer:layout(Sz),
@@ -321,7 +324,7 @@ handle_event(#wx{id=?SEARCH_ENTRY, event=#wxCommand{type=command_text_enter,cmdS
Pid ! {mark_search_hit, false},
case search(Pid, Str, Pos, Dir, Case) of
false ->
- wxStatusBar:setStatusText(SB, "Not found"),
+ wxStatusBar:setStatusText(SB, io_lib:format("Not found (regexp): ~s",[Str])),
Pid ! {mark_search_hit, Find#find.start},
wxListCtrl:refreshItem(Grid, Find#find.start),
{noreply, State#state{search=Search#search{find=Find#find{found=false}}}};
@@ -355,7 +358,7 @@ handle_event(#wx{id=?SEARCH_ENTRY, event=#wxCommand{cmdString=Str}},
Pid ! {mark_search_hit, false},
case search(Pid, Str, Cont#find.start, Dir, Case) of
false ->
- wxStatusBar:setStatusText(SB, "Not found"),
+ wxStatusBar:setStatusText(SB, io_lib:format("Not found (regexp): ~s",[Str])),
{noreply, State};
Row ->
wxListCtrl:ensureVisible(Grid, Row),
@@ -402,8 +405,11 @@ handle_info({new_cols, New}, State = #state{grid=Grid, columns=Cols0}) ->
Cols = add_columns(Grid, Cols0, New),
{noreply, State#state{columns=Cols}};
+handle_info({refresh, Min, Min}, State = #state{grid=Grid}) ->
+ wxListCtrl:refreshItem(Grid, Min), %% Avoid assert in wx below if Max is 0
+ {noreply, State};
handle_info({refresh, Min, Max}, State = #state{grid=Grid}) ->
- Max > 0 andalso wxListCtrl:refreshItems(Grid, Min, Max),
+ wxListCtrl:refreshItems(Grid, Min, Max),
{noreply, State};
handle_info(refresh_interval, State = #state{pid=Pid}) ->
@@ -426,10 +432,14 @@ handle_info(_Event, State) ->
terminate(_Event, #state{pid=Pid, attrs=Attrs}) ->
%% ListItemAttr are not auto deleted
- #attrs{odd=Odd, deleted=D, changed=Ch, searched=S} = Attrs,
- wxListItemAttr:destroy(Odd),
+ #attrs{odd=Odd, even=Even, deleted=D, searched=S,
+ changed_odd=Ch1, changed_even=Ch2,
+ new_odd=New1, new_even=New2
+ } = Attrs,
+ wxListItemAttr:destroy(Odd), wxListItemAttr:destroy(Even),
wxListItemAttr:destroy(D),
- wxListItemAttr:destroy(Ch),
+ wxListItemAttr:destroy(Ch1),wxListItemAttr:destroy(Ch2),
+ wxListItemAttr:destroy(New1),wxListItemAttr:destroy(New2),
wxListItemAttr:destroy(S),
unlink(Pid),
exit(Pid, window_closed),
@@ -473,7 +483,7 @@ search(Table, Str, Row, Dir, Case) ->
end.
-record(holder, {node, parent, pid,
- table=[], n=0, columns,
+ table=array:new(), n=0, columns,
temp=[],
search,
source, tabid,
@@ -507,6 +517,7 @@ table_holder(S0 = #holder{parent=Parent, pid=Pid, table=Table}) ->
S1 = handle_new_data_chunk(Data, S0),
table_holder(S1);
{sort, Col} ->
+ Parent ! {refresh, 0, S0#holder.n-1},
table_holder(sort(Col, S0));
{search, Data} ->
table_holder(search(Data, S0));
@@ -530,11 +541,14 @@ table_holder(S0 = #holder{parent=Parent, pid=Pid, table=Table}) ->
table_holder(S0);
What ->
io:format("Table holder got ~p~n",[What]),
+ Parent ! {refresh, 0, S0#holder.n-1},
table_holder(S0)
end.
handle_new_data_chunk(Data, S0 = #holder{columns=Cols, parent=Parent}) ->
- S1 = #holder{columns=NewCols} = handle_new_data_chunk2(Data, S0),
+ S1 = #holder{n=N,columns=NewCols} = handle_new_data_chunk2(Data, S0),
+ Parent ! {no_rows, N},
+ Parent ! {refresh, 0, N-1},
case NewCols =:= Cols of
true -> S1;
false ->
@@ -543,15 +557,12 @@ handle_new_data_chunk(Data, S0 = #holder{columns=Cols, parent=Parent}) ->
end.
handle_new_data_chunk2('$end_of_table',
- S0 = #holder{parent=Parent, sort=Opt,
- key=Key,
+ S0 = #holder{sort=Opt0, key=Key,
table=Old, temp=New}) ->
- Table = merge(Old, New, Key),
- N = length(Table),
- Parent ! {no_rows, N},
- sort(Opt#opt.sort_key, S0#holder{n=N, pid=undefine,
- sort=Opt#opt{sort_key = undefined},
- table=Table, temp=[]});
+ Merged = merge(array:to_list(Old), New, Key),
+ {Opt,Sorted} = sort(Opt0#opt.sort_key, Opt0#opt{sort_key = undefined}, Merged),
+ SortedA = array:from_list(Sorted),
+ S0#holder{sort=Opt, table=SortedA, n=array:size(SortedA), temp=[], pid=undefined};
handle_new_data_chunk2(Data, S0 = #holder{columns=Cols0, source=ets, temp=Tab0}) ->
{Tab, Cols} = parse_ets_data(Data, Cols0, Tab0),
S0#holder{columns=Cols, temp=Tab};
@@ -566,10 +577,9 @@ parse_ets_data([Recs|Rs], C0, Tab0) ->
parse_ets_data([], Cols, Tab) ->
{Tab, Cols}.
-sort(Col, S=#holder{n=N, parent=Parent, sort=Opt0, table=Table0}) ->
- {Opt, Table} = sort(Col, Opt0, Table0),
- Parent ! {refresh, 0, N-1},
- S#holder{sort=Opt, table=Table}.
+sort(Col, S=#holder{sort=Opt0, table=Table0}) ->
+ {Opt, Table} = sort(Col, Opt0, array:to_list(Table0)),
+ S#holder{sort=Opt, table=array:from_list(Table)}.
sort(Col, Opt = #opt{sort_key=Col, sort_incr=Bool}, Table) ->
{Opt#opt{sort_incr=not Bool}, lists:reverse(Table)};
@@ -597,7 +607,7 @@ keysort(Col, Table) ->
lists:sort(Sort, Table).
search([Str, Row, Dir0, CaseSens],
- S=#holder{parent=Parent, table=Table0}) ->
+ S=#holder{parent=Parent, n=N, table=Table}) ->
Opt = case CaseSens of
true -> [];
false -> [caseless]
@@ -607,32 +617,26 @@ search([Str, Row, Dir0, CaseSens],
false -> -1
end,
Res = case re:compile(Str, Opt) of
- {ok, Re} ->
- Table =
- case Dir0 of
- true ->
- lists:nthtail(Row, Table0);
- false ->
- lists:reverse(lists:sublist(Table0, Row+1))
- end,
- search(Row, Dir, Re, Table);
+ {ok, Re} -> re_search(Row, Dir, N, Re, Table);
{error, _} -> false
end,
Parent ! {self(), Res},
S#holder{search=Res}.
-search(Row, Dir, Re, [ [Term|_] |Table]) ->
+re_search(Row, Dir, N, Re, Table) when Row >= 0, Row < N ->
+ [Term|_] = array:get(Row, Table),
Str = format(Term),
Res = re:run(Str, Re),
case Res of
- nomatch -> search(Row+Dir, Dir, Re, Table);
- {match,_} -> Row
+ nomatch -> re_search(Row+Dir, Dir, N, Re, Table);
+ {match,_} ->
+ Row
end;
-search(_, _, _, []) ->
+re_search(_, _, _, _, _) ->
false.
get_row(From, Row, Col, Table) ->
- case lists:nth(Row+1, Table) of
+ case array:get(Row, Table) of
[Object|_] when Col =:= all ->
From ! {self(), format(Object)};
[Object|_] when Col =:= all_multiline ->
@@ -647,14 +651,15 @@ get_attr(From, Row, #holder{attrs=Attrs, search=Row}) ->
What = Attrs#attrs.searched,
From ! {self(), What};
get_attr(From, Row, #holder{table=Table, attrs=Attrs}) ->
- What = case lists:nth(Row+1, Table) of
+ Odd = (Row rem 2) > 0,
+ What = case array:get(Row, Table) of
[_|deleted] -> Attrs#attrs.deleted;
- [_|changed] -> Attrs#attrs.changed;
- [_|new] -> Attrs#attrs.changed;
- _ when (Row rem 2) > 0 ->
- Attrs#attrs.odd;
- _ ->
- Attrs#attrs.even
+ [_|changed] when Odd -> Attrs#attrs.changed_odd;
+ [_|changed] -> Attrs#attrs.changed_even;
+ [_|new] when Odd -> Attrs#attrs.new_odd;
+ [_|new] -> Attrs#attrs.new_even;
+ _ when Odd -> Attrs#attrs.odd;
+ _ -> Attrs#attrs.even
end,
From ! {self(), What}.
@@ -665,19 +670,29 @@ merge(Old, New, Key) ->
merge2([[Obj|_]|Old], [Obj|New], Key) ->
[[Obj]|merge2(Old, New, Key)];
-merge2([[A|_]|Old], [B|New], Key)
+merge2([[A|Op]|Old], [B|New], Key)
when element(Key, A) == element(Key, B) ->
- [[B|changed]|merge2(Old, New, Key)];
-merge2([[A|_]|Old], New = [B|_], Key)
+ case Op of
+ deleted ->
+ [[B|new]|merge2(Old, New, Key)];
+ _ ->
+ [[B|changed]|merge2(Old, New, Key)]
+ end;
+merge2([[A|Op]|Old], New = [B|_], Key)
when element(Key, A) < element(Key, B) ->
- [[A|deleted]|merge2(Old, New, Key)];
+ case Op of
+ deleted -> merge2(Old, New, Key);
+ _ -> [[A|deleted]|merge2(Old, New, Key)]
+ end;
merge2(Old = [[A|_]|_], [B|New], Key)
when element(Key, A) > element(Key, B) ->
[[B|new]|merge2(Old, New, Key)];
merge2([], New, _Key) ->
[[N|new] || N <- New];
merge2(Old, [], _Key) ->
- [[O|deleted] || [O|_] <- Old].
+ lists:foldl(fun([_O|deleted], Acc) -> Acc;
+ ([O|_], Acc) -> [[O|deleted]|Acc]
+ end, [], Old).
delete_row(Row, S0 = #holder{parent=Parent}) ->
@@ -691,7 +706,7 @@ delete_row(Row, S0 = #holder{parent=Parent}) ->
delete(Row, #holder{tabid=Id, table=Table,
source=Source, node=Node}) ->
- [Object|_] = lists:nth(Row+1, Table),
+ [Object|_] = array:get(Row, Table),
try
case Source of
ets ->