%%
%% %CopyrightBegin%
%% 
%% Copyright Ericsson AB 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%
%%%
%%% Description : Testing and demo xrc's
%%%               This mimics the xrc demo from wxwidgets.
%%% Created :  4 Dec 2007 by Dan Gudmundsson <dgud@erix.ericsson.se>
%%%-------------------------------------------------------------------

-module(xrc).
-compile(export_all).

-include("../../include/wx.hrl").


%% I've put all "classes" in the same file,  but you can see the follow
%% the code in xrcdemo from the samples directory in wxWidgets src package

start() ->
    %% Starts wxwidgets
    WX = wx:new(),
    %% In erlang wx, all image handlers are initilized already.
    %% wxImage::AddHandler(new wxXPMHandler);
    
    %% Initialize all the XRC handlers. Always required (unless you feel like
    %% going through and initializing a handler of each control type you will
    %% be using (ie initialize the spinctrl handler, initialize the textctrl
    %% handler). However, if you are only using a few control types, it will
    %% save some space to only initialize the ones you will be using. See
    %% wxXRC docs for details.

    Xrc = wxXmlResource:get(),
    wxXmlResource:initAllHandlers(Xrc),
    true = wxXmlResource:load(Xrc, rc_dir("menu.xrc")),
    true = wxXmlResource:load(Xrc, rc_dir("toolbar.xrc")),
    true = wxXmlResource:load(Xrc, rc_dir("basicdlg.xrc")),
    true = wxXmlResource:load(Xrc, rc_dir("derivdlg.xrc")),
    true = wxXmlResource:load(Xrc, rc_dir("controls.xrc")),
    true = wxXmlResource:load(Xrc, rc_dir("frame.xrc")),
    true = wxXmlResource:load(Xrc, rc_dir("uncenter.xrc")),
    true = wxXmlResource:load(Xrc, rc_dir("custclas.xrc")),
    true = wxXmlResource:load(Xrc, rc_dir("artprov.xrc")),
    true = wxXmlResource:load(Xrc, rc_dir("platform.xrc")),
    true = wxXmlResource:load(Xrc, rc_dir("variable.xrc")),
    Frame = wxFrame:new(),
    myframe(WX,Frame),
    wxFrame:show(Frame),
    loop(Frame),
    wx:destroy().

rc_dir(File) ->
  SelfDir = filename:dirname(code:which(?MODULE)),
  filename:join([SelfDir,rc,File]).

loop(Frame) ->
    receive 
	#wx{id=Id, event=#wxCommand{}} ->
	    handle_cmd(get(Id), Id, Frame),
	    loop(Frame);
	#wx{event=#wxClose{}} ->
	    catch wxWindows:'Destroy'(Frame),
	    ok;
	Ev = #wx{} ->
	    io:format("Got ~p ~n", [Ev]),
	    loop(Frame)
    end.

myframe(Parent, Frame) ->
    Xrc = wxXmlResource:get(),
    wxXmlResource:loadFrame(Xrc, Frame, Parent, "main_frame"),
    %% wxTopLevelWindow:setIcon(Frame, wxXmlResource:loadIcon(Xrc,"appicon")),
    %% Load and setup menubar
    wxFrame:setMenuBar(Frame, wxXmlResource:loadMenuBar(Xrc, "main_menu")),
    %% hmm wxSystemOptions::SetOption ( wxT("msw.remap"), 0 );
    wxFrame:setToolBar(Frame, wxXmlResource:loadToolBar(Xrc, Frame, "main_toolbar")),
    wxFrame:createStatusBar(Frame, [{number,1}]),
    ok = wxFrame:connect(Frame, close_window), 
    connect(Frame).
  
connect(Frame) ->    
    Menues = [unload_resource_menuitem, reload_resource_menuitem,
	      non_derived_dialog_tool_or_menuitem, derived_tool_or_menuitem,
	      controls_tool_or_menuitem, uncentered_tool_or_menuitem,
	      custom_class_tool_or_menuitem, platform_property_tool_or_menuitem,
	      art_provider_tool_or_menuitem, variable_expansion_tool_or_menuitem
	     ],
    wxFrame:connect(Frame,command_menu_selected, [{id, ?wxID_EXIT}]),
    wxFrame:connect(Frame,command_menu_selected, [{id, ?wxID_ABOUT}]),
    [connect_xrcid(Str,Frame) || Str <- Menues],
    ok.

connect_xrcid(Name,Frame) ->
    ID = wxXmlResource:getXRCID(atom_to_list(Name)),
    put(ID, Name),
    wxFrame:connect(Frame,command_menu_selected,[{id,ID}]).

%% Handle commands
    
handle_cmd(unload_resource_menuitem, _, _Frame) ->
    Xrc = wxXmlResource:get(),
    case wxXmlResource:unload(Xrc, "rc/basicdlg") of
	true -> 
	    io:format("Basic dialog unloaded~n",[]);
	false ->
	    io:format("Failed to unload basic dialog~n",[])
    end;

handle_cmd(reload_resource_menuitem, _, _Frame) ->
    Xrc = wxXmlResource:get(),
    case wxXmlResource:reload(Xrc, "rc/basicdlg") of
	true -> 
	    io:format("Basic dialog reloaded~n",[]);
	false ->
	    io:format("Failed to reload basic dialog~n",[])
    end;

handle_cmd(_, ?wxID_EXIT, Frame) ->
    wxFrame:close(Frame);

handle_cmd(non_derived_dialog_tool_or_menuitem, _, Frame) ->
    Xrc = wxXmlResource:get(),
    Dlg = wxDialog:new(),
    %% "non_derived_dialog" is the name of the wxDialog XRC node that should
    %% be loaded.
    case wxXmlResource:loadDialog(Xrc, Dlg, Frame, "non_derived_dialog") of
	true ->
	    wxDialog:showModal(Dlg);
	false ->
	    io:format("Failed to load non_derived_dialog~n",[])
    end,    
    %% In Erlang you should delete the dialog afterwards
    wxDialog:destroy(Dlg);

handle_cmd(derived_tool_or_menuitem, _, Frame) ->
    Pref = prefDialog(Frame),
    wxDialog:showModal(Pref);

handle_cmd(animation_ctrl_play, _, _Frame) ->
    %% Not yet implemented
    ok;

handle_cmd(controls_tool_or_menuitem,_,Frame) ->
    Xrc = wxXmlResource:get(),
    Dlg = wxDialog:new(),
    true = wxXmlResource:loadDialog(Xrc, Dlg, Frame, "controls_dialog"),
    
    LCtrl = wxXmlResource:xrcctrl(Dlg, "controls_listctrl", wxListCtrl),
    wxListCtrl:insertColumn(LCtrl, 0, "Name", [{width, 200}]), 
    wxListCtrl:insertItem(LCtrl, 0, "Todd Hope"),
    wxListCtrl:insertItem(LCtrl, 1, "Kim Wynd"),
    wxListCtrl:insertItem(LCtrl, 2, "Leon Li"),

    TCtrl = wxXmlResource:xrcctrl(Dlg, "controls_treectrl", wxTreeCtrl),
    wxTreeCtrl:addRoot(TCtrl, "Godfather"),
    TRoot = wxTreeCtrl:getRootItem(TCtrl),
    wxTreeCtrl:appendItem(TCtrl,TRoot, "Evil henchmen 1"), 
    wxTreeCtrl:appendItem(TCtrl,TRoot, "Evil henchmen 2"), 
    wxTreeCtrl:appendItem(TCtrl,TRoot, "Evil accountant"), 

    wxDialog:showModal(Dlg),
    wxDialog:destroy(Dlg);

handle_cmd(uncentered_tool_or_menuitem,_,Frame) ->
    Xrc = wxXmlResource:get(),
    Dlg = wxDialog:new(),
    true = wxXmlResource:loadDialog(Xrc, Dlg, Frame, "uncentered_dialog"),
    wxDialog:showModal(Dlg),
    wxDialog:destroy(Dlg);

handle_cmd(custom_class_tool_or_menuitem,_,Frame) ->
    Xrc = wxXmlResource:get(),
    Dlg = wxDialog:new(),
    true = wxXmlResource:loadDialog(Xrc, Dlg, Frame, "custom_class_dialog"),

    ResizeableLC = myResizeableListCtrl(Dlg, ?wxID_ANY, {-1,-1}, {-1,-1},?wxLC_REPORT),
    %% "custom_control_placeholder" is the name of the "unknown" tag in the
    %% custctrl.xrc XRC file.
    wxXmlResource:attachUnknownControl(Xrc, "custom_control_placeholder", ResizeableLC),
    wxDialog:showModal(Dlg),
    wxDialog:destroy(Dlg);

handle_cmd(platform_property_tool_or_menuitem, _, Frame) ->
    Xrc = wxXmlResource:get(),
    Dlg = wxDialog:new(),
    true = wxXmlResource:loadDialog(Xrc, Dlg, Frame, "platform_property_dialog"),
    wxDialog:showModal(Dlg),
    wxDialog:destroy(Dlg);

handle_cmd(art_provider_tool_or_menuitem, _, Frame) ->
    Xrc = wxXmlResource:get(),
    Dlg = wxDialog:new(),
    true = wxXmlResource:loadDialog(Xrc, Dlg, Frame, "art_provider_dialog"),
    wxDialog:showModal(Dlg),
    wxDialog:destroy(Dlg);

handle_cmd(variable_expansion_tool_or_menuitem, _, Frame) ->
    Xrc = wxXmlResource:get(),
    Dlg = wxDialog:new(),
    true = wxXmlResource:loadDialog(Xrc, Dlg, Frame, "variable_expansion_dialog"),
    wxDialog:showModal(Dlg),
    wxDialog:destroy(Dlg);
handle_cmd(_, ?wxID_ABOUT, Frame) ->
    Msg = "This is the about dialog of XML resources demo.\n",
    MD = wxMessageDialog:new(Frame,Msg,
			     [{style, ?wxOK bor ?wxICON_INFORMATION}, 
			      {caption, "About"}]),
    wxDialog:showModal(MD),
    wxDialog:destroy(MD);
handle_cmd(Dialog, Id, _) ->
    io:format("Not implemented yet ~p (~p) ~n",[Dialog, Id]).
   

%%%%%%%%%%%%%%%%
%% Trying to mimic the derived dialog example
%%%%%%%%%%%%%%%%
 
prefDialog(Parent) ->    
    Xrc = wxXmlResource:get(),
    Dlg = wxDialog:new(),
    true = wxXmlResource:loadDialog(Xrc, Dlg, Parent, "derived_dialog"),

    %% Shows that callbacks can be used it doesn't need to though.
    OnMyButtonClicked = fun(_EvRec, _wxEvent) ->
				MD = wxMessageDialog:new(Dlg, "You clicked on My Button"),
				wxMessageDialog:showModal(MD),
				wxMessageDialog:destroy(MD)
			end,
    wxDialog:connect(Dlg, command_button_clicked, 
		     [{id,wxXmlResource:getXRCID("my_button")},
		      {callback,OnMyButtonClicked}]),

    OnMyCheckBox = fun(_EvRec, _Event) ->
			   CheckB = wxXmlResource:xrcctrl(Dlg, "my_checkbox", wxCheckBox),
			   Text = wxXmlResource:xrcctrl(Dlg, "my_textctrl", wxTextCtrl),
			   Bool = wxCheckBox:isChecked(CheckB),
			   wxTextCtrl:enable(Text, [{enable,Bool}])
		   end,
    wxDialog:connect(Dlg,update_ui,[{id,wxXmlResource:getXRCID("my_checkbox")},
				    {callback,OnMyCheckBox}]),

    %% Keep updateUI event interval at 250ms
    wxUpdateUIEvent:setUpdateInterval(250),
    
    OnOk = fun(_,_) ->
		   Str = 
		       "Press Ok to close derived dialog, or Cancel to abort"
		       "Overriding base class ok button handler",
		   MD = wxMessageDialog:new(Dlg, Str, [{style, ?wxOK bor ?wxCANCEL bor ?wxCENTER}]),
		   case wxMessageDialog:showModal(MD) of
		       ?wxID_OK -> 
			   wxMessageDialog:endModal(Dlg, ?wxID_OK);
		       _R ->
			   ignore
		   end,
		   wxMessageDialog:destroy(MD)
	   end,
    wxDialog:connect(Dlg,command_button_clicked,[{id,?wxID_OK},{callback,OnOk}]),
    Dlg.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

-define(RECORD_COLUMN,  0).
-define(ACTION_COLUMN,  1).
-define(PRIORITY_COLUMN,2).

-define(PU_ADD_RECORD,     ?wxID_HIGHEST+1).
-define(PU_EDIT_RECORD,    ?wxID_HIGHEST+2).
-define(PU_DELETE_RECORD,  ?wxID_HIGHEST+3).

myResizeableListCtrl(Parent,Id,Pos,Size,Style) -> 
    LC = wxListCtrl:new(Parent, [{winid,Id}, {pos,Pos}, {size,Size}, {style,Style}]),
    wxListCtrl:insertColumn(LC,?RECORD_COLUMN, "Record", [{width, 140}]),
    wxListCtrl:insertColumn(LC,?ACTION_COLUMN, "Action", [{width, 70}]),
    wxListCtrl:insertColumn(LC,?PRIORITY_COLUMN, "Priority", [{width, 70}]),
    wxListCtrl:connect(LC, right_down, [{id,Id}, {callback, fun lc_onRightClick/2}]),
    wxListCtrl:connect(LC, size, [{id,Id}, {callback, fun lc_onSize/2}]),
    LC.
    
lc_onRightClick(#wx{obj=ListCtrl, event=#wxMouse{x=X,y=Y}},_Ev) ->
    Menu = wxMenu:new(),
    wxMenu:append(Menu, ?PU_ADD_RECORD, "Add a new record"),
    wxMenu:append(Menu, ?PU_EDIT_RECORD,"Edit selected record"),
    wxMenu:append(Menu, ?PU_DELETE_RECORD, "Delete selected record"),
    case wxListCtrl:getSelectedItemCount(ListCtrl) of
	0 ->
	    wxMenu:enable(Menu, ?PU_EDIT_RECORD, false),
	    wxMenu:enable(Menu, ?PU_DELETE_RECORD, false);
	_ ->
	    ignore
    end,
    MenuCB = fun(_,_) -> io:format("Menu selected~n",[]) end,
    wxWindow:connect(ListCtrl, command_menu_selected, [{callback, MenuCB}]),
    wxWindow:popupMenu(ListCtrl, Menu, [{pos, {X,Y}}]),
    wxMenu:destroy(Menu).
    
lc_onSize(#wx{obj=ListCtrl},EvObj) ->
    {LeftMostColW0,_} = wxListCtrl:getSize(ListCtrl),
    LeftMostColW1 = LeftMostColW0 - wxListCtrl:getColumnWidth(ListCtrl, ?ACTION_COLUMN),
    LeftMostColW2 = LeftMostColW1 - wxListCtrl:getColumnWidth(ListCtrl, ?PRIORITY_COLUMN),
    %% Hmm missing wxSystemSettings::GetMetric( wxSYS_VSCROLL_X );
    LeftMostColW = LeftMostColW2 - 5,  
    wxListCtrl:setColumnWidth(ListCtrl, ?RECORD_COLUMN, LeftMostColW),
    %% REQURED event.Skip() call to allow this event to propagate
    %% upwards so others can do what they need to do in response to
    %% this size event.
    wxEvent:skip(EvObj),
    io:format("Successfully set column width~n").

%%%%%
