diff --git a/src/preferences/filetypes/FileTypesWindow.cpp b/src/preferences/filetypes/FileTypesWindow.cpp index 71479b3ba6..03b3a1d293 100644 --- a/src/preferences/filetypes/FileTypesWindow.cpp +++ b/src/preferences/filetypes/FileTypesWindow.cpp @@ -67,26 +67,17 @@ const uint32 kMsgDescriptionEntered = 'dsce'; const uint32 kMsgToggleIcons = 'tgic'; const uint32 kMsgToggleRule = 'tgrl'; -class TypeIconView : public BControl { +class TypeIconView : public IconView { public: - TypeIconView(BRect frame, const char* name, BMessage* message, + TypeIconView(BRect frame, const char* name, int32 resizingMode = B_FOLLOW_LEFT | B_FOLLOW_TOP); virtual ~TypeIconView(); - void SetTo(BMimeType* type); - virtual void Draw(BRect updateRect); virtual void GetPreferredSize(float* _width, float* _height); - virtual void MouseDown(BPoint where); -#if 0 - virtual void MouseMoved(BPoint where, uint32 transit, - BMessage* dragMessage); -#endif - - private: - BBitmap* fIcon; - icon_source fIconSource; + protected: + virtual BRect BitmapRect() const; }; class ExtensionListView : public DropTargetListView { @@ -110,70 +101,29 @@ class ExtensionListView : public DropTargetListView { // #pragma mark - -TypeIconView::TypeIconView(BRect frame, const char* name, BMessage* message, - int32 resizingMode) - : BControl(frame, name, NULL, message, - resizingMode, B_WILL_DRAW), - fIcon(NULL), - fIconSource(kNoIcon) +TypeIconView::TypeIconView(BRect frame, const char* name, int32 resizingMode) + : IconView(frame, name, resizingMode) { + ShowEmptyFrame(false); } TypeIconView::~TypeIconView() { - delete fIcon; -} - - -void -TypeIconView::SetTo(BMimeType* type) -{ - int32 sourceWas = fIconSource; - fIconSource = kNoIcon; - - if (type != NULL) { - if (fIcon == NULL) { -#ifdef HAIKU_TARGET_PLATFORM_HAIKU - fIcon = new BBitmap(BRect(0, 0, B_LARGE_ICON - 1, B_LARGE_ICON - 1), - B_RGB32); -#else - fIcon = new BBitmap(BRect(0, 0, B_LARGE_ICON - 1, B_LARGE_ICON - 1), - B_CMAP8); -#endif - } - - icon_for_type(*type, *fIcon, B_LARGE_ICON, &fIconSource); - } - - if (fIconSource == kNoIcon) { - delete fIcon; - fIcon = NULL; - } - - if (sourceWas != fIconSource || sourceWas != kNoIcon) - Invalidate(); } void TypeIconView::Draw(BRect updateRect) { - SetHighColor(ViewColor()); - FillRect(updateRect); - if (!IsEnabled()) return; - if (fIcon != NULL) { - SetDrawingMode(B_OP_ALPHA); - DrawBitmap(fIcon, - BPoint((Bounds().Width() - fIcon->Bounds().Width()) / 2.0f, 0.0f)); - } + IconView::Draw(updateRect); const char* text = NULL; - switch (fIconSource) { + switch (IconSource()) { case kNoIcon: text = "no icon"; break; @@ -195,14 +145,14 @@ TypeIconView::Draw(BRect updateRect) GetFontHeight(&fontHeight); float y = fontHeight.ascent; - if (fIconSource == kNoIcon) { + if (IconSource() == kNoIcon) { // center text in the middle of the icon - y += (B_LARGE_ICON - fontHeight.ascent - fontHeight.descent) / 2.0f; + y += (IconSize() - fontHeight.ascent - fontHeight.descent) / 2.0f; } else - y += B_LARGE_ICON + 3.0f; + y += IconSize() + 3.0f; - DrawString(text, BPoint((Bounds().Width() - StringWidth(text)) / 2.0f, - y)); + DrawString(text, BPoint(ceilf((Bounds().Width() - StringWidth(text)) / 2.0f), + ceilf(y))); } @@ -213,8 +163,8 @@ TypeIconView::GetPreferredSize(float* _width, float* _height) float a = StringWidth("(from application)"); float b = StringWidth("(from super type)"); float width = max_c(a, b); - if (width < B_LARGE_ICON) - width = B_LARGE_ICON; + if (width < IconSize()) + width = IconSize(); *_width = ceilf(width); } @@ -223,34 +173,29 @@ TypeIconView::GetPreferredSize(float* _width, float* _height) font_height fontHeight; GetFontHeight(&fontHeight); - *_height = B_LARGE_ICON + 3.0f + ceilf(fontHeight.ascent + fontHeight.descent); + *_height = IconSize() + 3.0f + ceilf(fontHeight.ascent + fontHeight.descent); } } -void -TypeIconView::MouseDown(BPoint where) +BRect +TypeIconView::BitmapRect() const { - int32 buttons = B_PRIMARY_MOUSE_BUTTON; - if (Looper() != NULL && Looper()->CurrentMessage() != NULL) - Looper()->CurrentMessage()->FindInt32("buttons", &buttons); + if (IconSource() == kNoIcon) { + // this also defines the drop target area + font_height fontHeight; + GetFontHeight(&fontHeight); - if ((buttons & B_SECONDARY_MOUSE_BUTTON) != 0) { - // show context menu + float width = StringWidth("no icon") + 8.0f; + float height = ceilf(fontHeight.ascent + fontHeight.descent) + 6.0f; + float x = (Bounds().Width() - width) / 2.0f; + float y = ceilf((IconSize() - fontHeight.ascent - fontHeight.descent) / 2.0f) - 3.0f; - ConvertToScreen(&where); - - BPopUpMenu* menu = new BPopUpMenu("context"); - menu->SetFont(be_plain_font); - BMenuItem* item; - menu->AddItem(item = new BMenuItem(fIconSource == kOwnIcon - ? "Edit Icon" B_UTF8_ELLIPSIS : "Add Icon" B_UTF8_ELLIPSIS, NULL)); - item->SetEnabled(false); - menu->AddItem(item = new BMenuItem("Remove Icon", NULL)); - item->SetEnabled(false); - - menu->Go(where); + return BRect(x, y, x + width, y + height); } + + float x = (Bounds().Width() - IconSize()) / 2.0f; + return BRect(x, 0.0f, x + IconSize() - 1, IconSize() - 1); } @@ -427,7 +372,7 @@ FileTypesWindow::FileTypesWindow(const BMessage& settings) font.GetHeight(&boldHeight); BRect innerRect; - fIconView = new TypeIconView(innerRect, "icon", NULL, + fIconView = new TypeIconView(innerRect, "icon", B_FOLLOW_LEFT | B_FOLLOW_V_CENTER); fIconView->ResizeToPreferred(); @@ -740,7 +685,10 @@ FileTypesWindow::_UpdatePreferredApps(BMimeType* type) void FileTypesWindow::_UpdateIcon(BMimeType* type) { - fIconView->SetTo(type); + if (type != NULL) + fIconView->SetTo(*type); + else + fIconView->Unset(); } @@ -1151,14 +1099,11 @@ FileTypesWindow::MessageReceived(BMessage* message) // this change could still affect our current type if (which == B_MIME_TYPE_DELETED - || which == B_PREFERRED_APP_CHANGED #ifdef __HAIKU__ || which == B_SUPPORTED_TYPES_CHANGED #endif - || which == B_ICON_FOR_TYPE_CHANGED) { + || which == B_PREFERRED_APP_CHANGED) _UpdatePreferredApps(&fCurrentType); - _UpdateIcon(&fCurrentType); - } } break; } diff --git a/src/preferences/filetypes/IconView.cpp b/src/preferences/filetypes/IconView.cpp index e6c9f736af..e389497bc2 100644 --- a/src/preferences/filetypes/IconView.cpp +++ b/src/preferences/filetypes/IconView.cpp @@ -30,7 +30,7 @@ using namespace std; #ifdef HAIKU_TARGET_PLATFORM_HAIKU status_t -icon_for_type(BMimeType& type, uint8** _data, size_t* _size, +icon_for_type(const BMimeType& type, uint8** _data, size_t* _size, icon_source* _source) { if (_data == NULL || _size == NULL) @@ -89,7 +89,7 @@ icon_for_type(BMimeType& type, uint8** _data, size_t* _size, status_t -icon_for_type(BMimeType& type, BBitmap& bitmap, icon_size size, +icon_for_type(const BMimeType& type, BBitmap& bitmap, icon_size size, icon_source* _source) { icon_source source = kNoIcon; @@ -170,7 +170,7 @@ Icon::~Icon() void -Icon::SetTo(BAppFileInfo& info, const char* type) +Icon::SetTo(const BAppFileInfo& info, const char* type) { Unset(); @@ -199,7 +199,7 @@ Icon::SetTo(BAppFileInfo& info, const char* type) void -Icon::SetTo(entry_ref& ref, const char* type) +Icon::SetTo(const entry_ref& ref, const char* type) { Unset(); @@ -212,7 +212,7 @@ Icon::SetTo(entry_ref& ref, const char* type) void -Icon::SetTo(BMimeType& type, icon_source* _source) +Icon::SetTo(const BMimeType& type, icon_source* _source) { Unset(); @@ -258,7 +258,7 @@ Icon::CopyTo(BAppFileInfo& info, const char* type, bool force) const status_t -Icon::CopyTo(entry_ref& ref, const char* type, bool force) const +Icon::CopyTo(const entry_ref& ref, const char* type, bool force) const { BFile file; status_t status = file.SetTo(&ref, B_READ_ONLY); @@ -522,7 +522,7 @@ Icon::AllocateBitmap(int32 size, int32 space) IconView::IconView(BRect rect, const char* name, uint32 resizeMode, uint32 flags) - : BView(rect, name, resizeMode, B_WILL_DRAW | flags), + : BControl(rect, name, NULL, NULL, resizeMode, B_WILL_DRAW | flags), fIconSize(B_LARGE_ICON), fIcon(NULL), fHeapIcon(NULL), @@ -532,7 +532,7 @@ IconView::IconView(BRect rect, const char* name, uint32 resizeMode, uint32 flags fTracking(false), fDragging(false), fDropTarget(false), - fEnabled(true) + fShowEmptyFrame(true) { } @@ -569,7 +569,8 @@ IconView::DetachedFromWindow() void IconView::MessageReceived(BMessage* message) { - if (message->WasDropped() && _AcceptsDrag(message)) { + if (message->WasDropped() && message->ReturnAddress() != BMessenger(this) + && AcceptsDrag(message)) { // set icon from message BBitmap* mini = NULL; BBitmap* large = NULL; @@ -631,36 +632,49 @@ IconView::MessageReceived(BMessage* message) const char* type; int32 which; if (message->FindString("be:type", &type) != B_OK - || !strcmp(type, fType.Type()) || message->FindInt32("be:which", &which) != B_OK) break; - switch (which) { - case B_MIME_TYPE_DELETED: - Unset(); - break; + if (!strcasecmp(type, fType.Type())) { + switch (which) { + case B_MIME_TYPE_DELETED: + Unset(); + break; + + case B_ICON_CHANGED: + Update(); + break; + + default: + break; + } + } else if (fSource != kOwnIcon + && message->FindString("be:extra_type", &type) == B_OK + && !strcasecmp(type, fType.Type())) { + // this change could still affect our current icon - case B_ICON_CHANGED: + if (which == B_MIME_TYPE_DELETED + || which == B_PREFERRED_APP_CHANGED +#ifdef __HAIKU__ + || which == B_SUPPORTED_TYPES_CHANGED +#endif + || which == B_ICON_FOR_TYPE_CHANGED) Update(); - break; - - default: - break; } break; } default: - BView::MessageReceived(message); + BControl::MessageReceived(message); break; } } bool -IconView::_AcceptsDrag(const BMessage* message) +IconView::AcceptsDrag(const BMessage* message) { - if (!fEnabled) + if (!IsEnabled()) return false; type_code type; @@ -686,9 +700,9 @@ IconView::_AcceptsDrag(const BMessage* message) BRect -IconView::_BitmapRect() const +IconView::BitmapRect() const { - return BRect(0, 0, 31, 31); + return BRect(0, 0, fIconSize - 1, fIconSize - 1); } @@ -698,26 +712,26 @@ IconView::Draw(BRect updateRect) SetDrawingMode(B_OP_ALPHA); if (fHeapIcon != NULL) - DrawBitmap(fHeapIcon, _BitmapRect().LeftTop()); + DrawBitmap(fHeapIcon, BitmapRect().LeftTop()); else if (fIcon != NULL) - DrawBitmap(fIcon, _BitmapRect().LeftTop()); - else if (!fDropTarget) { + DrawBitmap(fIcon, BitmapRect().LeftTop()); + else if (!fDropTarget && fShowEmptyFrame) { // draw frame so that the user knows here is something he // might be able to click on SetHighColor(tint_color(ViewColor(), B_DARKEN_1_TINT)); - StrokeRect(Bounds()); + StrokeRect(BitmapRect()); } if (IsFocus()) { // mark this view as a having focus SetHighColor(ui_color(B_KEYBOARD_NAVIGATION_COLOR)); - StrokeRect(_BitmapRect()); + StrokeRect(BitmapRect()); } if (fDropTarget) { // mark this view as a drop target SetHighColor(0, 0, 0); SetPenSize(2); - BRect rect = _BitmapRect(); + BRect rect = BitmapRect(); // TODO: this is an incompatibility between R5 and Haiku and should be fixed! #ifdef HAIKU_TARGET_PLATFORM_HAIKU rect.left++; @@ -736,17 +750,17 @@ void IconView::GetPreferredSize(float* _width, float* _height) { if (_width) - *_width = ceilf(fIconSize); + *_width = fIconSize; if (_height) - *_height = ceilf(fIconSize); + *_height = fIconSize; } void IconView::MouseDown(BPoint where) { - if (!fEnabled) + if (!IsEnabled()) return; int32 buttons = B_PRIMARY_MOUSE_BUTTON; @@ -758,7 +772,7 @@ IconView::MouseDown(BPoint where) clicks = 1; } - if ((buttons & B_PRIMARY_MOUSE_BUTTON) != 0 && _BitmapRect().Contains(where)) { + if ((buttons & B_PRIMARY_MOUSE_BUTTON) != 0 && BitmapRect().Contains(where)) { if (clicks == 2) { // double click - open Icon-O-Matic Invoke(); @@ -777,12 +791,17 @@ IconView::MouseDown(BPoint where) BPopUpMenu* menu = new BPopUpMenu("context"); menu->SetFont(be_plain_font); - if (fIcon != NULL) + bool hasIcon = fHasType ? fSource == kOwnIcon : fIcon != NULL; + if (hasIcon) menu->AddItem(new BMenuItem("Edit Icon" B_UTF8_ELLIPSIS, new BMessage(kMsgEditIcon))); else menu->AddItem(new BMenuItem("Add Icon" B_UTF8_ELLIPSIS, new BMessage(kMsgAddIcon))); - menu->AddItem(new BMenuItem("Remove Icon", new BMessage(kMsgRemoveIcon))); + BMenuItem* item = new BMenuItem("Remove Icon", new BMessage(kMsgRemoveIcon)); + if (!hasIcon) + item->SetEnabled(false); + + menu->AddItem(item); menu->SetTargetForItems(fTarget); menu->Go(where, true, false, true); @@ -813,9 +832,12 @@ IconView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage) BMessage message(B_SIMPLE_DATA); ::Icon* icon = fIconData; - if (fHasRef) { + if (fHasRef || fHasType) { icon = new ::Icon; - icon->SetTo(fRef, fType.Type()); + if (fHasRef) + icon->SetTo(fRef, fType.Type()); + else if (fHasType) + icon->SetTo(fType); } icon->CopyTo(message); @@ -835,12 +857,13 @@ IconView::MouseMoved(BPoint where, uint32 transit, const BMessage* dragMessage) view->Sync(); dragBitmap->Unlock(); - DragMessage(&message, dragBitmap, B_OP_ALPHA, fDragPoint, this); + DragMessage(&message, dragBitmap, B_OP_ALPHA, + fDragPoint - BitmapRect().LeftTop(), this); fDragging = true; SetMouseEventMask(B_POINTER_EVENTS, B_NO_POINTER_HISTORY); } - if (dragMessage != NULL && !fDragging && _AcceptsDrag(dragMessage)) { + if (dragMessage != NULL && !fDragging && AcceptsDrag(dragMessage)) { bool dropTarget = transit == B_ENTERED_VIEW || transit == B_INSIDE_VIEW; if (dropTarget != fDropTarget) { fDropTarget = dropTarget; @@ -869,7 +892,7 @@ IconView::KeyDown(const char* bytes, int32 numBytes) } } - BView::KeyDown(bytes, numBytes); + BControl::KeyDown(bytes, numBytes); } @@ -879,12 +902,12 @@ IconView::MakeFocus(bool focus) if (focus != IsFocus()) Invalidate(); - BView::MakeFocus(focus); + BControl::MakeFocus(focus); } void -IconView::SetTo(entry_ref& ref, const char* fileType) +IconView::SetTo(const entry_ref& ref, const char* fileType) { Unset(); @@ -901,7 +924,7 @@ IconView::SetTo(entry_ref& ref, const char* fileType) void -IconView::SetTo(BMimeType& type) +IconView::SetTo(const BMimeType& type) { Unset(); @@ -1028,20 +1051,21 @@ IconView::ShowIconHeap(bool show) void -IconView::SetTarget(const BMessenger& target) +IconView::ShowEmptyFrame(bool show) { - fTarget = target; + if (show == fShowEmptyFrame) + return; + + fShowEmptyFrame = show; + if (fIcon == NULL) + Invalidate(); } void -IconView::SetEnabled(bool enabled) +IconView::SetTarget(const BMessenger& target) { - if (fEnabled == enabled) - return; - - fEnabled = enabled; - Invalidate(); + fTarget = target; } @@ -1059,6 +1083,28 @@ IconView::Icon() } +status_t +IconView::GetRef(entry_ref& ref) const +{ + if (!fHasRef) + return B_BAD_TYPE; + + ref = fRef; + return B_OK; +} + + +status_t +IconView::GetMimeType(BMimeType& type) const +{ + if (!fHasType) + return B_BAD_TYPE; + + type.SetTo(fType.Type()); + return B_OK; +} + + void IconView::_AddOrEditIcon() { diff --git a/src/preferences/filetypes/IconView.h b/src/preferences/filetypes/IconView.h index 0cf60a2f77..e4b124eca0 100644 --- a/src/preferences/filetypes/IconView.h +++ b/src/preferences/filetypes/IconView.h @@ -6,11 +6,11 @@ #define ICON_VIEW_H +#include #include #include #include #include -#include enum icon_source { @@ -27,11 +27,13 @@ class Icon { Icon(const Icon& source); ~Icon(); - void SetTo(BAppFileInfo& info, const char* type = NULL); - void SetTo(entry_ref& ref, const char* type = NULL); - void SetTo(BMimeType& type, icon_source* _source = NULL); - status_t CopyTo(BAppFileInfo& info, const char* type = NULL, bool force = false) const; - status_t CopyTo(entry_ref& ref, const char* type = NULL, bool force = false) const; + void SetTo(const BAppFileInfo& info, const char* type = NULL); + void SetTo(const entry_ref& ref, const char* type = NULL); + void SetTo(const BMimeType& type, icon_source* _source = NULL); + status_t CopyTo(BAppFileInfo& info, const char* type = NULL, + bool force = false) const; + status_t CopyTo(const entry_ref& ref, const char* type = NULL, + bool force = false) const; status_t CopyTo(BMimeType& type, bool force = false) const; status_t CopyTo(BMessage& message) const; @@ -61,7 +63,7 @@ class Icon { size_t fSize; }; -class IconView : public BView { +class IconView : public BControl { public: IconView(BRect rect, const char* name, uint32 resizeMode = B_FOLLOW_LEFT | B_FOLLOW_TOP, @@ -81,23 +83,29 @@ class IconView : public BView { virtual void MakeFocus(bool focus = true); - void SetTo(entry_ref& file, const char* fileType = NULL); - void SetTo(BMimeType& type); + void SetTo(const entry_ref& file, const char* fileType = NULL); + void SetTo(const BMimeType& type); void SetTo(::Icon* icon); void Unset(); void Update(); void SetIconSize(int32 size); void ShowIconHeap(bool show); - void SetEnabled(bool enabled); + void ShowEmptyFrame(bool show); void SetTarget(const BMessenger& target); void Invoke(); ::Icon* Icon(); + int32 IconSize() const { return fIconSize; } + icon_source IconSource() const { return fSource; } + status_t GetRef(entry_ref& ref) const; + status_t GetMimeType(BMimeType& type) const; + + protected: + virtual bool AcceptsDrag(const BMessage* message); + virtual BRect BitmapRect() const; private: - bool _AcceptsDrag(const BMessage* message); - BRect _BitmapRect() const; void _AddOrEditIcon(); void _SetIcon(BBitmap* large, BBitmap* mini, const uint8* data, size_t size, bool force = false); @@ -123,7 +131,7 @@ class IconView : public BView { bool fTracking; bool fDragging; bool fDropTarget; - bool fEnabled; + bool fShowEmptyFrame; }; static const uint32 kMsgIconInvoked = 'iciv'; @@ -131,9 +139,9 @@ static const uint32 kMsgRemoveIcon = 'icrm'; static const uint32 kMsgAddIcon = 'icad'; static const uint32 kMsgEditIcon = 'iced'; -extern status_t icon_for_type(BMimeType& type, uint8** _data, size_t* _size, +extern status_t icon_for_type(const BMimeType& type, uint8** _data, size_t* _size, icon_source* _source = NULL); -extern status_t icon_for_type(BMimeType& type, BBitmap& bitmap, +extern status_t icon_for_type(const BMimeType& type, BBitmap& bitmap, icon_size size, icon_source* _source = NULL); #endif // ICON_VIEW_H