]>
Commit | Line | Data |
---|---|---|
bbf1f0e5 | 1 | /////////////////////////////////////////////////////////////////////////////// |
23f681ec | 2 | // Name: regtest.cpp |
bbf1f0e5 KB |
3 | // Purpose: wxRegKey class demo |
4 | // Author: Vadim Zeitlin | |
23f681ec | 5 | // Modified by: |
bbf1f0e5 | 6 | // Created: 03.04.98 |
bbf1f0e5 | 7 | // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr> |
526954c5 | 8 | // Licence: wxWindows licence |
bbf1f0e5 KB |
9 | /////////////////////////////////////////////////////////////////////////////// |
10 | ||
11 | // ============================================================================ | |
12 | // declarations | |
13 | // ============================================================================ | |
14 | ||
15 | // ---------------------------------------------------------------------------- | |
16 | // headers | |
17 | // ---------------------------------------------------------------------------- | |
18 | #include "wx/wxprec.h" | |
19 | ||
20 | #ifdef __BORLANDC__ | |
721b8397 | 21 | # pragma hdrstop |
bbf1f0e5 KB |
22 | #endif |
23 | ||
24 | #ifndef WX_PRECOMP | |
721b8397 | 25 | # include "wx/wx.h" |
bbf1f0e5 KB |
26 | #endif |
27 | ||
bbf1f0e5 | 28 | #include "wx/treectrl.h" |
721b8397 DS |
29 | #include "wx/config.h" |
30 | #include "wx/imaglist.h" | |
c41ea66a VZ |
31 | #include "wx/tokenzr.h" |
32 | ||
bb5a9514 | 33 | #if wxUSE_CONFIG_NATIVE && defined( __WINDOWS__ ) |
721b8397 DS |
34 | # define DO_REGTEST 1 |
35 | #else | |
36 | # define DO_REGTEST 0 | |
37 | #endif | |
38 | ||
bbf1f0e5 KB |
39 | // ---------------------------------------------------------------------------- |
40 | // application type | |
41 | // ---------------------------------------------------------------------------- | |
42 | class RegApp : public wxApp | |
23f681ec | 43 | { |
bbf1f0e5 | 44 | public: |
721b8397 | 45 | bool OnInit(); |
bbf1f0e5 KB |
46 | }; |
47 | ||
48 | // ---------------------------------------------------------------------------- | |
49 | // image list with registry icons | |
50 | // ---------------------------------------------------------------------------- | |
51 | class RegImageList : public wxImageList | |
52 | { | |
53 | public: | |
721b8397 DS |
54 | enum Icon |
55 | { | |
56 | Root, | |
57 | ClosedKey, | |
58 | OpenedKey, | |
59 | TextValue, | |
60 | BinaryValue | |
61 | }; | |
62 | ||
63 | RegImageList(); | |
bbf1f0e5 KB |
64 | }; |
65 | ||
721b8397 DS |
66 | #if DO_REGTEST |
67 | ||
bbf1f0e5 KB |
68 | // ---------------------------------------------------------------------------- |
69 | // our control | |
70 | // ---------------------------------------------------------------------------- | |
71 | class RegTreeCtrl : public wxTreeCtrl | |
72 | { | |
73 | public: | |
721b8397 DS |
74 | // ctor & dtor |
75 | RegTreeCtrl(wxWindow *parent, wxWindowID id); | |
76 | virtual ~RegTreeCtrl(); | |
bbf1f0e5 | 77 | |
721b8397 DS |
78 | // notifications |
79 | void OnDeleteItem (wxTreeEvent& event); | |
80 | void OnItemExpanding (wxTreeEvent& event); | |
81 | void OnSelChanged (wxTreeEvent& event); | |
bbf1f0e5 | 82 | |
721b8397 DS |
83 | void OnBeginEdit (wxTreeEvent& event); |
84 | void OnEndEdit (wxTreeEvent& event); | |
c41ea66a | 85 | |
721b8397 DS |
86 | void OnBeginDrag (wxTreeEvent& event); |
87 | void OnEndDrag (wxTreeEvent& event); | |
23f681ec | 88 | |
721b8397 DS |
89 | void OnRightClick (wxMouseEvent& event); |
90 | void OnChar (wxKeyEvent& event); | |
91 | void OnIdle (wxIdleEvent& event); | |
bbf1f0e5 | 92 | |
721b8397 DS |
93 | // forwarded notifications (by the frame) |
94 | void OnMenuTest(); | |
bbf1f0e5 | 95 | |
721b8397 DS |
96 | // operations |
97 | void GoTo(const wxString& location); | |
98 | void DoRefresh(); | |
99 | void DeleteSelected(); | |
100 | void ShowProperties(); | |
101 | void CreateNewKey(const wxString& strName); | |
102 | void CreateNewTextValue(const wxString& strName); | |
103 | void CreateNewBinaryValue(const wxString& strName); | |
a5c46848 | 104 | void SetRegistryView(wxRegKey::WOW64ViewMode viewMode); |
bbf1f0e5 | 105 | |
721b8397 DS |
106 | // information |
107 | bool IsKeySelected() const; | |
bbf1f0e5 | 108 | |
bbf1f0e5 | 109 | private: |
721b8397 DS |
110 | // structure describing a registry key/value |
111 | class TreeNode : public wxTreeItemData | |
112 | { | |
113 | WX_DEFINE_ARRAY_PTR(TreeNode *, TreeChildren); | |
114 | public: | |
115 | RegTreeCtrl *m_pTree; // must be !NULL | |
116 | TreeNode *m_pParent; // NULL only for the root node | |
945d96f6 | 117 | wxTreeItemId m_id; // the id of the tree control item |
721b8397 DS |
118 | wxString m_strName; // name of the key/value |
119 | TreeChildren m_aChildren; // array of subkeys/values | |
120 | bool m_bKey; // key or value? | |
121 | wxRegKey *m_pKey; // only may be !NULL if m_bKey == true | |
a5c46848 | 122 | wxRegKey::WOW64ViewMode m_viewMode; // How to view the registry. |
23f681ec | 123 | |
721b8397 | 124 | // trivial accessors |
945d96f6 WS |
125 | wxTreeItemId Id() const { return m_id; } |
126 | bool IsRoot() const { return m_pParent == NULL; } | |
127 | bool IsKey() const { return m_bKey; } | |
128 | TreeNode *Parent() const { return m_pParent; } | |
23f681ec | 129 | |
721b8397 DS |
130 | // notifications |
131 | bool OnExpand(); | |
132 | void OnCollapse(); | |
23f681ec | 133 | |
721b8397 DS |
134 | // operations |
135 | void Refresh(); | |
136 | bool DeleteChild(TreeNode *child); | |
137 | void DestroyChildren(); | |
138 | const wxChar *FullName() const; | |
a5c46848 | 139 | void SetRegistryView(wxRegKey::WOW64ViewMode viewMode); |
23f681ec | 140 | |
721b8397 DS |
141 | // get the associated key: make sure the pointer is !NULL |
142 | wxRegKey& Key() { if ( !m_pKey ) OnExpand(); return *m_pKey; } | |
23f681ec | 143 | |
721b8397 DS |
144 | // dtor deletes all children |
145 | ~TreeNode(); | |
146 | }; | |
bbf1f0e5 | 147 | |
721b8397 DS |
148 | wxImageList *m_imageList; |
149 | wxMenu *m_pMenuPopup; | |
23f681ec | 150 | |
721b8397 | 151 | TreeNode *m_pRoot; |
23f681ec | 152 | |
721b8397 DS |
153 | TreeNode *m_draggedItem; // the item being dragged |
154 | bool m_copyOnDrop; // if false, then move | |
23f681ec | 155 | |
721b8397 | 156 | bool m_restoreStatus; // after OnItemExpanding() |
bbf1f0e5 | 157 | |
721b8397 | 158 | wxString m_nameOld; // the initial value of item being renamed |
c41ea66a | 159 | |
a5c46848 VZ |
160 | wxRegKey::WOW64ViewMode m_viewMode; // Registry view to use for keys. |
161 | ||
721b8397 | 162 | TreeNode *GetNode(const wxTreeEvent& event) |
2e3b8fa7 | 163 | { return (TreeNode *)GetItemData(event.GetItem()); } |
bbf1f0e5 KB |
164 | |
165 | public: | |
721b8397 DS |
166 | // create a new node and insert it to the tree |
167 | TreeNode *InsertNewTreeNode(TreeNode *pParent, | |
168 | const wxString& strName, | |
169 | int idImage = RegImageList::ClosedKey, | |
a5c46848 VZ |
170 | const wxString *pstrValue = NULL, |
171 | wxRegKey::WOW64ViewMode viewMode = wxRegKey::WOW64ViewMode_Default); | |
721b8397 DS |
172 | |
173 | // add standard registry keys | |
174 | void AddStdKeys(); | |
23f681ec VZ |
175 | |
176 | private: | |
721b8397 | 177 | DECLARE_EVENT_TABLE() |
bbf1f0e5 KB |
178 | }; |
179 | ||
721b8397 DS |
180 | #endif // #if DO_REGTEST |
181 | ||
bbf1f0e5 KB |
182 | // ---------------------------------------------------------------------------- |
183 | // the main window of our application | |
184 | // ---------------------------------------------------------------------------- | |
185 | class RegFrame : public wxFrame | |
23f681ec | 186 | { |
bbf1f0e5 | 187 | public: |
721b8397 | 188 | // ctor & dtor |
fbfb8bcc | 189 | RegFrame(wxFrame *parent, const wxChar *title, int x, int y, int w, int h); |
721b8397 | 190 | virtual ~RegFrame(); |
23f681ec | 191 | |
721b8397 DS |
192 | // callbacks |
193 | void OnQuit (wxCommandEvent& event); | |
194 | void OnAbout(wxCommandEvent& event); | |
195 | void OnTest (wxCommandEvent& event); | |
bbf1f0e5 | 196 | |
721b8397 | 197 | void OnGoTo (wxCommandEvent& event); |
c41ea66a | 198 | |
721b8397 DS |
199 | void OnExpand (wxCommandEvent& event); |
200 | void OnCollapse(wxCommandEvent& event); | |
201 | void OnToggle (wxCommandEvent& event); | |
202 | void OnRefresh (wxCommandEvent& event); | |
bbf1f0e5 | 203 | |
721b8397 DS |
204 | void OnDelete (wxCommandEvent& event); |
205 | void OnNewKey (wxCommandEvent& event); | |
206 | void OnNewText (wxCommandEvent& event); | |
207 | void OnNewBinary(wxCommandEvent& event); | |
bbf1f0e5 | 208 | |
721b8397 | 209 | void OnInfo (wxCommandEvent& event); |
bbf1f0e5 | 210 | |
a5c46848 VZ |
211 | void OnViewChange (wxCommandEvent& event); |
212 | ||
721b8397 | 213 | DECLARE_EVENT_TABLE() |
bbf1f0e5 KB |
214 | |
215 | private: | |
721b8397 DS |
216 | |
217 | #if DO_REGTEST | |
218 | RegTreeCtrl *m_treeCtrl; | |
219 | #endif | |
bbf1f0e5 KB |
220 | }; |
221 | ||
222 | // ---------------------------------------------------------------------------- | |
223 | // various ids | |
224 | // ---------------------------------------------------------------------------- | |
225 | ||
226 | enum | |
227 | { | |
721b8397 DS |
228 | Menu_Quit = 100, |
229 | Menu_About, | |
230 | Menu_Test, | |
231 | Menu_GoTo, | |
232 | Menu_Expand, | |
233 | Menu_Collapse, | |
234 | Menu_Toggle, | |
235 | Menu_Refresh, | |
236 | Menu_New, | |
237 | Menu_NewKey, | |
238 | Menu_NewText, | |
239 | Menu_NewBinary, | |
240 | Menu_Delete, | |
241 | Menu_Info, | |
a5c46848 VZ |
242 | Menu_View, |
243 | Menu_ViewDefault, | |
244 | Menu_View32, | |
245 | Menu_View64, | |
721b8397 | 246 | |
004f4002 | 247 | Ctrl_RegTree = 200 |
bbf1f0e5 KB |
248 | }; |
249 | ||
250 | // ---------------------------------------------------------------------------- | |
251 | // event tables | |
252 | // ---------------------------------------------------------------------------- | |
253 | ||
254 | BEGIN_EVENT_TABLE(RegFrame, wxFrame) | |
a5c46848 VZ |
255 | EVT_MENU(Menu_Test, RegFrame::OnTest) |
256 | EVT_MENU(Menu_About, RegFrame::OnAbout) | |
257 | EVT_MENU(Menu_Quit, RegFrame::OnQuit) | |
258 | EVT_MENU(Menu_GoTo, RegFrame::OnGoTo) | |
259 | EVT_MENU(Menu_Expand, RegFrame::OnExpand) | |
260 | EVT_MENU(Menu_Collapse, RegFrame::OnCollapse) | |
261 | EVT_MENU(Menu_Toggle, RegFrame::OnToggle) | |
262 | EVT_MENU(Menu_Refresh, RegFrame::OnRefresh) | |
263 | EVT_MENU(Menu_Delete, RegFrame::OnDelete) | |
264 | EVT_MENU(Menu_NewKey, RegFrame::OnNewKey) | |
265 | EVT_MENU(Menu_NewText, RegFrame::OnNewText) | |
266 | EVT_MENU(Menu_NewBinary, RegFrame::OnNewBinary) | |
267 | EVT_MENU(Menu_Info, RegFrame::OnInfo) | |
268 | EVT_MENU(Menu_ViewDefault, RegFrame::OnViewChange) | |
269 | EVT_MENU(Menu_View32, RegFrame::OnViewChange) | |
270 | EVT_MENU(Menu_View64, RegFrame::OnViewChange) | |
bbf1f0e5 KB |
271 | END_EVENT_TABLE() |
272 | ||
721b8397 DS |
273 | #if DO_REGTEST |
274 | ||
bbf1f0e5 | 275 | BEGIN_EVENT_TABLE(RegTreeCtrl, wxTreeCtrl) |
676e9e35 VZ |
276 | EVT_TREE_DELETE_ITEM (Ctrl_RegTree, RegTreeCtrl::OnDeleteItem) |
277 | EVT_TREE_ITEM_EXPANDING (Ctrl_RegTree, RegTreeCtrl::OnItemExpanding) | |
278 | EVT_TREE_ITEM_COLLAPSING(Ctrl_RegTree, RegTreeCtrl::OnItemExpanding) | |
279 | EVT_TREE_SEL_CHANGED (Ctrl_RegTree, RegTreeCtrl::OnSelChanged) | |
c41ea66a | 280 | |
721b8397 DS |
281 | EVT_TREE_BEGIN_LABEL_EDIT(Ctrl_RegTree, RegTreeCtrl::OnBeginEdit) |
282 | EVT_TREE_END_LABEL_EDIT (Ctrl_RegTree, RegTreeCtrl::OnEndEdit) | |
c41ea66a | 283 | |
721b8397 DS |
284 | EVT_TREE_BEGIN_DRAG (Ctrl_RegTree, RegTreeCtrl::OnBeginDrag) |
285 | EVT_TREE_BEGIN_RDRAG (Ctrl_RegTree, RegTreeCtrl::OnBeginDrag) | |
286 | EVT_TREE_END_DRAG (Ctrl_RegTree, RegTreeCtrl::OnEndDrag) | |
bbf1f0e5 | 287 | |
721b8397 DS |
288 | EVT_CHAR (RegTreeCtrl::OnChar) |
289 | EVT_RIGHT_DOWN(RegTreeCtrl::OnRightClick) | |
290 | EVT_IDLE (RegTreeCtrl::OnIdle) | |
bbf1f0e5 KB |
291 | END_EVENT_TABLE() |
292 | ||
721b8397 DS |
293 | #endif |
294 | ||
bbf1f0e5 KB |
295 | // ============================================================================ |
296 | // implementation | |
297 | // ============================================================================ | |
298 | ||
299 | // ---------------------------------------------------------------------------- | |
300 | // global functions | |
301 | // ---------------------------------------------------------------------------- | |
302 | ||
303 | // create the "registry operations" menu | |
304 | wxMenu *CreateRegistryMenu() | |
305 | { | |
721b8397 | 306 | wxMenu *pMenuNew = new wxMenu; |
9a83f860 | 307 | pMenuNew->Append(Menu_NewKey, wxT("&Key"), wxT("Create a new key")); |
721b8397 | 308 | pMenuNew->AppendSeparator(); |
9a83f860 VZ |
309 | pMenuNew->Append(Menu_NewText, wxT("&Text value"), wxT("Create a new text value")); |
310 | pMenuNew->Append(Menu_NewBinary, wxT("&Binary value"), wxT("Create a new binary value")); | |
721b8397 | 311 | |
a5c46848 VZ |
312 | wxMenu *pMenuView = new wxMenu; |
313 | pMenuView->AppendRadioItem( | |
314 | Menu_ViewDefault, | |
315 | wxT("&Default"), | |
316 | wxT("Default registry view for the program environment.")); | |
317 | pMenuView->AppendRadioItem( | |
318 | Menu_View32, | |
319 | wxT("32-bit Registry"), | |
320 | wxT("View 32-bit registry.")); | |
321 | pMenuView->AppendRadioItem( | |
322 | Menu_View64, | |
323 | wxT("64-bit Registry"), | |
324 | wxT("View 64-bit registry.")); | |
325 | ||
721b8397 | 326 | wxMenu *pMenuReg = new wxMenu; |
9a83f860 VZ |
327 | pMenuReg->Append(Menu_New, wxT("&New"), pMenuNew); |
328 | pMenuReg->Append(Menu_Delete, wxT("&Delete..."), wxT("Delete selected key/value")); | |
721b8397 | 329 | pMenuReg->AppendSeparator(); |
9a83f860 VZ |
330 | pMenuReg->Append(Menu_GoTo, wxT("&Go to...\tCtrl-G"), wxT("Go to registry key")); |
331 | pMenuReg->Append(Menu_Expand, wxT("&Expand"), wxT("Expand current key")); | |
332 | pMenuReg->Append(Menu_Collapse, wxT("&Collapse"), wxT("Collapse current key")); | |
333 | pMenuReg->Append(Menu_Toggle, wxT("&Toggle"), wxT("Toggle current key")); | |
721b8397 | 334 | pMenuReg->AppendSeparator(); |
9a83f860 | 335 | pMenuReg->Append(Menu_Refresh, wxT("&Refresh"), wxT("Refresh the subtree")); |
a5c46848 | 336 | pMenuReg->Append(Menu_View, wxT("&View"), pMenuView); |
721b8397 | 337 | pMenuReg->AppendSeparator(); |
9a83f860 | 338 | pMenuReg->Append(Menu_Info, wxT("&Properties"),wxT("Information about current selection")); |
721b8397 DS |
339 | |
340 | return pMenuReg; | |
bbf1f0e5 KB |
341 | } |
342 | ||
343 | // ---------------------------------------------------------------------------- | |
344 | // application class | |
345 | // ---------------------------------------------------------------------------- | |
346 | IMPLEMENT_APP(RegApp) | |
347 | ||
348 | // `Main program' equivalent, creating windows and returning main app frame | |
349 | bool RegApp::OnInit() | |
350 | { | |
45e6e6f8 VZ |
351 | if ( !wxApp::OnInit() ) |
352 | return false; | |
353 | ||
721b8397 | 354 | // create the main frame window and show it |
9a83f860 | 355 | RegFrame *frame = new RegFrame(NULL, wxT("wxRegTest"), 50, 50, 600, 350); |
721b8397 | 356 | frame->Show(true); |
23f681ec | 357 | |
721b8397 | 358 | return true; |
bbf1f0e5 KB |
359 | } |
360 | ||
361 | // ---------------------------------------------------------------------------- | |
362 | // RegFrame | |
363 | // ---------------------------------------------------------------------------- | |
364 | ||
fbfb8bcc | 365 | RegFrame::RegFrame(wxFrame *parent, const wxChar *title, int x, int y, int w, int h) |
945d96f6 | 366 | : wxFrame(parent, wxID_ANY, title, wxPoint(x, y), wxSize(w, h)) |
bbf1f0e5 | 367 | { |
721b8397 | 368 | // this reduces flicker effects |
ea92bb67 | 369 | SetBackgroundColour(*wxWHITE); |
721b8397 DS |
370 | |
371 | // set the icon | |
372 | // ------------ | |
9a83f860 | 373 | SetIcon(wxIcon(wxT("app_icon"))); |
721b8397 DS |
374 | |
375 | // create menu | |
376 | // ----------- | |
377 | wxMenu *pMenuFile = new wxMenu; | |
9a83f860 | 378 | pMenuFile->Append(Menu_Test, wxT("Te&st"), wxT("Test key creation")); |
721b8397 | 379 | pMenuFile->AppendSeparator(); |
2d143b66 | 380 | pMenuFile->Append(Menu_About, wxT("&About"), wxT("Show an extraordinarly beautiful dialog")); |
721b8397 | 381 | pMenuFile->AppendSeparator(); |
9a83f860 | 382 | pMenuFile->Append(Menu_Quit, wxT("E&xit"), wxT("Quit this program")); |
721b8397 DS |
383 | |
384 | wxMenuBar *pMenu = new wxMenuBar; | |
9a83f860 VZ |
385 | pMenu->Append(pMenuFile, wxT("&File")); |
386 | pMenu->Append(CreateRegistryMenu(), wxT("&Registry")); | |
721b8397 DS |
387 | SetMenuBar(pMenu); |
388 | ||
389 | #if DO_REGTEST | |
390 | // create child controls | |
391 | // --------------------- | |
392 | m_treeCtrl = new RegTreeCtrl(this, Ctrl_RegTree); | |
393 | #endif | |
394 | ||
8520f137 | 395 | #if wxUSE_STATUSBAR |
721b8397 DS |
396 | // create the status line |
397 | // ---------------------- | |
398 | CreateStatusBar(2); | |
8520f137 | 399 | #endif // wxUSE_STATUSBAR |
bbf1f0e5 KB |
400 | } |
401 | ||
23f681ec | 402 | RegFrame::~RegFrame() |
bbf1f0e5 | 403 | { |
721b8397 DS |
404 | #if DO_REGTEST |
405 | // this makes deletion of it *much* quicker | |
406 | m_treeCtrl->Hide(); | |
407 | #endif | |
bbf1f0e5 KB |
408 | } |
409 | ||
721b8397 | 410 | void RegFrame::OnQuit(wxCommandEvent& WXUNUSED(event)) |
bbf1f0e5 | 411 | { |
721b8397 | 412 | Close(true); |
bbf1f0e5 KB |
413 | } |
414 | ||
721b8397 | 415 | void RegFrame::OnAbout(wxCommandEvent& WXUNUSED(event)) |
bbf1f0e5 | 416 | { |
721b8397 | 417 | wxMessageDialog dialog(this, |
9a83f860 VZ |
418 | wxT("wxRegistry sample\n") |
419 | wxT("(c) 1998, 2000 Vadim Zeitlin"), | |
420 | wxT("About wxRegTest"), wxOK); | |
bbf1f0e5 | 421 | |
721b8397 | 422 | dialog.ShowModal(); |
bbf1f0e5 KB |
423 | } |
424 | ||
c41ea66a | 425 | void RegFrame::OnTest(wxCommandEvent& WXUNUSED(event)) |
bbf1f0e5 | 426 | { |
721b8397 DS |
427 | #if DO_REGTEST |
428 | m_treeCtrl->OnMenuTest(); | |
429 | #endif | |
bbf1f0e5 KB |
430 | } |
431 | ||
c41ea66a VZ |
432 | void RegFrame::OnGoTo(wxCommandEvent& WXUNUSED(event)) |
433 | { | |
9a83f860 | 434 | static wxString s_location = wxT("HKEY_CURRENT_USER\\Software\\wxWidgets"); |
c41ea66a | 435 | |
721b8397 | 436 | wxString location = wxGetTextFromUser( |
9a83f860 VZ |
437 | wxT("Enter the location to go to:"), |
438 | wxT("wxRegTest question"), | |
721b8397 DS |
439 | s_location, |
440 | this); | |
441 | ||
c41ea66a VZ |
442 | if ( !location ) |
443 | return; | |
444 | ||
445 | s_location = location; | |
721b8397 | 446 | #if DO_REGTEST |
c41ea66a | 447 | m_treeCtrl->GoTo(location); |
721b8397 | 448 | #endif |
c41ea66a VZ |
449 | } |
450 | ||
451 | void RegFrame::OnExpand(wxCommandEvent& WXUNUSED(event)) | |
bbf1f0e5 | 452 | { |
721b8397 DS |
453 | #if DO_REGTEST |
454 | m_treeCtrl->Expand(m_treeCtrl->GetSelection()); | |
455 | #endif | |
bbf1f0e5 KB |
456 | } |
457 | ||
c41ea66a | 458 | void RegFrame::OnCollapse(wxCommandEvent& WXUNUSED(event)) |
bbf1f0e5 | 459 | { |
721b8397 DS |
460 | #if DO_REGTEST |
461 | m_treeCtrl->Collapse(m_treeCtrl->GetSelection()); | |
462 | #endif | |
bbf1f0e5 KB |
463 | } |
464 | ||
c41ea66a | 465 | void RegFrame::OnToggle(wxCommandEvent& WXUNUSED(event)) |
bbf1f0e5 | 466 | { |
721b8397 DS |
467 | #if DO_REGTEST |
468 | m_treeCtrl->Toggle(m_treeCtrl->GetSelection()); | |
469 | #endif | |
bbf1f0e5 KB |
470 | } |
471 | ||
c41ea66a | 472 | void RegFrame::OnRefresh(wxCommandEvent& WXUNUSED(event)) |
5888ef1e | 473 | { |
721b8397 DS |
474 | #if DO_REGTEST |
475 | m_treeCtrl->DoRefresh(); | |
476 | #endif | |
5888ef1e VZ |
477 | } |
478 | ||
c41ea66a | 479 | void RegFrame::OnDelete(wxCommandEvent& WXUNUSED(event)) |
bbf1f0e5 | 480 | { |
721b8397 DS |
481 | #if DO_REGTEST |
482 | m_treeCtrl->DeleteSelected(); | |
483 | #endif | |
bbf1f0e5 KB |
484 | } |
485 | ||
c41ea66a | 486 | void RegFrame::OnNewKey(wxCommandEvent& WXUNUSED(event)) |
bbf1f0e5 | 487 | { |
721b8397 DS |
488 | #if DO_REGTEST |
489 | if ( m_treeCtrl->IsKeySelected() ) | |
490 | { | |
491 | m_treeCtrl->CreateNewKey( | |
9a83f860 | 492 | wxGetTextFromUser(wxT("Enter the name of the new key"))); |
721b8397 DS |
493 | } |
494 | #endif | |
bbf1f0e5 KB |
495 | } |
496 | ||
c41ea66a | 497 | void RegFrame::OnNewText(wxCommandEvent& WXUNUSED(event)) |
bbf1f0e5 | 498 | { |
721b8397 DS |
499 | #if DO_REGTEST |
500 | if ( m_treeCtrl->IsKeySelected() ) | |
501 | { | |
502 | m_treeCtrl->CreateNewTextValue( | |
9a83f860 | 503 | wxGetTextFromUser(wxT("Enter the name for the new text value"))); |
721b8397 DS |
504 | } |
505 | #endif | |
bbf1f0e5 KB |
506 | } |
507 | ||
c41ea66a | 508 | void RegFrame::OnNewBinary(wxCommandEvent& WXUNUSED(event)) |
bbf1f0e5 | 509 | { |
721b8397 DS |
510 | #if DO_REGTEST |
511 | if ( m_treeCtrl->IsKeySelected() ) | |
512 | { | |
513 | m_treeCtrl->CreateNewBinaryValue( | |
9a83f860 | 514 | wxGetTextFromUser(wxT("Enter the name for the new binary value"))); |
721b8397 DS |
515 | } |
516 | #endif | |
bbf1f0e5 KB |
517 | } |
518 | ||
c41ea66a | 519 | void RegFrame::OnInfo(wxCommandEvent& WXUNUSED(event)) |
23f681ec | 520 | { |
721b8397 | 521 | #if DO_REGTEST |
23f681ec | 522 | m_treeCtrl->ShowProperties(); |
721b8397 | 523 | #endif |
23f681ec VZ |
524 | } |
525 | ||
a5c46848 VZ |
526 | void RegFrame::OnViewChange(wxCommandEvent& event) |
527 | { | |
528 | #if DO_REGTEST | |
529 | wxRegKey::WOW64ViewMode view; | |
530 | switch ( event.GetId() ) | |
531 | { | |
532 | case Menu_ViewDefault: | |
533 | view = wxRegKey::WOW64ViewMode_Default; | |
534 | break; | |
535 | ||
536 | case Menu_View32: | |
537 | view = wxRegKey::WOW64ViewMode_32; | |
538 | break; | |
539 | ||
540 | case Menu_View64: | |
541 | view = wxRegKey::WOW64ViewMode_64; | |
542 | break; | |
543 | ||
544 | default: | |
545 | wxFAIL_MSG("Unexpected event source for view change."); | |
546 | return; | |
547 | } | |
548 | ||
549 | m_treeCtrl->SetRegistryView(view); | |
550 | #endif | |
551 | } | |
552 | ||
bbf1f0e5 KB |
553 | // ---------------------------------------------------------------------------- |
554 | // RegImageList | |
555 | // ---------------------------------------------------------------------------- | |
721b8397 | 556 | RegImageList::RegImageList() : wxImageList(16, 16, true) |
bbf1f0e5 | 557 | { |
721b8397 | 558 | // should be in sync with enum RegImageList::RegIcon |
9a83f860 VZ |
559 | static const wxChar *aszIcons[] = { wxT("key1"),wxT("key2"),wxT("key3"),wxT("value1"),wxT("value2") }; |
560 | wxString str = wxT("icon_"); | |
721b8397 DS |
561 | for ( unsigned int n = 0; n < WXSIZEOF(aszIcons); n++ ) |
562 | { | |
563 | Add(wxIcon(str + aszIcons[n], wxBITMAP_TYPE_ICO_RESOURCE)); | |
564 | } | |
bbf1f0e5 KB |
565 | } |
566 | ||
721b8397 DS |
567 | #if DO_REGTEST |
568 | ||
bbf1f0e5 KB |
569 | // ---------------------------------------------------------------------------- |
570 | // RegTreeCtrl | |
571 | // ---------------------------------------------------------------------------- | |
572 | ||
573 | // create a new tree item and insert it into the tree | |
a5c46848 VZ |
574 | RegTreeCtrl::TreeNode *RegTreeCtrl::InsertNewTreeNode( |
575 | TreeNode *pParent, | |
576 | const wxString& strName, | |
577 | int idImage, | |
578 | const wxString *pstrValue, | |
579 | wxRegKey::WOW64ViewMode viewMode) | |
bbf1f0e5 | 580 | { |
721b8397 DS |
581 | // create new item & insert it |
582 | TreeNode *pNewNode = new TreeNode; | |
583 | pNewNode->m_pTree = this; | |
584 | pNewNode->m_pParent = pParent; | |
585 | pNewNode->m_strName = strName; | |
586 | pNewNode->m_bKey = pstrValue == NULL; | |
587 | pNewNode->m_pKey = NULL; | |
a5c46848 | 588 | pNewNode->m_viewMode = viewMode; |
721b8397 DS |
589 | if (pParent) |
590 | { | |
591 | pNewNode->m_id = AppendItem(pParent->Id(), | |
592 | pNewNode->IsKey() ? strName : *pstrValue, | |
593 | idImage); | |
594 | } | |
595 | else | |
596 | { | |
597 | pNewNode->m_id = AddRoot(strName); | |
598 | } | |
599 | ||
600 | wxASSERT_MSG( pNewNode->m_id, wxT("can't create tree control item!")); | |
601 | ||
602 | // save the pointer in the item | |
603 | SetItemData(pNewNode->m_id, pNewNode); | |
604 | ||
605 | // add it to the list of parent's children | |
606 | if ( pParent != NULL ) | |
607 | { | |
608 | pParent->m_aChildren.Add(pNewNode); | |
609 | } | |
610 | ||
611 | if ( pNewNode->IsKey() ) | |
612 | { | |
613 | SetItemHasChildren(pNewNode->Id()); | |
614 | ||
615 | if ( !pNewNode->IsRoot() ) | |
616 | { | |
617 | // set the expanded icon as well | |
618 | SetItemImage(pNewNode->Id(), | |
619 | RegImageList::OpenedKey, | |
620 | wxTreeItemIcon_Expanded); | |
621 | } | |
23f681ec | 622 | } |
bbf1f0e5 | 623 | |
721b8397 | 624 | return pNewNode; |
bbf1f0e5 KB |
625 | } |
626 | ||
627 | RegTreeCtrl::RegTreeCtrl(wxWindow *parent, wxWindowID id) | |
721b8397 DS |
628 | : wxTreeCtrl(parent, id, wxDefaultPosition, wxDefaultSize, |
629 | wxTR_HAS_BUTTONS | wxTR_EDIT_LABELS | wxSUNKEN_BORDER) | |
bbf1f0e5 | 630 | { |
721b8397 DS |
631 | // init members |
632 | m_draggedItem = NULL; | |
633 | m_restoreStatus = false; | |
a5c46848 | 634 | m_viewMode = wxRegKey::WOW64ViewMode_Default; |
721b8397 DS |
635 | |
636 | // create the image list | |
637 | // --------------------- | |
638 | m_imageList = new RegImageList; | |
639 | SetImageList(m_imageList); | |
640 | ||
641 | // create root keys | |
642 | // ---------------- | |
a5c46848 VZ |
643 | m_pRoot = |
644 | InsertNewTreeNode( | |
645 | NULL, | |
646 | wxT("Registry Root"), | |
647 | RegImageList::Root, | |
648 | NULL, | |
649 | m_viewMode); | |
721b8397 DS |
650 | |
651 | // create popup menu | |
652 | // ----------------- | |
653 | m_pMenuPopup = CreateRegistryMenu(); | |
bbf1f0e5 KB |
654 | } |
655 | ||
656 | RegTreeCtrl::~RegTreeCtrl() | |
657 | { | |
721b8397 DS |
658 | delete m_pMenuPopup; |
659 | // delete m_pRoot; -- this is done by the tree now | |
660 | delete m_imageList; | |
bbf1f0e5 KB |
661 | } |
662 | ||
663 | void RegTreeCtrl::AddStdKeys() | |
664 | { | |
721b8397 DS |
665 | for ( unsigned int ui = 0; ui < wxRegKey::nStdKeys; ui++ ) |
666 | { | |
a5c46848 VZ |
667 | InsertNewTreeNode( |
668 | m_pRoot, | |
669 | wxRegKey::GetStdKeyName(ui), | |
670 | RegImageList::ClosedKey, | |
671 | NULL, | |
672 | m_viewMode); | |
721b8397 | 673 | } |
bbf1f0e5 KB |
674 | } |
675 | ||
676 | // ---------------------------------------------------------------------------- | |
677 | // notifications | |
678 | // ---------------------------------------------------------------------------- | |
679 | ||
23f681ec VZ |
680 | void RegTreeCtrl::OnIdle(wxIdleEvent& WXUNUSED(event)) |
681 | { | |
721b8397 DS |
682 | if ( m_restoreStatus ) |
683 | { | |
23f681ec | 684 | // restore it after OnItemExpanding() |
a60b1f5d | 685 | wxLogStatus(wxT("Ok")); |
23f681ec VZ |
686 | wxSetCursor(*wxSTANDARD_CURSOR); |
687 | ||
721b8397 | 688 | m_restoreStatus = false; |
23f681ec VZ |
689 | } |
690 | } | |
691 | ||
bbf1f0e5 KB |
692 | void RegTreeCtrl::OnRightClick(wxMouseEvent& event) |
693 | { | |
721b8397 | 694 | int iFlags; |
945d96f6 | 695 | wxTreeItemId lId = HitTest(wxPoint(event.GetX(), event.GetY()), iFlags); |
721b8397 DS |
696 | if ( iFlags & wxTREE_HITTEST_ONITEMLABEL ) |
697 | { | |
698 | // select the item first | |
699 | SelectItem(lId); | |
700 | } | |
701 | //else: take the currently selected item if click not on item | |
702 | ||
703 | PopupMenu(m_pMenuPopup, event.GetX(), event.GetY()); | |
bbf1f0e5 KB |
704 | } |
705 | ||
706 | ||
721b8397 | 707 | void RegTreeCtrl::OnDeleteItem(wxTreeEvent& WXUNUSED(event)) |
bbf1f0e5 KB |
708 | { |
709 | } | |
710 | ||
711 | // test the key creation functions | |
712 | void RegTreeCtrl::OnMenuTest() | |
713 | { | |
945d96f6 | 714 | wxTreeItemId lId = GetSelection(); |
721b8397 DS |
715 | TreeNode *pNode = (TreeNode *)GetItemData(lId); |
716 | ||
717 | wxCHECK_RET( pNode != NULL, wxT("tree item without data?") ); | |
718 | ||
719 | if ( pNode->IsRoot() ) | |
720 | { | |
721 | wxLogError(wxT("Can't create a subkey under the root key.")); | |
722 | return; | |
723 | } | |
724 | ||
725 | if ( !pNode->IsKey() ) | |
726 | { | |
727 | wxLogError(wxT("Can't create a subkey under a value!")); | |
728 | return; | |
729 | } | |
730 | ||
9a83f860 | 731 | wxRegKey key1(pNode->Key(), wxT("key1")); |
721b8397 DS |
732 | if ( key1.Create() ) |
733 | { | |
9a83f860 | 734 | wxRegKey key2a(key1, wxT("key2a")), key2b(key1, wxT("key2b")); |
721b8397 DS |
735 | if ( key2a.Create() && key2b.Create() ) |
736 | { | |
737 | // put some values under the newly created keys | |
9a83f860 VZ |
738 | key1.SetValue(wxT("first_term"), wxT("10")); |
739 | key1.SetValue(wxT("second_term"), wxT("7")); | |
740 | key2a = wxT("this is the unnamed value"); | |
721b8397 DS |
741 | key2b.SetValue(wxT("sum"), 17); |
742 | ||
743 | // refresh tree | |
744 | pNode->Refresh(); | |
745 | wxLogStatus(wxT("Test keys successfully added.")); | |
746 | return; | |
747 | } | |
bbf1f0e5 | 748 | } |
23f681ec | 749 | |
721b8397 | 750 | wxLogError(wxT("Creation of test keys failed.")); |
bbf1f0e5 KB |
751 | } |
752 | ||
753 | void RegTreeCtrl::OnChar(wxKeyEvent& event) | |
754 | { | |
721b8397 DS |
755 | switch ( event.GetKeyCode() ) |
756 | { | |
757 | case WXK_DELETE: | |
758 | DeleteSelected(); | |
759 | return; | |
760 | ||
761 | case WXK_RETURN: | |
762 | if ( event.AltDown() ) | |
763 | { | |
764 | ShowProperties(); | |
765 | ||
766 | return; | |
767 | } | |
768 | } | |
769 | ||
770 | event.Skip(); | |
bbf1f0e5 KB |
771 | } |
772 | ||
773 | void RegTreeCtrl::OnSelChanged(wxTreeEvent& event) | |
774 | { | |
8520f137 | 775 | #if wxUSE_STATUSBAR |
721b8397 DS |
776 | wxFrame *pFrame = (wxFrame *) wxWindow::GetParent(); |
777 | pFrame->SetStatusText(GetNode(event)->FullName(), 1); | |
8520f137 WS |
778 | #else |
779 | wxUnusedVar(event); | |
780 | #endif // wxUSE_STATUSBAR | |
bbf1f0e5 KB |
781 | } |
782 | ||
783 | void RegTreeCtrl::OnItemExpanding(wxTreeEvent& event) | |
784 | { | |
721b8397 | 785 | TreeNode *pNode = GetNode(event); |
ce7fe42e | 786 | bool bExpanding = event.GetEventType() == wxEVT_TREE_ITEM_EXPANDING; |
721b8397 DS |
787 | |
788 | // expansion might take some time | |
789 | wxSetCursor(*wxHOURGLASS_CURSOR); | |
790 | wxLogStatus(wxT("Working...")); | |
791 | wxYield(); // to give the status line a chance to refresh itself | |
792 | m_restoreStatus = true; // some time later... | |
793 | ||
794 | if ( pNode->IsKey() ) | |
795 | { | |
796 | if ( bExpanding ) | |
797 | { | |
798 | // expanding: add subkeys/values | |
799 | if ( !pNode->OnExpand() ) | |
800 | return; | |
801 | } | |
802 | else | |
803 | { | |
804 | // collapsing: clean up | |
805 | pNode->OnCollapse(); | |
806 | } | |
bbf1f0e5 | 807 | } |
23f681ec VZ |
808 | } |
809 | ||
c41ea66a VZ |
810 | void RegTreeCtrl::OnBeginEdit(wxTreeEvent& event) |
811 | { | |
812 | TreeNode *pNode = GetNode(event); | |
721b8397 DS |
813 | if ( pNode->IsRoot() || pNode->Parent()->IsRoot() ) |
814 | { | |
9a83f860 | 815 | wxLogStatus(wxT("This registry key can't be renamed.")); |
c41ea66a VZ |
816 | |
817 | event.Veto(); | |
818 | } | |
721b8397 DS |
819 | else |
820 | { | |
c41ea66a VZ |
821 | m_nameOld = pNode->m_strName; |
822 | } | |
823 | } | |
824 | ||
825 | void RegTreeCtrl::OnEndEdit(wxTreeEvent& event) | |
826 | { | |
827 | bool ok; | |
828 | ||
829 | wxString name = event.GetLabel(); | |
830 | ||
831 | TreeNode *pNode = GetNode(event); | |
832 | if ( pNode->IsKey() ) | |
833 | { | |
834 | wxRegKey& key = pNode->Key(); | |
835 | ok = key.Rename(name); | |
836 | } | |
837 | else | |
838 | { | |
839 | pNode = pNode->Parent(); | |
840 | wxRegKey& key = pNode->Key(); | |
841 | ||
842 | ok = key.RenameValue(m_nameOld, name); | |
843 | } | |
844 | ||
721b8397 DS |
845 | if ( !ok ) |
846 | { | |
9a83f860 | 847 | wxLogError(wxT("Failed to rename '%s' to '%s'."), |
721b8397 | 848 | m_nameOld.c_str(), name.c_str()); |
c41ea66a VZ |
849 | } |
850 | #if 0 // MSW tree ctrl doesn't like this at all, it hangs | |
721b8397 DS |
851 | else |
852 | { | |
c41ea66a VZ |
853 | pNode->Refresh(); |
854 | } | |
855 | #endif // 0 | |
856 | } | |
857 | ||
23f681ec VZ |
858 | void RegTreeCtrl::OnBeginDrag(wxTreeEvent& event) |
859 | { | |
ce7fe42e | 860 | m_copyOnDrop = event.GetEventType() == wxEVT_TREE_BEGIN_DRAG; |
23f681ec VZ |
861 | |
862 | TreeNode *pNode = GetNode(event); | |
863 | if ( pNode->IsRoot() || pNode->Parent()->IsRoot() ) | |
864 | { | |
a60b1f5d | 865 | wxLogStatus(wxT("This registry key can't be %s."), |
721b8397 | 866 | m_copyOnDrop ? wxT("copied") : wxT("moved")); |
23f681ec VZ |
867 | } |
868 | else | |
869 | { | |
a60b1f5d | 870 | wxLogStatus(wxT("%s item %s..."), |
721b8397 DS |
871 | m_copyOnDrop ? wxT("Copying") : wxT("Moving"), |
872 | pNode->FullName()); | |
bbf1f0e5 | 873 | |
23f681ec VZ |
874 | m_draggedItem = pNode; |
875 | ||
876 | event.Allow(); | |
877 | } | |
878 | } | |
879 | ||
880 | void RegTreeCtrl::OnEndDrag(wxTreeEvent& event) | |
881 | { | |
a60b1f5d | 882 | wxCHECK_RET( m_draggedItem, wxT("end drag without begin drag?") ); |
23f681ec VZ |
883 | |
884 | // clear the pointer anyhow | |
885 | TreeNode *src = m_draggedItem; | |
886 | m_draggedItem = NULL; | |
887 | ||
888 | // where are we going to drop it? | |
889 | TreeNode *dst = GetNode(event); | |
721b8397 DS |
890 | if ( dst && !dst->IsKey() ) |
891 | { | |
23f681ec VZ |
892 | // we need a parent key |
893 | dst = dst->Parent(); | |
894 | } | |
721b8397 DS |
895 | |
896 | if ( !dst || dst->IsRoot() ) | |
897 | { | |
a60b1f5d | 898 | wxLogError(wxT("Can't create a key here.")); |
23f681ec VZ |
899 | |
900 | return; | |
901 | } | |
902 | ||
903 | bool isKey = src->IsKey(); | |
904 | if ( (isKey && (src == dst)) || | |
5888ef1e | 905 | (!isKey && (dst->Parent() == src)) ) { |
a60b1f5d | 906 | wxLogStatus(wxT("Can't copy something on itself")); |
23f681ec VZ |
907 | |
908 | return; | |
909 | } | |
910 | ||
911 | // remove the "Registry Root\\" from the full name | |
912 | wxString nameSrc, nameDst; | |
913 | nameSrc << wxString(src->FullName()).AfterFirst('\\'); | |
914 | nameDst << wxString(dst->FullName()).AfterFirst('\\') << '\\' | |
915 | << wxString(src->FullName()).AfterLast('\\'); | |
916 | ||
9a83f860 VZ |
917 | wxString verb = m_copyOnDrop ? wxT("copy") : wxT("move"); |
918 | wxString what = isKey ? wxT("key") : wxT("value"); | |
23f681ec VZ |
919 | |
920 | if ( wxMessageBox(wxString::Format | |
921 | ( | |
a60b1f5d | 922 | wxT("Do you really want to %s the %s %s to %s?"), |
23f681ec VZ |
923 | verb.c_str(), |
924 | what.c_str(), | |
925 | nameSrc.c_str(), | |
926 | nameDst.c_str() | |
927 | ), | |
9a83f860 | 928 | wxT("RegTest Confirm"), |
23f681ec VZ |
929 | wxICON_QUESTION | wxYES_NO | wxCANCEL, this) != wxYES ) { |
930 | return; | |
931 | } | |
932 | ||
23f681ec | 933 | bool ok; |
721b8397 DS |
934 | if ( isKey ) |
935 | { | |
23f681ec | 936 | wxRegKey& key = src->Key(); |
5888ef1e | 937 | wxRegKey keyDst(dst->Key(), src->m_strName); |
721b8397 DS |
938 | ok = keyDst.Create(false); |
939 | if ( !ok ) | |
940 | { | |
2b5f62a0 | 941 | wxLogError(wxT("Key '%s' already exists"), keyDst.GetName().c_str()); |
5888ef1e | 942 | } |
721b8397 DS |
943 | else |
944 | { | |
5888ef1e VZ |
945 | ok = key.Copy(keyDst); |
946 | } | |
23f681ec | 947 | |
721b8397 DS |
948 | if ( ok && !m_copyOnDrop ) |
949 | { | |
23f681ec VZ |
950 | // delete the old key |
951 | ok = key.DeleteSelf(); | |
721b8397 DS |
952 | if ( ok ) |
953 | { | |
23f681ec VZ |
954 | src->Parent()->Refresh(); |
955 | } | |
956 | } | |
957 | } | |
721b8397 DS |
958 | else // value |
959 | { | |
23f681ec VZ |
960 | wxRegKey& key = src->Parent()->Key(); |
961 | ok = key.CopyValue(src->m_strName, dst->Key()); | |
721b8397 DS |
962 | if ( ok && !m_copyOnDrop ) |
963 | { | |
5888ef1e | 964 | // we moved it, so delete the old one |
23f681ec | 965 | ok = key.DeleteValue(src->m_strName); |
23f681ec | 966 | } |
bbf1f0e5 | 967 | } |
bbf1f0e5 | 968 | |
721b8397 DS |
969 | if ( !ok ) |
970 | { | |
a60b1f5d MB |
971 | wxLogError(wxT("Failed to %s registry %s."), |
972 | verb.c_str(), what.c_str()); | |
23f681ec | 973 | } |
721b8397 DS |
974 | else |
975 | { | |
c41ea66a VZ |
976 | dst->Refresh(); |
977 | } | |
bbf1f0e5 KB |
978 | } |
979 | ||
980 | // ---------------------------------------------------------------------------- | |
981 | // TreeNode implementation | |
982 | // ---------------------------------------------------------------------------- | |
983 | bool RegTreeCtrl::TreeNode::OnExpand() | |
984 | { | |
721b8397 DS |
985 | // we add children only once |
986 | if ( !m_aChildren.IsEmpty() ) | |
987 | { | |
988 | // we've been already expanded | |
989 | return true; | |
990 | } | |
991 | ||
992 | if ( IsRoot() ) | |
993 | { | |
994 | // we're the root key | |
995 | m_pTree->AddStdKeys(); | |
996 | return true; | |
997 | } | |
998 | ||
999 | if ( Parent()->IsRoot() ) | |
1000 | { | |
1001 | // we're a standard key | |
a5c46848 | 1002 | m_pKey = new wxRegKey(m_strName, m_viewMode); |
721b8397 | 1003 | } |
bbf1f0e5 | 1004 | else |
721b8397 DS |
1005 | { |
1006 | // we're a normal key | |
1007 | m_pKey = new wxRegKey(*(Parent()->m_pKey), m_strName); | |
1008 | } | |
1009 | ||
1010 | if ( !m_pKey->Open() ) | |
1011 | { | |
1012 | wxLogError(wxT("The key '%s' can't be opened."), FullName()); | |
1013 | return false; | |
1014 | } | |
1015 | ||
1016 | // if we're empty, we shouldn't be expandable at all | |
1017 | bool isEmpty = true; | |
1018 | ||
1019 | // enumeration variables | |
1020 | long l; | |
1021 | wxString str; | |
1022 | bool bCont; | |
1023 | ||
1024 | // enumerate all subkeys | |
1025 | bCont = m_pKey->GetFirstKey(str, l); | |
1026 | while ( bCont ) | |
1027 | { | |
a5c46848 VZ |
1028 | m_pTree->InsertNewTreeNode( |
1029 | this, | |
1030 | str, | |
1031 | RegImageList::ClosedKey, | |
1032 | NULL, | |
1033 | m_viewMode); | |
721b8397 DS |
1034 | bCont = m_pKey->GetNextKey(str, l); |
1035 | ||
1036 | // we have at least this key... | |
1037 | isEmpty = false; | |
1038 | } | |
1039 | ||
1040 | // enumerate all values | |
1041 | bCont = m_pKey->GetFirstValue(str, l); | |
1042 | while ( bCont ) | |
1043 | { | |
1044 | wxString strItem; | |
8afd90d5 | 1045 | if (str.empty()) |
9a83f860 | 1046 | strItem = wxT("<default>"); |
721b8397 DS |
1047 | else |
1048 | strItem = str; | |
9a83f860 | 1049 | strItem += wxT(" = "); |
721b8397 DS |
1050 | |
1051 | // determine the appropriate icon | |
1052 | RegImageList::Icon icon; | |
1053 | switch ( m_pKey->GetValueType(str) ) | |
bbf1f0e5 | 1054 | { |
721b8397 DS |
1055 | case wxRegKey::Type_String: |
1056 | case wxRegKey::Type_Expand_String: | |
1057 | case wxRegKey::Type_Multi_String: | |
1058 | { | |
1059 | wxString strValue; | |
1060 | icon = RegImageList::TextValue; | |
1061 | m_pKey->QueryValue(str, strValue); | |
1062 | strItem += strValue; | |
bbf1f0e5 KB |
1063 | } |
1064 | break; | |
1065 | ||
721b8397 DS |
1066 | case wxRegKey::Type_None: |
1067 | // @@ handle the error... | |
1068 | icon = RegImageList::BinaryValue; | |
1069 | break; | |
bbf1f0e5 | 1070 | |
721b8397 | 1071 | case wxRegKey::Type_Dword: |
bbf1f0e5 | 1072 | { |
721b8397 DS |
1073 | long l; |
1074 | m_pKey->QueryValue(str, &l); | |
1075 | strItem << l; | |
bbf1f0e5 KB |
1076 | } |
1077 | ||
1078 | // fall through | |
1079 | ||
721b8397 DS |
1080 | default: |
1081 | icon = RegImageList::BinaryValue; | |
1082 | } | |
bbf1f0e5 | 1083 | |
a5c46848 | 1084 | m_pTree->InsertNewTreeNode(this, str, icon, &strItem, m_viewMode); |
721b8397 | 1085 | bCont = m_pKey->GetNextValue(str, l); |
23f681ec | 1086 | |
721b8397 DS |
1087 | // we have at least this value... |
1088 | isEmpty = false; | |
1089 | } | |
23f681ec | 1090 | |
721b8397 DS |
1091 | if ( isEmpty ) |
1092 | { | |
1093 | // this is for the case when our last child was just deleted | |
1094 | wxTreeItemId theId(Id()); // Temp variable seems necessary for BC++ | |
1095 | m_pTree->Collapse(theId); | |
23f681ec | 1096 | |
721b8397 DS |
1097 | // we won't be expanded any more |
1098 | m_pTree->SetItemHasChildren(theId, false); | |
1099 | } | |
bbf1f0e5 | 1100 | |
721b8397 | 1101 | return true; |
bbf1f0e5 KB |
1102 | } |
1103 | ||
1104 | void RegTreeCtrl::TreeNode::OnCollapse() | |
1105 | { | |
721b8397 | 1106 | DestroyChildren(); |
bbf1f0e5 | 1107 | |
5276b0a5 | 1108 | wxDELETE(m_pKey); |
bbf1f0e5 KB |
1109 | } |
1110 | ||
23f681ec VZ |
1111 | void RegTreeCtrl::TreeNode::Refresh() |
1112 | { | |
5888ef1e VZ |
1113 | if ( !IsKey() ) |
1114 | return; | |
1115 | ||
f6bcfd97 BP |
1116 | wxTreeItemId theId(Id()); // Temp variable seems necessary for BC++ |
1117 | bool wasExpanded = m_pTree->IsExpanded(theId); | |
c41ea66a | 1118 | if ( wasExpanded ) |
f6bcfd97 | 1119 | m_pTree->Collapse(theId); |
c41ea66a VZ |
1120 | |
1121 | OnCollapse(); | |
f6bcfd97 | 1122 | m_pTree->SetItemHasChildren(theId); |
721b8397 DS |
1123 | if ( wasExpanded ) |
1124 | { | |
f6bcfd97 | 1125 | m_pTree->Expand(theId); |
5888ef1e VZ |
1126 | OnExpand(); |
1127 | } | |
23f681ec VZ |
1128 | } |
1129 | ||
1130 | bool RegTreeCtrl::TreeNode::DeleteChild(TreeNode *child) | |
bbf1f0e5 | 1131 | { |
23f681ec | 1132 | int index = m_aChildren.Index(child); |
721b8397 | 1133 | wxCHECK_MSG( index != wxNOT_FOUND, false, |
a60b1f5d | 1134 | wxT("our child in tree should be in m_aChildren") ); |
23f681ec VZ |
1135 | |
1136 | m_aChildren.RemoveAt((size_t)index); | |
1137 | ||
1138 | bool ok; | |
721b8397 DS |
1139 | if ( child->IsKey() ) |
1140 | { | |
23f681ec VZ |
1141 | // must close key before deleting it |
1142 | child->OnCollapse(); | |
1143 | ||
1144 | ok = Key().DeleteKey(child->m_strName); | |
1145 | } | |
721b8397 DS |
1146 | else |
1147 | { | |
23f681ec VZ |
1148 | ok = Key().DeleteValue(child->m_strName); |
1149 | } | |
1150 | ||
721b8397 DS |
1151 | if ( ok ) |
1152 | { | |
f6bcfd97 BP |
1153 | wxTreeItemId theId(child->Id()); // Temp variable seems necessary for BC++ |
1154 | m_pTree->Delete(theId); | |
23f681ec VZ |
1155 | |
1156 | Refresh(); | |
1157 | } | |
1158 | ||
1159 | return ok; | |
bbf1f0e5 KB |
1160 | } |
1161 | ||
1162 | void RegTreeCtrl::TreeNode::DestroyChildren() | |
1163 | { | |
721b8397 DS |
1164 | // destroy all children |
1165 | size_t nCount = m_aChildren.GetCount(); | |
1166 | for ( size_t n = 0; n < nCount; n++ ) | |
1167 | { | |
945d96f6 WS |
1168 | wxTreeItemId lId = m_aChildren[n]->Id(); |
1169 | m_pTree->Delete(lId); | |
721b8397 DS |
1170 | } |
1171 | ||
1172 | m_aChildren.Empty(); | |
bbf1f0e5 KB |
1173 | } |
1174 | ||
1175 | RegTreeCtrl::TreeNode::~TreeNode() | |
1176 | { | |
721b8397 | 1177 | delete m_pKey; |
bbf1f0e5 KB |
1178 | } |
1179 | ||
a60b1f5d | 1180 | const wxChar *RegTreeCtrl::TreeNode::FullName() const |
bbf1f0e5 | 1181 | { |
721b8397 DS |
1182 | static wxString s_strName; |
1183 | ||
1184 | if ( IsRoot() ) | |
1185 | { | |
1186 | return wxT("Registry Root"); | |
1187 | } | |
1188 | else | |
1189 | { | |
1190 | // our own registry key might not (yet) exist or we might be a value, | |
1191 | // so just use the parent's and concatenate | |
1192 | s_strName = Parent()->FullName(); | |
1193 | s_strName << wxT('\\') << m_strName; | |
1194 | ||
7e3ea54f | 1195 | return s_strName.t_str(); |
721b8397 | 1196 | } |
bbf1f0e5 KB |
1197 | } |
1198 | ||
a5c46848 VZ |
1199 | void RegTreeCtrl::TreeNode::SetRegistryView(wxRegKey::WOW64ViewMode viewMode) |
1200 | { | |
1201 | m_viewMode = viewMode; | |
1202 | ||
1203 | // Update children with new view. | |
1204 | size_t nCount = m_aChildren.GetCount(); | |
1205 | for (size_t n = 0; n < nCount; n++) | |
1206 | m_aChildren[n]->SetRegistryView(viewMode); | |
1207 | } | |
1208 | ||
bbf1f0e5 KB |
1209 | // ---------------------------------------------------------------------------- |
1210 | // operations on RegTreeCtrl | |
1211 | // ---------------------------------------------------------------------------- | |
1212 | ||
c41ea66a VZ |
1213 | void RegTreeCtrl::GoTo(const wxString& location) |
1214 | { | |
9a83f860 | 1215 | wxStringTokenizer tk(location, wxT("\\")); |
c41ea66a VZ |
1216 | |
1217 | wxTreeItemId id = GetRootItem(); | |
1218 | ||
721b8397 DS |
1219 | while ( tk.HasMoreTokens() ) |
1220 | { | |
c41ea66a VZ |
1221 | wxString subkey = tk.GetNextToken(); |
1222 | ||
1223 | wxTreeItemId idCurrent = id; | |
1224 | if ( !IsExpanded(idCurrent) ) | |
1225 | Expand(idCurrent); | |
1226 | ||
721b8397 | 1227 | wxTreeItemIdValue dummy; |
c41ea66a VZ |
1228 | id = GetFirstChild(idCurrent, dummy); |
1229 | ||
721b8397 DS |
1230 | if ( idCurrent == GetRootItem() ) |
1231 | { | |
c41ea66a | 1232 | // special case: we understand both HKCU and HKEY_CURRENT_USER here |
721b8397 DS |
1233 | for ( size_t key = 0; key < wxRegKey::nStdKeys; key++ ) |
1234 | { | |
1235 | if ( subkey == wxRegKey::GetStdKeyName(key) | |
1236 | || subkey == wxRegKey::GetStdKeyShortName(key) ) | |
1237 | { | |
c41ea66a VZ |
1238 | break; |
1239 | } | |
1240 | ||
1241 | id = GetNextChild(idCurrent, dummy); | |
1242 | } | |
1243 | } | |
721b8397 DS |
1244 | else |
1245 | { | |
c41ea66a | 1246 | // enum all children |
721b8397 DS |
1247 | while ( id.IsOk() ) |
1248 | { | |
c41ea66a VZ |
1249 | if ( subkey == ((TreeNode *)GetItemData(id))->m_strName ) |
1250 | break; | |
1251 | ||
1252 | id = GetNextChild(idCurrent, dummy); | |
1253 | } | |
1254 | } | |
1255 | ||
721b8397 DS |
1256 | if ( !id.IsOk() ) |
1257 | { | |
9a83f860 | 1258 | wxLogError(wxT("No such key '%s'."), location.c_str()); |
c41ea66a VZ |
1259 | |
1260 | return; | |
1261 | } | |
1262 | } | |
1263 | ||
1264 | if ( id.IsOk() ) | |
1265 | SelectItem(id); | |
1266 | } | |
1267 | ||
bbf1f0e5 KB |
1268 | void RegTreeCtrl::DeleteSelected() |
1269 | { | |
945d96f6 WS |
1270 | wxTreeItemId lCurrent = GetSelection(), |
1271 | lParent = GetItemParent(lCurrent); | |
721b8397 | 1272 | |
945d96f6 | 1273 | if ( lParent == GetRootItem() ) |
721b8397 DS |
1274 | { |
1275 | wxLogError(wxT("Can't delete root key.")); | |
1276 | return; | |
1277 | } | |
1278 | ||
1279 | TreeNode *pCurrent = (TreeNode *)GetItemData(lCurrent), | |
945d96f6 | 1280 | *pParent = (TreeNode *)GetItemData(lParent); |
721b8397 DS |
1281 | |
1282 | wxCHECK_RET(pCurrent && pParent, wxT("either node or parent without data?")); | |
1283 | ||
1284 | if ( pParent->IsRoot() ) | |
1285 | { | |
1286 | wxLogError(wxT("Can't delete standard key.")); | |
1287 | return; | |
1288 | } | |
1289 | ||
9a83f860 | 1290 | wxString what = pCurrent->IsKey() ? wxT("key") : wxT("value"); |
721b8397 DS |
1291 | if ( wxMessageBox(wxString::Format |
1292 | ( | |
1293 | wxT("Do you really want to delete this %s?"), | |
1294 | what.c_str() | |
1295 | ), | |
9a83f860 | 1296 | wxT("Confirmation"), |
721b8397 DS |
1297 | wxICON_QUESTION | wxYES_NO | wxCANCEL, this) != wxYES ) |
1298 | { | |
1299 | return; | |
1300 | } | |
1301 | ||
1302 | pParent->DeleteChild(pCurrent); | |
bbf1f0e5 KB |
1303 | } |
1304 | ||
1305 | void RegTreeCtrl::CreateNewKey(const wxString& strName) | |
1306 | { | |
945d96f6 | 1307 | wxTreeItemId lCurrent = GetSelection(); |
721b8397 | 1308 | TreeNode *pCurrent = (TreeNode *)GetItemData(lCurrent); |
bbf1f0e5 | 1309 | |
721b8397 | 1310 | wxCHECK_RET( pCurrent != NULL, wxT("node without data?") ); |
23f681ec | 1311 | |
721b8397 | 1312 | wxASSERT( pCurrent->IsKey() ); // check must have been done before |
bbf1f0e5 | 1313 | |
721b8397 DS |
1314 | if ( pCurrent->IsRoot() ) |
1315 | { | |
1316 | wxLogError(wxT("Can't create a new key under the root key.")); | |
1317 | return; | |
1318 | } | |
bbf1f0e5 | 1319 | |
721b8397 DS |
1320 | wxRegKey key(pCurrent->Key(), strName); |
1321 | if ( key.Create() ) | |
1322 | pCurrent->Refresh(); | |
bbf1f0e5 KB |
1323 | } |
1324 | ||
1325 | void RegTreeCtrl::CreateNewTextValue(const wxString& strName) | |
1326 | { | |
945d96f6 | 1327 | wxTreeItemId lCurrent = GetSelection(); |
721b8397 | 1328 | TreeNode *pCurrent = (TreeNode *)GetItemData(lCurrent); |
bbf1f0e5 | 1329 | |
721b8397 | 1330 | wxCHECK_RET( pCurrent != NULL, wxT("node without data?") ); |
23f681ec | 1331 | |
721b8397 | 1332 | wxASSERT( pCurrent->IsKey() ); // check must have been done before |
bbf1f0e5 | 1333 | |
721b8397 DS |
1334 | if ( pCurrent->IsRoot() ) |
1335 | { | |
1336 | wxLogError(wxT("Can't create a new value under the root key.")); | |
1337 | return; | |
1338 | } | |
bbf1f0e5 | 1339 | |
721b8397 DS |
1340 | if ( pCurrent->Key().SetValue(strName, wxEmptyString) ) |
1341 | pCurrent->Refresh(); | |
bbf1f0e5 KB |
1342 | } |
1343 | ||
1344 | void RegTreeCtrl::CreateNewBinaryValue(const wxString& strName) | |
1345 | { | |
945d96f6 | 1346 | wxTreeItemId lCurrent = GetSelection(); |
721b8397 | 1347 | TreeNode *pCurrent = (TreeNode *)GetItemData(lCurrent); |
bbf1f0e5 | 1348 | |
721b8397 | 1349 | wxCHECK_RET( pCurrent != NULL, wxT("node without data?") ); |
23f681ec | 1350 | |
721b8397 | 1351 | wxASSERT( pCurrent->IsKey() ); // check must have been done before |
bbf1f0e5 | 1352 | |
721b8397 DS |
1353 | if ( pCurrent->IsRoot() ) |
1354 | { | |
1355 | wxLogError(wxT("Can't create a new value under the root key.")); | |
1356 | return; | |
1357 | } | |
bbf1f0e5 | 1358 | |
721b8397 DS |
1359 | if ( pCurrent->Key().SetValue(strName, 0) ) |
1360 | pCurrent->Refresh(); | |
bbf1f0e5 KB |
1361 | } |
1362 | ||
a5c46848 VZ |
1363 | void RegTreeCtrl::SetRegistryView(wxRegKey::WOW64ViewMode viewMode) |
1364 | { | |
1365 | m_viewMode = viewMode; | |
1366 | m_pRoot->SetRegistryView(viewMode); | |
1367 | m_pRoot->Refresh(); | |
1368 | } | |
1369 | ||
23f681ec VZ |
1370 | void RegTreeCtrl::ShowProperties() |
1371 | { | |
945d96f6 | 1372 | wxTreeItemId lCurrent = GetSelection(); |
23f681ec VZ |
1373 | TreeNode *pCurrent = (TreeNode *)GetItemData(lCurrent); |
1374 | ||
1375 | if ( !pCurrent || pCurrent->IsRoot() ) | |
1376 | { | |
a60b1f5d | 1377 | wxLogStatus(wxT("No properties")); |
23f681ec VZ |
1378 | |
1379 | return; | |
1380 | } | |
1381 | ||
1382 | if ( pCurrent->IsKey() ) | |
1383 | { | |
1384 | const wxRegKey& key = pCurrent->Key(); | |
1385 | size_t nSubKeys, nValues; | |
1386 | if ( !key.GetKeyInfo(&nSubKeys, NULL, &nValues, NULL) ) | |
1387 | { | |
a60b1f5d | 1388 | wxLogError(wxT("Couldn't get key info")); |
23f681ec VZ |
1389 | } |
1390 | else | |
1391 | { | |
a60b1f5d | 1392 | wxLogMessage(wxT("Key '%s' has %u subkeys and %u values."), |
23f681ec VZ |
1393 | key.GetName().c_str(), nSubKeys, nValues); |
1394 | } | |
1395 | } | |
1396 | else // it's a value | |
1397 | { | |
1398 | TreeNode *parent = pCurrent->Parent(); | |
a60b1f5d | 1399 | wxCHECK_RET( parent, wxT("reg value without key?") ); |
23f681ec VZ |
1400 | |
1401 | const wxRegKey& key = parent->Key(); | |
a60b1f5d MB |
1402 | const wxChar *value = pCurrent->m_strName.c_str(); |
1403 | wxLogMessage(wxT("Value '%s' under the key '%s' is of type ") | |
721b8397 DS |
1404 | wxT("%d (%s)."), |
1405 | value, | |
1406 | parent->m_strName.c_str(), | |
1407 | key.GetValueType(value), | |
1408 | key.IsNumericValue(value) ? wxT("numeric") : wxT("string")); | |
23f681ec VZ |
1409 | |
1410 | } | |
1411 | } | |
1412 | ||
bbf1f0e5 KB |
1413 | bool RegTreeCtrl::IsKeySelected() const |
1414 | { | |
945d96f6 | 1415 | wxTreeItemId lCurrent = GetSelection(); |
721b8397 | 1416 | TreeNode *pCurrent = (TreeNode *) GetItemData(lCurrent); |
bbf1f0e5 | 1417 | |
721b8397 | 1418 | wxCHECK( pCurrent != NULL, false ); |
bbf1f0e5 | 1419 | |
721b8397 | 1420 | return pCurrent->IsKey(); |
23f681ec | 1421 | } |
5888ef1e | 1422 | |
721b8397 | 1423 | void RegTreeCtrl::DoRefresh() |
5888ef1e | 1424 | { |
945d96f6 | 1425 | wxTreeItemId lId = GetSelection(); |
5888ef1e VZ |
1426 | if ( !lId ) |
1427 | return; | |
1428 | ||
721b8397 | 1429 | TreeNode *pNode = (TreeNode *) GetItemData(lId); |
5888ef1e | 1430 | |
a60b1f5d | 1431 | wxCHECK_RET( pNode != NULL, wxT("tree item without data?") ); |
5888ef1e VZ |
1432 | |
1433 | pNode->Refresh(); | |
1434 | } | |
1435 | ||
721b8397 | 1436 | #endif |