1 /* 2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2011-2015, Rene Gollent, rene@gollent.com. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include "BreakpointsView.h" 9 10 #include <new> 11 12 #include <Button.h> 13 #include <CheckBox.h> 14 #include <LayoutBuilder.h> 15 16 #include <AutoLocker.h> 17 #include <ObjectList.h> 18 19 #include "MessageCodes.h" 20 #include "Team.h" 21 #include "UserBreakpoint.h" 22 23 24 // #pragma mark - BreakpointsView 25 26 27 BreakpointsView::BreakpointsView(Team* team, Listener* listener) 28 : 29 BGroupView(B_HORIZONTAL, 4.0f), 30 fTeam(team), 31 fListView(NULL), 32 fToggleBreakpointButton(NULL), 33 fEditBreakpointButton(NULL), 34 fRemoveBreakpointButton(NULL), 35 fListener(listener) 36 { 37 SetName("Breakpoints"); 38 } 39 40 41 BreakpointsView::~BreakpointsView() 42 { 43 if (fListView != NULL) 44 fListView->UnsetListener(); 45 } 46 47 48 /*static*/ BreakpointsView* 49 BreakpointsView::Create(Team* team, Listener* listener) 50 { 51 BreakpointsView* self = new BreakpointsView(team, listener); 52 53 try { 54 self->_Init(); 55 } catch (...) { 56 delete self; 57 throw; 58 } 59 60 return self; 61 } 62 63 64 void 65 BreakpointsView::UnsetListener() 66 { 67 fListener = NULL; 68 } 69 70 71 void 72 BreakpointsView::UserBreakpointChanged(UserBreakpoint* breakpoint) 73 { 74 fListView->UserBreakpointChanged(breakpoint); 75 76 _UpdateButtons(); 77 } 78 79 80 void 81 BreakpointsView::WatchpointChanged(Watchpoint* watchpoint) 82 { 83 fListView->WatchpointChanged(watchpoint); 84 85 _UpdateButtons(); 86 } 87 88 89 void 90 BreakpointsView::MessageReceived(BMessage* message) 91 { 92 switch (message->what) { 93 case MSG_ENABLE_BREAKPOINT: 94 case MSG_DISABLE_BREAKPOINT: 95 case MSG_CLEAR_BREAKPOINT: 96 _HandleBreakpointAction(message->what); 97 break; 98 99 case MSG_SHOW_BREAKPOINT_EDIT_WINDOW: 100 message->AddPointer("breakpoint", 101 fSelectedBreakpoints.ItemAt(0)->GetBreakpoint()); 102 Window()->PostMessage(message); 103 break; 104 105 default: 106 BGroupView::MessageReceived(message); 107 break; 108 } 109 } 110 111 112 void 113 BreakpointsView::AttachedToWindow() 114 { 115 fEditBreakpointButton->SetTarget(this); 116 fToggleBreakpointButton->SetTarget(this); 117 fRemoveBreakpointButton->SetTarget(this); 118 } 119 120 121 void 122 BreakpointsView::LoadSettings(const BMessage& settings) 123 { 124 BMessage breakpointListSettings; 125 if (settings.FindMessage("breakpointList", &breakpointListSettings) 126 == B_OK) 127 fListView->LoadSettings(breakpointListSettings); 128 } 129 130 131 status_t 132 BreakpointsView::SaveSettings(BMessage& settings) 133 { 134 BMessage breakpointListSettings; 135 if (fListView->SaveSettings(breakpointListSettings) != B_OK) 136 return B_NO_MEMORY; 137 138 if (settings.AddMessage("breakpointList", &breakpointListSettings) != B_OK) 139 return B_NO_MEMORY; 140 141 return B_OK; 142 } 143 144 145 void 146 BreakpointsView::BreakpointSelectionChanged(BreakpointProxyList& proxies) 147 { 148 if (fListener != NULL) 149 fListener->BreakpointSelectionChanged(proxies); 150 151 _SetSelection(proxies); 152 } 153 154 155 void 156 BreakpointsView::_Init() 157 { 158 BLayoutBuilder::Group<>(this, B_VERTICAL, 0.0f) 159 .Add(fListView = BreakpointListView::Create(fTeam, this, this)) 160 .AddGroup(B_HORIZONTAL, B_USE_SMALL_SPACING) 161 .SetInsets(B_USE_SMALL_SPACING) 162 .AddGlue() 163 .Add(fRemoveBreakpointButton = new BButton("Remove")) 164 .Add(fEditBreakpointButton = new BButton("Edit" B_UTF8_ELLIPSIS)) 165 .Add(fToggleBreakpointButton = new BButton("Toggle")) 166 .End(); 167 168 fToggleBreakpointButton->SetMessage(new BMessage(MSG_ENABLE_BREAKPOINT)); 169 fRemoveBreakpointButton->SetMessage(new BMessage(MSG_CLEAR_BREAKPOINT)); 170 fEditBreakpointButton->SetMessage( 171 new BMessage(MSG_SHOW_BREAKPOINT_EDIT_WINDOW)); 172 173 _UpdateButtons(); 174 } 175 176 177 void 178 BreakpointsView::_UpdateButtons() 179 { 180 AutoLocker<Team> teamLocker(fTeam); 181 182 bool hasEnabled = false; 183 bool hasDisabled = false; 184 bool valid = false; 185 186 for (int32 i = 0; i < fSelectedBreakpoints.CountItems(); i++) { 187 BreakpointProxy* proxy = fSelectedBreakpoints.ItemAt(i); 188 switch (proxy->Type()) { 189 case BREAKPOINT_PROXY_TYPE_BREAKPOINT: 190 { 191 UserBreakpoint* breakpoint = proxy->GetBreakpoint(); 192 if (breakpoint->IsValid()) { 193 valid = true; 194 if (breakpoint->IsEnabled()) 195 hasEnabled = true; 196 else 197 hasDisabled = true; 198 199 } 200 break; 201 } 202 case BREAKPOINT_PROXY_TYPE_WATCHPOINT: 203 { 204 Watchpoint* watchpoint = proxy->GetWatchpoint(); 205 valid = true; 206 if (watchpoint->IsEnabled()) 207 hasEnabled = true; 208 else 209 hasDisabled = true; 210 break; 211 } 212 default: 213 break; 214 } 215 } 216 217 if (valid) { 218 // only allow condition editing if we have a single 219 // actual breakpoint selected. 220 // TODO: allow using this to modify watchpoints as 221 // well. 222 if (fSelectedBreakpoints.CountItems() == 1 223 && fSelectedBreakpoints.ItemAt(0)->Type() 224 == BREAKPOINT_PROXY_TYPE_BREAKPOINT) { 225 fEditBreakpointButton->SetEnabled(true); 226 } else 227 fEditBreakpointButton->SetEnabled(false); 228 229 // if we have at least one disabled breakpoint in the 230 // selection, we leave the button as an Enable button 231 if (hasEnabled && !hasDisabled) { 232 fToggleBreakpointButton->SetLabel("Disable"); 233 fToggleBreakpointButton->SetMessage( 234 new BMessage(MSG_DISABLE_BREAKPOINT)); 235 } else { 236 fToggleBreakpointButton->SetLabel("Enable"); 237 fToggleBreakpointButton->SetMessage( 238 new BMessage(MSG_ENABLE_BREAKPOINT)); 239 } 240 241 fToggleBreakpointButton->SetEnabled(true); 242 fRemoveBreakpointButton->SetEnabled(true); 243 } else { 244 fToggleBreakpointButton->SetLabel("Enable"); 245 fToggleBreakpointButton->SetEnabled(false); 246 fEditBreakpointButton->SetEnabled(false); 247 fRemoveBreakpointButton->SetEnabled(false); 248 } 249 } 250 251 252 void 253 BreakpointsView::_SetSelection(BreakpointProxyList& proxies) 254 { 255 for (int32 i = 0; i < fSelectedBreakpoints.CountItems(); i++) 256 fSelectedBreakpoints.ItemAt(i)->ReleaseReference(); 257 258 fSelectedBreakpoints.MakeEmpty(); 259 260 for (int32 i = 0; i < proxies.CountItems(); i++) { 261 BreakpointProxy* proxy = proxies.ItemAt(i); 262 if (!fSelectedBreakpoints.AddItem(proxy)) 263 return; 264 proxy->AcquireReference(); 265 } 266 267 _UpdateButtons(); 268 } 269 270 271 void 272 BreakpointsView::_HandleBreakpointAction(uint32 action) 273 { 274 if (fListener == NULL) 275 return; 276 277 for (int32 i = 0; i < fSelectedBreakpoints.CountItems(); i++) { 278 BreakpointProxy* proxy = fSelectedBreakpoints.ItemAt(i); 279 if (proxy->Type() == BREAKPOINT_PROXY_TYPE_BREAKPOINT) { 280 UserBreakpoint* breakpoint = proxy->GetBreakpoint(); 281 if (action == MSG_ENABLE_BREAKPOINT && !breakpoint->IsEnabled()) 282 fListener->SetBreakpointEnabledRequested(breakpoint, true); 283 else if (action == MSG_DISABLE_BREAKPOINT 284 && breakpoint->IsEnabled()) { 285 fListener->SetBreakpointEnabledRequested(breakpoint, false); 286 } else if (action == MSG_CLEAR_BREAKPOINT) 287 fListener->ClearBreakpointRequested(breakpoint); 288 } else { 289 Watchpoint* watchpoint = proxy->GetWatchpoint(); 290 if (action == MSG_ENABLE_BREAKPOINT && !watchpoint->IsEnabled()) 291 fListener->SetWatchpointEnabledRequested(watchpoint, true); 292 else if (action == MSG_DISABLE_BREAKPOINT 293 && watchpoint->IsEnabled()) { 294 fListener->SetWatchpointEnabledRequested(watchpoint, false); 295 } else if (action == MSG_CLEAR_BREAKPOINT) 296 fListener->ClearWatchpointRequested(watchpoint); 297 } 298 } 299 } 300 301 302 // #pragma mark - Listener 303 304 305 BreakpointsView::Listener::~Listener() 306 { 307 } 308