Code::Blocks  SVN r11506
debuggermenu.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
3  * http://www.gnu.org/licenses/gpl-3.0.html
4  *
5  * $Revision: 11399 $
6  * $Id: debuggermenu.cpp 11399 2018-05-08 21:54:03Z fuscated $
7  * $HeadURL: https://svn.code.sf.net/p/codeblocks/code/trunk/src/src/debuggermenu.cpp $
8  */
9 #include "sdk.h"
10 
11 #ifndef CB_PRECOMP
12  #include <wx/menu.h>
13  #include <wx/toolbar.h>
14  #include <wx/xrc/xmlres.h>
15 
16  #include "cbeditor.h"
17  #include "cbproject.h"
18  #include "editormanager.h"
19  #include "logmanager.h"
20  #include "projectmanager.h"
21 #endif
22 
23 #include "debuggermenu.h"
24 
25 #include <algorithm>
26 #include <wx/aui/aui.h> // wxAuiManager
27 
28 #include "cbdebugger_interfaces.h"
29 #include "cbstyledtextctrl.h"
30 #include "debuggermanager.h"
31 
32 namespace
33 {
34  const int idMenuDebug = XRCID("idDebuggerMenuDebug");
35  const int idMenuDebugActive = XRCID("idDebuggerMenuActive");
36  const int idMenuDebugActiveTargetsDefault = wxNewId();
37  const int idMenuRunToCursor = XRCID("idDebuggerMenuRunToCursor");
38  const int idMenuSetNextStatement = XRCID("idDebuggerMenuSetNextStatement");
39  const int idMenuNext = XRCID("idDebuggerMenuNext");
40  const int idMenuStep = XRCID("idDebuggerMenuStep");
41  const int idMenuNextInstr = XRCID("idDebuggerMenuNextInstr");
42  const int idMenuStepIntoInstr = XRCID("idDebuggerMenuStepIntoInstr");
43  const int idMenuStepOut = XRCID("idDebuggerMenuStepOut");
44  const int idMenuBreak = XRCID("idDebuggerMenuBreak");
45  const int idMenuStop = XRCID("idDebuggerMenuStop");
46  const int idToolbarStop = XRCID("idDebuggerToolbarStop");
47  const int idMenuToggleBreakpoint = XRCID("idDebuggerMenuToggleBreakpoint");
48  const int idMenuRemoveAllBreakpoints = XRCID("idDebuggerMenuRemoveAllBreakpoints");
49  const int idMenuAddDataBreakpoint = XRCID("idMenuAddDataBreakpoint");
50  const int idMenuSendCommand = XRCID("idDebuggerMenuSendCommand");
51  const int idMenuAddSymbolFile = XRCID("idDebuggerMenuAddSymbolFile");
52  const int idMenuAttachToProcess = XRCID("idDebuggerMenuAttachToProcess");
53  const int idMenuDetach = XRCID("idDebuggerMenuDetach");
54 
55  const long idMenuDebuggingWindows = XRCID("idDebuggingWindows");
56  const long idMenuTools = XRCID("idDebuggerInfo");
57 
58  const int idDebuggerToolInfo = XRCID("idDebuggerToolInfo");
59  const int idDebuggerToolWindows = XRCID("idDebuggerToolWindows");
60 
61  const int idMenuDebuggerAddWatch = wxNewId();
62 
63  inline void HideValueTooltip() { Manager::Get()->GetDebuggerManager()->GetInterfaceFactory()->HideValueTooltip(); }
64 
65  bool Support(cbDebuggerPlugin *plugin, cbDebuggerFeature::Flags flag)
66  {
67  return plugin && plugin->SupportsFeature(flag);
68  }
69 
70  wxMenu* GetMenuById(long menuId, bool recreate = false)
71  {
72  wxMenuBar* mbar = Manager::Get()->GetAppFrame()->GetMenuBar();
73  if (!mbar)
74  return nullptr;
75  wxMenuItem *item = mbar->FindItem(menuId);
76  if (!item)
77  return nullptr;
78  if (recreate)
79  {
80  wxMenu *menu = item->GetMenu();
81  int pos = wxNOT_FOUND;
82  for (size_t ii = 0; ii < menu->GetMenuItemCount(); ++ii)
83  {
84  if (item == menu->FindItemByPosition(ii))
85  {
86  pos = ii;
87  break;
88  }
89  }
90  if (pos != wxNOT_FOUND)
91  {
92  wxMenu *newSubMenu = new wxMenu;
93  wxMenuItem *newItem = new wxMenuItem(menu, item->GetId(), item->GetItemLabelText(), item->GetHelp(),
94  item->GetKind(), newSubMenu);
95  menu->Insert(pos, newItem);
96 
97  menu->Destroy(item);
98  return newItem->GetSubMenu();
99  }
100  }
101  return item ? item->GetSubMenu() : nullptr;
102  }
103 }
104 
105 BEGIN_EVENT_TABLE(DebuggerMenuHandler, wxEvtHandler)
106  // these are different because they are loaded from the XRC
107  EVT_UPDATE_UI(idMenuDebug, DebuggerMenuHandler::OnUpdateUI)
108  EVT_UPDATE_UI(idMenuRunToCursor, DebuggerMenuHandler::OnUpdateUI)
109  EVT_UPDATE_UI(idMenuSetNextStatement, DebuggerMenuHandler::OnUpdateUI)
110  EVT_UPDATE_UI(idMenuNext, DebuggerMenuHandler::OnUpdateUI)
111  EVT_UPDATE_UI(idMenuNextInstr, DebuggerMenuHandler::OnUpdateUI)
112  EVT_UPDATE_UI(idMenuStepIntoInstr, DebuggerMenuHandler::OnUpdateUI)
113  EVT_UPDATE_UI(idMenuStep, DebuggerMenuHandler::OnUpdateUI)
114  EVT_UPDATE_UI(idMenuStepOut, DebuggerMenuHandler::OnUpdateUI)
115  EVT_UPDATE_UI(idMenuBreak, DebuggerMenuHandler::OnUpdateUI)
116  EVT_UPDATE_UI(idMenuStop, DebuggerMenuHandler::OnUpdateUI)
117 
118  EVT_UPDATE_UI(idMenuAttachToProcess, DebuggerMenuHandler::OnUpdateUI)
119  EVT_UPDATE_UI(idMenuDetach, DebuggerMenuHandler::OnUpdateUI)
120 
121  EVT_UPDATE_UI(idMenuTools, DebuggerMenuHandler::OnUpdateUI)
122 
123  EVT_MENU(idMenuDebug, DebuggerMenuHandler::OnStart)
124  EVT_MENU(idMenuBreak, DebuggerMenuHandler::OnBreak)
125  EVT_MENU(idMenuStop, DebuggerMenuHandler::OnStop)
126  EVT_MENU(idMenuNext, DebuggerMenuHandler::OnNext)
127  EVT_MENU(idMenuStep, DebuggerMenuHandler::OnStep)
128  EVT_MENU(idMenuNextInstr, DebuggerMenuHandler::OnNextInstr)
129  EVT_MENU(idMenuStepIntoInstr, DebuggerMenuHandler::OnStepIntoInstr)
130  EVT_MENU(idMenuStepOut, DebuggerMenuHandler::OnStepOut)
131  EVT_MENU(idMenuRunToCursor, DebuggerMenuHandler::OnRunToCursor)
132  EVT_MENU(idMenuSetNextStatement, DebuggerMenuHandler::OnSetNextStatement)
133  EVT_MENU(idMenuToggleBreakpoint, DebuggerMenuHandler::OnToggleBreakpoint)
134  EVT_MENU(idMenuRemoveAllBreakpoints, DebuggerMenuHandler::OnRemoveAllBreakpoints)
135  EVT_MENU(idMenuAddDataBreakpoint, DebuggerMenuHandler::OnAddDataBreakpoint)
136  EVT_MENU(idMenuSendCommand, DebuggerMenuHandler::OnSendCommand)
137 
138  EVT_MENU(idMenuDebuggerAddWatch, DebuggerMenuHandler::OnAddWatch)
139  EVT_MENU(idMenuAttachToProcess, DebuggerMenuHandler::OnAttachToProcess)
140  EVT_MENU(idMenuDetach, DebuggerMenuHandler::OnDetachFromProcess)
141  EVT_MENU(idMenuDebugActiveTargetsDefault, DebuggerMenuHandler::OnActiveDebuggerTargetsDefaultClick)
142 END_EVENT_TABLE()
143 
144 
146  m_activeDebugger(nullptr),
147  m_disableContinue(false)
148 {
149 }
150 
151 namespace
152 {
153 template<typename DlgType>
154 struct CommonItem : cbDebuggerWindowMenuItem
155 {
156  typedef DlgType* (DebuggerManager::*GetWindowFunc)();
157  CommonItem(cbDebuggerFeature::Flags enableFeature, cbDebuggerPlugin::DebugWindows requestUpdate, GetWindowFunc func) :
158  m_enableFeature(enableFeature),
159  m_requestUpdate(requestUpdate),
160  m_getWindowFunc(func)
161  {}
162 
163  void OnClick(bool enable) override
164  {
167  DlgType *dialog = (manager->*(m_getWindowFunc))();
168  if (dialog)
169  {
170  evt.pWindow = dialog->GetWindow();
171  Manager::Get()->ProcessEvent(evt);
172  }
173 
174  if (enable && manager->GetActiveDebugger())
175  manager->GetActiveDebugger()->RequestUpdate(m_requestUpdate);
176  }
177  bool IsEnabled() override
178  {
179  return Support(Manager::Get()->GetDebuggerManager()->GetActiveDebugger(), m_enableFeature);
180  }
181  bool IsChecked() override
182  {
183  DlgType *dialog = (Manager::Get()->GetDebuggerManager()->*(m_getWindowFunc))();
184  return dialog && IsWindowReallyShown(dialog->GetWindow());
185  }
186 private:
187  cbDebuggerFeature::Flags m_enableFeature;
188  cbDebuggerPlugin::DebugWindows m_requestUpdate;
189  GetWindowFunc m_getWindowFunc;
190 };
191 
192 template<typename DlgType>
193 CommonItem<DlgType>* MakeItem(cbDebuggerFeature::Flags enableFeature,
194  cbDebuggerPlugin::DebugWindows requestUpdate,
195  DlgType* (DebuggerManager::*func)())
196 {
197  return new CommonItem<DlgType>(enableFeature, requestUpdate, func);
198 }
199 
200 }
201 
203 {
204  struct Breakpoints : cbDebuggerWindowMenuItem
205  {
206  void OnClick(bool enable) override
207  {
210  if (dialog)
211  {
212  evt.pWindow = dialog->GetWindow();
213  Manager::Get()->ProcessEvent(evt);
214  }
215  }
216  bool IsEnabled() override
217  {
219  }
220  bool IsChecked() override
221  {
223  return dialog && IsWindowReallyShown(dialog->GetWindow());
224  }
225  };
226  struct Watches : CommonItem<cbWatchesDlg>
227  {
228  Watches() :
230  {
231  }
232  bool IsEnabled() override
233  {
235  }
236  };
237 
238  RegisterWindowMenu(_("Breakpoints"), _("Edit breakpoints"), new Breakpoints);
239  RegisterWindowMenu(_("Watches"), _("Watch variables"), new Watches);
240  RegisterWindowMenu(_("Call stack"), _("Displays the current call stack"),
243  RegisterWindowMenu(_("CPU Registers"), _("Display the CPU registers"),
246  RegisterWindowMenu(_("Disassembly"), _("Disassembles the current stack frame"),
249  RegisterWindowMenu(_("Memory dump"), _("Displays the contents of a memory location"),
252  RegisterWindowMenu(_("Running threads"),
253  _("Displays the currently running threads and allows switching between them"),
256 }
257 
259 {
260  for (WindowMenuItemsMap::iterator it = m_windowMenuItems.begin(); it != m_windowMenuItems.end(); ++it)
261  {
262  if (it->second.name == name)
263  {
264  wxString msg = wxString::Format(_("Duplicate debugger window name '%s'. Igrnoring it."), name.wx_str());
266  delete item;
267  return false;
268  }
269  }
270 
271  WindowMenuItem i;
272  i.item = cb::shared_ptr<cbDebuggerWindowMenuItem>(item);
273  i.name = name;
274  i.help = help;
275  long id = wxNewId();
276 
277  m_windowMenuItems[id] = i;
278 
279  Connect(id, wxEVT_UPDATE_UI, wxObjectEventFunction(&DebuggerMenuHandler::OnWindowMenuItemUpdateUI));
280  Connect(id, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(DebuggerMenuHandler::OnWindowMenuItemClicked));
281  return true;
282 }
283 
285 {
286  for (WindowMenuItemsMap::iterator it = m_windowMenuItems.begin(); it != m_windowMenuItems.end(); ++it)
287  {
288  if (it->second.name == name)
289  {
290  Disconnect(it->first, wxEVT_UPDATE_UI);
291  Disconnect(it->first, wxEVT_COMMAND_MENU_SELECTED);
292 
293  m_windowMenuItems.erase(it);
294  return;
295  }
296  }
297 }
298 
300 {
301  WindowMenuItemsMap::iterator it = m_windowMenuItems.find(event.GetId());
302  if (it != m_windowMenuItems.end())
303  {
304  event.Check(it->second.item->IsChecked());
305  event.Enable(it->second.item->IsEnabled());
306  }
307 }
308 
310 {
311  WindowMenuItemsMap::iterator it = m_windowMenuItems.find(event.GetId());
312  if (it != m_windowMenuItems.end())
313  it->second.item->OnClick(event.IsChecked());
314 }
315 
317 {
318  std::map<wxString, long> sortedNames;
319 
320  for (WindowMenuItemsMap::iterator it = m_windowMenuItems.begin(); it != m_windowMenuItems.end(); ++it)
321  sortedNames[it->second.name] = it->first;
322 
323  for (std::map<wxString, long>::iterator it = sortedNames.begin(); it != sortedNames.end(); ++it)
324  menu.AppendCheckItem(it->second, it->first, m_windowMenuItems[it->second].help);
325 }
326 
328 {
329  m_activeDebugger = active;
330 }
331 
333 {
334  wxMenu *menu = GetMenuById(idMenuDebugActive);
335  if (!menu)
336  return;
337  wxMenuItem *item = menu->FindItem(idMenuDebugActiveTargetsDefault);
338  if (item)
339 #if wxCHECK_VERSION(3, 0, 0)
340  item->SetItemLabel(valid ? _("Target's default") : _("Target's default (invalid)"));
341 #else
342  item->SetText(valid ? _("Target's default") : _("Target's default (invalid)"));
343 #endif
344 }
345 
347 {
348  wxMenu *menuWindows = GetMenuById(idMenuDebuggingWindows, true);
349  if (menuWindows)
350  AppendWindowMenuItems(*menuWindows);
351  if (m_activeDebugger)
352  {
353  wxMenu *menuTools = GetMenuById(idMenuTools, true);
354  if (menuTools)
355  m_activeDebugger->SetupToolsMenu(*menuTools);
356  }
357 
359  wxMenu *menu = GetMenuById(idMenuDebugActive, true);
360  if (!menu)
361  return;
362 
363  menu->AppendRadioItem(idMenuDebugActiveTargetsDefault, _("Target's default"),
364  _("Use the debugger associated with the compiler for the active target"));
365 
366  const DebuggerManager::RegisteredPlugins &allDebugger = dbgManager->GetAllDebuggers();
367  for (DebuggerManager::RegisteredPlugins::const_iterator it = allDebugger.begin(); it != allDebugger.end(); ++it)
368  {
369  const DebuggerManager::ConfigurationVector &configs = it->second.GetConfigurations();
370  for (DebuggerManager::ConfigurationVector::const_iterator itConf = configs.begin(); itConf != configs.end(); ++itConf)
371  {
372  long id = (*itConf)->GetMenuId();
373  if (id == wxID_ANY)
374  {
375  id = wxNewId();
376  (*itConf)->SetMenuId(id);
377  }
378 
379  menu->AppendRadioItem(id, it->first->GetGUIName() + wxT(": ") + (*itConf)->GetName());
380  Connect(id, -1, wxEVT_COMMAND_MENU_SELECTED,
381  (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction)
383  }
384  }
385 
386  if (m_activeDebugger && !dbgManager->IsActiveDebuggerTargetsDefault())
387  {
388  DebuggerManager::RegisteredPlugins::const_iterator it = allDebugger.find(m_activeDebugger);
389  cbAssert(it != allDebugger.end());
390 
391  const DebuggerManager::ConfigurationVector &configs = it->second.GetConfigurations();
392 
393  DebuggerManager::ConfigurationVector::const_iterator itConf = configs.begin();
394  std::advance(itConf, m_activeDebugger->GetIndexOfActiveConfig());
395 
396  if (itConf != configs.end())
397  menu->Check((*itConf)->GetMenuId(), true);
398  else
399  menu->Check(configs.front()->GetMenuId(), true);
400  }
401  else
402  menu->Check(idMenuDebugActiveTargetsDefault, true);
403 }
404 
405 void DebuggerMenuHandler::BuildContextMenu(wxMenu &menu, const wxString& word_at_caret, bool is_running)
406 {
408  if (!plugin)
409  return;
410 
411  PluginManager *pluginManager = Manager::Get()->GetPluginManager();
412 
413  int initialItem;
414  if (is_running)
415  {
416  // we want debugger menu items to be at the top when debugging
417  initialItem = pluginManager->GetFindMenuItemFirst();
418  }
419  else
420  initialItem = pluginManager->GetFindMenuItemFirst() + pluginManager->GetFindMenuItemCount();
421  int item = initialItem;
422 
423  // Insert Run to Cursor
425  menu.Insert(item++, idMenuRunToCursor, _("Run to cursor"));
426  if (is_running)
427  {
429  menu.Insert(item++, idMenuSetNextStatement, _("Set next statement"));
430  if (item > 0)
431  menu.InsertSeparator(item++);
432  if (!word_at_caret.empty())
433  {
435  menu.Insert(item++, idMenuDebuggerAddWatch, wxString::Format(_("Watch '%s'"), word_at_caret.c_str()));
436  // data breakpoint
438  {
439  menu.Insert(item++, idMenuAddDataBreakpoint,
440  wxString::Format(_("Add data breakpoint for '%s'"), word_at_caret.c_str()));
441  }
442  }
443  }
444  // Insert toggle breakpoint
446  menu.Insert(item++, idMenuToggleBreakpoint, _("Toggle breakpoint"));
447  if (item > 0)
448  menu.InsertSeparator(item++);
449 
450  if (is_running)
451  pluginManager->RegisterFindMenuItems(true, item - initialItem);
452 }
453 
455 {
457  bool en = false, stopped = false, isRunning = false, isAttached = false;
458 
459  if (m_activeDebugger)
460  {
461  isAttached = m_activeDebugger->IsAttachedToProcess();
462  en = (prj && !prj->GetCurrentlyCompilingTarget()) || isAttached;
463  stopped = m_activeDebugger->IsStopped() && !m_activeDebugger->IsBusy();
464  isRunning = m_activeDebugger->IsRunning();
465  }
466 
468  wxMenuBar* mbar = Manager::Get()->GetAppFrame()->GetMenuBar();
469  cbPlugin *runningPlugin = Manager::Get()->GetProjectManager()->GetIsRunning();
470 
471  bool otherPlugin = false;
472  if (runningPlugin != NULL && runningPlugin != m_activeDebugger)
473  {
474  en = false;
475  otherPlugin = true;
476  }
477 
478  if (mbar && Manager::Get()->GetDebuggerManager()->HasMenu())
479  {
480  bool hasBreaks = Support(m_activeDebugger, cbDebuggerFeature::Breakpoints);
481 
482  mbar->Enable(idMenuDebug, (!isRunning || stopped) && en);
483  mbar->Enable(idMenuNext, isRunning && en && stopped);
484  mbar->Enable(idMenuNextInstr, isRunning && en && stopped);
485  mbar->Enable(idMenuStepIntoInstr, isRunning && en && stopped);
486  mbar->Enable(idMenuStep, en && stopped);
487  mbar->Enable(idMenuStepOut, isRunning && en && stopped);
488  mbar->Enable(idMenuRunToCursor,
489  en && ed && stopped && Support(m_activeDebugger, cbDebuggerFeature::RunToCursor));
490  mbar->Enable(idMenuSetNextStatement,
491  en && ed && stopped && isRunning && Support(m_activeDebugger, cbDebuggerFeature::SetNextStatement));
492  mbar->Enable(idMenuToggleBreakpoint, ed && m_activeDebugger && hasBreaks);
493  mbar->Enable(idMenuRemoveAllBreakpoints, m_activeDebugger && hasBreaks);
494  mbar->Enable(idMenuSendCommand, isRunning && stopped);
495  mbar->Enable(idMenuAddSymbolFile, isRunning && stopped);
496  mbar->Enable(idMenuStop, isRunning && en);
497  mbar->Enable(idMenuBreak, isRunning && !stopped && en);
498  mbar->Enable(idMenuAttachToProcess, !isRunning && !otherPlugin && m_activeDebugger);
499  mbar->Enable(idMenuDetach, isRunning && stopped && isAttached);
500 
501  wxMenu *activeMenu = GetMenuById(idMenuDebugActive);
502  if (activeMenu)
503  {
504  for (size_t ii = 0; ii < activeMenu->GetMenuItemCount(); ++ii)
505  activeMenu->Enable(activeMenu->FindItemByPosition(ii)->GetId(), !isRunning);
506  }
507 
508  mbar->Enable(idMenuTools, m_activeDebugger && m_activeDebugger->ToolMenuEnabled());
509  }
510 
511  // allow other UpdateUI handlers to process this event
512  // *very* important! don't forget it...
513  event.Skip();
514 }
515 
517 {
519  const DebuggerManager::RegisteredPlugins &allDebuggers = dbgManager->GetAllDebuggers();
520  DebuggerManager::RegisteredPlugins::const_iterator it = allDebuggers.find(m_activeDebugger);
521  wxString configName;
522  if (it != allDebuggers.end())
523  {
524  cbDebuggerConfiguration &config = m_activeDebugger->GetActiveConfig();
525  configName = it->first->GetGUIName() + wxT(":") + config.GetName();
526  }
527  m_activeDebugger->Log(_("Active debugger config: ") + configName);
528 }
529 
531 {
532  cbAssert(m_activeDebugger);
533  if (!m_activeDebugger->IsRunning())
534  {
535  m_disableContinue = true;
536 
538  if (manager->GetIsRunning() == nullptr)
539  {
540  manager->SetIsRunning(m_activeDebugger);
541 
542  m_activeDebugger->ClearLog();
543  LogActiveConfig();
544 
545  if (!m_activeDebugger->Debug(false))
546  manager->SetIsRunning(nullptr);
547  }
548  m_disableContinue = false;
549  }
550  else if (m_activeDebugger->IsStopped() && !m_disableContinue)
551  {
552  HideValueTooltip();
553  m_activeDebugger->Continue();
554  }
555 }
556 
558 {
559  cbAssert(m_activeDebugger);
560  HideValueTooltip();
561  m_activeDebugger->Break();
562 }
563 
565 {
566  cbAssert(m_activeDebugger);
567  HideValueTooltip();
568  m_activeDebugger->Stop();
569 }
570 
572 {
573  cbAssert(m_activeDebugger);
574  if(!m_disableContinue)
575  {
576  HideValueTooltip();
577  m_activeDebugger->Continue();
578  }
579 }
580 
582 {
583  cbAssert(m_activeDebugger);
584  HideValueTooltip();
585  m_activeDebugger->Next();
586 }
587 
589 {
590  cbAssert(m_activeDebugger);
591  HideValueTooltip();
592  m_activeDebugger->NextInstruction();
593 }
594 
596 {
597  cbAssert(m_activeDebugger);
598  HideValueTooltip();
599  m_activeDebugger->StepIntoInstruction();
600 }
601 
603 {
604  cbAssert(m_activeDebugger);
605  if (m_activeDebugger->IsRunning())
606  {
607  if(!m_disableContinue)
608  {
609  HideValueTooltip();
610  m_activeDebugger->Step();
611  }
612  }
613  else
614  {
615  m_disableContinue = true;
617  if (manager->GetIsRunning() == nullptr)
618  {
619  manager->SetIsRunning(m_activeDebugger);
620  m_activeDebugger->ClearLog();
621  LogActiveConfig();
622 
623  if (!m_activeDebugger->Debug(true))
624  manager->SetIsRunning(nullptr);
625  }
626  m_disableContinue = false;
627  }
628 }
629 
631 {
632  cbAssert(m_activeDebugger);
633  HideValueTooltip();
634  m_activeDebugger->StepOut();
635 }
636 
638 {
639  cbAssert(m_activeDebugger);
641  if (!ed)
642  return;
643  const wxString &line_text = ed->GetControl()->GetLine(ed->GetControl()->GetCurrentLine());
644 
646  if (manager->GetIsRunning() == nullptr || manager->GetIsRunning() == m_activeDebugger)
647  {
648  manager->SetIsRunning(m_activeDebugger);
649  if (!m_activeDebugger->IsRunning())
650  {
651  m_activeDebugger->ClearLog();
652  LogActiveConfig();
653  }
654  HideValueTooltip();
655  if (!m_activeDebugger->RunToCursor(ed->GetFilename(), ed->GetControl()->GetCurrentLine() + 1, line_text))
656  manager->SetIsRunning(nullptr);
657  }
658 }
659 
661 {
662  cbAssert(m_activeDebugger);
664  if (!ed)
665  return;
666  HideValueTooltip();
667  m_activeDebugger->SetNextStatement(ed->GetFilename(), ed->GetControl()->GetCurrentLine() + 1);
668 }
669 
671 {
672  cbAssert(m_activeDebugger);
674  if (!ed)
675  return;
676  ed->ToggleBreakpoint();
677 }
678 
680 {
681  cbAssert(m_activeDebugger);
683 }
684 
686 {
687  cbAssert(m_activeDebugger);
688  const wxString& word_at_caret = m_activeDebugger->GetEditorWordAtCaret();
689  if (!word_at_caret.empty())
690  {
691  if (m_activeDebugger->AddDataBreakpoint(word_at_caret))
693  }
694 }
695 
697 {
698  cbAssert(m_activeDebugger);
699  wxString pidStr = cbGetTextFromUser(_("PID to attach to:"));
700  if (!pidStr.empty())
701  {
702  m_activeDebugger->AttachToProcess(pidStr);
703  }
704 }
705 
707 {
708  cbAssert(m_activeDebugger);
709  m_activeDebugger->DetachFromProcess();
710 }
711 
713 {
714  cbAssert(m_activeDebugger);
715  wxString cmd = cbGetTextFromUser(_("Enter command for Debugger:"), _("Send command to Debugger:"), m_lastCommand);
716  if (cmd.IsEmpty())
717  return;
718 
719  m_activeDebugger->SendCommand(cmd, false);
720  m_lastCommand = cmd;
721 }
722 
724 {
725  if (!m_activeDebugger)
726  return;
727 
728  wxString const &src = m_activeDebugger->GetEditorWordAtCaret();
729  if (!src.empty())
730  {
731  cb::shared_ptr<cbWatch> watch = m_activeDebugger->AddWatch(src);
732  if (watch.get())
733  {
735  dialog->AddWatch(watch);
736  if (!IsWindowReallyShown(dialog->GetWindow()))
737  {
739  evt.pWindow = dialog->GetWindow();
740  Manager::Get()->ProcessEvent(evt);
741  }
742  }
743  }
744 }
745 
747 {
749  const DebuggerManager::RegisteredPlugins &plugins = manager->GetAllDebuggers();
750 
751  for(DebuggerManager::RegisteredPlugins::const_iterator it = plugins.begin(); it != plugins.end(); ++it)
752  {
753  const DebuggerManager::ConfigurationVector &configs = it->second.GetConfigurations();
754  for (DebuggerManager::ConfigurationVector::const_iterator itConf = configs.begin(); itConf != configs.end(); ++itConf)
755  {
756  if((*itConf)->GetMenuId() == event.GetId())
757  {
758  manager->SetActiveDebugger(it->first, itConf);
759  return;
760  }
761  }
762  }
763 }
764 
766 {
768 }
769 
770 
771 BEGIN_EVENT_TABLE(DebuggerToolbarHandler, wxEvtHandler)
772  // these are different because they are loaded from the XRC
773  EVT_UPDATE_UI(idMenuDebug, DebuggerToolbarHandler::OnUpdateUI)
774  EVT_UPDATE_UI(idMenuRunToCursor, DebuggerToolbarHandler::OnUpdateUI)
775  EVT_UPDATE_UI(idMenuNext, DebuggerToolbarHandler::OnUpdateUI)
776  EVT_UPDATE_UI(idMenuNextInstr, DebuggerToolbarHandler::OnUpdateUI)
777  EVT_UPDATE_UI(idMenuStepIntoInstr, DebuggerToolbarHandler::OnUpdateUI)
778  EVT_UPDATE_UI(idMenuStep, DebuggerToolbarHandler::OnUpdateUI)
779  EVT_UPDATE_UI(idMenuStepOut, DebuggerToolbarHandler::OnUpdateUI)
780  EVT_UPDATE_UI(idMenuBreak, DebuggerToolbarHandler::OnUpdateUI)
781  EVT_UPDATE_UI(idToolbarStop, DebuggerToolbarHandler::OnUpdateUI)
782 
783  EVT_MENU(idDebuggerToolInfo, DebuggerToolbarHandler::OnToolInfo)
784  EVT_MENU(idDebuggerToolWindows, DebuggerToolbarHandler::OnDebugWindows)
785  EVT_MENU(idToolbarStop, DebuggerToolbarHandler::OnStop)
786 END_EVENT_TABLE()
787 
789  m_Toolbar(nullptr),
790  m_menuHandler(menuHandler)
791 {
792 }
793 
795 {
796  if (!m_Toolbar)
797  {
798  if (!create)
799  return nullptr;
800 
801  m_Toolbar = Manager::Get()->CreateEmptyToolbar();
802  wxString my_16x16 = Manager::isToolBar16x16(m_Toolbar) ? _T("_16x16") : _T("");
803  Manager::AddonToolBar(m_Toolbar, wxString(_T("debugger_toolbar")) + my_16x16);
804 
805  m_Toolbar->Realize();
806  m_Toolbar->SetInitialSize();
807  }
808  return m_Toolbar;
809 }
810 
812 {
815 
816  bool en = false;
817  bool stopped = false, isRunning = false;
818 
819  if (plugin)
820  {
821  cbProject* prj = manager->GetActiveProject();
822  en = (prj && !prj->GetCurrentlyCompilingTarget()) || plugin->IsAttachedToProcess();
823  stopped = plugin->IsStopped();
824  isRunning = plugin->IsRunning();
825  }
826 
827  if (m_Toolbar)
828  {
830 
831  cbPlugin *runningPlugin = manager->GetIsRunning();
832  if (runningPlugin != NULL && runningPlugin != plugin)
833  en = false;
834 
835  m_Toolbar->EnableTool(idMenuDebug, (!isRunning || stopped) && en);
836  m_Toolbar->EnableTool(idMenuRunToCursor, en && ed && stopped);
837  m_Toolbar->EnableTool(idMenuNext, isRunning && en && stopped);
838  m_Toolbar->EnableTool(idMenuNextInstr, isRunning && en && stopped);
839  m_Toolbar->EnableTool(idMenuStepIntoInstr, isRunning && en && stopped);
840  m_Toolbar->EnableTool(idMenuStep, en && stopped);
841  m_Toolbar->EnableTool(idMenuStepOut, isRunning && en && stopped);
842  m_Toolbar->EnableTool(idToolbarStop, isRunning && en);
843  m_Toolbar->EnableTool(idMenuBreak, isRunning && !stopped && en);
844  m_Toolbar->EnableTool(idDebuggerToolInfo, plugin && plugin->ToolMenuEnabled());
845  }
846 
847  // allow other UpdateUI handlers to process this event
848  // *very* important! don't forget it...
849  event.Skip();
850 }
851 
853 {
855  if (plugin)
856  {
857  wxMenu menu;
858  plugin->SetupToolsMenu(menu);
859  Manager::Get()->GetAppWindow()->PopupMenu(&menu);
860  }
861 }
862 
864 {
865  wxMenu m;
866  m_menuHandler->AppendWindowMenuItems(m);
867  Manager::Get()->GetAppWindow()->PopupMenu(&m);
868 }
869 
871 {
873  cbDebuggerPlugin *plugin = manager->GetActiveDebugger();
874  if (!plugin)
875  return;
876 
877  if (plugin->IsAttachedToProcess())
878  {
879  wxMenu m;
880 
881  if (plugin->IsStopped())
882  m.Append(idMenuDetach, _("Detach"));
883  else
884  {
885  wxMenuItem *detach_item = m.Append(idMenuDetach, _("Detach (debugger is running)"));
886  detach_item->Enable(false);
887  }
888 
889  m.Append(idMenuStop, _("Stop debugger (kills the debuggee)"));
890 
891  Manager::Get()->GetAppWindow()->PopupMenu(&m);
892  }
893  else
894  {
895  wxCommandEvent event2(wxEVT_COMMAND_TOOL_CLICKED, idMenuStop);
896  m_Toolbar->GetEventHandler()->ProcessEvent(event2);
897  }
898 }
Base class for plugins.
Definition: cbplugin.h:84
cbDebuggerPlugin * GetActiveDebugger()
void OnWindowMenuItemUpdateUI(wxUpdateUIEvent &event)
void OnRemoveAllBreakpoints(wxCommandEvent &event)
int wxNewId()
PluginManager * GetPluginManager() const
Definition: manager.cpp:444
cbExamineMemoryDlg * GetExamineMemoryDialog()
Returns a pointer to the memory dialog.
EVTIMPORT const wxEventType cbEVT_HIDE_DOCK_WINDOW
Definition: sdk_events.cpp:132
void OnDetachFromProcess(wxCommandEvent &event)
void OnActiveDebuggerClick(wxCommandEvent &event)
void SetIsRunning(cbPlugin *plugin)
This method should be called when the applications is started by a plugin.
Base class for debugger plugins.
Definition: cbplugin.h:397
static Manager * Get()
Use Manager::Get() to get a pointer to its instance Manager::Get() is guaranteed to never return an i...
Definition: manager.cpp:182
wxMenuItem * FindItemByPosition(size_t position) const
void OnWindowMenuItemClicked(wxCommandEvent &event)
void OnUpdateUI(wxUpdateUIEvent &event)
void OnStart(wxCommandEvent &event)
void OnAddWatch(wxCommandEvent &event)
wxMenuItem * InsertSeparator(size_t pos)
void OnStop(wxCommandEvent &event)
void OnRunToCursor(wxCommandEvent &event)
void OnAddDataBreakpoint(wxCommandEvent &event)
virtual void BuildContextMenu(wxMenu &menu, const wxString &word_at_caret, bool is_running)
void OnBreak(wxCommandEvent &event)
void Enable(int id, bool enable)
DLLIMPORT wxString cbGetTextFromUser(const wxString &message, const wxString &caption=cbGetTextFromUserPromptStr, const wxString &default_value=wxEmptyString, wxWindow *parent=NULL, int x=wxDefaultCoord, int y=wxDefaultCoord, bool centre=true)
Definition: globals.cpp:1465
wxWindow * pWindow
The window to dock.
Definition: sdk_events.h:137
void OnStep(wxCommandEvent &event)
virtual void SetItemLabel(const wxString &label)
virtual void Reload()=0
void OnStop(wxCommandEvent &event)
const wxString & GetName() const
Event used to request from the main app to add a window to the docking system.
Definition: sdk_events.h:83
static void AddonToolBar(wxToolBar *toolBar, wxString resid)
Definition: manager.cpp:405
wxCStrData c_str() const
cbCPURegistersDlg * GetCPURegistersDialog()
Returns a pointer to the CPU registers dialog.
wxMenuItem * Append(int id, const wxString &item=wxEmptyString, const wxString &helpString=wxEmptyString, wxItemKind kind=wxITEM_NORMAL)
wxString GetLine(int line) const
Retrieve the contents of a line.
#define _T(string)
const wxString & GetHelp() const
virtual bool IsEnabled()=0
void SetTargetsDefaultAsActiveDebugger()
void OnContinue(wxCommandEvent &event)
void OnNextInstr(wxCommandEvent &event)
static bool isToolBar16x16(wxToolBar *toolBar)
Definition: manager.cpp:412
virtual void RebuildMenus()
#define wxT(string)
#define wxNOT_FOUND
ProjectBuildTarget * GetCurrentlyCompilingTarget()
Get a pointer to the currently compiling target.
Definition: cbproject.h:478
size_t GetMenuItemCount() const
bool empty() const
bool Destroy(int id)
wxWindow * GetAppWindow() const
Definition: manager.cpp:424
void OnToggleBreakpoint(wxCommandEvent &event)
void OnSetNextStatement(wxCommandEvent &event)
EditorManager * GetEditorManager() const
Definition: manager.cpp:434
virtual bool IsChecked()=0
wxItemKind GetKind() const
virtual void Enable(bool enable=true)
ProjectManager * GetProjectManager() const
Functions returning pointers to the respective sub-manager instances.
Definition: manager.cpp:429
PluginManager manages plugins.
Definition: pluginmanager.h:76
virtual wxString GetItemLabelText() const
DebuggerManager * GetDebuggerManager() const
Definition: manager.cpp:484
virtual const wxString & GetFilename() const
Get the editor&#39;s filename (if applicable).
Definition: editorbase.h:45
void OnDebugWindows(wxCommandEvent &event)
virtual void MarkActiveTargetAsValid(bool valid)
Represents a Code::Blocks project.
Definition: cbproject.h:96
void Check(int id, bool check)
int GetCurrentLine()
Manually declared methods.
cbStyledTextCtrl * GetControl() const
Returns a pointer to the underlying cbStyledTextCtrl object (which itself is the wxWindows implementa...
Definition: cbeditor.cpp:842
cbPlugin * GetIsRunning() const
Return a pointer to the plugin which is running the application.
void OnToolInfo(wxCommandEvent &event)
cbDisassemblyDlg * GetDisassemblyDialog()
Returns a pointer to the disassembly dialog.
bool IsActiveDebuggerTargetsDefault() const
wxFrame * GetAppFrame() const
Definition: manager.cpp:419
int GetId() const
cbThreadsDlg * GetThreadsDialog()
Returns a pointer to the threads dialog.
cbEditor * GetBuiltinActiveEditor()
Definition: editormanager.h:95
void OnNext(wxCommandEvent &event)
cbWatchesDlg * GetWatchesDialog()
Returns a pointer to the watches dialog.
LogManager * GetLogManager() const
Definition: manager.cpp:439
DLLIMPORT bool IsWindowReallyShown(wxWindow *win)
Finds out if a window is really shown.
Definition: globals.cpp:931
cbProject * GetActiveProject()
Retrieve the active project.
wxMenu * GetMenu() const
const wxStringCharType * wx_str() const
virtual wxMenuItem * FindItem(int id, wxMenu **menu=NULL) const
virtual void HideValueTooltip()=0
virtual void AddWatch(cb::shared_ptr< cbWatch > watch)=0
cb::shared_ptr< cbDebuggerWindowMenuItem > item
Definition: debuggermenu.h:66
void RegisterDefaultWindowItems()
const wxString & _(const wxString &string)
void OnSendCommand(wxCommandEvent &event)
std::map< cbDebuggerPlugin *, PluginData > RegisteredPlugins
#define cbAssert(expr)
Definition: cbexception.h:48
void AppendWindowMenuItems(wxMenu &menu)
virtual wxWindow * GetWindow()=0
void OnStepOut(wxCommandEvent &event)
void OnActiveDebuggerTargetsDefaultClick(wxCommandEvent &event)
virtual void UnregisterWindowMenu(const wxString &name)
virtual void OnClick(bool enable)=0
virtual void SetupToolsMenu(wxMenu &menu)=0
A file editor.
Definition: cbeditor.h:43
virtual int FindItem(const wxString &itemString) const
bool IsEmpty() const
virtual bool ToolMenuEnabled() const
Definition: cbplugin.cpp:258
RegisteredPlugins const & GetAllDebuggers() const
The entry point singleton for working with projects.
void OnAttachToProcess(wxCommandEvent &event)
virtual wxWindow * GetWindow()=0
virtual void RemoveAllBreakpoints()=0
cbBacktraceDlg * GetBacktraceDialog()
cbBreakpointsDlg * GetBreakpointDialog()
Returns a pointer to the breakpoints dialog.
virtual void SetText(const wxString &text)
EVTIMPORT const wxEventType cbEVT_SHOW_DOCK_WINDOW
Definition: sdk_events.cpp:131
int GetFindMenuItemFirst() const
Returns the position of the first menu item in the find group.
void DebugLog(const wxString &msg, Logger::level lv=Logger::info)
Definition: logmanager.h:146
bool ProcessEvent(CodeBlocksEvent &event)
Definition: manager.cpp:246
void RegisterFindMenuItems(bool before, int count)
Can be called by plugins&#39; BuildModuleMenu when building the EditorManager&#39;s context menu...
virtual bool RegisterWindowMenu(const wxString &name, const wxString &help, cbDebuggerWindowMenuItem *item)
virtual void SetActiveDebugger(cbDebuggerPlugin *active)
virtual bool IsRunning() const =0
Is the plugin currently debugging?
wxToolBar * GetToolbar(bool create=true)
std::vector< cbDebuggerConfiguration * > ConfigurationVector
virtual void ToggleBreakpoint(int line=-1, bool notifyDebugger=true)
Toggle debugger breakpoint at specified line.
Definition: cbeditor.cpp:2322
void SetActiveDebugger(cbDebuggerPlugin *activeDebugger, ConfigurationVector::const_iterator config)
wxMenuItem * AppendRadioItem(int id, const wxString &item, const wxString &help=wxEmptyString)
virtual bool SupportsFeature(cbDebuggerFeature::Flags flag)=0
wxMenu * GetSubMenu() const
wxEventType wxEVT_UPDATE_UI
virtual bool IsStopped() const =0
Is the plugin stopped on breakpoint?
int GetFindMenuItemCount() const
Returns the number of items in the find group already added to the menu.
#define NULL
Definition: prefix.cpp:59
static wxString Format(const wxString &format,...)
void Enable(int id, bool enable)
wxToolBar * CreateEmptyToolbar()
Definition: manager.cpp:394
virtual void RequestUpdate(DebugWindows window)=0
wxMenuItem * Insert(size_t pos, wxMenuItem *menuItem)
cbDebugInterfaceFactory * GetInterfaceFactory()
virtual bool IsAttachedToProcess() const =0
void OnUpdateUI(wxUpdateUIEvent &event)
void OnStepIntoInstr(wxCommandEvent &event)
wxMenuItem * AppendCheckItem(int id, const wxString &item, const wxString &help=wxEmptyString)