1e838fe808491a60ee37ef6dcac510191222b966
[public/netxms.git] / src / console / win32 / ObjectBrowser.cpp
1 //
2 // ObjectBrowser.cpp : implementation file
3 //
4
5 #include "stdafx.h"
6 #include "nxcon.h"
7 #include "ObjectBrowser.h"
8
9 #ifdef _DEBUG
10 #define new DEBUG_NEW
11 #undef THIS_FILE
12 static char THIS_FILE[] = __FILE__;
13 #endif
14
15
16 //
17 // Constants
18 //
19
20 #define PREVIEW_PANE_WIDTH 200
21
22
23 //
24 // Compare two items in object tree hash for qsort()
25 //
26
27 static int CompareTreeHashItems(const void *p1, const void *p2)
28 {
29 return ((OBJ_TREE_HASH *)p1)->dwObjectId < ((OBJ_TREE_HASH *)p2)->dwObjectId ? -1 :
30 (((OBJ_TREE_HASH *)p1)->dwObjectId > ((OBJ_TREE_HASH *)p2)->dwObjectId ? 1 : 0);
31 }
32
33
34 //
35 // Get netmask value depending on object's class
36 //
37
38 static DWORD GetObjectNetMask(NXC_OBJECT *pObject)
39 {
40 DWORD dwMask;
41
42 switch(pObject->iClass)
43 {
44 case OBJECT_SUBNET:
45 dwMask = pObject->subnet.dwIpNetMask;
46 break;
47 case OBJECT_INTERFACE:
48 dwMask = pObject->iface.dwIpNetMask;
49 break;
50 default:
51 dwMask = 0;
52 break;
53 }
54 return dwMask;
55 }
56
57
58 //
59 // Compare two list view items
60 //
61
62 static int CALLBACK CompareListItems(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
63 {
64 CObjectBrowser *pBrowser = (CObjectBrowser *)lParamSort;
65 char *pszStr1, *pszStr2;
66 DWORD dwNum1, dwNum2;
67 int iResult;
68
69 switch(SortMode(lParamSort))
70 {
71 case OBJECT_SORT_BY_ID:
72 iResult = COMPARE_NUMBERS(((NXC_OBJECT *)lParam1)->dwId, ((NXC_OBJECT *)lParam2)->dwId);
73 break;
74 case OBJECT_SORT_BY_NAME:
75 iResult = stricmp(((NXC_OBJECT *)lParam1)->szName, ((NXC_OBJECT *)lParam2)->szName);
76 break;
77 case OBJECT_SORT_BY_CLASS:
78 iResult = COMPARE_NUMBERS(((NXC_OBJECT *)lParam1)->iClass, ((NXC_OBJECT *)lParam2)->iClass);
79 break;
80 case OBJECT_SORT_BY_STATUS:
81 iResult = COMPARE_NUMBERS(((NXC_OBJECT *)lParam1)->iStatus, ((NXC_OBJECT *)lParam2)->iStatus);
82 break;
83 case OBJECT_SORT_BY_IP:
84 dwNum1 = ((NXC_OBJECT *)lParam1)->dwIpAddr;
85 dwNum2 = ((NXC_OBJECT *)lParam2)->dwIpAddr;
86 iResult = COMPARE_NUMBERS(dwNum1, dwNum2);
87 break;
88 case OBJECT_SORT_BY_MASK:
89 dwNum1 = GetObjectNetMask((NXC_OBJECT *)lParam1);
90 dwNum2 = GetObjectNetMask((NXC_OBJECT *)lParam2);
91 iResult = COMPARE_NUMBERS(dwNum1, dwNum2);
92 break;
93 case OBJECT_SORT_BY_IFINDEX:
94 dwNum1 = (((NXC_OBJECT *)lParam1)->iClass == OBJECT_INTERFACE) ?
95 ((NXC_OBJECT *)lParam1)->iface.dwIfIndex : 0;
96 dwNum2 = (((NXC_OBJECT *)lParam2)->iClass == OBJECT_INTERFACE) ?
97 ((NXC_OBJECT *)lParam2)->iface.dwIfIndex : 0;
98 iResult = COMPARE_NUMBERS(dwNum1, dwNum2);
99 break;
100 case OBJECT_SORT_BY_OID:
101 pszStr1 = (((NXC_OBJECT *)lParam1)->iClass == OBJECT_NODE) ?
102 ((NXC_OBJECT *)lParam1)->node.szObjectId : "";
103 pszStr2 = (((NXC_OBJECT *)lParam2)->iClass == OBJECT_NODE) ?
104 ((NXC_OBJECT *)lParam2)->node.szObjectId : "";
105 iResult = stricmp(pszStr1, pszStr2);
106 break;
107 default:
108 iResult = 0;
109 break;
110 }
111
112 return (SortDir(lParamSort) == SORT_ASCENDING) ? iResult : -iResult;
113 }
114
115
116 //
117 // CObjectBrowser implementation
118 //
119
120 IMPLEMENT_DYNCREATE(CObjectBrowser, CMDIChildWnd)
121
122 CObjectBrowser::CObjectBrowser()
123 {
124 m_pImageList = NULL;
125 m_dwTreeHashSize = 0;
126 m_pTreeHash = NULL;
127 m_dwFlags = SHOW_OBJECT_PREVIEW | VIEW_OBJECTS_AS_TREE;
128 m_dwSortMode = OBJECT_SORT_BY_NAME;
129 m_pCurrentObject = NULL;
130 }
131
132 CObjectBrowser::~CObjectBrowser()
133 {
134 delete m_pImageList;
135 safe_free(m_pTreeHash);
136 }
137
138
139 BEGIN_MESSAGE_MAP(CObjectBrowser, CMDIChildWnd)
140 //{{AFX_MSG_MAP(CObjectBrowser)
141 ON_WM_DESTROY()
142 ON_WM_CREATE()
143 ON_WM_SIZE()
144 ON_WM_SETFOCUS()
145 ON_COMMAND(ID_VIEW_REFRESH, OnViewRefresh)
146 ON_WM_GETMINMAXINFO()
147 ON_COMMAND(ID_OBJECT_VIEW_SHOWPREVIEWPANE, OnObjectViewShowpreviewpane)
148 ON_COMMAND(ID_OBJECT_VIEW_VIEWASLIST, OnObjectViewViewaslist)
149 ON_COMMAND(ID_OBJECT_VIEW_VIEWASTREE, OnObjectViewViewastree)
150 ON_WM_CONTEXTMENU()
151 ON_COMMAND(ID_OBJECT_PROPERTIES, OnObjectProperties)
152 ON_COMMAND(ID_OBJECT_VIEW_SELECTION, OnObjectViewSelection)
153 ON_UPDATE_COMMAND_UI(ID_OBJECT_VIEW_VIEWASLIST, OnUpdateObjectViewViewaslist)
154 ON_UPDATE_COMMAND_UI(ID_OBJECT_VIEW_VIEWASTREE, OnUpdateObjectViewViewastree)
155 ON_UPDATE_COMMAND_UI(ID_OBJECT_VIEW_SELECTION, OnUpdateObjectViewSelection)
156 ON_UPDATE_COMMAND_UI(ID_OBJECT_VIEW_SHOWPREVIEWPANE, OnUpdateObjectViewShowpreviewpane)
157 ON_UPDATE_COMMAND_UI(ID_OBJECT_PROPERTIES, OnUpdateObjectProperties)
158 ON_COMMAND(ID_OBJECT_DATACOLLECTION, OnObjectDatacollection)
159 ON_UPDATE_COMMAND_UI(ID_OBJECT_DATACOLLECTION, OnUpdateObjectDatacollection)
160 ON_COMMAND(ID_OBJECT_MANAGE, OnObjectManage)
161 ON_COMMAND(ID_OBJECT_UNMANAGE, OnObjectUnmanage)
162 ON_UPDATE_COMMAND_UI(ID_OBJECT_UNMANAGE, OnUpdateObjectUnmanage)
163 ON_UPDATE_COMMAND_UI(ID_OBJECT_MANAGE, OnUpdateObjectManage)
164 ON_COMMAND(ID_OBJECT_BIND, OnObjectBind)
165 ON_UPDATE_COMMAND_UI(ID_OBJECT_BIND, OnUpdateObjectBind)
166 ON_COMMAND(ID_OBJECT_CREATE_CONTAINER, OnObjectCreateContainer)
167 ON_COMMAND(ID_OBJECT_CREATE_NODE, OnObjectCreateNode)
168 ON_COMMAND(ID_OBJECT_DELETE, OnObjectDelete)
169 ON_UPDATE_COMMAND_UI(ID_OBJECT_DELETE, OnUpdateObjectDelete)
170 ON_COMMAND(ID_OBJECT_POLL_STATUS, OnObjectPollStatus)
171 ON_COMMAND(ID_OBJECT_POLL_CONFIGURATION, OnObjectPollConfiguration)
172 ON_UPDATE_COMMAND_UI(ID_OBJECT_POLL_STATUS, OnUpdateObjectPollStatus)
173 ON_UPDATE_COMMAND_UI(ID_OBJECT_POLL_CONFIGURATION, OnUpdateObjectPollConfiguration)
174 ON_WM_CLOSE()
175 ON_COMMAND(ID_OBJECT_CREATE_TEMPLATE, OnObjectCreateTemplate)
176 ON_COMMAND(ID_OBJECT_CREATE_TEMPLATEGROUP, OnObjectCreateTemplategroup)
177 ON_COMMAND(ID_OBJECT_WAKEUP, OnObjectWakeup)
178 ON_UPDATE_COMMAND_UI(ID_OBJECT_WAKEUP, OnUpdateObjectWakeup)
179 //}}AFX_MSG_MAP
180 ON_NOTIFY(TVN_SELCHANGED, IDC_TREE_VIEW, OnTreeViewSelChange)
181 ON_NOTIFY(LVN_COLUMNCLICK, IDC_LIST_VIEW, OnListViewColumnClick)
182 ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST_VIEW, OnListViewItemChange)
183 ON_NOTIFY(NM_DBLCLK, IDC_LIST_VIEW, OnListViewDblClk)
184 ON_MESSAGE(WM_OBJECT_CHANGE, OnObjectChange)
185 ON_MESSAGE(WM_FIND_OBJECT, OnFindObject)
186 END_MESSAGE_MAP()
187
188 /////////////////////////////////////////////////////////////////////////////
189 // CObjectBrowser message handlers
190
191
192 //
193 // WM_DESTROY message handler
194 //
195
196 void CObjectBrowser::OnDestroy()
197 {
198 ((CConsoleApp *)AfxGetApp())->OnViewDestroy(IDR_OBJECTS, this);
199 CMDIChildWnd::OnDestroy();
200 }
201
202
203 //
204 // WM_CREATE message handler
205 //
206
207 int CObjectBrowser::OnCreate(LPCREATESTRUCT lpCreateStruct)
208 {
209 RECT rect;
210 LVCOLUMN lvCol;
211 BYTE *pwp;
212 UINT iBytes;
213 int i;
214
215 if (CMDIChildWnd::OnCreate(lpCreateStruct) == -1)
216 return -1;
217
218 // Read browser configuration
219 m_dwFlags = theApp.GetProfileInt(_T("ObjectBrowser"), _T("Flags"), m_dwFlags);
220 m_dwSortMode = theApp.GetProfileInt(_T("ObjectBrowser"), _T("SortMode"), m_dwSortMode);
221
222 // Create preview pane
223 GetClientRect(&rect);
224 rect.right = PREVIEW_PANE_WIDTH;
225 m_wndPreviewPane.Create(WS_CHILD | ((m_dwFlags & SHOW_OBJECT_PREVIEW) ? WS_VISIBLE : 0),
226 rect, this, IDC_PREVIEW_PANE);
227
228 // Create tree view control
229 GetClientRect(&rect);
230 if (m_dwFlags & SHOW_OBJECT_PREVIEW)
231 {
232 rect.left = PREVIEW_PANE_WIDTH;
233 rect.right -= PREVIEW_PANE_WIDTH;
234 }
235 m_wndTreeCtrl.Create(WS_CHILD | TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT | TVS_SHOWSELALWAYS,
236 rect, this, IDC_TREE_VIEW);
237
238 // Create list view control
239 m_wndListCtrl.Create(WS_CHILD | LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SHAREIMAGELISTS, rect, this, IDC_LIST_VIEW);
240 m_wndListCtrl.SetExtendedStyle(LVS_EX_TRACKSELECT | LVS_EX_UNDERLINEHOT |
241 LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES);
242 m_wndListCtrl.SetHoverTime(0x7FFFFFFF);
243
244 // Setup list view columns
245 m_wndListCtrl.InsertColumn(0, "ID", LVCFMT_LEFT, 50);
246 m_wndListCtrl.InsertColumn(1, "Name", LVCFMT_LEFT, 100);
247 m_wndListCtrl.InsertColumn(2, "Class", LVCFMT_LEFT, 70);
248 m_wndListCtrl.InsertColumn(3, "Status", LVCFMT_LEFT, 70);
249 m_wndListCtrl.InsertColumn(4, "IP Address", LVCFMT_LEFT, 100);
250 m_wndListCtrl.InsertColumn(5, "IP Netmask", LVCFMT_LEFT, 100);
251 m_wndListCtrl.InsertColumn(6, "IFIndex", LVCFMT_LEFT, 60);
252 m_wndListCtrl.InsertColumn(7, "IFType", LVCFMT_LEFT, 120);
253 m_wndListCtrl.InsertColumn(8, "Caps", LVCFMT_LEFT, 40);
254 m_wndListCtrl.InsertColumn(9, "Object ID", LVCFMT_LEFT, 150);
255
256 // Create image list
257 m_pImageList = new CImageList;
258 m_pImageList->Create(g_pObjectSmallImageList);
259 m_iLastObjectImage = m_pImageList->GetImageCount();
260 m_pImageList->Add(theApp.LoadIcon(IDI_SORT_UP));
261 m_pImageList->Add(theApp.LoadIcon(IDI_SORT_DOWN));
262 m_iStatusImageBase = m_pImageList->GetImageCount();
263 m_pImageList->Add(theApp.LoadIcon(IDI_OVL_STATUS_WARNING));
264 m_pImageList->Add(theApp.LoadIcon(IDI_OVL_STATUS_MINOR));
265 m_pImageList->Add(theApp.LoadIcon(IDI_OVL_STATUS_MAJOR));
266 m_pImageList->Add(theApp.LoadIcon(IDI_OVL_STATUS_CRITICAL));
267 m_pImageList->Add(theApp.LoadIcon(IDI_OVL_STATUS_UNKNOWN));
268 m_pImageList->Add(theApp.LoadIcon(IDI_OVL_STATUS_UNMANAGED));
269 m_pImageList->Add(theApp.LoadIcon(IDI_OVL_STATUS_DISABLED));
270 m_pImageList->Add(theApp.LoadIcon(IDI_OVL_STATUS_TESTING));
271 for(i = STATUS_WARNING; i <= STATUS_TESTING; i++)
272 m_pImageList->SetOverlayImage(m_iStatusImageBase + i - 1, i);
273 m_wndTreeCtrl.SetImageList(m_pImageList, TVSIL_NORMAL);
274 m_wndListCtrl.SetImageList(m_pImageList, LVSIL_SMALL);
275
276 // Mark sorting column in list control
277 lvCol.mask = LVCF_IMAGE | LVCF_FMT;
278 lvCol.fmt = LVCFMT_BITMAP_ON_RIGHT | LVCFMT_IMAGE | LVCFMT_LEFT;
279 lvCol.iImage = m_iLastObjectImage + SortDir(m_dwSortMode);
280 m_wndListCtrl.SetColumn(SortMode(m_dwSortMode), &lvCol);
281
282 if (m_dwFlags & VIEW_OBJECTS_AS_TREE)
283 m_wndTreeCtrl.ShowWindow(SW_SHOW);
284 else
285 m_wndListCtrl.ShowWindow(SW_SHOW);
286
287 // Restore window size and position if we have one
288 if (theApp.GetProfileBinary(_T("ObjectBrowser"), _T("WindowPlacement"),
289 &pwp, &iBytes))
290 {
291 if (iBytes == sizeof(WINDOWPLACEMENT))
292 {
293 RestoreMDIChildPlacement(this, (WINDOWPLACEMENT *)pwp);
294 }
295 delete pwp;
296 }
297
298 ((CConsoleApp *)AfxGetApp())->OnViewCreate(IDR_OBJECTS, this);
299 PostMessage(WM_COMMAND, ID_VIEW_REFRESH, 0);
300 return 0;
301 }
302
303
304 //
305 // WM_SIZE message handler
306 //
307
308 void CObjectBrowser::OnSize(UINT nType, int cx, int cy)
309 {
310 CMDIChildWnd::OnSize(nType, cx, cy);
311
312 if (m_dwFlags & SHOW_OBJECT_PREVIEW)
313 {
314 m_wndPreviewPane.SetWindowPos(NULL, 0, 0, PREVIEW_PANE_WIDTH, cy, SWP_NOZORDER);
315 m_wndTreeCtrl.SetWindowPos(NULL, PREVIEW_PANE_WIDTH, 0, cx - PREVIEW_PANE_WIDTH,
316 cy, SWP_NOZORDER);
317 m_wndListCtrl.SetWindowPos(NULL, PREVIEW_PANE_WIDTH, 0, cx - PREVIEW_PANE_WIDTH,
318 cy, SWP_NOZORDER);
319 }
320 else
321 {
322 m_wndTreeCtrl.SetWindowPos(NULL, 0, 0, cx, cy, SWP_NOZORDER);
323 m_wndListCtrl.SetWindowPos(NULL, 0, 0, cx, cy, SWP_NOZORDER);
324 }
325 }
326
327
328 //
329 // WM_SETFOCUS message handler
330 //
331
332 void CObjectBrowser::OnSetFocus(CWnd* pOldWnd)
333 {
334 CMDIChildWnd::OnSetFocus(pOldWnd);
335
336 if (m_dwFlags & VIEW_OBJECTS_AS_TREE)
337 m_wndTreeCtrl.SetFocus();
338 else
339 m_wndListCtrl.SetFocus();
340 }
341
342
343 //
344 // WM_COMMAND::ID_VIEW_REFRESH message handler
345 //
346
347 void CObjectBrowser::OnViewRefresh()
348 {
349 NXC_OBJECT *pObject;
350 NXC_OBJECT_INDEX *pIndex;
351 DWORD i, dwNumObjects;
352
353 // Populate objects' tree
354 m_wndTreeCtrl.DeleteAllItems();
355 m_dwTreeHashSize = 0;
356
357 pObject = NXCGetTopologyRootObject();
358 if (pObject != NULL)
359 AddObjectToTree(pObject, TVI_ROOT);
360
361 pObject = NXCGetServiceRootObject();
362 if (pObject != NULL)
363 AddObjectToTree(pObject, TVI_ROOT);
364
365 pObject = NXCGetTemplateRootObject();
366 if (pObject != NULL)
367 AddObjectToTree(pObject, TVI_ROOT);
368
369 qsort(m_pTreeHash, m_dwTreeHashSize, sizeof(OBJ_TREE_HASH), CompareTreeHashItems);
370
371 // Populate object's list
372 m_wndListCtrl.DeleteAllItems();
373 NXCLockObjectIndex();
374 pIndex = (NXC_OBJECT_INDEX *)NXCGetObjectIndex(&dwNumObjects);
375 for(i = 0; i < dwNumObjects; i++)
376 if (!pIndex[i].pObject->bIsDeleted)
377 AddObjectToList(pIndex[i].pObject);
378 NXCUnlockObjectIndex();
379 m_wndListCtrl.SortItems(CompareListItems, m_dwSortMode);
380 }
381
382
383 //
384 // Add new object to tree
385 //
386
387 void CObjectBrowser::AddObjectToTree(NXC_OBJECT *pObject, HTREEITEM hParent)
388 {
389 DWORD i;
390 HTREEITEM hItem;
391 char szBuffer[512];
392 int iImage;
393
394 // Add object record with class-dependent text
395 CreateTreeItemText(pObject, szBuffer);
396 iImage = GetObjectImageIndex(pObject);
397 hItem = m_wndTreeCtrl.InsertItem(szBuffer, iImage, iImage, hParent);
398 m_wndTreeCtrl.SetItemData(hItem, pObject->dwId);
399 m_wndTreeCtrl.SetItemState(hItem, INDEXTOOVERLAYMASK(pObject->iStatus), TVIS_OVERLAYMASK);
400
401 // Add to hash
402 m_pTreeHash = (OBJ_TREE_HASH *)realloc(m_pTreeHash, sizeof(OBJ_TREE_HASH) * (m_dwTreeHashSize + 1));
403 m_pTreeHash[m_dwTreeHashSize].dwObjectId = pObject->dwId;
404 m_pTreeHash[m_dwTreeHashSize].hTreeItem = hItem;
405 m_dwTreeHashSize++;
406
407 // Add object's childs
408 for(i = 0; i < pObject->dwNumChilds; i++)
409 {
410 NXC_OBJECT *pChildObject = NXCFindObjectById(pObject->pdwChildList[i]);
411 if (pChildObject != NULL)
412 AddObjectToTree(pChildObject, hItem);
413 }
414
415 // Sort childs
416 SortTreeItems(hItem);
417 }
418
419
420 //
421 // Overloaded PreCreateWindow() method
422 //
423
424 BOOL CObjectBrowser::PreCreateWindow(CREATESTRUCT& cs)
425 {
426 if (cs.lpszClass == NULL)
427 cs.lpszClass = AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW, NULL, NULL,
428 AfxGetApp()->LoadIcon(IDI_TREE));
429 return CMDIChildWnd::PreCreateWindow(cs);
430 }
431
432
433 //
434 // WM_GETMINMAXINFO message handler
435 //
436
437 void CObjectBrowser::OnGetMinMaxInfo(MINMAXINFO FAR* lpMMI)
438 {
439 CMDIChildWnd::OnGetMinMaxInfo(lpMMI);
440 lpMMI->ptMinTrackSize.x = 350;
441 lpMMI->ptMinTrackSize.y = 250;
442 }
443
444
445 //
446 // WM_COMMAND::ID_OBJECT_VIEW_SHOWPREVIEWPANE message handler
447 //
448
449 void CObjectBrowser::OnObjectViewShowpreviewpane()
450 {
451 RECT rect;
452
453 GetClientRect(&rect);
454
455 if (m_dwFlags & SHOW_OBJECT_PREVIEW)
456 {
457 m_dwFlags &= ~SHOW_OBJECT_PREVIEW;
458 m_wndPreviewPane.ShowWindow(SW_HIDE);
459 m_wndTreeCtrl.SetWindowPos(NULL, 0, 0, rect.right, rect.bottom, SWP_NOZORDER);
460 m_wndListCtrl.SetWindowPos(NULL, 0, 0, rect.right, rect.bottom, SWP_NOZORDER);
461 }
462 else
463 {
464 m_dwFlags |= SHOW_OBJECT_PREVIEW;
465 m_wndTreeCtrl.SetWindowPos(NULL, PREVIEW_PANE_WIDTH, 0, rect.right - PREVIEW_PANE_WIDTH,
466 rect.bottom, SWP_NOZORDER);
467 m_wndListCtrl.SetWindowPos(NULL, PREVIEW_PANE_WIDTH, 0, rect.right - PREVIEW_PANE_WIDTH,
468 rect.bottom, SWP_NOZORDER);
469 m_wndPreviewPane.SetWindowPos(NULL, 0, 0, PREVIEW_PANE_WIDTH, rect.bottom, SWP_NOZORDER);
470 m_wndPreviewPane.ShowWindow(SW_SHOW);
471 }
472 }
473
474
475 //
476 // WM_NOTIFY::TVN_SELCHANGED message handler
477 //
478
479 void CObjectBrowser::OnTreeViewSelChange(LPNMTREEVIEW lpnmt, LRESULT *pResult)
480 {
481 if (m_dwFlags & VIEW_OBJECTS_AS_TREE)
482 {
483 m_pCurrentObject = NXCFindObjectById(lpnmt->itemNew.lParam);
484 m_wndPreviewPane.SetCurrentObject(m_pCurrentObject);
485 }
486 *pResult = 0;
487 }
488
489
490 //
491 // WM_OBJECT_CHANGE message handler
492 // wParam contains object's ID, and lParam pointer to corresponding NXC_OBJECT structure
493 //
494
495 void CObjectBrowser::OnObjectChange(WPARAM wParam, LPARAM lParam)
496 {
497 UpdateObjectTree(wParam, (NXC_OBJECT *)lParam);
498 UpdateObjectList((NXC_OBJECT *)lParam);
499 }
500
501
502 //
503 // Perform binary search on tree hash
504 // Returns INVALID_INDEX if key not found or position of appropriate network object
505 // We assume that pHash == NULL will not be passed
506 //
507
508 static DWORD SearchTreeHash(OBJ_TREE_HASH *pBase, DWORD dwHashSize, DWORD dwKey)
509 {
510 DWORD dwFirst, dwLast, dwMid;
511
512 dwFirst = 0;
513 dwLast = dwHashSize - 1;
514
515 if ((dwKey < pBase[0].dwObjectId) || (dwKey > pBase[dwLast].dwObjectId))
516 return INVALID_INDEX;
517
518 while(dwFirst < dwLast)
519 {
520 dwMid = (dwFirst + dwLast) / 2;
521 if (dwKey == pBase[dwMid].dwObjectId)
522 return dwMid;
523 if (dwKey < pBase[dwMid].dwObjectId)
524 dwLast = dwMid - 1;
525 else
526 dwFirst = dwMid + 1;
527 }
528
529 if (dwKey == pBase[dwLast].dwObjectId)
530 return dwLast;
531
532 return INVALID_INDEX;
533 }
534
535
536 //
537 // Find object's tree item for give object's id
538 //
539
540 DWORD CObjectBrowser::FindObjectInTree(DWORD dwObjectId)
541 {
542 DWORD dwIndex;
543
544 dwIndex = SearchTreeHash(m_pTreeHash, m_dwTreeHashSize, dwObjectId);
545 while((dwIndex > 0) && (m_pTreeHash[dwIndex - 1].dwObjectId == dwObjectId))
546 dwIndex--;
547 return dwIndex;
548 }
549
550
551 //
552 // Create class-depemdent text for tree item
553 //
554
555 void CObjectBrowser::CreateTreeItemText(NXC_OBJECT *pObject, char *pszBuffer)
556 {
557 char szIpBuffer[32];
558
559 switch(pObject->iClass)
560 {
561 case OBJECT_SUBNET:
562 sprintf(pszBuffer, "%s [Status: %s]", pObject->szName, g_szStatusText[pObject->iStatus]);
563 break;
564 case OBJECT_INTERFACE:
565 if (pObject->dwIpAddr != 0)
566 sprintf(pszBuffer, "%s [IP: %s/%d Status: %s]", pObject->szName,
567 IpToStr(pObject->dwIpAddr, szIpBuffer),
568 BitsInMask(pObject->iface.dwIpNetMask), g_szStatusText[pObject->iStatus]);
569 else
570 sprintf(pszBuffer, "%s [Status: %s]", pObject->szName, g_szStatusText[pObject->iStatus]);
571 break;
572 default:
573 strcpy(pszBuffer, pObject->szName);
574 break;
575 }
576 }
577
578
579 //
580 // Delete tree item and appropriate record in hash
581 //
582
583 void CObjectBrowser::DeleteObjectTreeItem(HTREEITEM hRootItem)
584 {
585 HTREEITEM hItem;
586 DWORD dwIndex, dwId;
587
588 // Delete all child items
589 hItem = m_wndTreeCtrl.GetNextItem(hRootItem, TVGN_CHILD);
590 while(hItem != NULL)
591 {
592 DeleteObjectTreeItem(hItem);
593 hItem = m_wndTreeCtrl.GetNextItem(hRootItem, TVGN_CHILD);
594 }
595
596 // Find hash record for current item
597 dwId = m_wndTreeCtrl.GetItemData(hRootItem);
598 dwIndex = FindObjectInTree(dwId);
599 if (dwIndex != INVALID_INDEX)
600 {
601 while((dwIndex < m_dwTreeHashSize) && (m_pTreeHash[dwIndex].hTreeItem != hRootItem))
602 dwIndex++;
603 // Delete appropriate record in tree hash list
604 if (dwIndex < m_dwTreeHashSize - 1)
605 memmove(&m_pTreeHash[dwIndex], &m_pTreeHash[dwIndex + 1],
606 sizeof(OBJ_TREE_HASH) * (m_dwTreeHashSize - dwIndex - 1));
607 m_dwTreeHashSize--;
608 }
609
610 // Delete item from tree control
611 m_wndTreeCtrl.DeleteItem(hRootItem);
612 }
613
614
615 //
616 // Update objects' tree when we receive WM_OBJECT_CHANGE message
617 //
618
619 void CObjectBrowser::UpdateObjectTree(DWORD dwObjectId, NXC_OBJECT *pObject)
620 {
621 DWORD i, j, dwIndex;
622
623 // Find object in tree
624 dwIndex = FindObjectInTree(dwObjectId);
625
626 if (pObject->bIsDeleted)
627 {
628 // Delete all tree items
629 while(dwIndex != INVALID_INDEX)
630 {
631 DeleteObjectTreeItem(m_pTreeHash[dwIndex].hTreeItem);
632 dwIndex = FindObjectInTree(dwObjectId);
633 }
634 }
635 else
636 {
637 HTREEITEM hItem;
638
639 if (dwIndex != INVALID_INDEX)
640 {
641 char szBuffer[256];
642 DWORD j, dwId, *pdwParentList;
643
644 // Create a copy of object's parent list
645 pdwParentList = (DWORD *)nx_memdup(pObject->pdwParentList,
646 sizeof(DWORD) * pObject->dwNumParents);
647
648 CreateTreeItemText(pObject, szBuffer);
649 restart_parent_check:;
650 for(i = dwIndex; (i < m_dwTreeHashSize) && (m_pTreeHash[i].dwObjectId == dwObjectId); i++)
651 {
652 // Check if this item's parent still in object's parents list
653 hItem = m_wndTreeCtrl.GetParentItem(m_pTreeHash[i].hTreeItem);
654 if (hItem != NULL)
655 {
656 dwId = m_wndTreeCtrl.GetItemData(hItem);
657 for(j = 0; j < pObject->dwNumParents; j++)
658 if (pObject->pdwParentList[j] == dwId)
659 {
660 pdwParentList[j] = 0; // Mark this parent as presented
661 break;
662 }
663 if (j == pObject->dwNumParents) // Not a parent anymore
664 {
665 // Delete this tree item
666 DeleteObjectTreeItem(m_pTreeHash[i].hTreeItem);
667 goto restart_parent_check; // Restart loop, because m_dwTreeHashSize was changed
668 }
669 else // Current tree item is still valid
670 {
671 m_wndTreeCtrl.SetItemText(m_pTreeHash[i].hTreeItem, szBuffer);
672 m_wndTreeCtrl.SetItemState(m_pTreeHash[i].hTreeItem,
673 INDEXTOOVERLAYMASK(pObject->iStatus), TVIS_OVERLAYMASK);
674 SortTreeItems(hItem);
675 }
676 }
677 else // Current tree item has no parent
678 {
679 m_wndTreeCtrl.SetItemText(m_pTreeHash[i].hTreeItem, szBuffer);
680 m_wndTreeCtrl.SetItemState(m_pTreeHash[i].hTreeItem,
681 INDEXTOOVERLAYMASK(pObject->iStatus), TVIS_OVERLAYMASK);
682 }
683 }
684
685 // Now walk through all object's parents which hasn't corresponding
686 // items in tree view
687 for(i = 0; i < pObject->dwNumParents; i++)
688 if (pdwParentList[i] != 0)
689 {
690 dwIndex = FindObjectInTree(pdwParentList[i]);
691 if (dwIndex != INVALID_INDEX)
692 {
693 // Walk through all occurences of current parent object
694 for(j = dwIndex; (j < m_dwTreeHashSize) &&
695 (m_pTreeHash[j].dwObjectId == pdwParentList[i]); j++)
696 {
697 AddObjectToTree(pObject, m_pTreeHash[j].hTreeItem);
698 SortTreeItems(m_pTreeHash[j].hTreeItem);
699 }
700 qsort(m_pTreeHash, m_dwTreeHashSize, sizeof(OBJ_TREE_HASH), CompareTreeHashItems);
701 }
702 }
703
704 // Destroy copy of object's parents list
705 safe_free(pdwParentList);
706 }
707 else
708 {
709 // New object, link to all parents
710 for(i = 0; i < pObject->dwNumParents; i++)
711 {
712 dwIndex = FindObjectInTree(pObject->pdwParentList[i]);
713 if (dwIndex != INVALID_INDEX)
714 {
715 // Walk through all occurences of current parent object
716 for(j = dwIndex; (j < m_dwTreeHashSize) &&
717 (m_pTreeHash[j].dwObjectId == pObject->pdwParentList[i]); j++)
718 {
719 AddObjectToTree(pObject, m_pTreeHash[j].hTreeItem);
720 SortTreeItems(m_pTreeHash[j].hTreeItem);
721 }
722 qsort(m_pTreeHash, m_dwTreeHashSize, sizeof(OBJ_TREE_HASH), CompareTreeHashItems);
723 }
724 }
725 }
726
727 if (m_dwFlags & VIEW_OBJECTS_AS_TREE)
728 {
729 if (m_dwFlags & FOLLOW_OBJECT_UPDATES)
730 {
731 dwIndex = FindObjectInTree(dwObjectId);
732 if (dwIndex != INVALID_INDEX) // Shouldn't happen
733 m_wndTreeCtrl.Select(m_pTreeHash[dwIndex].hTreeItem, TVGN_CARET);
734 }
735 else
736 {
737 // Check if current item has been changed
738 hItem = m_wndTreeCtrl.GetSelectedItem();
739 if (hItem != NULL)
740 {
741 if (m_wndTreeCtrl.GetItemData(hItem) == dwObjectId)
742 m_wndPreviewPane.Refresh();
743 }
744 }
745 }
746 }
747 }
748
749
750 //
751 // Add new object to objects' list
752 //
753
754 void CObjectBrowser::AddObjectToList(NXC_OBJECT *pObject)
755 {
756 int iItem;
757 char szBuffer[16];
758
759 sprintf(szBuffer, "%ld", pObject->dwId);
760 iItem = m_wndListCtrl.InsertItem(0x7FFFFFFF, szBuffer, GetObjectImageIndex(pObject));
761 if (iItem != -1)
762 {
763 m_wndListCtrl.SetItemData(iItem, (LPARAM)pObject);
764 UpdateObjectListEntry(iItem, pObject);
765 }
766 }
767
768
769 //
770 // WM_COMMAND::ID_OBJECT_VIEW_VIEWASLIST message handler
771 //
772
773 void CObjectBrowser::OnObjectViewViewaslist()
774 {
775 int iItem;
776
777 m_dwFlags &= ~VIEW_OBJECTS_AS_TREE;
778 m_wndListCtrl.ShowWindow(SW_SHOW);
779 m_wndTreeCtrl.ShowWindow(SW_HIDE);
780
781 // Display currenly selected item in preview pane
782 iItem = m_wndListCtrl.GetNextItem(-1, LVNI_FOCUSED);
783 m_pCurrentObject = (iItem == -1) ? NULL : (NXC_OBJECT *)m_wndListCtrl.GetItemData(iItem);
784 m_wndPreviewPane.SetCurrentObject(m_pCurrentObject);
785 }
786
787
788 //
789 // WM_COMMAND::ID_OBJECT_VIEW_VIEWASTREE message handler
790 //
791
792 void CObjectBrowser::OnObjectViewViewastree()
793 {
794 HTREEITEM hItem = NULL;
795
796 m_dwFlags |= VIEW_OBJECTS_AS_TREE;
797 m_wndTreeCtrl.ShowWindow(SW_SHOW);
798 m_wndListCtrl.ShowWindow(SW_HIDE);
799
800 // Display currenly selected item in preview pane
801 hItem = m_wndTreeCtrl.GetSelectedItem();
802 m_pCurrentObject = (hItem == NULL) ? NULL : NXCFindObjectById(m_wndTreeCtrl.GetItemData(hItem));
803 m_wndPreviewPane.SetCurrentObject(m_pCurrentObject);
804 }
805
806
807 //
808 // WM_NOTIFY::LVN_COLUMNCLICK message handler
809 //
810
811 void CObjectBrowser::OnListViewColumnClick(LPNMLISTVIEW pNMHDR, LRESULT *pResult)
812 {
813 LVCOLUMN lvCol;
814 int iColumn;
815
816 // Unmark old sorting column
817 iColumn = SortMode(m_dwSortMode);
818 lvCol.mask = LVCF_FMT;
819 lvCol.fmt = LVCFMT_LEFT;
820 m_wndListCtrl.SetColumn(iColumn, &lvCol);
821
822 // Change current sort mode and resort list
823 if (iColumn == pNMHDR->iSubItem)
824 {
825 // Same column, change sort direction
826 m_dwSortMode = iColumn |
827 (((SortDir(m_dwSortMode) == SORT_ASCENDING) ? SORT_DESCENDING : SORT_ASCENDING) << 8);
828 }
829 else
830 {
831 // Another sorting column
832 m_dwSortMode = (m_dwSortMode & 0xFFFFFF00) | pNMHDR->iSubItem;
833 }
834 m_wndListCtrl.SortItems(CompareListItems, m_dwSortMode);
835
836 // Mark new sorting column
837 lvCol.mask = LVCF_IMAGE | LVCF_FMT;
838 lvCol.fmt = LVCFMT_BITMAP_ON_RIGHT | LVCFMT_IMAGE | LVCFMT_LEFT;
839 lvCol.iImage = (SortDir(m_dwSortMode) == SORT_ASCENDING) ? m_iLastObjectImage : (m_iLastObjectImage + 1);
840 m_wndListCtrl.SetColumn(pNMHDR->iSubItem, &lvCol);
841
842 *pResult = 0;
843 }
844
845
846 //
847 // WM_NOTIFY::LVN_ITEMACTIVATE message handler
848 //
849
850 void CObjectBrowser::OnListViewItemChange(LPNMLISTVIEW pNMHDR, LRESULT *pResult)
851 {
852 if (!(m_dwFlags & VIEW_OBJECTS_AS_TREE))
853 {
854 if (pNMHDR->iItem != -1)
855 if (pNMHDR->uChanged & LVIF_STATE)
856 {
857 if (pNMHDR->uNewState & LVIS_FOCUSED)
858 {
859 m_pCurrentObject = (NXC_OBJECT *)m_wndListCtrl.GetItemData(pNMHDR->iItem);
860 }
861 else
862 {
863 m_pCurrentObject = NULL;
864 }
865 m_wndPreviewPane.SetCurrentObject(m_pCurrentObject);
866 }
867 }
868 *pResult = 0;
869 }
870
871
872 //
873 // WM_FIND_OBJECT message handler
874 //
875
876 void CObjectBrowser::OnFindObject(WPARAM wParam, LPARAM lParam)
877 {
878 if (*((char *)lParam) != 0)
879 {
880 NXC_OBJECT *pObject;
881
882 pObject = NXCFindObjectByName((char *)lParam);
883 if (pObject != NULL)
884 {
885 // Object found, select it in the current view
886 if (m_dwFlags & VIEW_OBJECTS_AS_TREE)
887 {
888 DWORD dwIndex;
889
890 dwIndex = FindObjectInTree(pObject->dwId);
891 if (dwIndex != INVALID_INDEX)
892 m_wndTreeCtrl.Select(m_pTreeHash[dwIndex].hTreeItem, TVGN_CARET);
893 else
894 MessageBox("Object found, but it's hidden and cannot be displayed at the moment",
895 "Find", MB_OK | MB_ICONEXCLAMATION);
896 m_wndTreeCtrl.SetFocus();
897 }
898 else
899 {
900 LVFINDINFO lvfi;
901 int iItem, iOldItem;
902
903 lvfi.flags = LVFI_PARAM;
904 lvfi.lParam = (LPARAM)pObject;
905 iItem = m_wndListCtrl.FindItem(&lvfi);
906 if (iItem != -1)
907 {
908 ClearListSelection();
909 iOldItem = m_wndListCtrl.GetNextItem(-1, LVNI_FOCUSED);
910 if (iOldItem != -1)
911 m_wndListCtrl.SetItemState(iOldItem, 0, LVIS_FOCUSED);
912 m_wndListCtrl.EnsureVisible(iItem, FALSE);
913 m_wndListCtrl.SetItemState(iItem, LVIS_SELECTED | LVIS_FOCUSED,
914 LVIS_SELECTED | LVIS_FOCUSED);
915 }
916 else
917 {
918 MessageBox("Object found, but it's hidden and cannot be displayed at the moment",
919 "Find", MB_OK | MB_ICONEXCLAMATION);
920 }
921 m_wndListCtrl.SetFocus();
922 }
923 }
924 else
925 {
926 char szBuffer[384];
927
928 sprintf(szBuffer, "Matching object for pattern \"%s\" not found", lParam);
929 MessageBox(szBuffer, "Find", MB_OK | MB_ICONSTOP);
930 }
931 }
932 }
933
934
935 //
936 // Clear selection from list control
937 //
938
939 void CObjectBrowser::ClearListSelection()
940 {
941 int iItem;
942
943 iItem = m_wndListCtrl.GetNextItem(-1, LVNI_SELECTED);
944 while(iItem != -1)
945 {
946 m_wndListCtrl.SetItemState(iItem, 0, LVIS_SELECTED);
947 iItem = m_wndListCtrl.GetNextItem(iItem, LVNI_SELECTED);
948 }
949 }
950
951
952 //
953 // WM_CONTEXTMENU message handler
954 //
955
956 void CObjectBrowser::OnContextMenu(CWnd* pWnd, CPoint point)
957 {
958 CMenu *pMenu;
959 CPoint pt;
960
961 pt = point;
962 pWnd->ScreenToClient(&pt);
963
964 if (pWnd->GetDlgCtrlID() == IDC_LIST_VIEW)
965 {
966 int iItem;
967 UINT uFlags;
968
969 iItem = m_wndListCtrl.HitTest(pt, &uFlags);
970 if ((iItem != -1) && (uFlags & LVHT_ONITEM))
971 {
972 pMenu = theApp.GetContextMenu(1);
973 pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this, NULL);
974 }
975 }
976 else if (pWnd->GetDlgCtrlID() == IDC_TREE_VIEW)
977 {
978 HTREEITEM hItem;
979 UINT uFlags;
980
981 hItem = m_wndTreeCtrl.HitTest(pt, &uFlags);
982 if ((hItem != NULL) && (uFlags & TVHT_ONITEM))
983 {
984 m_wndTreeCtrl.Select(hItem, TVGN_CARET);
985
986 pMenu = theApp.GetContextMenu(1);
987 pMenu->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this, NULL);
988 }
989 }
990 }
991
992
993 //
994 // WM_COMMAND::ID_OBJECT_PROPERTIES message handler
995 //
996
997 void CObjectBrowser::OnObjectProperties()
998 {
999 DWORD dwId;
1000
1001 dwId = GetSelectedObject();
1002 if (dwId != 0)
1003 theApp.ObjectProperties(dwId);
1004 }
1005
1006
1007 //
1008 // Get ID of currently selected object
1009 // Will return 0 if there are no selection
1010 //
1011
1012 DWORD CObjectBrowser::GetSelectedObject()
1013 {
1014 DWORD dwId = 0;
1015
1016 if (m_dwFlags & VIEW_OBJECTS_AS_TREE)
1017 {
1018 HTREEITEM hItem;
1019
1020 hItem = m_wndTreeCtrl.GetSelectedItem();
1021 if (hItem != NULL)
1022 dwId = m_wndTreeCtrl.GetItemData(hItem);
1023 }
1024 else
1025 {
1026 if (m_wndListCtrl.GetSelectedCount() == 1)
1027 {
1028 int iItem;
1029 NXC_OBJECT *pObject;
1030
1031 iItem = m_wndListCtrl.GetSelectionMark();
1032 pObject = (NXC_OBJECT *)m_wndListCtrl.GetItemData(iItem);
1033 if (pObject != NULL)
1034 dwId = pObject->dwId;
1035 }
1036 }
1037 return dwId;
1038 }
1039
1040
1041 //
1042 // Update object list with new object information
1043 //
1044
1045 void CObjectBrowser::UpdateObjectList(NXC_OBJECT *pObject)
1046 {
1047 LVFINDINFO lvfi;
1048 int iItem;
1049
1050 // Find object in list
1051 lvfi.flags = LVFI_PARAM;
1052 lvfi.lParam = (LPARAM)pObject;
1053 iItem = m_wndListCtrl.FindItem(&lvfi);
1054
1055 if (pObject->bIsDeleted)
1056 {
1057 if (iItem != -1)
1058 m_wndListCtrl.DeleteItem(iItem);
1059 }
1060 else
1061 {
1062 if (iItem != -1)
1063 {
1064 UpdateObjectListEntry(iItem, pObject);
1065 }
1066 else
1067 {
1068 AddObjectToList(pObject);
1069 }
1070 m_wndListCtrl.SortItems(CompareListItems, m_dwSortMode);
1071
1072 if (!(m_dwFlags & VIEW_OBJECTS_AS_TREE))
1073 {
1074 if (m_dwFlags & FOLLOW_OBJECT_UPDATES)
1075 {
1076 lvfi.flags = LVFI_PARAM;
1077 lvfi.lParam = (LPARAM)pObject;
1078 iItem = m_wndListCtrl.FindItem(&lvfi);
1079 if (iItem != -1) // Shouldn't happen
1080 {
1081 int iOldItem;
1082
1083 ClearListSelection();
1084 iOldItem = m_wndListCtrl.GetNextItem(-1, LVNI_FOCUSED);
1085 if (iOldItem != -1)
1086 m_wndListCtrl.SetItemState(iOldItem, 0, LVIS_FOCUSED);
1087 m_wndListCtrl.EnsureVisible(iItem, FALSE);
1088 m_wndListCtrl.SetItemState(iItem, LVIS_SELECTED | LVIS_FOCUSED,
1089 LVIS_SELECTED | LVIS_FOCUSED);
1090 }
1091 }
1092 else
1093 {
1094 int iCurrItem;
1095
1096 lvfi.flags = LVFI_PARAM;
1097 lvfi.lParam = (LPARAM)pObject;
1098 iItem = m_wndListCtrl.FindItem(&lvfi);
1099
1100 // Check if current item has been changed
1101 iCurrItem = m_wndListCtrl.GetNextItem(-1, LVNI_FOCUSED);
1102 if (iItem == iCurrItem)
1103 {
1104 m_wndPreviewPane.Refresh();
1105 m_wndListCtrl.EnsureVisible(iItem, FALSE);
1106 }
1107 }
1108 }
1109 }
1110 }
1111
1112
1113 //
1114 // Replace specific list control item with new object's data
1115 //
1116
1117 void CObjectBrowser::UpdateObjectListEntry(int iItem, NXC_OBJECT *pObject)
1118 {
1119 char szBuffer[64];
1120 int iPos;
1121
1122 m_wndListCtrl.SetItemState(iItem, INDEXTOOVERLAYMASK(pObject->iStatus), LVIS_OVERLAYMASK);
1123
1124 m_wndListCtrl.SetItemText(iItem, 1, pObject->szName);
1125 m_wndListCtrl.SetItemText(iItem, 2, g_szObjectClass[pObject->iClass]);
1126 m_wndListCtrl.SetItemText(iItem, 3, g_szStatusTextSmall[pObject->iStatus]);
1127 m_wndListCtrl.SetItemText(iItem, 4, IpToStr(pObject->dwIpAddr, szBuffer));
1128
1129 // Class-specific fields
1130 switch(pObject->iClass)
1131 {
1132 case OBJECT_SUBNET:
1133 m_wndListCtrl.SetItemText(iItem, 5, IpToStr(pObject->subnet.dwIpNetMask, szBuffer));
1134 break;
1135 case OBJECT_INTERFACE:
1136 m_wndListCtrl.SetItemText(iItem, 5, IpToStr(pObject->iface.dwIpNetMask, szBuffer));
1137 sprintf(szBuffer, "%d", pObject->iface.dwIfIndex);
1138 m_wndListCtrl.SetItemText(iItem, 6, szBuffer);
1139 m_wndListCtrl.SetItemText(iItem, 7, pObject->iface.dwIfType > MAX_INTERFACE_TYPE ?
1140 "Unknown" : g_szInterfaceTypes[pObject->iface.dwIfType]);
1141 break;
1142 case OBJECT_NODE:
1143 // Create node capabilities string
1144 iPos = 0;
1145 if (pObject->node.dwFlags & NF_IS_NATIVE_AGENT)
1146 szBuffer[iPos++] = 'A';
1147 if (pObject->node.dwFlags & NF_IS_SNMP)
1148 szBuffer[iPos++] = 'S';
1149 if (pObject->node.dwFlags & NF_IS_LOCAL_MGMT)
1150 szBuffer[iPos++] = 'M';
1151 szBuffer[iPos] = 0;
1152 m_wndListCtrl.SetItemText(iItem, 8, szBuffer);
1153 m_wndListCtrl.SetItemText(iItem, 9, pObject->node.szObjectId);
1154 break;
1155 default:
1156 break;
1157 }
1158 }
1159
1160
1161 //
1162 // Change "selection follow changes" mode
1163 //
1164
1165 void CObjectBrowser::OnObjectViewSelection()
1166 {
1167 if (m_dwFlags & FOLLOW_OBJECT_UPDATES)
1168 m_dwFlags &= ~FOLLOW_OBJECT_UPDATES;
1169 else
1170 m_dwFlags |= FOLLOW_OBJECT_UPDATES;
1171 }
1172
1173
1174 //
1175 // ON_COMMAND_UPDATE_UI handlers
1176 //
1177
1178 void CObjectBrowser::OnUpdateObjectViewViewaslist(CCmdUI* pCmdUI)
1179 {
1180 pCmdUI->SetRadio(!(m_dwFlags & VIEW_OBJECTS_AS_TREE));
1181 }
1182
1183 void CObjectBrowser::OnUpdateObjectViewViewastree(CCmdUI* pCmdUI)
1184 {
1185 pCmdUI->SetRadio(m_dwFlags & VIEW_OBJECTS_AS_TREE);
1186 }
1187
1188 void CObjectBrowser::OnUpdateObjectViewSelection(CCmdUI* pCmdUI)
1189 {
1190 pCmdUI->SetCheck(m_dwFlags & FOLLOW_OBJECT_UPDATES);
1191 }
1192
1193 void CObjectBrowser::OnUpdateObjectViewShowpreviewpane(CCmdUI* pCmdUI)
1194 {
1195 pCmdUI->SetCheck(m_dwFlags & SHOW_OBJECT_PREVIEW);
1196 }
1197
1198 void CObjectBrowser::OnUpdateObjectProperties(CCmdUI* pCmdUI)
1199 {
1200 if (m_dwFlags & VIEW_OBJECTS_AS_TREE)
1201 pCmdUI->Enable(m_pCurrentObject != NULL);
1202 else
1203 pCmdUI->Enable((m_pCurrentObject != NULL) &&
1204 (m_wndListCtrl.GetSelectedCount() == 1));
1205 }
1206
1207 void CObjectBrowser::OnUpdateObjectDatacollection(CCmdUI* pCmdUI)
1208 {
1209 pCmdUI->Enable(CurrObjectIsNode(TRUE));
1210 }
1211
1212 void CObjectBrowser::OnUpdateObjectWakeup(CCmdUI* pCmdUI)
1213 {
1214 pCmdUI->Enable(CurrObjectIsNode(FALSE) || CurrObjectIsInterface());
1215 }
1216
1217 void CObjectBrowser::OnUpdateObjectUnmanage(CCmdUI* pCmdUI)
1218 {
1219 pCmdUI->Enable(m_pCurrentObject != NULL);
1220 }
1221
1222 void CObjectBrowser::OnUpdateObjectManage(CCmdUI* pCmdUI)
1223 {
1224 pCmdUI->Enable(m_pCurrentObject != NULL);
1225 }
1226
1227 void CObjectBrowser::OnUpdateObjectDelete(CCmdUI* pCmdUI)
1228 {
1229 pCmdUI->Enable(m_pCurrentObject != NULL);
1230 }
1231
1232 void CObjectBrowser::OnUpdateObjectBind(CCmdUI* pCmdUI)
1233 {
1234 if (m_pCurrentObject == NULL)
1235 {
1236 pCmdUI->Enable(FALSE);
1237 }
1238 else
1239 {
1240 if (m_dwFlags & VIEW_OBJECTS_AS_TREE)
1241 pCmdUI->Enable((m_pCurrentObject->iClass == OBJECT_CONTAINER) ||
1242 (m_pCurrentObject->iClass == OBJECT_SERVICEROOT));
1243 else
1244 pCmdUI->Enable(((m_pCurrentObject->iClass == OBJECT_CONTAINER) ||
1245 (m_pCurrentObject->iClass == OBJECT_SERVICEROOT)) &&
1246 (m_wndListCtrl.GetSelectedCount() == 1));
1247 }
1248 }
1249
1250 void CObjectBrowser::OnUpdateObjectPollStatus(CCmdUI* pCmdUI)
1251 {
1252 pCmdUI->Enable(CurrObjectIsNode());
1253 }
1254
1255 void CObjectBrowser::OnUpdateObjectPollConfiguration(CCmdUI* pCmdUI)
1256 {
1257 pCmdUI->Enable(CurrObjectIsNode());
1258 }
1259
1260
1261 //
1262 // Handler for WM_NOTIFY::NM_DBLCLK from IDC_LIST_VIEW
1263 //
1264
1265 void CObjectBrowser::OnListViewDblClk(LPNMITEMACTIVATE pNMHDR, LRESULT *pResult)
1266 {
1267 PostMessage(WM_COMMAND, ID_OBJECT_PROPERTIES, 0);
1268 }
1269
1270
1271 //
1272 // WM_COMMAND::ID_OBJECT_DATACOLLECTION message handler
1273 //
1274
1275 void CObjectBrowser::OnObjectDatacollection()
1276 {
1277 if (m_pCurrentObject != NULL)
1278 theApp.StartObjectDCEditor(m_pCurrentObject);
1279 }
1280
1281
1282 //
1283 // WM_COMMAND::ID_OBJECT_MANAGE message handler
1284 //
1285
1286 void CObjectBrowser::OnObjectManage()
1287 {
1288 ChangeMgmtStatus(TRUE);
1289 }
1290
1291
1292 //
1293 // WM_COMMAND::ID_OBJECT_UNMANAGE message handler
1294 //
1295
1296 void CObjectBrowser::OnObjectUnmanage()
1297 {
1298 ChangeMgmtStatus(FALSE);
1299 }
1300
1301
1302 //
1303 // Change management status for currently selected object(s)
1304 //
1305
1306 void CObjectBrowser::ChangeMgmtStatus(BOOL bIsManaged)
1307 {
1308 if (m_dwFlags & VIEW_OBJECTS_AS_TREE)
1309 {
1310 if (m_pCurrentObject != NULL)
1311 theApp.SetObjectMgmtStatus(m_pCurrentObject, bIsManaged);
1312 }
1313 else
1314 {
1315 int iItem;
1316 NXC_OBJECT *pObject;
1317
1318 iItem = m_wndListCtrl.GetNextItem(-1, LVNI_SELECTED);
1319 while(iItem != -1)
1320 {
1321 pObject = (NXC_OBJECT *)m_wndListCtrl.GetItemData(iItem);
1322 theApp.SetObjectMgmtStatus(pObject, bIsManaged);
1323 iItem = m_wndListCtrl.GetNextItem(iItem, LVNI_SELECTED);
1324 }
1325 }
1326 }
1327
1328
1329 //
1330 // WM_COMMAND::ID_OBJECT_BIND message handler
1331 //
1332
1333 void CObjectBrowser::OnObjectBind()
1334 {
1335 CObjectSelDlg dlg;
1336 DWORD i, dwResult;
1337
1338 dlg.m_dwAllowedClasses = SCL_NODE | SCL_CONTAINER | SCL_SUBNET;
1339 if (dlg.DoModal() == IDOK)
1340 {
1341 for(i = 0; i < dlg.m_dwNumObjects; i++)
1342 {
1343 dwResult = DoRequestArg2(NXCBindObject, (void *)m_pCurrentObject->dwId,
1344 (void *)dlg.m_pdwObjectList[i], "Binding objects...");
1345 if (dwResult != RCC_SUCCESS)
1346 {
1347 theApp.ErrorBox(dwResult, "Cannot bind object: %s");
1348 break;
1349 }
1350 }
1351 }
1352 }
1353
1354
1355 //
1356 // WM_COMMAND::ID_OBJECT_CREATE_CONTAINER message handler
1357 //
1358
1359 void CObjectBrowser::OnObjectCreateContainer()
1360 {
1361 theApp.CreateContainer((m_pCurrentObject != NULL) ? m_pCurrentObject->dwId : 0);
1362 }
1363
1364
1365 //
1366 // WM_COMMAND::ID_OBJECT_CREATE_NODE message handler
1367 //
1368
1369 void CObjectBrowser::OnObjectCreateNode()
1370 {
1371 theApp.CreateNode((m_pCurrentObject != NULL) ? m_pCurrentObject->dwId : 0);
1372 }
1373
1374
1375 //
1376 // WM_COMMAND::ID_OBJECT_CREATE_TEMPLATE message handler
1377 //
1378
1379 void CObjectBrowser::OnObjectCreateTemplate()
1380 {
1381 theApp.CreateTemplate((m_pCurrentObject != NULL) ? m_pCurrentObject->dwId : 0);
1382 }
1383
1384
1385 //
1386 // WM_COMMAND::ID_OBJECT_CREATE_TEMPLATEGROUP message handler
1387 //
1388
1389 void CObjectBrowser::OnObjectCreateTemplategroup()
1390 {
1391 theApp.CreateTemplateGroup((m_pCurrentObject != NULL) ? m_pCurrentObject->dwId : 0);
1392 }
1393
1394
1395 //
1396 // WM_COMMAND::ID_OBJECT_DELETE message handler
1397 //
1398
1399 void CObjectBrowser::OnObjectDelete()
1400 {
1401 if (m_dwFlags & VIEW_OBJECTS_AS_TREE)
1402 {
1403 if (m_pCurrentObject != NULL)
1404 theApp.DeleteNetXMSObject(m_pCurrentObject);
1405 }
1406 else
1407 {
1408 int iItem;
1409 NXC_OBJECT *pObject;
1410
1411 iItem = m_wndListCtrl.GetNextItem(-1, LVNI_SELECTED);
1412 while(iItem != -1)
1413 {
1414 pObject = (NXC_OBJECT *)m_wndListCtrl.GetItemData(iItem);
1415 theApp.DeleteNetXMSObject(pObject);
1416 iItem = m_wndListCtrl.GetNextItem(iItem, LVNI_SELECTED);
1417 }
1418 }
1419 }
1420
1421
1422 //
1423 // WM_COMMAND::ID_OBJECT_POLL_STATUS message handler
1424 //
1425
1426 void CObjectBrowser::OnObjectPollStatus()
1427 {
1428 if (m_dwFlags & VIEW_OBJECTS_AS_TREE)
1429 {
1430 if (m_pCurrentObject != NULL)
1431 theApp.PollNode(m_pCurrentObject->dwId, POLL_STATUS);
1432 }
1433 else
1434 {
1435 int iItem;
1436 NXC_OBJECT *pObject;
1437
1438 iItem = m_wndListCtrl.GetNextItem(-1, LVNI_SELECTED);
1439 while(iItem != -1)
1440 {
1441 pObject = (NXC_OBJECT *)m_wndListCtrl.GetItemData(iItem);
1442 theApp.PollNode(pObject->dwId, POLL_STATUS);
1443 iItem = m_wndListCtrl.GetNextItem(iItem, LVNI_SELECTED);
1444 }
1445 }
1446 }
1447
1448
1449 //
1450 // WM_COMMAND::ID_OBJECT_POLL_CONFIGURATION message handler
1451 //
1452
1453 void CObjectBrowser::OnObjectPollConfiguration()
1454 {
1455 if (m_dwFlags & VIEW_OBJECTS_AS_TREE)
1456 {
1457 if (m_pCurrentObject != NULL)
1458 theApp.PollNode(m_pCurrentObject->dwId, POLL_CONFIGURATION);
1459 }
1460 else
1461 {
1462 int iItem;
1463 NXC_OBJECT *pObject;
1464
1465 iItem = m_wndListCtrl.GetNextItem(-1, LVNI_SELECTED);
1466 while(iItem != -1)
1467 {
1468 pObject = (NXC_OBJECT *)m_wndListCtrl.GetItemData(iItem);
1469 theApp.PollNode(pObject->dwId, POLL_CONFIGURATION);
1470 iItem = m_wndListCtrl.GetNextItem(iItem, LVNI_SELECTED);
1471 }
1472 }
1473 }
1474
1475
1476 //
1477 // returns TRUE if currently selected object is node
1478 //
1479
1480 BOOL CObjectBrowser::CurrObjectIsNode(BOOL bIncludeTemplates)
1481 {
1482 if (m_pCurrentObject == NULL)
1483 {
1484 return FALSE;
1485 }
1486 else
1487 {
1488 if (m_dwFlags & VIEW_OBJECTS_AS_TREE)
1489 {
1490 return bIncludeTemplates ?
1491 ((m_pCurrentObject->iClass == OBJECT_NODE) ||
1492 (m_pCurrentObject->iClass == OBJECT_TEMPLATE)) :
1493 (m_pCurrentObject->iClass == OBJECT_NODE);
1494 }
1495 else
1496 {
1497 return ((bIncludeTemplates ?
1498 ((m_pCurrentObject->iClass == OBJECT_NODE) ||
1499 (m_pCurrentObject->iClass == OBJECT_TEMPLATE)) :
1500 (m_pCurrentObject->iClass == OBJECT_NODE)) &&
1501 (m_wndListCtrl.GetSelectedCount() == 1));
1502 }
1503 }
1504 }
1505
1506
1507 //
1508 // returns TRUE if currently selected object is interface
1509 //
1510
1511 BOOL CObjectBrowser::CurrObjectIsInterface()
1512 {
1513 if (m_pCurrentObject == NULL)
1514 {
1515 return FALSE;
1516 }
1517 else
1518 {
1519 if (m_dwFlags & VIEW_OBJECTS_AS_TREE)
1520 {
1521 return m_pCurrentObject->iClass == OBJECT_INTERFACE;
1522 }
1523 else
1524 {
1525 return ((m_pCurrentObject->iClass == OBJECT_INTERFACE) &&
1526 (m_wndListCtrl.GetSelectedCount() == 1));
1527 }
1528 }
1529 }
1530
1531
1532 //
1533 // WM_CLOSE message handler
1534 //
1535
1536 void CObjectBrowser::OnClose()
1537 {
1538 WINDOWPLACEMENT wp;
1539
1540 theApp.WriteProfileInt(_T("ObjectBrowser"), _T("Flags"), m_dwFlags);
1541 theApp.WriteProfileInt(_T("ObjectBrowser"), _T("SortMode"), m_dwSortMode);
1542 GetWindowPlacement(&wp);
1543 theApp.WriteProfileBinary(_T("ObjectBrowser"), _T("WindowPlacement"),
1544 (BYTE *)&wp, sizeof(WINDOWPLACEMENT));
1545
1546 CMDIChildWnd::OnClose();
1547 }
1548
1549
1550 //
1551 // Handler for WM_COMMAND::ID_OBJECT_WAKEUP message
1552 //
1553
1554 void CObjectBrowser::OnObjectWakeup()
1555 {
1556 if (m_dwFlags & VIEW_OBJECTS_AS_TREE)
1557 {
1558 if (m_pCurrentObject != NULL)
1559 theApp.WakeUpNode(m_pCurrentObject->dwId);
1560 }
1561 else
1562 {
1563 int iItem;
1564 NXC_OBJECT *pObject;
1565
1566 iItem = m_wndListCtrl.GetNextItem(-1, LVNI_SELECTED);
1567 while(iItem != -1)
1568 {
1569 pObject = (NXC_OBJECT *)m_wndListCtrl.GetItemData(iItem);
1570 theApp.WakeUpNode(pObject->dwId);
1571 iItem = m_wndListCtrl.GetNextItem(iItem, LVNI_SELECTED);
1572 }
1573 }
1574 }
1575
1576
1577 //
1578 // Check if object has default name formed from IP address
1579 //
1580
1581 static BOOL ObjectHasDefaultName(NXC_OBJECT *pObject)
1582 {
1583 if (pObject->iClass == OBJECT_SUBNET)
1584 {
1585 TCHAR szBuffer[64], szIpAddr[32];
1586 _stprintf(szBuffer, _T("%s/%d"), IpToStr(pObject->dwIpAddr, szIpAddr),
1587 BitsInMask(pObject->subnet.dwIpNetMask));
1588 return !_tcscmp(szBuffer, pObject->szName);
1589 }
1590 else
1591 {
1592 return ((pObject->dwIpAddr != 0) &&
1593 (ntohl(inet_addr(pObject->szName)) == pObject->dwIpAddr));
1594 }
1595 }
1596
1597
1598 //
1599 // Get object name suitable for comparision
1600 //
1601
1602 static void GetComparableObjectName(DWORD dwObjectId, TCHAR *pszName)
1603 {
1604 NXC_OBJECT *pObject;
1605
1606 pObject = NXCFindObjectById(dwObjectId);
1607 if (pObject != NULL)
1608 {
1609 // If object has an IP address as name, we sort as numbers
1610 // otherwise in alphabetical order
1611 if (ObjectHasDefaultName(pObject))
1612 {
1613 _sntprintf(pszName, MAX_OBJECT_NAME, _T("\x01%03d%03d%03d%03d"),
1614 pObject->dwIpAddr >> 24, (pObject->dwIpAddr >> 16) & 255,
1615 (pObject->dwIpAddr >> 8) & 255, pObject->dwIpAddr & 255);
1616 }
1617 else
1618 {
1619 _tcscpy(pszName, pObject->szName);
1620 }
1621 }
1622 else
1623 {
1624 *pszName = 0;
1625 }
1626 }
1627
1628
1629 //
1630 // Comparision function for tree items sorting
1631 //
1632
1633 static int CALLBACK CompareTreeItems(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
1634 {
1635 TCHAR szName1[MAX_OBJECT_NAME], szName2[MAX_OBJECT_NAME];
1636
1637 GetComparableObjectName(lParam1, szName1);
1638 GetComparableObjectName(lParam2, szName2);
1639 return _tcsicmp(szName1, szName2);
1640 }
1641
1642
1643 //
1644 // Sort childs of given tree item
1645 //
1646
1647 void CObjectBrowser::SortTreeItems(HTREEITEM hItem)
1648 {
1649 TVSORTCB tvs;
1650
1651 tvs.hParent = hItem;
1652 tvs.lpfnCompare = CompareTreeItems;
1653 m_wndTreeCtrl.SortChildrenCB(&tvs);
1654 }