* TypeIconView now inherits from IconView and only adds the icon source label

to it - it also inherits all the features like drag&drop, of course.
* IconView now inherits from BControl instead of BView, might need some more
  work to properly handle the invocation message stuff, though.
* The "Remove Icon" menu item was always enabled, no matter if there was an
  icon or not; also it was not properly detected wether or not a MIME type
  had an icon when building the menu.
* Dragging in MIME type mode now works as well.
* Added some getter methods to the IconView to retrieve the data it has.
* Some other cleanup, like adding missing consts.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19299 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2006-11-15 20:22:46 +00:00
parent b724cb6408
commit 7cb11339a0
3 changed files with 158 additions and 159 deletions
+37 -92
View File
@@ -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;
}
+98 -52
View File
@@ -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()
{
+23 -15
View File
@@ -6,11 +6,11 @@
#define ICON_VIEW_H
#include <Control.h>
#include <Entry.h>
#include <Messenger.h>
#include <Mime.h>
#include <String.h>
#include <View.h>
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