/**********************************************************************
UML StateWizard provides its software under the LGPL License and
zlib/libpng License.
Email us at info@intelliwizard.com for any information, suggestions and
feature requestions.
Home Page: http://www.intelliwizard.com
*************************************************************************/
// AddAppDLg.cpp : implementation file
//
#include "stdafx.h"
#include "StateTree.h"
#include "AddAppDLg.h"
// AddAppDlg.cpp : implementation file
//
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#ifdef _DUMMY_DEBUG
#define new SME_DEBUG_NEW
#define delete SME_DEBUG_DELETE
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CAddAppDlg dialog
// Request to ignore 2 file item update events: .c/.cpp and .h
extern int g_nIgnoreFileItemUpdateNum;
CAddAppDlg::CAddAppDlg(CWnd* pParent /*=NULL*/)
: CDialog(CAddAppDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CAddAppDlg)
m_entryHdlName = _T("");
m_exitHdlName = _T("");
m_appStateName = _T("");
m_parentStateName = _T("");
//}}AFX_DATA_INIT
}
void CAddAppDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAddAppDlg)
DDX_Text(pDX, IDC_ENTRY_HANDLER_EDIT, m_entryHdlName);
DDX_Text(pDX, IDC_EXIT_HANDLER_EDIT, m_exitHdlName);
DDX_Text(pDX, IDC_APP_STATE_NAME_EDIT, m_appStateName);
DDX_Text(pDX, IDC_STATIC_APP_NAME, m_parentStateName);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAddAppDlg, CDialog)
//{{AFX_MSG_MAP(CAddAppDlg)
ON_EN_CHANGE(IDC_APP_STATE_NAME_EDIT, OnAppNameEditTextChange)
ON_WM_DESTROY()
ON_BN_CLICKED(IDC_ENTRY_CHECK, OnEntryCheck)
ON_BN_CLICKED(IDC_EXIT_CHECK, OnExitCheck)
ON_WM_HELPINFO()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CAddAppDlg message handlers
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Initialize the AddApp(state) dialog
// INPUT: None
// OUTPUT: None
// Note:
///////////////////////////////////////////////////////////////////////////////////////////
BOOL CAddAppDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Check the check box of entry and exit functions initially
((CButton*)GetDlgItem(IDC_ENTRY_CHECK))->SetCheck(1);
((CButton*)GetDlgItem(IDC_EXIT_CHECK))->SetCheck(1);
// TODO: Add extra initialization here
HTREEITEM hSelector = m_pStateTree->tree.GetSelectedItem();
if (m_pStateTree->tree.GetItemData(hSelector) & STATE_TREE_APPLICATION_MASK)
{
CString sAppName;
sAppName = m_pStateTree->tree.GetItemText(hSelector);
SetWindowText("Add a New State");
((CStatic*)GetDlgItem(IDC_STATIC_APP_OR_STATE))->SetWindowText("State Name:");
((CStatic*)GetDlgItem(IDC_STATIC_APP_NAME))->SetWindowText(sAppName);
}
else if (m_pStateTree->tree.GetItemData(hSelector) & STATE_TREE_STATE_MASK)
{
CString sStateName;
sStateName = m_pStateTree->tree.GetItemText(hSelector);
if (m_pStateTree->tree.GetItemData(hSelector) & STATE_TREE_DEFAULT_STATE)
{
int idx = sStateName.Find(" (default)");
sStateName = sStateName.Left(idx);
}
SetWindowText("Add a New State");
((CStatic*)GetDlgItem(IDC_STATIC_APP_OR_STATE))->SetWindowText("State Name:");
((CStatic*)GetDlgItem(IDC_STATIC_APP_NAME))->SetWindowText(sStateName);
}
else
{
SetWindowText("Add a New Application");
((CStatic*)GetDlgItem(IDC_STATIC_APP_OR_STATE))->SetWindowText("Application Name:");
((CStatic*)GetDlgItem(IDC_STATIC_APP_NAME))->SetWindowText("No Parent Application or State");
}
((CButton*)GetDlgItem(IDOK))->EnableWindow(FALSE);
//. SME_TRACE("Create add application dialog!\n");
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Automatically creating two child nodes(entry function, exit function)
// under new state or application node in state tree
// INPUT: None
// OUTPUT: None
// Note: It will only be invoked by OnOk method
///////////////////////////////////////////////////////////////////////////////////////////
void CAddAppDlg::AddEntryExitHandlers()
{
CString sEntryHdlItem = "Entry: ";
CString sExitHdlItem = "Exit: ";
HTREEITEM hSelector = NULL;
HTREEITEM hInsert = NULL;
hSelector = m_pStateTree->tree.GetSelectedItem();
/* retrieve the entry function name */
if (((CButton*)GetDlgItem(IDC_ENTRY_CHECK))->GetCheck() == 1)
{
sEntryHdlItem += m_entryHdlName;
sEntryHdlItem += STR_HDLER_PROTOTYPE;
}
hInsert = m_pStateTree->tree.InsertItem((LPCTSTR)(sEntryHdlItem), 4, 4, hSelector, TVI_LAST);
m_pStateTree->tree.SetItemData(hInsert, STATE_TREE_ENTRY_EXIT_HANDLER_MASK);
m_pStateTree->tree.SetItemImage(hInsert, 4, 4);
/* retrieve the exit function name */
if (((CButton*)GetDlgItem(IDC_EXIT_CHECK))->GetCheck() == 1)
{
sExitHdlItem += m_exitHdlName;
sExitHdlItem += STR_HDLER_PROTOTYPE;
}
hInsert = m_pStateTree->tree.InsertItem((LPCTSTR)(sExitHdlItem), 4, 4, hSelector, TVI_LAST);
m_pStateTree->tree.SetItemData(hInsert, STATE_TREE_ENTRY_EXIT_HANDLER_MASK);
m_pStateTree->tree.SetItemImage(hInsert, 4, 4);
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Response to ok button click
// INPUT: None
// OUTPUT: None
// Note:
///////////////////////////////////////////////////////////////////////////////////////////
void CAddAppDlg::OnOK()
{
// TODO: Add extra validation here
UpdateData(TRUE);
// Trim space at the beginning and the end of the name
m_appStateName.TrimLeft();
m_appStateName.TrimRight();
m_entryHdlName.TrimLeft();
m_entryHdlName.TrimRight();
m_exitHdlName.TrimLeft();
m_exitHdlName.TrimRight();
if (m_appStateName.Find(' ') != -1 || m_appStateName.Find('\t') != -1 || m_appStateName.IsEmpty() ||
((((CButton*)GetDlgItem(IDC_ENTRY_CHECK))->GetCheck() == 1) && (m_entryHdlName.Find(' ') != -1 || m_entryHdlName.Find('\t') != -1 || m_entryHdlName.IsEmpty())) ||
((((CButton*)GetDlgItem(IDC_EXIT_CHECK))->GetCheck() == 1) && (m_exitHdlName.Find(' ') != -1 || m_exitHdlName.Find('\t') != -1 || m_exitHdlName.IsEmpty())))
{
AfxMessageBox("Application(state, exit action, entry action) name can not contain any white space.", MB_ICONERROR|MB_OK);
return;
}
int nCharSeq = 0;
while (true)
{
if (nCharSeq >= m_appStateName.GetLength())
break;
char ch = m_appStateName.GetAt(nCharSeq);
if (nCharSeq == 0)
{
// The first character must be alphabetic or underline
if (!((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || ch == '_'))
{
AfxMessageBox("First letter in an application(state) name must be '[A-Za-z|_]'.", MB_ICONERROR|MB_OK);
return;
}
}
else
{
if (!((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || ch == '_' || (ch >= '0' && ch <= '9')))
{
AfxMessageBox("Letters in an application(state) name must be '[A-Za-z|0-9|_]'.", MB_ICONERROR|MB_OK);
return;
}
}
nCharSeq++;
}
CString sAddItemName;
CString strDefault = " (default)";
CString sParentName;
CString sDefaultStateName = "";
HTREEITEM hSelector = NULL;
HTREEITEM hInsert = NULL;
HTREEITEM hSelApp = NULL; // Selected application
DWORD lMask = 0;
DWORD lParam = 0;
TV_INSERTSTRUCT Inserter; // Define insert item structure
CString strHdrFullPath;
CString strSrcFullPath;
hSelector = m_pStateTree->tree.GetSelectedItem();
if(hSelector)
{
// Get application item covering current selected tree item in state tree
hSelApp = m_pStateTree->tree.GetSelectedApp(hSelector);
CString sAppName = m_pStateTree->tree.GetItemText(hSelApp);
CString sAppClass = m_pStateTree->tree.GetSelectedAppClass(hSelector);
CString sFuncClassPrefix;
if (!sAppClass.IsEmpty()) sFuncClassPrefix+= sAppClass + "::";
lMask = m_pStateTree->tree.GetItemData(hSelector);
DWORD lParentMask = lMask;
if (lMask & STATE_TREE_PROJECT_MASK)
{// Add a new application
Inserter.item.lParam = STATE_TREE_APPLICATION_MASK;
// Get parent item text(current project name)
sParentName = m_pStateTree->tree.GetItemText(hSelector);
sParentName.Replace(" application(s)", NULL);
sParentName.TrimLeft();
sParentName.TrimRight();
// Get new application name
sAddItemName = m_appStateName;
hSelApp = hSelector;
lParam = STATE_TREE_APPLICATION_MASK; // Check only application redundancy
}
else
{// Add a new state
Inserter.item.lParam = STATE_TREE_STATE_MASK;
// Get parent tree item name
sParentName = m_parentStateName;
// Get new state name
// sAddItemName = "State name: ";
sAddItemName = "";
if (!(lMask & STATE_TREE_HAS_DEFAULT_CHILD_STATE))
{
lMask |= STATE_TREE_HAS_DEFAULT_CHILD_STATE;
Inserter.item.lParam |= STATE_TREE_DEFAULT_STATE;
sAddItemName = sAddItemName+m_appStateName+strDefault;
sDefaultStateName = m_appStateName;
}
else
sAddItemName += m_appStateName;
lParam = STATE_TREE_APPLICATION_MASK|STATE_TREE_STATE_MASK; // Check app and state redundancy
}
// Check redundancy
if (!m_pStateTree->tree.TraverseStateTree(hSelApp, m_appStateName, lParam, NULL))
{
MessageBox("Error!\nThe name already exists. Please choose another application(state) name.", NULL ,MB_OK|MB_ICONERROR);
return;
}
m_pStateTree->tree.SetItemData(hSelector, lMask);
// Retrieve DSUtils object
if (lMask & STATE_TREE_PROJECT_MASK)
{
if (((CButton*)GetDlgItem(IDC_ENTRY_CHECK))->GetCheck() == 0)
m_entryHdlName = "SME_NULL";
if (((CButton*)GetDlgItem(IDC_EXIT_CHECK))->GetCheck() == 0)
m_exitHdlName = "SME_NULL";
// Check do-all-or-nothing
// Request to ignore 2 file item update events: .c/.cpp and .h
// If checking is OK, it will add these 2 files and then trigger ItemAdded event.
g_nIgnoreFileItemUpdateNum =2;
//!!! Update Interface
//!!! From CString To BSTR & In Lack Of 1 Parameters
BSTR bstrParentName = _com_util::ConvertStringToBSTR(sParentName.GetBuffer());
sParentName.ReleaseBuffer();
BSTR bstrAppStateName= _com_util::ConvertStringToBSTR(m_appStateName.GetBuffer());
m_appStateName.ReleaseBuffer();
m_pStateTree->Fire_CheckAddAppAtomic(bstrParentName, bstrAppStateName);
if(!m_pStateTree->data.isAddAppAtomic)
{
// If checking fail, it will not add these 2 files,roll back .
g_nIgnoreFileItemUpdateNum =0;
// CDialog::OnOK(); // Allow to try again.
return;
}
//!!! Update Interface
//!!! From CString to BSTR & In Lack Of 1 Parameter
bstrParentName = _com_util::ConvertStringToBSTR(sParentName.GetBuffer());
bstrAppStateName= _com_util::ConvertStringToBSTR(m_appStateName.GetBuffer());
BSTR bstrEntryHdlName = _com_util::ConvertStringToBSTR(m_entryHdlName.GetBuffer());
BSTR bstrExitHdlName = _com_util::ConvertStringToBSTR(m_exitHdlName.GetBuffer());
m_pStateTree->Fire_CreateAppFiles(bstrParentName, bstrAppStateName, bstrEntryHdlName, bstrExitHdlName);
sParentName.ReleaseBuffer();
m_appStateName.ReleaseBuffer();
m_entryHdlName.ReleaseBuffer();
m_exitHdlName.ReleaseBuffer();
if(!m_pStateTree->data.isCreateAppFilesOk)
{
CDialog::OnOK();
return;
}
}
else
{
int nTotalStateNum = 0;
m_pStateTree->tree.CountBeforehandAppState(hSelApp, NULL, &nTotalStateNum);
//limit hierarchy num
/*
#ifdef EVALUATE_VER
if (nTotalStateNum > 16)
{
AfxMessageBox("Please buy official version!");
CDialog::OnOK();
return;
}
#endif
*/
int nSkippedLineNum = 0;
if ((lParentMask & STATE_TREE_HAS_DEFAULT_CHILD_STATE) == 0)
{
m_pStateTree->tree.CountBeforehandAppState(hSelApp, hSelector, &nSkippedLineNum);
nSkippedLineNum++;
}
else
{
HTREEITEM hChild = m_pStateTree->tree.GetChildItem(hSelector);
HTREEITEM hClosetSibling = NULL;
while (true)
{
while (true)
{
if (NULL == hChild)
break;
if (m_pStateTree->tree.GetItemData(hChild) & STATE_TREE_STATE_MASK)
{
hClosetSibling = hChild;
// CString sTemp = m_pStateTree->tree.GetItemText(hClosetSibling);
}
hChild = m_pStateTree->tree.GetNextSiblingItem(hChild);
}
if ((m_pStateTree->tree.GetItemData(hClosetSibling) & STATE_TREE_HAS_DEFAULT_CHILD_STATE) == 0)
break;
else
hChild = m_pStateTree->tree.GetChildItem(hClosetSibling);
}
m_pStateTree->tree.CountBeforehandAppState(hSelApp, hClosetSibling, &nSkippedLineNum);
nSkippedLineNum++;
}
CStringArray AppPathList;
AppPathList.RemoveAll();
m_pStateTree->GetAppSrcHdrPath(AppPathList, sAppName, hSelApp);
strHdrFullPath = AppPathList.GetAt(0);
strSrcFullPath = AppPathList.GetAt(1);
if (((CButton*)GetDlgItem(IDC_ENTRY_CHECK))->GetCheck() == 0)
m_entryHdlName = "SME_NULL";
if (((CButton*)GetDlgItem(IDC_EXIT_CHECK))->GetCheck() == 0)
m_exitHdlName = "SME_NULL";
//!!! Update Interface
//!!! From CString to BSTR
BSTR bstrSrcFullPath =_com_util::ConvertStringToBSTR(strSrcFullPath.GetBuffer());
BSTR bstrHdrFullPath =_com_util::ConvertStringToBSTR(strHdrFullPath.GetBuffer());
BSTR bstrAppStateName =_com_util::ConvertStringToBSTR(m_appStateName.GetBuffer());
BSTR bstrParentName =_com_util::ConvertStringToBSTR(sParentName.GetBuffer());
BSTR bstrAppName =_com_util::ConvertStringToBSTR(sAppName.GetBuffer());
BSTR bstrFuncClassPrefix =_com_util::ConvertStringToBSTR(sFuncClassPrefix.GetBuffer());
BSTR bstrDefaultStateName =_com_util::ConvertStringToBSTR(sDefaultStateName.GetBuffer());
BSTR bstrEntryHdlName =_com_util::ConvertStringToBSTR(m_entryHdlName.GetBuffer());
BSTR bstrExitHdlName =_com_util::ConvertStringToBSTR(m_exitHdlName.GetBuffer());
m_pStateTree->Fire_CheckAddStateAtomic(bstrSrcFullPath, bstrHdrFullPath, bstrAppStateName, bstrParentName, bstrAppName, bstrFuncClassPrefix
, bstrDefaultStateName,(ULONG)nSkippedLineNum, bstrEntryHdlName, bstrExitHdlName);
strSrcFullPath.ReleaseBuffer();
strHdrFullPath.ReleaseBuffer();
m_appStateName.ReleaseBuffer();
sParentName.ReleaseBuffer();
sAppName.ReleaseBuffer();
sDefaultStateName.ReleaseBuffer();
m_entryHdlName.ReleaseBuffer();
m_exitHdlName.ReleaseBuffer();
if(!m_pStateTree->data.isAddStateAtomic){
CDialog::OnOK();
return;
}
}
// Insert new state or application into state tree
CString sTemp = m_pStateTree->tree.GetItemText(hSelector);
Inserter.hParent = hSelector;
if (lMask & STATE_TREE_PROJECT_MASK)
Inserter.hInsertAfter = TVI_SORT;
else
Inserter.hInsertAfter = TVI_LAST;// Insert position
Inserter.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE;// Set mask
Inserter.item.pszText = (LPTSTR)(LPCTSTR)(sAddItemName);
hInsert= m_pStateTree->tree.InsertItem(&Inserter);// Do insert
int nImage = (lMask & STATE_TREE_PROJECT_MASK)? 2: 3;
m_pStateTree->tree.SetItemImage(hInsert, nImage, nImage);
m_pStateTree->tree.SelectItem(hInsert);
AddEntryExitHandlers();
TV_SORTCB SortCB;
SortCB.hParent = hSelector;
SortCB.lpfnCompare = CompareFunc;
SortCB.lParam = 0;
m_pStateTree->tree.SortChildrenCB(&SortCB);
BOOL bHandler = TRUE;
if (nImage == 2) // I think it does not need to refresh...?????
m_pStateTree->OnRefresh(0,0,0,bHandler);
}
CDialog::OnOK();
// Acivate c file;
// Note: On adding app, strSrcFullPath is empty.
if (!strSrcFullPath.IsEmpty())
m_pStateTree->Fire_OpenFileAndMoveLineTo(CComBSTR(strSrcFullPath), -1);
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Set the application name as prefix for entry and exit function
// INPUT: None
// OUTPUT: None
// Note:
///////////////////////////////////////////////////////////////////////////////////////////
void CAddAppDlg::OnAppNameEditTextChange()
{
// TODO: If this is a RICHEDIT control, the control will not
// send this notification unless you override the CDialog::OnInitDialog()
// function and call CRichEditCtrl().SetEventMask()
// with the ENM_CHANGE flag ORed into the mask.
// TODO: Add your control notification handler code here
UpdateData(TRUE);
m_appStateName.TrimLeft();
m_appStateName.TrimRight();
if (m_appStateName.GetLength() == 0)
{
((CButton*)GetDlgItem(IDOK))->EnableWindow(FALSE);
((CEdit*)GetDlgItem(IDC_ENTRY_HANDLER_EDIT))->SetWindowText(m_appStateName);
((CEdit*)GetDlgItem(IDC_EXIT_HANDLER_EDIT))->SetWindowText(m_appStateName);
}
else
{
((CButton*)GetDlgItem(IDOK))->EnableWindow(TRUE);
((CEdit*)GetDlgItem(IDC_ENTRY_HANDLER_EDIT))->SetWindowText(m_appStateName+"Entry");
((CEdit*)GetDlgItem(IDC_EXIT_HANDLER_EDIT))->SetWindowText(m_appStateName+"Exit");
}
}
void CAddAppDlg::OnDestroy()
{
CDialog::OnDestroy();
// TODO: Add your message handler code here
/* SME_TRACE("Destroy add application dialog!\n");
SME_ALLOC_MEM_SIZE();
*/
}
void CAddAppDlg::OnEntryCheck()
{
// TODO: Add your control notification handler code here
if (((CButton*)GetDlgItem(IDC_ENTRY_CHECK))->GetCheck() == 0)
((CEdit*)GetDlgItem(IDC_ENTRY_HANDLER_EDIT))->EnableWindow(FALSE);
else
((CEdit*)GetDlgItem(IDC_ENTRY_HANDLER_EDIT))->EnableWindow(TRUE);
}
void CAddAppDlg::OnExitCheck()
{
// TODO: Add your control notification handler code here
if (((CButton*)GetDlgItem(IDC_EXIT_CHECK))->GetCheck() == 0)
((CEdit*)GetDlgItem(IDC_EXIT_HANDLER_EDIT))->EnableWindow(FALSE);
else
((CEdit*)GetDlgItem(IDC_EXIT_HANDLER_EDIT))->EnableWindow(TRUE);
}
BOOL CAddAppDlg::OnHelpInfo(HELPINFO* pHelpInfo)
{
// TODO: Add your message handler code here and/or call default
HTREEITEM hSelector;
DWORD lMask;
hSelector = m_pStateTree->tree.GetSelectedItem();
lMask = m_pStateTree->tree.GetItemData(hSelector);
CString sCmdName = GetHelpFileName();
if (lMask & STATE_TREE_PROJECT_MASK)
{
//DSUtils(m_pStateTree->tree.m_pApp).GotoWinHelp(0x4F);
sCmdName += "::/new_state.htm";
::HtmlHelp(NULL, sCmdName, HH_DISPLAY_TOPIC, 0);
}
else
{
//DSUtils(m_pStateTree->tree.m_pApp).GotoWinHelp(0x50);
sCmdName += "::/new_application.htm";
::HtmlHelp(NULL, sCmdName, HH_DISPLAY_TOPIC, 0);
}
return TRUE;
// return CDialog::OnHelpInfo(pHelpInfo);
}