xref: /haiku/src/apps/debugger/user_interface/gui/team_settings_window/ImageStopConfigView.cpp (revision 6d2f2ec177bf615a117a7428d71be4330545b320)
1 /*
2  * Copyright 2013-2015, Rene Gollent, rene@gollent.com.
3  * Distributed under the terms of the MIT License.
4  */
5 #include "ImageStopConfigView.h"
6 
7 #include <Button.h>
8 #include <CheckBox.h>
9 #include <LayoutBuilder.h>
10 #include <ListView.h>
11 #include <MenuField.h>
12 #include <ScrollView.h>
13 
14 #include <AutoDeleter.h>
15 #include <AutoLocker.h>
16 
17 #include "FunctionInstance.h"
18 #include "Image.h"
19 #include "ImageDebugInfo.h"
20 #include "MessageCodes.h"
21 #include "UserInterface.h"
22 
23 
24 enum {
25 	MSG_SET_STOP_FOR_ALL_IMAGES				= 'sfai',
26 	MSG_SET_STOP_FOR_CUSTOM_IMAGES			= 'sfci',
27 	MSG_IMAGE_NAME_SELECTION_CHANGED		= 'insc',
28 	MSG_ADD_IMAGE_NAME						= 'anin',
29 	MSG_REMOVE_IMAGE_NAME					= 'arin',
30 	MSG_IMAGE_NAME_INPUT_CHANGED			= 'inic'
31 };
32 
33 
34 static int SortStringItems(const void* a, const void* b)
35 {
36 	BStringItem* item1 = *(BStringItem**)a;
37 	BStringItem* item2 = *(BStringItem**)b;
38 
39 	return strcmp(item1->Text(), item2->Text());
40 }
41 
42 
43 ImageStopConfigView::ImageStopConfigView(::Team* team,
44 	UserInterfaceListener* listener)
45 	:
46 	BGroupView(B_VERTICAL),
47 	fTeam(team),
48 	fListener(listener),
49 	fStopOnImageLoad(NULL),
50 	fStopImageConstraints(NULL),
51 	fStopImageNames(NULL),
52 	fStopImageNameInput(NULL),
53 	fAddImageNameButton(NULL),
54 	fRemoveImageNameButton(NULL),
55 	fCustomImageGroup(NULL),
56 	fStopOnLoadEnabled(false),
57 	fUseCustomImages(false)
58 {
59 	SetName("Images");
60 	fTeam->AddListener(this);
61 }
62 
63 
64 ImageStopConfigView::~ImageStopConfigView()
65 {
66 	fTeam->RemoveListener(this);
67 }
68 
69 
70 ImageStopConfigView*
71 ImageStopConfigView::Create(::Team* team, UserInterfaceListener* listener)
72 {
73 	ImageStopConfigView* self = new ImageStopConfigView(team, listener);
74 
75 	try {
76 		self->_Init();
77 	} catch (...) {
78 		delete self;
79 		throw;
80 	}
81 
82 	return self;
83 }
84 
85 
86 void
87 ImageStopConfigView::AttachedToWindow()
88 {
89 	fAddImageNameButton->SetEnabled(false);
90 	fRemoveImageNameButton->SetEnabled(false);
91 
92 	fStopImageConstraints->Menu()->SetTargetForItems(this);
93 	fStopOnImageLoad->SetTarget(this);
94 	fAddImageNameButton->SetTarget(this);
95 	fRemoveImageNameButton->SetTarget(this);
96 	fStopImageNames->SetTarget(this);
97 	fStopImageNameInput->SetTarget(this);
98 
99 	AutoLocker< ::Team> teamLocker(fTeam);
100 	_UpdateStopImageState();
101 
102 	BGroupView::AttachedToWindow();
103 }
104 
105 
106 void
107 ImageStopConfigView::MessageReceived(BMessage* message)
108 {
109 	switch (message->what) {
110 		case MSG_SET_STOP_FOR_ALL_IMAGES:
111 		{
112 			fListener->SetStopOnImageLoadRequested(
113 				fStopOnImageLoad->Value() == B_CONTROL_ON,
114 				false);
115 			break;
116 		}
117 
118 		case MSG_SET_STOP_FOR_CUSTOM_IMAGES:
119 		{
120 			fListener->SetStopOnImageLoadRequested(
121 				fStopOnImageLoad->Value() == B_CONTROL_ON,
122 				true);
123 			break;
124 		}
125 
126 		case MSG_IMAGE_NAME_SELECTION_CHANGED:
127 		{
128 			if (!fUseCustomImages)
129 				break;
130 
131 			fRemoveImageNameButton->SetEnabled(
132 				fStopImageNames->CurrentSelection() >= 0);
133 			break;
134 		}
135 
136 		case MSG_IMAGE_NAME_INPUT_CHANGED:
137 		{
138 			BString imageName(fStopImageNameInput->Text());
139 			imageName.Trim();
140 			fAddImageNameButton->SetEnabled(!imageName.IsEmpty());
141 			break;
142 		}
143 
144 		case MSG_STOP_ON_IMAGE_LOAD:
145 		{
146 			fListener->SetStopOnImageLoadRequested(
147 				fStopOnImageLoad->Value() == B_CONTROL_ON,
148 				fUseCustomImages);
149 			break;
150 		}
151 
152 		case MSG_STOP_IMAGE_SETTINGS_CHANGED:
153 		{
154 			_UpdateStopImageState();
155 			break;
156 		}
157 
158 		case MSG_ADD_IMAGE_NAME:
159 		{
160 			BString imageName(fStopImageNameInput->Text());
161 			imageName.Trim();
162 			AutoLocker< ::Team> teamLocker(fTeam);
163 			if (fTeam->StopImageNames().HasString(imageName))
164 				break;
165 
166 			fStopImageNameInput->SetText("");
167 			fListener->AddStopImageNameRequested(imageName.String());
168 			break;
169 		}
170 
171 		case MSG_STOP_IMAGE_NAME_ADDED:
172 		{
173 			const char* imageName;
174 			if (message->FindString("name", &imageName) != B_OK)
175 				break;
176 
177 			BStringItem* item = new(std::nothrow) BStringItem(imageName);
178 			if (item == NULL)
179 				break;
180 
181 			ObjectDeleter<BStringItem> itemDeleter(item);
182 			if (!fStopImageNames->AddItem(item)) {
183 				break;
184 			}
185 			itemDeleter.Detach();
186 			fStopImageNames->SortItems(SortStringItems);
187 			break;
188 		}
189 
190 		case MSG_REMOVE_IMAGE_NAME:
191 		{
192 			BStringItem* item;
193 			int32 selectedIndex;
194 			AutoLocker< ::Team> teamLocker(fTeam);
195 			int32 i = 0;
196 			while ((selectedIndex = fStopImageNames->CurrentSelection(i++))
197 				>= 0) {
198 				item = (BStringItem*)fStopImageNames->ItemAt(selectedIndex);
199 				fListener->RemoveStopImageNameRequested(item->Text());
200 			}
201 			break;
202 		}
203 
204 		case MSG_STOP_IMAGE_NAME_REMOVED:
205 		{
206 			const char* imageName;
207 			if (message->FindString("name", &imageName) != B_OK)
208 				break;
209 
210 			for (int32 i = 0; i < fStopImageNames->CountItems(); i++) {
211 				BStringItem* item = (BStringItem*)fStopImageNames->ItemAt(i);
212 				if (strcmp(item->Text(), imageName) == 0) {
213 					fStopImageNames->RemoveItem(i);
214 					delete item;
215 				}
216 			}
217 			break;
218 		}
219 
220 
221 		default:
222 			BGroupView::MessageReceived(message);
223 			break;
224 	}
225 
226 }
227 
228 
229 void
230 ImageStopConfigView::StopOnImageLoadSettingsChanged(
231 	const Team::ImageLoadEvent& event)
232 {
233 	BMessage message(MSG_STOP_IMAGE_SETTINGS_CHANGED);
234 	message.AddBool("enabled", event.StopOnImageLoad());
235 	message.AddBool("useNameList", event.StopImageNameListEnabled());
236 	BMessenger(this).SendMessage(&message);
237 }
238 
239 
240 void
241 ImageStopConfigView::StopOnImageLoadNameAdded(
242 	const Team::ImageLoadNameEvent& event)
243 {
244 	BMessage message(MSG_STOP_IMAGE_NAME_ADDED);
245 	message.AddString("name", event.ImageName());
246 	BMessenger(this).SendMessage(&message);
247 }
248 
249 
250 void
251 ImageStopConfigView::StopOnImageLoadNameRemoved(
252 	const Team::ImageLoadNameEvent& event)
253 {
254 	BMessage message(MSG_STOP_IMAGE_NAME_REMOVED);
255 	message.AddString("name", event.ImageName());
256 	BMessenger(this).SendMessage(&message);
257 }
258 
259 
260 void
261 ImageStopConfigView::_Init()
262 {
263 	BMenu* stopImageMenu = new BMenu("stopImageTypesMenu");
264 
265 	stopImageMenu->AddItem(new BMenuItem("All",
266 		new BMessage(MSG_SET_STOP_FOR_ALL_IMAGES)));
267 	stopImageMenu->AddItem(new BMenuItem("Custom",
268 		new BMessage(MSG_SET_STOP_FOR_CUSTOM_IMAGES)));
269 
270 	fStopImageNames = new BListView("customImageList",
271 		B_MULTIPLE_SELECTION_LIST);
272 	fStopImageNames->SetSelectionMessage(
273 		new BMessage(MSG_IMAGE_NAME_SELECTION_CHANGED));
274 
275 	fCustomImageGroup = new BGroupView();
276 	BLayoutBuilder::Group<>(fCustomImageGroup, B_VERTICAL, 0.0)
277 		.Add(new BScrollView("stopImageScroll", fStopImageNames,
278 			0, false, true))
279 		.Add(fStopImageNameInput = new BTextControl("stopImageName",
280 			"Image:", NULL,	NULL))
281 		.AddGroup(B_HORIZONTAL)
282 			.SetInsets(B_USE_SMALL_SPACING)
283 			.AddGlue()
284 			.Add(fAddImageNameButton = new BButton("Add",
285 				new BMessage(MSG_ADD_IMAGE_NAME)))
286 			.Add(fRemoveImageNameButton = new BButton("Remove",
287 				new BMessage(MSG_REMOVE_IMAGE_NAME)))
288 		.End();
289 
290 	BLayoutBuilder::Group<>(this, B_VERTICAL)
291 		.SetInsets(B_USE_SMALL_SPACING)
292 		.Add(fStopOnImageLoad = new BCheckBox("stopOnImage",
293 			"Stop when an image is loaded",
294 			new BMessage(MSG_STOP_ON_IMAGE_LOAD)))
295 		.Add(fStopImageConstraints = new BMenuField(
296 			"stopTypes", "Types:", stopImageMenu))
297 		.Add(fCustomImageGroup);
298 
299 	font_height fontHeight;
300 	be_plain_font->GetHeight(&fontHeight);
301 	float minListHeight = 5 * (fontHeight.ascent + fontHeight.descent
302 			+ fontHeight.leading);
303 	fStopImageNames->SetExplicitMinSize(BSize(B_SIZE_UNSET, minListHeight));
304 
305 	stopImageMenu->SetLabelFromMarked(true);
306 	fStopImageNameInput->SetModificationMessage(
307 		new BMessage(MSG_IMAGE_NAME_INPUT_CHANGED));
308 }
309 
310 
311 void
312 ImageStopConfigView::_UpdateStopImageState()
313 {
314 	fStopOnLoadEnabled = fTeam->StopOnImageLoad();
315 	fStopOnImageLoad->SetValue(
316 		fStopOnLoadEnabled ? B_CONTROL_ON : B_CONTROL_OFF);
317 	fUseCustomImages = fTeam->StopImageNameListEnabled();
318 	fStopImageConstraints->Menu()
319 		->ItemAt(fUseCustomImages ? 1 : 0)->SetMarked(true);
320 
321 	fStopImageNames->MakeEmpty();
322 	const BStringList& imageNames = fTeam->StopImageNames();
323 	for (int32 i = 0; i < imageNames.CountStrings(); i++) {
324 		BStringItem* item = new(std::nothrow) BStringItem(
325 			imageNames.StringAt(i));
326 		if (item == NULL)
327 			return;
328 		item->SetEnabled(fUseCustomImages);
329 		ObjectDeleter<BStringItem> itemDeleter(item);
330 		if (!fStopImageNames->AddItem(item))
331 			return;
332 		itemDeleter.Detach();
333 	}
334 
335 	fStopImageConstraints->SetEnabled(fStopOnLoadEnabled);
336 	fStopImageNameInput->SetEnabled(fUseCustomImages);
337 }
338