/////////////////////////////////////////////////////////////////////////////
// Name:        excludedlg.cpp
// Purpose:     wxPackageExcludeDialog
// Author:      Francesco Montorsi
// Modified by:
// Created:     26/12/2006 23:17:17
// RCS-ID:      $Id: excludedlg.cpp,v 1.6 2007/01/01 20:06:20 frm Exp $
// Copyright:   (c) 2006 Francesco Montorsi
// Licence:     wxWidgets license
/////////////////////////////////////////////////////////////////////////////


// 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

#include <wx/filename.h>
#include <wx/dir.h>

#include "guipkg/excludedlg.h"
#include "wx/checkedlistctrl.h"

#include "guipkg/proppanel.h"   // for IsSelected() utility


// ----------------------------------------------------------------------------
// wxPackageExcludeDlg
// ----------------------------------------------------------------------------

IMPLEMENT_DYNAMIC_CLASS( wxPackageExcludeDlg, wxDialog )
BEGIN_EVENT_TABLE( wxPackageExcludeDlg, wxDialog )
    EVT_TEXT( ID_EXCLUDEDLG_PATTERN, wxPackageExcludeDlg::OnText )
END_EVENT_TABLE()

wxPackageExcludeDlg::wxPackageExcludeDlg( )
{
}

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

