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