2017-03-15 19:43:10 +00:00
// ConditionsView.cpp : implementation file
//
# include "stdafx.h"
# include "logic_editor.h"
# include "ConditionsView.h"
# include "Logic_editorDoc.h"
# include "MainFrm.h"
# include "ChildFrm.h"
# include "EditorFormView.h"
# include "TMenu.h"
# ifdef _DEBUG
# define new DEBUG_NEW
# undef THIS_FILE
static char THIS_FILE [ ] = __FILE__ ;
# endif
# ifndef ID_MOVEASCHILD
# define ID_MOVEASCHILD 32857
# endif
# ifndef ID_MOVEASSIBLING
# define ID_MOVEASSIBLING 32858
# endif
# ifndef ID_COPYASSIBLING
# define ID_COPYASSIBLING 32859
# endif
# ifndef ID_COPYASCHILD
# define ID_COPYASCHILD 32860
# endif
/////////////////////////////////////////////////////////////////////////////
// CConditionsView
IMPLEMENT_DYNCREATE ( CConditionsView , CTreeView )
CConditionsView : : CConditionsView ( )
{
}
CConditionsView : : ~ CConditionsView ( )
{
}
BEGIN_MESSAGE_MAP ( CConditionsView , CTreeView )
//{{AFX_MSG_MAP(CConditionsView)
ON_NOTIFY_REFLECT ( TVN_SELCHANGED , OnSelchanged )
ON_WM_KILLFOCUS ( )
ON_NOTIFY_REFLECT ( TVN_BEGINRDRAG , OnBeginrdrag )
ON_WM_MOUSEMOVE ( )
ON_WM_RBUTTONUP ( )
//}}AFX_MSG_MAP
ON_COMMAND ( ID_MOVEASCHILD , OnMoveAsChild )
ON_COMMAND ( ID_MOVEASSIBLING , OnMoveAsSibling )
ON_COMMAND ( ID_COPYASCHILD , OnCopyAsChild )
ON_COMMAND ( ID_COPYASSIBLING , OnCopyAsSibling )
END_MESSAGE_MAP ( )
// Creating Drag Image for a CTreeCtrl without images
// Contribution of Pal K Tonder on www.codeguru.com
// The method CreateDragImage is used during drag'n drop to create a drag image. The problem is that it only works for a CTreeCtrl with images.
// The following method, CreateDragImageEx, checks whether the CTreeCtrl has a valid normal CImageList. If so, it just calls the standard CreateDragImage method and returns.
// If, on the other hand, no valid CImageList is found, a bitmap is created based on the size of item rect, and the item text is drawn into it. Then a CImageList is
// created and the bitmap is added to it.
CImageList * CConditionsView : : CreateDragImageEx ( HTREEITEM hItem )
{
CTreeCtrl & tree = GetTreeCtrl ( ) ;
if ( tree . GetImageList ( TVSIL_NORMAL ) ! = NULL )
return tree . CreateDragImage ( hItem ) ;
CRect rect ;
tree . GetItemRect ( hItem , rect , TRUE ) ;
rect . OffsetRect ( - rect . left , - rect . top ) ;
// Create bitmap
CClientDC dc ( this ) ;
CDC memDC ;
if ( ! memDC . CreateCompatibleDC ( & dc ) )
return NULL ;
CBitmap bitmap ;
if ( ! bitmap . CreateCompatibleBitmap ( & dc , rect . Width ( ) , rect . Height ( ) ) )
return NULL ;
CBitmap * pOldMemDCBitmap = memDC . SelectObject ( & bitmap ) ;
CFont * pOldFont = memDC . SelectObject ( GetFont ( ) ) ;
memDC . FillSolidRect ( & rect , RGB ( 0 , 255 , 0 ) ) ; // Here green is used as mask color
memDC . SetTextColor ( GetSysColor ( COLOR_GRAYTEXT ) ) ;
memDC . TextOut ( rect . left , rect . top , tree . GetItemText ( hItem ) ) ;
memDC . SelectObject ( pOldFont ) ;
memDC . SelectObject ( pOldMemDCBitmap ) ;
// Create imagelist
CImageList * pImageList = new CImageList ;
pImageList - > Create ( rect . Width ( ) , rect . Height ( ) ,
ILC_COLOR | ILC_MASK , 0 , 1 ) ;
pImageList - > Add ( & bitmap , RGB ( 0 , 255 , 0 ) ) ; // Here green is used as mask color
return pImageList ;
}
/////////////////////////////////////////////////////////////////////////////
// CConditionsView drawing
void CConditionsView : : OnDraw ( CDC * pDC )
{
CDocument * pDoc = GetDocument ( ) ;
// TODO: add draw code here
}
/////////////////////////////////////////////////////////////////////////////
// CConditionsView diagnostics
# ifdef _DEBUG
void CConditionsView : : AssertValid ( ) const
{
CTreeView : : AssertValid ( ) ;
}
void CConditionsView : : Dump ( CDumpContext & dc ) const
{
CTreeView : : Dump ( dc ) ;
}
# endif //_DEBUG
void CConditionsView : : expand ( UINT nCode , HTREEITEM hItem )
{
HTREEITEM hElement ;
HTreeItemArray pile ;
CTreeCtrl & m_tree = GetTreeCtrl ( ) ;
if ( hItem = = NULL )
hElement = m_tree . GetRootItem ( ) ;
else
{
m_tree . Expand ( hItem , nCode ) ;
hElement = m_tree . GetChildItem ( hItem ) ;
}
pile . RemoveAll ( ) ;
while ( ( hElement ! = NULL ) | | ( pile . GetSize ( ) ! = 0 ) )
{
while ( ( hElement = = NULL ) & & ( pile . GetSize ( ) ! = 0 ) )
{
hElement = pile [ pile . GetSize ( ) - 1 ] ;
pile . RemoveAt ( pile . GetSize ( ) - 1 ) ;
hElement = m_tree . GetNextSiblingItem ( hElement ) ;
}
if ( hElement )
{
pile . Add ( hElement ) ;
m_tree . Expand ( hElement , nCode ) ;
hElement = m_tree . GetChildItem ( hElement ) ;
}
}
}
HMENU CConditionsView : : GetRDragMenu ( )
{
CMenu menu ;
menu . CreatePopupMenu ( ) ;
menu . AppendMenu ( MF_STRING , ID_MOVEASCHILD , _T ( " Move As Child " ) ) ;
menu . AppendMenu ( MF_STRING , ID_MOVEASSIBLING , _T ( " Move As Sibling " ) ) ;
menu . AppendMenu ( MF_STRING , ID_COPYASCHILD , _T ( " Copy As Child " ) ) ;
menu . AppendMenu ( MF_STRING , ID_COPYASSIBLING , _T ( " Copy As Sibling " ) ) ;
return menu . Detach ( ) ;
}
/////////////////////////////////////////////////////////////////////////////
// CConditionsView message handlers
void CConditionsView : : OnInitialUpdate ( )
{
CTreeView : : OnInitialUpdate ( ) ;
m_pSelectedCondition = NULL ;
m_pDragCondition = NULL ;
m_pSelectedNode = NULL ;
m_pDragImage = NULL ;
m_hitemDrag = NULL ;
m_hitemDrop = NULL ;
m_bRDragging = FALSE ;
m_bRDragCanceled = FALSE ;
}
void CConditionsView : : OnUpdate ( CView * pSender , LPARAM lHint , CObject * pHint )
{
/** TO DO : REDRAW ONLY IF Some CONDITIONS have changed **/
SetRedraw ( FALSE ) ;
CTreeView : : OnUpdate ( pSender , lHint , pHint ) ;
BOOL bSelection = FALSE ;
// get a pointer on associated document
CLogic_editorDoc * pDoc = static_cast < CLogic_editorDoc * > ( GetDocument ( ) ) ;
ASSERT_VALID ( pDoc ) ;
CTreeCtrl & m_tree = GetTreeCtrl ( ) ;
m_tree . DeleteAllItems ( ) ;
m_mapItemToNode . RemoveAll ( ) ;
TPositionList heap ;
HTREEITEM hItem = m_tree . InsertItem ( " Conditions " , 0 , 0 ) ;
// get the states map
CCondition * pCondition ;
CString condName ;
POSITION pos = pDoc - > m_conditions . GetStartPosition ( ) ;
while ( pos ! = NULL )
{
pDoc - > m_conditions . GetNextAssoc ( pos , condName , ( void * & ) pCondition ) ;
hItem = m_tree . InsertItem ( condName , m_tree . GetRootItem ( ) ) ;
//
if ( m_pSelectedCondition = = pCondition & & m_pSelectedNode = = NULL )
{
m_tree . SelectItem ( hItem ) ;
bSelection = TRUE ;
}
CConditionNode * pNode , * pNodeTemp ;
HTREEITEM parentHItem = hItem ;
POSITION nodePos = pCondition - > m_ctConditionTree . GetHeadPosition ( ) ;
while ( nodePos ! = NULL )
{
pNode = pCondition - > m_ctConditionTree . GetNext ( nodePos ) ;
if ( pNode ! = NULL )
{
hItem = m_tree . InsertItem ( pNode - > getNodeAsString ( ) , parentHItem ) ;
// memorize the association hItem/pNode in the map
m_mapItemToNode . SetAt ( hItem , pNode ) ;
if ( m_pSelectedNode = = pNode )
{
m_tree . SelectItem ( hItem ) ;
bSelection = TRUE ;
}
for ( ; ; )
{
// get the deepest first level node in the sub tree
POSITION subPos = pNode - > m_ctSubTree . GetHeadPosition ( ) ;
while ( subPos ! = NULL )
{
pNodeTemp = pNode - > m_ctSubTree . GetNext ( subPos ) ;
if ( pNodeTemp ! = NULL )
{
pNode = pNodeTemp ;
hItem = m_tree . InsertItem ( pNode - > getNodeAsString ( ) , hItem ) ;
m_mapItemToNode . SetAt ( hItem , pNode ) ;
if ( m_pSelectedNode = = pNode )
{
m_tree . SelectItem ( hItem ) ;
bSelection = TRUE ;
}
// push the position
heap . AddTail ( subPos ) ;
subPos = pNode - > m_ctSubTree . GetHeadPosition ( ) ;
}
}
// get sibling if any, if none, get next node
do
{
pNode = pNode - > getParentNode ( ) ;
hItem = m_tree . GetParentItem ( hItem ) ;
// pop subPos
if ( heap . IsEmpty ( ) )
break ;
subPos = heap . GetTail ( ) ;
heap . RemoveTail ( ) ;
if ( subPos ! = NULL )
{
pNodeTemp = pNode - > m_ctSubTree . GetNext ( subPos ) ;
if ( pNodeTemp ! = NULL )
{
pNode = pNodeTemp ;
hItem = m_tree . InsertItem ( pNode - > getNodeAsString ( ) , hItem ) ;
// memorize the association hItem/pNode in the map
m_mapItemToNode . SetAt ( hItem , pNode ) ;
if ( m_pSelectedNode = = pNode )
{
m_tree . SelectItem ( hItem ) ;
bSelection = TRUE ;
}
//push
heap . AddTail ( subPos ) ;
subPos = pNode - > m_ctSubTree . GetHeadPosition ( ) ;
}
else
break ;
}
}
while ( subPos = = NULL ) ;
if ( pNode = = NULL )
break ;
}
}
}
}
// expand all tree
expand ( /*TVE_EXPAND ,NULL*/ ) ;
if ( ! bSelection )
{
m_pSelectedNode = NULL ;
m_pSelectedCondition = NULL ;
}
else
{
// assure the selected item is visible (if any)
hItem = m_tree . GetSelectedItem ( ) ;
ASSERT ( hItem ! = NULL ) ;
m_tree . EnsureVisible ( hItem ) ;
}
SetRedraw ( /*TRUE*/ ) ;
}
BOOL CConditionsView : : PreCreateWindow ( CREATESTRUCT & cs )
{
// modify arborescence style
cs . style | = ( TVS_HASLINES | TVS_LINESATROOT | TVS_HASBUTTONS /*|TVS_EDITLABELS*/ ) ;
// cs.style &= ~TVS_DISABLEDRAGDROP;
return CTreeView : : PreCreateWindow ( cs ) ;
}
void CConditionsView : : OnSelchanged ( NMHDR * pNMHDR , LRESULT * pResult )
{
NM_TREEVIEW * pNMTreeView = ( NM_TREEVIEW * ) pNMHDR ;
//
m_pSelectedCondition = NULL ;
m_pSelectedNode = NULL ;
// get the selected item and update the good frame (open the condition edition page in the form too)
CTreeCtrl & treeCtrl = GetTreeCtrl ( ) ;
HTREEITEM hItem ;
hItem = treeCtrl . GetSelectedItem ( ) ;
//
if ( hItem = = treeCtrl . GetRootItem ( ) )
return ;
// get the node selected (if any)
if ( ! m_mapItemToNode . Lookup ( hItem , m_pSelectedNode ) )
m_pSelectedNode = NULL ;
// get the condition (if any)
while ( treeCtrl . GetParentItem ( hItem ) ! = treeCtrl . GetRootItem ( ) )
hItem = treeCtrl . GetParentItem ( hItem ) ;
CString condName = treeCtrl . GetItemText ( hItem ) ;
CLogic_editorDoc * pDoc = static_cast < CLogic_editorDoc * > ( GetDocument ( ) ) ;
// to update the fields of the condition page in the form view
CMainFrame * pFrame = ( CMainFrame * ) AfxGetApp ( ) - > m_pMainWnd ;
// Get the active MDI child window.
CChildFrame * pChild = ( CChildFrame * ) pFrame - > GetActiveFrame ( ) ;
CEditorFormView * pFormView = static_cast < CEditorFormView * > ( pChild - > m_wndSplitter . GetPane ( 0 , 1 ) ) ;
CConditionPage * pCondPage = static_cast < CConditionPage * > ( pFormView - > m_pPropertySheet - > GetPage ( 2 ) ) ;
if ( pDoc - > m_conditions . Lookup ( condName , ( void * & ) m_pSelectedCondition ) )
{
pFormView - > m_pPropertySheet - > SetActivePage ( pCondPage ) ;
if ( pCondPage - > m_pSelectedConditionNode ! = m_pSelectedNode | | m_pSelectedNode = = NULL )
{
pCondPage - > m_pSelectedCondition = this - > m_pSelectedCondition ;
pCondPage - > m_pSelectedConditionNode = this - > m_pSelectedNode ;
pCondPage - > Update ( ) ;
}
}
else
{
if ( pCondPage - > m_pSelectedCondition ! = NULL )
{
pCondPage - > m_pSelectedConditionNode = this - > m_pSelectedNode ; // = NULL
pCondPage - > m_pSelectedCondition = this - > m_pSelectedCondition ; // = NULL
pCondPage - > Update ( ) ;
}
}
this - > SetFocus ( ) ;
//
* pResult = 0 ;
}
void CConditionsView : : OnKillFocus ( CWnd * pNewWnd )
{
// keep the current selection, so do not call CTreeView::OnKillFocus()
// CTreeView::OnKillFocus(pNewWnd);
}
void CConditionsView : : OnBeginrdrag ( NMHDR * pNMHDR , LRESULT * pResult )
{
NM_TREEVIEW * pNMTreeView = ( NM_TREEVIEW * ) pNMHDR ;
* pResult = 0 ;
CTreeCtrl & tree = GetTreeCtrl ( ) ;
CPoint ptAction ;
GetCursorPos ( & ptAction ) ;
ScreenToClient ( & ptAction ) ;
m_bRDragging = TRUE ;
m_bRDragCanceled = FALSE ;
m_hitemDrag = pNMTreeView - > itemNew . hItem ;
m_hitemDrop = NULL ;
m_pDragImage = CreateDragImageEx ( m_hitemDrag ) ; // get the image list for dragging
m_pDragImage - > BeginDrag ( 0 , CPoint ( 10 , - 15 ) ) ;
tree . SelectDropTarget ( NULL ) ; // to prevent image corruption.
m_pDragImage - > DragEnter ( NULL , ptAction ) ;
SetCapture ( ) ;
// get the drag condition
HTREEITEM hItem = m_hitemDrag ;
//
if ( hItem = = tree . GetRootItem ( ) )
return ;
// get the condition (if any)
while ( tree . GetParentItem ( hItem ) ! = tree . GetRootItem ( ) )
hItem = tree . GetParentItem ( hItem ) ;
CString condName = tree . GetItemText ( hItem ) ;
CLogic_editorDoc * pDoc = static_cast < CLogic_editorDoc * > ( GetDocument ( ) ) ;
pDoc - > m_conditions . Lookup ( condName , ( void * & ) m_pDragCondition ) ;
}
void CConditionsView : : OnMouseMove ( UINT nFlags , CPoint point )
{
HTREEITEM hitem ;
UINT flags ;
CTreeCtrl & tree = GetTreeCtrl ( ) ;
if ( m_bRDragging )
{
POINT pt = point ;
ClientToScreen ( & pt ) ;
CImageList : : DragMove ( pt ) ;
if ( ( hitem = tree . HitTest ( point , & flags ) ) ! = NULL )
{
CImageList : : DragShowNolock ( FALSE ) ;
tree . SelectDropTarget ( hitem ) ;
m_hitemDrop = hitem ;
CImageList : : DragShowNolock ( TRUE ) ;
}
}
CTreeView : : OnMouseMove ( nFlags , point ) ;
}
void CConditionsView : : OnRButtonUp ( UINT nFlags , CPoint point )
{
CTreeCtrl & tree = GetTreeCtrl ( ) ;
if ( m_bRDragging )
{
m_bRDragging = FALSE ;
CImageList : : DragLeave ( this ) ;
CImageList : : EndDrag ( ) ;
ReleaseCapture ( ) ;
delete m_pDragImage ;
if ( m_hitemDrag = = m_hitemDrop )
return ;
CTMenu menu ;
menu . Attach ( GetRDragMenu ( ) ) ;
menu . AddMenuTitle ( tree . GetItemText ( m_hitemDrag ) ) ;
// if the target is a condition and the dragged item is a node, do not allow '..as sibling' operations
CConditionNode * pNode ;
if ( m_mapItemToNode . Lookup ( m_hitemDrag , pNode ) & & ! m_mapItemToNode . Lookup ( m_hitemDrop , pNode ) )
{
menu . EnableMenuItem ( ID_MOVEASSIBLING , MF_GRAYED ) ;
menu . EnableMenuItem ( ID_COPYASSIBLING , MF_GRAYED ) ;
}
if ( menu = = NULL ) return ;
ClientToScreen ( & point ) ;
menu . TrackPopupMenu ( TPM_LEFTALIGN | TPM_RIGHTBUTTON ,
point . x , point . y ,
this ) ;
tree . SelectDropTarget ( NULL ) ;
}
else
CTreeView : : OnRButtonUp ( nFlags , point ) ;
}
void CConditionsView : : OnMoveAsChild ( )
{
CTreeCtrl & tree = GetTreeCtrl ( ) ;
// Check that the dragged item is not an ancestor
HTREEITEM htiParent = m_hitemDrop ;
while ( ( htiParent = tree . GetParentItem ( htiParent ) ) ! = NULL )
{
if ( htiParent = = m_hitemDrag )
return ;
}
CConditionNode * pTargetNode = NULL ;
CCondition * pTargetCond = NULL ;
CConditionNode * pDragNode ;
// get the drag object
if ( m_mapItemToNode . Lookup ( m_hitemDrag , pDragNode ) )
{
CConditionNode * pParentNode = pDragNode - > getParentNode ( ) ;
// parent is a node
if ( pParentNode ! = NULL )
{
POSITION pos = pParentNode - > m_ctSubTree . Find ( pDragNode ) ;
if ( pos ! = NULL )
{
pParentNode - > m_ctSubTree . RemoveAt ( pos ) ;
}
else
return ;
}
// parent is a condition
else
{
POSITION pos = m_pDragCondition - > m_ctConditionTree . Find ( pDragNode ) ;
if ( pos ! = NULL )
{
m_pDragCondition - > m_ctConditionTree . RemoveAt ( pos ) ;
}
else
return ;
}
}
else
return ;
CLogic_editorDoc * pDoc = static_cast < CLogic_editorDoc * > ( GetDocument ( ) ) ;
// target is a node
if ( m_mapItemToNode . Lookup ( m_hitemDrop , pTargetNode ) )
{
pTargetNode - > m_ctSubTree . AddTail ( pDragNode ) ;
pDragNode - > m_pParentNode = pTargetNode ;
}
// target is a condition
else
{
CString name = tree . GetItemText ( m_hitemDrop ) ;
if ( pDoc - > m_conditions . Lookup ( name , ( void * & ) pTargetCond ) )
{
pTargetCond - > m_ctConditionTree . AddTail ( pDragNode ) ;
pDragNode - > m_pParentNode = NULL ;
}
else
{
AfxMessageBox ( " Error : root condition not found " ) ;
delete pDragNode ;
}
}
// for the moment, update all views, but moving branch may be faster
pDoc - > UpdateAllViews ( NULL ) ;
/*
Expand ( m_hitemDrop , TVE_EXPAND ) ;
HTREEITEM htiNew = CopyBranch ( m_hitemDrag , m_hitemDrop , TVI_LAST ) ;
DeleteItem ( m_hitemDrag ) ;
SelectItem ( htiNew ) ;
*/
}
void CConditionsView : : OnMoveAsSibling ( )
{
CTreeCtrl & tree = GetTreeCtrl ( ) ;
if ( m_hitemDrop = = tree . GetRootItem ( ) )
return ;
m_hitemDrop = tree . GetParentItem ( m_hitemDrop ) ;
OnMoveAsChild ( ) ;
}
void CConditionsView : : OnCopyAsChild ( )
{
CTreeCtrl & tree = GetTreeCtrl ( ) ;
// Check that the dragged item is not an ancestor
HTREEITEM htiParent = m_hitemDrop ;
while ( ( htiParent = tree . GetParentItem ( htiParent ) ) ! = NULL )
{
if ( htiParent = = m_hitemDrag )
return ;
}
CConditionNode * pTargetNode = NULL ;
CCondition * pTargetCond = NULL ;
CConditionNode * pDragNode = NULL ;
CConditionNode * pNewNode = NULL ;
// get the drag object
if ( m_mapItemToNode . Lookup ( m_hitemDrag , pDragNode ) )
{
pNewNode = new CConditionNode ( * pDragNode ) ;
}
else
return ;
CLogic_editorDoc * pDoc = static_cast < CLogic_editorDoc * > ( GetDocument ( ) ) ;
// target is a node
if ( m_mapItemToNode . Lookup ( m_hitemDrop , pTargetNode ) )
{
pTargetNode - > m_ctSubTree . AddTail ( pNewNode ) ;
pNewNode - > m_pParentNode = pTargetNode ;
}
// target is a condition
else
{
CString name = tree . GetItemText ( m_hitemDrop ) ;
if ( pDoc - > m_conditions . Lookup ( name , ( void * & ) pTargetCond ) )
{
pTargetCond - > m_ctConditionTree . AddTail ( pNewNode ) ;
pNewNode - > m_pParentNode = NULL ;
}
else
{
AfxMessageBox ( " Error : root condition not found " ) ;
delete pNewNode ;
}
}
// for the moment, update all views, but moving branch may be faster
pDoc - > UpdateAllViews ( NULL ) ;
/*
HTREEITEM htiNew = CopyBranch ( m_hitemDrag , m_hitemDrop , TVI_LAST ) ;
*/
}
void CConditionsView : : OnCopyAsSibling ( )
{
CTreeCtrl & tree = GetTreeCtrl ( ) ;
if ( m_hitemDrop = = tree . GetRootItem ( ) )
return ;
m_hitemDrop = tree . GetParentItem ( m_hitemDrop ) ;
OnCopyAsChild ( ) ;
}