%%
%% %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%
%%
-module(pman_tool).

%% Listbox selection window

-export([select/3]).

-record(state, {topwin,
		frame,
		listbox}).

%% Constants
-define(WIN_WIDTH, 350).
-define(WIN_HEIGHT, 350).

select(Win, Title, Choices) ->
    Self = self(),
    Pid = spawn_link(fun() -> init(Self, Win, Title, Choices) end),
    receive 
	{Pid, Result} ->
	    Result
    end.

init(Pid, Win, Title, Choices) ->

    %% Create window
    State = create_window(Win, Title, Choices),

    gse:map(State#state.topwin),
    
    %% enter event loop
    loop(Pid, Choices, State).

loop(Pid, Choices, State) ->
    receive
	{gs, _, destroy, _Data, _Args} ->
	    Pid ! {self(), cancelled};
	{gs, _, configure, _Data, [W, H|_]} ->
	    gse:resize(State#state.frame, W, H),
	    loop(Pid, Choices, State);
	{gs, _, click, ok, _Args} ->
	    case gs:read(State#state.listbox, selection) of
		[] ->
		    Pid ! {self(), cancelled};
		Indices ->
		    Selection = selection(Indices, Choices),
		    Pid ! {self(), Selection}
	    end;
	{gs, _, click, cancel, _Args} ->
	    Pid ! {self(), cancelled};
	{gs, Obj, doubleclick, _Data, _Args} ->
	    self() ! {gs, Obj, click, ok, []},
	    loop(Pid, Choices, State);
	_GSEvent ->
	    loop(Pid, Choices, State)
    end.

selection(Indices, Choices) ->
    selection(0, Indices, Choices).

selection(I, [I|Is], [{Val,_Str}|Vals]) ->
    [Val | selection(I+1, Is, Vals)];
selection(I, [I|Is], [Val|Vals]) ->
    [Val | selection(I+1, Is, Vals)];
selection(_I, [], _Vals) ->
    [];
selection(I, Is, [_Val|Vals]) ->
    selection(I+1, Is, Vals).
    
create_window(Win, Title, Choices) ->
    Font = pman_win:font(Win),

    %% Top window and a frame that covers it entirely, to allow
    %% usage of the packer for geometry management.
    Topwin = gse:window(Win, [{width, ?WIN_WIDTH},
			      {height,?WIN_HEIGHT},
			      {configure, true},
			      {title, Title}]),
    Frame = gse:frame(Topwin, [{packer_x,[{stretch,1},
					  {stretch,1}]},
			       {packer_y,[{stretch,1},
					  {stretch,5},
					  {stretch,1}]}]),

    %% Caption above the list of items
    CaptionTxt = "Select one or more of the following:",
    gse:label(Frame, [{pack_x,{1,2}},
		      {pack_y,{1,1}},
		      {label,{text,CaptionTxt}}, {font,Font}]),

    %% List of selectable items
    Listbox = gse:listbox(Frame, [{pack_x,{1,2}},
				  {pack_y,{2,2}},
				  {selectmode,multiple},
				  {doubleclick, true},
				  {font,Font},
				  {items, str_choices(Choices)}]),

    %% OK and Cancel buttons in a separate frame.
    F13 = gse:frame(Frame, [{bw,1},
			    {pack_xy,{{1,2},3}},
			    {packer_x,[{stretch,1},
				       {fixed, 60},
				       {stretch,1},
				       {fixed, 60},
				       {stretch,1}]},
			    {packer_y,[{stretch,1},
				       {fixed, 30},
				       {stretch,1}]}]),

    gse:button(F13, [{pack_xy,{2,2}},
		     {label,{text,"OK"}}, {font,Font},
		     {data,ok}]),
    gse:button(F13, [{pack_xy,{4,2}},
		     {label,{text,"Cancel"}}, {font,Font},
		     {data,cancel}]),

    gse:resize(Frame, ?WIN_WIDTH, ?WIN_HEIGHT),
    #state{topwin=Topwin, frame=Frame, listbox=Listbox}.

str_choices(Choices) ->
    lists:map(
      fun({Val, Str}) ->
	      lists:flatten(io_lib:format("~p: ~s", [Val, Str]));
	 (Term) ->
	      lists:flatten(io_lib:format("~p", [Term]))
      end,
      Choices).