1 //####COPYRIGHTBEGIN####
3 // ----------------------------------------------------------------------------
4 // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.
6 // This program is part of the eCos host tools.
8 // This program is free software; you can redistribute it and/or modify it
9 // under the terms of the GNU General Public License as published by the Free
10 // Software Foundation; either version 2 of the License, or (at your option)
13 // This program is distributed in the hope that it will be useful, but WITHOUT
14 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
18 // You should have received a copy of the GNU General Public License along with
19 // this program; if not, write to the Free Software Foundation, Inc.,
20 // 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 // ----------------------------------------------------------------------------
24 //####COPYRIGHTEND####
25 // ControlView.cpp : implementation file
28 //===========================================================================
29 //===========================================================================
30 //#####DESCRIPTIONBEGIN####
37 // Description: This is the implementation of the tree (control) view
44 //####DESCRIPTIONEND####
46 //===========================================================================
52 #include "ControlView.h"
53 #include "ConfigTool.h"
54 #include "ConfigItem.h"
55 #include "ConfigToolDoc.h"
59 #include "MessageBox.h"
60 #include "FindDialog.h"
61 #include "CTPropertiesDialog.h"
62 #include "ConfigViewOptionsDialog.h"
64 //#include "ide.common.h"
65 #define INCLUDEFILE "ide.guicommon.h" // for ID_EDIT_FINDAGAIN
66 #include "IncludeSTL.h"
72 #include <afxpriv.h> // for WM_COMMANDHELP, WM_HITTEST
75 #include "DescView.h" // for testing
79 static char THIS_FILE[] = __FILE__;
82 /////////////////////////////////////////////////////////////////////////////
85 IMPLEMENT_DYNCREATE(CControlView, CTreeView)
87 CControlView::CControlView()
91 m_dwDefaultStyle&=(~WS_VSCROLL);
93 m_hExpandedForFind=NULL;
94 m_GrayPen.CreatePen(PS_SOLID,1,RGB(192,192,192));
95 CConfigTool::SetControlView(this);
98 CControlView::~CControlView()
100 CConfigTool::SetControlView(0);
103 static UINT WM_FINDREPLACE = ::RegisterWindowMessage(FINDMSGSTRING);
105 BEGIN_MESSAGE_MAP(CControlView, CTreeView)
106 //{{AFX_MSG_MAP(CControlView)
108 ON_NOTIFY_REFLECT(TVN_ITEMEXPANDED, OnItemexpanded)
109 ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelchanged)
113 ON_COMMAND(ID_RESTORE_DEFAULTS, OnRestoreDefaults)
114 ON_COMMAND(ID_POPUP_PROPERTIES, OnPopupProperties)
115 ON_COMMAND(ID_UNLOAD_PACKAGE, OnUnload)
117 ON_COMMAND(ID_VIEW_URL, OnViewUrl)
121 ON_NOTIFY_REFLECT(TVN_ITEMEXPANDING, OnItemexpanding)
126 ON_COMMAND(ID_VIEW_HEADER, OnViewHeader)
127 ON_REGISTERED_MESSAGE( WM_FINDREPLACE, OnFind)
128 ON_COMMAND(ID_EDIT_FIND,OnEditFind)
129 ON_COMMAND(ID_EDIT_FINDAGAIN,OnEditFindAgain)
130 ON_UPDATE_COMMAND_UI(ID_EDIT_FINDAGAIN, OnUpdateEditFindAgain)
131 ON_UPDATE_COMMAND_UI(ID_EDIT_FIND, OnUpdateEditFind)
133 ON_NOTIFY_REFLECT(TVN_DELETEITEM, OnDeleteitem)
134 ON_COMMAND(ID_CV_WHATS_THIS, OnWhatsThis)
135 ON_MESSAGE(WM_SETFONT,OnSetFont)
142 /////////////////////////////////////////////////////////////////////////////
143 // CControlView drawing
145 void CControlView::OnDraw(CDC* pDC)
150 /////////////////////////////////////////////////////////////////////////////
151 // CControlView diagnostics
154 void CControlView::AssertValid() const
156 CTreeView::AssertValid();
159 void CControlView::Dump(CDumpContext& dc) const
166 /////////////////////////////////////////////////////////////////////////////
167 // CControlView message handlers
169 void CControlView::OnPaint()
171 CPaintDC dc(this); // device context for painting
173 // First let the control do its default drawing.
174 CWnd::DefWindowProc( WM_PAINT, (WPARAM)dc.m_hDC, 0 );
176 CConfigToolDoc* pDoc = CConfigTool::GetConfigToolDoc();
177 if(pDoc->ItemCount()>0)
179 // Redraw the disabled labels
180 CFont *pOldFont=dc.SelectObject(GetFont());
181 dc.SetTextColor(GetSysColor(COLOR_GRAYTEXT));
183 for(HTREEITEM h=GetFirstVisibleItem();h;h=GetNextVisibleItem(h))
185 const UINT selflag = TVIS_DROPHILITED | TVIS_SELECTED;
186 if(!IsActive(h)&&!(GetItemState( h, selflag ) & selflag )){
187 // Do not meddle with selected items or drop highlighted items
189 GetItemRect( h, &rect, TRUE );
190 dc.TextOut(m_TreeXOffsetAdjustment+rect.left+2, rect.top+1, GetItemText(h));
193 dc.SelectObject(pOldFont);
195 // Now draw grid lines
198 GetClientRect(rcClient);
199 CPen *pOldPen=dc.SelectObject(&m_GrayPen);
201 for(h=GetFirstVisibleItem();h;h=GetNextVisibleItem(h))
203 dc.MoveTo(rcClient.left,cy);
204 dc.LineTo(rcClient.right,cy);
207 dc.MoveTo(rcClient.left,cy);
208 dc.LineTo(rcClient.right,cy);
209 dc.SelectObject(pOldPen);
214 void CControlView::OnItemexpanded(NMHDR* pNMHDR, LRESULT* pResult)
216 //NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
218 //SetHScrollRangePos();
219 if(CConfigTool::GetCellView()){
220 CConfigTool::GetCellView()->Invalidate();
221 //sdf1 CConfigTool::GetCellView()->UpdateWindow();
225 UNUSED_ALWAYS(pNMHDR);
228 void CControlView::OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult)
230 //NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
233 UNUSED_ALWAYS(pNMHDR);
236 void CControlView::OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult)
238 CConfigToolDoc* pDoc = CConfigTool::GetConfigToolDoc();
239 if(pDoc->ItemCount()>0){
240 // Do nothing if in process of destroying configitems
241 NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
242 pDoc->UpdateAllViews (this, CConfigToolDoc::SelChanged, (CObject *)&TI(pNMTreeView->itemNew.hItem));
243 CConfigItem &ti=TI(pNMTreeView->itemNew.hItem);
245 CString strDesc(ti.Desc());
246 if(strDesc.IsEmpty()){
247 strDesc=_T("No context help is available for this item");
249 //pMain->m_wndHelp.SetWindowText(strDesc);
250 //pMain->m_wndHelp.SetTitle(ti.ItemNameOrMacro());
252 if(CConfigTool::GetCellView()){
253 CConfigTool::GetCellView()->Sync();
262 void CControlView::OnLButtonDown(UINT nFlags, CPoint point)
264 CConfigTool::GetCellView()->CancelCellEdit();
267 HTREEITEM h=HitTest(point,&nFlags);
268 if(h && IsActive(h) && (nFlags&TVHT_ONITEMICON))
271 BumpItem (h, TI (h).HasBool () ? 0 : 1); // toggle boolean or increment data
275 CTreeView::OnLButtonDown(nFlags,point);
279 // Relay to the splitter
280 ClientToScreen(&point);
281 GetParent()->ScreenToClient(&point);
282 GetParent()->SendMessage(WM_LBUTTONDOWN,(WPARAM)nFlags,MAKELPARAM(point.x,point.y));
286 void CControlView::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
288 // Round to nearest item and express in units of items for the benefit of CTreeView
289 nPos=(nPos+m_nItemHeight/2)/m_nItemHeight;
290 DefWindowProc(WM_VSCROLL,MAKELONG(nSBCode, nPos), (LPARAM)pScrollBar->m_hWnd);
294 /////////////////////////////////////////////////////////////////////////////
295 // CControlView message handlers
297 void CControlView::OnInitialUpdate()
299 CTreeView::OnInitialUpdate();
305 // Do this here, because the framework resets the title after calling OnOpenDocument()
306 CConfigToolDoc* pDoc = CConfigTool::GetConfigToolDoc();
307 CString strTitle(pDoc->BuildTree());
308 if(strTitle.IsEmpty())
310 strTitle+=_T("Repository ");
311 strTitle+=pDoc->Repository();
313 pDoc->SetTitle(strTitle);
318 void CControlView::OnSize(UINT nType, int cx, int cy)
321 CScrollBar *cv=GetScrollBarCtrl(SB_VERT);
322 //int dx=cx-m_Size.cx;
323 //int dy=cy-m_Size.cy;
325 TRACE("WM_SIZE[%d] dx=%d dy=%d depth=%d ch=%08x cv=%08x",
331 int bIsHScrollBarDelta=(cv==NULL);
332 //int bIsVScrollBarDelta=(ch==NULL);
333 if(bIsHScrollBarDelta/*dx==-16*/){
336 // if(bIsVScrollBarDelta/*dy==-16*/){
339 if(cx!=m_Size.cx || cy!=m_Size.cy){
341 DefWindowProc(WM_SIZE,(WPARAM)nType,MAKELPARAM(cx,cy));
345 //SetHScrollRangePos();
349 BOOL CControlView::PreCreateWindow(CREATESTRUCT& cs)
351 cs.style=TVS_HASBUTTONS | TVS_LINESATROOT | TVS_SHOWSELALWAYS |
352 WS_CHILD | WS_VISIBLE /*| WS_BORDER*/ | WS_TABSTOP;
353 cs.style&=(~WS_VSCROLL);
354 m_dwDefaultStyle&=(~WS_VSCROLL);
355 return CTreeView::PreCreateWindow(cs);
358 void CControlView::OnRButtonDown(UINT nFlags, CPoint point)
360 UNUSED_ALWAYS(nFlags);
362 HTREEITEM h=HitTest(point,&Flags);
366 // point is in client coords
367 ClientToScreen(&point);
368 ShowPopupMenu(h,point);
371 // Button functionality
373 void CControlView::Refresh (HTREEITEM h) // was Enable()
377 // Invalidate the labels of the affected items
379 GetItemRect(h, rect, TRUE );
380 rect.left+=m_TreeXOffsetAdjustment;
381 InvalidateRect(rect);
382 // Do the same for the cell view
384 CConfigTool::GetCellView()->GetClientRect(rcBuddyClient);
385 rect.left=rcBuddyClient.left;
386 rect.right=rcBuddyClient.right;
387 CConfigTool::GetCellView()->InvalidateRect(rect);
391 BOOL CControlView::IsActive(HTREEITEM h) const
393 const CdlUserVisible vitem = TI (h).GetCdlItem ();
394 return vitem ? vitem->is_active () : true;
397 void CControlView::AdjustItemImage(HTREEITEM h)
399 CConfigItem &ti=TI(h);
400 CString str(ti.ItemNameOrMacro());
405 // CConfigTool::GetConfigToolDoc()->SetTitle(_T("rt")); // Parameter is ignored
410 enum {FolderIcon=0, CheckBoxIcon=2, RadioIcon=6, IntegerIcon=10, StringIcon=12, EnumIcon=14, PackageIcon=16, DoubleIcon=20};
414 nImage = PackageIcon;
416 nImage = ti.HasRadio () ? RadioIcon : CheckBoxIcon;
426 case CConfigItem::Boolean:
427 nImage=ti.IsPackage()?PackageIcon:CheckBoxIcon;
428 // These images have all four states
434 case CConfigItem::Radio:
443 case CConfigItem::Double:
446 case CConfigItem::Integer:
449 case CConfigItem::Enum:
452 case CConfigItem::None:
455 case CConfigItem::String:
456 // if a package use the enabled package icon else use the string icon
457 nImage = ti.IsPackage () ? PackageIcon + 2 : StringIcon;
464 // All items have an enabled alternative
469 // else if (ti.Type () == CConfigItem::Boolean)
470 else if ((ti.Type () != CConfigItem::None) || ti.HasBool ())
472 // grey icon if the option is not modifiable or is inactive
473 const CdlValuable valuable = ti.GetCdlValuable();
474 if (valuable && ! (valuable->is_modifiable () && valuable->is_active ()))
477 BOOL b=SetItemImage(h,nImage,nImage);
481 ItemIntegerType CControlView::Value(HTREEITEM h) const
484 CConfigItem &ti=TI(h);
485 if(CConfigTool::GetCellView()->ActiveCell()==h){
486 rc=CConfigTool::GetCellView()->GetCellValue();
494 void CControlView::OnUpdate(CView* pSender, LPARAM lHint, CObject* pHint)
496 CConfigToolDoc* pDoc = CConfigTool::GetConfigToolDoc();
499 case CConfigToolDoc::AllSaved:
502 for(int nItem=0;nItem<pDoc->ItemCount();nItem++)
504 CConfigItem *pItem=pDoc->Item(nItem);
505 HTREEITEM h=pItem->HItem();
507 SetItemText(h,pItem->ItemNameOrMacro());
513 case CConfigToolDoc::NameFormatChanged:
515 for(int nItem=0;nItem<pDoc->ItemCount();nItem++)
517 CConfigItem *pItem=pDoc->Item(nItem);
518 CString strName(pItem->ItemNameOrMacro());
519 if(pItem->Modified()){
520 strName+=_TCHAR('*');
522 SetItemText(pItem->HItem(),strName);
528 case CConfigToolDoc::IntFormatChanged:
530 case CConfigToolDoc::Clear:
531 m_hExpandedForFind=NULL;
535 case CConfigToolDoc::ValueChanged:
537 CConfigItem &ti=*(CConfigItem *)pHint;
538 HTREEITEM h=ti.HItem();
541 case CConfigItem::Integer:
542 // case CConfigItem::Boolean:
543 // case CConfigItem::Radio:
545 ItemIntegerType n=ti.Value();
547 for(HTREEITEM hc=GetChildItem(h);hc;hc=GetNextSiblingItem (hc)){
551 // In the case of radio buttons, do the same thing to my siblings:
552 if(ti.Type()==CConfigItem::Radio && n==1){
553 for(HTREEITEM hs=ti.FirstRadio()->HItem();hs;hs=GetNextSiblingItem(hs)){
554 if(TI(hs).Type()==CConfigItem::Radio && hs!=h){
556 // Enable or disable their children
557 for(HTREEITEM hn=GetChildItem(hs);hn;hn=GetNextSiblingItem(hn)){
564 if(pDoc->m_bAutoExpand){
565 if ( (0==(GetItemState(h,TVIS_EXPANDED) & TVIS_EXPANDED)) != (0==n) ){
566 Expand(h,n?TVE_EXPAND:TVE_COLLAPSE);
570 //SetHScrollRangePos();
571 if(CConfigTool::GetCellView()){
572 CConfigTool::GetCellView()->Invalidate();
581 GetItemRect(h,rect,FALSE);
582 InvalidateRect(rect);
585 case CConfigToolDoc::ExternallyChanged:
587 for(int nItem=0;nItem<pDoc->ItemCount();nItem++){
588 CConfigItem *pItem=pDoc->Item(nItem);
589 AdjustItemImage(pItem->HItem());
594 if(pDoc->ItemCount()>0)
597 GetItemRect(GetFirstVisibleItem(),rect,FALSE);
598 m_nItemHeight=rect.Height();
599 m_nWorkspace=m_nItemHeight;
601 SetHScrollRangePos();
604 for(int nItem=0;nItem<pDoc->ItemCount();nItem++)
606 CConfigItem *pItem=pDoc->Item(nItem);
607 ASSERT(pItem->HItem());
608 switch(pItem->Type()){
609 case CConfigItem::None:
611 case CConfigItem::String:
612 case CConfigItem::Enum:
613 case CConfigItem::Integer:
614 case CConfigItem::Double:
615 // case CConfigItem::Boolean:
618 // case CConfigItem::Radio:
619 // nCP+=(pItem==pItem->FirstRadio());
626 TRACE(_T("### done creating - %d config items created: %d configuration points\n"),GetCount(),nCP);
633 break; // not for us, apparently
635 UNUSED_ALWAYS(pSender);
638 void CControlView::OnRestoreDefaults()
640 if(TI(m_hContext).HasModifiedChildren())
642 switch(CUtils::MessageBoxFT(MB_YESNOCANCEL,_T("Restore defaults for nested items?")))
645 RestoreDefault(m_hContext,TRUE);
648 RestoreDefault(m_hContext,FALSE);
658 RestoreDefault(m_hContext,FALSE);
661 // current values may have changed so refresh the other views
662 //CConfigTool::GetConfigToolDoc ()->UpdateFailingRuleCount ();
663 if (TI (m_hContext).Type () != CConfigItem::None)
664 CConfigTool::GetConfigToolDoc ()->UpdateAllViews (NULL, CConfigToolDoc::ValueChanged, (CObject *) GetItemData (m_hContext));
667 void CControlView::OnPopupProperties()
669 if(NULL==m_hContext){
670 m_hContext=GetSelectedItem();
672 if(NULL!=m_hContext){
673 CCTPropertiesDialog dlg(TI(m_hContext));
680 void CControlView::RestoreDefault(HTREEITEM h, BOOL bRecurse /* = FALSE */, BOOL bTopLevel /* = TRUE */)
682 CConfigItem &ti = TI (h);
683 const CdlValuable valuable = ti.GetCdlValuable();
684 if (valuable && (CdlValueFlavor_None != valuable->get_flavor ())) // skip the root node and nodes without a value
685 valuable->set_source (CdlValueSource_Default);
686 SetItemText (h, ti.ItemNameOrMacro ()); // remove asterisk in control view
688 if (bTopLevel && ti.HasRadio ()) // if user-specified item is a radio button
690 for (CConfigItem * pItem = ti.FirstRadio (); pItem; pItem = pItem->NextRadio ())
694 const CdlValuable valuable = pItem->GetCdlValuable();
696 valuable->set_source (CdlValueSource_Default); // restore default for each sibling radio button
697 SetItemText (pItem->HItem (), pItem->ItemNameOrMacro ()); // remove asterisk in control view
705 for (h = GetChildItem (h); h; h = GetNextSiblingItem (h))
707 RestoreDefault (h, TRUE, FALSE);
712 BOOL CControlView::IsChanged(HTREEITEM h, BOOL bRecurse)
714 BOOL rc = TI (h).Modified ();
715 // CConfigItem &ti=TI(h);
716 // BOOL rc=(0!=ti.StringDefaultValue().Compare(ti.StringValue()));
719 for(h=GetChildItem(h);h;h=GetNextSiblingItem(h))
721 if(IsChanged(h,TRUE))
732 void CControlView::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
735 HTREEITEM h=GetSelectedItem();
739 CTreeView::OnKeyDown(nChar, nRepCnt, nFlags);
742 void CControlView::InvalidateItem(HTREEITEM h)
744 if(CConfigTool::GetCellView()->ActiveCell()==h)
746 //m_pwndCell->Invalidate();
751 GetItemRect(h,rect,FALSE);
752 InvalidateRect(rect);
757 void CControlView::OnViewSwitches()
760 CConfigToolDoc* pDoc = CConfigTool::GetConfigToolDoc();
761 for(int nItem=0;nItem<pDoc->ItemCount();nItem++)
763 CConfigItem *pItem=pDoc->Item(nItem);
764 HTREEITEM h=pItem->HItem();
765 if(pItem->m_Icon==CConfigItem::IconCheckbox)
767 pItem->m_Icon=CConfigItem::IconSwitch;
768 } else if(pItem->m_Icon==CConfigItem::IconSwitch)
770 pItem->m_Icon=CConfigItem::IconCheckbox;
779 void CControlView::OnUpdateViewSwitches(CCmdUI* pCmdUI)
781 pCmdUI->SetCheck(m_bSwitches);
784 void CControlView::OnViewCheckboxes()
788 void CControlView::OnUpdateViewCheckboxes(CCmdUI* pCmdUI)
790 pCmdUI->SetCheck(!m_bSwitches);
793 void CControlView::OnViewUrl()
795 TI(m_hContext).ViewURL();
798 bool CControlView::BumpItem(HTREEITEM h,int nInc)
801 // Take an action for clicking on the icon
802 CConfigToolDoc* pDoc = CConfigTool::GetConfigToolDoc();
803 CConfigItem &ti=TI(h);
805 // do not modify the option value if it is inactive or not modifiable
806 const CdlValuable valuable = ti.GetCdlValuable();
807 if (!valuable || (valuable->is_modifiable () && valuable->is_active ())) {
808 if (0 == nInc) // if a toggle request
810 if (ti.HasBool () && ! (ti.HasRadio () && ti.IsEnabled ())) { // only enable (not disable) a radio button
811 rc=pDoc->SetEnabled (ti, ! ti.IsEnabled ()); // toggle enabled/disabled state
813 } else if (ti.IsEnabled ()) { // the item is enabled...
816 case CConfigItem::None:
817 case CConfigItem::String:
818 case CConfigItem::Double:
820 case CConfigItem::Enum:
823 ti.EvalEnumStrings (arEnum); // calculate legal values just in time
824 if (0==arEnum.GetSize()) // if no legal values...
825 break; // ...do nothing
827 const CString strCurrent = ti.StringValue ();
828 for (int nEnum = 0; (nEnum < arEnum.GetSize()) && (nIndex == -1); nEnum++)
829 if (0 == arEnum[nEnum].Compare (strCurrent))
830 nIndex = nEnum; // the index of the current value
832 if (nIndex != -1) // if the current value is still legal
833 nIndex += (nInc < 0 ? -1 : 1); // increment/decrement the index
835 nIndex = 0; // otherwise select the first enum
837 if (nIndex < 0) // if the new index is negative
838 nIndex = arEnum.GetSize()-1; // make it positive
840 rc=pDoc->SetValue (ti, arEnum[nIndex % arEnum.GetSize()]);
843 case CConfigItem::Integer:
845 ItemIntegerType nOldValue=Value(h);
846 if(nInc==1 && nOldValue==ItemIntegerType (-1)){
848 } else if(nInc==-1 && nOldValue==0){
849 nOldValue=ItemIntegerType (-1);
853 rc=pDoc->SetValue(ti,nOldValue);
859 case CConfigItem::Boolean:
862 ItemIntegerType nOldValue=Value(h);
863 pDoc->SetValue(ti,nOldValue^1);
866 case CConfigItem::Radio:
869 pDoc->SetValue(ti, (ItemIntegerType) 1);
882 int CControlView::OnCreate(LPCREATESTRUCT lpCreateStruct)
884 if (CTreeView::OnCreate(lpCreateStruct) == -1)
887 BOOL b=m_il.Create(IDB_BITMAP2,16,1,RGB(0,128,128));
889 // This code is necessary because of what appears to be an inconsistency between
890 // different versions of the common control dll. In some the text rectangles seem
891 // not to take into account the offset introduced by the item image of the root item.
892 // The offset is used in the OnPaint handler to make sure the greyed text is in the
897 HTREEITEM h=InsertItem(_T("Foo"));
899 GetItemRect(h,rect1,TRUE);
901 SetImageList(&m_il,TVSIL_NORMAL);
902 GetItemRect(h,rect2,TRUE);
903 m_TreeXOffsetAdjustment=rect1.left==0?(rect2.left-rect1.left):0;
911 GetClientRect(rcClient);
912 CSplitterWnd *pSplitter=(CSplitterWnd*)GetParent();
913 pSplitter->SetColumnInfo(1,rcClient.Width()/4,0);
918 void CControlView::KillScrollBars()
920 CSplitterWnd *pSplit=(CSplitterWnd *)GetParent();
923 pSplit->GetColumnInfo(col,curX,min);
927 pSplit->GetRowInfo (0,curY,min);
932 GetClientRect(rcClient);
934 TRACE("splitter[%d]=(%d,%d) view=(%d,%d)",
937 rcClient.Width(),rcClient.Height());
939 if(curX>rcClient.Width()&&curY>rcClient.Height()){
940 //sdf ShowScrollBar(SB_BOTH,FALSE);
941 ShowScrollBar(SB_VERT,FALSE);
943 if(curX>rcClient.Width()){
945 ShowScrollBar(SB_VERT,FALSE);
947 if(curY>rcClient.Height()){
949 //sdf ShowScrollBar(SB_HORZ,FALSE);
955 void CControlView::SetScrollPos()
957 if(m_bHasVScroll==1){
959 GetTreeCtrl().GetItemRect(GetTreeCtrl().GetRootItem(),rect,FALSE);
960 CScrollBar *cv=(CScrollBar *)(GetParent()->GetDlgItem(AFX_IDW_VSCROLL_FIRST));
962 if(cv && m_bHasVScroll){
963 //TRACE("SetScrollPos %d\n",-rect.top);
964 cv->SetScrollPos(-rect.top);
965 //SetScrollInfo(SB_VERT,&si,SIF_POS);
970 void CControlView::SetScrollRangePos()
972 RecalcWorkSpaceSize();
974 CScrollBar *cv=(CScrollBar *)(GetParent()->GetDlgItem(AFX_IDW_VSCROLL_FIRST));
979 GetClientRect(rcClient);
981 si.cbSize=sizeof SCROLLINFO;
982 memset(&si,0,sizeof SCROLLINFO);
983 si.nPage=rcClient.Height();
984 si.fMask=SIF_PAGE|SIF_RANGE|SIF_POS;
987 GetTreeCtrl().GetItemRect(GetTreeCtrl().GetRootItem(),rect,FALSE);
989 BOOL bHasVScroll=(si.nPage<(unsigned)m_nWorkspace);
991 si.nMax=m_nWorkspace/*-si.nPage*/;
992 cv->SetScrollInfo(&si,SIF_PAGE|SIF_RANGE|SIF_POS);
993 //TRACE("SetScrollInfo range=(%d,%d) pos=%d page=%d\n",si.nMin,si.nMax,si.nPos,si.nPage);
995 if(bHasVScroll!=m_bHasVScroll){
996 CSplitterWnd *pSplitter=(CSplitterWnd *)GetParent();
997 DWORD style=(pSplitter->GetScrollStyle()&(~WS_VSCROLL))
998 |(bHasVScroll*WS_VSCROLL);
999 pSplitter->SetScrollStyle(style);
1000 pSplitter->RecalcLayout();
1001 m_bHasVScroll=bHasVScroll;
1007 void CControlView::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
1009 CTreeView::OnHScroll(nSBCode, nPos, pScrollBar);
1013 void CControlView::SetHScrollRangePos()
1018 void CControlView::SetHScrollPos()
1022 GetClientRect(rcClient);
1024 si.cbSize=sizeof SCROLLINFO;
1025 memset(&si,0,sizeof SCROLLINFO);
1028 GetTreeCtrl().GetItemRect(GetTreeCtrl().GetRootItem(),rect,FALSE);
1031 CScrollBar *cv=(CScrollBar *)(GetParent()->GetDlgItem(AFX_IDW_HSCROLL_FIRST+nCol));
1033 if(cv && m_bHasHScroll){
1034 cv->SetScrollInfo(&si,SIF_POS);
1035 //SetScrollInfo(SB_HORZ,&si,SIF_POS);
1040 void CControlView::OnMouseMove(UINT nFlags, CPoint point)
1042 CTreeView::OnMouseMove(nFlags, point) ;
1044 // Relay the mouse event to the splitter
1045 ClientToScreen(&point);
1046 GetParent()->ScreenToClient(&point);
1047 GetParent()->SendMessage(WM_MOUSEMOVE,(WPARAM)nFlags,MAKELPARAM(point.x,point.y));
1050 BOOL CControlView::OnMouseWheel(UINT, short zDelta, CPoint)
1052 UINT nScrollCode=((zDelta<0)?SB_LINEDOWN:SB_LINEUP);
1053 LPARAM lParam=(LPARAM)GetScrollBarCtrl(SB_VERT)->GetSafeHwnd();
1055 for(int i=0;i<abs(zDelta)/WHEEL_DELTA;i++){
1056 SendMessage(WM_VSCROLL,MAKEWPARAM(nScrollCode,0),lParam);
1057 CConfigTool::GetCellView()->Sync();
1063 void CControlView::RecalcWorkSpaceSize()
1065 //TRACE("Control view recalcworkspace\n");
1066 CRect rcFirst,rcLast;
1067 CConfigToolDoc* pDoc = CConfigTool::GetConfigToolDoc();
1068 if(pDoc->ItemCount()>0){
1069 HTREEITEM h=pDoc->FirstItem()->HItem();
1071 GetItemRect(h,rcFirst,FALSE);
1072 if(pDoc->ItemCount()>0 && pDoc->Item(pDoc->ItemCount()-1)->HItem()){
1073 for(HTREEITEM h=pDoc->Item(pDoc->ItemCount()-1)->HItem();h;h=GetPrevVisibleItem(h)){
1074 if(GetItemRect(h,rcLast,FALSE)){
1075 m_nWorkspace=rcLast.bottom-rcFirst.top;
1084 void CControlView::OnSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
1088 if(::GetKeyState(VK_SHIFT)&0x8000){
1090 ShowPopupMenu(GetSelectedItem());
1096 m_hContext=GetSelectedItem();
1097 OnPopupProperties();
1101 CTreeView::OnSysKeyDown(nChar, nRepCnt, nFlags);
1104 void CControlView::ShowPopupMenu(HTREEITEM h,CPoint point/*=CPoint(-1,-1)*/)
1106 // Display a context menu
1109 menu.LoadMenu(IDR_CONTROLVIEW_POPUP);
1110 Menu *pPopup=(Menu *)menu.GetSubMenu(0);
1114 GetItemRect(h,rcItem,TRUE);
1115 point=rcItem.CenterPoint();
1116 ClientToScreen(&point);
1119 CConfigItem &ti=TI(m_hContext);
1120 CConfigItem::TreeItemType type=ti.Type();
1123 menu.LoadToolbar(IDR_MISCBAR);
1125 if(!IsChanged(m_hContext,true)){
1126 pPopup->EnableMenuItem(ID_RESTORE_DEFAULTS,MF_BYCOMMAND|MF_GRAYED);
1129 if((CConfigItem::None!=type) || ti.HasBool ()){
1130 const CString strURL(ti.GetURL());
1131 if(strURL.IsEmpty()){
1132 pPopup->EnableMenuItem(ID_VIEW_URL,MF_BYCOMMAND|MF_GRAYED);
1136 const CFileName strFile(TI(h).FileName());
1137 if(strFile.IsEmpty() || CConfigTool::GetConfigToolDoc()->BuildTree().IsEmpty()){
1138 pPopup->EnableMenuItem(ID_VIEW_HEADER,MF_BYCOMMAND|MF_GRAYED);
1141 if(!TI(h).IsPackage()){
1142 int n=pPopup->GetMenuItemCount();
1143 pPopup->RemoveMenu(n-1,MF_BYPOSITION);
1144 pPopup->RemoveMenu(n-2,MF_BYPOSITION);
1146 pPopup->TrackPopupMenu(TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON, point.x,point.y,this);
1150 void CControlView::OnSysChar(UINT nChar, UINT nRepCnt, UINT nFlags)
1152 // TODO: Add your message handler code here and/or call default
1154 CTreeView::OnSysChar(nChar, nRepCnt, nFlags);
1157 CConfigToolDoc * CControlView::GetDocument()
1159 return CConfigTool::GetConfigToolDoc();
1162 void CControlView::OnViewHeader()
1164 TI(m_hContext).ViewHeader();
1167 void CControlView::OnEditFind()
1169 CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc();
1170 if(!CConfigTool::GetMain()->m_bFindInProgress){
1171 (new CFindDialog())->Create(pDoc->m_strFind,pDoc->m_nFindFlags&(FR_WHOLEWORD|FR_MATCHCASE|FR_DOWN),pDoc->m_nFindWhere, this);
1172 CConfigTool::GetMain()->m_bFindInProgress=true;
1176 void CControlView::OnEditFindAgain()
1178 CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc();
1179 DoFind(pDoc->m_strFind,pDoc->m_nFindFlags,pDoc->m_nFindWhere);
1182 LONG CControlView::OnFind(WPARAM wParam, LPARAM lParam)
1184 UNUSED_ALWAYS(wParam);
1185 CFindDialog *pDlg=(CFindDialog *)CFindDialog::GetNotifier(lParam);
1186 FINDREPLACE &fr=pDlg->m_fr;
1187 CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc();
1188 if(0==(fr.Flags&FR_DIALOGTERM)){
1189 pDoc->m_strFind=fr.lpstrFindWhat;
1190 pDoc->m_nFindFlags=fr.Flags;
1191 pDoc->m_nFindWhere=pDlg->m_nFindPos;
1193 CConfigItem *pItem=DoFind(pDoc->m_strFind,pDoc->m_nFindFlags,pDoc->m_nFindWhere);
1195 // Is the find window on top of the item?
1197 GetItemRect(pItem->HItem(),rect1,TRUE);
1198 ClientToScreen(rect1);
1199 pDlg->GetWindowRect(rect2); // screen coords
1200 rect1=rect1 & rect2;
1201 if(rect1.Height()|rect1.Width()){
1202 int nWidth=rect2.Width();
1203 rect2.left=rect1.right;
1204 rect2.right=rect2.left+nWidth;
1205 pDlg->MoveWindow(rect2);
1209 CConfigTool::GetMain()->m_bFindInProgress=false;
1215 CConfigItem * CControlView::DoFind(LPCTSTR pszWhat,DWORD dwFlags,WhereType where)
1217 CConfigToolDoc *pDoc=CConfigTool::GetConfigToolDoc();
1218 int nCount=pDoc->ItemCount();
1219 static LPCTSTR arWhereImage[]={_T("name"),_T("macro"),_T("description string"),_T("current value"),_T("default value")};
1221 CString strFind(pszWhat);
1222 if(!(dwFlags&FR_MATCHCASE)){
1223 strFind.MakeLower();
1226 HTREEITEM h=GetSelectedItem();
1231 for(nItem=nCount-1;nItem>=0;--nItem) {
1232 if(h==pDoc->Item(nItem)->HItem()){
1239 CConfigItem *pItem=NULL;
1240 for(int i=0;i<nCount;i++){
1241 if(dwFlags&FR_DOWN){
1242 nItem=(nItem+1)%nCount;
1244 nItem=(nCount+nItem-1)%nCount;
1246 pItem=pDoc->Item(nItem);
1248 CString strName(pItem->StringValue(where));
1249 if(0==(dwFlags&FR_MATCHCASE)){
1250 strName.MakeLower();
1252 int nIndex=strName.Find(strFind);
1254 if(dwFlags&FR_WHOLEWORD){
1255 // Enforce whole-word semantics: to left and right
1256 if(nIndex>0 && IsWordChar(strName[nIndex-1])){
1259 nIndex+=strFind.GetLength();
1260 if(nIndex<strName.GetLength() && IsWordChar(strName[nIndex])){
1269 if(m_hExpandedForFind){
1270 Expand(m_hExpandedForFind,TVE_COLLAPSE);
1272 HTREEITEM h=pItem->HItem();
1274 for(HTREEITEM hv=GetFirstVisibleItem();hv;hv=GetNextVisibleItem(hv)){
1280 // we want to record the highest unexpanded item
1281 for(HTREEITEM hv=GetParentItem(h);hv;hv=GetParentItem(hv)){
1282 const UINT selflag = TVIS_EXPANDED;
1283 if(0==(GetItemState( hv, selflag ) & selflag )){
1284 m_hExpandedForFind=hv;
1292 CUtils::MessageBoxF(_T("Cannot find the %s '%s'"),arWhereImage[where],pszWhat);
1297 bool CControlView::IsWordChar(TCHAR c)
1299 return _istalnum(c) || _TCHAR('_')==c;
1302 void CControlView::OnUpdateEditFindAgain(CCmdUI* pCmdUI)
1304 pCmdUI->Enable(!CConfigTool::GetMain()->m_bFindInProgress && !CConfigTool::GetConfigToolDoc()->m_strFind.IsEmpty() && CWnd::GetFocus() && m_hWnd==CWnd::GetFocus()->m_hWnd);
1307 bool CControlView::SelectItem(const CConfigItem *pItem)
1310 CConfigTool::GetMain()->ShoweCosBar();
1313 return SelectItem(pItem->HItem());
1316 void CControlView::OnUpdateEditFind(CCmdUI* pCmdUI)
1318 pCmdUI->Enable(!CConfigTool::GetMain()->m_bFindInProgress);
1321 BOOL CControlView::PreTranslateMessage(MSG* pMsg)
1323 // We handle WM_KEYDOWN here to avoid the problem of the keyboard buffer not being emptied
1324 if(WM_KEYDOWN==pMsg->message){
1325 HTREEITEM h=GetSelectedItem();
1327 switch(pMsg->wParam){
1329 if(BumpItem(h,0)){ // toggle boolean
1335 bool bShift=(::GetKeyState(VK_SHIFT)&0x8000);// Shift key down
1337 h=GetPrevVisibleItem(h);
1341 if(!CConfigTool::GetCellView()->InCell(h) && !bShift){
1342 h=GetNextVisibleItem(h);
1349 MessageBeep (0xFFFFFFFF);
1351 // Always handle this message to keep focus within the tree control
1357 return CTreeView::PreTranslateMessage(pMsg);
1360 void CControlView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags)
1362 HTREEITEM h=GetSelectedItem();
1366 if(!BumpItem(h,+1)){
1367 MessageBeep(0xffff);
1371 if(!BumpItem(h,-1)){
1372 MessageBeep(0xffff);
1378 CTreeView::OnChar(nChar, nRepCnt, nFlags);
1381 LRESULT CControlView::OnSetFont(WPARAM, LPARAM)
1383 LRESULT rc=Default();
1385 GetItemRect(GetFirstVisibleItem(),rect,FALSE);
1386 m_nItemHeight=rect.Height();
1387 RecalcWorkSpaceSize();
1391 void CControlView::OnUnload()
1393 if(IDYES==CUtils::MessageBoxFT(MB_YESNO|MB_DEFBUTTON2,_T("Are you sure you wish to unload this package?"))){
1394 TI(m_hContext).Unload();
1395 CConfigTool::GetConfigToolDoc()->RegenerateData();
1399 void CControlView::OnDeleteitem(NMHDR*, LRESULT* pResult)
1401 if(CConfigTool::GetCellView()){
1402 CConfigTool::GetCellView()->Invalidate();
1407 void CControlView::OnWhatsThis()
1409 DWORD dwPos=GetMessagePos();
1412 hhp.cbStruct=sizeof(hhp);
1414 hhp.hinst=AfxGetInstanceHandle();
1415 hhp.pszText=TI(m_hContext).Desc();
1416 hhp.pt.x=GET_X_LPARAM(dwPos);
1417 hhp.pt.y=GET_Y_LPARAM(dwPos);
1418 hhp.clrForeground=(COLORREF)-1; //default
1419 hhp.clrBackground=GetSysColor(COLOR_INFOBK);
1420 hhp.rcMargins=CRect(-1,-1,-1,-1);
1426 HH_DISPLAY_TEXT_POPUP, //HH_TP_HELP_CONTEXTMENU,
1432 void CControlView::Refresh(LPCTSTR pszMacroName)
1434 const CConfigItem * pItem=CConfigTool::GetConfigToolDoc()->Find(pszMacroName);
1435 if(pItem){ // will be NULL if item has been removed
1436 Refresh(pItem->HItem());
1440 BOOL CControlView::OnHelpInfo(HELPINFO*)
1442 return CConfigTool::GetConfigToolDoc()->ShowURL(CUtils::LoadString(IDS_CONTROL_VIEW_HELP));
1445 LRESULT CControlView::OnMenuChar(UINT, UINT, CMenu*)
1447 const MSG *pMsg=GetCurrentMessage();
1448 // punt to the mainframe to deal with shortcuts in popups
1449 return AfxGetMainWnd()->SendMessage(pMsg->message,pMsg->wParam,pMsg->lParam);