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