bool wxPackageExcludeDlg::Create( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
{
////@begin wxPackageExcludeDlg member initialisation
    m_pChoiceBook = NULL;
    m_pFileList = NULL;
    m_pDirList = NULL;
    m_pPattern = NULL;
    m_pPatternList = NULL;
////@end wxPackageExcludeDlg member initialisation

    SetExtraStyle(GetExtraStyle()|wxWS_EX_BLOCK_EVENTS);
    wxDialog::Create( parent, id, caption, pos, size, style );

    CreateControls();
    if (GetSizer())
    {
        GetSizer()->SetSizeHints(this);

        // set a min size bigger than default minsize
        SetMinSize(GetMinSize().Scale(1.2, 1.6));
    }
    CentreOnScreen();

    return true;
}

void wxPackageExcludeDlg::CreateControls()
{    
////@begin wxPackageExcludeDlg content construction
    wxPackageExcludeDlg* itemDialog1 = this;

    wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
    itemDialog1->SetSizer(itemBoxSizer2);

    m_pChoiceBook = new wxChoicebook( itemDialog1, ID_EXCLUDEDLG_CHOICEBOOK, wxDefaultPosition, wxDefaultSize, wxCHB_DEFAULT );

    wxPanel* itemPanel4 = new wxPanel( m_pChoiceBook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
    wxBoxSizer* itemBoxSizer5 = new wxBoxSizer(wxVERTICAL);
    itemPanel4->SetSizer(itemBoxSizer5);

    wxStaticText* itemStaticText6 = new wxStaticText( itemPanel4, wxID_STATIC, _("Select one or more files and then click OK to exclude them from the package:"), wxDefaultPosition, wxDefaultSize, 0 );
    itemBoxSizer5->Add(itemStaticText6, 0, wxALIGN_LEFT|wxALL|wxADJUST_MINSIZE, 5);

    m_pFileList = new wxListCtrl( itemPanel4, ID_EXCLUDEDLG_FILES, wxDefaultPosition, wxDefaultSize, wxLC_REPORT|wxLC_REPORT|wxLC_HRULES  );
    itemBoxSizer5->Add(m_pFileList, 1, wxGROW|wxALL, 5);

    m_pChoiceBook->AddPage(itemPanel4, _("Exclude file(s)"));

    wxPanel* itemPanel8 = new wxPanel( m_pChoiceBook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
    wxBoxSizer* itemBoxSizer9 = new wxBoxSizer(wxVERTICAL);
    itemPanel8->SetSizer(itemBoxSizer9);

    wxStaticText* itemStaticText10 = new wxStaticText( itemPanel8, wxID_STATIC, _("Select one or more directories and then click OK to exclude them from the package:"), wxDefaultPosition, wxDefaultSize, 0 );
    itemBoxSizer9->Add(itemStaticText10, 0, wxALIGN_LEFT|wxALL|wxADJUST_MINSIZE, 5);

    m_pDirList = new wxListCtrl( itemPanel8, ID_EXCLUDEDLG_DIRECTORIES, wxDefaultPosition, wxDefaultSize, wxLC_REPORT|wxLC_REPORT );
    itemBoxSizer9->Add(m_pDirList, 1, wxGROW|wxALL, 5);

    m_pChoiceBook->AddPage(itemPanel8, _("Exclude directory(s)"));

    wxPanel* itemPanel12 = new wxPanel( m_pChoiceBook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL );
    wxBoxSizer* itemBoxSizer13 = new wxBoxSizer(wxVERTICAL);
    itemPanel12->SetSizer(itemBoxSizer13);

    wxBoxSizer* itemBoxSizer14 = new wxBoxSizer(wxHORIZONTAL);
    itemBoxSizer13->Add(itemBoxSizer14, 0, wxGROW, 5);
    wxStaticText* itemStaticText15 = new wxStaticText( itemPanel12, wxID_STATIC, _("Pattern:"), wxDefaultPosition, wxDefaultSize, 0 );
    itemBoxSizer14->Add(itemStaticText15, 0, wxALIGN_CENTER_VERTICAL|wxALL|wxADJUST_MINSIZE, 5);

    m_pPattern = new wxTextCtrl( itemPanel12, ID_EXCLUDEDLG_PATTERN, _T(""), wxDefaultPosition, wxDefaultSize, 0 );
    itemBoxSizer14->Add(m_pPattern, 1, wxALIGN_CENTER_VERTICAL|wxALL, 5);

    itemBoxSizer13->Add(5, 5, 0, wxALIGN_CENTER_HORIZONTAL|wxLEFT|wxRIGHT, 5);

    wxStaticText* itemStaticText18 = new wxStaticText( itemPanel12, wxID_STATIC, _("Files matched by the pattern:"), wxDefaultPosition, wxDefaultSize, 0 );
    itemBoxSizer13->Add(itemStaticText18, 0, wxALIGN_LEFT|wxLEFT|wxRIGHT|wxTOP|wxADJUST_MINSIZE, 5);

    m_pPatternList = new wxListCtrl( itemPanel12, ID_EXCLUDEDLG_PATTERN_LIST, wxDefaultPosition, wxDefaultSize, wxLC_REPORT );
    itemBoxSizer13->Add(m_pPatternList, 1, wxGROW|wxALL, 5);

    m_pChoiceBook->AddPage(itemPanel12, _("Exclude files with a pattern"));

    itemBoxSizer2->Add(m_pChoiceBook, 1, wxGROW|wxALL, 5);

    wxStdDialogButtonSizer* itemStdDialogButtonSizer20 = new wxStdDialogButtonSizer;

    itemBoxSizer2->Add(itemStdDialogButtonSizer20, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
    wxButton* itemButton21 = new wxButton( itemDialog1, wxID_OK, _("&OK"), wxDefaultPosition, wxDefaultSize, 0 );
    itemStdDialogButtonSizer20->AddButton(itemButton21);

    wxButton* itemButton22 = new wxButton( itemDialog1, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
    itemStdDialogButtonSizer20->AddButton(itemButton22);

    itemStdDialogButtonSizer20->Realize();

////@end wxPackageExcludeDlg content construction

    // file list
    m_pFileList->InsertColumn(0, wxT("File path"), wxLIST_FORMAT_LEFT, 250);
    m_pFileList->InsertColumn(1, wxT("Size"));

    // dir list
    m_pDirList->InsertColumn(0, wxT("Directory path"), wxLIST_FORMAT_LEFT, 250);
    m_pDirList->InsertColumn(1, wxT("Size"));

    // pattern list
    m_pPatternList->InsertColumn(0, wxT("File path"), wxLIST_FORMAT_LEFT, 250);
    m_pPatternList->InsertColumn(1, wxT("Size"));
}

bool wxPackageExcludeDlg::ShowToolTips()
{
    return true;
}

#define ADD_TO_LISTCTRL(list, prefix, arr, getsize)                 \
    unsigned long size, l = prefix.Len();                           \
    if (prefix.Last() != wxFileName::GetPathSeparator()) l++;       \
    for (size_t i=0; i<arr.GetCount(); i++)                         \
    {                                                               \
        wxULongLong sz = getsize;                                   \
        wxString szstr = wxFileName::GetHumanReadableSize(sz);      \
        long szl = sz == wxInvalidSize ? -1 : sz.ToULong();         \
                                                                    \
        /* add i-th file */                                         \
        list->InsertItem(i, arr[i].Right(arr[i].Len() - l));        \
        list->SetItem(i, 1, szstr);                                 \
        list->SetItemData(i, szl);                                  \
    }


void wxPackageExcludeDlg::SetFileList(const wxString &prefix, 
                                      const wxArrayString &arr)
{
    ADD_TO_LISTCTRL(m_pFileList, prefix, arr, 
                    wxFileName::GetSize(arr[i]));
}

void wxPackageExcludeDlg::SetDirList(const wxString &prefix, 
                                     const wxArrayString &arr)
{
    ADD_TO_LISTCTRL(m_pDirList, prefix, arr, 
                    wxDir::GetTotalSize(arr[i]));
}

wxArrayString wxPackageExcludeDlg::GetSelectedFiles() const
{
    wxArrayString ret;
    for (int i=0; i<m_pFileList->GetItemCount(); i++)
        if (IsSelected(m_pFileList, i))
            ret.Add(m_pFileList->GetItemText(i));
    return ret;
}

wxArrayString wxPackageExcludeDlg::GetSelectedDirs() const
{
    wxArrayString ret;
    for (int i=0; i<m_pDirList->GetItemCount(); i++)
        if (IsSelected(m_pDirList, i))
            ret.Add(m_pDirList->GetItemText(i));
    return ret;
}

wxArrayString wxPackageExcludeDlg::GetMatchingFiles(wxArrayLong *sz) const
{
    // see which files of m_pFileList matches the user pattern
    wxString pattern = GetPattern();
    wxArrayString ret;
    for (int i=0; i<m_pFileList->GetItemCount(); i++)
    {
        wxString curr = m_pFileList->GetItemText(i);
        if (wxMatchWild(pattern, curr, false))
        {
            ret.Add(curr);
            if (sz)
                sz->Add(m_pFileList->GetItemData(i));
        }
    }

    return ret;
}


// ----------------------------------------------------------------------------
// wxPackageExcludeDlg - event handlers
// ----------------------------------------------------------------------------

void wxPackageExcludeDlg::OnText(wxCommandEvent& event)
{
    // update the file list of the matching files
    wxArrayLong sz;
    wxArrayString files = GetMatchingFiles(&sz);
    wxString pattern = GetPattern();

    // reset the contents of the list control
    m_pPatternList->DeleteAllItems();
    for (size_t i=0; i<files.GetCount(); i++)
    {
        m_pPatternList->InsertItem(i, files[i]);
        m_pPatternList->SetItem(i, 1, 
            wxFileName::GetHumanReadableSize(wxULongLong(sz[i])));
    }
}

