xref: /haiku/src/preferences/backgrounds/BackgroundsView.cpp (revision d3d8b26997fac34a84981e6d2b649521de2cc45a)
1 /*
2  * Copyright 2002-2005, Haiku, Inc. All Rights Reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Jerome Duval (jerome.duval@free.fr)
7  *		Axel Dörfler, axeld@pinc-software.de
8  */
9 
10 
11 #include "BackgroundsView.h"
12 #include "ImageFilePanel.h"
13 
14 #include <OS.h>
15 #include <MenuField.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <StorageKit.h>
19 #include <Background.h>
20 #include <Window.h>
21 #include <Messenger.h>
22 #include <Bitmap.h>
23 #include <Point.h>
24 #include <TranslationKit.h>
25 #include <PopUpMenu.h>
26 
27 
28 static const uint32 kMsgApplySettings = 'aply';
29 static const uint32 kMsgRevertSettings = 'rvrt';
30 
31 static const uint32 kMsgUpdateColor = 'upcl';
32 static const uint32 kMsgAllWorkspaces = 'alwk';
33 static const uint32 kMsgCurrentWorkspace = 'crwk';
34 static const uint32 kMsgDefaultFolder = 'dffl';
35 static const uint32 kMsgOtherFolder = 'otfl';
36 static const uint32 kMsgNoImage = 'noim';
37 static const uint32 kMsgOtherImage = 'otim';
38 static const uint32 kMsgImageSelected = 'imsl';
39 static const uint32 kMsgFolderSelected = 'flsl';
40 
41 static const uint32 kMsgCenterPlacement = 'cnpl';
42 static const uint32 kMsgManualPlacement = 'mnpl';
43 static const uint32 kMsgScalePlacement = 'scpl';
44 static const uint32 kMsgTilePlacement = 'tlpl';
45 static const uint32 kMsgIconLabelBackground = 'ilcb';
46 
47 static const uint32 kMsgImagePlacement = 'xypl';
48 static const uint32 kMsgUpdatePreviewPlacement = 'pvpl';
49 
50 
51 const uint8 kHandCursorData[68] = {
52 	16, 1, 2, 2,
53 
54 	0,0,		// 0000000000000000
55 	7,128,		// 0000011110000000
56 	61,112,		// 0011110101110000
57 	37,40,		// 0010010100101000
58 	36,168,		// 0010010010101000
59 	18,148,		// 0001001010010100
60 	18,84,		// 0001001001010100
61 	9,42,		// 0000100100101010
62 	8,1,		// 0000100000000001
63 	60,1,		// 0011110000000001
64 	76,1,		// 0100110000000001
65 	66,1,		// 0100001000000001
66 	48,1,		// 0011000000000001
67 	12,1,		// 0000110000000001
68 	2,0,		// 0000001000000000
69 	1,0,		// 0000000100000000
70 
71 	0,0,		// 0000000000000000
72 	7,128,		// 0000011110000000
73 	63,240,		// 0011111111110000
74 	63,248,		// 0011111111111000
75 	63,248,		// 0011111111111000
76 	31,252,		// 0001111111111100
77 	31,252,		// 0001111111111100
78 	15,254,		// 0000111111111110
79 	15,255,		// 0000111111111111
80 	63,255,		// 0011111111111111
81 	127,255,	// 0111111111111111
82 	127,255,	// 0111111111111111
83 	63,255,		// 0011111111111111
84 	15,255,		// 0000111111111111
85 	3,254,		// 0000001111111110
86 	1,248		// 0000000111111000
87 };
88 
89 
90 BackgroundsView::BackgroundsView(BRect frame, const char *name, int32 resize,
91 		int32 flags)
92 	: BBox(frame, name, resize,
93 		flags | B_WILL_DRAW | B_FRAME_EVENTS, B_NO_BORDER),
94 	fCurrent(NULL),
95 	fCurrentInfo(NULL),
96 	fLastImageIndex(-1),
97 	fPathList(1, true),
98 	fImageList(1, true)
99 {
100 	// we need the "Current Workspace" first to get its height
101 
102 	BMenuItem *menuItem;
103 	fWorkspaceMenu = new BPopUpMenu("pick one");
104 	fWorkspaceMenu->AddItem(menuItem = new BMenuItem("All Workspaces",
105 		new BMessage(kMsgAllWorkspaces)));
106 	fWorkspaceMenu->AddItem(menuItem = new BMenuItem("Current Workspace",
107 		new BMessage(kMsgCurrentWorkspace)));
108 	menuItem->SetMarked(true);
109 	fLastWorkspaceIndex = fWorkspaceMenu->IndexOf(fWorkspaceMenu->FindMarked());
110 	fWorkspaceMenu->AddSeparatorItem();
111 	fWorkspaceMenu->AddItem(menuItem = new BMenuItem("Default folder",
112 		new BMessage(kMsgDefaultFolder)));
113 	fWorkspaceMenu->AddItem(menuItem = new BMenuItem("Other folder" B_UTF8_ELLIPSIS,
114 		new BMessage(kMsgOtherFolder)));
115 
116 	BMenuField *workspaceMenuField = new BMenuField(BRect(0, 0, 130, 18),
117 		"workspaceMenuField", NULL, fWorkspaceMenu, true);
118 	workspaceMenuField->ResizeToPreferred();
119 
120 	/* the preview box */
121 
122 	BFont font(be_plain_font);
123 	font_height fontHeight;
124 	font.GetHeight(&fontHeight);
125 
126 	fPreview = new PreviewBox(BRect(10, 8.0 + workspaceMenuField->Bounds().Height() / 2.0f
127 		- ceilf(fontHeight.ascent + fontHeight.descent) / 2.0f, 160, 180), "preview");
128 	fPreview->SetFont(&font);
129 	fPreview->SetLabel("Preview");
130 	AddChild(fPreview);
131 
132 	BRect rect(10, fPreview->Bounds().bottom - 30, 70, fPreview->Bounds().bottom - 10);
133 	fXPlacementText = new BTextControl(rect, "xPlacementText", "X:", NULL,
134 		new BMessage(kMsgImagePlacement), B_FOLLOW_LEFT | B_FOLLOW_BOTTOM);
135 	fXPlacementText->SetDivider(fXPlacementText->StringWidth(fXPlacementText->Label()) + 4.0f);
136 	fXPlacementText->TextView()->SetMaxBytes(5);
137 	float width, height;
138 	fXPlacementText->GetPreferredSize(&width, &height);
139 	float delta = fXPlacementText->Bounds().Height() - height;
140 	fXPlacementText->MoveBy(0, delta);
141 	fXPlacementText->ResizeTo(fXPlacementText->Bounds().Width(), height);
142 	fPreview->AddChild(fXPlacementText);
143 
144 	rect.OffsetBy(70, delta);
145 	fYPlacementText = new BTextControl(rect, "yPlacementText", "Y:", NULL,
146 		new BMessage(kMsgImagePlacement), B_FOLLOW_LEFT | B_FOLLOW_BOTTOM);
147 	fYPlacementText->SetDivider(fYPlacementText->StringWidth(fYPlacementText->Label()) + 4.0f);
148 	fYPlacementText->TextView()->SetMaxBytes(5);
149 	fXPlacementText->ResizeTo(fYPlacementText->Bounds().Width(), height);
150 	fPreview->AddChild(fYPlacementText);
151 
152 	for (int32 i = 0; i < 256; i++) {
153 		if ((i < '0' || i > '9') && i != '-') {
154 			fXPlacementText->TextView()->DisallowChar(i);
155 			fYPlacementText->TextView()->DisallowChar(i);
156 		}
157 	}
158 
159 	fPreView = new PreView(BRect(15, 25, 135, 115), "preView",
160 		B_FOLLOW_LEFT | B_FOLLOW_TOP, B_WILL_DRAW | B_SUBPIXEL_PRECISE);
161 	fPreview->AddChild(fPreView);
162 
163 	/* the right box */
164 
165 	BBox *rightbox = new BBox(BRect(fPreview->Frame().right + 10,
166 		7, Frame().right - 10, fPreview->Frame().bottom),
167 		"rightbox");
168 	rightbox->SetLabel(workspaceMenuField);
169 	AddChild(rightbox);
170 
171 	fPicker = new BColorControl(BPoint(10, 110), B_CELLS_32x8, 5.0, "Picker",
172 		new BMessage(kMsgUpdateColor));
173 	rightbox->AddChild(fPicker);
174 
175 	delta = fPicker->Frame().bottom + 10.0f - rightbox->Bounds().Height();
176 	rightbox->ResizeBy(0, delta);
177 	fPreview->ResizeBy(0, delta);
178 
179 	// we're not yet attached to a view, so we need to move them manually
180 	fXPlacementText->MoveBy(0, delta);
181 	fYPlacementText->MoveBy(0, delta);
182 
183 	float offset = be_plain_font->StringWidth("Placement:") + 5;
184 	rect.Set(offset + 10, 76, 280, 96);
185 
186 	fIconLabelBackground = new BCheckBox(rect, "iconLabelBackground",
187 		"Icon label background", new BMessage(kMsgIconLabelBackground));
188 	fIconLabelBackground->SetValue(B_CONTROL_ON);
189 	rightbox->AddChild(fIconLabelBackground);
190 
191 	fImageMenu = new BPopUpMenu("pick one");
192 	fImageMenu->AddItem(new BGImageMenuItem("None", -1, new BMessage(kMsgNoImage)));
193 	fImageMenu->AddSeparatorItem();
194 	fImageMenu->AddItem(new BMenuItem("Other" B_UTF8_ELLIPSIS, new BMessage(kMsgOtherImage)));
195 
196 	fPlacementMenu = new BPopUpMenu("pick one");
197 	fPlacementMenu->AddItem(new BMenuItem("Manual",
198 		new BMessage(kMsgManualPlacement)));
199 	fPlacementMenu->AddItem(new BMenuItem("Center",
200 		new BMessage(kMsgCenterPlacement)));
201 	fPlacementMenu->AddItem(new BMenuItem("Scale to fit",
202 		new BMessage(kMsgScalePlacement)));
203 	fPlacementMenu->AddItem(new BMenuItem("Tile",
204 		new BMessage(kMsgTilePlacement)));
205 
206 	rect.OffsetBy(-offset, -25);
207 	BMenuField *placementMenuField = new BMenuField(rect, "placementMenuField",
208 		"Placement:", fPlacementMenu);
209 	placementMenuField->SetDivider(offset);
210 	placementMenuField->SetAlignment(B_ALIGN_RIGHT);
211 	rightbox->AddChild(placementMenuField);
212 
213 	rect.OffsetBy(0, -25);
214 	rect.right += 40;
215 	BMenuField *imageMenuField = new BMenuField(rect, "imageMenuField",
216 		"Image:", fImageMenu);
217 	imageMenuField->SetDivider(offset);
218 	imageMenuField->SetAlignment(B_ALIGN_RIGHT);
219 	rightbox->AddChild(imageMenuField);
220 
221 	fRevert = new BButton(BRect(fPreview->Frame().left, fPreview->Frame().bottom + 10,
222 		fPreview->Frame().left + 80, Frame().bottom - 10), "RevertButton",
223 		"Revert", new BMessage(kMsgRevertSettings), B_FOLLOW_LEFT | B_FOLLOW_TOP,
224 		B_WILL_DRAW | B_NAVIGABLE);
225 	AddChild(fRevert);
226 
227 	fApply = new BButton(BRect(rightbox->Frame().right - 70, fPreview->Frame().bottom
228 		+ 10, rightbox->Frame().right, 110), "ApplyButton", "Apply",
229 		new BMessage(kMsgApplySettings), B_FOLLOW_LEFT | B_FOLLOW_TOP,
230 		B_WILL_DRAW | B_NAVIGABLE);
231 	AddChild(fApply);
232 
233 	ResizeBy(0, delta);
234 }
235 
236 
237 BackgroundsView::~BackgroundsView()
238 {
239 	delete fPanel;
240 	delete fFolderPanel;
241 }
242 
243 
244 void
245 BackgroundsView::AllAttached()
246 {
247 	fPlacementMenu->SetTargetForItems(this);
248 	fImageMenu->SetTargetForItems(this);
249 	fWorkspaceMenu->SetTargetForItems(this);
250 	fXPlacementText->SetTarget(this);
251 	fYPlacementText->SetTarget(this);
252 	fIconLabelBackground->SetTarget(this);
253 	fPicker->SetTarget(this);
254 	fApply->SetTarget(this);
255 	fRevert->SetTarget(this);
256 
257 	fPanel = new ImageFilePanel(B_OPEN_PANEL, new BMessenger(this), NULL,
258 		B_FILE_NODE, false, NULL, new CustomRefFilter(true));
259 	fPanel->SetButtonLabel(B_DEFAULT_BUTTON, "Select");
260 
261 	fFolderPanel = new BFilePanel(B_OPEN_PANEL, new BMessenger(this), NULL,
262 		B_DIRECTORY_NODE, false, NULL, new CustomRefFilter(false));
263 	fFolderPanel->SetButtonLabel(B_DEFAULT_BUTTON, "Select");
264 
265 	Window()->ResizeTo(Frame().Width(), Frame().Height());
266 
267 	LoadSettings();
268 	LoadDesktopFolder();
269 }
270 
271 
272 void
273 BackgroundsView::MessageReceived(BMessage *msg)
274 {
275 	switch (msg->what) {
276 		case B_SIMPLE_DATA:
277 		case B_REFS_RECEIVED:
278 			RefsReceived(msg);
279 			break;
280 
281 		case kMsgUpdatePreviewPlacement:
282 		{
283 			BString xstring, ystring;
284 			xstring << (int)fPreView->fPoint.x;
285 			ystring << (int)fPreView->fPoint.y;
286 			fXPlacementText->SetText(xstring.String());
287 			fYPlacementText->SetText(ystring.String());
288 			UpdatePreview();
289 			UpdateButtons();
290 			break;
291 		}
292 
293 		case kMsgManualPlacement:
294 			UpdatePreview();
295 			UpdateButtons();
296 			break;
297 
298 		case kMsgTilePlacement:
299 		case kMsgScalePlacement:
300 		case kMsgCenterPlacement:
301 			UpdatePreview();
302 			UpdateButtons();
303 			break;
304 
305 		case kMsgIconLabelBackground:
306 			UpdateButtons();
307 			break;
308 
309 		case kMsgUpdateColor:
310 		case kMsgImagePlacement:
311 			UpdatePreview();
312 			UpdateButtons();
313 			break;
314 
315 		case kMsgCurrentWorkspace:
316 		case kMsgAllWorkspaces:
317 			fImageMenu->FindItem(kMsgNoImage)->SetLabel("None");
318 			fLastWorkspaceIndex = fWorkspaceMenu->IndexOf(
319 				fWorkspaceMenu->FindMarked());
320 			if (!fCurrent->IsDesktop()) {
321 				fPreview->SetDesktop(true);
322 				LoadDesktopFolder();
323 			} else
324 				UpdateButtons();
325 			break;
326 
327 		case kMsgDefaultFolder:
328 			fImageMenu->FindItem(kMsgNoImage)->SetLabel("None");
329 			fLastWorkspaceIndex = fWorkspaceMenu->IndexOf(
330 				fWorkspaceMenu->FindMarked());
331 			fPreview->SetDesktop(false);
332 			LoadDefaultFolder();
333 			break;
334 
335 		case kMsgOtherFolder:
336 			fFolderPanel->Show();
337 			break;
338 
339 		case kMsgOtherImage:
340 			fPanel->Show();
341 			break;
342 
343 		case B_CANCEL:
344 		{
345 			PRINT(("cancel received\n"));
346 			void* pointer;
347 			msg->FindPointer("source", &pointer);
348 			if (pointer == fPanel) {
349 				if (fLastImageIndex >= 0)
350 					FindImageItem(fLastImageIndex)->SetMarked(true);
351 				else
352 					fImageMenu->ItemAt(0)->SetMarked(true);
353 			} else if (pointer == fFolderPanel) {
354 				if (fLastWorkspaceIndex >= 0)
355 					fWorkspaceMenu->ItemAt(fLastWorkspaceIndex)->SetMarked(true);
356 			}
357 			break;
358 		}
359 
360 		case kMsgImageSelected:
361 		case kMsgNoImage:
362 			fLastImageIndex = ((BGImageMenuItem*)fImageMenu->FindMarked())->ImageIndex();
363 			UpdatePreview();
364 			UpdateButtons();
365 			break;
366 
367 		case kMsgFolderSelected:
368 			fImageMenu->FindItem(kMsgNoImage)->SetLabel("Default");
369 			fLastWorkspaceIndex = fWorkspaceMenu->IndexOf(
370 				fWorkspaceMenu->FindMarked());
371 			fPreview->SetDesktop(false);
372 			LoadRecentFolder(*fPathList.ItemAt(fWorkspaceMenu->IndexOf(
373 				fWorkspaceMenu->FindMarked()) - 6));
374 			break;
375 
376 		case kMsgApplySettings:
377 		{
378 			Save();
379 
380 			//NotifyServer();
381 			thread_id notify_thread;
382 			notify_thread = spawn_thread(BackgroundsView::NotifyThread, "notifyServer",
383 				B_NORMAL_PRIORITY, this);
384 			resume_thread(notify_thread);
385 			UpdateButtons();
386 			break;
387 		}
388 		case kMsgRevertSettings:
389 			UpdateWithCurrent();
390 			break;
391 
392 		default:
393 			BView::MessageReceived(msg);
394 			break;
395 	}
396 }
397 
398 
399 void
400 BackgroundsView::LoadDesktopFolder()
401 {
402 	BPath path;
403 	if (find_directory(B_DESKTOP_DIRECTORY, &path) == B_OK) {
404 		status_t err;
405 		err = get_ref_for_path(path.Path(), &fCurrentRef);
406 		if (err != B_OK)
407 			printf("error in LoadDesktopSettings\n");
408 		LoadFolder(true);
409 	}
410 }
411 
412 
413 void
414 BackgroundsView::LoadDefaultFolder()
415 {
416 	BPath path;
417 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) {
418 		BString pathString = path.Path();
419 		pathString << "/Tracker/DefaultFolderTemplate";
420 		status_t err;
421 		err = get_ref_for_path(pathString.String(), &fCurrentRef);
422 		if (err != B_OK)
423 			printf("error in LoadDefaultFolderSettings\n");
424 		LoadFolder(false);
425 	}
426 }
427 
428 
429 void
430 BackgroundsView::LoadRecentFolder(BPath path)
431 {
432 	status_t err;
433 	err = get_ref_for_path(path.Path(), &fCurrentRef);
434 	if (err != B_OK)
435 		printf("error in LoadRecentFolder\n");
436 	LoadFolder(false);
437 }
438 
439 
440 void
441 BackgroundsView::LoadFolder(bool isDesktop)
442 {
443 	if (fCurrent) {
444 		delete fCurrent;
445 		fCurrent = NULL;
446 	}
447 
448 	BNode node(&fCurrentRef);
449 	if (node.InitCheck() == B_OK)
450 		fCurrent = BackgroundImage::GetBackgroundImage(&node, isDesktop, this);
451 
452 	UpdateWithCurrent();
453 }
454 
455 
456 void
457 BackgroundsView::UpdateWithCurrent(void)
458 {
459 	if (fCurrent == NULL)
460 		return;
461 
462 	fPlacementMenu->FindItem(kMsgScalePlacement)->SetEnabled(fCurrent->IsDesktop());
463 	fPlacementMenu->FindItem(kMsgCenterPlacement)->SetEnabled(fCurrent->IsDesktop());
464 
465 	if (fWorkspaceMenu->IndexOf(fWorkspaceMenu->FindMarked()) > 5)
466 		fImageMenu->FindItem(kMsgNoImage)->SetLabel("Default");
467 	else
468 		fImageMenu->FindItem(kMsgNoImage)->SetLabel("None");
469 
470 	for (int32 i = fImageMenu->CountItems() - 5; i >= 0; i--) {
471 		fImageMenu->RemoveItem(2);
472 	}
473 
474 	for (int32 i = fImageList.CountItems() - 1; i >= 0; i--) {
475 		BMessage *message = new BMessage(kMsgImageSelected);
476 		AddItem(new BGImageMenuItem(GetImage(i)->GetName(), i, message));
477 	}
478 
479 	fImageMenu->SetTargetForItems(this);
480 
481 	fCurrentInfo = fCurrent->ImageInfoForWorkspace(current_workspace());
482 
483 	if (!fCurrentInfo) {
484 		fImageMenu->FindItem(kMsgNoImage)->SetMarked(true);
485 		fPlacementMenu->FindItem(kMsgManualPlacement)->SetMarked(true);
486 	} else {
487 		fIconLabelBackground->SetValue(fCurrentInfo->fEraseTextWidgetBackground
488 			? B_CONTROL_ON : B_CONTROL_OFF);
489 
490 		BString xtext, ytext;
491 		int32 cmd = 0;
492 		switch (fCurrentInfo->fMode) {
493 			case BackgroundImage::kCentered:
494 				cmd = kMsgCenterPlacement;
495 				break;
496 			case BackgroundImage::kScaledToFit:
497 				cmd = kMsgScalePlacement;
498 				break;
499 			case BackgroundImage::kAtOffset:
500 				cmd = kMsgManualPlacement;
501 				xtext << (int)fCurrentInfo->fOffset.x;
502 				ytext << (int)fCurrentInfo->fOffset.y;
503 				break;
504 			case BackgroundImage::kTiled:
505 				cmd = kMsgTilePlacement;
506 			break;
507 		}
508 
509 		if (cmd != 0)
510 			fPlacementMenu->FindItem(cmd)->SetMarked(true);
511 
512 		fXPlacementText->SetText(xtext.String());
513 		fYPlacementText->SetText(ytext.String());
514 
515 		fLastImageIndex = fCurrentInfo->fImageIndex;
516 		FindImageItem(fLastImageIndex)->SetMarked(true);
517 	}
518 
519 	rgb_color color = {255, 255, 255, 255};
520 	if (fCurrent->IsDesktop()) {
521 		color = BScreen().DesktopColor();
522 		fPicker->SetEnabled(true);
523 	} else
524 		fPicker->SetEnabled(false);
525 
526 	fPicker->SetValue(color);
527 
528 	UpdatePreview();
529 	UpdateButtons();
530 }
531 
532 
533 void
534 BackgroundsView::Save()
535 {
536 	bool eraseTextWidgetBackground =
537 		fIconLabelBackground->Value() == B_CONTROL_ON;
538 	BackgroundImage::Mode mode = FindPlacementMode();
539 	BPoint offset(atoi(fXPlacementText->Text()), atoi(fYPlacementText->Text()));
540 
541 	if (!fCurrent->IsDesktop()) {
542 		if (fCurrentInfo == NULL) {
543 			fCurrentInfo = new BackgroundImage::BackgroundImageInfo(B_ALL_WORKSPACES,
544 				fLastImageIndex, mode, offset, eraseTextWidgetBackground, 0, 0);
545 			fCurrent->Add(fCurrentInfo);
546 		} else {
547 			fCurrentInfo->fEraseTextWidgetBackground = eraseTextWidgetBackground;
548 			fCurrentInfo->fMode = mode;
549 			if (fCurrentInfo->fMode == BackgroundImage::kAtOffset)
550 				fCurrentInfo->fOffset = offset;
551 			fCurrentInfo->fImageIndex = fLastImageIndex;
552 		}
553 	} else {
554 		uint32 workspaceMask = 1;
555 		int32 workspace = current_workspace();
556 		for (; workspace; workspace--)
557 			workspaceMask *= 2;
558 
559 		if (fCurrentInfo != NULL) {
560 			if (fWorkspaceMenu->FindItem(kMsgCurrentWorkspace)->IsMarked()) {
561 				if (fCurrentInfo->fWorkspace != workspaceMask) {
562 					fCurrentInfo->fWorkspace = fCurrentInfo->fWorkspace
563 						^ workspaceMask;
564 					if (fLastImageIndex > -1) {
565 						fCurrentInfo = new BackgroundImage::BackgroundImageInfo(
566 							workspaceMask, fLastImageIndex, mode, offset,
567 							eraseTextWidgetBackground, fCurrentInfo->fImageSet,
568 							fCurrentInfo->fCacheMode);
569 						fCurrent->Add(fCurrentInfo);
570 					}
571 				} else {
572 					if (fLastImageIndex > -1) {
573 						fCurrentInfo->fEraseTextWidgetBackground =
574 							eraseTextWidgetBackground;
575 						fCurrentInfo->fMode = mode;
576 						if (fCurrentInfo->fMode == BackgroundImage::kAtOffset)
577 							fCurrentInfo->fOffset = offset;
578 
579 						fCurrentInfo->fImageIndex = fLastImageIndex;
580 					} else {
581 						fCurrent->Remove(fCurrentInfo);
582 						fCurrentInfo = NULL;
583 					}
584 				}
585 			} else if (fLastImageIndex > -1) {
586 				fCurrent->RemoveAll();
587 				fCurrentInfo = new BackgroundImage::BackgroundImageInfo(
588 					B_ALL_WORKSPACES, fLastImageIndex, mode, offset,
589 					eraseTextWidgetBackground, fCurrent->GetShowingImageSet(),
590 					fCurrentInfo->fCacheMode);
591 				fCurrent->Add(fCurrentInfo);
592 			}
593 		} else if (fLastImageIndex > -1) {
594 			if (fWorkspaceMenu->FindItem(kMsgCurrentWorkspace)->IsMarked()) {
595 				fCurrentInfo = new BackgroundImage::BackgroundImageInfo(
596 					workspaceMask, fLastImageIndex, mode, offset,
597 					eraseTextWidgetBackground, fCurrent->GetShowingImageSet(), 0);
598 			} else {
599 				fCurrent->RemoveAll();
600 				fCurrentInfo = new BackgroundImage::BackgroundImageInfo(
601 					B_ALL_WORKSPACES, fLastImageIndex, mode, offset,
602 					eraseTextWidgetBackground, fCurrent->GetShowingImageSet(), 0);
603 			}
604 			fCurrent->Add(fCurrentInfo);
605 		}
606 
607 		if (!fWorkspaceMenu->FindItem(kMsgCurrentWorkspace)->IsMarked()) {
608 			for (int32 i = 0; i < count_workspaces(); i++) {
609 					BScreen().SetDesktopColor(fPicker->ValueAsColor(), i, true);
610 			}
611 		} else
612 			BScreen().SetDesktopColor(fPicker->ValueAsColor(), true);
613 	}
614 
615 	BNode node(&fCurrentRef);
616 
617 	status_t status = fCurrent->SetBackgroundImage(&node);
618 	if (status != B_OK) {
619 		// TODO: this should be a BAlert!
620 		printf("setting background image failed: %s\n", strerror(status));
621 	}
622 }
623 
624 
625 void
626 BackgroundsView::NotifyServer()
627 {
628 	BMessenger tracker("application/x-vnd.Be-TRAK");
629 
630 	if (fCurrent->IsDesktop()) {
631 		tracker.SendMessage(new BMessage(B_RESTORE_BACKGROUND_IMAGE));
632 	} else {
633 		int32 i = -1;
634 		BMessage reply;
635 		int32 err;
636 		BEntry currentEntry(&fCurrentRef);
637 		BPath currentPath(&currentEntry);
638 		bool isCustomFolder = !fWorkspaceMenu->FindItem(kMsgDefaultFolder)->IsMarked();
639 
640 		do {
641 			BMessage msg(B_GET_PROPERTY);
642 			i++;
643 
644 			// look at the "Poses" in every Tracker window
645 			msg.AddSpecifier("Poses");
646 			msg.AddSpecifier("Window", i);
647 
648 			reply.MakeEmpty();
649 			tracker.SendMessage(&msg, &reply);
650 
651 			// break out of the loop when we're at the end of
652 			// the windows
653 			if (reply.what == B_MESSAGE_NOT_UNDERSTOOD
654 				&& reply.FindInt32("error", &err) == B_OK
655 				&& err == B_BAD_INDEX)
656 				break;
657 
658 			// don't stop for windows that don't understand
659 			// a request for "Poses"; they're not displaying
660 			// folders
661 			if (reply.what == B_MESSAGE_NOT_UNDERSTOOD
662 				&& reply.FindInt32("error", &err) == B_OK
663 				&& err != B_BAD_SCRIPT_SYNTAX)
664 				continue;
665 
666 			BMessenger trackerWindow;
667 			if (reply.FindMessenger("result", &trackerWindow) != B_OK)
668 				continue;
669 
670 			if (isCustomFolder) {
671            		// found a window with poses, ask for its path
672 				msg.MakeEmpty();
673 				msg.what = B_GET_PROPERTY;
674 				msg.AddSpecifier("Path");
675 				msg.AddSpecifier("Poses");
676 				msg.AddSpecifier("Window", i);
677 
678 				reply.MakeEmpty();
679 				tracker.SendMessage(&msg, &reply);
680 
681            		// go on with the next if this din't have a path
682 				if (reply.what == B_MESSAGE_NOT_UNDERSTOOD)
683 					continue;
684 
685 				entry_ref ref;
686 				if (reply.FindRef("result", &ref) == B_OK) {
687 					BEntry entry(&ref);
688 					BPath path(&entry);
689 
690 					// these are not the paths you're looking for
691 					if (currentPath != path)
692 						continue;
693 				}
694 			}
695 
696 			trackerWindow.SendMessage(B_RESTORE_BACKGROUND_IMAGE);
697 		} while (true);
698 	}
699 }
700 
701 
702 int32
703 BackgroundsView::NotifyThread(void *data)
704 {
705 	BackgroundsView *view = (BackgroundsView*)data;
706 
707 	view->NotifyServer();
708 	return B_OK;
709 }
710 
711 
712 void
713 BackgroundsView::SaveSettings(void)
714 {
715 	BPath path;
716 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) == B_OK) {
717 		path.Append(SETTINGS_FILE);
718 		BFile file(path.Path(), B_READ_WRITE | B_CREATE_FILE | B_ERASE_FILE);
719 
720 		BPoint point = Window()->Frame().LeftTop();
721 		if (fSettings.ReplacePoint("pos", point)!=B_OK)
722 			fSettings.AddPoint("pos", point);
723 
724 		entry_ref ref;
725 		BEntry entry;
726 		BPath path;
727 
728 		fPanel->GetPanelDirectory(&ref);
729 		entry.SetTo(&ref);
730 		entry.GetPath(&path);
731 		if (fSettings.ReplaceString("paneldir", path.Path()) != B_OK)
732 			fSettings.AddString("paneldir", path.Path());
733 
734 		fFolderPanel->GetPanelDirectory(&ref);
735 		entry.SetTo(&ref);
736 		entry.GetPath(&path);
737 		if (fSettings.ReplaceString("folderpaneldir", path.Path()) != B_OK)
738 			fSettings.AddString("folderpaneldir", path.Path());
739 
740 		fSettings.RemoveName("recentfolder");
741 		for (int32 i = 0; i < fPathList.CountItems(); i++) {
742 			fSettings.AddString("recentfolder", fPathList.ItemAt(i)->Path());
743 		}
744 
745 		fSettings.Flatten(&file);
746 	}
747 }
748 
749 
750 void
751 BackgroundsView::LoadSettings()
752 {
753 	fSettings.MakeEmpty();
754 
755 	BPath path;
756 	if (find_directory(B_USER_SETTINGS_DIRECTORY, &path) != B_OK)
757 		return;
758 
759 	path.Append(SETTINGS_FILE);
760 	BFile file(path.Path(), B_READ_ONLY);
761 	if (file.InitCheck() != B_OK)
762 		return;
763 
764 	if (fSettings.Unflatten(&file) != B_OK) {
765 		printf("Error unflattening settings file %s\n", path.Path());
766 		return;
767 	}
768 
769 	PRINT_OBJECT(fSettings);
770 
771 	BPoint point;
772 	if (fSettings.FindPoint("pos", &point) == B_OK)
773 		Window()->MoveTo(point);
774 
775 	BString string;
776 	if (fSettings.FindString("paneldir", &string) == B_OK)
777 		fPanel->SetPanelDirectory(string.String());
778 
779 	if (fSettings.FindString("folderpaneldir", &string) == B_OK)
780 		fFolderPanel->SetPanelDirectory(string.String());
781 
782 	int32 index = 0;
783 	while (fSettings.FindString("recentfolder", index, &string) == B_OK) {
784 		if (index == 0)
785 			fWorkspaceMenu->AddSeparatorItem();
786 
787 		BPath path(string.String());
788 		int32 i = AddPath(path);
789 		BString s;
790 		s << "Folder: " << path.Leaf();
791 		BMenuItem *item = new BMenuItem(s.String(),
792 			new BMessage(kMsgFolderSelected));
793 		fWorkspaceMenu->AddItem(item, -i-1+6);
794 		index++;
795 	}
796 	fWorkspaceMenu->SetTargetForItems(this);
797 
798 	PRINT(("Settings Loaded\n"));
799 }
800 
801 
802 void
803 BackgroundsView::WorkspaceActivated(uint32 oldWorkspaces, bool active)
804 {
805 	UpdateWithCurrent();
806 }
807 
808 
809 void
810 BackgroundsView::UpdatePreview()
811 {
812 	bool imageEnabled = !(fImageMenu->FindItem(kMsgNoImage)->IsMarked());
813 	if (fPlacementMenu->IsEnabled() ^ imageEnabled)
814 		fPlacementMenu->SetEnabled(imageEnabled);
815 	if (fIconLabelBackground->IsEnabled() ^ imageEnabled)
816 		fIconLabelBackground->SetEnabled(imageEnabled);
817 
818 	bool textEnabled = (fPlacementMenu->FindItem(kMsgManualPlacement)->IsMarked())
819 		&& imageEnabled;
820 	if (fXPlacementText->IsEnabled() ^ textEnabled)
821 		fXPlacementText->SetEnabled(textEnabled);
822 	if (fYPlacementText->IsEnabled() ^ textEnabled)
823 		fYPlacementText->SetEnabled(textEnabled);
824 
825 	if (textEnabled && (strcmp(fXPlacementText->Text(), "") == 0)) {
826 		fXPlacementText->SetText("0");
827 		fYPlacementText->SetText("0");
828 	}
829 	if (!textEnabled) {
830 		fXPlacementText->SetText(NULL);
831 		fYPlacementText->SetText(NULL);
832 	}
833 
834 	fXPlacementText->TextView()->MakeSelectable(textEnabled);
835 	fYPlacementText->TextView()->MakeSelectable(textEnabled);
836 	fXPlacementText->TextView()->MakeEditable(textEnabled);
837 	fYPlacementText->TextView()->MakeEditable(textEnabled);
838 
839 	fPreView->ClearViewBitmap();
840 
841 	int32 index = ((BGImageMenuItem*)fImageMenu->FindMarked())->ImageIndex();
842 	if (index >= 0) {
843 		BBitmap *bitmap = GetImage(index)->GetBitmap();
844 		if (bitmap) {
845 			BackgroundImage::BackgroundImageInfo *info =
846 				new BackgroundImage::BackgroundImageInfo(0, index,
847 					FindPlacementMode(), BPoint(atoi(fXPlacementText->Text()),
848 					atoi(fYPlacementText->Text())),
849 					fIconLabelBackground->Value() == B_CONTROL_ON, 0, 0);
850 			if (info->fMode == BackgroundImage::kAtOffset) {
851 				fPreView->SetEnabled(true);
852 				fPreView->fPoint.x = atoi(fXPlacementText->Text());
853 				fPreView->fPoint.y = atoi(fYPlacementText->Text());
854 			} else
855 				fPreView->SetEnabled(false);
856 
857 			fPreView->fImageBounds = BRect(bitmap->Bounds());
858 			fCurrent->Show(info, fPreView);
859 		}
860 	} else
861 		fPreView->SetEnabled(false);
862 
863 	fPreView->SetViewColor(fPicker->ValueAsColor());
864 	fPreView->Invalidate();
865 }
866 
867 
868 BackgroundImage::Mode
869 BackgroundsView::FindPlacementMode()
870 {
871 	BackgroundImage::Mode mode = BackgroundImage::kAtOffset;
872 
873 	if (fPlacementMenu->FindItem(kMsgCenterPlacement)->IsMarked())
874 		mode = BackgroundImage::kCentered;
875 	if (fPlacementMenu->FindItem(kMsgScalePlacement)->IsMarked())
876 		mode = BackgroundImage::kScaledToFit;
877 	if (fPlacementMenu->FindItem(kMsgManualPlacement)->IsMarked())
878 		mode = BackgroundImage::kAtOffset;
879 	if (fPlacementMenu->FindItem(kMsgTilePlacement)->IsMarked())
880 		mode = BackgroundImage::kTiled;
881 
882 	return mode;
883 }
884 
885 
886 #ifndef __HAIKU__
887 inline bool operator!=(const rgb_color& x, const rgb_color& y)
888 {
889 	return (x.red!=y.red || x.blue!=y.blue || x.green!=y.green);
890 }
891 #endif
892 
893 
894 void
895 BackgroundsView::UpdateButtons()
896 {
897 	bool hasChanged = false;
898 	if (fPicker->IsEnabled()
899 		&& fPicker->ValueAsColor() != BScreen().DesktopColor()) {
900 		hasChanged = true;
901 	} else if (fCurrentInfo) {
902 		if ((fIconLabelBackground->Value() == B_CONTROL_ON) ^
903 				fCurrentInfo->fEraseTextWidgetBackground) {
904 			hasChanged = true;
905 		} else if (FindPlacementMode() != fCurrentInfo->fMode) {
906 			hasChanged = true;
907 		} else if (fCurrentInfo->fImageIndex !=
908 				((BGImageMenuItem*)fImageMenu->FindMarked())->ImageIndex()) {
909 			hasChanged = true;
910 		} else if (fCurrent->IsDesktop()
911 			&& ((fCurrentInfo->fWorkspace != B_ALL_WORKSPACES)
912 				^ (fWorkspaceMenu->FindItem(kMsgCurrentWorkspace)->IsMarked()))) {
913 			hasChanged = true;
914 		} else if (fCurrentInfo->fMode == BackgroundImage::kAtOffset) {
915 			BString oldString, newString;
916 			oldString << (int)fCurrentInfo->fOffset.x;
917 			if (oldString != BString(fXPlacementText->Text())) {
918 				hasChanged = true;
919 			}
920 			oldString = "";
921 			oldString << (int)fCurrentInfo->fOffset.y;
922 			if (oldString != BString(fYPlacementText->Text())) {
923 				hasChanged = true;
924 			}
925 		}
926 	} else if (fImageMenu->IndexOf(fImageMenu->FindMarked()) > 0) {
927 		hasChanged = true;
928 	}
929 
930 	fApply->SetEnabled(hasChanged);
931 	fRevert->SetEnabled(hasChanged);
932 }
933 
934 
935 void
936 BackgroundsView::RefsReceived(BMessage *msg)
937 {
938 	entry_ref ref;
939 	int32 i = 0;
940 	BMimeType imageType("image");
941 	BPath desktopPath;
942 	find_directory(B_DESKTOP_DIRECTORY, &desktopPath);
943 
944 	while (msg->FindRef("refs", i++, &ref) == B_OK) {
945 		BPath path;
946 		BEntry entry(&ref, true);
947 		path.SetTo(&entry);
948 		BNode node(&entry);
949 
950 		if (node.IsFile()) {
951 			BNodeInfo nodeInfo(&node);
952 			char fileType[B_MIME_TYPE_LENGTH];
953 			if (nodeInfo.GetType(fileType) != B_OK)
954 				continue;
955 
956 			BMimeType refType(fileType);
957 			if (!imageType.Contains(&refType))
958 				continue;
959 
960 			BGImageMenuItem *item;
961 			int32 index = AddImage(path);
962 			if (index >= 0) {
963 				item = FindImageItem(index);
964 				fLastImageIndex = index;
965 			} else {
966 				const char* name = GetImage(-index-1)->GetName();
967 				item = new BGImageMenuItem(name, -index-1,
968 					new BMessage(kMsgImageSelected));
969 				AddItem(item);
970 				item->SetTarget(this);
971 				fLastImageIndex = -index-1;
972 			}
973 
974 			item->SetMarked(true);
975 			BMessenger(this).SendMessage(kMsgImageSelected);
976 		} else if (node.IsDirectory()) {
977 			if (desktopPath == path) {
978 				fWorkspaceMenu->FindItem(kMsgCurrentWorkspace)->SetMarked(true);
979 				BMessenger(this).SendMessage(kMsgCurrentWorkspace);
980 				break;
981 			}
982 			BMenuItem *item;
983 			int32 index = AddPath(path);
984 			if (index >= 0) {
985 				item = fWorkspaceMenu->ItemAt(index + 6);
986 				fLastWorkspaceIndex = index + 6;
987 			} else {
988 				if (fWorkspaceMenu->CountItems() <= 5)
989 					fWorkspaceMenu->AddSeparatorItem();
990 				BString s;
991 				s << "Folder: " << path.Leaf();
992 				item = new BMenuItem(s.String(), new BMessage(kMsgFolderSelected));
993 				fWorkspaceMenu->AddItem(item, -index-1+6);
994 				item->SetTarget(this);
995 				fLastWorkspaceIndex = -index-1 + 6;
996 			}
997 
998 			item->SetMarked(true);
999 			BMessenger(this).SendMessage(kMsgFolderSelected);
1000 		}
1001 	}
1002 }
1003 
1004 
1005 int32
1006 BackgroundsView::AddPath(BPath path)
1007 {
1008 	int32 count = fPathList.CountItems();
1009 	int32 index = 0;
1010 	for(; index < count; index++) {
1011 		BPath *p = fPathList.ItemAt(index);
1012 		int c = BString(p->Path()).ICompare(path.Path());
1013 		if (c == 0)
1014 			return index;
1015 
1016 		if (c > 0)
1017 			break;
1018 	}
1019 	fPathList.AddItem(new BPath(path), index);
1020 	return -index-1;
1021 }
1022 
1023 
1024 int32
1025 BackgroundsView::AddImage(BPath path)
1026 {
1027 	int32 count = fImageList.CountItems();
1028 	int32 index = 0;
1029 	for(; index < count; index++) {
1030 		Image *image = fImageList.ItemAt(index);
1031 		if (image->GetPath() == path)
1032 			return index;
1033 	}
1034 
1035 	fImageList.AddItem(new Image(path));
1036 	return -index-1;
1037 }
1038 
1039 
1040 void
1041 BackgroundsView::ProcessRefs(entry_ref dir, BMessage* refs)
1042 {
1043 	fWorkspaceMenu->FindItem(kMsgDefaultFolder)->SetMarked(true);
1044 	BMessenger messenger(this);
1045 	messenger.SendMessage(kMsgDefaultFolder);
1046 
1047 	if (refs->CountNames(B_REF_TYPE) > 0) {
1048 		messenger.SendMessage(refs);
1049 	} else {
1050 		BMessage message(B_REFS_RECEIVED);
1051 		message.AddRef("refs", &dir);
1052 		messenger.SendMessage(&message);
1053 	}
1054 }
1055 
1056 
1057 Image*
1058 BackgroundsView::GetImage(int32 imageIndex)
1059 {
1060 	return fImageList.ItemAt(imageIndex);
1061 }
1062 
1063 
1064 BGImageMenuItem*
1065 BackgroundsView::FindImageItem(const int32 imageIndex)
1066 {
1067 	if (imageIndex < 0)
1068 		return (BGImageMenuItem *)fImageMenu->ItemAt(0);
1069 
1070 	int32 count = fImageMenu->CountItems() - 2;
1071 	int32 index = 2;
1072 	for (; index < count; index++) {
1073 		BGImageMenuItem *image = (BGImageMenuItem *)fImageMenu->ItemAt(index);
1074 		if (image->ImageIndex() == imageIndex)
1075 			return image;
1076 	}
1077 	return NULL;
1078 }
1079 
1080 
1081 bool
1082 BackgroundsView::AddItem(BGImageMenuItem *item)
1083 {
1084 	int32 count = fImageMenu->CountItems() - 2;
1085 	int32 index = 2;
1086 	if (count < index) {
1087 		fImageMenu->AddItem(new BSeparatorItem(), 1);
1088 		count = fImageMenu->CountItems() - 2;
1089 	}
1090 
1091 	for (; index < count; index++) {
1092 		BGImageMenuItem* image = (BGImageMenuItem *)fImageMenu->ItemAt(index);
1093 		int c = (BString(image->Label()).ICompare(BString(item->Label())));
1094 		if (c > 0)
1095 			break;
1096 	}
1097 	return fImageMenu->AddItem(item, index);
1098 }
1099 
1100 
1101 //	#pragma mark -
1102 
1103 
1104 PreView::PreView(BRect frame, const char *name, int32 resize, int32 flags)
1105 	: BControl(frame, name, NULL, NULL, resize, flags),
1106 	fMoveHandCursor(kHandCursorData)
1107 {
1108 }
1109 
1110 
1111 void
1112 PreView::AttachedToWindow()
1113 {
1114 	rgb_color color = ViewColor();
1115 	BControl::AttachedToWindow();
1116 	SetViewColor(color);
1117 }
1118 
1119 
1120 void
1121 PreView::MouseDown(BPoint point)
1122 {
1123 	if (IsEnabled() && Bounds().Contains(point)) {
1124 		uint32 buttons;
1125 		GetMouse(&point, &buttons);
1126 	 	if(buttons & B_PRIMARY_MOUSE_BUTTON) {
1127 			fOldPoint = point;
1128 			SetTracking(true);
1129 			BScreen().GetMode(&mode);
1130 			x_ratio = Bounds().Width() / mode.virtual_width;
1131 			y_ratio = Bounds().Height() / mode.virtual_height;
1132 			SetMouseEventMask(B_POINTER_EVENTS,
1133 				B_LOCK_WINDOW_FOCUS | B_NO_POINTER_HISTORY);
1134 		}
1135 	}
1136 }
1137 
1138 
1139 void
1140 PreView::MouseUp(BPoint point)
1141 {
1142 	if (IsTracking())
1143 		SetTracking(false);
1144 }
1145 
1146 
1147 void
1148 PreView::MouseMoved(BPoint point, uint32 transit, const BMessage *message)
1149 {
1150 	if (IsEnabled())
1151 		SetViewCursor(&fMoveHandCursor);
1152 	else
1153 		SetViewCursor(B_CURSOR_SYSTEM_DEFAULT);
1154 
1155 	if (IsTracking()) {
1156 		float x, y;
1157 		x = fPoint.x + (point.x - fOldPoint.x)/ x_ratio;
1158 		y = fPoint.y + (point.y - fOldPoint.y)/ y_ratio;
1159 		bool min, max, mustSend = false;
1160 		min = (x > -fImageBounds.Width());
1161 		max = (x < mode.virtual_width);
1162 		if (min && max) {
1163 			fOldPoint.x = point.x;
1164 			fPoint.x = x;
1165 			mustSend = true;
1166 		} else {
1167 			if (!min && fPoint.x > -fImageBounds.Width()) {
1168 				fPoint.x = -fImageBounds.Width();
1169 				fOldPoint.x = point.x - (x - fPoint.x) * x_ratio;
1170 				mustSend = true;
1171 			}
1172 			if (!max && fPoint.x < mode.virtual_width) {
1173 				fPoint.x = mode.virtual_width;
1174 				fOldPoint.x = point.x - (x - fPoint.x) * x_ratio;
1175 				mustSend = true;
1176 			}
1177 		}
1178 
1179 		min = (y > -fImageBounds.Height());
1180 		max = (y < mode.virtual_height);
1181 		if (min && max) {
1182 			fOldPoint.y = point.y;
1183 			fPoint.y = y;
1184 			mustSend = true;
1185 		} else {
1186 			if (!min && fPoint.y > -fImageBounds.Height()) {
1187 				fPoint.y = -fImageBounds.Height();
1188 				fOldPoint.y = point.y - (y - fPoint.y) * y_ratio;
1189 				mustSend = true;
1190 			}
1191 			if (!max && fPoint.y < mode.virtual_height) {
1192 				fPoint.y = mode.virtual_height;
1193 				fOldPoint.y = point.y - (y - fPoint.y) * y_ratio;
1194 				mustSend = true;
1195 			}
1196 		}
1197 
1198 		if (mustSend) {
1199 			BMessenger messenger(Parent());
1200 			messenger.SendMessage(kMsgUpdatePreviewPlacement);
1201 		}
1202 	}
1203 	BControl::MouseMoved(point, transit, message);
1204 }
1205 
1206 
1207 //	#pragma mark -
1208 
1209 
1210 PreviewBox::PreviewBox(BRect frame, const char *name)
1211 	: BBox(frame, name)
1212 {
1213 	fIsDesktop = true;
1214 }
1215 
1216 
1217 void
1218 PreviewBox::Draw(BRect rect)
1219 {
1220 	rgb_color color = HighColor();
1221 	BPoint points[] = {
1222 		BPoint(11,19), BPoint(139,19), BPoint(141,21),
1223 		BPoint(141,119), BPoint(139,121), BPoint(118,121),
1224 		BPoint(118,126), BPoint(117,127), BPoint(33,127),
1225 		BPoint(32,126), BPoint(32,121),BPoint(11,121),
1226 		BPoint(9,119),BPoint(9,21),BPoint(11,19)
1227 	};
1228 
1229 	SetHighColor(LowColor());
1230 	FillRect(BRect(9,19,141,127));
1231 
1232 	if (fIsDesktop) {
1233 		SetHighColor(184,184,184);
1234 		FillPolygon(points, 15);
1235 		SetHighColor(96,96,96);
1236 		StrokePolygon(points, 15);
1237 		FillRect(BRect(107,121,111,123));
1238 		SetHighColor(0,0,0);
1239 		StrokeRect(BRect(14,24,136,116));
1240 		SetHighColor(0,255,0);
1241 		FillRect(BRect(101,122,103,123));
1242 	} else {
1243 		SetHighColor(152,152,152);
1244 		StrokeLine(BPoint(11,13), BPoint(67,13));
1245 		StrokeLine(BPoint(67,21));
1246 		StrokeLine(BPoint(139,21));
1247 		StrokeLine(BPoint(139,119));
1248 		StrokeLine(BPoint(11,119));
1249 		StrokeLine(BPoint(11,13));
1250 		StrokeRect(BRect(14,24,136,116));
1251 		SetHighColor(255,203,0);
1252 		FillRect(BRect(12,14,66,21));
1253 		SetHighColor(240,240,240);
1254 		StrokeRect(BRect(12,22,137,117));
1255 		StrokeLine(BPoint(138,22), BPoint(138,22));
1256 		StrokeLine(BPoint(12,118), BPoint(12,118));
1257 		SetHighColor(200,200,200);
1258 		StrokeRect(BRect(13,23,138,118));
1259 	}
1260 
1261 	SetHighColor(color);
1262 	BBox::Draw(rect);
1263 }
1264 
1265 
1266 void
1267 PreviewBox::SetDesktop(bool isDesktop)
1268 {
1269 	fIsDesktop = isDesktop;
1270 	Invalidate();
1271 }
1272 
1273 
1274 //	#pragma mark -
1275 
1276 
1277 BGImageMenuItem::BGImageMenuItem(const char *label, int32 imageIndex,
1278 	BMessage *message, char shortcut, uint32 modifiers)
1279 	: BMenuItem(label, message, shortcut, modifiers),
1280 	fImageIndex(imageIndex)
1281 {
1282 }
1283