6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
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:
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.
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.
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.
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.
35 // Classes used for setting up and managing background images
38 #include "BackgroundImage.h"
47 #include <TranslationKit.h>
56 #include "BackgroundsView.h"
59 const char* kBackgroundImageInfo
= "be:bgndimginfo";
60 const char* kBackgroundImageInfoOffset
= "be:bgndimginfooffset";
61 // const char* kBackgroundImageInfoTextOutline = "be:bgndimginfotextoutline";
62 const char* kBackgroundImageInfoTextOutline
= "be:bgndimginfoerasetext";
63 // NOTE: the attribute keeps the old name for backwards compatibility,
64 // just in case some users spend time configuring a few windows with
65 // this feature on or off...
66 const char* kBackgroundImageInfoMode
= "be:bgndimginfomode";
67 const char* kBackgroundImageInfoWorkspaces
= "be:bgndimginfoworkspaces";
68 const char* kBackgroundImageInfoPath
= "be:bgndimginfopath";
69 const char* kBackgroundImageInfoSet
= "be:bgndimginfoset";
70 const char* kBackgroundImageInfoCacheMode
= "be:bgndimginfocachemode";
71 const char* kBackgroundImageSetPeriod
= "be:bgndimgsetperiod";
72 const char* kBackgroundImageRandomChange
= "be:bgndimgrandomchange";
73 const char* kBackgroundImageCacheMode
= "be:bgndimgcachemode";
77 BackgroundImage::GetBackgroundImage(const BNode
* node
, bool isDesktop
,
78 BackgroundsView
* view
)
80 BackgroundImage
* result
= new BackgroundImage(node
, isDesktop
, view
);
82 if (node
->GetAttrInfo(kBackgroundImageInfo
, &info
) != B_OK
)
86 char* buffer
= new char [info
.size
];
88 status_t error
= node
->ReadAttr(kBackgroundImageInfo
, info
.type
, 0, buffer
,
90 if (error
== info
.size
)
91 error
= container
.Unflatten(buffer
);
98 PRINT_OBJECT(container
);
100 uint32 imageSetPeriod
= 0;
101 uint32 globalCacheMode
= 0;
102 bool randomChange
= false;
103 uint32 maxImageSet
= 0;
106 container
.FindInt32(kBackgroundImageSetPeriod
, (int32
*)&imageSetPeriod
);
107 container
.FindInt32(kBackgroundImageCacheMode
,
108 (int32
*)&globalCacheMode
);
109 container
.FindBool(kBackgroundImageRandomChange
, &randomChange
);
112 for (int32 index
= 0; ; index
++) {
114 uint32 workspaces
= B_ALL_WORKSPACES
;
116 bool textWidgetLabelOutline
= false;
119 uint32 cacheMode
= 0;
120 int32 imageIndex
= -1;
122 if (container
.FindString(kBackgroundImageInfoPath
, index
, &path
)
124 if (strcmp(path
, "")) {
126 imageIndex
= view
->AddImage(bpath
);
127 if (imageIndex
< 0) {
128 imageIndex
= -imageIndex
- 1;
134 container
.FindInt32(kBackgroundImageInfoWorkspaces
, index
,
135 (int32
*)&workspaces
);
136 container
.FindInt32(kBackgroundImageInfoMode
, index
, (int32
*)&mode
);
137 container
.FindBool(kBackgroundImageInfoTextOutline
, index
,
138 &textWidgetLabelOutline
);
139 container
.FindPoint(kBackgroundImageInfoOffset
, index
, &offset
);
142 container
.FindInt32(kBackgroundImageInfoSet
, index
,
144 container
.FindInt32(kBackgroundImageInfoCacheMode
, index
,
148 BackgroundImage::BackgroundImageInfo
* imageInfo
= new
149 BackgroundImage::BackgroundImageInfo(workspaces
, imageIndex
,
150 mode
, offset
, textWidgetLabelOutline
, imageSet
, cacheMode
);
152 // imageInfo->UnloadBitmap(globalCacheMode);
154 if (imageSet
> maxImageSet
)
155 maxImageSet
= imageSet
;
157 result
->Add(imageInfo
);
161 result
->fImageSetCount
= maxImageSet
+ 1;
162 result
->fRandomChange
= randomChange
;
163 result
->fImageSetPeriod
= imageSetPeriod
;
164 result
->fCacheMode
= globalCacheMode
;
165 if (result
->fImageSetCount
> 1)
166 result
->fShowingImageSet
= random() % result
->fImageSetCount
;
173 BackgroundImage::BackgroundImageInfo::BackgroundImageInfo(uint32 workspaces
,
174 int32 imageIndex
, Mode mode
, BPoint offset
, bool textWidgetLabelOutline
,
175 uint32 imageSet
, uint32 cacheMode
)
177 fWorkspace(workspaces
),
178 fImageIndex(imageIndex
),
181 fTextWidgetLabelOutline(textWidgetLabelOutline
),
183 fCacheMode(cacheMode
)
188 BackgroundImage::BackgroundImageInfo::~BackgroundImageInfo()
196 BackgroundImage::BackgroundImage(const BNode
* node
, bool desktop
,
197 BackgroundsView
* view
)
200 fDefinedByNode(*node
),
202 fBackgroundsView(view
),
203 fShowingBitmap(NULL
),
204 fBitmapForWorkspaceList(1, true),
214 BackgroundImage::~BackgroundImage()
220 BackgroundImage::Add(BackgroundImageInfo
* info
)
222 fBitmapForWorkspaceList
.AddItem(info
);
227 BackgroundImage::Remove(BackgroundImageInfo
* info
)
229 fBitmapForWorkspaceList
.RemoveItem(info
);
234 BackgroundImage::RemoveAll()
236 for (int32 index
= 0; index
< fBitmapForWorkspaceList
.CountItems();) {
237 BackgroundImageInfo
* info
= fBitmapForWorkspaceList
.ItemAt(index
);
238 if (info
->fImageSet
!= fShowingImageSet
)
241 fBitmapForWorkspaceList
.RemoveItemAt(index
);
247 BackgroundImage::Show(BView
* view
, int32 workspace
)
251 BackgroundImageInfo
* info
= ImageInfoForWorkspace(workspace
);
253 /*BPoseView* poseView = dynamic_cast<BPoseView*>(fView);
256 ->SetEraseWidgetTextBackground(info->fTextWidgetLabelOutline);*/
263 BackgroundImage::Show(BackgroundImageInfo
* info
, BView
* view
)
266 = fBackgroundsView
->GetImage(info
->fImageIndex
)->GetBitmap();
271 BRect
viewBounds(view
->Bounds());
274 BScreen().GetMode(&mode
);
275 float x_ratio
= viewBounds
.Width() / mode
.virtual_width
;
276 float y_ratio
= viewBounds
.Height() / mode
.virtual_height
;
278 BRect
bitmapBounds(bitmap
->Bounds());
279 BRect
destinationBitmapBounds(bitmapBounds
);
280 destinationBitmapBounds
.right
*= x_ratio
;
281 destinationBitmapBounds
.bottom
*= y_ratio
;
282 BPoint
offset(info
->fOffset
);
287 uint32 followFlags
= B_FOLLOW_TOP
| B_FOLLOW_LEFT
;
289 // figure out the display mode and the destination bounds for the bitmap
290 switch (info
->fMode
) {
293 destinationBitmapBounds
.OffsetBy(
294 (viewBounds
.Width() - destinationBitmapBounds
.Width()) / 2,
295 (viewBounds
.Height() - destinationBitmapBounds
.Height())
302 if (BRectRatio(destinationBitmapBounds
)
303 >= BRectRatio(viewBounds
)) {
304 float overlap
= BRectHorizontalOverlap(viewBounds
,
305 destinationBitmapBounds
);
306 destinationBitmapBounds
.Set(-overlap
, 0,
307 viewBounds
.Width() + overlap
, viewBounds
.Height());
309 float overlap
= BRectVerticalOverlap(viewBounds
,
310 destinationBitmapBounds
);
311 destinationBitmapBounds
.Set(0, -overlap
,
312 viewBounds
.Width(), viewBounds
.Height() + overlap
);
314 followFlags
= B_FOLLOW_ALL
;
315 options
|= B_FILTER_BITMAP_BILINEAR
;
321 destinationBitmapBounds
.OffsetTo(offset
);
325 // Original Backgrounds Preferences center the tiled paper
326 // but Tracker doesn't do that
328 destinationBitmapBounds
.OffsetBy(
329 (viewBounds
.Width() - destinationBitmapBounds
.Width()) / 2,
330 (viewBounds
.Height() - destinationBitmapBounds
.Height()) / 2);
332 options
|= B_TILE_BITMAP
;
336 // switch to the bitmap and force a redraw
337 view
->SetViewBitmap(bitmap
, bitmapBounds
, destinationBitmapBounds
,
338 followFlags
, options
);
341 /*if (fShowingBitmap != info) {
343 fShowingBitmap->UnloadBitmap(fCacheMode);
344 fShowingBitmap = info;
350 BackgroundImage::BRectRatio(BRect rect
)
352 return rect
.Width() / rect
.Height();
357 BackgroundImage::BRectHorizontalOverlap(BRect hostRect
, BRect resizedRect
)
359 return ((hostRect
.Height() / resizedRect
.Height() * resizedRect
.Width())
360 - hostRect
.Width()) / 2;
365 BackgroundImage::BRectVerticalOverlap(BRect hostRect
, BRect resizedRect
)
367 return ((hostRect
.Width() / resizedRect
.Width() * resizedRect
.Height())
368 - hostRect
.Height()) / 2;
373 BackgroundImage::Remove()
375 if (fShowingBitmap
) {
376 fView
->ClearViewBitmap();
378 /*BPoseView* poseView = dynamic_cast<BPoseView*>(fView);
379 // make sure text widgets draw the default way, erasing their background
381 poseView->SetEraseWidgetTextBackground(true);*/
383 fShowingBitmap
= NULL
;
387 BackgroundImage::BackgroundImageInfo
*
388 BackgroundImage::ImageInfoForWorkspace(int32 workspace
) const
390 uint32 workspaceMask
= 1;
392 for (; workspace
; workspace
--)
395 int32 count
= fBitmapForWorkspaceList
.CountItems();
397 // do a simple lookup for the most likely candidate bitmap -
398 // pick the imageInfo that is only defined for this workspace over one
399 // that supports multiple workspaces
400 BackgroundImageInfo
* result
= NULL
;
401 for (int32 index
= 0; index
< count
; index
++) {
402 BackgroundImageInfo
* info
= fBitmapForWorkspaceList
.ItemAt(index
);
403 if (info
->fImageSet
!= fShowingImageSet
)
407 if (info
->fWorkspace
== workspaceMask
)
410 if (info
->fWorkspace
& workspaceMask
)
420 BackgroundImage::WorkspaceActivated(BView
* view
, int32 workspace
, bool state
)
423 // we only care for desktop bitmaps
428 // we only care comming into a new workspace, not leaving one
432 BackgroundImageInfo
* info
= ImageInfoForWorkspace(workspace
);
433 if (info
!= fShowingBitmap
) {
437 /*if (BPoseView* poseView = dynamic_cast<BPoseView*>(view))
438 poseView->SetEraseWidgetTextBackground(true);*/
439 view
->ClearViewBitmap();
442 fShowingBitmap
= info
;
448 BackgroundImage::ScreenChanged(BRect
, color_space
)
450 if (!fIsDesktop
|| !fShowingBitmap
)
453 /*if (fShowingBitmap->fMode == kCentered) {
454 BRect viewBounds(fView->Bounds());
455 BRect bitmapBounds(fShowingBitmap->fBitmap->Bounds());
456 BRect destinationBitmapBounds(bitmapBounds);
457 destinationBitmapBounds.OffsetBy(
458 (viewBounds.Width() - bitmapBounds.Width()) / 2,
459 (viewBounds.Height() - bitmapBounds.Height()) / 2);
461 fView->SetViewBitmap(fShowingBitmap->fBitmap, bitmapBounds,
462 destinationBitmapBounds, B_FOLLOW_NONE, 0);
469 BackgroundImage::SetBackgroundImage(BNode
* node
)
473 int32 count
= fBitmapForWorkspaceList
.CountItems();
475 for (int32 index
= 0; index
< count
; index
++) {
476 BackgroundImageInfo
* info
= fBitmapForWorkspaceList
.ItemAt(index
);
478 container
.AddBool(kBackgroundImageInfoTextOutline
,
479 info
->fTextWidgetLabelOutline
);
480 if (fBackgroundsView
->GetImage(info
->fImageIndex
) != NULL
) {
481 container
.AddString(kBackgroundImageInfoPath
,
483 ->GetImage(info
->fImageIndex
)->GetPath().Path());
485 container
.AddString(kBackgroundImageInfoPath
, "");
487 container
.AddInt32(kBackgroundImageInfoWorkspaces
, info
->fWorkspace
);
488 container
.AddPoint(kBackgroundImageInfoOffset
, info
->fOffset
);
489 container
.AddInt32(kBackgroundImageInfoMode
, info
->fMode
);
492 container
.AddInt32(kBackgroundImageInfoSet
, info
->fImageSet
);
495 PRINT_OBJECT(container
);
497 ssize_t flattenedSize
= container
.FlattenedSize();
498 if (flattenedSize
< B_OK
)
499 return flattenedSize
;
501 char* buffer
= new(std::nothrow
) char[flattenedSize
];
505 if ((err
= container
.Flatten(buffer
, flattenedSize
)) != B_OK
) {
510 ssize_t size
= node
->WriteAttr(kBackgroundImageInfo
, B_MESSAGE_TYPE
,
511 0, buffer
, flattenedSize
);
517 if (size
!= flattenedSize
)
525 BackgroundImage::Refresh(BackgroundImage* oldBackgroundImage,
526 const BNode* fromNode, bool desktop, BPoseView* poseView)
528 if (oldBackgroundImage) {
529 oldBackgroundImage->Remove();
530 delete oldBackgroundImage;
533 BackgroundImage* result = GetBackgroundImage(fromNode, desktop);
534 if (result && poseView->ViewMode() != kListMode)
535 result->Show(poseView, current_workspace());
541 BackgroundImage::ChangeImageSet(BPoseView* poseView)
544 if (fImageSetCount > 1) {
545 uint32 oldShowingImageSet = fShowingImageSet;
546 while (oldShowingImageSet == fShowingImageSet)
547 fShowingImageSet = random()%fImageSetCount;
549 fShowingImageSet = 0;
552 if (fShowingImageSet > fImageSetCount - 1)
553 fShowingImageSet = 0;
556 this->Show(poseView, current_workspace());
563 Image::Image(BPath path
)
568 const int32 kMaxNameChars
= 40;
570 int extra
= fName
.CountChars() - kMaxNameChars
;
573 int offset
= fName
.FindLast('.');
575 fName
.CopyInto(extension
, ++offset
, -1);
576 fName
.TruncateChars(kMaxNameChars
) << B_UTF8_ELLIPSIS
<< extension
;
591 fBitmap
= BTranslationUtils::GetBitmap(fPath
.Path());