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