1 /* 2 * Copyright 2009, Ingo Weinhold, ingo_weinhold@gmx.de. 3 * Copyright 2011-2016, 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 "AppMessageCodes.h" 20 #include "MessageCodes.h" 21 #include "Team.h" 22 #include "UserBreakpoint.h" 23 24 25 // #pragma mark - BreakpointsView 26 27 28 BreakpointsView::BreakpointsView(Team* team, Listener* listener) 29 : 30 BGroupView(B_HORIZONTAL, 4.0f), 31 fTeam(team), 32 fListView(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 fEditBreakpointButton->SetTarget(this); 117 fToggleBreakpointButton->SetTarget(this); 118 fRemoveBreakpointButton->SetTarget(this); 119 } 120 121 122 void 123 BreakpointsView::LoadSettings(const BMessage& settings) 124 { 125 BMessage breakpointListSettings; 126 if (settings.FindMessage("breakpointList", &breakpointListSettings) 127 == B_OK) 128 fListView->LoadSettings(breakpointListSettings); 129 } 130 131 132 status_t 133 BreakpointsView::SaveSettings(BMessage& settings) 134 { 135 BMessage breakpointListSettings; 136 if (fListView->SaveSettings(breakpointListSettings) != B_OK) 137 return B_NO_MEMORY; 138 139 if (settings.AddMessage("breakpointList", &breakpointListSettings) != B_OK) 140 return B_NO_MEMORY; 141 142 return B_OK; 143 } 144 145 146 void 147 BreakpointsView::BreakpointSelectionChanged(BreakpointProxyList& proxies) 148 { 149 if (fListener != NULL) 150 fListener->BreakpointSelectionChanged(proxies); 151 152 _SetSelection(proxies); 153 } 154 155 156 void 157 BreakpointsView::_Init() 158 { 159 BLayoutBuilder::Group<>(this, B_VERTICAL, 0.0f) 160 .Add(fListView = BreakpointListView::Create(fTeam, this, this)) 161 .AddGroup(B_HORIZONTAL, B_USE_SMALL_SPACING) 162 .SetInsets(B_USE_SMALL_SPACING) 163 .AddGlue() 164 .Add(fRemoveBreakpointButton = new BButton("Remove")) 165 .Add(fEditBreakpointButton = new BButton("Edit" B_UTF8_ELLIPSIS)) 166 .Add(fToggleBreakpointButton = new BButton("Toggle")) 167 .End(); 168 169 fToggleBreakpointButton->SetMessage(new BMessage(MSG_ENABLE_BREAKPOINT)); 170 fRemoveBreakpointButton->SetMessage(new BMessage(MSG_CLEAR_BREAKPOINT)); 171 fEditBreakpointButton->SetMessage( 172 new BMessage(MSG_SHOW_BREAKPOINT_EDIT_WINDOW)); 173 174 _UpdateButtons(); 175 } 176 177 178 void 179 BreakpointsView::_UpdateButtons() 180 { 181 AutoLocker<Team> teamLocker(fTeam); 182 183 bool hasEnabled = false; 184 bool hasDisabled = false; 185 bool valid = false; 186 187 for (int32 i = 0; i < fSelectedBreakpoints.CountItems(); i++) { 188 BreakpointProxy* proxy = fSelectedBreakpoints.ItemAt(i); 189 switch (proxy->Type()) { 190 case BREAKPOINT_PROXY_TYPE_BREAKPOINT: 191 { 192 UserBreakpoint* breakpoint = proxy->GetBreakpoint(); 193 if (breakpoint->IsValid()) { 194 valid = true; 195 if (breakpoint->IsEnabled()) 196 hasEnabled = true; 197 else 198 hasDisabled = true; 199 200 } 201 break; 202 } 203 case BREAKPOINT_PROXY_TYPE_WATCHPOINT: 204 { 205 Watchpoint* watchpoint = proxy->GetWatchpoint(); 206 valid = true; 207 if (watchpoint->IsEnabled()) 208 hasEnabled = true; 209 else 210 hasDisabled = true; 211 break; 212 } 213 default: 214 break; 215 } 216 } 217 218 if (valid) { 219 // only allow condition editing if we have a single 220 // actual breakpoint selected. 221 // TODO: allow using this to modify watchpoints as 222 // well. 223 if (fSelectedBreakpoints.CountItems() == 1 224 && fSelectedBreakpoints.ItemAt(0)->Type() 225 == BREAKPOINT_PROXY_TYPE_BREAKPOINT) { 226 fEditBreakpointButton->SetEnabled(true); 227 } else 228 fEditBreakpointButton->SetEnabled(false); 229 230 // if we have at least one disabled breakpoint in the 231 // selection, we leave the button as an Enable button 232 if (hasEnabled && !hasDisabled) { 233 fToggleBreakpointButton->SetLabel("Disable"); 234 fToggleBreakpointButton->SetMessage( 235 new BMessage(MSG_DISABLE_BREAKPOINT)); 236 } else { 237 fToggleBreakpointButton->SetLabel("Enable"); 238 fToggleBreakpointButton->SetMessage( 239 new BMessage(MSG_ENABLE_BREAKPOINT)); 240 } 241 242 fToggleBreakpointButton->SetEnabled(true); 243 fRemoveBreakpointButton->SetEnabled(true); 244 } else { 245 fToggleBreakpointButton->SetLabel("Enable"); 246 fToggleBreakpointButton->SetEnabled(false); 247 fEditBreakpointButton->SetEnabled(false); 248 fRemoveBreakpointButton->SetEnabled(false); 249 } 250 } 251 252 253 void 254 BreakpointsView::_SetSelection(BreakpointProxyList& proxies) 255 { 256 for (int32 i = 0; i < fSelectedBreakpoints.CountItems(); i++) 257 fSelectedBreakpoints.ItemAt(i)->ReleaseReference(); 258 259 fSelectedBreakpoints.MakeEmpty(); 260 261 for (int32 i = 0; i < proxies.CountItems(); i++) { 262 BreakpointProxy* proxy = proxies.ItemAt(i); 263 if (!fSelectedBreakpoints.AddItem(proxy)) 264 return; 265 proxy->AcquireReference(); 266 } 267 268 _UpdateButtons(); 269 } 270 271 272 void 273 BreakpointsView::_HandleBreakpointAction(uint32 action) 274 { 275 if (fListener == NULL) 276 return; 277 278 for (int32 i = 0; i < fSelectedBreakpoints.CountItems(); i++) { 279 BreakpointProxy* proxy = fSelectedBreakpoints.ItemAt(i); 280 if (proxy->Type() == BREAKPOINT_PROXY_TYPE_BREAKPOINT) { 281 UserBreakpoint* breakpoint = proxy->GetBreakpoint(); 282 if (action == MSG_ENABLE_BREAKPOINT && !breakpoint->IsEnabled()) 283 fListener->SetBreakpointEnabledRequested(breakpoint, true); 284 else if (action == MSG_DISABLE_BREAKPOINT 285 && breakpoint->IsEnabled()) { 286 fListener->SetBreakpointEnabledRequested(breakpoint, false); 287 } else if (action == MSG_CLEAR_BREAKPOINT) 288 fListener->ClearBreakpointRequested(breakpoint); 289 } else { 290 Watchpoint* watchpoint = proxy->GetWatchpoint(); 291 if (action == MSG_ENABLE_BREAKPOINT && !watchpoint->IsEnabled()) 292 fListener->SetWatchpointEnabledRequested(watchpoint, true); 293 else if (action == MSG_DISABLE_BREAKPOINT 294 && watchpoint->IsEnabled()) { 295 fListener->SetWatchpointEnabledRequested(watchpoint, false); 296 } else if (action == MSG_CLEAR_BREAKPOINT) 297 fListener->ClearWatchpointRequested(watchpoint); 298 } 299 } 300 } 301 302 303 // #pragma mark - Listener 304 305 306 BreakpointsView::Listener::~Listener() 307 { 308 } 309