2011-09-30 14:15:37 -04:00
|
|
|
/**
|
|
|
|
* @file kicad/mainframe.cpp
|
|
|
|
* @brief KICAD_MANAGER_FRAME is the KiCad main frame.
|
|
|
|
*/
|
2007-10-31 17:47:44 +00:00
|
|
|
|
2012-02-16 21:03:33 +01:00
|
|
|
/*
|
|
|
|
* This program source code file is part of KiCad, a free EDA CAD application.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2012 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
|
2013-01-18 11:42:23 +01:00
|
|
|
* Copyright (C) 2013 CERN (www.cern.ch)
|
2012-02-16 21:03:33 +01:00
|
|
|
* Copyright (C) 2004-2012 KiCad Developers, see change_log.txt for contributors.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, you may find one here:
|
|
|
|
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
|
|
|
|
* or you may search the http://www.gnu.org website for the version 2 license,
|
|
|
|
* or you may write to the Free Software Foundation, Inc.,
|
|
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
2007-10-31 17:47:44 +00:00
|
|
|
|
2012-01-22 22:33:36 -06:00
|
|
|
#include <fctsys.h>
|
|
|
|
#include <appl_wxstruct.h>
|
|
|
|
#include <confirm.h>
|
|
|
|
#include <gestfich.h>
|
2014-02-01 19:27:18 +01:00
|
|
|
#include <macros.h>
|
2007-10-31 17:47:44 +00:00
|
|
|
|
2012-01-22 22:33:36 -06:00
|
|
|
#include <kicad.h>
|
|
|
|
#include <tree_project_frame.h>
|
2012-02-16 21:03:33 +01:00
|
|
|
#include <wildcards_and_files_ext.h>
|
2012-04-09 11:16:47 +02:00
|
|
|
#include <menus_helpers.h>
|
2007-10-31 17:47:44 +00:00
|
|
|
|
|
|
|
|
2009-04-05 20:49:15 +00:00
|
|
|
static const wxString TreeFrameWidthEntry( wxT( "LeftWinWidth" ) );
|
|
|
|
|
2011-04-17 15:54:17 +02:00
|
|
|
KICAD_MANAGER_FRAME::KICAD_MANAGER_FRAME( wxWindow* parent,
|
2011-08-19 11:08:41 -04:00
|
|
|
const wxString& title,
|
|
|
|
const wxPoint& pos,
|
|
|
|
const wxSize& size ) :
|
2012-09-12 11:53:11 +02:00
|
|
|
EDA_BASE_FRAME( parent, KICAD_MAIN_FRAME_TYPE, title, pos, size,
|
2014-02-01 19:27:18 +01:00
|
|
|
KICAD_DEFAULT_DRAWFRAME_STYLE, wxT( "KicadFrame" ) )
|
2007-10-31 17:47:44 +00:00
|
|
|
{
|
2014-02-01 19:27:18 +01:00
|
|
|
m_leftWinWidth = 60;
|
2007-10-31 17:47:44 +00:00
|
|
|
|
|
|
|
// Create the status line (bottom of the frame
|
2009-08-07 04:44:42 +00:00
|
|
|
static const int dims[3] = { -1, -1, 100 };
|
|
|
|
|
2007-10-31 17:47:44 +00:00
|
|
|
CreateStatusBar( 3 );
|
|
|
|
SetStatusWidths( 3, dims );
|
|
|
|
|
|
|
|
// Give an icon
|
2011-09-09 21:30:59 +02:00
|
|
|
wxIcon icon;
|
|
|
|
icon.CopyFromBitmap( KiBitmap( icon_kicad_xpm ) );
|
|
|
|
SetIcon( icon );
|
2007-10-31 17:47:44 +00:00
|
|
|
|
2014-02-01 19:27:18 +01:00
|
|
|
// Give the last sise and pos to main window
|
|
|
|
LoadSettings();
|
|
|
|
SetSize( m_FramePos.x, m_FramePos.y, m_FrameSize.x, m_FrameSize.y );
|
2007-10-31 17:47:44 +00:00
|
|
|
|
|
|
|
// Left window: is the box which display tree project
|
2010-02-19 15:01:32 +00:00
|
|
|
m_LeftWin = new TREE_PROJECT_FRAME( this );
|
2010-01-13 21:15:54 +00:00
|
|
|
|
2014-02-01 19:27:18 +01:00
|
|
|
// Right top Window: buttons to launch applications
|
|
|
|
m_Launcher = new LAUNCHER_PANEL( this );
|
|
|
|
// Add the wxTextCtrl showing all messages from KiCad:
|
|
|
|
m_MessagesBox = new wxTextCtrl( this, wxID_ANY, wxEmptyString,
|
|
|
|
wxDefaultPosition, wxDefaultSize,
|
|
|
|
wxTE_MULTILINE | wxSUNKEN_BORDER | wxTE_READONLY );
|
2007-10-31 17:47:44 +00:00
|
|
|
|
2009-11-02 22:24:55 +00:00
|
|
|
RecreateBaseHToolbar();
|
2013-01-01 15:06:49 +01:00
|
|
|
ReCreateMenuBar();
|
2009-11-02 22:24:55 +00:00
|
|
|
|
2009-11-18 20:12:11 +00:00
|
|
|
m_auimgr.SetManagedWindow( this );
|
2009-11-04 19:08:08 +00:00
|
|
|
|
2014-02-01 19:27:18 +01:00
|
|
|
EDA_PANEINFO horiztb;
|
|
|
|
horiztb.HorizontalToolbarPane();
|
2011-09-15 14:25:44 -04:00
|
|
|
|
|
|
|
EDA_PANEINFO info;
|
|
|
|
info.InfoToolbarPane();
|
2010-01-13 21:15:54 +00:00
|
|
|
|
2014-02-01 19:27:18 +01:00
|
|
|
m_auimgr.AddPane( m_mainToolBar,
|
|
|
|
wxAuiPaneInfo( horiztb ).Name( wxT( "m_mainToolBar" ) ).Top() );
|
|
|
|
|
|
|
|
m_auimgr.AddPane( m_LeftWin,
|
|
|
|
wxAuiPaneInfo(info).Name( wxT( "m_LeftWin" ) ).Left().
|
|
|
|
BestSize( m_leftWinWidth, -1 ).
|
|
|
|
Layer( 1 ) );
|
2010-01-13 21:15:54 +00:00
|
|
|
|
2014-02-01 19:27:18 +01:00
|
|
|
m_auimgr.AddPane( m_Launcher, wxTOP );
|
|
|
|
m_auimgr.GetPane( m_Launcher).CaptionVisible( false ).Row(1)
|
|
|
|
.BestSize( -1, m_Launcher->GetPanelHeight() ).PaneBorder( false ).Resizable( false );
|
2010-01-13 21:15:54 +00:00
|
|
|
|
2014-02-01 19:27:18 +01:00
|
|
|
m_auimgr.AddPane( m_MessagesBox,
|
|
|
|
wxAuiPaneInfo().Name( wxT( "m_MessagesBox" ) ).CentrePane().Layer( 2 ) );
|
|
|
|
|
|
|
|
m_auimgr.GetPane( m_LeftWin ).MinSize( wxSize( 80, -1) );
|
|
|
|
m_auimgr.GetPane( m_LeftWin ).BestSize(wxSize(m_leftWinWidth, -1) );
|
2011-10-27 07:43:44 +02:00
|
|
|
|
2009-11-02 22:24:55 +00:00
|
|
|
m_auimgr.Update();
|
2007-10-31 17:47:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-04-17 15:54:17 +02:00
|
|
|
KICAD_MANAGER_FRAME::~KICAD_MANAGER_FRAME()
|
2007-10-31 17:47:44 +00:00
|
|
|
{
|
2009-11-18 20:12:11 +00:00
|
|
|
m_auimgr.UnInit();
|
2007-10-31 17:47:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-08-19 11:08:41 -04:00
|
|
|
void KICAD_MANAGER_FRAME::PrintMsg( const wxString& aText )
|
2007-10-31 17:47:44 +00:00
|
|
|
{
|
2014-02-01 19:27:18 +01:00
|
|
|
m_MessagesBox->AppendText( aText );
|
2007-10-31 17:47:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-04-17 15:54:17 +02:00
|
|
|
void KICAD_MANAGER_FRAME::OnSize( wxSizeEvent& event )
|
2007-10-31 17:47:44 +00:00
|
|
|
{
|
2009-11-18 20:12:11 +00:00
|
|
|
if( m_auimgr.GetManagedWindow() )
|
|
|
|
m_auimgr.Update();
|
2007-10-31 17:47:44 +00:00
|
|
|
|
2008-07-21 13:44:01 +00:00
|
|
|
event.Skip();
|
2007-10-31 17:47:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-04-17 15:54:17 +02:00
|
|
|
void KICAD_MANAGER_FRAME::OnCloseWindow( wxCloseEvent& Event )
|
2007-10-31 17:47:44 +00:00
|
|
|
{
|
|
|
|
int px, py;
|
|
|
|
|
2011-03-17 20:14:45 +01:00
|
|
|
UpdateFileHistory( m_ProjectFileName.GetFullPath() );
|
2007-10-31 17:47:44 +00:00
|
|
|
|
|
|
|
if( !IsIconized() ) // save main frame position and size
|
|
|
|
{
|
|
|
|
GetPosition( &px, &py );
|
|
|
|
m_FramePos.x = px;
|
|
|
|
m_FramePos.y = py;
|
|
|
|
|
|
|
|
GetSize( &px, &py );
|
|
|
|
m_FrameSize.x = px;
|
|
|
|
m_FrameSize.y = py;
|
|
|
|
}
|
|
|
|
|
2011-08-19 11:08:41 -04:00
|
|
|
Event.SetCanVeto( true );
|
2007-10-31 17:47:44 +00:00
|
|
|
|
|
|
|
// Close the help frame
|
2011-12-16 15:12:49 -05:00
|
|
|
if( wxGetApp().GetHtmlHelpController() )
|
2007-10-31 17:47:44 +00:00
|
|
|
{
|
2011-12-16 15:12:49 -05:00
|
|
|
if( wxGetApp().GetHtmlHelpController()->GetFrame() ) // returns NULL if no help frame active
|
|
|
|
wxGetApp().GetHtmlHelpController()->GetFrame()->Close( true );
|
2011-08-19 11:08:41 -04:00
|
|
|
|
2011-12-16 15:12:49 -05:00
|
|
|
wxGetApp().SetHtmlHelpController( NULL );
|
2007-10-31 17:47:44 +00:00
|
|
|
}
|
2008-12-08 15:27:13 +00:00
|
|
|
|
2009-11-18 20:12:11 +00:00
|
|
|
m_LeftWin->Show( false );
|
2007-10-31 17:47:44 +00:00
|
|
|
|
|
|
|
Destroy();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-04-17 15:54:17 +02:00
|
|
|
void KICAD_MANAGER_FRAME::OnExit( wxCommandEvent& event )
|
2007-10-31 17:47:44 +00:00
|
|
|
{
|
2009-04-05 20:49:15 +00:00
|
|
|
Close( true );
|
|
|
|
}
|
2007-10-31 17:47:44 +00:00
|
|
|
|
2011-08-19 11:08:41 -04:00
|
|
|
|
2013-01-18 11:42:23 +01:00
|
|
|
void KICAD_MANAGER_FRAME::PROCESS_TERMINATE_EVENT_HANDLER::
|
|
|
|
OnTerminate( int pid, int status )
|
|
|
|
{
|
|
|
|
|
|
|
|
wxString msg;
|
|
|
|
|
|
|
|
msg.Printf( appName + _( " closed [pid=%d]\n" ), pid );
|
|
|
|
( (KICAD_MANAGER_FRAME*) wxGetApp().GetTopWindow() )->PrintMsg( msg );
|
|
|
|
|
|
|
|
delete this;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void KICAD_MANAGER_FRAME::Execute( wxWindow* frame, const wxString& execFile,
|
|
|
|
const wxString& param )
|
|
|
|
{
|
|
|
|
|
|
|
|
PROCESS_TERMINATE_EVENT_HANDLER* callback;
|
|
|
|
long pid;
|
|
|
|
wxString msg;
|
|
|
|
|
|
|
|
callback = new PROCESS_TERMINATE_EVENT_HANDLER( execFile );
|
|
|
|
pid = ExecuteFile( frame, execFile, param, callback );
|
|
|
|
|
|
|
|
if( pid > 0 )
|
|
|
|
{
|
|
|
|
msg.Printf( execFile + _( " opened [pid=%ld]\n" ), pid );
|
|
|
|
PrintMsg( msg );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
delete callback;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-04-17 15:54:17 +02:00
|
|
|
void KICAD_MANAGER_FRAME::OnRunBitmapConverter( wxCommandEvent& event )
|
2010-07-11 18:24:44 +02:00
|
|
|
{
|
2013-01-18 11:42:23 +01:00
|
|
|
Execute( this, BITMAPCONVERTER_EXE );
|
2010-07-11 18:24:44 +02:00
|
|
|
}
|
|
|
|
|
2011-08-19 11:08:41 -04:00
|
|
|
|
2011-08-05 21:53:42 +02:00
|
|
|
void KICAD_MANAGER_FRAME::OnRunPcbCalculator( wxCommandEvent& event )
|
|
|
|
{
|
2013-01-18 11:42:23 +01:00
|
|
|
Execute( this, PCB_CALCULATOR_EXE );
|
2011-08-05 21:53:42 +02:00
|
|
|
}
|
2007-10-31 17:47:44 +00:00
|
|
|
|
2013-07-19 20:27:22 +02:00
|
|
|
void KICAD_MANAGER_FRAME::OnRunPageLayoutEditor( wxCommandEvent& event )
|
|
|
|
{
|
|
|
|
Execute( this, PL_EDITOR_EXE );
|
|
|
|
}
|
|
|
|
|
2011-08-19 11:08:41 -04:00
|
|
|
|
2011-04-17 15:54:17 +02:00
|
|
|
void KICAD_MANAGER_FRAME::OnRunPcbNew( wxCommandEvent& event )
|
2009-04-05 20:49:15 +00:00
|
|
|
{
|
2012-12-14 10:54:54 -06:00
|
|
|
wxFileName legacy_board( m_ProjectFileName );
|
|
|
|
wxFileName kicad_board( m_ProjectFileName );
|
|
|
|
|
|
|
|
legacy_board.SetExt( LegacyPcbFileExtension );
|
|
|
|
kicad_board.SetExt( KiCadPcbFileExtension );
|
2009-11-18 20:12:11 +00:00
|
|
|
|
2012-12-14 10:54:54 -06:00
|
|
|
if( !legacy_board.FileExists() || kicad_board.FileExists() )
|
2013-01-18 11:42:23 +01:00
|
|
|
Execute( this, PCBNEW_EXE, QuoteFullPath( kicad_board ) );
|
2012-12-14 10:54:54 -06:00
|
|
|
else
|
2013-01-18 11:42:23 +01:00
|
|
|
Execute( this, PCBNEW_EXE, QuoteFullPath( legacy_board ) );
|
2007-10-31 17:47:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-04-17 15:54:17 +02:00
|
|
|
void KICAD_MANAGER_FRAME::OnRunCvpcb( wxCommandEvent& event )
|
2007-10-31 17:47:44 +00:00
|
|
|
{
|
2009-04-05 20:49:15 +00:00
|
|
|
wxFileName fn( m_ProjectFileName );
|
2009-11-18 20:12:11 +00:00
|
|
|
|
2009-04-05 20:49:15 +00:00
|
|
|
fn.SetExt( NetlistFileExtension );
|
2013-01-18 11:42:23 +01:00
|
|
|
Execute( this, CVPCB_EXE, QuoteFullPath( fn ) );
|
2009-04-05 20:49:15 +00:00
|
|
|
}
|
2007-10-31 17:47:44 +00:00
|
|
|
|
2011-04-17 15:54:17 +02:00
|
|
|
void KICAD_MANAGER_FRAME::OnRunEeschema( wxCommandEvent& event )
|
2009-04-05 20:49:15 +00:00
|
|
|
{
|
|
|
|
wxFileName fn( m_ProjectFileName );
|
2009-11-18 20:12:11 +00:00
|
|
|
|
2009-04-05 20:49:15 +00:00
|
|
|
fn.SetExt( SchematicFileExtension );
|
2013-01-18 11:42:23 +01:00
|
|
|
Execute( this, EESCHEMA_EXE, QuoteFullPath( fn ) );
|
2007-10-31 17:47:44 +00:00
|
|
|
|
2013-01-18 11:42:23 +01:00
|
|
|
}
|
2007-10-31 17:47:44 +00:00
|
|
|
|
2011-04-17 15:54:17 +02:00
|
|
|
void KICAD_MANAGER_FRAME::OnRunGerbview( wxCommandEvent& event )
|
2009-04-05 20:49:15 +00:00
|
|
|
{
|
|
|
|
wxFileName fn( m_ProjectFileName );
|
2011-08-19 11:08:41 -04:00
|
|
|
wxString path = wxT( "\"" );
|
|
|
|
path += fn.GetPath( wxPATH_GET_SEPARATOR | wxPATH_GET_VOLUME ) + wxT( "\"" );
|
2009-11-18 20:12:11 +00:00
|
|
|
|
2013-01-18 11:42:23 +01:00
|
|
|
Execute( this, GERBVIEW_EXE, path );
|
2009-04-05 20:49:15 +00:00
|
|
|
}
|
2007-10-31 17:47:44 +00:00
|
|
|
|
|
|
|
|
2011-04-17 15:54:17 +02:00
|
|
|
void KICAD_MANAGER_FRAME::OnOpenTextEditor( wxCommandEvent& event )
|
2009-04-05 20:49:15 +00:00
|
|
|
{
|
|
|
|
wxString editorname = wxGetApp().GetEditorName();
|
|
|
|
|
|
|
|
if( !editorname.IsEmpty() )
|
2013-01-18 11:42:23 +01:00
|
|
|
Execute( this, editorname, wxEmptyString );
|
2009-04-05 20:49:15 +00:00
|
|
|
}
|
|
|
|
|
2007-10-31 17:47:44 +00:00
|
|
|
|
2011-04-17 15:54:17 +02:00
|
|
|
void KICAD_MANAGER_FRAME::OnOpenFileInTextEditor( wxCommandEvent& event )
|
2009-04-05 20:49:15 +00:00
|
|
|
{
|
|
|
|
wxString mask( wxT( "*" ) );
|
2009-11-18 20:12:11 +00:00
|
|
|
|
2007-10-31 17:47:44 +00:00
|
|
|
#ifdef __WINDOWS__
|
2009-04-05 20:49:15 +00:00
|
|
|
mask += wxT( ".*" );
|
2007-10-31 17:47:44 +00:00
|
|
|
#endif
|
|
|
|
|
2009-04-05 20:49:15 +00:00
|
|
|
mask = _( "Text file (" ) + mask + wxT( ")|" ) + mask;
|
2012-12-31 09:12:29 +01:00
|
|
|
wxString default_dir = wxGetCwd();
|
2007-10-31 17:47:44 +00:00
|
|
|
|
2012-12-31 09:12:29 +01:00
|
|
|
wxFileDialog dlg( this, _( "Load File to Edit" ), default_dir,
|
2009-11-18 20:12:11 +00:00
|
|
|
wxEmptyString, mask, wxFD_OPEN );
|
2009-04-05 20:49:15 +00:00
|
|
|
|
2009-04-09 09:00:23 +00:00
|
|
|
if( dlg.ShowModal() == wxID_CANCEL )
|
|
|
|
return;
|
|
|
|
|
2011-08-19 11:08:41 -04:00
|
|
|
wxString filename = wxT( "\"" );
|
|
|
|
filename += dlg.GetPath() + wxT( "\"" );
|
|
|
|
|
2009-11-18 20:12:11 +00:00
|
|
|
if( !dlg.GetPath().IsEmpty() && !wxGetApp().GetEditorName().IsEmpty() )
|
2013-01-18 11:42:23 +01:00
|
|
|
Execute( this, wxGetApp().GetEditorName(), filename );
|
2007-10-31 17:47:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-04-17 15:54:17 +02:00
|
|
|
void KICAD_MANAGER_FRAME::OnRefresh( wxCommandEvent& event )
|
2007-10-31 17:47:44 +00:00
|
|
|
{
|
|
|
|
m_LeftWin->ReCreateTreePrj();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-04-17 15:54:17 +02:00
|
|
|
void KICAD_MANAGER_FRAME::ClearMsg()
|
2007-10-31 17:47:44 +00:00
|
|
|
{
|
2014-02-01 19:27:18 +01:00
|
|
|
m_MessagesBox->Clear();
|
2007-10-31 17:47:44 +00:00
|
|
|
}
|
|
|
|
|
2008-11-02 14:54:53 +00:00
|
|
|
|
2011-04-17 15:54:17 +02:00
|
|
|
void KICAD_MANAGER_FRAME::LoadSettings()
|
2009-04-05 20:49:15 +00:00
|
|
|
{
|
2011-12-16 15:12:49 -05:00
|
|
|
wxConfig* cfg = wxGetApp().GetSettings();
|
2009-04-05 20:49:15 +00:00
|
|
|
|
2014-02-01 19:27:18 +01:00
|
|
|
if( cfg )
|
|
|
|
{
|
|
|
|
EDA_BASE_FRAME::LoadSettings();
|
|
|
|
cfg->Read( TreeFrameWidthEntry, &m_leftWinWidth );
|
|
|
|
}
|
2009-04-05 20:49:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-04-17 15:54:17 +02:00
|
|
|
void KICAD_MANAGER_FRAME::SaveSettings()
|
2009-04-05 20:49:15 +00:00
|
|
|
{
|
2011-12-16 15:12:49 -05:00
|
|
|
wxConfig* cfg = wxGetApp().GetSettings();
|
2009-04-05 20:49:15 +00:00
|
|
|
|
2014-02-01 19:27:18 +01:00
|
|
|
if( cfg )
|
|
|
|
{
|
|
|
|
EDA_BASE_FRAME::SaveSettings();
|
|
|
|
cfg->Write( TreeFrameWidthEntry, m_LeftWin->GetSize().x );
|
|
|
|
}
|
|
|
|
}
|
2009-04-05 20:49:15 +00:00
|
|
|
|
2014-02-01 19:27:18 +01:00
|
|
|
/**
|
|
|
|
* a minor helper function:
|
|
|
|
* Prints the Current Working Dir name and the projet name on the text panel.
|
|
|
|
*/
|
|
|
|
void KICAD_MANAGER_FRAME::PrintPrjInfo()
|
|
|
|
{
|
|
|
|
wxString msg;
|
|
|
|
msg.Printf( _( "Working dir: %s\nProject: %s\n" ),
|
|
|
|
GetChars( wxGetCwd() ),
|
|
|
|
GetChars( m_ProjectFileName.GetFullPath() ) );
|
|
|
|
PrintMsg( msg );
|
2009-04-05 20:49:15 +00:00
|
|
|
}
|