#include "stdafx.h" #include "GaugeRepo.h" #pragma comment(lib, "shlwapi") #ifndef INVALID_FILE_ATTRIBUTES # define INVALID_FILE_ATTRIBUTES ((DWORD)-1) #endif CGaugeRepo::~CGaugeRepo() { Cleanup(); } BOOL CGaugeRepo::Load(LPCTSTR pPath) { if (!XTP_ASSERT_CHECK(NULL != pPath)) return FALSE; DWORD dwAttr = ::GetFileAttributes(pPath); if (!XTP_ASSERT_CHECK(INVALID_FILE_ATTRIBUTES != dwAttr && 0 != (dwAttr & FILE_ATTRIBUTE_DIRECTORY))) return FALSE; Cleanup(); m_strPath = pPath; ProcessTree(pPath); DumpGaugeList(pPath); return TRUE; } INT_PTR CGaugeRepo::GetCount() const { return m_items.GetCount(); } const CGaugeRepo::RepoItem* CGaugeRepo::GetItem(INT_PTR nIndex) { if (!XTP_ASSERT_CHECK(nIndex < GetCount())) return NULL; POSITION pos = m_items.FindIndex(nIndex); if (NULL == pos) return NULL; return &m_items.GetAt(pos); } BOOL CGaugeRepo::EnumFiles(BOOL bFiles, LPCTSTR pPath, EnumFilesCallback pCallback) { if (!XTP_ASSERT_CHECK(NULL != pPath)) return FALSE; if (!XTP_ASSERT_CHECK(NULL != pCallback)) return FALSE; WIN32_FIND_DATA fdata = { 0 }; HANDLE hFind = ::FindFirstFile(CString(pPath) + _T("\\*.*"), &fdata); if (INVALID_HANDLE_VALUE == hFind) return FALSE; do { BOOL bIsFile = (0 == (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)); if (bFiles != bIsFile) continue; if (!bIsFile && (0 == _tcscmp(fdata.cFileName, _T(".")) || 0 == _tcscmp(fdata.cFileName, _T("..")))) continue; (this->*pCallback)(CString(pPath) + _T("\\") + fdata.cFileName); } while (::FindNextFile(hFind, &fdata)); ::FindClose(hFind); return TRUE; } void CGaugeRepo::ProcessTree(LPCTSTR pPath) { if (!XTP_ASSERT_CHECK(NULL != pPath)) return; LPCTSTR pRelPath = pPath + m_strPath.GetLength(); if (_T('\\') == *pRelPath) ++pRelPath; m_current.strRelativePath = pRelPath; CString strTraitsPath = CString(pPath) + _T("\\traits.js"); BOOL bTraitsFound = (0 == (::GetFileAttributes(strTraitsPath) & FILE_ATTRIBUTE_DIRECTORY)); CString strStylePath = CString(pPath) + _T("\\style.xaml"); BOOL bStyleFound = (0 == (::GetFileAttributes(strStylePath) & FILE_ATTRIBUTE_DIRECTORY)); if (bStyleFound) m_current.strStylePath = strStylePath; if (!bTraitsFound) { EnumFiles(FALSE, pPath, &CGaugeRepo::ProcessTree); m_current.strStylePath = _T(""); return; } m_current.strTraitsPath = strTraitsPath; m_nGauges = 0; EnumFiles(FALSE, pPath, &CGaugeRepo::ProcessGauges); if (0 == m_nGauges) { int n = m_current.strRelativePath.ReverseFind(_T('\\')); if (0 <= n) m_current.strRelativePath = m_current.strRelativePath.Left(n); ProcessGauges(pPath); } m_current.strTraitsPath = _T(""); } void CGaugeRepo::ProcessGauges(LPCTSTR pPath) { _ASSERTE(NULL != pPath); _ASSERTE(!m_current.strRelativePath.IsEmpty()); _ASSERTE(!m_current.strStylePath.IsEmpty()); _ASSERTE(!m_current.strTraitsPath.IsEmpty()); m_items.AddTail(m_current); RepoItem& item = m_items.GetTail(); item.strPath = pPath; item.strName = ::PathFindFileName(pPath); CString strPreviewPath = item.strPath + _T("\\preview.png"); item.pPreviewImg = LoadPreview(strPreviewPath); if (NULL != item.pPreviewImg) item.strPreviewPath = strPreviewPath; CString strTraitsInitPath = item.strPath + _T("\\init_traits.json"); if (0 == (::GetFileAttributes(strTraitsInitPath) & FILE_ATTRIBUTE_DIRECTORY)) item.strInitTraitsPath = strTraitsInitPath; ++m_nGauges; } CXTPGraphicBitmapPng* CGaugeRepo::LoadPreview(LPCTSTR pPath) { if (!XTP_ASSERT_CHECK(NULL != pPath)) return NULL; DWORD dwAttrib = ::GetFileAttributes(pPath); if (INVALID_FILE_ATTRIBUTES == dwAttrib || 0 != (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) return NULL; CXTPGraphicBitmapPng* pPreview = new CXTPGraphicBitmapPng(); if (!pPreview->LoadFromFile(pPath)) { delete pPreview; return NULL; } return pPreview; } void CGaugeRepo::Cleanup() { POSITION pos = m_items.GetHeadPosition(); while (NULL != pos) { RepoItem& item = m_items.GetNext(pos); SAFE_DELETE(item.pPreviewImg); } m_items.RemoveAll(); m_current = RepoItem(); } static BOOL FindTreeFile(LPCTSTR pStartPath, LPCTSTR pFileName, CString& strPath, BOOL bRecursive = TRUE) { if (!XTP_ASSERT_CHECK(NULL != pStartPath)) return FALSE; if (!XTP_ASSERT_CHECK(NULL != pFileName)) return FALSE; TCHAR szFullPath[MAX_PATH + 1]; TCSNCCPY_S(szFullPath, _countof(szFullPath), pStartPath, _tcslen(pStartPath)); if (!::PathAppend(szFullPath, pFileName)) return FALSE; while (TRUE) { if (0 == (::GetFileAttributes(szFullPath) & FILE_ATTRIBUTE_DIRECTORY)) { strPath = szFullPath; return TRUE; } if (!bRecursive) return FALSE; if (!::PathRemoveFileSpec(szFullPath)) return FALSE; if (!::PathRemoveFileSpec(szFullPath)) return FALSE; if (!::PathAppend(szFullPath, pFileName)) return FALSE; } } CGaugeRepo::RepoItem* CGaugeRepo::Find(LPCTSTR pPath, BOOL bLoadPreview /*= FALSE*/) { if (!XTP_ASSERT_CHECK(NULL != pPath)) return NULL; CString strTraitsPath; if (!FindTreeFile(pPath, _T("traits.js"), strTraitsPath)) return NULL; CString strStylePath; if (!FindTreeFile(pPath, _T("style.xaml"), strStylePath)) return NULL; CString strInitTraitsPath; FindTreeFile(pPath, _T("init_traits.json"), strInitTraitsPath, FALSE); RepoItem* pItem = new RepoItem(); pItem->strPath = pPath; pItem->strName = ::PathFindFileName(pPath); pItem->strTraitsPath = strTraitsPath; pItem->strStylePath = strStylePath; pItem->strInitTraitsPath = strInitTraitsPath; if (bLoadPreview) pItem->pPreviewImg = LoadPreview(CString(pPath) + _T("\\preview.png")); return pItem; } void CGaugeRepo::DumpGaugeList(LPCTSTR pPath) { if (!XTP_ASSERT_CHECK(NULL != pPath)) return; CStdioFile listFile; if (!listFile.Open(CString(pPath) + _T("\\gauges.lst"), CFile::modeCreate | CFile::modeWrite | CFile::typeText)) { TRACE(_T("Failed to create gauges.lst file\n")); return; } size_t nPathLen = _tcslen(pPath); // File format: // Name:RelativePath:StylePath:TraitsPath:InitTraitsPath:PreviewPath POSITION pos = m_items.GetHeadPosition(); while (NULL != pos) { const RepoItem& item = m_items.GetNext(pos); LPCTSTR pRelativeStyle = item.strStylePath.operator LPCTSTR() + nPathLen; LPCTSTR pRelativeTraits = item.strTraitsPath.operator LPCTSTR() + nPathLen; LPCTSTR pRelativeInitTraits = _T(""); if (!item.strInitTraitsPath.IsEmpty()) pRelativeInitTraits = item.strInitTraitsPath.operator LPCTSTR() + nPathLen; LPCTSTR pRelativePreview = _T(""); if (!item.strPreviewPath.IsEmpty()) pRelativePreview = item.strPreviewPath.operator LPCTSTR() + nPathLen; CString strLine; strLine.Format(_T("%s:%s:%s:%s:%s:%s\n"), item.strName.operator LPCTSTR(), item.strRelativePath.operator LPCTSTR(), pRelativeStyle, pRelativeTraits, pRelativeInitTraits, pRelativePreview); listFile.WriteString(strLine); } }