2 * Copyright 2006-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3 * Distributed under the terms of the MIT License.
13 #include <Application.h>
14 #include <AppFileInfo.h>
15 #include <Attributes.h>
18 #include <IconEditorProtocol.h>
19 #include <IconUtils.h>
23 #include <NodeMonitor.h>
24 #include <PopUpMenu.h>
25 #include <Resources.h>
29 #include "FileTypes.h"
30 #include "MimeTypeListView.h"
33 #undef B_TRANSLATION_CONTEXT
34 #define B_TRANSLATION_CONTEXT "Icon View"
41 icon_for_type(const BMimeType
& type
, uint8
** _data
, size_t* _size
,
44 if (_data
== NULL
|| _size
== NULL
)
47 icon_source source
= kNoIcon
;
51 if (type
.GetIcon(&data
, &size
) == B_OK
)
54 if (source
== kNoIcon
) {
55 // check for icon from preferred app
57 char preferred
[B_MIME_TYPE_LENGTH
];
58 if (type
.GetPreferredApp(preferred
) == B_OK
) {
59 BMimeType
preferredApp(preferred
);
61 if (preferredApp
.GetIconForType(type
.Type(), &data
, &size
) == B_OK
)
62 source
= kApplicationIcon
;
66 if (source
== kNoIcon
) {
67 // check super type for an icon
70 if (type
.GetSupertype(&superType
) == B_OK
) {
71 if (superType
.GetIcon(&data
, &size
) == B_OK
)
72 source
= kSupertypeIcon
;
74 // check the super type's preferred app
75 char preferred
[B_MIME_TYPE_LENGTH
];
76 if (superType
.GetPreferredApp(preferred
) == B_OK
) {
77 BMimeType
preferredApp(preferred
);
79 if (preferredApp
.GetIconForType(superType
.Type(),
80 &data
, &size
) == B_OK
)
81 source
= kSupertypeIcon
;
87 if (source
!= kNoIcon
) {
90 } // NOTE: else there is no data, so nothing is leaked.
94 return source
!= kNoIcon
? B_OK
: B_ERROR
;
99 icon_for_type(const BMimeType
& type
, BBitmap
& bitmap
, icon_size size
,
100 icon_source
* _source
)
102 icon_source source
= kNoIcon
;
104 if (type
.GetIcon(&bitmap
, size
) == B_OK
)
107 if (source
== kNoIcon
) {
108 // check for icon from preferred app
110 char preferred
[B_MIME_TYPE_LENGTH
];
111 if (type
.GetPreferredApp(preferred
) == B_OK
) {
112 BMimeType
preferredApp(preferred
);
114 if (preferredApp
.GetIconForType(type
.Type(), &bitmap
, size
) == B_OK
)
115 source
= kApplicationIcon
;
119 if (source
== kNoIcon
) {
120 // check super type for an icon
123 if (type
.GetSupertype(&superType
) == B_OK
) {
124 if (superType
.GetIcon(&bitmap
, size
) == B_OK
)
125 source
= kSupertypeIcon
;
127 // check the super type's preferred app
128 char preferred
[B_MIME_TYPE_LENGTH
];
129 if (superType
.GetPreferredApp(preferred
) == B_OK
) {
130 BMimeType
preferredApp(preferred
);
132 if (preferredApp
.GetIconForType(superType
.Type(),
133 &bitmap
, size
) == B_OK
)
134 source
= kSupertypeIcon
;
143 return source
!= kNoIcon
? B_OK
: B_ERROR
;
160 Icon::Icon(const Icon
& source
)
180 Icon::SetTo(const BAppFileInfo
& info
, const char* type
)
187 if (info
.GetIconForType(type
, &data
, &size
) == B_OK
) {
188 // we have the vector icon, no need to get the rest
189 AdoptData(data
, size
);
193 BBitmap
* icon
= AllocateBitmap(B_LARGE_ICON
, B_CMAP8
);
194 if (icon
&& info
.GetIconForType(type
, icon
, B_LARGE_ICON
) == B_OK
)
199 icon
= AllocateBitmap(B_MINI_ICON
, B_CMAP8
);
200 if (icon
&& info
.GetIconForType(type
, icon
, B_MINI_ICON
) == B_OK
)
208 Icon::SetTo(const entry_ref
& ref
, const char* type
)
212 BFile
file(&ref
, B_READ_ONLY
);
213 BAppFileInfo
info(&file
);
214 if (file
.InitCheck() == B_OK
215 && info
.InitCheck() == B_OK
)
221 Icon::SetTo(const BMimeType
& type
, icon_source
* _source
)
227 if (icon_for_type(type
, &data
, &size
, _source
) == B_OK
) {
228 // we have the vector icon, no need to get the rest
229 AdoptData(data
, size
);
233 BBitmap
* icon
= AllocateBitmap(B_LARGE_ICON
, B_CMAP8
);
234 if (icon
&& icon_for_type(type
, *icon
, B_LARGE_ICON
, _source
) == B_OK
)
239 icon
= AllocateBitmap(B_MINI_ICON
, B_CMAP8
);
240 if (icon
&& icon_for_type(type
, *icon
, B_MINI_ICON
) == B_OK
)
248 Icon::CopyTo(BAppFileInfo
& info
, const char* type
, bool force
) const
250 status_t status
= B_OK
;
252 if (fLarge
!= NULL
|| force
)
253 status
= info
.SetIconForType(type
, fLarge
, B_LARGE_ICON
);
254 if (fMini
!= NULL
|| force
)
255 status
= info
.SetIconForType(type
, fMini
, B_MINI_ICON
);
256 if (fData
!= NULL
|| force
)
257 status
= info
.SetIconForType(type
, fData
, fSize
);
264 Icon::CopyTo(const entry_ref
& ref
, const char* type
, bool force
) const
267 status_t status
= file
.SetTo(&ref
, B_READ_ONLY
);
271 BAppFileInfo
info(&file
);
272 status
= info
.InitCheck();
276 return CopyTo(info
, type
, force
);
281 Icon::CopyTo(BMimeType
& type
, bool force
) const
283 status_t status
= B_OK
;
285 if (fLarge
!= NULL
|| force
)
286 status
= type
.SetIcon(fLarge
, B_LARGE_ICON
);
287 if (fMini
!= NULL
|| force
)
288 status
= type
.SetIcon(fMini
, B_MINI_ICON
);
289 if (fData
!= NULL
|| force
)
290 status
= type
.SetIcon(fData
, fSize
);
297 Icon::CopyTo(BMessage
& message
) const
299 status_t status
= B_OK
;
301 if (status
== B_OK
&& fLarge
!= NULL
) {
303 status
= fLarge
->Archive(&archive
);
305 status
= message
.AddMessage("icon/large", &archive
);
307 if (status
== B_OK
&& fMini
!= NULL
) {
309 status
= fMini
->Archive(&archive
);
311 status
= message
.AddMessage("icon/mini", &archive
);
313 if (status
== B_OK
&& fData
!= NULL
)
314 status
= message
.AddData("icon", B_VECTOR_ICON_TYPE
, fData
, fSize
);
321 Icon::SetLarge(const BBitmap
* large
)
325 fLarge
= new BBitmap(BRect(0, 0, 31, 31), B_CMAP8
);
327 memcpy(fLarge
->Bits(), large
->Bits(), min_c(large
->BitsLength(),
328 fLarge
->BitsLength()));
337 Icon::SetMini(const BBitmap
* mini
)
341 fMini
= new BBitmap(BRect(0, 0, 15, 15), B_CMAP8
);
343 memcpy(fMini
->Bits(), mini
->Bits(), min_c(mini
->BitsLength(),
344 fMini
->BitsLength()));
353 Icon::SetData(const uint8
* data
, size_t size
)
359 fData
= (uint8
*)malloc(size
);
362 //fType = B_VECTOR_ICON_TYPE;
363 memcpy(fData
, data
, size
);
376 fLarge
= fMini
= NULL
;
382 Icon::HasData() const
384 return fData
!= NULL
|| fLarge
!= NULL
|| fMini
!= NULL
;
389 Icon::GetData(icon_size which
, BBitmap
** _bitmap
) const
404 return B_ENTRY_NOT_FOUND
;
406 BBitmap
* bitmap
= new (nothrow
) BBitmap(source
);
407 if (bitmap
== NULL
|| bitmap
->InitCheck() != B_OK
) {
418 Icon::GetData(uint8
** _data
, size_t* _size
) const
421 return B_ENTRY_NOT_FOUND
;
423 uint8
* data
= (uint8
*)malloc(fSize
);
427 memcpy(data
, fData
, fSize
);
435 Icon::GetIcon(BBitmap
* bitmap
) const
441 && BIconUtils::GetVectorIcon(fData
, fSize
, bitmap
) == B_OK
)
444 int32 width
= bitmap
->Bounds().IntegerWidth() + 1;
446 if (width
== B_LARGE_ICON
&& fLarge
!= NULL
) {
447 bitmap
->SetBits(fLarge
->Bits(), fLarge
->BitsLength(), 0,
448 fLarge
->ColorSpace());
451 if (width
== B_MINI_ICON
&& fMini
!= NULL
) {
452 bitmap
->SetBits(fMini
->Bits(), fMini
->BitsLength(), 0,
453 fMini
->ColorSpace());
457 return B_ENTRY_NOT_FOUND
;
462 Icon::operator=(const Icon
& source
)
466 SetData(source
.fData
, source
.fSize
);
467 SetLarge(source
.fLarge
);
468 SetMini(source
.fMini
);
475 Icon::AdoptLarge(BBitmap
*large
)
483 Icon::AdoptMini(BBitmap
*mini
)
491 Icon::AdoptData(uint8
* data
, size_t size
)
500 Icon::AllocateBitmap(int32 size
, int32 space
)
502 int32 kSpace
= B_RGBA32
;
506 BBitmap
* bitmap
= new (nothrow
) BBitmap(BRect(0, 0, size
- 1, size
- 1),
508 if (bitmap
== NULL
|| bitmap
->InitCheck() != B_OK
) {
520 IconView::IconView(const char* name
, uint32 flags
)
521 : BControl(name
, NULL
, NULL
, B_WILL_DRAW
| flags
),
522 fModificationMessage(NULL
),
523 fIconSize(B_LARGE_ICON
),
532 fShowEmptyFrame(true)
537 IconView::~IconView()
540 delete fModificationMessage
;
545 IconView::AttachedToWindow()
551 // SetTo() was already called before we were a valid messenger
552 if (fHasRef
|| fHasType
)
558 IconView::DetachedFromWindow()
565 IconView::MessageReceived(BMessage
* message
)
567 if (message
->WasDropped() && message
->ReturnAddress() != BMessenger(this)
568 && AcceptsDrag(message
)) {
569 // set icon from message
570 BBitmap
* mini
= NULL
;
571 BBitmap
* large
= NULL
;
572 const uint8
* data
= NULL
;
575 message
->FindData("icon", B_VECTOR_ICON_TYPE
, (const void**)&data
,
579 if (message
->FindMessage("icon/large", &archive
) == B_OK
)
580 large
= (BBitmap
*)BBitmap::Instantiate(&archive
);
581 if (message
->FindMessage("icon/mini", &archive
) == B_OK
)
582 mini
= (BBitmap
*)BBitmap::Instantiate(&archive
);
584 if (large
!= NULL
|| mini
!= NULL
|| (data
!= NULL
&& size
> 0))
585 _SetIcon(large
, mini
, data
, size
);
588 if (message
->FindRef("refs", &ref
) == B_OK
)
598 switch (message
->what
) {
599 case kMsgIconInvoked
:
614 if (message
->FindInt32("opcode", &opcode
) != B_OK
615 || opcode
!= B_ATTR_CHANGED
)
619 if (message
->FindString("attr", &name
) != B_OK
)
622 if (!strcmp(name
, kAttrMiniIcon
)
623 || !strcmp(name
, kAttrLargeIcon
)
624 || !strcmp(name
, kAttrIcon
))
629 case B_META_MIME_CHANGED
:
636 if (message
->FindString("be:type", &type
) != B_OK
637 || message
->FindInt32("be:which", &which
) != B_OK
)
640 if (!strcasecmp(type
, fType
.Type())) {
642 case B_MIME_TYPE_DELETED
:
653 } else if (fSource
!= kOwnIcon
654 && message
->FindString("be:extra_type", &type
) == B_OK
655 && !strcasecmp(type
, fType
.Type())) {
656 // this change could still affect our current icon
658 if (which
== B_MIME_TYPE_DELETED
659 || which
== B_PREFERRED_APP_CHANGED
660 || which
== B_SUPPORTED_TYPES_CHANGED
661 || which
== B_ICON_FOR_TYPE_CHANGED
)
667 case B_ICON_DATA_EDITED
:
671 if (message
->FindData("icon data", B_VECTOR_ICON_TYPE
,
672 (const void**)&data
, &size
) < B_OK
)
675 _SetIcon(NULL
, NULL
, data
, size
);
680 BControl::MessageReceived(message
);
687 IconView::AcceptsDrag(const BMessage
* message
)
694 if (message
->GetInfo("refs", &type
, &count
) == B_OK
&& count
== 1
695 && type
== B_REF_TYPE
) {
696 // if we're bound to an entry, check that no one drops this to us
698 if (fHasRef
&& message
->FindRef("refs", &ref
) == B_OK
&& fRef
== ref
)
704 if ((message
->GetInfo("icon/large", &type
) == B_OK
705 && type
== B_MESSAGE_TYPE
)
706 || (message
->GetInfo("icon", &type
) == B_OK
707 && type
== B_VECTOR_ICON_TYPE
)
708 || (message
->GetInfo("icon/mini", &type
) == B_OK
709 && type
== B_MESSAGE_TYPE
))
717 IconView::BitmapRect() const
719 return BRect(0, 0, fIconSize
- 1, fIconSize
- 1);
724 IconView::Draw(BRect updateRect
)
726 SetDrawingMode(B_OP_ALPHA
);
728 if (fHeapIcon
!= NULL
)
729 DrawBitmap(fHeapIcon
, BitmapRect().LeftTop());
730 else if (fIcon
!= NULL
)
731 DrawBitmap(fIcon
, BitmapRect().LeftTop());
732 else if (!fDropTarget
&& fShowEmptyFrame
) {
733 // draw frame so that the user knows here is something he
734 // might be able to click on
735 SetHighColor(tint_color(ViewColor(), B_DARKEN_1_TINT
));
736 StrokeRect(BitmapRect());
740 // mark this view as a having focus
741 SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR
));
742 StrokeRect(BitmapRect());
745 // mark this view as a drop target
746 SetHighColor(0, 0, 0);
748 BRect rect
= BitmapRect();
749 // TODO: this is an incompatibility between R5 and Haiku and should be fixed!
750 // (Necessary adjustment differs.)
761 IconView::GetPreferredSize(float* _width
, float* _height
)
767 *_height
= fIconSize
;
775 GetPreferredSize(&width
, &height
);
776 return BSize(width
, height
);
781 IconView::PreferredSize()
795 IconView::MouseDown(BPoint where
)
800 int32 buttons
= B_PRIMARY_MOUSE_BUTTON
;
802 if (Looper() != NULL
&& Looper()->CurrentMessage() != NULL
) {
803 if (Looper()->CurrentMessage()->FindInt32("buttons", &buttons
) != B_OK
)
804 buttons
= B_PRIMARY_MOUSE_BUTTON
;
805 if (Looper()->CurrentMessage()->FindInt32("clicks", &clicks
) != B_OK
)
809 if ((buttons
& B_PRIMARY_MOUSE_BUTTON
) != 0
810 && BitmapRect().Contains(where
)) {
812 // double click - open Icon-O-Matic
814 } else if (fIcon
!= NULL
) {
815 // start tracking - this icon might be dragged around
818 SetMouseEventMask(B_POINTER_EVENTS
, B_NO_POINTER_HISTORY
);
822 if ((buttons
& B_SECONDARY_MOUSE_BUTTON
) != 0) {
825 ConvertToScreen(&where
);
827 BPopUpMenu
* menu
= new BPopUpMenu("context");
828 menu
->SetFont(be_plain_font
);
830 bool hasIcon
= fHasType
? fSource
== kOwnIcon
: fIcon
!= NULL
;
832 menu
->AddItem(new BMenuItem(
833 B_TRANSLATE("Edit icon" B_UTF8_ELLIPSIS
),
834 new BMessage(kMsgEditIcon
)));
836 menu
->AddItem(new BMenuItem(
837 B_TRANSLATE("Add icon" B_UTF8_ELLIPSIS
),
838 new BMessage(kMsgAddIcon
)));
841 BMenuItem
* item
= new BMenuItem(
842 B_TRANSLATE("Remove icon"), new BMessage(kMsgRemoveIcon
));
844 item
->SetEnabled(false);
847 menu
->SetTargetForItems(fTarget
);
849 menu
->Go(where
, true, false, true);
855 IconView::MouseUp(BPoint where
)
868 IconView::MouseMoved(BPoint where
, uint32 transit
, const BMessage
* dragMessage
)
870 if (fTracking
&& !fDragging
&& fIcon
!= NULL
871 && (abs((int32
)(where
.x
- fDragPoint
.x
)) > 3
872 || abs((int32
)(where
.y
- fDragPoint
.y
)) > 3)) {
874 BMessage
message(B_SIMPLE_DATA
);
876 ::Icon
* icon
= fIconData
;
877 if (fHasRef
|| fHasType
) {
880 icon
->SetTo(fRef
, fType
.Type());
885 icon
->CopyTo(message
);
887 if (icon
!= fIconData
)
890 BBitmap
*dragBitmap
= new BBitmap(fIcon
->Bounds(), B_RGBA32
, true);
893 = new BView(dragBitmap
->Bounds(), B_EMPTY_STRING
, B_FOLLOW_NONE
, 0);
894 dragBitmap
->AddChild(view
);
896 view
->SetHighColor(B_TRANSPARENT_COLOR
);
897 view
->FillRect(dragBitmap
->Bounds());
898 view
->SetBlendingMode(B_CONSTANT_ALPHA
, B_ALPHA_COMPOSITE
);
899 view
->SetDrawingMode(B_OP_ALPHA
);
900 view
->SetHighColor(0, 0, 0, 160);
901 view
->DrawBitmap(fIcon
);
904 dragBitmap
->Unlock();
906 DragMessage(&message
, dragBitmap
, B_OP_ALPHA
,
907 fDragPoint
- BitmapRect().LeftTop(), this);
911 if (dragMessage
!= NULL
&& !fDragging
&& AcceptsDrag(dragMessage
)) {
912 bool dropTarget
= transit
== B_ENTERED_VIEW
|| transit
== B_INSIDE_VIEW
;
913 if (dropTarget
!= fDropTarget
) {
914 fDropTarget
= dropTarget
;
917 } else if (fDropTarget
) {
925 IconView::KeyDown(const char* bytes
, int32 numBytes
)
940 BControl::KeyDown(bytes
, numBytes
);
945 IconView::MakeFocus(bool focus
)
947 if (focus
!= IsFocus())
950 BControl::MakeFocus(focus
);
955 IconView::SetTo(const entry_ref
& ref
, const char* fileType
)
961 if (fileType
!= NULL
)
962 fType
.SetTo(fileType
);
972 IconView::SetTo(const BMimeType
& type
)
976 if (type
.Type() == NULL
)
980 fType
.SetTo(type
.Type());
988 IconView::SetTo(::Icon
* icon
)
990 if (fIconData
== icon
)
1004 if (fHasRef
|| fHasType
)
1022 // this will actually trigger a redraw *after* we updated the icon below
1024 BBitmap
* icon
= NULL
;
1027 BFile
file(&fRef
, B_READ_ONLY
);
1028 if (file
.InitCheck() != B_OK
)
1032 if (info
.SetTo(&file
) != B_OK
)
1035 icon
= Icon::AllocateBitmap(fIconSize
);
1036 if (icon
!= NULL
&& info
.GetTrackerIcon(icon
,
1037 (icon_size
)fIconSize
) != B_OK
) {
1041 } else if (fHasType
) {
1042 icon
= Icon::AllocateBitmap(fIconSize
);
1043 if (icon
!= NULL
&& icon_for_type(fType
, *icon
, (icon_size
)fIconSize
,
1044 &fSource
) != B_OK
) {
1048 } else if (fIconData
) {
1049 icon
= Icon::AllocateBitmap(fIconSize
);
1050 if (fIconData
->GetIcon(icon
) != B_OK
) {
1061 IconView::SetIconSize(int32 size
)
1063 if (size
< B_MINI_ICON
)
1067 if (size
== fIconSize
)
1076 IconView::ShowIconHeap(bool show
)
1078 if (show
== (fHeapIcon
!= NULL
))
1082 BResources
* resources
= be_app
->AppResources();
1083 if (resources
!= NULL
) {
1084 const void* data
= NULL
;
1086 data
= resources
->LoadResource('VICN', "icon heap", &size
);
1088 // got vector icon data
1089 fHeapIcon
= Icon::AllocateBitmap(B_LARGE_ICON
, B_RGBA32
);
1090 if (BIconUtils::GetVectorIcon((const uint8
*)data
,
1091 size
, fHeapIcon
) != B_OK
) {
1099 // no vector icon or failed to get bitmap
1101 data
= resources
->LoadResource(B_LARGE_ICON_TYPE
, "icon heap",
1104 fHeapIcon
= Icon::AllocateBitmap(B_LARGE_ICON
, B_CMAP8
);
1105 if (fHeapIcon
!= NULL
) {
1106 memcpy(fHeapIcon
->Bits(), data
,
1107 fHeapIcon
->BitsLength());
1120 IconView::ShowEmptyFrame(bool show
)
1122 if (show
== fShowEmptyFrame
)
1125 fShowEmptyFrame
= show
;
1132 IconView::SetTarget(const BMessenger
& target
)
1140 IconView::SetModificationMessage(BMessage
* message
)
1142 delete fModificationMessage
;
1143 fModificationMessage
= message
;
1148 IconView::Invoke(BMessage
* message
)
1150 if (message
== NULL
)
1151 fTarget
.SendMessage(kMsgIconInvoked
);
1153 fTarget
.SendMessage(message
);
1166 IconView::GetRef(entry_ref
& ref
) const
1177 IconView::GetMimeType(BMimeType
& type
) const
1182 type
.SetTo(fType
.Type());
1188 IconView::_AddOrEditIcon()
1191 if (fHasRef
&& fType
.Type() == NULL
) {
1192 // in ref mode, Icon-O-Matic can change the icon directly, and
1193 // we'll pick it up via node monitoring
1194 message
.what
= B_REFS_RECEIVED
;
1195 message
.AddRef("refs", &fRef
);
1197 // in static or MIME type mode, Icon-O-Matic needs to return the
1198 // buffer it changed once its done
1199 message
.what
= B_EDIT_ICON_DATA
;
1200 message
.AddMessenger("reply to", BMessenger(this));
1202 ::Icon
* icon
= fIconData
;
1204 icon
= new ::Icon();
1206 icon
->SetTo(fRef
, fType
.Type());
1211 if (icon
->HasData()) {
1214 if (icon
->GetData(&data
, &size
) == B_OK
) {
1215 message
.AddData("icon data", B_VECTOR_ICON_TYPE
, data
, size
);
1219 // TODO: somehow figure out how names of objects in the icon
1220 // can be preserved. Maybe in a second (optional) attribute
1221 // where ever a vector icon attribute is present?
1224 if (icon
!= fIconData
)
1228 be_roster
->Launch("application/x-vnd.haiku-icon_o_matic", &message
);
1233 IconView::_SetIcon(BBitmap
* large
, BBitmap
* mini
, const uint8
* data
,
1234 size_t size
, bool force
)
1237 BFile
file(&fRef
, B_READ_WRITE
);
1239 if (is_application(file
)) {
1240 BAppFileInfo
info(&file
);
1241 if (info
.InitCheck() == B_OK
) {
1242 if (large
!= NULL
|| force
)
1243 info
.SetIconForType(fType
.Type(), large
, B_LARGE_ICON
);
1244 if (mini
!= NULL
|| force
)
1245 info
.SetIconForType(fType
.Type(), mini
, B_MINI_ICON
);
1246 if (data
!= NULL
|| force
)
1247 info
.SetIconForType(fType
.Type(), data
, size
);
1250 BNodeInfo
info(&file
);
1251 if (info
.InitCheck() == B_OK
) {
1252 if (large
!= NULL
|| force
)
1253 info
.SetIcon(large
, B_LARGE_ICON
);
1254 if (mini
!= NULL
|| force
)
1255 info
.SetIcon(mini
, B_MINI_ICON
);
1256 if (data
!= NULL
|| force
)
1257 info
.SetIcon(data
, size
);
1260 // the icon shown will be updated using node monitoring
1261 } else if (fHasType
) {
1262 if (large
!= NULL
|| force
)
1263 fType
.SetIcon(large
, B_LARGE_ICON
);
1264 if (mini
!= NULL
|| force
)
1265 fType
.SetIcon(mini
, B_MINI_ICON
);
1266 if (data
!= NULL
|| force
)
1267 fType
.SetIcon(data
, size
);
1269 // the icon shown will be updated automatically - we're watching
1270 // any changes to the MIME database
1271 } else if (fIconData
!= NULL
) {
1272 if (large
!= NULL
|| force
)
1273 fIconData
->SetLarge(large
);
1274 if (mini
!= NULL
|| force
)
1275 fIconData
->SetMini(mini
);
1276 if (data
!= NULL
|| force
)
1277 fIconData
->SetData(data
, size
);
1279 // replace visible icon
1280 if (fIcon
== NULL
&& fIconData
->HasData())
1281 fIcon
= Icon::AllocateBitmap(fIconSize
);
1283 if (fIconData
->GetIcon(fIcon
) != B_OK
) {
1290 if (fModificationMessage
)
1291 Invoke(fModificationMessage
);
1296 IconView::_SetIcon(entry_ref
* ref
)
1298 // retrieve icons from file
1299 BFile
file(ref
, B_READ_ONLY
);
1300 BAppFileInfo
info(&file
);
1301 if (file
.InitCheck() != B_OK
|| info
.InitCheck() != B_OK
)
1304 // try vector/PNG icon first
1307 if (info
.GetIcon(&data
, &size
) == B_OK
) {
1308 _SetIcon(NULL
, NULL
, data
, size
);
1313 // try large/mini icons
1314 bool hasMini
= false;
1315 bool hasLarge
= false;
1317 BBitmap
* large
= new BBitmap(BRect(0, 0, 31, 31), B_CMAP8
);
1318 if (large
->InitCheck() != B_OK
) {
1322 BBitmap
* mini
= new BBitmap(BRect(0, 0, 15, 15), B_CMAP8
);
1323 if (mini
->InitCheck() != B_OK
) {
1328 if (large
!= NULL
&& info
.GetIcon(large
, B_LARGE_ICON
) == B_OK
)
1330 if (mini
!= NULL
&& info
.GetIcon(mini
, B_MINI_ICON
) == B_OK
)
1333 if (!hasMini
&& !hasLarge
) {
1334 // TODO: don't forget device icons!
1336 // try MIME type icon
1337 char type
[B_MIME_TYPE_LENGTH
];
1338 if (info
.GetType(type
) != B_OK
)
1341 BMimeType
mimeType(type
);
1342 if (icon_for_type(mimeType
, &data
, &size
) != B_OK
) {
1343 // only try large/mini icons when there is no vector icon
1345 && icon_for_type(mimeType
, *large
, B_LARGE_ICON
) == B_OK
)
1348 && icon_for_type(mimeType
, *mini
, B_MINI_ICON
) == B_OK
)
1354 _SetIcon(NULL
, NULL
, data
, size
);
1356 } else if (hasLarge
|| hasMini
)
1357 _SetIcon(large
, mini
, NULL
, 0);
1365 IconView::_RemoveIcon()
1367 _SetIcon(NULL
, NULL
, NULL
, 0, true);
1372 IconView::_StartWatching()
1374 if (Looper() == NULL
) {
1375 // we are not a valid messenger yet
1382 if (node
.InitCheck() == B_OK
1383 && node
.GetNodeRef(&nodeRef
) == B_OK
)
1384 watch_node(&nodeRef
, B_WATCH_ATTR
, this);
1385 } else if (fHasType
)
1386 BMimeType::StartWatching(this);
1391 IconView::_StopWatching()
1394 stop_watching(this);
1396 BMimeType::StopWatching(this);
1403 IconView::SetTarget(BMessenger target
)
1405 return BControl::SetTarget(target
);
1410 IconView::SetTarget(const BHandler
* handler
, const BLooper
* looper
= NULL
)
1412 return BControl::SetTarget(handler
,