%% %% %CopyrightBegin% %% %% Copyright Ericsson AB 2008-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. %% You may obtain a copy of the License at %% %% http://www.apache.org/licenses/LICENSE-2.0 %% %% Unless required by applicable law or agreed to in writing, software %% distributed under the License is distributed on an "AS IS" BASIS, %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %% See the License for the specific language governing permissions and %% limitations under the License. %% %% %CopyrightEnd% %% %% -module(dbg_wx_winman). -behaviour(gen_server). %% External exports -export([start/0]). -export([insert/2, is_started/1, clear_process/1, raise/1, update_windows_menu/2]). %% gen_server callbacks -export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]). -record(win, {owner, % pid() title, % string() win % gsobj() }). -record(state, {wins=[] % [#win{}] }). %%==================================================================== %% External exports %%==================================================================== %%-------------------------------------------------------------------- %% start() %%-------------------------------------------------------------------- start() -> gen_server:start({local,?MODULE}, ?MODULE, [], []). %%-------------------------------------------------------------------- %% insert(Title, Win) %% Title = string() %% Win = gsobj() %%-------------------------------------------------------------------- insert(Title, Win) -> gen_server:cast(?MODULE, {insert, self(), Title, Win}). %%-------------------------------------------------------------------- %% is_started(Title) -> true | false %% Title = string() %%-------------------------------------------------------------------- is_started(Title) -> case gen_server:call(?MODULE, {is_started, Title}, infinity) of {true, Win} -> raise(Win), true; false -> false end. %%-------------------------------------------------------------------- %% clear_process(Title) %% Title = string() %%-------------------------------------------------------------------- clear_process(Title) -> gen_server:cast(?MODULE, {clear_process, Title}). %%-------------------------------------------------------------------- %% raise(Win) %% Win = gsobj() %%-------------------------------------------------------------------- raise(Win) -> case wxTopLevelWindow:isIconized(Win) of true -> wxTopLevelWindow:iconize(Win, [{iconize, false}]); false -> ignore end, wxWindow:raise(Win). %%-------------------------------------------------------------------- %% update_windows_menu(Data) %% Data = {New, Old} %% New = Old = list() %%-------------------------------------------------------------------- update_windows_menu(Win, [MonInfo|Infos]) -> Menu = get('Windows'), OldItems = wxMenu:getMenuItems(Menu), [wxMenu:delete(Menu, Item) || Item <- OldItems], menuitem(Win, Menu,MonInfo, 700), _ = wxMenu:appendSeparator(Menu), wx:foldl(fun(Info,Acc) -> menuitem(Win,Menu,Info,Acc) end, 701, Infos). menuitem(Window, Menu, {Title, Win}, Id) -> _ = wxMenu:append(Menu, Id, Title), wxWindow:connect(Window, command_menu_selected, [{id,Id},{userData,{dbg_ui_winman,Win}}]), Id+1. %%==================================================================== %% gen_server callbacks %%==================================================================== init([]) -> process_flag(trap_exit, true), {ok, #state{}}. handle_call({is_started, Title}, _From, State) -> Reply = case lists:keyfind(Title, #win.title, State#state.wins) of false -> false; Win -> {true, Win#win.win} end, {reply, Reply, State}. handle_cast({insert, Pid, Title, Win}, State) -> link(Pid), Wins = State#state.wins ++ [#win{owner=Pid, title=Title, win=Win}], inform_all(Wins), {noreply, State#state{wins=Wins}}; handle_cast({clear_process, Title}, State) -> OldWins = State#state.wins, Wins = case lists:keyfind(Title, #win.title, OldWins) of #win{owner=Pid} -> Msg = {dbg_ui_winman, destroy}, Pid ! Msg, lists:keydelete(Title, #win.title, OldWins); false -> OldWins end, {noreply, State#state{wins=Wins}}. handle_info({'EXIT', Pid, _Reason}, State) -> [Mon | _Wins] = State#state.wins, if Pid =:= Mon#win.owner -> {stop, normal, State}; true -> Wins2 = lists:keydelete(Pid, #win.owner, State#state.wins), inform_all(Wins2), {noreply, State#state{wins=Wins2}} end. terminate(_Reason, State) -> delete_all(State#state.wins), ok. code_change(_OldVsn, State, _Extra) -> {ok, State}. %%==================================================================== %% Internal functions %%==================================================================== inform_all(Wins) -> Infos = lists:map(fun(#win{title=Title, win=Win}) -> {Title, Win} end, Wins), Msg = {dbg_ui_winman, update_windows_menu, Infos}, lists:foreach(fun(#win{owner=Pid}) -> Pid ! Msg end, Wins). delete_all(Wins) -> Msg = {dbg_ui_winman, destroy}, lists:foreach(fun(#win{owner=Pid}) -> Pid ! Msg end, Wins).