/*=========================================================================

  Program:   WXDialog - wxWidgets X-platform GUI Front-End for CMake
  Module:    $RCSfile$
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Author:    Jorgen Bodde

  Copyright (c) 2002 Kitware, Inc., Insight Consortium.  All rights reserved.
  See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.

     This software is distributed WITHOUT ANY WARRANTY; without even 
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#if defined(__GNUG__) && !defined(__APPLE__)
#pragma implementation "CMakeSetupFrame.h"
#endif

// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"

#ifdef __BORLANDC__
#pragma hdrstop
#endif

#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif

////@begin includes
////@end includes

#include <wx/dirdlg.h>
#include <wx/msgdlg.h>
#include <wx/filename.h>

#include "CMakeSetupFrame.h"
#include "PropertyList.h"
#include "app_resources.h"
#include "CMakeIcon.xpm"
#include "aboutdlg.h"

// cmake includes
#include "../cmVersion.h"
#include "../cmListFileCache.h"
#include "../cmCacheManager.h"
#include "../cmGlobalGenerator.h"
#include "../cmDynamicLoader.h"

////@begin XPM images
////@end XPM images

/*!
 * CMakeSetupFrm type definition
 */

IMPLEMENT_CLASS( CMakeSetupFrm, wxFrame )

/*!
 * CMakeSetupFrm event table definition
 */

BEGIN_EVENT_TABLE( CMakeSetupFrm, wxFrame )

////@begin CMakeSetupFrm event table entries
    EVT_CLOSE( CMakeSetupFrm::OnCloseWindow )

    EVT_SPLITTER_SASH_POS_CHANGING( ID_SPLITTERWINDOW, CMakeSetupFrm::OnSplitterPosChanging )
    EVT_SPLITTER_DCLICK( ID_SPLITTERWINDOW, CMakeSetupFrm::OnSplitterwindowSashDClick )

    EVT_BUTTON( ID_BROWSE_PROJECT, CMakeSetupFrm::OnButtonBrowseProject )

    EVT_TEXT( ID_SOURCE_BUILD_PATH, CMakeSetupFrm::OnSourceBuildPathUpdated )
    EVT_TEXT_ENTER( ID_SOURCE_BUILD_PATH, CMakeSetupFrm::OnSourceBuildPathEnter )

    EVT_BUTTON( ID_BROWSE_BUILD, CMakeSetupFrm::OnButtonBrowseBuild )

    EVT_COMBOBOX( ID_SEARCHQUERY, CMakeSetupFrm::OnSearchquerySelected )
    EVT_TEXT( ID_SEARCHQUERY, CMakeSetupFrm::OnSearchqueryUpdated )

    EVT_CHECKBOX( ID_SHOW_ADVANCED, CMakeSetupFrm::OnShowAdvancedValues )

    EVT_GRID_CELL_CHANGE( CMakeSetupFrm::OnCellChange )
    EVT_GRID_SELECT_CELL( CMakeSetupFrm::OnGridSelectCell )
    EVT_MOTION( CMakeSetupFrm::OnPropertyMotion )

    EVT_BUTTON( ID_DO_CONFIGURE, CMakeSetupFrm::OnButtonConfigure )

    EVT_BUTTON( ID_DO_OK, CMakeSetupFrm::OnButtonOk )

    EVT_BUTTON( ID_DO_CANCEL, CMakeSetupFrm::OnButtonCancel )

    EVT_BUTTON( ID_DO_DELETE_CACHE, CMakeSetupFrm::OnButtonDeleteCache )

    EVT_BUTTON( ID_CLEAR_LOG, CMakeSetupFrm::OnClearLogClick )

    EVT_BUTTON( ID_BROWSE_GRID, CMakeSetupFrm::OnBrowseGridClick )

    EVT_MENU( ID_MENU_RELOAD_CACHE, CMakeSetupFrm::OnMenuReloadCacheClick )

    EVT_MENU( ID_MENU_DELETE_CACHE, CMakeSetupFrm::OnMenuDeleteCacheClick )

    EVT_MENU( ID_MENU_QUIT, CMakeSetupFrm::OnMenuQuitClick )

    EVT_MENU( ID_MENU_CONFIGURE, CMakeSetupFrm::OnMenuConfigureClick )

    EVT_MENU( ID_MENU_EXITGENERATE, CMakeSetupFrm::OnMenuGenerateClick )

    EVT_MENU( ID_MENU_TOGGLE_ADVANCED, CMakeSetupFrm::OnMenuToggleAdvancedClick )

    EVT_MENU( ID_CMAKE_OPTIONS, CMakeSetupFrm::OnOptionsClick )

    EVT_MENU( ID_ABOUTDLG, CMakeSetupFrm::OnAboutClick )

////@end CMakeSetupFrm event table entries

    EVT_MENU_RANGE(CM_RECENT_BUILD_ITEM, CM_RECENT_BUILD_ITEM + CM_MAX_RECENT_PATHS, CMakeSetupFrm::OnRecentFileMenu)   

    EVT_TEXT_ENTER(ID_SEARCHQUERY, CMakeSetupFrm::OnAddQuery )

END_EVENT_TABLE()

/** Callback function for CMake generator, to tell user how
    far the generation actually is */
void updateProgress(const char *msg, float prog, void *cd)
{
    // TODO: Make some kind of progress counter 
    
    CMakeSetupFrm *fm = (CMakeSetupFrm *)cd;

    if(fm)
    {
        if(prog < 0)
            fm->LogMessage(0, msg);
        else
        {
            fm->UpdateProgress(prog);
            fm->IssueUpdate();
        }
    }
}

/** Callback function for CMake generator, to tell user about stuff. This should be
    logged in the m_log window */
void MFCMessageCallback(const char* m, const char* title, bool& nomore, void *clientdata)
{ 
    CMakeSetupFrm *fm = (CMakeSetupFrm *)clientdata;

    if(fm)
    {
        wxString what = m, msg;
        if(what.StartsWith("CMake Error: "))
            fm->LogMessage(-1, m);
        else
            fm->LogMessage(1, m);
    }
}

// Convert to Win32 path (slashes). This calls the system tools one and then
// removes the spaces. It is not in system tools because we don't want any
// generators accidentally use it
std::string ConvertToWindowsPath(const char* path)
{
  // Convert to output path.
  // Remove the "" around it (if any) since it's an output path for
  // the shell. If another shell-oriented feature is not designed 
  // for a GUI use, then we are in trouble.
  // save the value of the force to unix path option
  bool saveForce = cmSystemTools::GetForceUnixPaths();
  // make sure we get windows paths no matter what for the GUI
  cmSystemTools::SetForceUnixPaths(false);
  std::string s = cmSystemTools::ConvertToOutputPath(path);
  // now restore the force unix path to its previous value
  cmSystemTools::SetForceUnixPaths(saveForce);
  if (s.size())
    {
    std::string::iterator i = s.begin();
    if (*i == '\"')
      {
      s.erase(i, i + 1);
      }
    i = s.begin() + s.length() - 1;
    if (*i == '\"')
      {
      s.erase(i, i + 1);
      }
    }
  return s;
}


bool DnDFile::OnDropFiles(wxCoord, wxCoord, const wxArrayString& filenames)
{
    size_t nFiles = filenames.GetCount();

    // only one item allowed
    if(nFiles > 1)
        return false;

    if(nFiles == 1)
    {
        // only one dir allowed
        if(!wxDirExists(filenames[0]))
            return false;

        // strip the seperator
        wxFileName name;
        name.AssignDir(filenames[0]);       
        
        // issue a 'drop' by changing text ctrl
        m_pOwner->SetValue(name.GetFullPath());

        return true;
    }

    return false;
}

/*!
 * CMakeSetupFrm constructors
 */

CMakeSetupFrm::CMakeSetupFrm( )
    : m_cmake(0)
{
}

