2 ===========================================================================
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company.
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).
9 Doom 3 Source Code is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Doom 3 Source Code is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Doom 3 Source Code. If not, see <http://www.gnu.org/licenses/>.
22 In addition, the Doom 3 Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 Source Code. If not, please request a copy in writing from id Software at the address below.
24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
26 ===========================================================================
29 #include "../../idlib/precompiled.h"
32 #include "CPathTreeCtrl.h"
37 CPathTreeCtrl::CPathTreeCtrl
40 CPathTreeCtrl::CPathTreeCtrl() {
45 CPathTreeCtrl::~CPathTreeCtrl
48 CPathTreeCtrl::~CPathTreeCtrl() {
53 CPathTreeCtrl::PreSubclassWindow
56 void CPathTreeCtrl::PreSubclassWindow() {
57 CTreeCtrl::PreSubclassWindow();
58 EnableToolTips( TRUE );
63 CPathTreeCtrl::FindItem
65 Find the given path in the tree.
68 HTREEITEM CPathTreeCtrl::FindItem( const idStr &pathName ) {
70 idStr path, tmpPath, itemName;
71 HTREEITEM item, parentItem;
76 lastSlash = pathName.Last( '/' );
78 while( item && lastSlash > path.Length() ) {
79 itemName = GetItemText( item );
80 tmpPath = path + itemName;
81 if ( pathName.Icmpn( tmpPath, tmpPath.Length() ) == 0 ) {
83 item = GetChildItem( item );
86 item = GetNextSiblingItem( item );
90 for ( item = GetChildItem( parentItem ); item; item = GetNextSiblingItem( item ) ) {
91 itemName = GetItemText( item );
92 if ( pathName.Icmp( path + itemName ) == 0 ) {
102 CPathTreeCtrl::InsertPathIntoTree
104 Inserts a new item going from the root down the tree only creating paths where necessary.
105 This is slow and should only be used to insert single items.
108 HTREEITEM CPathTreeCtrl::InsertPathIntoTree( const idStr &pathName, const int id ) {
110 idStr path, tmpPath, itemName;
111 HTREEITEM item, parentItem;
114 item = GetRootItem();
116 lastSlash = pathName.Last( '/' );
118 while( item && lastSlash > path.Length() ) {
119 itemName = GetItemText( item );
120 tmpPath = path + itemName;
121 if ( pathName.Icmpn( tmpPath, tmpPath.Length() ) == 0 ) {
123 item = GetChildItem( item );
124 path = tmpPath + "/";
126 item = GetNextSiblingItem( item );
130 while( lastSlash > path.Length() ) {
131 pathName.Mid( path.Length(), pathName.Length(), tmpPath );
132 tmpPath.Left( tmpPath.Find( '/' ), itemName );
133 parentItem = InsertItem( itemName, parentItem );
134 path += itemName + "/";
137 pathName.Mid( path.Length(), pathName.Length(), itemName );
138 item = InsertItem( itemName, parentItem, TVI_SORT );
139 SetItemData( item, id );
146 CPathTreeCtrl::AddPathToTree
148 Adds a new item to the tree.
149 Assumes new paths after the current stack path do not yet exist.
152 HTREEITEM CPathTreeCtrl::AddPathToTree( const idStr &pathName, const int id, idPathTreeStack &stack ) {
154 idStr itemName, tmpPath;
157 lastSlash = pathName.Last( '/' );
159 while( stack.Num() > 1 ) {
160 if ( pathName.Icmpn( stack.TopName(), stack.TopNameLength() ) == 0 ) {
166 while( lastSlash > stack.TopNameLength() ) {
167 pathName.Mid( stack.TopNameLength(), pathName.Length(), tmpPath );
168 tmpPath.Left( tmpPath.Find( '/' ), itemName );
169 item = InsertItem( itemName, stack.TopItem() );
170 stack.Push( item, itemName );
173 pathName.Mid( stack.TopNameLength(), pathName.Length(), itemName );
174 item = InsertItem( itemName, stack.TopItem() );
175 SetItemData( item, id );
182 CPathTreeCtrl::SearchTree
184 Search the three using the search string.
185 Adds the matched tree items to the result tree.
186 Returns the number of items added to the result tree.
189 int CPathTreeCtrl::SearchTree( treeItemCompare_t compare, void *data, CPathTreeCtrl &result ) {
190 idPathTreeStack stack, searchStack;
191 HTREEITEM item, child;
196 result.DeleteAllItems();
197 stack.PushRoot( NULL );
199 item = GetRootItem();
200 searchStack.PushRoot( item );
203 while( searchStack.Num() > 0 ) {
205 for ( child = GetChildItem( item ); child; child = GetChildItem( child ) ) {
206 searchStack.Push( item, GetItemText( item ) );
210 name = searchStack.TopName();
211 name += GetItemText( item );
212 id = GetItemData( item );
214 if ( compare( data, item, name ) ) {
215 result.AddPathToTree( name, id, stack );
219 for ( item = GetNextSiblingItem( item ); item == NULL; ) {
220 item = GetNextSiblingItem( searchStack.TopItem() );
222 if ( searchStack.Num() <= 0 ) {
231 BEGIN_MESSAGE_MAP(CPathTreeCtrl,CTreeCtrl)
232 //{{AFX_MSG_MAP(CPathTreeCtrl)
233 ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTW, 0, 0xFFFF, OnToolTipText)
234 ON_NOTIFY_EX_RANGE(TTN_NEEDTEXTA, 0, 0xFFFF, OnToolTipText)
241 CPathTreeCtrl::OnToolHitTest
244 int CPathTreeCtrl::OnToolHitTest( CPoint point, TOOLINFO * pTI ) const {
248 HTREEITEM hitem = HitTest( point, &nFlags );
249 if( nFlags & TVHT_ONITEM ) {
250 GetItemRect( hitem, &rect, TRUE );
252 pTI->uId = (UINT)hitem;
253 pTI->lpszText = LPSTR_TEXTCALLBACK;
262 CPathTreeCtrl::OnToolTipText
265 BOOL CPathTreeCtrl::OnToolTipText( UINT id, NMHDR * pNMHDR, LRESULT * pResult ) {
266 // need to handle both ANSI and UNICODE versions of the message
267 TOOLTIPTEXTA* pTTTA = (TOOLTIPTEXTA*)pNMHDR;
268 TOOLTIPTEXTW* pTTTW = (TOOLTIPTEXTW*)pNMHDR;
270 UINT nID = pNMHDR->idFrom;
274 // Do not process the message from built in tooltip
275 if( nID == (UINT)m_hWnd &&
276 (( pNMHDR->code == TTN_NEEDTEXTA && pTTTA->uFlags & TTF_IDISHWND ) ||
277 ( pNMHDR->code == TTN_NEEDTEXTW && pTTTW->uFlags & TTF_IDISHWND ) ) ) {
281 CString toolTip = "?";
283 // Get the mouse position
286 pMessage = GetCurrentMessage();
289 ScreenToClient( &pt );
293 HTREEITEM hitem = HitTest( pt, &nFlags );
295 if( nFlags & TVHT_ONITEM ) {
296 // relay message to parent
297 pTTTA->hdr.hwndFrom = GetSafeHwnd();
298 pTTTA->hdr.idFrom = (UINT) hitem;
299 if ( GetParent()->SendMessage( WM_NOTIFY, ( TTN_NEEDTEXT << 16 ) | GetDlgCtrlID(), (LPARAM)pTTTA ) == FALSE ) {
304 return TRUE; // message was handled