xref: /haiku/src/apps/debugger/user_interface/gui/team_window/BreakpointsView.cpp (revision 13581b3d2a71545960b98fefebc5225b5bf29072)
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