//***************************************************************************
//*
//* File: DialogBuild.cpp
//* Description: Dialog for executing builds
//*
//***************************************************************************
//
//--------------------------------------------------------------- PRECOMPILED
//
#include "stdafx.h"
//
//--------------------------------------------------- DECLARATION DEPENDENCIES
//
#include "BuildMgr2.h"
//
//--------------------------------------------------------------- DECLARATION
//
#include "DialogBuild.h"
//
//--------------------------------------------------- DEFINITION DEPENDENCIES
//
#include "DialogProgress.h"
//
//-------------------------------------------------------------- PREPROCESSOR
//
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#pragma warning ( disable : 4239 ) // passing CString to CArray< CString, CString& >
//
//---------------------------------------------------------------- DEFINITION
//
static CDialogProgress* g_pdlgProgress = NULL;
//
//---------------------------------------------------------------------------------------------------
//************************************* CON/DESTRUCTION *************************************
//---------------------------------------------------------------------------------------------------
//
//***************************************************************************************************
//** Constructor
//***************************************************************************************************
//** @DOC CONSTRUCTION
//** @MFUNC Default constructor
//** @PARM [in|opt] Pointer to parent window
//** @END
//***************************************************************************************************
//inline
CDialogBuild::CDialogBuild(CWnd* pParent /*=NULL*/)
: CDialog(CDialogBuild::IDD, pParent)
{
//{{AFX_DATA_INIT(CDialogBuild)
m_iMode = 1 ;
//}}AFX_DATA_INIT
this->m_pIApplication = NULL ;
this->m_enuFinishAction = EFinishAction_Continue;
}
//
//---------------------------------------------------------------------------------------------------
//***************************************** GET/SET *****************************************
//---------------------------------------------------------------------------------------------------
//
//***************************************************************************************************
//** SetApplication
//***************************************************************************************************
//** @DOC SET
//** @MFUNC Sets the pointer to the application's interface
//** @PARM [in] Pointer to application's interface
//** @END
//***************************************************************************************************
//inline
void CDialogBuild::SetApplication( IApplication *a_pIApplication )
{
this->m_pIApplication = a_pIApplication;
}
//
//---------------------------------------------------------------------------------------------------
//*************************************** PERSISTENCE ***************************************
//---------------------------------------------------------------------------------------------------
//
//***************************************************************************************************
//** LoadProfile
//***************************************************************************************************
//** @DOC PERSISTENCE
//** @MFUNC Loads the dialog's settings from the registry
//** @END
//***************************************************************************************************
//inline
void CDialogBuild::LoadProfile( void )
{
//
// CLEAR LIST CONTROL
//
this->m_ctrlListConfigurations.DeleteAllItems();
//
// SETUP VARS
//
CString strWorkspacePath ;
CString strWorkspaceName ;
CString strProjectPath ;
CString strProjectName ;
CString strConfigurations ;
CString strSection ;
UINT iProjects = 0;
UINT iStyle = 0;
DWORD dwCount = 0;
///
// GET APP
//
CWinApp* pApplication = ::AfxGetApp();
//
// GET SECTION KEY
//
CRegKey keySection;
keySection.Attach( pApplication->GetSectionKey( _T( "Configure" ) ) );
//
// READ PROJECT COUNT
//
iProjects = pApplication->GetProfileInt( _T( "Configure" ), _T( "NumProjects" ), 0 );
//
// READ PROJECTS
//
for ( UINT iProject = 0; iProject < iProjects; iProject++ )
{
//
// SETUP SECTION
//
strSection.Format( "Project.%04d", iProject );
//
// GET SUB KEY
//
CRegKey keyProject ;
keyProject.Open( keySection, strSection );
//
// READ PROJECT
//
dwCount = _MAX_PATH; keyProject.QueryValue( strProjectName .GetBuffer( _MAX_PATH ) , _T( "0.Project.Name" ), &dwCount );
dwCount = _MAX_PATH; keyProject.QueryValue( strProjectPath .GetBuffer( _MAX_PATH ) , _T( "1.Project.Path" ), &dwCount );
dwCount = _MAX_PATH; keyProject.QueryValue( strWorkspaceName .GetBuffer( _MAX_PATH ) , _T( "2.Workspace.Name" ), &dwCount );
dwCount = _MAX_PATH; keyProject.QueryValue( strWorkspacePath .GetBuffer( _MAX_PATH ) , _T( "3.Workspace.Path" ), &dwCount );
dwCount = _MAX_PATH; keyProject.QueryValue( strConfigurations .GetBuffer( _MAX_PATH ) , _T( "4.Configurations" ), &dwCount );
dwCount = _MAX_PATH; keyProject.QueryValue( (DWORD&) iStyle , _T( "5.Style" ) );
strProjectName .ReleaseBuffer();
strProjectPath .ReleaseBuffer();
strWorkspaceName .ReleaseBuffer();
strWorkspacePath .ReleaseBuffer();
strConfigurations .ReleaseBuffer();
//
// CLOSE THE KEY
//
keyProject.Close();
//
// ADD CONFIGURATIONS
//
this->AddProject( strProjectName, strProjectPath, strWorkspaceName, strWorkspacePath, strConfigurations, iStyle );
}
}
//***************************************************************************************************
//** WriteProfile
//***************************************************************************************************
//** @DOC PERSISTENCE
//** @MFUNC Saves the dialog's settings to the registry
//** @END
//***************************************************************************************************
//inline
void CDialogBuild::WriteProfile( void ) const
{
}
//
//---------------------------------------------------------------------------------------------------
//**************************************** EXECUTION ****************************************
//---------------------------------------------------------------------------------------------------
//
//***************************************************************************************************
//** Execute
//***************************************************************************************************
//** @DOC EXECUTION
//** @MFUNC Executes the selected configurations' build process.
//** @RDESC <t TRUE> if successful, <t FALSE> otherwise.
//** @END
//***************************************************************************************************
//inline
BOOL CDialogBuild::Execute( void )
{
//
// CREATE PROGRESS DIALOG
//
CDialogProgress dlgProgress( this );
dlgProgress.Create( IDD_PROGRESS, this );
dlgProgress.SetApplication( this->m_pIApplication );
//
// This is a bit of a hack:
//
// Store a pointer to the progress dialog for routing
// incoming BuildFinished events through to it
//
::g_pdlgProgress = &dlgProgress;
//
// SHOW PROGRESS DIALOG
//
dlgProgress.ShowWindow( SW_SHOW );
//
// SETUP RESULT
//
BOOL bResult = TRUE;
//
// FOR EACH ACTIVE CONFIGURATION
//
int iBuilt = 0;
for ( int iItem = 0; iItem < this->m_ctrlListConfigurations.GetItemCount(); iItem++ )
{
//
// CHECK WHETHER THIS CONFIGURATION IS ENABLED
//
if ( TRUE == this->m_ctrlListConfigurations.GetCheck( iItem ) )
{
//
// EXECUTE ALL ACTIVE PROJECTS CONTAINING THIS CONFIGURATION
//
bResult &= dlgProgress.Execute( this->m_ctrlListConfigurations.GetItemText( iItem, 0 ), static_cast< CDialogProgress::EBuildMode > (this->m_iMode) );
//
// INCREMENT NUMBER OF BUILT CONFIGURATIONS
//
++iBuilt;
}
}
//
// Stop routing events to the progress dialog
//
::g_pdlgProgress = NULL;
//
// HIDE PROGRESS DIALOG
//
dlgProgress.ShowWindow( SW_HIDE );
//
// CHECK NUMBER OF BUILT CONFIGURATIONS
//
if ( 0 == iBuilt )
{
this->MessageBox( "No projects have been built. Skipping shutdown mode evaluation.", "Information", MB_ICONINFORMATION );
return bResult;
}
//
// SET FINISH MODE
//
this->m_enuFinishAction = static_cast< EFinishAction > (dlgProgress.m_iFinishedAction);
//
// RETURN RESULT
//
return bResult;
}
//
//---------------------------------------------------------------------------------------------------
//***************************************** HELPERS *****************************************
//---------------------------------------------------------------------------------------------------
//
//***************************************************************************************************
//** AddProject
//***************************************************************************************************
//** @DOC HELPERS
//** @MFUNC Adds the specified project to the dialog
//** @PARM [in] The project's name
//** @PARM [in] The project's path
//** @PARM [in] The workspace's name
//** @PARM [in] The workspace's path
//** @PARM [in] The project's style flags
//** @END
//***************************************************************************************************
//inline
void CDialogBuild::AddProject( const CString& a_strProjectName, const CString& a_strProjectPath, const CString& a_strWorkspaceName, const CString& a_strWorkspacePath, const CString& a_strConfigurations, int a_iStyle )
{
//
// SPLIT CONFIGURATIONS
//
CArray< CString, CString& > arrConfigurations;
CString strConfigurations( a_strConfigurations );
CString strConfiguration ;
int iPos = strConfigurations.Find( ';' );
while ( iPos >= 0 )
{
//
// ADD CONFIGURATION
//
arrConfigurations.Add( strConfigurations.Left( iPos ) );
//
// REMOVE CONFIGURATION
//
strConfigurations = strConfigurations.Right( strConfigurations.GetLength() - iPos - 1 );
//
// FIND NEXT CONFIGURATION
//
iPos = strConfigurations.Find( ';' );
}
if ( ! strConfigurations.IsEmpty() )
{
arrConfigurations.Add( strConfigurations );
}
//
// ADD MISSING CONFIGURATIONS TO THE LIST CONTROL [i know, this can be optimized]
//
for ( int iConfiguration = 0; iConfiguration < arrConfigurations.GetSize(); iConfiguration++ )
{
//
// SETUP SKIP INDICATOR
//
bool bSkip = false;
//
// CHECK EACH ITEM
//
for ( int iItem = 0; iItem < this->m_ctrlListConfigurations.GetItemCount(); iItem++ )
{
strConfiguration = this->m_ctrlListConfigurations.GetItemText( iItem, 0 );
if ( strConfiguration == arrConfigurations[ iConfiguration ] )
{
bSkip = true; // skip this configuration
break; // stop searching
}
}
//
// CHECK FOR SKIP
//
if ( true == bSkip )
{
continue;
}
//
// OK, ADD THE CONFIGURATION
//
this->m_ctrlListConfigurations.InsertItem( 0, arrConfigurations[ iConfiguration ], 0 );
}
}
//***************************************************************************************************
//** MoveItem
//***************************************************************************************************
//** @DOC HELPERS
//** @PARM Swaps the contents of the items at the specified positions
//** @PARM [in] Source item's index
//** @PARM [in] Destination item's index
//** @END
//***************************************************************************************************
//inline
void CDialogBuild::MoveItem( int a_iSrc, int a_iDst )
{
//
// CHECK VALIDITY
//
if ( a_iSrc < 0 ) return;
if ( a_iDst < 0 ) return;
if ( a_iSrc >= this->m_ctrlListConfigurations.GetItemCount() ) return;
if ( a_iDst >= this->m_ctrlListConfigurations.GetItemCount() ) return;
//
// SETUP VARS
//
CString strSwap ;
CString strTemp ;
int iSubItem = 0;
//
// SWAP TEXTs
//
for ( iSubItem = 0; iSubItem < 1; iSubItem++ )
{
//
// STORE DESTINATION IN SWAP MEM
//
strSwap = this->m_ctrlListConfigurations.GetItemText( a_iDst, iSubItem );
//
// COPY SOURCE TO DESTINATION
//
strTemp = this->m_ctrlListConfigurations.GetItemText( a_iSrc, iSubItem );
this->m_ctrlListConfigurations.SetItemText( a_iDst, iSubItem, strTemp.GetBuffer( _MAX_PATH ) );
strTemp.ReleaseBuffer();
//
// COPY SWAP TO SOURCE
//
this->m_ctrlListConfigurations.SetItemText( a_iSrc, iSubItem, strSwap.GetBuffer( _MAX_PATH ) );
strSwap.ReleaseBuffer();
}
//
// SWAP ITEM STATES
//
UINT uiSrc = this->m_ctrlListConfigurations.GetItemState( a_iSrc, (UINT) -1 );
UINT uiDst = this->m_ctrlListConfigurations.GetItemState( a_iDst, (UINT) -1 );
this->m_ctrlListConfigurations.SetItemState( a_iSrc, uiDst, (UINT) -1 );
this->m_ctrlListConfigurations.SetItemState( a_iDst, uiSrc, (UINT) -1 );
}
//
//---------------------------------------------------------------------------------------------------
//**************************************** VIRTUALS *****************************************
//---------------------------------------------------------------------------------------------------
//
//***************************************************************************************************
//** DoDataExchange
//***************************************************************************************************
//** @DOC VIRTUALS
//** @MFUNC Exchanges data between the dialog's members and its controls
//** @PARM [in/out] Pointer to data exchange context
//** @END
//***************************************************************************************************
//inline
void CDialogBuild::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange( pDX );
//{{AFX_DATA_MAP(CDialogBuild)
DDX_Control( pDX, IDC_CONFIGURATIONS, m_ctrlListConfigurations );
DDX_CBIndex( pDX, IDC_BUILD , m_iMode );
//}}AFX_DATA_MAP
}
//
//---------------------------------------------------------------------------------------------------
//**************************************** MESSAGES *****************************************
//---------------------------------------------------------------------------------------------------
//
BEGIN_MESSAGE_MAP( CDialogBuild, CDialog )
//{{AFX_MSG_MAP(CDialogBuild)
ON_BN_CLICKED ( IDC_MOVE_UP , OnMoveUp )
ON_BN_CLICKED ( IDC_MOVE_DOWN , OnMoveDown )
ON_NOTIFY ( NM_CLICK , IDC_CONFIGURATIONS , OnClickConfigurations )
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//***************************************************************************************************
//** OnInitDialog
//***************************************************************************************************
//** @DOC MESSAGES
//** @MFUNC Called to initialize the dialog
//** @END
//***************************************************************************************************
//inline
BOOL CDialogBuild::OnInitDialog()
{
//
// CALL BASE CLASS' IMPLEMENTATION
//
CDialog::OnInitDialog();
//
// MODIFY LIST CONTROL
//
this->m_ctrlListConfigurations.InsertColumn( 0, _T( "Configuration" ), LVCFMT_LEFT, 250, 0 );
this->m_ctrlListConfigurations.SetExtendedStyle( LVS_EX_FULLROWSELECT | LVS_EX_CHECKBOXES );
//
// READ PROFILE
//
this->LoadProfile();
//
// ENABLE AUTO-FOCUS
//
return TRUE;
}
//***************************************************************************************************
//** OnOK
//***************************************************************************************************
//** @DOC MESSAGES
//** @MFUNC Called when OK button is clicked
//** @COMM Executes the current settings, writes the profile and closes the dialog
//** @END
//***************************************************************************************************
//inline
void CDialogBuild::OnOK()
{
//
// EXECUTE
//
this->Execute();
//
// WRITE PROFILE
//
this->WriteProfile();
//
// CALL BASE CLASS' IMPLEMENTATION
//
CDialog::OnOK();
}
//***************************************************************************************************
//** OnMoveUp
//***************************************************************************************************
//** @DOC MESSAGES
//** @MFUNC Called when the MoveUp button is pressed
//** @COMM Moves all selected items one place up while taking care of boundaries.
//** @END
//***************************************************************************************************
//inline
void CDialogBuild::OnMoveUp()
{
//
// SETUP VARS
//
int iPredecessor = 0;
int iItem = 0;
//
// ENUMERATE SELECTED ITEMS
//
POSITION pos = this->m_ctrlListConfigurations.GetFirstSelectedItemPosition();
while ( NULL != pos )
{
//
// GET NEXT SELECTED ITEM'S INDEX
//
iItem = this->m_ctrlListConfigurations.GetNextSelectedItem( pos );
//
// CHECK WHETHER WE CAN MOVE THAT ITEM
//
if ( iItem > iPredecessor )
{
//
// MOVE THAT ITEM
//
this->MoveItem( iItem, iItem - 1 );
//
// KEEP ANY FOLLOWING ITEM FROM REPLACING THIS ITEM
//
iPredecessor = iItem;
}
else
{
//
// THIS ITEM COULD NOT BE MOVED
//
++iPredecessor;
}
}
//
// ENSURE THAT OUR SELECTION IS VISIBLE
//
pos = this->m_ctrlListConfigurations.GetFirstSelectedItemPosition();
if ( NULL != pos )
{
//
// GET FIRST SELECTED ITEM'S POSITION
//
iItem = this->m_ctrlListConfigurations.GetNextSelectedItem( pos );
//
// ENSURE THAT ITEMS's VISIBILITY
//
this->m_ctrlListConfigurations.EnsureVisible( iItem, FALSE );
}
//
// SET THE FOCUS BACK TO THE LIST CONTROL (neccessary in order to have the control re-display its selection)
//
this->m_ctrlListConfigurations.SetFocus();
}
//***************************************************************************************************
//** OnMoveDown
//***************************************************************************************************
//** @DOC MESSAGES
//** @MFUNC Called when the MoveDown button is pressed
//** @COMM Moves all selected items one place down while taking care of boundaries.
//** @END
//***************************************************************************************************
//inline
void CDialogBuild::OnMoveDown()
{
//
// GATHER SELECTED INDICES (for we must process them in reverse order)
//
CArray< int, int > arrSelected ;
POSITION pos = this->m_ctrlListConfigurations.GetFirstSelectedItemPosition();
if ( NULL == pos )
{
return; // avoid messing around with GetUpperBound()
}
while ( NULL != pos )
{
//
// GET NEXT SELECTED ITEM'S INDEX
//
arrSelected.Add( this->m_ctrlListConfigurations.GetNextSelectedItem( pos ) );
}
//
// NOW, PROCESS THE ITEMS
//
int iSuccessor = this->m_ctrlListConfigurations.GetItemCount() - 1;
int iItem = iSuccessor;
int iSelected = 0;
for ( iSelected = arrSelected.GetUpperBound(); iSelected >= 0; iSelected-- )
{
//
// GET ITEM INDEX
//
iItem = arrSelected[ iSelected ];
//
// CHECK WHETHER WE CAN MOVE THE ITEM
//
if ( iItem < iSuccessor )
{
//
// MOVE THAT ITEM
//
this->MoveItem( iItem, iItem + 1 );
//
// PREVENT THAT ITEM FROM BEING OVERRIDEEN
//
iSuccessor = iItem;
}
else
{
//
// COULD NOT MOVE THAT ITEM
//
--iSuccessor;
}
}
//
// ENSURE THAT OUR SELECTION IS VISIBLE
//
pos = this->m_ctrlListConfigurations.GetFirstSelectedItemPosition();
while ( NULL != pos )
{
//
// GET LAST SELECTED ITEM'S POSITION
//
iItem = this->m_ctrlListConfigurations.GetNextSelectedItem( pos );
}
//
// ENSURE THAT ITEMS's VISIBILITY
//
this->m_ctrlListConfigurations.EnsureVisible( iItem, FALSE );
//
// SET THE FOCUS BACK TO THE LIST CONTROL (neccessary in order to have the control re-display its selection)
//
this->m_ctrlListConfigurations.SetFocus();
}
//***************************************************************************************************
//** OnClickConfigurations
//***************************************************************************************************
//** @DOC MESSAGES
//** @MFUNC Called when the user clicks within the configurations' list control
//** @COMM Assures that when the user (un-)checks a selected item, all other selected items
//** will have the same check state.
//** @END
//***************************************************************************************************
//inline
void CDialogBuild::OnClickConfigurations( NMHDR* pNMHDR, LRESULT* pResult )
{
//
// GET LIST VIEW NOTIFICATION HEADER
//
NMLISTVIEW* pNMListView = reinterpret_cast< NMLISTVIEW* > (pNMHDR);
//
// WE'RE ONLY INTERESTED IN CLICKS ON A SELECTED ITEM'S CHECK BOX
//
if ( pNMListView->ptAction.x >= 16 )
{
return; // not the check box [@HACK: assumes checkboxes are always 16 pixels wide]
}
if ( LVIS_SELECTED != this->m_ctrlListConfigurations.GetItemState( pNMListView->iItem, LVIS_SELECTED ) )
{
return; // not selected
}
//
// GET THE ITEM's CHECK STATE
//
BOOL bChecked = this->m_ctrlListConfigurations.GetCheck( pNMListView->iItem );
//
// SET INVERSE CHECK STATE FOR ALL SELECTED ITEMS EXCEPT THIS ONE
//
POSITION pos = this->m_ctrlListConfigurations.GetFirstSelectedItemPosition();
while( NULL != pos )
{
//
// GET NEXT SELECTED ITEM'S INDEX
//
int iItem = this->m_ctrlListConfigurations.GetNextSelectedItem( pos );
//
// CHECK FOR CURRENT ITEM
//
if ( iItem == pNMListView->iItem )
{
continue;
}
//
// SET INVERSE CHECK
//
this->m_ctrlListConfigurations.SetCheck( iItem, bChecked ? FALSE : TRUE );
}
//
// RETURN RESULT
//
*pResult = 0;
}
//***************************************************************************************************
//** OnBuildFinished
//***************************************************************************************************
//** @DOC MESSAGES
//** @MFUNC Called when DevStuido signals that a build has finished
//** @PARM [in] The number of errors
//** @PARM [in] The number of warnings
//** @COMM This is a plain proxy method that delegates the event further to the current
//** progress dialog (if any).
//** @END
//***************************************************************************************************
//inline
void CDialogBuild::OnBuildFinished( long a_lErrors, long a_lWarnings )
{
//
// CHECK WHETHER WE ARE URRENTLY IN THE MIDDLE OF A BUILD
//
if ( NULL == ::g_pdlgProgress )
{
return;
}
//
// ROUTE THE EVENT TO THE PROGRESS DIALOG
//
::g_pdlgProgress->OnBuildFinished( a_lErrors, a_lWarnings );
}