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