]> icculus.org git repositories - icculus/iodoom3.git/blob - neo/tools/comafx/CPathTreeCtrl.cpp
Various Mac OS X tweaks to get this to build. Probably breaking things.
[icculus/iodoom3.git] / neo / tools / comafx / CPathTreeCtrl.cpp
1 /*
2 ===========================================================================
3
4 Doom 3 GPL Source Code
5 Copyright (C) 1999-2011 id Software LLC, a ZeniMax Media company. 
6
7 This file is part of the Doom 3 GPL Source Code (?Doom 3 Source Code?).  
8
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.
13
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.
18
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/>.
21
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.
23
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.
25
26 ===========================================================================
27 */
28
29 #include "../../idlib/precompiled.h"
30 #pragma hdrstop
31
32 #include "CPathTreeCtrl.h"
33
34
35 /*
36 ================
37 CPathTreeCtrl::CPathTreeCtrl
38 ================
39 */
40 CPathTreeCtrl::CPathTreeCtrl() {
41 }
42
43 /*
44 ================
45 CPathTreeCtrl::~CPathTreeCtrl
46 ================
47 */
48 CPathTreeCtrl::~CPathTreeCtrl() {
49 }
50
51 /*
52 ================
53 CPathTreeCtrl::PreSubclassWindow
54 ================
55 */
56 void CPathTreeCtrl::PreSubclassWindow() {
57         CTreeCtrl::PreSubclassWindow();
58         EnableToolTips( TRUE );
59 }
60
61 /*
62 ================
63 CPathTreeCtrl::FindItem
64
65 Find the given path in the tree.
66 ================
67 */
68 HTREEITEM CPathTreeCtrl::FindItem( const idStr &pathName ) {
69         int lastSlash;
70         idStr path, tmpPath, itemName;
71         HTREEITEM item, parentItem;
72
73         parentItem = NULL;
74         item = GetRootItem();
75
76         lastSlash = pathName.Last( '/' );
77
78         while( item && lastSlash > path.Length() ) {
79                 itemName = GetItemText( item );
80                 tmpPath = path + itemName;
81                 if ( pathName.Icmpn( tmpPath, tmpPath.Length() ) == 0 ) {
82                         parentItem = item;
83                         item = GetChildItem( item );
84                         path = tmpPath + "/";
85                 } else {
86                         item = GetNextSiblingItem( item );
87                 }
88         }
89
90         for ( item = GetChildItem( parentItem ); item; item = GetNextSiblingItem( item ) ) {
91                 itemName = GetItemText( item );
92                 if ( pathName.Icmp( path + itemName ) == 0 ) {
93                         return item;
94                 }
95         }
96
97         return NULL;
98 }
99
100 /*
101 ================
102 CPathTreeCtrl::InsertPathIntoTree
103
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.
106 ================
107 */
108 HTREEITEM CPathTreeCtrl::InsertPathIntoTree( const idStr &pathName, const int id ) {
109         int lastSlash;
110         idStr path, tmpPath, itemName;
111         HTREEITEM item, parentItem;
112
113         parentItem = NULL;
114         item = GetRootItem();
115
116         lastSlash = pathName.Last( '/' );
117
118         while( item && lastSlash > path.Length() ) {
119                 itemName = GetItemText( item );
120                 tmpPath = path + itemName;
121                 if ( pathName.Icmpn( tmpPath, tmpPath.Length() ) == 0 ) {
122                         parentItem = item;
123                         item = GetChildItem( item );
124                         path = tmpPath + "/";
125                 } else {
126                         item = GetNextSiblingItem( item );
127                 }
128         }
129
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 + "/";
135         }
136
137         pathName.Mid( path.Length(), pathName.Length(), itemName );
138         item = InsertItem( itemName, parentItem, TVI_SORT );
139         SetItemData( item, id );
140
141         return item;
142 }
143
144 /*
145 ================
146 CPathTreeCtrl::AddPathToTree
147
148 Adds a new item to the tree.
149 Assumes new paths after the current stack path do not yet exist.
150 ================
151 */
152 HTREEITEM CPathTreeCtrl::AddPathToTree( const idStr &pathName, const int id, idPathTreeStack &stack ) {
153         int lastSlash;
154         idStr itemName, tmpPath;
155         HTREEITEM item;
156
157         lastSlash = pathName.Last( '/' );
158
159         while( stack.Num() > 1 ) {
160                 if ( pathName.Icmpn( stack.TopName(), stack.TopNameLength() ) == 0 ) {
161                         break;
162                 }
163                 stack.Pop();
164         }
165
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 );
171         }
172
173         pathName.Mid( stack.TopNameLength(), pathName.Length(), itemName );
174         item = InsertItem( itemName, stack.TopItem() );
175         SetItemData( item, id );
176
177         return item;
178 }
179
180 /*
181 ================
182 CPathTreeCtrl::SearchTree
183
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.
187 ================
188 */
189 int CPathTreeCtrl::SearchTree( treeItemCompare_t compare, void *data, CPathTreeCtrl &result ) {
190         idPathTreeStack stack, searchStack;
191         HTREEITEM item, child;
192         idStr name;
193         int id, numItems;
194
195         numItems = 0;
196         result.DeleteAllItems();
197         stack.PushRoot( NULL );
198
199         item = GetRootItem();
200         searchStack.PushRoot( item );
201         id = 0;
202
203         while( searchStack.Num() > 0 ) {
204
205                 for ( child = GetChildItem( item ); child; child = GetChildItem( child ) ) {
206                         searchStack.Push( item, GetItemText( item ) );
207                         item = child;
208                 }
209
210                 name = searchStack.TopName();
211                 name += GetItemText( item );
212                 id = GetItemData( item );
213
214                 if ( compare( data, item, name ) ) {
215                         result.AddPathToTree( name, id, stack );
216                         numItems++;
217                 }
218
219                 for ( item = GetNextSiblingItem( item ); item == NULL;  ) {
220                         item = GetNextSiblingItem( searchStack.TopItem() );
221                         searchStack.Pop();
222                         if ( searchStack.Num() <= 0 ) {
223                                 return numItems;
224                         }
225                 }
226         }
227
228         return numItems;
229 }
230
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)
235         ON_WM_MOUSEMOVE()
236         //}}AFX_MSG_MAP
237 END_MESSAGE_MAP()
238
239 /*
240 ================
241 CPathTreeCtrl::OnToolHitTest
242 ================
243 */
244 int CPathTreeCtrl::OnToolHitTest( CPoint point, TOOLINFO * pTI ) const {
245         RECT rect;
246
247         UINT nFlags;
248         HTREEITEM hitem = HitTest( point, &nFlags );
249         if( nFlags & TVHT_ONITEM ) {
250                 GetItemRect( hitem, &rect, TRUE );
251                 pTI->hwnd = m_hWnd;
252                 pTI->uId = (UINT)hitem;
253                 pTI->lpszText = LPSTR_TEXTCALLBACK;
254                 pTI->rect = rect;
255                 return pTI->uId;
256         }
257         return -1;
258 }
259
260 /*
261 ================
262 CPathTreeCtrl::OnToolTipText
263 ================
264 */
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;
269
270         UINT nID = pNMHDR->idFrom;
271
272         *pResult = 0;
273
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 ) ) ) {
278                 return FALSE;
279         }
280
281         CString toolTip = "?";
282
283         // Get the mouse position
284         const MSG* pMessage;
285         CPoint pt;
286         pMessage = GetCurrentMessage();
287         ASSERT ( pMessage );
288         pt = pMessage->pt;
289         ScreenToClient( &pt );
290
291         // get the tree item
292         UINT nFlags;
293         HTREEITEM hitem = HitTest( pt, &nFlags );
294
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 ) {
300                         return FALSE;
301                 }
302         }
303
304         return TRUE;    // message was handled
305 }