xref: /haiku/src/kits/tracker/BackgroundImage.cpp (revision 2222d0559df303a9846a2fad53741f8b20b14d7c)
1 /*
2 Open Tracker License
3 
4 Terms and Conditions
5 
6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
7 
8 Permission is hereby granted, free of charge, to any person obtaining a copy of
9 this software and associated documentation files (the "Software"), to deal in
10 the Software without restriction, including without limitation the rights to
11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12 of the Software, and to permit persons to whom the Software is furnished to do
13 so, subject to the following conditions:
14 
15 The above copyright notice and this permission notice applies to all licensees
16 and shall be included in all copies or substantial portions of the Software.
17 
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 
25 Except as contained in this notice, the name of Be Incorporated shall not be
26 used in advertising or otherwise to promote the sale, use or other dealings in
27 this Software without prior written authorization from Be Incorporated.
28 
29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30 of Be Incorporated in the United States and other countries. Other brand product
31 names are registered trademarks or trademarks of their respective holders.
32 All rights reserved.
33 */
34 
35 //  Classes used for setting up and managing background images
36 //
37 
38 #include <Bitmap.h>
39 #include <Node.h>
40 #include <TranslationKit.h>
41 #include <View.h>
42 #include <Window.h>
43 
44 #include <fs_attr.h>
45 
46 #include "BackgroundImage.h"
47 
48 #include "Background.h"
49 #include "Commands.h"
50 #include "PoseView.h"
51 
52 namespace BPrivate {
53 
54 const char *kBackgroundImageInfo 			= B_BACKGROUND_INFO;
55 const char *kBackgroundImageInfoOffset 		= B_BACKGROUND_ORIGIN;
56 const char *kBackgroundImageInfoTextOutline	= B_BACKGROUND_TEXT_OUTLINE;
57 const char *kBackgroundImageInfoMode 		= B_BACKGROUND_MODE;
58 const char *kBackgroundImageInfoWorkspaces 	= B_BACKGROUND_WORKSPACES;
59 const char *kBackgroundImageInfoPath 		= B_BACKGROUND_IMAGE;
60 
61 }
62 
63 BackgroundImage *
64 BackgroundImage::GetBackgroundImage(const BNode *node, bool isDesktop)
65 {
66 	attr_info info;
67 	if (node->GetAttrInfo(kBackgroundImageInfo, &info) != B_OK)
68 		return NULL;
69 
70 	BMessage container;
71 	char *buffer = new char [info.size];
72 
73 	status_t error = node->ReadAttr(kBackgroundImageInfo, info.type, 0, buffer, (size_t)info.size);
74 	if (error == info.size)
75 		error = container.Unflatten(buffer);
76 
77 	delete [] buffer;
78 
79 	if (error != B_OK)
80 		return NULL;
81 
82 	BackgroundImage *result = NULL;
83 	for (int32 index = 0; ; index++) {
84 		const char *path;
85 		uint32 workspaces = B_ALL_WORKSPACES;
86 		Mode mode = kTiled;
87 		bool textWidgetLabelOutline = false;
88 		BPoint offset;
89 		BBitmap *bitmap = NULL;
90 
91 		if (container.FindString(kBackgroundImageInfoPath, index, &path) == B_OK) {
92 			bitmap = BTranslationUtils::GetBitmap(path);
93 			if (!bitmap) {
94 				PRINT(("failed to load background bitmap from path\n"));
95 			}
96 		} else
97 			break;
98 
99 		container.FindInt32(kBackgroundImageInfoWorkspaces, index, (int32 *)&workspaces);
100 		container.FindInt32(kBackgroundImageInfoMode, index, (int32 *)&mode);
101 		container.FindBool(kBackgroundImageInfoTextOutline, index, &textWidgetLabelOutline);
102 		container.FindPoint(kBackgroundImageInfoOffset, index, &offset);
103 
104 		BackgroundImage::BackgroundImageInfo *imageInfo = new
105 			BackgroundImage::BackgroundImageInfo(workspaces, bitmap, mode, offset,
106 				textWidgetLabelOutline);
107 
108 		if (!result)
109 			result = new BackgroundImage(node, isDesktop);
110 
111 		result->Add(imageInfo);
112 	}
113 	return result;
114 }
115 
116 
117 BackgroundImage::BackgroundImageInfo::BackgroundImageInfo(uint32 workspaces,
118 	BBitmap *bitmap, Mode mode, BPoint offset, bool textWidgetOutline)
119 	:	fWorkspace(workspaces),
120 		fBitmap(bitmap),
121 		fMode(mode),
122 		fOffset(offset),
123 		fTextWidgetOutline(textWidgetOutline)
124 {
125 }
126 
127 
128 BackgroundImage::BackgroundImageInfo::~BackgroundImageInfo()
129 {
130 	delete fBitmap;
131 }
132 
133 
134 BackgroundImage::BackgroundImage(const BNode *node, bool desktop)
135 	:	fIsDesktop(desktop),
136 		fDefinedByNode(*node),
137 		fView(NULL),
138 		fShowingBitmap(NULL),
139 		fBitmapForWorkspaceList(1, true)
140 {
141 }
142 
143 
144 BackgroundImage::~BackgroundImage()
145 {
146 }
147 
148 
149 void
150 BackgroundImage::Add(BackgroundImageInfo *info)
151 {
152 	fBitmapForWorkspaceList.AddItem(info);
153 }
154 
155 
156 void
157 BackgroundImage::Show(BView *view, int32 workspace)
158 {
159 	fView = view;
160 
161 	BackgroundImageInfo *info = ImageInfoForWorkspace(workspace);
162 	if (info) {
163 		BPoseView *poseView = dynamic_cast<BPoseView *>(fView);
164 		if (poseView)
165 			poseView->SetWidgetTextOutline(info->fTextWidgetOutline);
166 		Show(info, fView);
167 	}
168 }
169 
170 void
171 BackgroundImage::Show(BackgroundImageInfo *info, BView *view)
172 {
173 	BPoseView *poseView = dynamic_cast<BPoseView *>(view);
174 	if (poseView)
175 		poseView->SetWidgetTextOutline(info->fTextWidgetOutline);
176 
177 	if (info->fBitmap == NULL) {
178 		view->ClearViewBitmap();
179 		view->Invalidate();
180 		fShowingBitmap = info;
181 		return;
182 	}
183 	BRect viewBounds(view->Bounds());
184 	BRect bitmapBounds(info->fBitmap->Bounds());
185 	BRect destinationBitmapBounds(bitmapBounds);
186 
187 	uint32 tile = 0;
188 	uint32 followFlags = B_FOLLOW_TOP | B_FOLLOW_LEFT;
189 
190 	// figure out the display mode and the destination bounds for the bitmap
191 	switch (info->fMode) {
192 		case kCentered:
193 			if (fIsDesktop) {
194 				destinationBitmapBounds.OffsetBy(
195 					(viewBounds.Width() - bitmapBounds.Width()) / 2,
196 					(viewBounds.Height() - bitmapBounds.Height()) / 2);
197 				break;
198 			}
199 			// else fall thru
200 		case kScaledToFit:
201 			if (fIsDesktop) {
202 				destinationBitmapBounds = viewBounds;
203 				followFlags = B_FOLLOW_ALL;
204 				break;
205 			}
206 			// else fall thru
207 		case kAtOffset:
208 			destinationBitmapBounds.OffsetTo(info->fOffset);
209 			break;
210 		case kTiled:
211 			if (fIsDesktop) {
212 				destinationBitmapBounds.OffsetBy(
213 					(viewBounds.Width() - bitmapBounds.Width()) / 2,
214 					(viewBounds.Height() - bitmapBounds.Height()) / 2);
215 			}
216 			tile = B_TILE_BITMAP;
217 			break;
218 	}
219 
220 	// switch to the bitmap and force a redraw
221 	view->SetViewBitmap(info->fBitmap, bitmapBounds, destinationBitmapBounds,
222 		followFlags, tile);
223 	view->Invalidate();
224 	fShowingBitmap = info;
225 }
226 
227 void
228 BackgroundImage::Remove()
229 {
230 	if (fShowingBitmap) {
231 		fView->ClearViewBitmap();
232 		fView->Invalidate();
233 		BPoseView *poseView = dynamic_cast<BPoseView *>(fView);
234 		// make sure text widgets draw the default way, erasing their background
235 		if (poseView)
236 			poseView->SetWidgetTextOutline(true);
237 	}
238 	fShowingBitmap = NULL;
239 }
240 
241 BackgroundImage::BackgroundImageInfo *
242 BackgroundImage::ImageInfoForWorkspace(int32 workspace) const
243 {
244 	uint32 workspaceMask = 1;
245 
246 	for ( ; workspace; workspace--)
247 		workspaceMask *= 2;
248 
249 	int32 count = fBitmapForWorkspaceList.CountItems();
250 
251 	// do a simple lookup for the most likely candidate bitmap -
252 	// pick the imageInfo that is only defined for this workspace over one
253 	// that supports multiple workspaces
254 	BackgroundImageInfo *result = NULL;
255 	for (int32 index = 0; index < count; index++) {
256 		BackgroundImageInfo *info = fBitmapForWorkspaceList.ItemAt(index);
257 		if (info->fWorkspace == workspaceMask)
258 			return info;
259 		if (info->fWorkspace & workspaceMask)
260 			result = info;
261 	}
262 
263 	return result;
264 }
265 
266 void
267 BackgroundImage::WorkspaceActivated(BView *view, int32 workspace, bool state)
268 {
269 	if (!fIsDesktop)
270 		// we only care for desktop bitmaps
271 		return;
272 
273 	if (!state)
274 		// we only care comming into a new workspace, not leaving one
275 		return;
276 
277 	BackgroundImageInfo *info = ImageInfoForWorkspace(workspace);
278 
279 	if (info != fShowingBitmap) {
280 		if (info)
281 			Show(info, view);
282 		else {
283 			if (BPoseView *poseView = dynamic_cast<BPoseView *>(view))
284 				poseView->SetWidgetTextOutline(true);
285 			view->ClearViewBitmap();
286 			view->Invalidate();
287 		}
288 		fShowingBitmap = info;
289 	}
290 }
291 
292 void
293 BackgroundImage::ScreenChanged(BRect, color_space)
294 {
295 	if (!fIsDesktop || !fShowingBitmap)
296 		return;
297 
298 	if (fShowingBitmap->fMode == kCentered) {
299 		BRect viewBounds(fView->Bounds());
300 		BRect bitmapBounds(fShowingBitmap->fBitmap->Bounds());
301 		BRect destinationBitmapBounds(bitmapBounds);
302 		destinationBitmapBounds.OffsetBy(
303 			(viewBounds.Width() - bitmapBounds.Width()) / 2,
304 			(viewBounds.Height() - bitmapBounds.Height()) / 2);
305 
306 		fView->SetViewBitmap(fShowingBitmap->fBitmap, bitmapBounds, destinationBitmapBounds,
307 			B_FOLLOW_NONE, 0);
308 		fView->Invalidate();
309 	}
310 }
311 
312 BackgroundImage *
313 BackgroundImage::Refresh(BackgroundImage *oldBackgroundImage,
314 	const BNode *fromNode, bool desktop, BPoseView *poseView)
315 {
316 	if (oldBackgroundImage) {
317 		oldBackgroundImage->Remove();
318 		delete oldBackgroundImage;
319 	}
320 
321 	BackgroundImage *result = GetBackgroundImage(fromNode, desktop);
322 	if (result && poseView->ViewMode() != kListMode)
323 		result->Show(poseView, current_workspace());
324 
325 	return result;
326 }
327 
328