inspectctrl.cpp 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2012 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #include "stdafx.h"
  14. #include "inspectctrl.hpp"
  15. #include "resource.h"
  16. #include "newvaluedlg.h"
  17. #include "jthread.hpp"
  18. #define MAX_PROPERTY_VALUE_SIZE 256
  19. #define TREE_TOOLTIP_ID 100
  20. #define IDC_EIP_CTRL 1099
  21. enum TreeList_t { TLT_property, TLT_attribute, TLT_root };
  22. const char binaryValue[] = "[BINARY]";
  23. const UINT MSG_COLUMN_SIZED = 7000;
  24. const UINT MSG_EIP_RESIZE = 7001;
  25. bool ShowAttrsOnProps = true;
  26. bool ShowQualifiedNames = false;
  27. IConnection * connection = NULL; // the current connection
  28. const COLORREF color_highlight = GetSysColor(COLOR_HIGHLIGHT);
  29. const COLORREF color_window = GetSysColor(COLOR_WINDOW);
  30. const COLORREF color_windowtext = GetSysColor(COLOR_WINDOWTEXT);
  31. const COLORREF color_inactiveborder = GetSysColor(COLOR_INACTIVEBORDER);
  32. const COLORREF color_highlighttext = GetSysColor(COLOR_HIGHLIGHTTEXT);
  33. const COLORREF color_eip_back = RGB(210, 210, 240);
  34. #define STRCAT(dest, destSz, src) {size32_t l = strlen(src); if(destSz > l) { strcat(dest, src); destSz -= l; } }
  35. enum CTState { CTS_None, CTS_Visible = 0x01, CTS_Expanded = 0x02 };
  36. class CTreeListItem
  37. {
  38. private:
  39. TreeList_t type;
  40. char * name;
  41. IPropertyTree * pTree;
  42. byte state;
  43. public:
  44. CTreeListItem(LPCSTR _name, IPropertyTree * _pTree, TreeList_t _type)
  45. {
  46. state = CTS_None;
  47. type = _type;
  48. pTree =_pTree;
  49. name = type == TLT_attribute ? strdup(_name) : NULL;
  50. }
  51. ~CTreeListItem() { if(name) free(name); }
  52. inline int getDisplayName(IPropertyTree * parent, char * buffer, size32_t buffsz) const
  53. {
  54. *buffer = 0;
  55. size32_t insz = buffsz;
  56. switch(type)
  57. {
  58. case TLT_root:
  59. case TLT_property:
  60. STRCAT(buffer, buffsz, " ");
  61. STRCAT(buffer, buffsz, getName(parent));
  62. if(ShowAttrsOnProps)
  63. {
  64. bool first = true;
  65. IAttributeIterator * attrIterator = pTree->getAttributes();
  66. attrIterator->first();
  67. while(attrIterator->isValid())
  68. {
  69. STRCAT(buffer, buffsz, " ");
  70. if(first)
  71. {
  72. STRCAT(buffer, buffsz, "<");
  73. first = false;
  74. }
  75. STRCAT(buffer, buffsz, attrIterator->queryName() + 1);
  76. STRCAT(buffer, buffsz, "=");
  77. STRCAT(buffer, buffsz, attrIterator->queryValue());
  78. attrIterator->next();
  79. }
  80. attrIterator->Release();
  81. if(!first) STRCAT(buffer, buffsz, ">");
  82. }
  83. break;
  84. case TLT_attribute:
  85. STRCAT(buffer, buffsz, "= ");
  86. STRCAT(buffer, buffsz, getName(NULL));
  87. break;
  88. }
  89. return insz - buffsz;
  90. }
  91. bool setValue(LPCSTR newValue) // returns true if value actually updated
  92. {
  93. ASSERT(!isBinary());
  94. ASSERT(connection != NULL);
  95. if(connection->lockWrite())
  96. {
  97. pTree->setProp(name, newValue);
  98. connection->unlockWrite();
  99. return true;
  100. }
  101. return false;
  102. }
  103. inline bool isBinary() const { return pTree->isBinary(name); }
  104. inline bool isExpanded() const { return 0 != (state & CTS_Expanded); }
  105. inline bool isVisible() const { return 0 != (state & CTS_Visible); }
  106. inline void setExpanded() { state += CTS_Expanded; }
  107. inline void setVisible() { state += CTS_Visible; }
  108. inline IPropertyTree *queryPropertyTree() const { return pTree; }
  109. inline LPCSTR getName(IPropertyTree * parent, bool forceQualified = false) const
  110. {
  111. if(type != TLT_attribute && parent && (ShowQualifiedNames || forceQualified))
  112. {
  113. static StringBuffer buf;
  114. buf.clear().append(type == TLT_attribute ? name + 1 : pTree->queryName());
  115. buf.append("[");
  116. buf.append(parent->queryChildIndex(pTree) + 1);
  117. buf.append("]");
  118. return buf.str();
  119. }
  120. return type == TLT_attribute ? name + 1 : pTree->queryName();
  121. }
  122. inline LPCSTR getValue() const
  123. {
  124. static StringBuffer buf;
  125. if(isBinary())
  126. buf.clear().append(binaryValue);
  127. else
  128. pTree->getProp(name, buf.clear());
  129. return buf.str();
  130. }
  131. inline TreeList_t getType() const { return type; }
  132. };
  133. CTreeListItem * createTreeListProperty(LPCSTR PropName, IPropertyTree & pTree)
  134. {
  135. return new CTreeListItem(PropName, &pTree, TLT_property);
  136. }
  137. CTreeListItem * createTreeListAttribute(LPCSTR AttrName, IPropertyTree & pTree)
  138. {
  139. return new CTreeListItem(AttrName, &pTree, TLT_attribute);
  140. }
  141. CTreeListItem * createTreeListRoot(LPCSTR RootName, IPropertyTree & pTree)
  142. {
  143. return new CTreeListItem(RootName, &pTree, TLT_root);
  144. }
  145. class CFinderThread : public Thread
  146. {
  147. private:
  148. CInspectorTreeCtrl & tree;
  149. LPSTR findWhat;
  150. BOOL matchCase;
  151. BOOL wholeWord;
  152. Semaphore hold;
  153. bool terminate;
  154. HTREEITEM matchedItem;
  155. bool matches(CTreeListItem * tli)
  156. {
  157. LPCSTR name = tli->getName(NULL), value = tli->getValue();
  158. if(matchCase)
  159. {
  160. if(strstr(name, findWhat)) return true;
  161. if(value && !tli->isBinary() && strstr(value, findWhat)) return true;
  162. }
  163. else
  164. {
  165. static CString what, nbuf;
  166. what = findWhat;
  167. nbuf = name;
  168. what.MakeUpper();
  169. nbuf.MakeUpper();
  170. if(strstr(nbuf, what)) return true;
  171. if(value && !tli->isBinary())
  172. {
  173. static CString vbuf;
  174. vbuf= value;
  175. vbuf.MakeUpper();
  176. if(strstr(vbuf, what)) return true;
  177. }
  178. }
  179. return false;
  180. }
  181. public:
  182. CFinderThread(CInspectorTreeCtrl &_tree, LPCSTR _findWhat, BOOL _matchCase, BOOL _wholeWord) : tree(_tree)
  183. {
  184. findWhat = strdup(_findWhat);
  185. matchCase = _matchCase;
  186. wholeWord = _wholeWord;
  187. terminate = false;
  188. matchedItem = 0;
  189. }
  190. ~CFinderThread()
  191. {
  192. free(findWhat);
  193. }
  194. void process(HTREEITEM in)
  195. {
  196. if(!terminate)
  197. {
  198. CTreeListItem * tli = tree.GetTreeListItem(in);
  199. if(tli->getType() == TLT_property && !tli->isExpanded()) tree.AddLevel(*tli->queryPropertyTree(), in);
  200. if(matches(tli))
  201. {
  202. tree.EnsureVisible(in);
  203. tree.SelectItem(in);
  204. hold.wait();
  205. if(terminate) return;
  206. }
  207. HTREEITEM i = tree.GetChildItem(in);
  208. while(i)
  209. {
  210. process(i);
  211. if(terminate) break;
  212. i = tree.GetNextItem(i, TVGN_NEXT);
  213. }
  214. }
  215. }
  216. void kill() // called on message thread
  217. {
  218. terminate = true;
  219. hold.signal();
  220. }
  221. void next()
  222. {
  223. hold.signal();
  224. }
  225. virtual int run()
  226. {
  227. process(tree.GetRootItem());
  228. if(!terminate) MessageBox(NULL, "Search finished, no more matches", "Search Complete", MB_OK | MB_ICONHAND);
  229. return 0;
  230. }
  231. };
  232. inline void getTypeText(TreeList_t type, CString & dest, bool forToolTip)
  233. {
  234. switch(type)
  235. {
  236. case TLT_property: dest = "Property"; break;
  237. case TLT_attribute: dest = "Attribute"; break;
  238. case TLT_root: dest = "Root"; break;
  239. }
  240. if(forToolTip) dest += ": ";
  241. }
  242. // ----- Inspector tree control --------------------------------------------------
  243. BEGIN_MESSAGE_MAP(CInspectorTreeCtrl, CTreeCtrl)
  244. //{{AFX_MSG_MAP(CInspectorTreeCtrl)
  245. ON_WM_PAINT()
  246. ON_WM_SIZE()
  247. ON_WM_CREATE()
  248. ON_WM_LBUTTONDOWN()
  249. ON_WM_LBUTTONDBLCLK()
  250. ON_WM_KEYDOWN()
  251. ON_WM_DESTROY()
  252. ON_WM_LBUTTONUP()
  253. ON_WM_RBUTTONDOWN()
  254. ON_WM_RBUTTONUP()
  255. ON_WM_CLOSE()
  256. ON_WM_VSCROLL()
  257. ON_WM_MOUSEWHEEL()
  258. ON_WM_CTLCOLOR()
  259. ON_NOTIFY_REFLECT(TVN_ITEMEXPANDED, OnItemExpanded)
  260. ON_NOTIFY_REFLECT(TVN_GETDISPINFO, OnGetDispInfo)
  261. ON_COMMAND(IDMP_SETASROOT, OnSetAsRoot)
  262. ON_COMMAND(IDMP_ADDATTRIBUTE, OnAddAttribute)
  263. ON_COMMAND(IDMP_ADDPROPERTY, OnAddProperty)
  264. ON_COMMAND(IDMP_DELETE, OnDelete)
  265. ON_WM_HSCROLL()
  266. //}}AFX_MSG_MAP
  267. END_MESSAGE_MAP()
  268. CInspectorTreeCtrl::CInspectorTreeCtrl()
  269. {
  270. linePen.CreatePen(PS_SOLID, 0, color_inactiveborder);
  271. whitespaceHighlightBrush_Focused.CreateSolidBrush(color_highlight);
  272. whitespaceHighlightBrush_Unfocused.CreateSolidBrush(color_inactiveborder);
  273. EIPBrush.CreateSolidBrush(color_eip_back);
  274. popupMenus.LoadMenu(IDR_POPUPMENUS);
  275. EIPActive = false;
  276. connection = NULL;
  277. finder = NULL;
  278. }
  279. CInspectorTreeCtrl::~CInspectorTreeCtrl()
  280. {
  281. if(finder) delete finder;
  282. }
  283. void CInspectorTreeCtrl::killDataItems(HTREEITEM in)
  284. {
  285. if(in)
  286. {
  287. HTREEITEM i = GetChildItem(in);
  288. while(i)
  289. {
  290. killDataItems(i);
  291. i = GetNextItem(i, TVGN_NEXT);
  292. }
  293. CTreeListItem * tli = GetTreeListItem(in);
  294. SetItemData(in, 0);
  295. delete tli;
  296. }
  297. }
  298. LRESULT CInspectorTreeCtrl::WindowProc(UINT Msg, WPARAM wParam, LPARAM lParam)
  299. {
  300. switch(Msg)
  301. {
  302. case MSG_EIP_RESIZE:
  303. HTREEITEM hitItem = GetSelectedItem();
  304. CRect rect;
  305. GetItemRect(hitItem, &rect, FALSE);
  306. rect.left = getColumnWidth(0);
  307. rect.right = rect.left + getColumnWidth(1);
  308. if(rect.Width() > 0)
  309. editCtrl.Resize(rect);
  310. else
  311. DeactivateEIP();
  312. return 0;
  313. }
  314. return CTreeCtrl::WindowProc(Msg, wParam, lParam);
  315. }
  316. void CInspectorTreeCtrl::DeleteCurrentItem(bool confirm)
  317. {
  318. HTREEITEM hItem = GetSelectedItem();
  319. if (hItem)
  320. {
  321. if(connection->lockWrite())
  322. {
  323. IPropertyTree * pTree = NULL;
  324. CString name;
  325. CTreeListItem * tli = GetTreeListItem(hItem);
  326. if(tli->getType() == TLT_property)
  327. {
  328. if (!confirm || MessageBox("Delete property, are you sure?", "Delete Confirmation", MB_ICONQUESTION | MB_YESNO) == IDYES)
  329. {
  330. CTreeListItem * parentTli = GetTreeListItem(GetParentItem(hItem));
  331. pTree = parentTli->queryPropertyTree();
  332. name = tli->getName(pTree, true);
  333. }
  334. }
  335. else
  336. {
  337. if (!confirm || MessageBox("Delete attribute, are you sure?", "Delete Confirmation", MB_ICONQUESTION | MB_YESNO) == IDYES)
  338. {
  339. pTree = tli->queryPropertyTree();
  340. name = "@";
  341. name += tli->getName(NULL);
  342. }
  343. }
  344. if(pTree)
  345. {
  346. if(pTree->removeProp(name))
  347. {
  348. killDataItems(hItem);
  349. DeleteItem(hItem);
  350. }
  351. else
  352. {
  353. MessageBox("Failed to remove property or attribute, removeProp()\nfailed", "Failed to Remove", MB_OK | MB_ICONEXCLAMATION);
  354. }
  355. }
  356. connection->unlockWrite();
  357. }
  358. else
  359. MessageBox("Unable to lock connection for write", "Cannot Obtain Lock", MB_OK);
  360. }
  361. }
  362. BOOL CInspectorTreeCtrl::DeleteAllItems()
  363. {
  364. DeactivateEIP();
  365. killDataItems(GetRootItem());
  366. CTreeCtrl::DeleteAllItems();
  367. return TRUE;
  368. }
  369. CTreeListItem * CInspectorTreeCtrl::GetTreeListItem(HTREEITEM in)
  370. {
  371. return in ? reinterpret_cast <CTreeListItem *> (GetItemData(in)) : NULL;
  372. }
  373. void CInspectorTreeCtrl::xpath(HTREEITEM item, CString & dest)
  374. {
  375. HTREEITEM parent = GetParentItem(item);
  376. if(parent) xpath(parent, dest); // recursion
  377. CTreeListItem * i = GetTreeListItem(item);
  378. if(i->getType() != TLT_root)
  379. {
  380. if(parent && GetTreeListItem(parent)->getType() != TLT_root) dest += "/";
  381. IPropertyTree * ppTree = GetTreeListItem(parent)->queryPropertyTree();
  382. if(i->getType() == TLT_attribute) dest += "@";
  383. dest += i->getName(ppTree, true);
  384. }
  385. }
  386. DWORD CInspectorTreeCtrl::getFullXPath(HTREEITEM item, CString & dest)
  387. {
  388. xpath(item, dest);
  389. return dest.GetLength();
  390. }
  391. BOOL CInspectorTreeCtrl::DestroyWindow()
  392. {
  393. DeactivateEIP();
  394. DeleteAllItems();
  395. return CWnd::DestroyWindow();
  396. }
  397. bool CInspectorTreeCtrl::VScrollVisible()
  398. {
  399. int sMin, sMax; // crafty eh?
  400. GetScrollRange(SB_VERT, &sMin, &sMax);
  401. return sMax != 0;
  402. }
  403. int CInspectorTreeCtrl::getColumnWidth(int idx)
  404. {
  405. int r = (reinterpret_cast <CPropertyInspector *> (GetParent()))->getColumnWidth(idx);
  406. if(idx == 1 && VScrollVisible()) r -= GetSystemMetrics(SM_CXVSCROLL);
  407. return r > 0 ? r : 0;
  408. }
  409. void CInspectorTreeCtrl::setColumnWidth(int idx, int wid)
  410. {
  411. (reinterpret_cast <CPropertyInspector *> (GetParent()))->setColumnWidth(idx, wid);
  412. }
  413. #define DRAWLINE(x1, y1, x2, y2) dc.MoveTo(x1, y1); dc.LineTo(x2, y2)
  414. void CInspectorTreeCtrl::drawValues(CPaintDC & dc)
  415. {
  416. CRect rect;
  417. GetWindowRect(rect);
  418. dc.SetViewportOrg(0, 0);
  419. dc.SelectObject(linePen);
  420. dc.SetBkMode(TRANSPARENT);
  421. dc.SelectObject(GetFont());
  422. dc.SetTextColor(color_windowtext);
  423. DRAWLINE(0, 0, rect.right, 0);
  424. int cWid0 = getColumnWidth(0);
  425. int cWid1 = getColumnWidth(1);
  426. int height = 0;
  427. HTREEITEM hItemFocus = GetSelectedItem();
  428. HTREEITEM hItem = GetFirstVisibleItem();
  429. while(hItem && height < rect.Height())
  430. {
  431. CRect iRect;
  432. GetItemRect(hItem, &iRect, FALSE);
  433. DRAWLINE(0, iRect.bottom, rect.right, iRect.bottom);
  434. height += iRect.Height();
  435. CTreeListItem * itemData = GetTreeListItem(hItem);
  436. if(itemData)
  437. {
  438. iRect.left = cWid0 + 6;
  439. iRect.right = cWid0 + cWid1;
  440. if(hItem == hItemFocus)
  441. {
  442. CRect whitespaceRect;
  443. GetItemRect(hItem, &whitespaceRect, TRUE);
  444. if(whitespaceRect.right < cWid0)
  445. {
  446. whitespaceRect.left = whitespaceRect.right;
  447. whitespaceRect.right = cWid0;
  448. CWnd * focusWnd = GetFocus();
  449. if(focusWnd && (focusWnd->m_hWnd == m_hWnd)) // I have focus
  450. dc.FillRect(whitespaceRect, &whitespaceHighlightBrush_Focused);
  451. else
  452. dc.FillRect(whitespaceRect, &whitespaceHighlightBrush_Unfocused);
  453. }
  454. CString xpath;
  455. getTypeText(itemData->getType(), xpath, true);
  456. if(getFullXPath(hItem, xpath))
  457. {
  458. CRect itemRect, r;
  459. GetItemRect(hItem, &itemRect, FALSE);
  460. r.UnionRect(&itemRect, &whitespaceRect);
  461. tooltipCtrl->DelTool(this, TREE_TOOLTIP_ID);
  462. tooltipCtrl->AddTool(this, xpath, r, TREE_TOOLTIP_ID);
  463. }
  464. }
  465. dc.DrawText(itemData->getValue(), &iRect, DT_SINGLELINE | DT_LEFT);
  466. }
  467. hItem = GetNextVisibleItem(hItem);
  468. }
  469. DRAWLINE(cWid0, 0, cWid0, height);
  470. }
  471. void CInspectorTreeCtrl::OnSize(UINT type, int cx, int cy)
  472. {
  473. CWnd::OnSize(type, cx, cy);
  474. if(EIPActive) PostMessage(MSG_EIP_RESIZE);
  475. }
  476. void CInspectorTreeCtrl::OnPaint()
  477. {
  478. CPaintDC dc(this);
  479. CPropertyInspector * parent = static_cast <CPropertyInspector *> (GetParent());
  480. CRect rcClip;
  481. dc.GetClipBox( &rcClip );
  482. rcClip.right = getColumnWidth(0);
  483. CRgn rgn;
  484. rgn.CreateRectRgnIndirect( &rcClip );
  485. dc.SelectClipRgn(&rgn);
  486. CWnd::DefWindowProc(WM_PAINT, reinterpret_cast <WPARAM> (dc.m_hDC), 0); // let CTreeCtrl paint as normal
  487. rgn.DeleteObject();
  488. rcClip.right += parent->getColumnWidth(1);
  489. rgn.CreateRectRgnIndirect( &rcClip );
  490. dc.SelectClipRgn(&rgn);
  491. drawValues(dc);
  492. rgn.DeleteObject();
  493. }
  494. int CInspectorTreeCtrl::OnCreate(LPCREATESTRUCT createStruct)
  495. {
  496. if(CTreeCtrl::OnCreate(createStruct) == -1) return -1;
  497. tooltipCtrl = GetToolTips();
  498. ASSERT(tooltipCtrl != NULL);
  499. if(!editCtrl.Create(WS_CHILD | WS_BORDER | ES_AUTOHSCROLL, CRect(0, 0, 0, 0), this, IDC_EIP_CTRL)) return -1;
  500. return 0;
  501. }
  502. HTREEITEM CInspectorTreeCtrl::selectFromPoint(CPoint & point)
  503. {
  504. HTREEITEM hitItem = HitTest(point);
  505. if(hitItem && hitItem != GetSelectedItem()) SelectItem(hitItem);
  506. return hitItem;
  507. }
  508. void CInspectorTreeCtrl::OnLButtonDown(UINT flags, CPoint point)
  509. {
  510. DeactivateEIP();
  511. HTREEITEM hitItem = HitTest(point);
  512. if(hitItem && hitItem != GetSelectedItem()) selectFromPoint(point);
  513. CTreeCtrl::OnLButtonDown(flags, point);
  514. }
  515. void CInspectorTreeCtrl::DeactivateEIP(BOOL save)
  516. {
  517. if(editCtrl.Deactivate(save)) Invalidate();
  518. }
  519. void CInspectorTreeCtrl::ActivateEIP(HTREEITEM i, CRect & rect)
  520. {
  521. ASSERT(connection != NULL);
  522. DeactivateEIP();
  523. EIPActive = editCtrl.Activate(GetTreeListItem(i), rect);
  524. }
  525. void CInspectorTreeCtrl::OnLButtonUp(UINT flags, CPoint point)
  526. {
  527. DeactivateEIP();
  528. HTREEITEM hitItem = HitTest(point);
  529. if(hitItem && hitItem == GetSelectedItem())
  530. {
  531. CRect rect;
  532. GetItemRect(hitItem, &rect, FALSE);
  533. rect.left = getColumnWidth(0);
  534. rect.right = rect.left + getColumnWidth(1);
  535. if(rect.PtInRect(point)) ActivateEIP(hitItem, rect);
  536. }
  537. CTreeCtrl::OnLButtonUp(flags, point);
  538. }
  539. void CInspectorTreeCtrl::OnRButtonDown(UINT flags, CPoint point)
  540. {
  541. /* NULL */
  542. }
  543. void CInspectorTreeCtrl::OnRButtonUp(UINT flags, CPoint point)
  544. {
  545. HTREEITEM sel = selectFromPoint(point);
  546. if(sel)
  547. {
  548. ClientToScreen(&point);
  549. CMenu * sm = popupMenus.GetSubMenu(0);
  550. switch(GetTreeListItem(sel)->getType())
  551. {
  552. case TLT_root:
  553. sm->EnableMenuItem(IDMP_ADDPROPERTY, MF_ENABLED);
  554. sm->EnableMenuItem(IDMP_ADDATTRIBUTE, MF_ENABLED);
  555. sm->EnableMenuItem(IDMP_DELETE, MF_GRAYED);
  556. sm->EnableMenuItem(IDMP_SETASROOT, MF_GRAYED);
  557. break;
  558. case TLT_property:
  559. sm->EnableMenuItem(IDMP_ADDPROPERTY, MF_ENABLED);
  560. sm->EnableMenuItem(IDMP_ADDATTRIBUTE, MF_ENABLED);
  561. sm->EnableMenuItem(IDMP_DELETE, MF_ENABLED);
  562. sm->EnableMenuItem(IDMP_SETASROOT, MF_ENABLED);
  563. break;
  564. case TLT_attribute:
  565. sm->EnableMenuItem(IDMP_ADDPROPERTY, MF_GRAYED);
  566. sm->EnableMenuItem(IDMP_ADDATTRIBUTE, MF_GRAYED);
  567. sm->EnableMenuItem(IDMP_DELETE, MF_ENABLED);
  568. sm->EnableMenuItem(IDMP_SETASROOT, MF_GRAYED);
  569. break;
  570. default:
  571. ASSERT(FALSE);
  572. }
  573. sm->TrackPopupMenu(TPM_LEFTALIGN | TPM_RIGHTBUTTON, point.x, point.y, this);
  574. }
  575. }
  576. void CInspectorTreeCtrl::OnLButtonDblClk(UINT flags, CPoint point)
  577. {
  578. CTreeCtrl::OnLButtonDblClk(flags, point);
  579. }
  580. void CInspectorTreeCtrl::OnKeyDown(UINT chr, UINT repCnt, UINT flags)
  581. {
  582. CTreeCtrl::OnKeyDown(chr, repCnt, flags);
  583. }
  584. void CInspectorTreeCtrl::OnDestroy()
  585. {
  586. DeactivateEIP(FALSE);
  587. DeleteAllItems();
  588. CTreeCtrl::OnDestroy();
  589. }
  590. void CInspectorTreeCtrl::OnClose()
  591. {
  592. DeactivateEIP();
  593. CTreeCtrl::OnClose();
  594. }
  595. void CInspectorTreeCtrl::OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
  596. {
  597. DeactivateEIP();
  598. CTreeCtrl::OnVScroll(nSBCode, nPos, pScrollBar);
  599. }
  600. BOOL CInspectorTreeCtrl::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
  601. {
  602. DeactivateEIP();
  603. return CTreeCtrl::OnMouseWheel(nFlags, zDelta, pt);
  604. }
  605. void CInspectorTreeCtrl::OnGetDispInfo(NMHDR* pNMHDR, LRESULT* pResult)
  606. {
  607. TV_DISPINFO * pTVDispInfo = reinterpret_cast <TV_DISPINFO *> (pNMHDR);
  608. CTreeListItem * tli = reinterpret_cast <CTreeListItem *> (pTVDispInfo->item.lParam);
  609. if(tli)
  610. {
  611. static char nameBuffer[256];
  612. IPropertyTree * ppTree = tli->getType() == TLT_root ? NULL : GetTreeListItem(GetParentItem(pTVDispInfo->item.hItem))->queryPropertyTree();
  613. int origlen = tli->getDisplayName(ppTree, nameBuffer , sizeof(nameBuffer));
  614. HTREEITEM parent = NULL;
  615. CDC * dc = GetDC();
  616. dc->SetViewportOrg(0, 0);
  617. dc->SelectObject(GetFont());
  618. int fit;
  619. CSize sz;
  620. CRect rect;
  621. if(GetItemRect(pTVDispInfo->item.hItem, &rect, TRUE))
  622. {
  623. rect.right = getColumnWidth(0);
  624. GetTextExtentExPoint(dc->m_hDC, nameBuffer, origlen, rect.Width() - 2, &fit, NULL, &sz);
  625. if(fit < origlen)
  626. {
  627. if(fit > 3)
  628. {
  629. strcpy(&nameBuffer[fit - 3], "...");
  630. pTVDispInfo->item.pszText = nameBuffer;
  631. }
  632. else
  633. {
  634. pTVDispInfo->item.pszText = NULL;
  635. }
  636. }
  637. else
  638. {
  639. pTVDispInfo->item.pszText = nameBuffer;
  640. }
  641. }
  642. else
  643. {
  644. pTVDispInfo->item.pszText = NULL;
  645. }
  646. ReleaseDC(dc);
  647. }
  648. *pResult = 0;
  649. }
  650. HBRUSH CInspectorTreeCtrl::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
  651. {
  652. HBRUSH hbr = CTreeCtrl::OnCtlColor(pDC, pWnd, nCtlColor);
  653. if(pWnd->GetDlgCtrlID() == IDC_EIP_CTRL)
  654. {
  655. if(nCtlColor == CTLCOLOR_EDIT || nCtlColor == CTLCOLOR_MSGBOX)
  656. {
  657. pDC->SetBkColor(color_eip_back);
  658. return EIPBrush;
  659. }
  660. }
  661. return hbr;
  662. }
  663. void CInspectorTreeCtrl::NewTree(LPCSTR rootxpath)
  664. {
  665. ASSERT(connection != NULL);
  666. DeleteAllItems();
  667. IPropertyTree & pTree = *connection->queryRoot(rootxpath);
  668. if(connection->getType() != CT_none)
  669. {
  670. TV_INSERTSTRUCT is;
  671. is.hInsertAfter = TVI_LAST;
  672. is.item.mask = TVIF_TEXT | TVIF_PARAM;
  673. is.item.pszText = LPSTR_TEXTCALLBACK;
  674. is.hParent = TVI_ROOT;
  675. is.item.lParam = reinterpret_cast <DWORD> (createTreeListRoot(pTree.queryName(), pTree));
  676. HTREEITEM r = InsertItem(&is);
  677. AddLevel(pTree, r);
  678. Expand(r, TVE_EXPAND);
  679. }
  680. }
  681. void CInspectorTreeCtrl::dynExpand(HTREEITEM in)
  682. {
  683. CTreeListItem *parent = GetTreeListItem(in);
  684. assertex(parent);
  685. IPropertyTree &pTree = *parent->queryPropertyTree();
  686. if (!parent->isExpanded())
  687. {
  688. HTREEITEM i = GetChildItem(in);
  689. while(i)
  690. {
  691. DeleteItem(i);
  692. i = GetNextItem(i, TVGN_NEXT);
  693. }
  694. CString txt;
  695. TV_INSERTSTRUCT is;
  696. is.hInsertAfter = TVI_LAST;
  697. is.item.mask = TVIF_TEXT | TVIF_PARAM;
  698. is.item.pszText = LPSTR_TEXTCALLBACK;
  699. Owned<IAttributeIterator> attrIterator = pTree.getAttributes();
  700. ForEach(*attrIterator)
  701. {
  702. is.hParent = in;
  703. is.item.lParam = reinterpret_cast <DWORD> (createTreeListAttribute(attrIterator->queryName(), pTree));
  704. HTREEITEM r = InsertItem(&is);
  705. ASSERT(r != NULL);
  706. }
  707. Owned<IPropertyTreeIterator> iterator = pTree.getElements("*", iptiter_sort);
  708. ForEach(*iterator)
  709. {
  710. IPropertyTree & thisTree = iterator->query();
  711. is.hParent = in;
  712. is.item.lParam = reinterpret_cast <DWORD> (createTreeListProperty(thisTree.queryName(), thisTree));
  713. HTREEITEM thisTreeItem = InsertItem(&is);
  714. ASSERT(thisTreeItem != NULL);
  715. }
  716. parent->setExpanded();
  717. }
  718. HTREEITEM i = GetChildItem(in);
  719. while(i)
  720. {
  721. CTreeListItem * ctli = GetTreeListItem(i);
  722. if(ctli->getType() == TLT_property) AddLevel(*ctli->queryPropertyTree(), i);
  723. i = GetNextItem(i, TVGN_NEXT);
  724. }
  725. }
  726. void CInspectorTreeCtrl::OnItemExpanded(NMHDR* pNMHDR, LRESULT* pResult)
  727. {
  728. NM_TREEVIEW * pNMTreeView = reinterpret_cast <NM_TREEVIEW*> (pNMHDR);
  729. dynExpand(pNMTreeView->itemNew.hItem);
  730. *pResult = 0;
  731. }
  732. void CInspectorTreeCtrl::AddLevel(IPropertyTree & pTree, HTREEITEM hParent)
  733. {
  734. CTreeListItem * itm = GetTreeListItem(hParent);
  735. if(!itm->isVisible())
  736. {
  737. CString txt;
  738. TV_INSERTSTRUCT is;
  739. is.hInsertAfter = TVI_LAST;
  740. is.item.mask = TVIF_TEXT | TVIF_PARAM;
  741. is.item.pszText = LPSTR_TEXTCALLBACK;
  742. // place holder for children
  743. if (pTree.hasChildren())
  744. {
  745. is.hParent = hParent;
  746. is.item.lParam = reinterpret_cast <DWORD> (createTreeListAttribute("@[loading...]", pTree));
  747. HTREEITEM thisTreeItem = InsertItem(&is);
  748. ASSERT(thisTreeItem != NULL);
  749. }
  750. itm->setVisible();
  751. }
  752. }
  753. void CInspectorTreeCtrl::BeginFind()
  754. {
  755. }
  756. void CInspectorTreeCtrl::EndFind()
  757. {
  758. if(finder)
  759. {
  760. finder->kill();
  761. finder->join();
  762. delete finder;
  763. finder = NULL;
  764. }
  765. }
  766. void CInspectorTreeCtrl::NextFind(LPCSTR txt, BOOL matchCase, BOOL wholeWord)
  767. {
  768. if(!finder)
  769. {
  770. finder = new CFinderThread(*this, txt, matchCase, wholeWord);
  771. finder->start();
  772. }
  773. else
  774. {
  775. finder->next();
  776. }
  777. }
  778. void CInspectorTreeCtrl::OnSetAsRoot()
  779. {
  780. HTREEITEM hItem = GetSelectedItem();
  781. if(hItem)
  782. {
  783. CString xp;
  784. xpath(hItem, xp);
  785. NewTree(xp);
  786. }
  787. }
  788. bool CInspectorTreeCtrl::GetNewItem(NewValue_t nvt, CString & name, CString & value, HTREEITEM & hParent)
  789. {
  790. hParent = GetSelectedItem();
  791. if(hParent)
  792. {
  793. Invalidate();
  794. CNewValueDlg nvDlg(nvt, name, value, this);
  795. if(nvDlg.DoModal() == IDOK)
  796. {
  797. name = nvDlg.GetName();
  798. value = nvDlg.GetValue();
  799. return true;
  800. }
  801. }
  802. return false;
  803. }
  804. void CInspectorTreeCtrl::OnAddAttribute()
  805. {
  806. CString name, value;
  807. HTREEITEM hParent;
  808. while(GetNewItem(NVT_attribute, name, value, hParent))
  809. {
  810. if(connection->lockWrite())
  811. {
  812. CString attrName;
  813. if(name[0] != '@')
  814. {
  815. attrName = "@";
  816. attrName += name;
  817. }
  818. else
  819. attrName = name;
  820. IPropertyTree * pTree = GetTreeListItem(hParent)->queryPropertyTree();
  821. pTree->addProp(attrName, value);
  822. TV_INSERTSTRUCT is;
  823. is.hInsertAfter = TVI_LAST;
  824. is.item.mask = TVIF_TEXT | TVIF_PARAM;
  825. is.item.pszText = LPSTR_TEXTCALLBACK;
  826. is.hParent = hParent;
  827. is.item.lParam = reinterpret_cast <DWORD> (createTreeListAttribute(attrName, *pTree));
  828. InsertItem(&is);
  829. connection->unlockWrite();
  830. Expand(hParent, TVE_EXPAND);
  831. break;
  832. }
  833. }
  834. }
  835. void CInspectorTreeCtrl::OnAddProperty()
  836. {
  837. HTREEITEM hParent;
  838. CString name, value;
  839. while(GetNewItem(NVT_property, name, value, hParent))
  840. {
  841. if(connection->lockWrite())
  842. {
  843. IPropertyTree * t = createPTree();
  844. t->setProp(NULL, value);
  845. t = GetTreeListItem(hParent)->queryPropertyTree()->addPropTree(name, t);
  846. TV_INSERTSTRUCT is;
  847. is.hInsertAfter = TVI_LAST;
  848. is.item.mask = TVIF_TEXT | TVIF_PARAM;
  849. is.item.pszText = LPSTR_TEXTCALLBACK;
  850. is.hParent = hParent;
  851. is.item.lParam = reinterpret_cast <DWORD> (createTreeListProperty(t->queryName(), * t));
  852. InsertItem(&is);
  853. connection->unlockWrite();
  854. Expand(hParent, TVE_EXPAND);
  855. break;
  856. }
  857. else
  858. MessageBox("Unable to lock connection for write", "Cannot Obtain Lock", MB_OK);
  859. }
  860. }
  861. void CInspectorTreeCtrl::OnDelete()
  862. {
  863. DeleteCurrentItem();
  864. }
  865. void CInspectorTreeCtrl::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
  866. {
  867. /* NULL */
  868. }
  869. // ----- Inspector frame window --------------------------------------------------
  870. BEGIN_MESSAGE_MAP(CPropertyInspector, CWnd)
  871. ON_WM_SIZE()
  872. END_MESSAGE_MAP()
  873. CPropertyInspector::~CPropertyInspector()
  874. {
  875. connection = NULL;
  876. }
  877. LONG FAR PASCAL CPropertyInspector::wndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
  878. {
  879. return ::DefWindowProc(hWnd, msg, wParam, lParam);
  880. }
  881. LRESULT CPropertyInspector::WindowProc(UINT Msg, WPARAM wParam, LPARAM lParam)
  882. {
  883. switch(Msg)
  884. {
  885. case MSG_COLUMN_SIZED:
  886. CRect rect;
  887. GetWindowRect(&rect);
  888. setColumnWidth(1, rect.Width() - getColumnWidth(0) - 2);
  889. inspectorCtrl.Invalidate();
  890. if(inspectorCtrl.EIPActive) inspectorCtrl.PostMessage(MSG_EIP_RESIZE);
  891. return 0;
  892. }
  893. return CWnd::WindowProc(Msg, wParam, lParam);
  894. }
  895. void CPropertyInspector::registerClass()
  896. {
  897. WNDCLASS wc;
  898. memset(&wc, 0, sizeof(wc));
  899. wc.style = CS_DBLCLKS | CS_VREDRAW | CS_HREDRAW | CS_GLOBALCLASS;
  900. wc.lpfnWndProc = (WNDPROC)wndProc;
  901. wc.hInstance = AfxGetInstanceHandle();
  902. wc.hCursor = 0;
  903. wc.lpszClassName = "PROPERTY_INSPECTOR_CTRL";
  904. wc.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH);
  905. if (!::RegisterClass(&wc)) ASSERT(FALSE);
  906. }
  907. BOOL CPropertyInspector::SubclassDlgItem(UINT id, CWnd * parent)
  908. {
  909. return CWnd::SubclassDlgItem(id, parent) ? initialize() : FALSE;
  910. }
  911. CWnd * CPropertyInspector::SetFocus()
  912. {
  913. return inspectorCtrl.SetFocus();
  914. }
  915. int CPropertyInspector::initialize()
  916. {
  917. CRect rect;
  918. GetWindowRect(rect);
  919. if(!staticCtrl.Create(NULL, WS_CHILD | WS_VISIBLE | SS_SUNKEN, CRect(0, 0 ,0 ,0), this)) return FALSE;
  920. staticCtrl.SetWindowPos(&wndBottom, 0, 0, rect.Width(), rect.Height(), SWP_SHOWWINDOW);
  921. if(!headerCtrl.Create(WS_CHILD | WS_VISIBLE | HDS_HORZ, CRect(0, 0, 0, 0), this, IDC_TREE_LIST_HEADER)) return FALSE;
  922. CSize textSize;
  923. headerCtrl.SetFont(GetParent()->GetFont());
  924. CDC * dc = headerCtrl.GetDC();
  925. textSize = dc->GetTextExtent("A");
  926. headerCtrl.ReleaseDC(dc);
  927. headerCtrl.SetWindowPos(NULL, 1, 1, rect.Width() - 2, textSize.cy + 4, SWP_SHOWWINDOW | SWP_NOZORDER);
  928. HD_ITEM hdItem;
  929. hdItem.mask = HDI_FORMAT | HDI_TEXT | HDI_WIDTH;
  930. hdItem.fmt = HDF_LEFT | HDF_STRING;
  931. hdItem.pszText = "Value";
  932. hdItem.cchTextMax = 5;
  933. hdItem.cxy = 140;
  934. headerCtrl.InsertItem(0, &hdItem);
  935. hdItem.pszText = "Property";
  936. hdItem.cchTextMax = 8;
  937. hdItem.cxy = rect.Width() - hdItem.cxy;
  938. headerCtrl.InsertItem(0, &hdItem);
  939. if(!inspectorCtrl.Create(WS_CHILD | WS_VISIBLE | TVS_SHOWSELALWAYS | TVS_HASLINES |TVS_LINESATROOT | TVS_HASBUTTONS |TVS_DISABLEDRAGDROP, CRect(0, 0, 0, 0), this, IDC_TREE_LIST_CTRL)) return FALSE;
  940. inspectorCtrl.SetWindowPos(NULL, 1, textSize.cy + 5, rect.Width(), rect.Height() - (textSize.cy + 6), SWP_SHOWWINDOW | SWP_NOZORDER);
  941. PostMessage(MSG_COLUMN_SIZED);
  942. return TRUE;
  943. }
  944. BOOL CPropertyInspector::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT * result)
  945. {
  946. LPNMHEADER hdn = reinterpret_cast <LPNMHEADER> (lParam);
  947. if(wParam == IDC_TREE_LIST_HEADER)
  948. {
  949. if(hdn->hdr.code == HDN_ENDTRACK) PostMessage(MSG_COLUMN_SIZED);
  950. }
  951. return CWnd::OnNotify(wParam, lParam, result);
  952. }
  953. void CPropertyInspector::OnSize(UINT type, int cx, int cy)
  954. {
  955. CWnd::OnSize(type, cx, cy);
  956. staticCtrl.MoveWindow(0, 0, cx, cy);
  957. CRect headerRect;
  958. headerCtrl.GetWindowRect(&headerRect);
  959. headerCtrl.MoveWindow(1, 1, cx - 2, headerRect.Height());
  960. inspectorCtrl.MoveWindow(1, headerRect.Height() + 1, cx - 2, cy - headerRect.Height() - 2);
  961. setColumnWidth(1, cx - getColumnWidth(0) - 2);
  962. }
  963. void CPropertyInspector::NewTree(IConnection * conn)
  964. {
  965. connection = conn;
  966. if(connection) inspectorCtrl.NewTree();
  967. }
  968. void CPropertyInspector::KillTree()
  969. {
  970. connection = NULL;
  971. inspectorCtrl.DeleteAllItems();
  972. }
  973. UINT CPropertyInspector::GetCount()
  974. {
  975. return inspectorCtrl.GetCount();
  976. }
  977. void CPropertyInspector::NextFind(LPCSTR txt, BOOL MatchCase, BOOL MatchWholeWord)
  978. {
  979. inspectorCtrl.NextFind(txt, MatchCase, MatchWholeWord);
  980. }
  981. void CPropertyInspector::BeginFind()
  982. {
  983. inspectorCtrl.BeginFind();
  984. }
  985. void CPropertyInspector::EndFind()
  986. {
  987. inspectorCtrl.EndFind();
  988. }
  989. int CPropertyInspector::getColumnWidth(int idx)
  990. {
  991. if(idx < 2)
  992. {
  993. static HD_ITEM hdItem;
  994. hdItem.mask = HDI_WIDTH;
  995. if(headerCtrl.GetItem(idx, &hdItem)) return hdItem.cxy;
  996. }
  997. return 0;
  998. }
  999. void CPropertyInspector::setColumnWidth(int idx, int wid)
  1000. {
  1001. if(idx < 2)
  1002. {
  1003. static HD_ITEM hdItem;
  1004. hdItem.mask = HDI_WIDTH;
  1005. hdItem.cxy = wid;
  1006. headerCtrl.SetItem(idx, &hdItem);
  1007. }
  1008. }
  1009. void CPropertyInspector::showAttribs(bool show)
  1010. {
  1011. if(ShowAttrsOnProps != show)
  1012. {
  1013. ShowAttrsOnProps = show;
  1014. inspectorCtrl.Invalidate();
  1015. }
  1016. }
  1017. void CPropertyInspector::showQualified(bool show)
  1018. {
  1019. if(ShowQualifiedNames != show)
  1020. {
  1021. ShowQualifiedNames = show;
  1022. inspectorCtrl.Invalidate();
  1023. }
  1024. }
  1025. /////////////////////////////////////////////////////////////////////////////
  1026. // CEditEIP
  1027. CEditEIP::CEditEIP()
  1028. {
  1029. tli = NULL;
  1030. }
  1031. CEditEIP::~CEditEIP()
  1032. {
  1033. }
  1034. BEGIN_MESSAGE_MAP(CEditEIP, CEdit)
  1035. //{{AFX_MSG_MAP(CEditEIP)
  1036. ON_WM_CREATE()
  1037. ON_WM_KEYUP()
  1038. //}}AFX_MSG_MAP
  1039. END_MESSAGE_MAP()
  1040. /////////////////////////////////////////////////////////////////////////////
  1041. // CEditEIP message handlers
  1042. int CEditEIP::OnCreate(LPCREATESTRUCT lpCreateStruct)
  1043. {
  1044. if(CEdit::OnCreate(lpCreateStruct) == -1) return -1;
  1045. parent = static_cast <CInspectorTreeCtrl *> (GetParent());
  1046. ASSERT(parent != NULL);
  1047. SetFont(parent->GetFont());
  1048. return 0;
  1049. }
  1050. BOOL CEditEIP::Activate(CTreeListItem * i, CRect & rect)
  1051. {
  1052. ASSERT(i != NULL);
  1053. if(!i->isBinary())
  1054. {
  1055. tli = i;
  1056. Resize(rect);
  1057. SetFocusText(tli->getValue());
  1058. GetWindowText(ValuePreserve);
  1059. return TRUE;
  1060. }
  1061. return FALSE;
  1062. }
  1063. BOOL CEditEIP::Deactivate(BOOL save)
  1064. {
  1065. BOOL r = FALSE;
  1066. if(IsActive())
  1067. {
  1068. ASSERT(!tli->isBinary());
  1069. ShowWindow(FALSE);
  1070. CString ecTxt;
  1071. GetWindowText(ecTxt);
  1072. if(connection && save && GetModify())
  1073. {
  1074. if((!tli->getValue() || strcmp(tli->getValue(), ecTxt) != 0))
  1075. {
  1076. if(tli->setValue(ecTxt))
  1077. {
  1078. GetParent()->Invalidate();
  1079. r = TRUE;
  1080. }
  1081. else
  1082. {
  1083. ::MessageBox(NULL, "Unable to gain exclusive lock for write", "Unable to lock", MB_OK);
  1084. }
  1085. }
  1086. }
  1087. tli = NULL;
  1088. }
  1089. return r;
  1090. }
  1091. BOOL CEditEIP::IsActive()
  1092. {
  1093. return tli == NULL ? FALSE : TRUE;
  1094. }
  1095. void CEditEIP::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
  1096. {
  1097. switch(nChar)
  1098. {
  1099. case 0x09: // tab key
  1100. case 0x0d: // enter key - accept value
  1101. Deactivate();
  1102. break;
  1103. case 0x1b: // esc key - get value when editing began
  1104. SetFocusText(ValuePreserve);
  1105. break;
  1106. default:
  1107. CEdit::OnKeyUp(nChar, nRepCnt, nFlags);
  1108. break;
  1109. }
  1110. }
  1111. void CEditEIP::SetFocusText(LPCSTR text)
  1112. {
  1113. SetWindowText(text);
  1114. SetModify(FALSE);
  1115. SetFocus();
  1116. SetSel(0, -1); // NB select all
  1117. }
  1118. BOOL CEditEIP::Resize(CRect & rect)
  1119. {
  1120. return IsActive() ? SetWindowPos(&wndTop, rect.left, rect.top, rect.Width(), rect.Height(), SWP_SHOWWINDOW) : FALSE;
  1121. }