795 lines
20 KiB
C++
795 lines
20 KiB
C++
// ==========================================================================
|
|
// Class Implementation : COXPropertiesWnd
|
|
// ==========================================================================
|
|
|
|
// Source file : OXPropertiesWnd.cpp
|
|
|
|
// Version: 9.3
|
|
|
|
// This software along with its related components, documentation and files ("The Libraries")
|
|
// is © 1994-2007 The Code Project (1612916 Ontario Limited) and use of The Libraries is
|
|
// governed by a software license agreement ("Agreement"). Copies of the Agreement are
|
|
// available at The Code Project (www.codeproject.com), as part of the package you downloaded
|
|
// to obtain this file, or directly from our office. For a copy of the license governing
|
|
// this software, you may contact us at legalaffairs@codeproject.com, or by calling 416-849-8900.
|
|
|
|
#include "stdafx.h"
|
|
#include "OXPropertiesWnd.h"
|
|
#include "OXListEdit.h"
|
|
#include "OXMaskedEdit.h"
|
|
#include "OXSkins.h"
|
|
|
|
#ifdef _DEBUG
|
|
#define new DEBUG_NEW
|
|
#undef THIS_FILE
|
|
static char THIS_FILE[] = __FILE__;
|
|
#endif
|
|
|
|
#pragma warning(disable : 4355)
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COXPropertiesWnd
|
|
|
|
COXPropertiesWnd::COXPropertiesWnd() :
|
|
m_wndTree(this)
|
|
{
|
|
m_bSortCategories = TRUE;
|
|
m_bCategorized = TRUE;
|
|
m_hCurrentProp = NULL;
|
|
m_pEditWnd = NULL;
|
|
m_hEditProp = NULL;
|
|
m_pFrameSkin = NULL;
|
|
}
|
|
|
|
COXPropertiesWnd::~COXPropertiesWnd()
|
|
{
|
|
m_mapProp2Cat.RemoveAll();
|
|
m_mapProp2Desc.RemoveAll();
|
|
m_mapProp2Editor.RemoveAll();
|
|
m_listCategories.RemoveAll();
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(COXPropertiesWnd, CFrameWnd)
|
|
//{{AFX_MSG_MAP(COXPropertiesWnd)
|
|
ON_WM_CREATE()
|
|
ON_WM_SIZE()
|
|
ON_COMMAND(ID_CATEGORIZED, OnCategorized)
|
|
ON_COMMAND(ID_ALPHABETIC, OnAlphabetic)
|
|
ON_WM_PAINT()
|
|
ON_UPDATE_COMMAND_UI(ID_CATEGORIZED, OnUpdateCategorized)
|
|
ON_UPDATE_COMMAND_UI(ID_ALPHABETIC, OnUpdateAlphabetic)
|
|
//}}AFX_MSG_MAP
|
|
ON_NOTIFY(LVN_ITEMCHANGED, _TREE_ID, OnItemChanged)
|
|
ON_MESSAGE(WM_USER_QUERY_PROPERTIESWND, OnQueryPropertiesWnd)
|
|
ON_MESSAGE(WM_USER_STARTEDITING, OnStartEditing)
|
|
ON_MESSAGE(WM_USER_ADJUSTLASTCOLUMN, OnUserAdjustLastColumn)
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// COXPropertiesWnd message handlers
|
|
|
|
int COXPropertiesWnd::OnCreate(LPCREATESTRUCT lpCreateStruct)
|
|
{
|
|
if (CFrameWnd::OnCreate(lpCreateStruct) == -1)
|
|
return -1;
|
|
|
|
ModifyStyleEx(WS_EX_CLIENTEDGE, 0);
|
|
|
|
// Create the combo
|
|
if (!m_wndCombo.Create(WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST, CRect(0, 0, 0, 300), this, _COMBO_ID))
|
|
{
|
|
TRACE0("Failed to create the combo box.\n");
|
|
return -1; // fail to create
|
|
}
|
|
|
|
// Create the toolbar
|
|
if (!m_wndToolBar.Create(this,
|
|
WS_CHILD | WS_VISIBLE | CBRS_TOP | CBRS_TOOLTIPS | CBRS_FLYBY | CBRS_SIZE_DYNAMIC,
|
|
IDR_PROPERTIES_TOOLBAR) || !m_wndToolBar.LoadToolBar(IDR_PROPERTIES_TOOLBAR))
|
|
{
|
|
TRACE0("Failed to create toolbar.\n");
|
|
return -1; // fail to create
|
|
}
|
|
m_wndToolBar.SetOwner(this);
|
|
|
|
// Create the category list
|
|
if (!m_wndTree.Create(WS_CHILD | WS_VISIBLE | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_SHOWSELALWAYS,
|
|
CRect(0, 0, 0, 0), this, _TREE_ID,
|
|
TVOXS_VGRID | TVOXS_HGRID | TVOXS_COLUMNHDR | TVOXS_NOSORTHEADER | TVOXS_NOFOCUSRECT |
|
|
TVOXS_EXTENDCOLUMNS | TVOXS_ROWSEL | TVOXS_FLGRID))
|
|
{
|
|
TRACE0("Failed to create the category list.\n");
|
|
return -1; // fail to create
|
|
}
|
|
|
|
// Create the description pane
|
|
// Create the combo
|
|
if (!m_wndDescription.Create(NULL, NULL, WS_CHILD | WS_VISIBLE, CRect(0, 0, 0, 0), this, _DESCRIPTION_ID))
|
|
{
|
|
TRACE0("Failed to create the description pane.\n");
|
|
return -1; // fail to create
|
|
}
|
|
|
|
m_wndTree.SetHorizontalGridColor(::GetSysColor(COLOR_3DFACE));
|
|
m_wndTree.SetVerticalGridColor(::GetSysColor(COLOR_3DFACE));
|
|
|
|
// Set up the two columns
|
|
LV_COLUMN lvc;
|
|
memset(&lvc, 0, sizeof(lvc));
|
|
lvc.fmt = LVCFMT_LEFT;
|
|
lvc.cx = 100;
|
|
lvc.pszText = _T("Property");
|
|
lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
|
|
m_wndTree.SetColumn(0,&lvc);
|
|
m_wndTree.InsertColumn(1, _T("Value"), LVCFMT_LEFT, 100, 1);
|
|
|
|
m_wndTree.m_wndEdit.SetBorder(FALSE);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void COXPropertiesWnd::OnSize(UINT nType, int cx, int cy)
|
|
{
|
|
CFrameWnd::OnSize(nType, cx, cy);
|
|
|
|
CRect rectClient;
|
|
GetClientRect(rectClient);
|
|
|
|
m_wndCombo.MoveWindow(rectClient);
|
|
|
|
// Get the height of the combo box
|
|
CRect rectCombo;
|
|
m_wndCombo.GetClientRect(rectCombo);
|
|
|
|
if (!(m_wndCombo.GetStyle() & WS_VISIBLE))
|
|
rectCombo.bottom = rectCombo.top;
|
|
|
|
// Position the toolbar below the combo box
|
|
CRect rectToolBar = rectClient;
|
|
rectToolBar.top += rectCombo.Height();
|
|
rectToolBar.bottom = rectToolBar.top + 25;
|
|
m_wndToolBar.MoveWindow(rectToolBar);
|
|
|
|
if (!(m_wndToolBar.GetStyle() & WS_VISIBLE))
|
|
rectToolBar.bottom = rectToolBar.top;
|
|
|
|
// Position the description pane at the bottom
|
|
CRect rectDescription = rectClient;
|
|
rectDescription.top = rectDescription.bottom - 50;
|
|
m_wndDescription.MoveWindow(rectDescription);
|
|
|
|
if (!(m_wndDescription.GetStyle() & WS_VISIBLE))
|
|
rectDescription.bottom = rectDescription.top;
|
|
|
|
// Position the tree in the space that remains
|
|
CRect rectTree = rectClient;
|
|
rectTree.top += rectCombo.Height() + rectToolBar.Height();
|
|
rectTree.bottom -= rectDescription.Height();
|
|
rectTree.DeflateRect(1, 1);
|
|
m_wndTree.MoveWindow(rectTree);
|
|
|
|
// If an item is being edited reposition the editor
|
|
if (m_pEditWnd != NULL)
|
|
{
|
|
HPROPERTY hSelectedProp = GetSelectedProperty();
|
|
CRect rectSubItem;
|
|
int iItemIndex = m_wndTree.GetItemIndex(hSelectedProp);
|
|
m_wndTree.GetSubItemRect(iItemIndex, 1, LVIR_LABEL, rectSubItem);
|
|
rectSubItem.DeflateRect(0, 0, 1, 1);
|
|
|
|
m_pEditWnd->MoveWindow(rectSubItem);
|
|
}
|
|
}
|
|
|
|
void COXPropertiesWnd::OnCategorized()
|
|
{
|
|
if (m_bCategorized)
|
|
return;
|
|
|
|
m_bCategorized = TRUE;
|
|
m_wndTree.ModifyStyle(0, TVS_LINESATROOT);
|
|
|
|
|
|
// Insert the categories
|
|
POSITION catpos = m_listCategories.GetHeadPosition();
|
|
for(int i=0; i<m_listCategories.GetCount(); i++)
|
|
{
|
|
InsertCategory(m_listCategories.GetNext(catpos));
|
|
}
|
|
|
|
|
|
// Re-insert all properties under their categories
|
|
POSITION pos = m_mapProp2Cat.GetStartPosition();
|
|
while (pos != NULL)
|
|
{
|
|
HPROPERTY hProp;
|
|
CString strCategory;
|
|
m_mapProp2Cat.GetNextAssoc(pos, hProp, strCategory);
|
|
|
|
// Insert the category if it hasn't been inserted yet
|
|
HCATEGORY hCategory = m_wndTree.GetRootItem();
|
|
if (strCategory.IsEmpty() == FALSE)
|
|
{
|
|
hCategory= FindCategory(strCategory);
|
|
if (hCategory == NULL)
|
|
hCategory = InsertCategory(strCategory);
|
|
}
|
|
|
|
if (hCategory != m_wndTree.GetRootItem())
|
|
{
|
|
m_wndTree.MoveItem(hProp, hCategory);
|
|
m_wndTree.SortChildren(hCategory);
|
|
}
|
|
}
|
|
|
|
// Sort
|
|
if(m_bSortCategories)
|
|
m_wndTree.SortChildren(m_wndTree.GetRootItem());
|
|
}
|
|
|
|
void COXPropertiesWnd::OnAlphabetic()
|
|
{
|
|
if (!m_bCategorized)
|
|
return;
|
|
|
|
m_bCategorized = FALSE;
|
|
m_wndTree.ModifyStyle(TVS_LINESATROOT, 0);
|
|
|
|
// Remove all categories from the tree and insert all items directly under the root item
|
|
|
|
// If a root item is not in m_mapProp2Cat when it needs to be removed
|
|
HTREEITEM hRoot = m_wndTree.GetRootItem();
|
|
if (m_wndTree.ItemHasChildren(hRoot))
|
|
{
|
|
HCATEGORY hNextCat, hCat = m_wndTree.GetChildItem(hRoot);
|
|
while (hCat != NULL)
|
|
{
|
|
CString strDummy;
|
|
hNextCat = m_wndTree.GetNextItem(hCat, TVGN_NEXT);
|
|
if (!m_mapProp2Cat.Lookup(hCat, strDummy))
|
|
{
|
|
// This is a category, so move all its children to the root and delete it
|
|
HPROPERTY hNextProp, hProp = m_wndTree.GetChildItem(hCat);
|
|
while (hProp != NULL)
|
|
{
|
|
hNextProp = m_wndTree.GetNextItem(hProp, TVGN_NEXT);
|
|
m_wndTree.MoveItem(hProp, hRoot);
|
|
hProp = hNextProp;
|
|
}
|
|
|
|
m_wndTree.DeleteItem(hCat);
|
|
}
|
|
|
|
hCat = hNextCat;
|
|
}
|
|
}
|
|
|
|
// Now sort all items under the root
|
|
m_wndTree.SortChildren(hRoot);
|
|
}
|
|
|
|
HCATEGORY COXPropertiesWnd::InsertCategory(LPCTSTR lpszCategoryName)
|
|
{
|
|
HCATEGORY hCategory = m_wndTree.InsertItem(lpszCategoryName);
|
|
m_wndTree.SetItemBackColor(hCategory, ::GetSysColor(COLOR_3DFACE));
|
|
m_wndTree.SetSubItem(hCategory, 1, OX_SUBITEM_BGCOLOR, NULL, 0, NULL, 0, ::GetSysColor(COLOR_3DFACE));
|
|
CStringArray saDummy;
|
|
m_wndTree.SetEditMode(hCategory, OXET_NOEDIT, saDummy, 0);
|
|
m_wndTree.SetEditMode(hCategory, OXET_NOEDIT, saDummy, 1);
|
|
|
|
m_wndTree.Expand(hCategory, TVE_EXPAND);
|
|
|
|
return hCategory;
|
|
}
|
|
|
|
HCATEGORY COXPropertiesWnd::FindCategory(LPCTSTR lpszCategory)
|
|
{
|
|
HTREEITEM hRoot = m_wndTree.GetRootItem();
|
|
if (m_wndTree.ItemHasChildren(hRoot))
|
|
{
|
|
HTREEITEM hNextItem, hChildItem = m_wndTree.GetChildItem(hRoot);
|
|
while (hChildItem != NULL)
|
|
{
|
|
hNextItem = m_wndTree.GetNextItem(hChildItem, TVGN_NEXT);
|
|
if (m_wndTree.GetItemText(hChildItem) == lpszCategory)
|
|
return hChildItem;
|
|
|
|
hChildItem = hNextItem;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
HPROPERTY COXPropertiesWnd::InsertProperty(LPCTSTR lpszName,
|
|
LPCTSTR lpszInitialValue,
|
|
LPCTSTR lpszDescription,
|
|
LPCTSTR lpszCategory,
|
|
CEdit* pEditorClass)
|
|
{
|
|
if (pEditorClass != NULL)
|
|
{
|
|
ASSERT(pEditorClass->IsKindOf(RUNTIME_CLASS(CWnd)));
|
|
}
|
|
|
|
|
|
HCATEGORY hCategory = NULL;
|
|
if (lpszCategory != NULL)
|
|
{
|
|
hCategory= FindCategory(lpszCategory);
|
|
if (hCategory == NULL)
|
|
{
|
|
hCategory = InsertCategory(lpszCategory);
|
|
CString tmpStr = lpszCategory;
|
|
m_listCategories.AddTail(tmpStr);
|
|
}
|
|
}
|
|
|
|
HPROPERTY hProp = m_wndTree.InsertItem(lpszName, hCategory);
|
|
if (hProp == NULL)
|
|
return NULL;
|
|
|
|
// Insert the sub item
|
|
m_wndTree.SetSubItem(hProp, 1, 0, NULL);
|
|
|
|
// Set up the editing mode to none
|
|
CStringArray saDummy;
|
|
m_wndTree.SetEditMode(hProp, OXET_NOEDIT, saDummy, 0);
|
|
m_wndTree.SetEditMode(hProp, OXET_NOEDIT, saDummy, 1);
|
|
|
|
// Sort
|
|
if (hCategory != NULL)
|
|
m_wndTree.SortChildren(hCategory);
|
|
else
|
|
{
|
|
if(m_bSortCategories)
|
|
m_wndTree.SortChildren(m_wndTree.GetRootItem());
|
|
else
|
|
m_wndTree.MoveItem(hProp,m_wndTree.GetRootItem(),TVI_FIRST);
|
|
}
|
|
|
|
// Insert an entry in the property to category map
|
|
CString strCategory = _T("");
|
|
if (hCategory != NULL)
|
|
strCategory = m_wndTree.GetItemText(hCategory);
|
|
m_mapProp2Cat.SetAt(hProp, strCategory);
|
|
|
|
// Insert an entry in the property to description map
|
|
m_mapProp2Desc.SetAt(hProp, lpszDescription);
|
|
|
|
// Insert an entry to the editor map
|
|
if (pEditorClass != NULL)
|
|
m_mapProp2Editor.SetAt(hProp, pEditorClass);
|
|
|
|
// Set the initial value (if any)
|
|
if (lpszInitialValue != NULL)
|
|
SetPropertyValue(hProp, lpszInitialValue);
|
|
|
|
return hProp;
|
|
}
|
|
|
|
BOOL COXPropertiesWnd::DeleteProperty(HPROPERTY hProperty)
|
|
{
|
|
ASSERT(hProperty != NULL);
|
|
|
|
FinishEditing();
|
|
|
|
if (!OnDeleteProperty(hProperty))
|
|
return FALSE;
|
|
|
|
HTREEITEM hParent = m_wndTree.GetParentItem(hProperty);
|
|
|
|
// Remove the property handle from the maps
|
|
m_mapProp2Cat.RemoveKey(hProperty);
|
|
m_mapProp2Desc.RemoveKey(hProperty);
|
|
m_mapProp2Editor.RemoveKey(hProperty);
|
|
|
|
BOOL bRes = m_wndTree.DeleteItem((HTREEITEM) hProperty);
|
|
if (hParent != m_wndTree.GetRootItem())
|
|
{
|
|
// The parent is a category
|
|
COXTreeItem* pParent = m_wndTree.GetXItem(hParent);
|
|
if (pParent->GetChildrenCount() == 0)
|
|
{
|
|
CString strCategory = m_wndTree.GetItemText(hParent);
|
|
if(POSITION pos = m_listCategories.Find(strCategory))
|
|
{
|
|
m_listCategories.RemoveAt(pos);
|
|
}
|
|
m_wndTree.DeleteItem(hParent); // delete the empty category
|
|
}
|
|
}
|
|
|
|
return bRes;
|
|
}
|
|
|
|
BOOL COXPropertiesWnd::SetPropertyValue(HPROPERTY hProperty, LPCTSTR lpszValue)
|
|
{
|
|
ASSERT(hProperty != NULL);
|
|
return m_wndTree.SetItemText(hProperty, lpszValue, 1);
|
|
}
|
|
|
|
CString COXPropertiesWnd::GetPropertyValue(HPROPERTY hProperty)
|
|
{
|
|
ASSERT(hProperty != NULL);
|
|
return m_wndTree.GetItemText(hProperty, 1);
|
|
}
|
|
|
|
HPROPERTY COXPropertiesWnd::FindProperty(LPCTSTR lpszName, LPCTSTR lpszCategory)
|
|
{
|
|
// First try to find the category
|
|
HCATEGORY hCategory = NULL;
|
|
if (lpszCategory != NULL)
|
|
hCategory = FindCategory(lpszCategory);
|
|
|
|
HTREEITEM hParent = hCategory;
|
|
if (hParent == NULL)
|
|
hParent = m_wndTree.GetRootItem();
|
|
|
|
// At this point we know that if the property exist it is a child of hParent
|
|
if (m_wndTree.ItemHasChildren(hParent))
|
|
{
|
|
HTREEITEM hNextItem, hChildItem = m_wndTree.GetChildItem(hParent);
|
|
while (hChildItem != NULL)
|
|
{
|
|
hNextItem = m_wndTree.GetNextItem(hChildItem, TVGN_NEXT);
|
|
if (m_wndTree.GetItemText(hChildItem) == lpszName)
|
|
return hChildItem;
|
|
|
|
hChildItem = hNextItem;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void COXPropertiesWnd::OnPaint()
|
|
{
|
|
CPaintDC dc(this); // device context for painting
|
|
|
|
// TODO: Add your message handler code here
|
|
CRect rectClient;
|
|
GetClientRect(rectClient);
|
|
dc.FillSolidRect(rectClient, GetFrameSkin()->GetBackgroundColor());
|
|
CBrush brBackground;
|
|
brBackground.CreateSolidBrush(::GetSysColor(COLOR_3DFACE));
|
|
dc.FrameRect(rectClient, &brBackground);
|
|
|
|
// Draw a gray border around the tree
|
|
CRect rectTree;
|
|
m_wndTree.GetWindowRect(rectTree);
|
|
ScreenToClient(rectTree);
|
|
rectTree.InflateRect(1, 1);
|
|
CBrush brBorder;
|
|
brBorder.CreateSolidBrush(GetFrameSkin()->GetBorderColor());
|
|
dc.FrameRect(rectTree, &brBorder);
|
|
}
|
|
|
|
void COXPropertiesWnd::PostNcDestroy()
|
|
{
|
|
// DO NOTHING
|
|
}
|
|
|
|
void COXPropertiesWnd::OnUpdateCategorized(CCmdUI* pCmdUI)
|
|
{
|
|
pCmdUI->SetCheck(m_bCategorized);
|
|
}
|
|
|
|
void COXPropertiesWnd::OnUpdateAlphabetic(CCmdUI* pCmdUI)
|
|
{
|
|
pCmdUI->SetCheck(!m_bCategorized);
|
|
}
|
|
|
|
void COXPropertiesWnd::SetCategorized(BOOL bCategorized)
|
|
{
|
|
m_bCategorized = bCategorized;
|
|
|
|
if (bCategorized)
|
|
OnCategorized();
|
|
else
|
|
OnAlphabetic();
|
|
}
|
|
|
|
CComboBoxEx& COXPropertiesWnd::GetComboBoxEx()
|
|
{
|
|
return m_wndCombo;
|
|
}
|
|
|
|
COXCoolToolBar& COXPropertiesWnd::GetToolBar()
|
|
{
|
|
return m_wndToolBar;
|
|
}
|
|
|
|
void COXPropertiesWnd::ShowCombo(BOOL bShow)
|
|
{
|
|
if (bShow)
|
|
m_wndCombo.ModifyStyle(0, WS_VISIBLE);
|
|
else
|
|
m_wndCombo.ModifyStyle(WS_VISIBLE, 0);
|
|
}
|
|
|
|
void COXPropertiesWnd::ShowToolBar(BOOL bShow)
|
|
{
|
|
if (bShow)
|
|
m_wndToolBar.ModifyStyle(0, WS_VISIBLE);
|
|
else
|
|
m_wndToolBar.ModifyStyle(WS_VISIBLE, 0);
|
|
}
|
|
|
|
void COXPropertiesWnd::ShowDescription(BOOL bShow)
|
|
{
|
|
if (bShow)
|
|
m_wndDescription.ModifyStyle(0, WS_VISIBLE);
|
|
else
|
|
m_wndDescription.ModifyStyle(WS_VISIBLE, 0);
|
|
}
|
|
|
|
HPROPERTY COXPropertiesWnd::GetSelectedProperty()
|
|
{
|
|
HTREEITEM hSelected = m_wndTree.GetNextItem(TVI_ROOT, TVGN_FIRSTSELECTED);
|
|
|
|
if (hSelected == NULL)
|
|
return NULL; // no property is selected
|
|
|
|
CString strDummy;
|
|
if (m_mapProp2Cat.Lookup(hSelected, strDummy))
|
|
return hSelected; // this is indeed a property;
|
|
else
|
|
return NULL; // it is a category
|
|
}
|
|
|
|
BOOL COXPropertiesWnd::OnPropertyValueChanged(HPROPERTY /*hProperty*/, LPCTSTR /*lpszOldValue*/, LPCTSTR /*lpszNewValue*/)
|
|
{
|
|
return TRUE; // accept the new value
|
|
}
|
|
|
|
void COXPropertiesWnd::OnItemChanged(NMHDR* /*pNMHDR*/, LRESULT* /*pResult*/)
|
|
{
|
|
CString strName, strDescription;
|
|
HPROPERTY hSelectedProp = GetSelectedProperty();
|
|
if (hSelectedProp == NULL)
|
|
{
|
|
strName = _T("");
|
|
strDescription = _T("");
|
|
}
|
|
else
|
|
{
|
|
strName = m_wndTree.GetItemText(hSelectedProp);
|
|
m_mapProp2Desc.Lookup(hSelectedProp, strDescription);
|
|
|
|
SendMessage(WM_USER_STARTEDITING, 0, (LPARAM) hSelectedProp);
|
|
}
|
|
|
|
m_wndDescription.SetDescription(strName, strDescription);
|
|
}
|
|
|
|
LRESULT COXPropertiesWnd::OnQueryPropertiesWnd(WPARAM /*wParam*/, LPARAM /*lParam*/)
|
|
{
|
|
return TRUE; // yes, this is a COXPropertiesWnd
|
|
}
|
|
|
|
LRESULT COXPropertiesWnd::OnStartEditing(WPARAM /*wParam*/, LPARAM lParam)
|
|
{
|
|
HPROPERTY hSelectedProp = (HPROPERTY) lParam;
|
|
|
|
// Finish editing first
|
|
if (m_pEditWnd != NULL)
|
|
FinishEditing();
|
|
else
|
|
StartEditing(hSelectedProp);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void COXPropertiesWnd::StartEditing(HPROPERTY hSelectedProp)
|
|
{
|
|
// Create the editing control and place it over the sub-item
|
|
CEdit* pEditor;
|
|
BOOL bFound = m_mapProp2Editor.Lookup(hSelectedProp, pEditor);
|
|
if (bFound)
|
|
{
|
|
m_pEditWnd = pEditor;
|
|
|
|
CRect rectSubItem;
|
|
int iItemIndex = m_wndTree.GetItemIndex(hSelectedProp);
|
|
m_wndTree.GetSubItemRect(iItemIndex, 1, LVIR_LABEL, rectSubItem);
|
|
rectSubItem.DeflateRect(0, 0, 1, 1);
|
|
|
|
// Create the editor window if not created already
|
|
if (!::IsWindow(m_pEditWnd->m_hWnd))
|
|
m_pEditWnd->Create(WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL, rectSubItem, &m_wndTree, _EDITOR_ID);
|
|
else
|
|
{
|
|
m_pEditWnd->MoveWindow(rectSubItem);
|
|
m_pEditWnd->ShowWindow(SW_SHOW);
|
|
}
|
|
m_pEditWnd->SetOwner(&m_wndTree);
|
|
|
|
m_pEditWnd->SetFont(m_wndTree.GetFont());
|
|
|
|
// Set the text of the editing window
|
|
CString strText = GetPropertyValue(hSelectedProp);
|
|
|
|
COXEdit* pOXEdit = DYNAMIC_DOWNCAST(COXEdit, m_pEditWnd);
|
|
COXMaskedEdit* pOXMaskedEdit = DYNAMIC_DOWNCAST(COXMaskedEdit, m_pEditWnd);
|
|
if (pOXEdit != NULL)
|
|
{
|
|
pOXEdit->EmptyData();
|
|
pOXEdit->SetInputData(strText);
|
|
}
|
|
else if (pOXMaskedEdit != NULL)
|
|
pOXMaskedEdit->SetText(strText);
|
|
else
|
|
m_pEditWnd->SetWindowText(strText);
|
|
|
|
m_hEditProp = hSelectedProp;
|
|
}
|
|
}
|
|
|
|
void COXPropertiesWnd::FinishEditing(BOOL bSave)
|
|
{
|
|
if (m_hEditProp == NULL) {
|
|
return;
|
|
}
|
|
if (bSave)
|
|
{
|
|
// Call OnPropertyValueChanged(...) and save the value
|
|
CString strText;
|
|
COXMaskedEdit* pMaskedEdit = DYNAMIC_DOWNCAST(COXMaskedEdit, m_pEditWnd);
|
|
if (pMaskedEdit != NULL)
|
|
strText = pMaskedEdit->GetText();
|
|
else
|
|
m_pEditWnd->GetWindowText(strText);
|
|
|
|
BOOL bSaveValue = OnPropertyValueChanged(m_hEditProp,
|
|
GetPropertyValue(m_hEditProp), strText);
|
|
|
|
if (bSaveValue)
|
|
SetPropertyValue(m_hEditProp, strText);
|
|
}
|
|
|
|
// Hide the editor
|
|
m_pEditWnd->ShowWindow(SW_HIDE);
|
|
m_pEditWnd = NULL;
|
|
m_hEditProp = NULL;
|
|
|
|
m_wndTree.SelectItem(NULL);
|
|
}
|
|
|
|
BOOL COXPropertiesWnd::PreTranslateMessage(MSG* pMsg)
|
|
{
|
|
return CFrameWnd::PreTranslateMessage(pMsg);
|
|
}
|
|
|
|
LRESULT COXPropertiesWnd::OnUserAdjustLastColumn(WPARAM /*wParam*/, LPARAM /*lParam*/)
|
|
{
|
|
// If an item is being edited reposition the editor
|
|
if (m_pEditWnd != NULL)
|
|
{
|
|
HPROPERTY hSelectedProp = GetSelectedProperty();
|
|
CRect rectSubItem;
|
|
int iItemIndex = m_wndTree.GetItemIndex(hSelectedProp);
|
|
m_wndTree.GetSubItemRect(iItemIndex, 1, LVIR_LABEL, rectSubItem);
|
|
rectSubItem.DeflateRect(0, 0, 1, 1);
|
|
|
|
m_pEditWnd->MoveWindow(rectSubItem);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
BOOL COXPropertiesWnd::IsDescendant(CWnd* pWndParent, CWnd* pWndChild)
|
|
// helper for detecting whether child descendent of parent
|
|
// (works with owned popups as well)
|
|
{
|
|
ASSERT(pWndParent!=NULL);
|
|
ASSERT(::IsWindow(pWndParent->GetSafeHwnd()));
|
|
ASSERT(pWndChild!=NULL);
|
|
ASSERT(::IsWindow(pWndChild->GetSafeHwnd()));
|
|
|
|
HWND hWndParent=pWndParent->GetSafeHwnd();
|
|
HWND hWndChild=pWndChild->GetSafeHwnd();
|
|
do
|
|
{
|
|
if (hWndParent == hWndChild)
|
|
return TRUE;
|
|
|
|
// check for permanent-owned window first
|
|
CWnd* pWnd=CWnd::FromHandlePermanent(hWndChild);
|
|
if(pWnd!=NULL)
|
|
hWndChild=pWnd->GetOwner()->GetSafeHwnd();
|
|
else
|
|
hWndChild=(::GetWindowLongPtr(hWndChild,GWL_STYLE)&WS_CHILD) ?
|
|
::GetParent(hWndChild) : ::GetWindow(hWndChild,GW_OWNER);
|
|
|
|
} while (hWndChild != NULL);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL COXPropertiesWnd::OnDeleteProperty(HPROPERTY /*hProperty*/)
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL COXPropertiesWnd::DeleteAll()
|
|
{
|
|
// Loop through all the properties using the m_mapProp2Cat map
|
|
|
|
CArray<HPROPERTY, HPROPERTY> arrToBeDeleted;
|
|
|
|
POSITION pos = m_mapProp2Cat.GetStartPosition();
|
|
while (pos != NULL)
|
|
{
|
|
HPROPERTY hProperty;
|
|
CString strCategory;
|
|
m_mapProp2Cat.GetNextAssoc(pos, hProperty, strCategory);
|
|
arrToBeDeleted.Add(hProperty);
|
|
}
|
|
|
|
BOOL bAllDeleted = TRUE;
|
|
for (int i = 0; i < arrToBeDeleted.GetSize(); i++)
|
|
if (!DeleteProperty(arrToBeDeleted[i]))
|
|
bAllDeleted = FALSE;
|
|
|
|
return bAllDeleted;
|
|
}
|
|
|
|
COXFrameSkin* COXPropertiesWnd::GetFrameSkin()
|
|
{
|
|
// Check if the app is derived from COXSkinnedApp
|
|
COXSkinnedApp* pSkinnedApp = DYNAMIC_DOWNCAST(COXSkinnedApp, AfxGetApp());
|
|
if (pSkinnedApp != NULL && pSkinnedApp->GetCurrentSkin() != NULL)
|
|
return pSkinnedApp->GetCurrentSkin()->GetFrameSkin();
|
|
else
|
|
{
|
|
// Create a classic skin for this class if not created already
|
|
if (m_pFrameSkin == NULL)
|
|
m_pFrameSkin = new COXFrameSkinClassic();
|
|
|
|
return m_pFrameSkin;
|
|
}
|
|
}
|
|
|
|
void COXPropertiesWnd::SetSortCategories(BOOL bSortCategories /*= TRUE*/ )
|
|
{
|
|
m_bSortCategories = bSortCategories;
|
|
}
|
|
|
|
|
|
/*
|
|
Used to jump to the next property (if it's the end of the current
|
|
category, the first property in the next category gets selected).
|
|
Nish - June 14, 2005
|
|
*/
|
|
|
|
BOOL COXPropertiesWnd::SelectNextProperty()
|
|
{
|
|
HTREEITEM hSelected = m_wndTree.GetNextItem(TVI_ROOT, TVGN_FIRSTSELECTED);
|
|
|
|
if (hSelected == NULL)
|
|
return FALSE; // no property is selected
|
|
|
|
HTREEITEM hNext = m_wndTree.GetNextItem(hSelected, TVGN_CHILD);
|
|
|
|
if (hNext == NULL)
|
|
hNext = m_wndTree.GetNextItem(hSelected, TVGN_NEXT);
|
|
|
|
if (hNext == NULL)
|
|
hNext = m_wndTree.GetNextItem(m_wndTree.GetParentItem(hSelected), TVGN_NEXT);
|
|
|
|
if (hNext == NULL)
|
|
return FALSE; // no more properties
|
|
|
|
FinishEditing(FALSE);
|
|
m_wndTree.SelectItem(hNext);
|
|
m_wndTree.SetItemState(hNext,LVIS_SELECTED, LVIS_SELECTED);
|
|
StartEditing(hNext);
|
|
|
|
if(m_wndTree.ItemHasChildren(hNext))
|
|
return SelectNextProperty();
|
|
|
|
return TRUE;
|
|
}
|
|
|