CMakeSetupFrm::CMakeSetupFrm( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
    : m_cmake(0)
{
    Create( parent, id, caption, pos, size, style );
}

/*!
 * CMakeSetupFrm creator
 */

bool CMakeSetupFrm::Create( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
{
////@begin CMakeSetupFrm member initialisation
    m_splitter = NULL;
    m_cmProjectPath = NULL;
    m_BrowseProjectPathButton = NULL;
    m_cmBuildPath = NULL;
    m_BrowseSourcePathButton = NULL;
    m_cmGeneratorChoice = NULL;
    m_cmSearchQuery = NULL;
    m_cmShowAdvanced = NULL;
    m_cmOptions = NULL;
    m_cmLog = NULL;
    m_cmDescription = NULL;
    m_ConfigureButton = NULL;
    m_OkButton = NULL;
    m_CancelButton = NULL;
    m_DeleteCacheButton = NULL;
    m_ClearLogButton = NULL;
    m_cmBrowseCell = NULL;
////@end CMakeSetupFrm member initialisation

    wxFrame::Create( parent, id, caption, pos, size, style );

    // make sure the developer does not assign more then 100
    // would be rediculous but also overlap other id's
    wxASSERT(CM_MAX_RECENT_PATHS < 100);

    m_ExitTimer = 0;

    m_progressDlg = 0;
    m_noRefresh = false;
    m_quitAfterGenerating = false;

    m_config = new wxConfig("CMakeSetup");

    wxIcon icon(CMakeIcon_xpm);
    SetIcon(icon);

    CreateControls();
    
    //SetIcon(GetIconResource(wxT("cmake_icon.xpm")));
    //SetIcon(wxIcon("NGDialog.ico", wxBITMAP_TYPE_ICO_RESOURCE));
    Centre();

    // is it needed to hide console?
    m_RunningConfigure = false;
    cmSystemTools::SetRunCommandHideConsole(true);
    cmSystemTools::SetErrorCallback(MFCMessageCallback, (void *)this);

    // create our cmake instance
    m_cmake = new cmake;
    m_cmake->SetProgressCallback(updateProgress, (void *)this);

    return TRUE;
}

CMakeSetupFrm::~CMakeSetupFrm()
{
    wxString str;

    // write configs back to disk
    m_config->Write(CM_LASTPROJECT_PATH, m_cmProjectPath->GetValue());
    m_config->Write(CM_LASTBUILD_PATH, m_cmBuildPath->GetValue());

    // clear the config first
    for(size_t i = 0 ; i < CM_MAX_RECENT_PATHS; i++)
    {
        str.Printf("%s%i", _(CM_RECENT_BUILD_PATH), i);
        m_config->Write(str, _(""));
    }

    // write the last CM_MAX_RECENT_PATHS items back to config
    int i = (m_recentPaths.Count() >= CM_MAX_RECENT_PATHS ? CM_MAX_RECENT_PATHS : m_recentPaths.Count());
    while(i > 0)
    {
        str.Printf("%s%i", _(CM_RECENT_BUILD_PATH), i);
        m_config->Write(str, m_recentPaths[i - 1]);
        i--;
    }
    
    // write recent query list to config
    for(int j = 0; j < m_cmSearchQuery->GetCount(); j++)
    {
        // allow max to be written
        if(j < CM_MAX_SEARCH_QUERIES)
        {
            str.Printf("%s%i", _(CM_SEARCH_QUERY), j);
            m_config->Write(str, m_cmSearchQuery->GetString(j));
        }
        else
            break;
    }

    // set window pos + size in settings
    if(!IsIconized() && !IsMaximized())
    {
        int xsize, ysize;
        GetSize(&xsize, &ysize);
        if(xsize > 0 && ysize > 0) 
        {
            m_config->Write(CM_XSIZE, (long)xsize);
            m_config->Write(CM_YSIZE, (long)ysize);
        }

        if(m_splitter->GetSashPosition() > 0)
            m_config->Write(CM_SPLITTERPOS, (long)m_splitter->GetSashPosition());

        GetPosition(&xsize, &ysize);
        if(xsize != 0 && ysize != 0) 
        {
            m_config->Write(CM_XPOS, (long)xsize);
            m_config->Write(CM_YPOS, (long)ysize);
        }
    }

    // write changes (will be done before deletion)
    delete m_config;
    
    // delete timer
    if(m_ExitTimer)
        delete m_ExitTimer;

    // delete our cmake instance again
    if(m_cmake)
        delete m_cmake;
}

void CMakeSetupFrm::UpdateWindowState()
{
    bool dogenerate = !m_RunningConfigure && !m_cmOptions->IsCacheDirty() && 
                       (m_cmOptions->GetCount() != 0);
    
    // when configure is running, disable a lot of stuff
    m_cmProjectPath->Enable(!m_RunningConfigure);
    m_BrowseProjectPathButton->Enable(!m_RunningConfigure);
    m_cmBuildPath->Enable(!m_RunningConfigure);
    m_BrowseSourcePathButton->Enable(!m_RunningConfigure);
    m_cmGeneratorChoice->Enable(!m_RunningConfigure);
    m_cmShowAdvanced->Enable(!m_RunningConfigure);
    m_cmOptions->Enable(!m_RunningConfigure);
    m_ConfigureButton->Enable(!m_RunningConfigure);
    m_OkButton->Enable(dogenerate);
    m_CancelButton->Enable(m_RunningConfigure);
    m_DeleteCacheButton->Enable(!m_RunningConfigure);
    m_ClearLogButton->Enable(!m_RunningConfigure);
    if(m_RunningConfigure)
        m_cmBrowseCell->Enable(false);

    // when cache loaded (items available show other control)
    m_cmGeneratorChoice->Enable(m_cmOptions->GetCount() == 0 && !m_RunningConfigure);
    m_cmSearchQuery->Enable(!m_RunningConfigure);
    m_cmBrowseCell->Enable(!m_RunningConfigure && m_cmOptions->IsSelectedItemBrowsable());

    // disable the menus when configuring
    if(GetMenuBar())
    {
        // disable configure button when there is nothing, and generate and exit
        // only when it is allowed to generate
        GetMenuBar()->Enable(ID_MENU_EXITGENERATE, dogenerate);
        GetMenuBar()->Enable(ID_MENU_CONFIGURE, !m_RunningConfigure);

        for(size_t i = 0; i < GetMenuBar()->GetMenuCount(); i++)
            GetMenuBar()->EnableTop(i, !m_RunningConfigure); 
    }
}

void CMakeSetupFrm::LogMessage(int logkind, const char *msg)
{
    // put CR first but prevent a CR at the end
#ifndef __LINUX__   
    if(m_cmLog->IsModified())
        (*m_cmLog) << wxT("\n");
#else
    // Linux requires a different approach
    if(!m_cmLog->GetValue().IsEmpty())
        (*m_cmLog) << wxT("\n");
#endif        

    // log error, warning, or message
    wxTextAttr defattr = m_cmLog->GetDefaultStyle();
    
    switch(logkind)
    {
    // user message
    case 1:
        {
            wxTextAttr colattr(*wxBLUE);
            m_cmLog->SetDefaultStyle(colattr);
            (*m_cmLog) << msg;
            m_cmLog->SetDefaultStyle(defattr);
        }
        break;

    // progress
    case 0:
        (*m_cmLog) << msg;
        break;

    // error
    case -1:
        {
            wxTextAttr colattr(*wxRED);
            m_cmLog->SetDefaultStyle(colattr);
            (*m_cmLog) << msg;
            m_cmLog->SetDefaultStyle(defattr);
        }
        break;
    }
        
    IssueUpdate();
}

void CMakeSetupFrm::IssueUpdate()
{
    //::wxSafeYield(m_CancelButton, true);
    ::wxYield();

    // when we pressed cancel on the progress dialog
    // stop all activities
    if(m_progressDlg)
    {
        if(m_progressDlg->CancelPressed() && !m_progressDlg->IsCancelling())
        {           
            m_progressDlg->CancelAcknowledged();

            // send a button event to cancel the progress
            wxCommandEvent event( wxEVT_COMMAND_BUTTON_CLICKED, ID_DO_CANCEL);
            wxPostEvent(this, event);
        }
    }
}

/*!
 * Control creation for CMakeSetupFrm
 */

void CMakeSetupFrm::CreateControls()
{    
////@begin CMakeSetupFrm content construction
    CMakeSetupFrm* itemFrame1 = this;

    wxMenuBar* menuBar = new wxMenuBar;
    wxMenu* itemMenu37 = new wxMenu;
    itemMenu37->Append(ID_MENU_RELOAD_CACHE, _("&Reload Cache\tCtrl+R"), _("Reload the cache from disk"), wxITEM_NORMAL);
    itemMenu37->Append(ID_MENU_DELETE_CACHE, _("&Delete Cache\tCtrl+D"), _("Delete the cache on disk of the current path"), wxITEM_NORMAL);
    itemMenu37->AppendSeparator();
    itemMenu37->Append(ID_MENU_QUIT, _("E&xit\tAlt+F4"), _("Quit CMake Setup"), wxITEM_NORMAL);
    menuBar->Append(itemMenu37, _("&File"));
    wxMenu* itemMenu42 = new wxMenu;
    itemMenu42->Append(ID_MENU_CONFIGURE, _("&Configure\tCtrl+N"), _T(""), wxITEM_NORMAL);
    itemMenu42->Append(ID_MENU_EXITGENERATE, _("&Generate and Exit\tCtrl+G"), _T(""), wxITEM_NORMAL);
    itemMenu42->Append(ID_MENU_TOGGLE_ADVANCED, _("Toggle &Advanced\tCtrl+A"), _T(""), wxITEM_NORMAL);
    itemMenu42->AppendSeparator();
    itemMenu42->Append(ID_CMAKE_OPTIONS, _("&Options\tCtrl+O"), _T(""), wxITEM_NORMAL);
    menuBar->Append(itemMenu42, _("&Tools"));
    wxMenu* itemMenu48 = new wxMenu;
    itemMenu48->Append(ID_ABOUTDLG, _("&About ..."), _("Shows the about dialog ..."), wxITEM_NORMAL);
    menuBar->Append(itemMenu48, _("&Help"));
    itemFrame1->SetMenuBar(menuBar);

    m_splitter = new wxSplitterWindow( itemFrame1, ID_SPLITTERWINDOW, wxDefaultPosition, wxSize(100, 100), wxSP_3DBORDER|wxSP_3DSASH|wxNO_BORDER );

    wxPanel* itemPanel3 = new wxPanel( m_splitter, ID_MAINPANEL, wxDefaultPosition, wxSize(600, 400), wxNO_BORDER|wxTAB_TRAVERSAL );
    itemPanel3->SetExtraStyle(itemPanel3->GetExtraStyle()|wxWS_EX_VALIDATE_RECURSIVELY);
    wxBoxSizer* itemBoxSizer4 = new wxBoxSizer(wxVERTICAL);
    itemPanel3->SetSizer(itemBoxSizer4);

    wxBoxSizer* itemBoxSizer5 = new wxBoxSizer(wxHORIZONTAL);
    itemBoxSizer4->Add(itemBoxSizer5, 0, wxGROW|wxTOP|wxBOTTOM, 5);
    wxFlexGridSizer* itemFlexGridSizer6 = new wxFlexGridSizer(2, 3, 0, 0);
    itemFlexGridSizer6->AddGrowableRow(1);
    itemFlexGridSizer6->AddGrowableCol(1);
    itemBoxSizer5->Add(itemFlexGridSizer6, 1, wxALIGN_TOP|wxLEFT, 5);
    wxStaticText* itemStaticText7 = new wxStaticText( itemPanel3, wxID_STATIC, _("CMake project path"), wxDefaultPosition, wxDefaultSize, 0 );
    itemFlexGridSizer6->Add(itemStaticText7, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxADJUST_MINSIZE, 5);

    m_cmProjectPath = new wxTextCtrl( itemPanel3, ID_PROJECT_PATH, _T(""), wxDefaultPosition, wxSize(50, -1), 0 );
    itemFlexGridSizer6->Add(m_cmProjectPath, 1, wxGROW|wxALIGN_CENTER_VERTICAL|wxTOP|wxBOTTOM, 5);

    m_BrowseProjectPathButton = new wxButton( itemPanel3, ID_BROWSE_PROJECT, _("Browse"), wxDefaultPosition, wxSize(55, -1), 0 );
    itemFlexGridSizer6->Add(m_BrowseProjectPathButton, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);

    wxStaticText* itemStaticText10 = new wxStaticText( itemPanel3, wxID_STATIC, _("Project build path"), wxDefaultPosition, wxDefaultSize, 0 );
    itemFlexGridSizer6->Add(itemStaticText10, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxLEFT|wxRIGHT|wxADJUST_MINSIZE, 5);

    m_cmBuildPath = new wxTextCtrl( itemPanel3, ID_SOURCE_BUILD_PATH, _T(""), wxDefaultPosition, wxSize(50, -1), 0 );
    itemFlexGridSizer6->Add(m_cmBuildPath, 1, wxGROW|wxALIGN_TOP|wxTOP|wxBOTTOM, 5);

    m_BrowseSourcePathButton = new wxButton( itemPanel3, ID_BROWSE_BUILD, _("Browse"), wxDefaultPosition, wxSize(55, -1), 0 );
    itemFlexGridSizer6->Add(m_BrowseSourcePathButton, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);

    wxBoxSizer* itemBoxSizer13 = new wxBoxSizer(wxVERTICAL);
    itemBoxSizer5->Add(itemBoxSizer13, 0, wxGROW|wxLEFT|wxRIGHT, 5);
    wxFlexGridSizer* itemFlexGridSizer14 = new wxFlexGridSizer(2, 2, 0, 0);
    itemBoxSizer13->Add(itemFlexGridSizer14, 0, wxALIGN_CENTER_HORIZONTAL|wxLEFT|wxRIGHT, 5);
    wxStaticText* itemStaticText15 = new wxStaticText( itemPanel3, wxID_STATIC, _("Generate"), wxDefaultPosition, wxDefaultSize, 0 );
    itemFlexGridSizer14->Add(itemStaticText15, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxRIGHT|wxADJUST_MINSIZE, 5);

    wxString* m_cmGeneratorChoiceStrings = NULL;
    m_cmGeneratorChoice = new wxComboBox( itemPanel3, ID_CHOOSE_GENERATOR, _T(""), wxDefaultPosition, wxSize(170, -1), 0, m_cmGeneratorChoiceStrings, wxCB_READONLY );
    itemFlexGridSizer14->Add(m_cmGeneratorChoice, 1, wxALIGN_CENTER_HORIZONTAL|wxGROW|wxTOP|wxBOTTOM, 5);

    wxStaticText* itemStaticText17 = new wxStaticText( itemPanel3, wxID_STATIC, _("Search"), wxDefaultPosition, wxDefaultSize, 0 );
    itemFlexGridSizer14->Add(itemStaticText17, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxRIGHT|wxADJUST_MINSIZE, 5);

    wxString* m_cmSearchQueryStrings = NULL;
    m_cmSearchQuery = new wxComboBox( itemPanel3, ID_SEARCHQUERY, _T(""), wxDefaultPosition, wxSize(170, -1), 0, m_cmSearchQueryStrings, wxWANTS_CHARS );
    itemFlexGridSizer14->Add(m_cmSearchQuery, 1, wxALIGN_CENTER_HORIZONTAL|wxGROW|wxTOP|wxBOTTOM, 5);

    m_cmShowAdvanced = new wxCheckBox( itemPanel3, ID_SHOW_ADVANCED, _("Show advanced values"), wxDefaultPosition, wxDefaultSize, wxCHK_2STATE );
    m_cmShowAdvanced->SetValue(FALSE);
    itemBoxSizer13->Add(m_cmShowAdvanced, 0, wxALIGN_RIGHT|wxLEFT|wxRIGHT, 5);

    m_cmOptions = new wxPropertyList( itemPanel3, ID_OPTIONS, wxDefaultPosition, wxSize(200, 150), wxSTATIC_BORDER|wxWANTS_CHARS|wxVSCROLL );
    m_cmOptions->SetDefaultColSize(250);
    m_cmOptions->SetDefaultRowSize(25);
    m_cmOptions->SetColLabelSize(20);
    m_cmOptions->SetRowLabelSize(0);
    m_cmOptions->CreateGrid(10, 2, wxGrid::wxGridSelectRows);
    itemBoxSizer4->Add(m_cmOptions, 1, wxGROW|wxALL, 5);

    wxPanel* itemPanel21 = new wxPanel( m_splitter, ID_LOGPANEL, wxDefaultPosition, wxSize(-1, 100), wxNO_BORDER|wxTAB_TRAVERSAL );
    wxBoxSizer* itemBoxSizer22 = new wxBoxSizer(wxVERTICAL);
    itemPanel21->SetSizer(itemBoxSizer22);

    wxBoxSizer* itemBoxSizer23 = new wxBoxSizer(wxHORIZONTAL);
    itemBoxSizer22->Add(itemBoxSizer23, 1, wxGROW|wxLEFT|wxRIGHT|wxTOP, 5);
    m_cmLog = new wxTextCtrl( itemPanel21, ID_LOG_AREA, _("Select your project path (where CMakeLists.txt is) and then select the build path (where the projects should be saved), or select a previous build path.\n\nRight click on a cache value for additional options (delete and ignore). Press configure to update and display new values in red, press OK to generate the projects and exit."), wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY|wxTE_RICH2|wxSTATIC_BORDER );
    itemBoxSizer23->Add(m_cmLog, 1, wxGROW|wxRIGHT, 5);

    m_cmDescription = new wxTextCtrl( itemPanel21, ID_DESCRIPTION, _T(""), wxDefaultPosition, wxSize(200, -1), wxTE_MULTILINE|wxTE_READONLY|wxTE_RICH2|wxSTATIC_BORDER );
    itemBoxSizer23->Add(m_cmDescription, 0, wxGROW|wxLEFT, 5);

    wxBoxSizer* itemBoxSizer26 = new wxBoxSizer(wxHORIZONTAL);
    itemBoxSizer22->Add(itemBoxSizer26, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
    m_ConfigureButton = new wxButton( itemPanel21, ID_DO_CONFIGURE, _("Co&nfigure"), wxDefaultPosition, wxDefaultSize, 0 );
    m_ConfigureButton->SetDefault();
    itemBoxSizer26->Add(m_ConfigureButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

    m_OkButton = new wxButton( itemPanel21, ID_DO_OK, _("&Generate!"), wxDefaultPosition, wxDefaultSize, 0 );
    itemBoxSizer26->Add(m_OkButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

    m_CancelButton = new wxButton( itemPanel21, ID_DO_CANCEL, _("C&ancel"), wxDefaultPosition, wxDefaultSize, 0 );
    itemBoxSizer26->Add(m_CancelButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

#if defined(__WXMSW__)
    wxStaticLine* itemStaticLine30 = new wxStaticLine( itemPanel21, wxID_STATIC, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
    itemBoxSizer26->Add(itemStaticLine30, 0, wxGROW|wxALL, 5);
#endif

    m_DeleteCacheButton = new wxButton( itemPanel21, ID_DO_DELETE_CACHE, _("&Delete Cache"), wxDefaultPosition, wxDefaultSize, 0 );
    itemBoxSizer26->Add(m_DeleteCacheButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

    m_ClearLogButton = new wxButton( itemPanel21, ID_CLEAR_LOG, _("Clear &Log"), wxDefaultPosition, wxDefaultSize, 0 );
    itemBoxSizer26->Add(m_ClearLogButton, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

#if defined(__WXMSW__)
    wxStaticLine* itemStaticLine33 = new wxStaticLine( itemPanel21, wxID_STATIC, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
    itemBoxSizer26->Add(itemStaticLine33, 0, wxGROW|wxALL, 5);
#endif

    m_cmBrowseCell = new wxButton( itemPanel21, ID_BROWSE_GRID, _("&Browse"), wxDefaultPosition, wxDefaultSize, 0 );
    itemBoxSizer26->Add(m_cmBrowseCell, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);

    m_splitter->SplitHorizontally(itemPanel3, itemPanel21, 300);

    wxStatusBar* itemStatusBar35 = new wxStatusBar( itemFrame1, ID_STATUSBAR, wxST_SIZEGRIP|wxNO_BORDER );
    itemStatusBar35->SetFieldsCount(2);
    itemFrame1->SetStatusBar(itemStatusBar35);

////@end CMakeSetupFrm content construction
}

void CMakeSetupFrm::DoInitFrame(cmCommandLineInfo &cm, const wxString &fn)
{ 
    // path to where cmake.exe is
    // m_PathToExecutable = cm.GetPathToExecutable().c_str();
    m_PathToExecutable = fn;

    // adjust size of last bar, to display % progress
    wxStatusBar *bar = GetStatusBar();
    if(bar)
    {
        wxASSERT(bar->GetFieldsCount() > 1);
        
        // fill all with -1. Why this way? because the count of the status bars
        // can change. All of the widths must be accounted for and initialised
        int *widths = new int[bar->GetFieldsCount()];
        for(int i = 0; i < bar->GetFieldsCount(); i++)
            widths[i] = -1;

        // the % field
        widths[1] = 75;
        bar->SetStatusWidths(bar->GetFieldsCount(), widths);
        delete widths;
    }

    wxString name, generator;
    std::vector<std::string> names;
  
    m_RunningConfigure = false;

    // set grid labels
    m_cmOptions->SetColLabelValue(0, wxT("Cache Name"));
    m_cmOptions->SetColLabelValue(1, wxT("Cache Value"));
    m_cmOptions->SetProjectGenerated(false);

    // set drop target
    m_cmOptions->SetDropTarget(new DnDFile(m_cmBuildPath));

    m_cmake->GetRegisteredGenerators(names);
    for(std::vector<std::string>::iterator i = names.begin(); i != names.end(); ++i)
    {
        name = i->c_str();
        m_cmGeneratorChoice->Append(name);
    }
    
    // sync advanced option with grid
    m_cmOptions->SetShowAdvanced(m_cmShowAdvanced->GetValue());

    // if we have a command line query that a generator 
    // needs to be chosen instead of the default, take it
    bool foundGivenGenerator = false;
    if(!cm.m_GeneratorChoiceString.IsEmpty())
    {
        // set proper discovered generator
        foundGivenGenerator = m_cmGeneratorChoice->SetStringSelection(cm.m_GeneratorChoiceString);  
    }

    // if none selected, we will see if VS8, VS7 or VS6 is present
    if(!foundGivenGenerator || m_cmGeneratorChoice->GetValue().IsEmpty())
    {
        std::string mp;
        mp = "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\8.0\\Setup;Dbghelp_path]";
        cmSystemTools::ExpandRegistryValues(mp);
        if(mp != "/registry")
            generator = wxT("Visual Studio 8 2005");
        else
        {
            mp = "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\7.1;InstallDir]";
            cmSystemTools::ExpandRegistryValues(mp);
            if (mp != "/registry")
                generator = wxT("Visual Studio 7 .NET 2003");
            else
            {
                mp = "[HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\7.0;InstallDir]";
                cmSystemTools::ExpandRegistryValues(mp);
                if (mp != "/registry")
                    generator = wxT("Visual Studio 7");
                else
                    generator = wxT("Visual Studio 6");         
            }
        }
    }

    // set proper discovered generator
    m_cmGeneratorChoice->SetStringSelection(generator);
    
    wxString str;
    str.Printf("CMake %d.%d - %s", cmVersion::GetMajorVersion(),
               cmVersion::GetMinorVersion(), 
               cmVersion::GetReleaseVersion().c_str());
    str.Printf("CMakeSetup v%i.%i%s", CMAKEGUI_MAJORVER, CMAKEGUI_MINORVER, CMAKEGUI_ADDVER);

    SetTitle(str);
    wxString path;
    
    // get last 5 used projects
    for(size_t i = 0; i < CM_MAX_RECENT_PATHS; i++)
    {
        path.Printf("%s%i", _(CM_RECENT_BUILD_PATH), i);
        if(m_config->Read(path, &str))
            AppendPathToRecentList(str);
    }

    // get query items
    for(size_t i = 0; i < CM_MAX_SEARCH_QUERIES; i++)
    {
        path.Printf("%s%i", _(CM_SEARCH_QUERY), i);
        if(m_config->Read(path, &str))
            m_cmSearchQuery->Append(str);
    }


    // make sure the call to update grid is not executed
    m_noRefresh = true;
    m_cmSearchQuery->SetValue(_(""));
    m_noRefresh = false;

    // Get the parameters from the command line info
    // If an unknown parameter is found, try to interpret it too, since it
    // is likely to be a file dropped on the shortcut :)
    bool sourceDirLoaded = false,
         buildDirLoaded = false;
    
    if(cm.m_LastUnknownParameter.empty())
    {
        if(cm.m_WhereSource.size() > 0 )
        {
            m_cmProjectPath->SetValue(cm.m_WhereSource.c_str());
            sourceDirLoaded = true;
        }   
    
        if (cm.m_WhereBuild.size() > 0 )
        {
            m_cmBuildPath->SetValue(cm.m_WhereBuild.c_str());
            buildDirLoaded = true;
        }
            
        m_cmShowAdvanced->SetValue(cm.m_AdvancedValues);
    }
    else
    {
        m_cmShowAdvanced->SetValue(false);
        
        // TODO: Interpret directory from dropped shortcut
        //this->ChangeDirectoriesFromFile(cmdInfo->m_LastUnknownParameter.c_str());
    }

    if (cm.m_ExitAfterLoad)
    {
        int id = GetId();
        m_ExitTimer = new wxTimer(this, id);
        m_ExitTimer->Start(3000);

        Connect( id, wxEVT_TIMER,(wxObjectEventFunction) &CMakeSetupFrm::OnExitTimer ); 

    } 

    // retrieve settings, this needs to be done here
    // because writing to the m_cmBuildPath triggers a cache reload
    if(!sourceDirLoaded && m_config->Read(CM_LASTPROJECT_PATH, &str))
        m_cmProjectPath->SetValue(str);

    if(!buildDirLoaded)
    {
        m_cmOptions->RemoveAll();
        if(m_config->Read(CM_LASTBUILD_PATH, &str))
            m_cmBuildPath->SetValue(str);
    }

    // set window size from settings
    long xsize, ysize, splitpos;
    if(m_config->Read(CM_XSIZE, &xsize) && m_config->Read(CM_YSIZE, &ysize) &&
       m_config->Read(CM_SPLITTERPOS, &splitpos))
    {
        SetSize(xsize, ysize);
        m_splitter->SetSashPosition(splitpos);
    }

    if(m_config->Read(CM_XPOS, &xsize) && m_config->Read(CM_YPOS, &ysize))
        SetSize(xsize, ysize, -1, -1, wxSIZE_USE_EXISTING);

    UpdateWindowState();
}

void CMakeSetupFrm::LoadCacheFromDiskToGUI()
{
    wxString builddir = m_cmBuildPath->GetValue();  
    
    cmCacheManager *cachem = m_cmake->GetCacheManager();
    if(cachem && !builddir.Trim().IsEmpty())
    {
        if(cachem->LoadCache(builddir.c_str()))
            AppendPathToRecentList(builddir);

        // represent this cache in the grid, but not before we
        // wiped all of the old items
        FillCacheGUIFromCacheManager();
    
        // set the generator string to the one used in the cache
        cmCacheManager::CacheIterator it = cachem->GetCacheIterator("CMAKE_GENERATOR");
        if(!it.IsAtEnd())
        {
            wxString curGen = it.GetValue();
            m_cmGeneratorChoice->SetStringSelection(curGen);
        }
    }
}

void CMakeSetupFrm::AppendPathToRecentList(const wxString &p)
{
    wxFileName path;
    wxString str;

    if(p.IsEmpty())
        return;
    
    // cheap way to get rid of trailing seperators
    path.AssignDir(p);
    str = path.GetPath();

    // append the item, or add it to end to make sure
    // it is remembered between sessions
    for(size_t i = 0; i < m_recentPaths.Count(); i++)
    {
        if(m_recentPaths[i].IsSameAs(str, false))
        {
            m_recentPaths.RemoveAt(i);
            
            // only re-add when item is still valid
            if(::wxDirExists(str))
                m_recentPaths.Add(str);
            else
                return;  // no add when the item is not existing

            return;
        }
    }
 
    if(GetMenuBar())
    {
        // get file menu
        int lastUsedID = 0;
        wxMenu *mnu = GetMenuBar()->GetMenu(0);
        wxASSERT(mnu != 0);
        
        if(::wxDirExists(str))
        {
            // add to array
            if(m_recentPaths.Count() == 0)
                mnu->AppendSeparator();

            lastUsedID = CM_RECENT_BUILD_ITEM + m_recentPaths.Count();
            m_recentPaths.Add(str);

            // when we have more in list then we can display, prune and 
            // remove some menu items until we have room (and available ID's again)
            if(m_recentPaths.Count() > CM_MAX_RECENT_PATHS)
            {
                // prune the list
                while(m_recentPaths.Count() > CM_MAX_RECENT_PATHS)
                    m_recentPaths.RemoveAt(0);  

                // now determine count, and remove until we have room
                int index = mnu->GetMenuItemCount() - 1;
                int count = 0;
                wxASSERT(index > 0);
                
                wxMenuItem *item;
                do
                {
                    item = mnu->FindItemByPosition(index);
                    if(item)
                    {
                        if(item->IsSeparator())
                        {
                            // next index is valid item
                            index ++;
                            break;
                        }
                        else
                            count ++;
                    }

                    index --;
                }
                while(index >= 0 && item);

                // ok, if count > CM_MAX_RECENT_PATHS then we are going to
                // delete some items on the index position
                if(count >= CM_MAX_RECENT_PATHS)
                {
                    // delete items that are exceeding
                    while(count >= CM_MAX_RECENT_PATHS)
                    {
                        lastUsedID = mnu->FindItemByPosition(index)->GetId();
                        mnu->Delete(lastUsedID);
                        count --;
                    }
                }
            }

            // append item
            mnu->Append(lastUsedID, str);
        }
    }
}

bool CMakeSetupFrm::PerformCacheRun()
{
    bool enable = false;
    cmCacheManager *cachem = m_cmake->GetCacheManager();
    cmCacheManager::CacheIterator it = cachem->NewIterator();

    // remove all items that are no longer present
    size_t j = 0;
    while(j < m_cmOptions->GetCount())
    {
        // check to see if it is still in the CMake cache
        // if it is still in the cache then it is no longer new
        wxPropertyItem *item = m_cmOptions->GetItem(j);
        if ( !it.Find((const char*)item->GetPropName().c_str()) )
            m_cmOptions->RemoveProperty(item);
        else
        {
            // ok we found it, mark as old
            item->SetNewValue(false);
            int row = m_cmOptions->FindProperty(item);
            if(row != -1) 
                m_cmOptions->UpdatePropertyItem(item, row);
            j++;
        }
    }

    if(cachem->GetSize() > 0 && !cmSystemTools::GetErrorOccuredFlag())
    {
        bool enable = true;     
        for(size_t i = 0; i < m_cmOptions->GetCount(); i++)
        {
            wxPropertyItem* item = m_cmOptions->GetItem(i);
            if(item->GetAdvanced())
            {
                if(item->GetNewValue() && m_cmOptions->GetShowAdvanced())
                {
                    // if one new value then disable to OK button
                    enable = false;
                    break;
                }
            }
            else
            {
                if(item->GetNewValue())
                {
                    // if one new value then disable to OK button
                    enable = false;
                    break;
                }
            }
        }
    }

    return enable;  
}

void CMakeSetupFrm::FillCacheGUIFromCacheManager()
{
    cmCacheManager *cachem = m_cmake->GetCacheManager();
    cmCacheManager::CacheIterator it = cachem->NewIterator();
  
    // remove all items that are no longer present
    size_t j = 0;
    while(j < m_cmOptions->GetCount())
    {
        // check to see if it is still in the CMake cache
        // if it is still in the cache then it is no longer new
        wxPropertyItem *item = m_cmOptions->GetItem(j);
        if ( !it.Find((const char*)item->GetPropName().c_str()) )
            m_cmOptions->RemoveProperty(item);
        else
            j++;
    }

    // if there are already entries in the cache, then
    // put the new ones in the top, so they show up first
    bool reverseOrder = false;
    for(cmCacheManager::CacheIterator i = cachem->NewIterator(); !i.IsAtEnd(); i.Next())
    {
        const char* key = i.GetName();

        // if value has trailing space or tab, enclose it in single quotes
        // to enforce the fact that it has 'invisible' trailing stuff
        std::string value = i.GetValue();
        if (value.size() && (value[value.size() - 1] == ' ' ||  value[value.size() - 1] == '\t'))
            value = '\'' + value +  '\'';

        bool advanced = i.GetPropertyAsBool("ADVANCED");
        switch(i.GetType() )
        {
        case cmCacheManager::BOOL:
            {
                wxString OnOff;
                
                if(cmSystemTools::IsOn(value.c_str()))
                    OnOff = wxT("ON");
                else
                    OnOff = wxT("OFF");

                m_cmOptions->AddProperty(key,
                                         OnOff.c_str(),
                                         i.GetProperty("HELPSTRING"),
                                         wxPropertyList::CHECKBOX, "ON|OFF",
                                         reverseOrder,
                                         advanced );
            }
            break;

        case cmCacheManager::PATH:
            m_cmOptions->AddProperty(key, 
                                     value.c_str(),
                                     i.GetProperty("HELPSTRING"),
                                     wxPropertyList::PATH,"",
                                     reverseOrder, advanced);
            break;
        
        case cmCacheManager::FILEPATH:
            m_cmOptions->AddProperty(key, 
                                     value.c_str(),
                                     i.GetProperty("HELPSTRING"),
                                     wxPropertyList::FILE,"",
                                     reverseOrder, advanced);
            break;
      
        case cmCacheManager::STRING:
            m_cmOptions->AddProperty(key,
                                     value.c_str(),
                                     i.GetProperty("HELPSTRING"),
                                     wxPropertyList::EDIT,"",
                                     reverseOrder, advanced);
            break;
      
        case cmCacheManager::INTERNAL:
            {
                wxPropertyItem *pItem = m_cmOptions->FindPropertyByName(key);
                if(pItem)
                    m_cmOptions->RemoveProperty(pItem);
            }
            break;          
        }
    }
}

void CMakeSetupFrm::OnExitTimer(wxTimerEvent &event)
{
    Close();
} 

/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_BROWSE_PROJECT
 */

void CMakeSetupFrm::OnButtonBrowseProject( wxCommandEvent& event )
{
    const wxString& dir = wxDirSelector("Select project directory", m_cmProjectPath->GetValue());
    if(!dir.IsEmpty())
        m_cmProjectPath->SetValue(dir);
}

/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_BROWSE_BUILD
 */

void CMakeSetupFrm::OnButtonBrowseBuild( wxCommandEvent& event )
{
    const wxString& dir = wxDirSelector("Select build directory", m_cmBuildPath->GetValue());
    if(!dir.IsEmpty())
        m_cmBuildPath->SetValue(dir);
}

/*!
 * wxEVT_COMMAND_CHECKBOX_CLICKED event handler for ID_SHOW_ADVANCED
 */

void CMakeSetupFrm::OnShowAdvancedValues( wxCommandEvent& event )
{
    if(m_cmShowAdvanced->GetValue())
        m_cmOptions->ShowAdvanced();
    else
        m_cmOptions->HideAdvanced();
}

/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_DO_CONFIGURE
 */

void CMakeSetupFrm::OnButtonConfigure( wxCommandEvent& event )
{
    DoConfigure();
}

void CMakeSetupFrm::DoConfigure()
{
    // enable error messages each time configure is pressed
    cmSystemTools::EnableMessages();
    m_cmOptions->HideControls();

    cmSystemTools::ResetErrorOccuredFlag(); 
    
    // instantiate a dialog for the progress meter

    PerformCacheRun();
    RunCMake(false);
}

int CMakeSetupFrm::RunCMake(bool generateProjectFiles)
{
    int value = -1;
    
    // clear log
    m_cmLog->Clear();
    m_cmLog->DiscardEdits();

    wxString builddir = m_cmBuildPath->GetValue(), 
             sourcedir = m_cmProjectPath->GetValue(),
             err = wxT("Error in configuration process, project files may be invalid");


    // sanity check for people pressing OK on empty dirs
    if(builddir.Trim().IsEmpty() || sourcedir.Trim().IsEmpty())
    {
        wxMessageBox(wxT("Please enter a valid source directory and build directory"), wxT("Error"), wxOK | wxICON_ERROR, this);
        return -1;
    }

    // check if the directory exists, if not, create it
    if(!cmSystemTools::FileExists(builddir.c_str()))
    {
        wxString str;
        str << wxT("Build directory does not exist, should I create it?\n\nDirectory: ") << builddir;
    
        int answer = wxMessageBox(str, wxT("Create directory"), wxYES_NO, this);
        if (answer == wxYES)
        {
            if(!cmSystemTools::MakeDirectory(builddir.c_str()))
            {
                // could not create, tell and abort
                wxMessageBox(wxT("Could not create directory"), wxT("Error"), wxOK | wxICON_ERROR, this);
                return -1;
            }
        }
        else
        {
            // we abort because the user did not want to make the directory
            wxMessageBox(wxT("Build Project aborted, nothing done."), wxT("Aborted"), 
                         wxOK | wxICON_EXCLAMATION, this);
            return -1;
        }
    }

    /** show progress dialog that informs the user with a progress bar */ 
    if(m_progressDlg)
        m_progressDlg->Destroy();

    m_progressDlg = new CMProgressDialog(this);
    m_progressDlg->Show();

    // set the wait cursor
    m_RunningConfigure = true;
    UpdateWindowState();

    // always save the current gui values to disk
    SaveCacheFromGUI();
  
    // Make sure we are working from the cache on disk
    LoadCacheFromDiskToGUI(); 

    // setup the cmake instance
    if (generateProjectFiles)
    {
        if(m_cmake->Generate() != 0)
        {
            wxMessageBox(err, wxT("Error"), wxOK | wxICON_ERROR, this);
            cmSystemTools::Error(err.c_str());
            value = -1;
        }
        else
        {
            value = 0;
            m_cmOptions->SetProjectGenerated(true); // clear cache dirty when generated
        }
    }
    else
    {
        // set paths 
        m_cmake->SetHomeDirectory(m_cmProjectPath->GetValue().c_str());
        m_cmake->SetStartDirectory(m_cmProjectPath->GetValue().c_str());
        m_cmake->SetHomeOutputDirectory(m_cmBuildPath->GetValue().c_str());
        m_cmake->SetStartOutputDirectory(m_cmBuildPath->GetValue().c_str());
        
        m_cmake->SetGlobalGenerator(m_cmake->CreateGlobalGenerator(m_cmGeneratorChoice->GetValue().c_str()));
        m_cmake->SetCMakeCommand(m_PathToExecutable.c_str());
        m_cmake->LoadCache();
        if(m_cmake->Configure() != 0)
        {
            wxMessageBox(err, wxT("Error"), wxOK | wxICON_ERROR, this);
            cmSystemTools::Error(err.c_str());
        }
        
        // update the GUI with any new values in the caused by the
        // generation process
        LoadCacheFromDiskToGUI();
    }

    m_RunningConfigure = false;
    
    if(!value)
        cmSystemTools::ResetErrorOccuredFlag();

    m_progressDlg->Destroy();
    m_progressDlg = 0;

    // reset the statusbar progress 
    wxStatusBar *bar = GetStatusBar();
    if(bar)
        bar->SetStatusText(wxEmptyString, 1);

    UpdateWindowState();
    return value;
}

//! Save GUI values to cmCacheManager and then save to disk.
void CMakeSetupFrm::SaveCacheFromGUI()
{
    cmCacheManager *cachem = m_cmake->GetCacheManager();
    FillCacheManagerFromCacheGUI();
  
    // write the cache to disk
    if(!m_cmBuildPath->GetValue().Trim().IsEmpty())
        cachem->SaveCache(m_cmBuildPath->GetValue().c_str());
}

void CMakeSetupFrm::FillCacheManagerFromCacheGUI()
{ 
    cmCacheManager *cachem = m_cmake->GetCacheManager();
    
    cmCacheManager::CacheIterator it = cachem->NewIterator();
    for(size_t i = 0; i < m_cmOptions->GetCount(); i++)
    {
        wxPropertyItem* item = m_cmOptions->GetItem(i); 
        if ( it.Find((const char*)item->GetPropName().c_str()) )
        {
            // if value is enclosed in single quotes ('foo') then remove them
            // they were used to enforce the fact that it had 'invisible' 
            // trailing stuff
            if (item->GetCurValue().Len() >= 2 &&
                item->GetCurValue().GetChar(0) == '\'' && 
                item->GetCurValue().GetChar(item->GetCurValue().Len() - 1) == '\'') 
            {
                it.SetValue(item->GetCurValue().Mid(1, item->GetCurValue().Len() - 2).c_str());
            }
            else
                it.SetValue(item->GetCurValue().c_str());
        }
    }
}


/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_DO_OK
 */

void CMakeSetupFrm::OnButtonOk( wxCommandEvent& event )
{
    DoGenerate();
}

void CMakeSetupFrm::DoGenerate()
{
    cmSystemTools::EnableMessages();
    
    cmSystemTools::ResetErrorOccuredFlag(); 
    
    m_cmOptions->HideControls();
    PerformCacheRun();
  
    if(!RunCMake(true))
    {
        // issue a close when this is done (this is issued by menu "Generate and Exit"
        if(m_quitAfterGenerating)
            Close();
        else if(!wxGetKeyState(WXK_SHIFT))
        {
            bool close;
            m_config->Read(CM_CLOSEAFTERGEN, &close, CM_CLOSEAFTERGEN_DEF);
            
            if(!close)
                wxMessageBox(wxT("Building of project files succesful!"), wxT("Success!"), wxOK|wxICON_INFORMATION);
            else
                Close();
        }
    }
}

/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_DO_CANCEL
 */

void CMakeSetupFrm::OnButtonCancel( wxCommandEvent& event )
{
    DoCancelButton();
}

void CMakeSetupFrm::DoCancelButton()
{
    if(m_RunningConfigure)
    {
        int result = wxMessageBox(wxT("You are in the middle of a Configure.\n"
                                      "If you Cancel now the configure information will be lost.\n"
                                      "Are you sure you want to Cancel?"), wxT("Warning"), wxYES_NO|wxICON_WARNING);
        if(result == wxYES)
            cmSystemTools::SetFatalErrorOccured();
        else
            if(m_progressDlg)
                m_progressDlg->ResetCancel();
    }
}

/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_DO_DELETE_CACHE
 */

void CMakeSetupFrm::OnButtonDeleteCache( wxCommandEvent& event )
{
    DoDeleteCache();
}

void CMakeSetupFrm::DoDeleteCache()
{
    bool deletecache = true;
    if(m_cmOptions->IsCacheDirty() || (m_cmOptions->GetCount() > 0 && !m_cmOptions->IsGenerated()))
    {
        int result = ::wxMessageBox(_("You have changed options, are you sure you want to delete all items?\n"), 
                                    _("Warning"), wxYES_NO|wxICON_QUESTION);
        
        // when user wants to wait, wait.. else quit
        if(result == wxNO)
            deletecache = false;
            
    }

    if(deletecache)
    {
        // indicate that we haven't generated a project yet
        m_cmOptions->SetProjectGenerated(false);
        
        if(!m_cmBuildPath->GetValue().Trim().IsEmpty() && m_cmake != 0)
            m_cmake->GetCacheManager()->DeleteCache(m_cmBuildPath->GetValue().Trim());
      
        LoadCacheFromDiskToGUI();   
        UpdateWindowState();
    }
}

/*!
 * Should we show tooltips?
 */

bool CMakeSetupFrm::ShowToolTips()
{
    return TRUE;
}

/*!
 * Get bitmap resources
 */

wxBitmap CMakeSetupFrm::GetBitmapResource( const wxString& name )
{
    // Bitmap retrieval
////@begin CMakeSetupFrm bitmap retrieval
    return wxNullBitmap;
////@end CMakeSetupFrm bitmap retrieval
}

/*!
 * Get icon resources
 */

wxIcon CMakeSetupFrm::GetIconResource( const wxString& name )
{
    // Icon retrieval
////@begin CMakeSetupFrm icon retrieval
    if (name == wxT("cmake_icon.xpm"))
    {
        wxIcon icon(_T("cmake_icon.xpm"), wxBITMAP_TYPE_XPM);
        return icon;
    }
    return wxNullIcon;
////@end CMakeSetupFrm icon retrieval
}

/*!
 * wxEVT_COMMAND_SPLITTER_SASH_POS_CHANGING event handler for ID_SPLITTERWINDOW
 */

void CMakeSetupFrm::OnSplitterPosChanging( wxSplitterEvent& event )
{
    int width, height;

    GetSize(&width, &height);

    if((height > 100))
    {
        if(event.GetSashPosition() < 170)
            event.SetSashPosition(170);
        else
        {
            if(event.GetSashPosition() > (height - 180))
                event.SetSashPosition(height - 180);
        }
    }
    else
        event.Veto();

}


/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_CLEAR_LOG
 */

void CMakeSetupFrm::OnClearLogClick( wxCommandEvent& event )
{
    // delete the log text
    m_cmLog->Clear();
    m_cmLog->DiscardEdits();
}


/*!
 * wxEVT_COMMAND_TEXT_UPDATED event handler for ID_SOURCE_BUILD_PATH
 */

void CMakeSetupFrm::OnSourceBuildPathUpdated( wxCommandEvent& event )
{
    DoReloadCache();
}

void CMakeSetupFrm::DoReloadCache()
{
    wxString buildpath = m_cmBuildPath->GetValue();
    // The build dir has changed, check if there is a cache, and 
    // grab the source dir from it

    // make sure the call to update grid is not executed
    m_noRefresh = true;
    m_cmSearchQuery->SetValue(_(""));
    m_noRefresh = false;

    std::string path = buildpath.c_str();
    cmSystemTools::ConvertToUnixSlashes(path);

    // adjust the cmake instance
    m_cmake->SetHomeOutputDirectory(buildpath.c_str());
    m_cmake->SetStartOutputDirectory(buildpath.c_str());

    std::string cache_file = path;
    cache_file += "/CMakeCache.txt";

    // fill in the project path where the source is located, this is 
    // read from the CMake cache
    cmCacheManager *cachem = m_cmake->GetCacheManager();
    cmCacheManager::CacheIterator it = cachem->NewIterator();
    if (cmSystemTools::FileExists(cache_file.c_str()) && cachem->LoadCache(path.c_str()) && 
        it.Find("CMAKE_HOME_DIRECTORY"))
    {
        path = ConvertToWindowsPath(it.GetValue());
        m_cmProjectPath->SetValue(path.c_str());
    }

    m_cmOptions->RemoveAll();
    LoadCacheFromDiskToGUI();
    UpdateWindowState();
}


/*!
 * wxEVT_COMMAND_TEXT_ENTER event handler for ID_SOURCE_BUILD_PATH
 */

void CMakeSetupFrm::OnSourceBuildPathEnter( wxCommandEvent& event )
{
    OnSourceBuildPathUpdated(event);
}

/*!
 * wxEVT_MOTION event handler for ID_OPTIONS
 */

void CMakeSetupFrm::OnPropertyMotion( wxMouseEvent& event )
{
    ShowPropertyDescription(m_cmOptions->YToRow(event.GetY()));
    event.Skip();
}


/*!
 * wxEVT_GRID_SELECT_CELL event handler for ID_OPTIONS
 */

void CMakeSetupFrm::OnGridSelectCell( wxGridEvent& event )
{
    // show description 
    ShowPropertyDescription(event.GetRow());
    
    // enable or disable the browse button
    m_cmBrowseCell->Enable(m_cmOptions->IsSelectedItemBrowsable(event.GetRow()));
    event.Skip();
}

void CMakeSetupFrm::ShowPropertyDescription(int row)
{
    if(row == wxNOT_FOUND || row < 0)
        m_cmDescription->SetValue(wxEmptyString);
    else
    {
        wxPropertyItem *pItem = m_cmOptions->GetPropertyItemFromRow(row);
        if(pItem)
            m_cmDescription->SetValue(pItem->GetHelpString());
        else
            m_cmDescription->SetValue(wxEmptyString);
    }
}

/*!
 * wxEVT_GRID_CELL_CHANGE event handler for ID_OPTIONS
 */

void CMakeSetupFrm::OnCellChange( wxGridEvent& event )
{
    // update the button state when the cache is invalidated
    UpdateWindowState();
}

void CMakeSetupFrm::OnRecentFileMenu( wxCommandEvent &event )
{   
    if(GetMenuBar())
    {
        // get file menu
        wxMenu *mnu = GetMenuBar()->GetMenu(0);
        wxASSERT(mnu != 0);

        wxMenuItem *item = mnu->FindItem(event.GetId());
        if(item)
            m_cmBuildPath->SetValue(item->GetLabel());
    }
}
/*!
 * wxEVT_COMMAND_COMBOBOX_SELECTED event handler for ID_COMBOBOX
 */

void CMakeSetupFrm::OnSearchquerySelected( wxCommandEvent& event )
{
    m_cmOptions->SetQuery(m_cmSearchQuery->GetValue());
}

void CMakeSetupFrm::OnAddQuery ( wxCommandEvent &event )
{
    // add current text if not yet present
    if(m_cmSearchQuery->FindString(m_cmSearchQuery->GetValue()) == wxNOT_FOUND)
    {
        m_cmSearchQuery->Append(m_cmSearchQuery->GetValue());
        
        // if too many items are present, prune
        while(m_cmSearchQuery->GetCount() > CM_MAX_SEARCH_QUERIES)
            m_cmSearchQuery->Delete(0);     
    }
}

/*!
 * wxEVT_COMMAND_TEXT_UPDATED event handler for ID_SEARCHQUERY
 */

void CMakeSetupFrm::OnSearchqueryUpdated( wxCommandEvent& event )
{
    // only refresh when this event was caused by user
    if(!m_noRefresh)
        m_cmOptions->SetQuery(m_cmSearchQuery->GetValue());
}


/*!
 * wxEVT_COMMAND_BUTTON_CLICKED event handler for ID_BROWSE_GRID
 */

void CMakeSetupFrm::OnBrowseGridClick( wxCommandEvent& event )
{
    m_cmOptions->BrowseSelectedItem();
}


/*!
 * wxEVT_COMMAND_MENU_SELECTED event handler for ID_MENU_RELOAD_CACHE
 */

void CMakeSetupFrm::OnMenuReloadCacheClick( wxCommandEvent& event )
{
    bool reload = true;
    if(m_cmOptions->IsCacheDirty() || (m_cmOptions->GetCount() > 0 && !m_cmOptions->IsGenerated()))
    {
        int result = ::wxMessageBox(_("You have changed options, are you sure you want to reload?\n"), 
                                    _("Warning"), wxYES_NO|wxICON_QUESTION);
        
        // when user wants to wait, wait.. else quit
        if(result == wxNO)
            reload = false;
            
    }

    if(reload) 
        DoReloadCache();
}

/*!
 * wxEVT_COMMAND_MENU_SELECTED event handler for ID_MENU_DELETE_CACHE
 */

void CMakeSetupFrm::OnMenuDeleteCacheClick( wxCommandEvent& event )
{
    DoDeleteCache();
}


/*!
 * wxEVT_COMMAND_MENU_SELECTED event handler for ID_MENU_QUIT
 */

void CMakeSetupFrm::OnMenuQuitClick( wxCommandEvent& event )
{
    // the close event will veto if the user 
    // did not want to quit due to unsaved changes
    Close();
}


/*!
 * wxEVT_CLOSE_WINDOW event handler for ID_FRAME
 */

void CMakeSetupFrm::OnCloseWindow( wxCloseEvent& event )
{
    // ask quit if:
    //  - The cache is dirty
    //  - Or the cache is OK and has some items, and no project was generated recently (configure -> generate)
    if(m_cmOptions->IsCacheDirty() || (m_cmOptions->GetCount() > 0 && !m_cmOptions->IsGenerated()))
    {
        int result = ::wxMessageBox(_("You have changed options, but not yet generated the projects\n"
                                      "are you sure you want to quit?"), _("Warning"), wxYES_NO|wxICON_QUESTION);
        
        // when user wants to wait, wait.. else quit
        if(result == wxNO)
            event.Veto();
        else
            event.Skip();
    }
    else
        event.Skip();
}


/*!
 * wxEVT_COMMAND_MENU_SELECTED event handler for ID_ABOUTDLG
 */

void CMakeSetupFrm::OnAboutClick( wxCommandEvent& event )
{
    CMAboutDlg *dlg = new CMAboutDlg(this);
    
    wxArrayString generators;
    std::vector<std::string> names; 
    m_cmake->GetRegisteredGenerators(names);
    for(std::vector<std::string>::iterator i = names.begin(); i != names.end(); ++i)
        generators.Add(i->c_str());

    wxString cmversion, cmsversion;
//    cmversion.Printf("v%i.%i %s", cmake::GetMajorVersion(), cmake::GetMinorVersion(), cmake::GetReleaseVersion());
    cmsversion.Printf("v%i.%i%s", CMAKEGUI_MAJORVER, CMAKEGUI_MINORVER, CMAKEGUI_ADDVER);

    dlg->SetAboutText(cmversion, cmsversion, generators);

    dlg->ShowModal();
    dlg->Destroy();
}


/*!
 * wxEVT_COMMAND_MENU_SELECTED event handler for ID_CMAKE_OPTIONS
 */

void CMakeSetupFrm::OnOptionsClick( wxCommandEvent& event )
{
    CMOptionsDlg *dlg = new CMOptionsDlg(this);

    dlg->SetConfig(m_config);
    if(dlg->ShowModal() == wxID_OK)
    {
        // store volatile settings
        dlg->GetConfig(m_config);
        
        // apply non volatile setting such as clear search query, recent menu, etc.
        SyncFormOptions(dlg);
    }

    dlg->Destroy();
}

void CMakeSetupFrm::SyncFormOptions(CMOptionsDlg *dlg)
{
    // TODO: Clear search query etc.
}
/*!
 * wxEVT_COMMAND_SPLITTER_DOUBLECLICKED event handler for ID_SPLITTERWINDOW
 */

void CMakeSetupFrm::OnSplitterwindowSashDClick( wxSplitterEvent& event )
{
    event.Veto(); 
}


/*!
 * wxEVT_COMMAND_MENU_SELECTED event handler for ID_MENU_CONFIGURE
 */

void CMakeSetupFrm::OnMenuConfigureClick( wxCommandEvent& event )
{
    DoConfigure();
}

/*!
 * wxEVT_COMMAND_MENU_SELECTED event handler for ID_MENU_EXITGENERATE
 */

void CMakeSetupFrm::OnMenuGenerateClick( wxCommandEvent& event )
{
    // set flag so that a close command is issued
    // after generating the cmake cache to projects
    m_quitAfterGenerating = true;
    DoGenerate();
    m_quitAfterGenerating = false;
}


/*!
 * wxEVT_COMMAND_MENU_SELECTED event handler for ID_MENU_TOGGLE_ADVANCED
 */

void CMakeSetupFrm::OnMenuToggleAdvancedClick( wxCommandEvent& event )
{
    // toggle the check box
    m_cmShowAdvanced->SetValue(!m_cmShowAdvanced->GetValue());
    OnShowAdvancedValues(event);
}


