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
BreakpointsView(Team * team,Listener * listener)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
~BreakpointsView()42 BreakpointsView::~BreakpointsView()
43 {
44 if (fListView != NULL)
45 fListView->UnsetListener();
46 }
47
48
49 /*static*/ BreakpointsView*
Create(Team * team,Listener * listener)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
UnsetListener()66 BreakpointsView::UnsetListener()
67 {
68 fListener = NULL;
69 }
70
71
72 void
UserBreakpointChanged(UserBreakpoint * breakpoint)73 BreakpointsView::UserBreakpointChanged(UserBreakpoint* breakpoint)
74 {
75 fListView->UserBreakpointChanged(breakpoint);
76
77 _UpdateButtons();
78 }
79
80
81 void
WatchpointChanged(Watchpoint * watchpoint)82 BreakpointsView::WatchpointChanged(Watchpoint* watchpoint)
83 {
84 fListView->WatchpointChanged(watchpoint);
85
86 _UpdateButtons();
87 }
88
89
90 void
MessageReceived(BMessage * message)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
AttachedToWindow()114 BreakpointsView::AttachedToWindow()
115 {
116 fEditBreakpointButton->SetTarget(this);
117 fToggleBreakpointButton->SetTarget(this);
118 fRemoveBreakpointButton->SetTarget(this);
119 }
120
121
122 void
LoadSettings(const BMessage & settings)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
SaveSettings(BMessage & settings)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
BreakpointSelectionChanged(BreakpointProxyList & proxies)147 BreakpointsView::BreakpointSelectionChanged(BreakpointProxyList& proxies)
148 {
149 if (fListener != NULL)
150 fListener->BreakpointSelectionChanged(proxies);
151
152 _SetSelection(proxies);
153 }
154
155
156 void
_Init()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
_UpdateButtons()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
_SetSelection(BreakpointProxyList & proxies)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
_HandleBreakpointAction(uint32 action)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
~Listener()306 BreakpointsView::Listener::~Listener()
307 {
308 }
309