From 7fb6186f3cb93a14ea0f96a82bdfc3d18f3ad56e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stephan=20A=C3=9Fmus?= Date: Tue, 29 Aug 2006 17:06:23 +0000 Subject: [PATCH] * integration of vector icons with the registrar and the mime data base * additional versions of SetIcon[ForType] and GetIcon[ForType] in BMimeType and BAppFileInfo, which handle flat vector icon data * changes in Tracker to support scalable icons (currently broken for non-vector icons and needs cleanup) and drawing icons correctly with alpha channel (large parts of this work done by Michael Lotz) If someone feels like looking over the changes, that would be much appreciated! :-) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@18699 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/storage/AppFileInfo.h | 7 + headers/os/storage/MimeType.h | 4 + headers/private/storage/mime/Database.h | 9 +- .../private/storage/mime/database_access.h | 7 +- src/kits/storage/AppFileInfo.cpp | 160 +++++++++++++++++- src/kits/storage/MimeType.cpp | 113 +++++++++++++ .../storage/mime/CreateAppMetaMimeThread.cpp | 16 ++ src/kits/storage/mime/Database.cpp | 126 +++++++++++++- .../storage/mime/UpdateMimeInfoThread.cpp | 30 ++++ src/kits/storage/mime/database_access.cpp | 93 +++++++++- src/kits/tracker/Bitmaps.cpp | 6 +- src/kits/tracker/ContainerWindow.cpp | 22 ++- src/kits/tracker/IconCache.cpp | 18 +- src/kits/tracker/Pose.cpp | 157 +++++++++-------- src/kits/tracker/PoseView.cpp | 86 +++++++--- src/kits/tracker/PoseView.h | 15 ++ src/kits/tracker/TextWidget.cpp | 16 +- src/kits/tracker/Utilities.cpp | 84 ++++----- src/kits/tracker/ViewState.cpp | 32 +++- src/kits/tracker/ViewState.h | 15 ++ src/libs/icon/IconUtils.cpp | 4 +- src/servers/registrar/MIMEManager.cpp | 19 ++- 22 files changed, 865 insertions(+), 174 deletions(-) diff --git a/headers/os/storage/AppFileInfo.h b/headers/os/storage/AppFileInfo.h index abfe1de1b5..599926fd43 100644 --- a/headers/os/storage/AppFileInfo.h +++ b/headers/os/storage/AppFileInfo.h @@ -77,13 +77,20 @@ class BAppFileInfo: public BNodeInfo { virtual status_t GetIcon(BBitmap *icon, icon_size which) const; virtual status_t SetIcon(const BBitmap *icon, icon_size which); + status_t GetIcon(uint8** data, size_t* size) const; + status_t SetIcon(const uint8* data, size_t size); + status_t GetVersionInfo(version_info *info, version_kind kind) const; status_t SetVersionInfo(const version_info *info, version_kind kind); status_t GetIconForType(const char *type, BBitmap *icon, icon_size which) const; + status_t GetIconForType(const char *type, uint8** data, + size_t* size) const; status_t SetIconForType(const char *type, const BBitmap *icon, icon_size which); + status_t SetIconForType(const char *type, const uint8* data, + size_t size); void SetInfoLocation(info_location location); bool IsUsingAttributes() const; diff --git a/headers/os/storage/MimeType.h b/headers/os/storage/MimeType.h index 3f0f3023e4..af38f611f9 100644 --- a/headers/os/storage/MimeType.h +++ b/headers/os/storage/MimeType.h @@ -110,6 +110,7 @@ class BMimeType { status_t Delete(); bool IsInstalled() const; status_t GetIcon(BBitmap *icon, icon_size size) const; + status_t GetIcon(uint8** data, size_t* size) const; status_t GetPreferredApp(char *signature, app_verb verb = B_OPEN) const; status_t GetAttrInfo(BMessage *info) const; status_t GetFileExtensions(BMessage *extensions) const; @@ -118,6 +119,7 @@ class BMimeType { status_t GetSupportingApps(BMessage *signatures) const; status_t SetIcon(const BBitmap *icon, icon_size size); + status_t SetIcon(const uint8* data, size_t size); status_t SetPreferredApp(const char *signature, app_verb verb = B_OPEN); status_t SetAttrInfo(const BMessage *info); status_t SetFileExtensions(const BMessage *extensions); @@ -139,6 +141,8 @@ class BMimeType { icon_size which) const; status_t SetIconForType(const char *type, const BBitmap *icon, icon_size which); + status_t SetIconForType(const char* type, const uint8* data, + size_t size); /* sniffer rule manipulation */ status_t GetSnifferRule(BString *result) const; diff --git a/headers/private/storage/mime/Database.h b/headers/private/storage/mime/Database.h index 6eb905a6a1..1470ed852e 100644 --- a/headers/private/storage/mime/Database.h +++ b/headers/private/storage/mime/Database.h @@ -58,8 +58,11 @@ class Database { status_t SetFileExtensions(const char *type, const BMessage *extensions); status_t SetIcon(const char *type, const void *data, size_t dataSize, icon_size which); - status_t SetIconForType(const char *type, const char *fileType, const void *data, - size_t dataSize, icon_size which); + status_t SetIcon(const char *type, const void *data, size_t dataSize); + status_t SetIconForType(const char *type, const char *fileType, + const void *data, size_t dataSize, icon_size which); + status_t SetIconForType(const char *type, const char *fileType, + const void *data, size_t dataSize); status_t SetPreferredApp(const char *type, const char *signature, app_verb verb = B_OPEN); status_t SetSnifferRule(const char *type, const char *rule); @@ -89,8 +92,10 @@ class Database { status_t DeleteLongDescription(const char *type); status_t DeleteFileExtensions(const char *type); status_t DeleteIcon(const char *type, icon_size size); + status_t DeleteIcon(const char *type); status_t DeleteIconForType(const char *type, const char *fileType, icon_size which); + status_t DeleteIconForType(const char *type, const char *fileType); status_t DeletePreferredApp(const char *type, app_verb verb = B_OPEN); status_t DeleteSnifferRule(const char *type); status_t DeleteSupportedTypes(const char *type, bool fullSync); diff --git a/headers/private/storage/mime/database_access.h b/headers/private/storage/mime/database_access.h index 5e6a8026f2..e1ea3397b6 100644 --- a/headers/private/storage/mime/database_access.h +++ b/headers/private/storage/mime/database_access.h @@ -27,8 +27,11 @@ status_t get_short_description(const char *type, char *description); status_t get_long_description(const char *type, char *description); status_t get_file_extensions(const char *type, BMessage *extensions); status_t get_icon(const char *type, BBitmap *icon, icon_size size); -status_t get_icon_for_type(const char *type, const char *fileType, BBitmap *icon, - icon_size which); +status_t get_icon(const char *type, uint8** data, size_t* size); +status_t get_icon_for_type(const char *type, const char *fileType, + BBitmap *icon, icon_size which); +status_t get_icon_for_type(const char *type, const char *fileType, + uint8** data, size_t* size); status_t get_preferred_app(const char *type, char *signature, app_verb verb); status_t get_sniffer_rule(const char *type, BString *result); status_t get_supported_types(const char *type, BMessage *types); diff --git a/src/kits/storage/AppFileInfo.cpp b/src/kits/storage/AppFileInfo.cpp index 8283d56e96..73486009d8 100644 --- a/src/kits/storage/AppFileInfo.cpp +++ b/src/kits/storage/AppFileInfo.cpp @@ -43,9 +43,11 @@ static const int32 kAppFlagsResourceID = 1; static const int32 kSupportedTypesResourceID = 1; static const int32 kMiniIconResourceID = 101; static const int32 kLargeIconResourceID = 101; +static const int32 kIconResourceID = 101; static const int32 kVersionInfoResourceID = 1; static const int32 kMiniIconForTypeResourceID = 0; static const int32 kLargeIconForTypeResourceID = 0; +static const int32 kIconForTypeResourceID = 0; // type codes enum { @@ -615,6 +617,22 @@ BAppFileInfo::GetIcon(BBitmap *icon, icon_size which) const return GetIconForType(NULL, icon, which); } +// GetIcon +/*! \brief Gets the file's icon. + \param data The pointer in which the flat icon data will be returned. + \param size The pointer in which the size of the data found will be returned. + \return + - \c B_OK: Everything went fine. + - \c B_NO_INIT: The object is not properly initialized. + - \c B_BAD_VALUE: \c NULL \a data or \c NULL size. + - other error codes +*/ +status_t +BAppFileInfo::GetIcon(uint8** data, size_t* size) const +{ + return GetIconForType(NULL, data, size); +} + // SetIcon /*! \brief Sets the file's icon. @@ -637,6 +655,26 @@ BAppFileInfo::SetIcon(const BBitmap *icon, icon_size which) return SetIconForType(NULL, icon, which); } +// SetIcon +/*! \brief Sets the file's icon. + + If \a icon is \c NULL the file's icon is unset. + + \param data A pointer to the data buffer containing the vector icon + to be set. May be \c NULL. + \param size Specifies the size of buffer pointed to by \a data. + \return + - \c B_OK: Everything went fine. + - \c B_NO_INIT: The object is not properly initialized. + - \c B_BAD_VALUE: \c NULL data. + - other error codes +*/ +status_t +BAppFileInfo::SetIcon(const uint8* data, size_t size) +{ + return SetIconForType(NULL, data, size); +} + // GetVersionInfo /*! \brief Gets the file's version info. \param info A pointer to a pre-allocated version_info structure into which @@ -813,8 +851,10 @@ BAppFileInfo::GetIconForType(const char *type, BBitmap *icon, status_t error = _ReadData(attribute, -1, B_RAW_TYPE, NULL, 0, bytesRead, &allocatedBuffer); if (error == B_OK) { - return BIconUtils::GetVectorIcon((uint8*)allocatedBuffer, - bytesRead, icon); + error = BIconUtils::GetVectorIcon((uint8*)allocatedBuffer, + bytesRead, icon); + free(allocatedBuffer); + return error; } // no vector icon if we got this far @@ -888,6 +928,56 @@ BAppFileInfo::GetIconForType(const char *type, BBitmap *icon, return error; } +// GetIconForType +/*! \brief Gets the icon the application provides for a given MIME type. + + If \a type is \c NULL, the application's icon is retrieved. + + \param type The MIME type in question. May be \c NULL. + \param data A pointer in which the icon data will be returned. When you + are done with the data, you should use free() to deallocate it. + \param size A pointer in which the size of the retrieved data is returned. + \return + - \c B_OK: Everything went fine. + - \c B_NO_INIT: The object is not properly initialized. + - \c B_BAD_VALUE: \c NULL \a data and/or \a size. Or the supplied + \a type is not a valid MIME type. + - other error codes +*/ +status_t +BAppFileInfo::GetIconForType(const char *type, uint8** data, + size_t* size) const +{ + if (InitCheck() != B_OK) + return B_NO_INIT; + + if (!data || !size) + return B_BAD_VALUE; + + // get vector icon + BString attributeName(kIconAttribute); + + // check type param + if (type) { + if (BMimeType::IsValid(type)) + attributeName += type; + else + return B_BAD_VALUE; + } else { + attributeName += kIconType; + } + + void* allocatedBuffer = NULL; + status_t ret = _ReadData(attributeName.String(), -1, + B_RAW_TYPE, NULL, 0, *size, &allocatedBuffer); + + if (ret < B_OK) + return ret; + + *data = (uint8*)allocatedBuffer; + return B_OK; +} + // SetIconForType /*! \brief Sets the icon the application provides for a given MIME type. @@ -906,8 +996,9 @@ BAppFileInfo::GetIconForType(const char *type, BBitmap *icon, \return - \c B_OK: Everything went fine. - \c B_NO_INIT: The object is not properly initialized. - - \c B_BAD_VALUE: Unknown icon size \a which or bitmap dimensions (\a icon) - and icon size (\a which) do not match. + - \c B_BAD_VALUE: Either the icon size \a which is unkown, bitmap dimensions (\a icon) + and icon size (\a which) do not match, or the provided \a type is + not a valid MIME type. - other error codes */ status_t @@ -991,6 +1082,67 @@ BAppFileInfo::SetIconForType(const char *type, const BBitmap *icon, return error; } +// SetIconForType +/*! \brief Sets the icon the application provides for a given MIME type. + + If \a type is \c NULL, the application's icon is set. + If \a data is \c NULL the icon is unset. + + If the file has a signature, then the icon is also set on the MIME type. + If the type for the signature has not been installed yet, it is installed + before. + + \param type The MIME type in question. May be \c NULL. + \param data A pointer to the data containing the icon to be set. + May be \c NULL. + \param size Specifies the size of buffer provided in \a data. + \return + - \c B_OK: Everything went fine. + - \c B_NO_INIT: The object is not properly initialized. + - \c B_BAD_VALUE: The provided \a type is not a valid MIME type. + - other error codes +*/ +status_t +BAppFileInfo::SetIconForType(const char* type, const uint8* data, + size_t size) +{ + if (InitCheck() != B_OK) + return B_NO_INIT; + + // set some icon related variables + BString attributeString = kIconAttribute; + int32 resourceID = type ? kIconForTypeResourceID : kIconResourceID; + uint32 attrType = B_RAW_TYPE; + + // check type param + if (type) { + if (BMimeType::IsValid(type)) + attributeString += type; + else + return B_BAD_VALUE; + } else + attributeString += kIconType; + + const char *attribute = attributeString.String(); + + status_t error; + // write/remove the attribute + if (data) + error = _WriteData(attribute, resourceID, attrType, data, size, true); + else // no icon given => remove + error = _RemoveData(attribute, attrType); + + // set the attribute on the MIME type, if the file has a signature + BMimeType mimeType; + if (error == B_OK && GetMetaMime(&mimeType) == B_OK) { + if (!mimeType.IsInstalled()) + error = mimeType.Install(); + if (error == B_OK) + error = mimeType.SetIconForType(type, data, size); + } + return error; +} + // SetInfoLocation /*! \brief Specifies the location where the meta data shall be stored. diff --git a/src/kits/storage/MimeType.cpp b/src/kits/storage/MimeType.cpp index 3d2e380ba4..7b6db18549 100644 --- a/src/kits/storage/MimeType.cpp +++ b/src/kits/storage/MimeType.cpp @@ -443,6 +443,30 @@ BMimeType::GetIcon(BBitmap *icon, icon_size size) const return err; } + +// GetIcon +//! Fetches the vector icon associated with the MIME type +/*! The icon data is returned in \c data. + + \param data Pointer in which the allocated icon data is returned. You need to + delete the buffer when you are done with it. + \param size Pointer in which the size of the allocated icon data is returned. + \return + - \c B_OK: Success + - \c B_ENTRY_NOT_FOUND: No icon of the given size exists for the given type + - other error code: Failure + +*/ +status_t +BMimeType::GetIcon(uint8** data, size_t* size) const +{ + status_t err = InitCheck(); + if (!err) + err = get_icon(Type(), data, size); + return err; +} + + // GetPreferredApp //! Fetches the signature of the MIME type's preferred application from the MIME database /*! The preferred app is the application that's used to access a file when, for example, the user @@ -713,6 +737,26 @@ BMimeType::SetIcon(const BBitmap *icon, icon_size which) return SetIconForType(NULL, icon, which); } +// SetIcon +//! Sets the vector icon for the MIME type +/*! The icon is copied from the provided \a data which must contain \a size bytes. + + If you want to erase the current icon, pass \c NULL as the \a data argument. + + \param data Pointer to a buffer containing the new icon, or \c NULL to clear + the current icon. + \param size Size of the provided buffer. + \return + - \c B_OK: Success + - other error code: Failure + +*/ +status_t +BMimeType::SetIcon(const uint8* data, size_t size) +{ + return SetIconForType(NULL, data, size); +} + // SetPreferredApp //! Sets the preferred application for the MIME type /*! The preferred app is the application that's used to access a file when, for example, the user @@ -1321,6 +1365,75 @@ BMimeType::SetIconForType(const char *type, const BBitmap *icon, icon_size which return err; } +// SetIconForType +/*! \brief Sets the large or mini icon used by an application of this type for + files of the given type. + + This can be confusing, so here's how this function is intended to be used: + - The actual \c BMimeType object should be set to the MIME signature of an + application to whom you want to assign custom icons for custom MIME types. + - The \c type parameter specifies the file type whose custom icon you are + setting. + + The type of the \c BMimeType object is not required to actually be a subtype of + \c "application/"; that is the intended use however, and application-specific + icons are not expected to be present for non-application types. + + The icon is copied from the \c BBitmap pointed to by \c icon. The bitmap must + be the proper size: \c 32x32 for the large icon, \c 16x16 for the mini icon. + + If you want to erase the current icon, pass \c NULL as the \c icon argument. + + \param type Pointer to a pre-allocated string containing the MIME type whose + custom icon you wish to set. + \param icon Pointer to a pre-allocated \c BBitmap of proper size and colorspace + containing the new icon, or \c NULL to clear the current icon. + \param icon_size Value that specifies which icon to update. Currently \c B_LARGE_ICON + and \c B_MINI_ICON are supported. + \return + - \c B_OK: Success + - other error code: Failure + +*/ +status_t +BMimeType::SetIconForType(const char* type, const uint8* data, size_t dataSize) +{ + status_t err = InitCheck(); + + BMessage msg(data ? B_REG_MIME_SET_PARAM : B_REG_MIME_DELETE_PARAM); + BMessage reply; + status_t result; + + // Build and send the message, read the reply + if (!err) + err = msg.AddString("type", Type()); + if (!err) + err = msg.AddInt32("which", (type ? B_REG_MIME_ICON_FOR_TYPE : B_REG_MIME_ICON)); + if (data) { + if (!err) + err = msg.AddData("icon data", B_RAW_TYPE, data, dataSize); + } + if (!err) + err = msg.AddInt32("icon size", -1); + // -1 indicates size should be ignored (vector icon data) + if (type) { + if (!err) + err = BMimeType::IsValid(type) ? B_OK : B_BAD_VALUE; + if (!err) + err = msg.AddString("file type", type); + } + if (!err) + err = BRoster::Private().SendTo(&msg, &reply, true); + if (!err) + err = reply.what == B_REG_RESULT ? (status_t)B_OK : (status_t)B_BAD_REPLY; + if (!err) + err = reply.FindInt32("result", &result); + if (!err) + err = result; + + return err; +} + // GetSnifferRule /*! \brief Retrieves the MIME type's sniffer rule. \param result Pointer to a pre-allocated BString into which the value is diff --git a/src/kits/storage/mime/CreateAppMetaMimeThread.cpp b/src/kits/storage/mime/CreateAppMetaMimeThread.cpp index 949dc79018..e9b915bd32 100644 --- a/src/kits/storage/mime/CreateAppMetaMimeThread.cpp +++ b/src/kits/storage/mime/CreateAppMetaMimeThread.cpp @@ -96,6 +96,15 @@ CreateAppMetaMimeThread::DoMimeUpdate(const entry_ref* ref, bool* _entryIsDir) if (status == B_OK && (fForce || typeNode.GetAttrInfo(kAppHintAttr, &info) != B_OK)) status = mime.SetAppHint(ref); + // Vector Icon + if (status == B_OK && (fForce || typeNode.GetAttrInfo(kIconAttr, &info) != B_OK)) { + uint8* data = NULL; + size_t size = 0; + if (appInfo.GetIcon(&data, &size) == B_OK) { + status = mime.SetIcon(data, size); + free(data); + } + } // Mini Icon BBitmap miniIcon(BRect(0, 0, 15, 15), B_BITMAP_NO_SERVER_LINK, B_CMAP8); if (status == B_OK && (fForce || typeNode.GetAttrInfo(kMiniIconAttr, &info) != B_OK)) { @@ -119,6 +128,13 @@ CreateAppMetaMimeThread::DoMimeUpdate(const entry_ref* ref, bool* _entryIsDir) // Icons for supported types const char* type; for (int32 i = 0; supportedTypes.FindString("types", i, &type) == B_OK; i++) { + // vector icon + uint8* data = NULL; + size_t size = 0; + if (status == B_OK && appInfo.GetIconForType(type, &data, &size) == B_OK) { + status = mime.SetIconForType(type, data, size); + free(data); + } // mini icon if (status == B_OK && appInfo.GetIconForType(type, &miniIcon, B_MINI_ICON) == B_OK) status = mime.SetIconForType(type, &miniIcon, B_MINI_ICON); diff --git a/src/kits/storage/mime/Database.cpp b/src/kits/storage/mime/Database.cpp index ccb8760ccc..6ff1b07d2c 100644 --- a/src/kits/storage/mime/Database.cpp +++ b/src/kits/storage/mime/Database.cpp @@ -352,6 +352,12 @@ Database::SetIcon(const char *type, const void *data, size_t dataSize, return SetIconForType(type, NULL, data, dataSize, which); } +status_t +Database::SetIcon(const char *type, const void *data, size_t dataSize) +{ + return SetIconForType(type, NULL, data, dataSize); +} + // SetIconForType /*! \brief Sets the large or mini icon used by an application of this type for files of the given type. @@ -436,6 +442,67 @@ Database::SetIconForType(const char *type, const char *fileType, return err; } +// SetIconForType +/*! \brief Sets the vector icon used by an application of this type for + files of the given type. + + The type of the \c BMimeType object is not required to actually be a subtype of + \c "application/"; that is the intended use however, and application-specific + icons are not expected to be present for non-application types. + + \param type The MIME type + \param fileType The MIME type whose custom icon you wish to set. + \param data Pointer to an array of vector data + \param dataSize The length of the array pointed to by \c data + \return + - \c B_OK: Success + - "error code": Failure + +*/ +status_t +Database::SetIconForType(const char *type, const char *fileType, + const void *data, size_t dataSize) +{ + DBG(OUT("Database::SetIconForType()\n")); + + if (type == NULL || data == NULL) + return B_BAD_VALUE; + + int32 attrType = B_RAW_TYPE; + + // Construct our attribute name + std::string attr; + if (fileType) { + attr = kIconAttrPrefix + BPrivate::Storage::to_lower(fileType); + } else + attr = kIconAttr; + + // Write the icon data + BNode node; + bool didCreate = false; + + status_t err = open_or_create_type(type, &node, &didCreate); + if (!err && didCreate) + _SendInstallNotification(type); + + if (!err) + err = node.WriteAttr(attr.c_str(), attrType, 0, data, dataSize); + if (err >= 0) + err = err == (ssize_t)dataSize ? (status_t)B_OK : (status_t)B_FILE_ERROR; + if (!err) { + // TODO: extra notification for vector icons (currently + // passing "true" for B_LARGE_ICON)? + if (fileType) { + _SendMonitorUpdate(B_ICON_FOR_TYPE_CHANGED, type, fileType, + true, B_META_MIME_MODIFIED); + } else { + _SendMonitorUpdate(B_ICON_CHANGED, type, true, + B_META_MIME_MODIFIED); + } + } + return err; +} + // SetPreferredApp /*! \brief Sets the signature of the preferred application for the given app verb @@ -993,6 +1060,28 @@ Database::DeleteIcon(const char *type, icon_size which) } +/*! \brief Deletes the vector icon for the given type + + A \c B_ICON_CHANGED notification is sent to the mime monitor service. + \param type The mime type of interest + \return + - B_OK: success + - B_ENTRY_NOT_FOUND: no such attribute existed + - "error code": failure +*/ +status_t +Database::DeleteIcon(const char *type) +{ + // TODO: exta notification for vector icon (uses B_LARGE_ICON now) + status_t status = delete_attribute(type, kIconAttr); + if (status == B_OK) + _SendMonitorUpdate(B_ICON_CHANGED, type, B_LARGE_ICON, + B_META_MIME_DELETED); + + return status; +} + + /*! \brief Deletes the icon of the given size associated with the given file type for the given application signature. @@ -1001,7 +1090,7 @@ Database::DeleteIcon(const char *type, icon_size which) A \c B_ICON_FOR_TYPE_CHANGED notification is sent to the mime monitor service. \param type The mime type of the application whose custom icon you are deleting. - \param which The mime type for which you no longer wish \c type to have a custom icon. + \param fileType The mime type for which you no longer wish \c type to have a custom icon. \param which The icon size of interest \return - B_OK: success @@ -1026,6 +1115,41 @@ Database::DeleteIconForType(const char *type, const char *fileType, icon_size wh return status; } + +/*! \brief Deletes the vector icon associated with the given file + type for the given application signature. + + (If this function seems confusing, please see BMimeType::GetIconForType() for a + better description of what the *IconForType() functions are used for.) + + A \c B_ICON_FOR_TYPE_CHANGED notification is sent to the mime monitor service. + \param type The mime type of the application whose custom icon you are deleting. + \param fileType The mime type for which you no longer wish \c type to have a custom icon. + \return + - B_OK: success + - B_ENTRY_NOT_FOUND: no such attribute existed + - "error code": failure +*/ +status_t +Database::DeleteIconForType(const char *type, const char *fileType) +{ + if (fileType == NULL) + return B_BAD_VALUE; + + std::string attr = kIconAttrPrefix + BPrivate::Storage::to_lower(fileType); + + // TODO: introduce extra notification for vector icons? + // (uses B_LARGE_ICON now) + status_t status = delete_attribute(type, attr.c_str()); + if (status == B_OK) { + _SendMonitorUpdate(B_ICON_FOR_TYPE_CHANGED, type, fileType, + true, B_META_MIME_DELETED); + } + + return status; +} + + // DeletePreferredApp //! Deletes the preferred app for the given app verb for the given type /*! A \c B_PREFERRED_APP_CHANGED notification is sent to the mime monitor service. diff --git a/src/kits/storage/mime/UpdateMimeInfoThread.cpp b/src/kits/storage/mime/UpdateMimeInfoThread.cpp index 3c409de92b..71ac60f963 100644 --- a/src/kits/storage/mime/UpdateMimeInfoThread.cpp +++ b/src/kits/storage/mime/UpdateMimeInfoThread.cpp @@ -36,6 +36,25 @@ update_icon(BAppFileInfo &appFileInfoRead, BAppFileInfo &appFileInfoWrite, return err; } +// update_icon +static status_t +update_icon(BAppFileInfo &appFileInfoRead, BAppFileInfo &appFileInfoWrite, + const char *type) +{ + uint8* data = NULL; + size_t size = 0; + + status_t err = appFileInfoRead.GetIconForType(type, &data, &size); + if (err == B_OK) + err = appFileInfoWrite.SetIconForType(type, data, size); + else if (err == B_ENTRY_NOT_FOUND) + err = appFileInfoWrite.SetIconForType(type, NULL, size); + + free(data); + + return err; +} + // is_shared_object_mime_type static bool is_shared_object_mime_type(BMimeType &type) @@ -151,6 +170,11 @@ UpdateMimeInfoThread::DoMimeUpdate(const entry_ref *entry, bool *entryIsDir) if (err != B_OK) return err; + // vector icon + err = update_icon(appFileInfoRead, appFileInfoWrite, NULL); + if (err != B_OK) + return err; + // small icon BBitmap smallIcon(BRect(0, 0, 15, 15), B_BITMAP_NO_SERVER_LINK, B_CMAP8); @@ -192,6 +216,12 @@ UpdateMimeInfoThread::DoMimeUpdate(const entry_ref *entry, bool *entryIsDir) for (int32 i = 0; supportedTypes.FindString("types", i, &supportedType) == B_OK; i++) { + // vector icon + err = update_icon(appFileInfoRead, appFileInfoWrite, + supportedType); + if (err != B_OK) + return err; + // small icon err = update_icon(appFileInfoRead, appFileInfoWrite, supportedType, smallIcon, B_MINI_ICON); diff --git a/src/kits/storage/mime/database_access.cpp b/src/kits/storage/mime/database_access.cpp index 15eb6ac714..6f12d5993b 100644 --- a/src/kits/storage/mime/database_access.cpp +++ b/src/kits/storage/mime/database_access.cpp @@ -185,6 +185,19 @@ get_icon(const char *type, BBitmap *icon, icon_size which) return get_icon_for_type(type, NULL, icon, which); } +// get_icon +//! Fetches the vector icon associated with the given MIME type +/* \param type The mime type + \param data Pointer in which the allocated icon data is returned. You need to + free the buffer once you're done with it. + \param size Pointer in which the size of the icon data is returned. +*/ +status_t +get_icon(const char *type, uint8** data, size_t* size) +{ + return get_icon_for_type(type, NULL, data, size); +} + // get_icon_for_type /*! \brief Fetches the large or mini icon used by an application of this type for files of the given type. @@ -197,8 +210,8 @@ get_icon(const char *type, BBitmap *icon, icon_size which) be the proper size: \c 32x32 for the large icon, \c 16x16 for the mini icon. \param type The MIME type - \param type Pointer to a pre-allocated string containing the MIME type whose - custom icon you wish to fetch. If NULL, works just like get_icon(). + \param fileType Pointer to a pre-allocated string containing the MIME type whose + custom icon you wish to fetch. If NULL, works just like get_icon(). \param icon Pointer to a pre-allocated \c BBitmap of proper size and colorspace into which the icon is copied. \param icon_size Value that specifies which icon to return. Currently \c B_LARGE_ICON @@ -323,6 +336,82 @@ get_icon_for_type(const char* type, const char* fileType, BBitmap* icon, // return err; } +// get_icon_for_type +/*! \brief Fetches the vector icon used by an application of this type for files of the + given type. + + The type of the \c BMimeType object is not required to actually be a subtype of + \c "application/"; that is the intended use however, and calling \c get_icon_for_type() + on a non-application type will likely return \c B_ENTRY_NOT_FOUND. + + The icon data is allocated and returned in \a data. + + \param type The MIME type + \param fileType Pointer to a pre-allocated string containing the MIME type whose + custom icon you wish to fetch. If NULL, works just like get_icon(). + \param data Pointer in which the icon data is returned on success. + \param size Pointer in which the size of the icon data is returned. + \return + - \c B_OK: Success + - \c B_ENTRY_NOT_FOUND: No vector icon exists for the given type + - "error code": Failure + +*/ +status_t +get_icon_for_type(const char* type, const char* fileType, uint8** data, + size_t* size) +{ + if (!type || !data || !size) + return B_BAD_VALUE; + + // open the node for the given type + BNode node; + ssize_t err = open_type(type, &node); + if (err < B_OK) + return (status_t)err; + + // construct our attribute name + std::string iconAttrName; + + if (fileType) + iconAttrName = kIconAttrPrefix + BPrivate::Storage::to_lower(fileType); + else + iconAttrName = kIconAttr; + + // get info about attribute for that name + attr_info info; + if (!err) + err = node.GetAttrInfo(iconAttrName.c_str(), &info); + + // validate attribute type + if (!err) + err = (info.type == B_RAW_TYPE) ? B_OK : B_BAD_VALUE; + + // allocate a buffer and read the attribute data into it + if (!err) { + uint8* buffer = new(std::nothrow) uint8[info.size]; + if (!buffer) + err = B_NO_MEMORY; + if (!err) { + err = node.ReadAttr(iconAttrName.c_str(), B_RAW_TYPE, + 0, buffer, info.size); + } + + if (err >= 0) + err = (err == info.size) ? (ssize_t)B_OK : (ssize_t)B_FILE_ERROR; + + if (!err) { + // success, set data pointer and size + *data = buffer; + *size = info.size; + } else { + delete[] buffer; + } + } + + return err; +} + // get_preferred_app //! Fetches signature of the MIME type's preferred application for the given action. /*! The string pointed to by \c signature must be long enough to diff --git a/src/kits/tracker/Bitmaps.cpp b/src/kits/tracker/Bitmaps.cpp index d718c649ef..53ac3cc011 100644 --- a/src/kits/tracker/Bitmaps.cpp +++ b/src/kits/tracker/Bitmaps.cpp @@ -127,9 +127,6 @@ BImageResources::LoadResource(type_code type, const char *name, size_t *out_size status_t BImageResources::GetIconResource(int32 id, icon_size size, BBitmap *dest) const { - if (size != B_LARGE_ICON && size != B_MINI_ICON ) - return B_ERROR; - size_t length = 0; const void *data; @@ -140,6 +137,9 @@ BImageResources::GetIconResource(int32 id, icon_size size, BBitmap *dest) const return B_OK; // fall back to R5 icon + if (size != B_LARGE_ICON && size != B_MINI_ICON) + return B_ERROR; + length = 0; data = LoadResource(size == B_LARGE_ICON ? 'ICON' : 'MICN', id, &length); diff --git a/src/kits/tracker/ContainerWindow.cpp b/src/kits/tracker/ContainerWindow.cpp index 63fa84c095..326a6314fe 100644 --- a/src/kits/tracker/ContainerWindow.cpp +++ b/src/kits/tracker/ContainerWindow.cpp @@ -1879,9 +1879,25 @@ BContainerWindow::AddWindowMenu(BMenu *menu) { BMenuItem *item; - item = new BMenuItem("Icon View", new BMessage(kIconMode), '1'); + BMenu* iconSizeMenu = new BMenu("Icon View"); + + item = new BMenuItem("32 x 32", new BMessage(kIconMode), '1'); item->SetTarget(PoseView()); - menu->AddItem(item); + iconSizeMenu->AddItem(item); + + BMessage* message = new BMessage(kScaleIconMode); + message->AddInt32("size", 48); + item = new BMenuItem("48 x 48", message); + item->SetTarget(PoseView()); + iconSizeMenu->AddItem(item); + + message = new BMessage(kScaleIconMode); + message->AddInt32("size", 64); + item = new BMenuItem("64 x 64", message); + item->SetTarget(PoseView()); + iconSizeMenu->AddItem(item); + + menu->AddItem(iconSizeMenu); item = new BMenuItem("Mini Icon View", new BMessage(kMiniIconMode), '2'); item->SetTarget(PoseView()); @@ -2849,7 +2865,7 @@ BContainerWindow::UpdateMenu(BMenu *menu, UpdateMenuContext context) } if (context == kMenuBarContext || context == kWindowPopUpContext) { - MarkNamedMenuItem(menu, kIconMode, PoseView()->ViewMode() == kIconMode); +// MarkNamedMenuItem(menu, kIconMode, PoseView()->ViewMode() == kIconMode); MarkNamedMenuItem(menu, kListMode, PoseView()->ViewMode() == kListMode); MarkNamedMenuItem(menu, kMiniIconMode, PoseView()->ViewMode() == kMiniIconMode); diff --git a/src/kits/tracker/IconCache.cpp b/src/kits/tracker/IconCache.cpp index 96ec91605c..f5e58bc953 100644 --- a/src/kits/tracker/IconCache.cpp +++ b/src/kits/tracker/IconCache.cpp @@ -175,12 +175,14 @@ IconCacheEntry::HaveIconBitmap(IconDrawMode mode, icon_size size) const if (size == B_MINI_ICON) return fMiniIcon != NULL; else - return fLargeIcon != NULL; + return fLargeIcon != NULL + && fLargeIcon->Bounds().IntegerWidth() + 1 == size; } else if (mode == kSelected) { if (size == B_MINI_ICON) return fHilitedMiniIcon != NULL; else - return fHilitedLargeIcon != NULL; + return fHilitedLargeIcon != NULL + && fHilitedLargeIcon->Bounds().IntegerWidth() + 1 == size; } return false; } @@ -280,15 +282,15 @@ IconCacheEntry::SetIcon(BBitmap *bitmap, IconDrawMode mode, icon_size size, bool /*create*/) { if (mode == kNormalIcon) { - if (size == B_LARGE_ICON) - fLargeIcon = bitmap; - else + if (size == B_MINI_ICON) fMiniIcon = bitmap; - } else if (mode == kSelectedIcon) { - if (size == B_LARGE_ICON) - fHilitedLargeIcon = bitmap; else + fLargeIcon = bitmap; + } else if (mode == kSelectedIcon) { + if (size == B_MINI_ICON) fHilitedMiniIcon = bitmap; + else + fHilitedLargeIcon = bitmap; } else TRESPASS(); } diff --git a/src/kits/tracker/Pose.cpp b/src/kits/tracker/Pose.cpp index 2808253430..6b14b20c03 100644 --- a/src/kits/tracker/Pose.cpp +++ b/src/kits/tracker/Pose.cpp @@ -319,18 +319,14 @@ BPose::UpdateIcon(BPoint poseLoc, BPoseView *poseView) if (poseView->ViewMode() == kListMode) { rect = CalcRect(poseLoc, poseView); rect.left += kListOffset; + // TODO: make this depend on IconSizeInt() as well? rect.right = rect.left + B_MINI_ICON; rect.top = rect.bottom - B_MINI_ICON; - } else if (poseView->ViewMode() == kIconMode) { - rect.left = fLocation.x; - rect.top = fLocation.y; - rect.right = rect.left + B_LARGE_ICON; - rect.bottom = rect.top + B_LARGE_ICON; } else { rect.left = fLocation.x; rect.top = fLocation.y; - rect.right = rect.left + B_MINI_ICON; - rect.bottom = rect.top + B_MINI_ICON; + rect.right = rect.left + poseView->IconSizeInt(); + rect.bottom = rect.top + poseView->IconSizeInt(); } poseView->Invalidate(rect); @@ -439,28 +435,32 @@ BPose::PointInPose(const BPoseView *poseView, BPoint where) const { ASSERT(poseView->ViewMode() != kListMode); - if (poseView->ViewMode() == kIconMode) { + if (poseView->ViewMode() == kIconMode + || poseView->ViewMode() == kScaleIconMode) { // check icon rect, then actual icon pixel BRect rect(fLocation, fLocation); - rect.right += B_LARGE_ICON - 1; - rect.bottom += B_LARGE_ICON - 1; + rect.right += poseView->IconSizeInt() - 1; + rect.bottom += poseView->IconSizeInt() - 1; if (rect.Contains(where)) - return TestLargeIconPixel(where - fLocation); + return IconCache::sIconCache->IconHitTest(where - fLocation, + ResolvedModel(), + kNormalIcon, + poseView->IconSize()); BTextWidget *widget = WidgetFor(poseView->FirstColumn()->AttrHash()); if (widget) { float textWidth = ceilf(widget->TextWidth(poseView) + 1); - rect.left += (B_LARGE_ICON - textWidth) / 2; + rect.left += (poseView->IconSizeInt() - textWidth) / 2; rect.right = rect.left + textWidth; } - rect.top = fLocation.y + B_LARGE_ICON; + rect.top = fLocation.y + poseView->IconSizeInt(); rect.bottom = rect.top + poseView->FontHeight(); return rect.Contains(where); } - + // MINI_ICON_MODE rect calc BRect rect(fLocation, fLocation); rect.right += B_MINI_ICON + kMiniIconSeparator; @@ -468,7 +468,7 @@ BPose::PointInPose(const BPoseView *poseView, BPoint where) const BTextWidget *widget = WidgetFor(poseView->FirstColumn()->AttrHash()); if (widget) rect.right += ceil(widget->TextWidth(poseView) + 1); - + return rect.Contains(where); } @@ -509,47 +509,51 @@ void BPose::Draw(BRect rect, BPoseView *poseView, BView *drawView, bool fullDraw, const BRegion *updateRgn, BPoint offset, bool selected, bool recalculateText) { - if (fClipboardMode == kMoveSelectionTo) { - // If the background wasn't cleared and Draw() is not called after - // having edited a name or similar (with fullDraw) - if (!fBackgroundClean && !fullDraw) { - fBackgroundClean = true; - poseView->Invalidate(rect); - return; - } else - fBackgroundClean = false; - } - + // If the background wasn't cleared and Draw() is not called after + // having edited a name or similar (with fullDraw) + if (!fBackgroundClean && !fullDraw) { + fBackgroundClean = true; + poseView->Invalidate(rect); + return; + } else + fBackgroundClean = false; + bool directDraw = (drawView == poseView); bool windowActive = poseView->Window()->IsActive(); bool showSelectionWhenInactive = poseView->fShowSelectionWhenInactive; bool isDrawingSelectionRect = poseView->fIsDrawingSelectionRect; - + ModelNodeLazyOpener modelOpener(fModel); - + if (poseView->ViewMode() == kListMode) { + uint32 size = poseView->IconSizeInt(); BRect iconRect(rect); iconRect.OffsetBy(offset); iconRect.left += kListOffset; - iconRect.right = iconRect.left + B_MINI_ICON; - iconRect.top = iconRect.bottom - B_MINI_ICON; - if (!updateRgn || updateRgn->Intersects(iconRect)) - DrawIcon(iconRect.LeftTop(), drawView, B_MINI_ICON, directDraw, + iconRect.right = iconRect.left + size; + iconRect.top = iconRect.bottom - size; + if (!updateRgn || updateRgn->Intersects(iconRect)) { + DrawIcon(iconRect.LeftTop(), drawView, poseView->IconSize(), directDraw, !windowActive && !showSelectionWhenInactive); - + } + // draw text - for (int32 index = 0; ; index++) { + int32 columnsToDraw = 1; + if (fullDraw) + columnsToDraw = poseView->CountColumns(); + + for (int32 index = 0; index < columnsToDraw; index++) { BColumn *column = poseView->ColumnAt(index); if (!column) break; - + // if widget doesn't exist, create it BTextWidget *widget = WidgetFor(column, poseView, modelOpener); - + if (widget && widget->IsVisible()) { BRect widgetRect(widget->ColumnRect(rect.LeftTop(), column, poseView)); - + if (!updateRgn || updateRgn->Intersects(widgetRect)) { BRect widgetTextRect(widget->CalcRect(rect.LeftTop(), column, poseView)); @@ -557,10 +561,25 @@ BPose::Draw(BRect rect, BPoseView *poseView, BView *drawView, bool fullDraw, if (recalculateText) widget->RecalculateText(poseView); - widget->Draw(widgetRect, widgetTextRect, column->Width(), - poseView, drawView, selected, fClipboardMode, offset, directDraw); + bool selectDuringDraw = directDraw && selected + && (windowActive && !poseView->EraseWidgetTextBackground()); - if (index == 0 && selected) { + if (index == 0 && selectDuringDraw) { + //draw with dark background to select text + drawView->PushState(); + drawView->SetLowColor(0, 0, 0); + } + + if (index == 0) + widget->Draw(widgetRect, widgetTextRect, column->Width(), + poseView, drawView, selected, fClipboardMode, offset, directDraw); + else + widget->Draw(widgetTextRect, widgetTextRect, column->Width(), + poseView, drawView, false, fClipboardMode, offset, directDraw); + + if (index == 0 && selectDuringDraw) + drawView->PopState(); + else if (index == 0 && selected) { if (windowActive || isDrawingSelectionRect) { widgetTextRect.OffsetBy(offset); drawView->InvertRect(widgetTextRect); @@ -575,9 +594,6 @@ BPose::Draw(BRect rect, BPoseView *poseView, BView *drawView, bool fullDraw, } } } - - if (!fullDraw) - break; } } else { @@ -588,9 +604,8 @@ BPose::Draw(BRect rect, BPoseView *poseView, BView *drawView, bool fullDraw, BPoint iconOrigin(fLocation); iconOrigin += offset; - DrawIcon(iconOrigin, drawView, poseView->ViewMode() == kIconMode ? - B_LARGE_ICON : B_MINI_ICON, directDraw, - !windowActive && !showSelectionWhenInactive && !poseView->IsDesktopWindow()); + DrawIcon(iconOrigin, drawView, poseView->IconSize(), directDraw, + !windowActive && !showSelectionWhenInactive); BColumn *column = poseView->FirstColumn(); if (!column) @@ -642,8 +657,7 @@ BPose::DeselectWithoutErasingBackground(BRect, BPoseView *poseView) // draw icon directly if (fPercent == -1) - DrawIcon(fLocation, poseView, poseView->ViewMode() == kIconMode ? - B_LARGE_ICON : B_MINI_ICON, true); + DrawIcon(fLocation, poseView, poseView->IconSize(), true); else UpdateIcon(fLocation, poseView); @@ -696,7 +710,7 @@ BPose::MoveTo(BPoint point, BPoseView *poseView, bool inval) BTextWidget * BPose::ActiveWidget() const { - for (int32 i = fWidgetList.CountItems();i-- > 0;) { + for (int32 i = fWidgetList.CountItems(); i-- > 0;) { BTextWidget *widget = fWidgetList.ItemAt(i); if (widget->IsActive()) return widget; @@ -734,12 +748,14 @@ BPose::WidgetFor(BColumn *column, BPoseView *poseView, ModelNodeLazyOpener &open } +/* deprecated */ bool BPose::TestLargeIconPixel(BPoint point) const { return IconCache::sIconCache->IconHitTest(point, ResolvedModel(), kNormalIcon, B_LARGE_ICON); } +/* deprecated */ void @@ -747,7 +763,7 @@ BPose::DrawIcon(BPoint where, BView *view, icon_size kind, bool direct, bool dra { if (fClipboardMode == kMoveSelectionTo) { view->SetDrawingMode(B_OP_ALPHA); - view->SetHighColor(0,0,0,64); // set the level of transparency + view->SetHighColor(0, 0, 0, 64); // set the level of transparency view->SetBlendingMode(B_CONSTANT_ALPHA, B_ALPHA_OVERLAY); } else if (direct) view->SetDrawingMode(B_OP_OVER); @@ -765,29 +781,29 @@ BPose::DrawBar(BPoint where,BView *view,icon_size kind) { view->PushState(); - int32 size,barWidth,barHeight,yOffset; - if (kind == B_LARGE_ICON) { - size = B_LARGE_ICON - 1; - barWidth = 7; + int32 size, barWidth, barHeight, yOffset; + if (kind >= B_LARGE_ICON) { + size = kind - 1; + barWidth = (int32)((float)7 / (float)32 * (float)kind); yOffset = 2; - barHeight = size - 4 - 2*yOffset; + barHeight = size - 4 - 2 * yOffset; } else { size = B_MINI_ICON; barWidth = 4; yOffset = 0; - barHeight = size - 4 - 2*yOffset; + barHeight = size - 4 - 2 * yOffset; } // the black shadowed line - view->SetHighColor(32,32,32,92); - view->MovePenTo(BPoint(where.x + size,where.y + 1 + yOffset)); - view->StrokeLine(BPoint(where.x + size,where.y + size - yOffset)); - view->StrokeLine(BPoint(where.x + size - barWidth + 1,where.y + size - yOffset)); + view->SetHighColor(32, 32, 32, 92); + view->MovePenTo(BPoint(where.x + size, where.y + 1 + yOffset)); + view->StrokeLine(BPoint(where.x + size, where.y + size - yOffset)); + view->StrokeLine(BPoint(where.x + size - barWidth + 1, where.y + size - yOffset)); view->SetDrawingMode(B_OP_ALPHA); // the gray frame - view->SetHighColor(76,76,76,192); + view->SetHighColor(76, 76, 76, 192); BRect rect( where.x + size - barWidth,where.y + yOffset, where.x + size - 1,where.y + size - 1 - yOffset); view->StrokeRect(rect); @@ -801,8 +817,7 @@ BPose::DrawBar(BPoint where,BView *view,icon_size kind) barPos = barHeight; // the free space bar - TrackerSettings settings; - view->SetHighColor(settings.FreeSpaceColor()); + view->SetHighColor(TrackerSettings().FreeSpaceColor()); rect.InsetBy(1,1); BRect bar(rect); @@ -813,7 +828,7 @@ BPose::DrawBar(BPoint where,BView *view,icon_size kind) // the used space bar bar.top = bar.bottom + 1; bar.bottom = rect.bottom; - view->SetHighColor(fPercent < -1 ? settings.WarningSpaceColor() : settings.UsedSpaceColor()); + view->SetHighColor(fPercent < -1 ? TrackerSettings().WarningSpaceColor() : TrackerSettings().UsedSpaceColor()); view->FillRect(bar); view->PopState(); @@ -852,19 +867,19 @@ BPose::CalcRect(BPoint loc, const BPoseView *poseView, bool minimalRect) BRect BPose::CalcRect(const BPoseView *poseView) { - ASSERT(poseView->ViewMode() != kListMode); BRect rect; - if (poseView->ViewMode() == kIconMode) { + if (poseView->ViewMode() == kIconMode + || poseView->ViewMode() == kScaleIconMode) { rect.left = fLocation.x; - rect.right = rect.left + B_LARGE_ICON; + rect.right = rect.left + poseView->IconSizeInt(); BTextWidget *widget = WidgetFor(poseView->FirstColumn()->AttrHash()); if (widget) { float textWidth = ceilf(widget->TextWidth(poseView) + 1); - if (textWidth > B_LARGE_ICON) { - rect.left += (B_LARGE_ICON - textWidth) / 2; + if (textWidth > poseView->IconSizeInt()) { + rect.left += (poseView->IconSizeInt() - textWidth) / 2; rect.right = rect.left + textWidth; } } @@ -892,7 +907,6 @@ void BPose::PrintToStream() { TargetModel()->PrintToStream(); - PRINT(("%sselected\n", IsSelected() ? "" : "not ")); switch (fClipboardMode) { case kMoveSelectionTo: PRINT(("clipboardMode: Cut\n")); @@ -903,10 +917,11 @@ BPose::PrintToStream() default: PRINT(("clipboardMode: 0 - not in clipboard\n")); } + PRINT(("%sselected\n", IsSelected() ? "" : "not ")); PRINT(("location %s x:%f y:%f\n", HasLocation() ? "" : "unknown ", HasLocation() ? Location().x : 0, HasLocation() ? Location().y : 0)); - PRINT(("%sautoplaced \n", WasAutoPlaced() ? "was " : "not ")); + PRINT(("%s autoplaced \n", WasAutoPlaced() ? "was" : "not")); } #endif diff --git a/src/kits/tracker/PoseView.cpp b/src/kits/tracker/PoseView.cpp index a6a2af3574..c8f47428f2 100644 --- a/src/kits/tracker/PoseView.cpp +++ b/src/kits/tracker/PoseView.cpp @@ -905,14 +905,22 @@ BPoseView::SetIconPoseHeight() { switch (ViewMode()) { case kIconMode: - fIconPoseHeight = ceilf(B_LARGE_ICON + fFontHeight + 1); + fViewState->SetIconSize(B_LARGE_ICON); + fIconPoseHeight = ceilf(IconSizeInt() + fFontHeight + 1); break; - + case kMiniIconMode: - fIconPoseHeight = ceilf(fFontHeight < B_MINI_ICON ? B_MINI_ICON : fFontHeight + 1); + fViewState->SetIconSize(B_MINI_ICON); + fIconPoseHeight = ceilf(fFontHeight < IconSizeInt() ? IconSizeInt() : fFontHeight + 1); break; - + + case kScaleIconMode: + // IconSize should allready be set in MessageReceived() + fIconPoseHeight = ceilf(IconSizeInt() + fFontHeight + 1); + break; + default: + fViewState->SetIconSize(B_MINI_ICON); fIconPoseHeight = fListElemHeight; break; } @@ -932,10 +940,15 @@ BPoseView::GetLayoutInfo(uint32 mode, BPoint *grid, BPoint *offset) const grid->Set(60, 60); offset->Set(20, 20); break; - + + case kScaleIconMode: + grid->Set(IconSizeInt() + 28, IconSizeInt() + 28); + offset->Set(20, 20); + break; + default: - offset->Set(5, 5); grid->Set(0, 0); + offset->Set(5, 5); break; } } @@ -1669,6 +1682,7 @@ BPoseView::CreatePoses(Model **models, PoseInfo *poseInfoArray, int32 count, case kIconMode: case kMiniIconMode: + case kScaleIconMode: if (poseInfo->fInitedDirectory == -1LL || fAlwaysAutoPlace) { if (pose->HasLocation()) RemoveFromVSList(pose); @@ -1909,8 +1923,8 @@ BPoseView::AddCountView() Window()->AddChild(fCountView); if (fHScrollBar) { - fHScrollBar->MoveBy(kCountViewWidth+1, 0); - fHScrollBar->ResizeBy(-kCountViewWidth-1, 0); + fHScrollBar->MoveBy(kCountViewWidth + 1, 0); + fHScrollBar->ResizeBy(-kCountViewWidth - 1, 0); } } @@ -1974,6 +1988,17 @@ BPoseView::MessageReceived(BMessage *message) pendingNodeMonitorCache.Add(message); break; + case kScaleIconMode: { + int32 size; + if (message->FindInt32("size", &size) == B_OK) { + if (size != (int32)IconSizeInt()) { + fViewState->SetIconSize(size); + Refresh(); // we need to refresh since the icons need + // to be rescaled + } else + break; // no change + } + } // fall thru case kListMode: case kIconMode: case kMiniIconMode: @@ -2636,7 +2661,7 @@ BPoseView::ReadExtendedPoseInfo(Model *model) void BPoseView::SetViewMode(uint32 newMode) { - if (newMode == ViewMode()) + if (newMode == ViewMode() && newMode != kScaleIconMode) return; ASSERT(!IsFilePanel()); @@ -2729,7 +2754,7 @@ BPoseView::SetViewMode(uint32 newMode) } // sort poselist if we are switching to list mode - if (ViewMode() == kListMode) + if (newMode == kListMode) SortPoses(); else RecalcExtent(); @@ -3139,6 +3164,9 @@ BPoseView::PlacePose(BPose *pose, BRect &viewBounds) void BPoseView::CheckAutoPlacedPoses() { + if (ViewMode() == kListMode) + return; + BRect viewBounds(Bounds()); int32 count = fPoseList->CountItems(); @@ -3843,7 +3871,7 @@ BPoseView::HandleMessageDropped(BMessage *message) return true; } - if (fDropTarget) + if (fDropTarget && !DragSelectionContains(fDropTarget, message)) HiliteDropTarget(false); fDropTarget = NULL; @@ -4847,7 +4875,8 @@ BPoseView::FSNotification(const BMessage *message) if (TargetModel() != NULL && TargetModel()->IsRoot()) { BVolume volume(device); - CreateVolumePose(&volume, false); + if (volume.InitCheck() == B_OK) + CreateVolumePose(&volume, false); } else if (ContainerWindow()->IsTrash()) { // add trash items from newly mounted volume @@ -6864,8 +6893,12 @@ BPoseView::SelectPosesListMode(BRect selectionRect, BList **oldList) newList->AddItem((void *)index); // this sucks, need to clean up // using a vector class instead of BList - if ((selected != pose->IsSelected()) && poseRect.Intersects(bounds)) - pose->Draw(poseRect, this, false); + if ((selected != pose->IsSelected()) && poseRect.Intersects(bounds)) { + if (pose->IsSelected() || EraseWidgetTextBackground()) + pose->Draw(poseRect, this, false); + else + Invalidate(poseRect); + } // First Pose selected gets to be the pivot. if ((fSelectionPivotPose == NULL) && (selected == false)) @@ -6889,8 +6922,12 @@ BPoseView::SelectPosesListMode(BRect selectionRect, BList **oldList) loc.Set(0, oldIndex * fListElemHeight); BRect poseRect(pose->CalcRect(loc, this)); - if (poseRect.Intersects(bounds)) - pose->Draw(poseRect, this, false); + if (poseRect.Intersects(bounds)) { + if (pose->IsSelected() || EraseWidgetTextBackground()) + pose->Draw(poseRect, this, false); + else + Invalidate(poseRect); + } } } @@ -6924,11 +6961,12 @@ BPoseView::SelectPosesIconMode(BRect selectionRect, BList **oldList) pose->Select(!fSelectionList->HasItem(pose)); newList->AddItem((void *)index); - if ((selected != pose->IsSelected()) && poseRect.Intersects(bounds)) + if ((selected != pose->IsSelected()) && poseRect.Intersects(bounds)) { if (pose->IsSelected() || EraseWidgetTextBackground()) pose->Draw(poseRect, this, false); else Invalidate(poseRect); + } // First Pose selected gets to be the pivot. if ((fSelectionPivotPose == NULL) && (selected == false)) @@ -7370,7 +7408,11 @@ BPoseView::UnmountSelectedVolumes() int32 select_count = fSelectionList->CountItems(); for (int32 index = 0; index < select_count; index++) { - Model *model = fSelectionList->ItemAt(index)->TargetModel(); + BPose *pose = fSelectionList->ItemAt(index); + if (!pose) + continue; + + Model *model = pose->TargetModel(); if (model->IsVolume()) { BVolume volume(model->NodeRef()->device); if (volume != boot) { @@ -7705,7 +7747,11 @@ BPoseView::ClearSelection() BPose *pose = fPoseList->ItemAt(index); if (pose->IsSelected()) { pose->Select(false); - pose->Draw(pose->CalcRect(loc, this, false), this, false); + BRect poseRect(pose->CalcRect(loc, this, false)); + if (EraseWidgetTextBackground()) + pose->Draw(poseRect, this, false); + else + Invalidate(poseRect); } loc.y += fListElemHeight; @@ -8678,7 +8724,7 @@ BPoseView::UpdateDropTarget(BPoint mouseLoc, const BMessage *dragMessage, // no change return false; - if (fDropTarget) + if (fDropTarget && !DragSelectionContains(fDropTarget, dragMessage)) HiliteDropTarget(false); fDropTarget = targetPose; diff --git a/src/kits/tracker/PoseView.h b/src/kits/tracker/PoseView.h index 014a64123a..1478662063 100644 --- a/src/kits/tracker/PoseView.h +++ b/src/kits/tracker/PoseView.h @@ -79,6 +79,7 @@ const int32 kListOffset = 20; const uint32 kMiniIconMode = 'Tmic'; const uint32 kIconMode = 'Ticn'; const uint32 kListMode = 'Tlst'; +const uint32 kScaleIconMode = 'Tsic'; // new mode for scaled icons const uint32 kCheckTypeahead = 'Tcty'; @@ -195,6 +196,8 @@ class BPoseView : public BView { void SetIconPoseHeight(); float IconPoseHeight() const; + uint32 IconSizeInt() const; + icon_size IconSize() const; BRect Extent() const; void GetLayoutInfo(uint32 viewMode, BPoint *grid, BPoint *offset) const; @@ -724,6 +727,18 @@ BPoseView::IconPoseHeight() const return fIconPoseHeight; } +inline uint32 +BPoseView::IconSizeInt() const +{ + return fViewState->IconSize(); +} + +inline icon_size +BPoseView::IconSize() const +{ + return (icon_size)fViewState->IconSize(); +} + inline PoseList * BPoseView::SelectionList() const { diff --git a/src/kits/tracker/TextWidget.cpp b/src/kits/tracker/TextWidget.cpp index 9264381bc9..cd1c5aa925 100644 --- a/src/kits/tracker/TextWidget.cpp +++ b/src/kits/tracker/TextWidget.cpp @@ -169,11 +169,14 @@ BTextWidget::CalcRectCommon(BPoint poseLoc, const BColumn *column, result.bottom = poseLoc.y + (view->ListElemHeight() - 1); } else { - if (view->ViewMode() == kIconMode) - result.left = poseLoc.x + (B_LARGE_ICON - textWidth) / 2; - else - // MINI_ICON_MODE rect calc + if (view->ViewMode() == kIconMode + || view->ViewMode() == kScaleIconMode) { + // large/scaled icon mode + result.left = poseLoc.x + (view->IconSizeInt() - textWidth) / 2; + } else { + // mini icon mode result.left = poseLoc.x + B_MINI_ICON + kMiniIconSeparator; + } result.right = result.left + textWidth; result.bottom = poseLoc.y + view->IconPoseHeight(); @@ -345,8 +348,10 @@ BTextWidget::StartEdit(BRect bounds, BPoseView *view, BPose *pose) rect.right = rect.left + textView->LineWidth() + 3; // center new width, if necessary if (view->ViewMode() == kIconMode - || view->ViewMode() == kListMode && fAlignment == B_ALIGN_CENTER) + || view->ViewMode() == kScaleIconMode + || view->ViewMode() == kListMode && fAlignment == B_ALIGN_CENTER) { rect.OffsetBy(bounds.Width() / 2 - rect.Width() / 2, 0); + } rect.bottom = rect.top + textView->LineHeight() + 1; textRect = rect.OffsetToCopy(2, 1); @@ -371,6 +376,7 @@ BTextWidget::StartEdit(BRect bounds, BPoseView *view, BPose *pose) // configure text view switch (view->ViewMode()) { case kIconMode: + case kScaleIconMode: textView->SetAlignment(B_ALIGN_CENTER); break; diff --git a/src/kits/tracker/Utilities.cpp b/src/kits/tracker/Utilities.cpp index a9f124dd2d..fb206db75e 100644 --- a/src/kits/tracker/Utilities.cpp +++ b/src/kits/tracker/Utilities.cpp @@ -1334,50 +1334,50 @@ GetAppIconFromAttr(BFile *file, BBitmap *result, icon_size size) // app icons -- the call is expensive because by default // the resource fork is scanned to read the icons -#ifdef B_APP_FILE_INFO_IS_FAST +//#ifdef B_APP_FILE_INFO_IS_FAST BAppFileInfo appFileInfo(file); return appFileInfo.GetIcon(result, size); -#else - - const char *attrName = kAttrIcon; - uint32 type = B_RAW_TYPE; - - // try vector icon - attr_info ainfo; - status_t ret = file->GetAttrInfo(attrName, &ainfo); - - if (ret == B_OK) { - uint8 buffer[ainfo.size]; - ssize_t readResult = file->ReadAttr(attrName, type, 0, buffer, - ainfo.size); - if (readResult == ainfo.size) { - if (BIconUtils::GetVectorIcon(buffer, ainfo.size, result) == B_OK) - return B_OK; - } - } - - // try again with R5 icons - attrName = size == B_LARGE_ICON ? kAttrLargeIcon : kAttrMiniIcon; - type = size == B_LARGE_ICON ? LARGE_ICON_TYPE : MINI_ICON_TYPE; - - ret = file->GetAttrInfo(attrName, &ainfo); - if (ret < B_OK) - return ret; - - uint8 buffer[ainfo.size]; - - ssize_t readResult = file->ReadAttr(attrName, type, 0, buffer, ainfo.size); - if (readResult <= 0) - return (status_t)readResult; - - if (result->ColorSpace() != B_CMAP8) { - ret = BIconUtils::ConvertFromCMAP8(buffer, size, size, size, result); - } else { - result->SetBits(buffer, result->BitsLength(), 0, B_CMAP8); - } - - return ret; -#endif // B_APP_FILE_INFO_IS_FAST +//#else +// +// const char *attrName = kAttrIcon; +// uint32 type = B_RAW_TYPE; +// +// // try vector icon +// attr_info ainfo; +// status_t ret = file->GetAttrInfo(attrName, &ainfo); +// +// if (ret == B_OK) { +// uint8 buffer[ainfo.size]; +// ssize_t readResult = file->ReadAttr(attrName, type, 0, buffer, +// ainfo.size); +// if (readResult == ainfo.size) { +// if (BIconUtils::GetVectorIcon(buffer, ainfo.size, result) == B_OK) +// return B_OK; +// } +// } +// +// // try again with R5 icons +// attrName = size == B_LARGE_ICON ? kAttrLargeIcon : kAttrMiniIcon; +// type = size == B_LARGE_ICON ? LARGE_ICON_TYPE : MINI_ICON_TYPE; +// +// ret = file->GetAttrInfo(attrName, &ainfo); +// if (ret < B_OK) +// return ret; +// +// uint8 buffer[ainfo.size]; +// +// ssize_t readResult = file->ReadAttr(attrName, type, 0, buffer, ainfo.size); +// if (readResult <= 0) +// return (status_t)readResult; +// +// if (result->ColorSpace() != B_CMAP8) { +// ret = BIconUtils::ConvertFromCMAP8(buffer, size, size, size, result); +// } else { +// result->SetBits(buffer, result->BitsLength(), 0, B_CMAP8); +// } +// +// return ret; +//#endif // B_APP_FILE_INFO_IS_FAST } diff --git a/src/kits/tracker/ViewState.cpp b/src/kits/tracker/ViewState.cpp index 9b2af6d7ee..51e483ffe5 100644 --- a/src/kits/tracker/ViewState.cpp +++ b/src/kits/tracker/ViewState.cpp @@ -124,11 +124,11 @@ BColumn::InstantiateFromStream(BMallocIO *stream, bool endianSwap) version = SwapInt32(version); } - // PRINT(("validating key %x, version %d\n", key, version)); +// PRINT(("validating key %x, version %d\n", key, version)); if (!ValidateStream(stream, key, version)) return 0; - // PRINT(("instantiating column, %s\n", endianSwap ? "endian swapping," : "")); +// PRINT(("instantiating column, %s\n", endianSwap ? "endian swapping," : "")); BColumn *result = new BColumn(stream, endianSwap); // sanity-check the resulting column @@ -191,7 +191,7 @@ BColumn::ArchiveToStream(BMallocIO *stream) const int32 version = kColumnStateArchiveVersion; stream->Write(&version, sizeof(int32)); - // PRINT(("ArchiveToStream column, key %x, version %d\n", key, version)); +// PRINT(("ArchiveToStream column, key %x, version %d\n", key, version)); StringToStream(&fTitle, stream); stream->Write(&fOffset, sizeof(float)); @@ -230,11 +230,13 @@ const char *kViewStatePrimarySortTypeName = "ViewState:fPrimarySortType"; const char *kViewStateSecondarySortAttrName = "ViewState:fSecondarySortAttr"; const char *kViewStateSecondarySortTypeName = "ViewState:fSecondarySortType"; const char *kViewStateReverseSortName = "ViewState:fReverseSort"; +const char *kViewStateIconSizeName = "ViewState:fIconSize"; BViewState::BViewState() { fViewMode = kListMode; fLastIconMode = 0; + fIconSize = 32; fListOrigin.Set(0, 0); fIconOrigin.Set(0, 0); fPrimarySortAttr = AttrHashString(kAttrStatName, B_STRING_TYPE); @@ -256,11 +258,13 @@ BViewState::BViewState(BMallocIO *stream, bool endianSwap) stream->Read(&fSecondarySortAttr, sizeof(uint32)); stream->Read(&fSecondarySortType, sizeof(uint32)); stream->Read(&fReverseSort, sizeof(bool)); + stream->Read(&fIconSize, sizeof(uint32)); if (endianSwap) { PRINT(("endian swapping view state\n")); fViewMode = B_SWAP_INT32(fViewMode); fLastIconMode = B_SWAP_INT32(fLastIconMode); + fIconSize = B_SWAP_INT32(fIconSize); swap_data(B_POINT_TYPE, &fListOrigin, sizeof(fListOrigin), B_SWAP_ALWAYS); swap_data(B_POINT_TYPE, &fIconOrigin, sizeof(fIconOrigin), B_SWAP_ALWAYS); fPrimarySortAttr = B_SWAP_INT32(fPrimarySortAttr); @@ -268,6 +272,13 @@ BViewState::BViewState(BMallocIO *stream, bool endianSwap) fPrimarySortType = B_SWAP_INT32(fPrimarySortType); fSecondarySortType = B_SWAP_INT32(fSecondarySortType); } + + // assure a sane state + if (fIconSize < 16) + fIconSize = 16; + if (fIconSize > 64) + fIconSize = 64; + fStateNeedsSaving = false; } @@ -282,7 +293,14 @@ BViewState::BViewState(const BMessage &message) message.FindInt32(kViewStateSecondarySortAttrName, (int32 *)&fSecondarySortAttr); message.FindInt32(kViewStateSecondarySortTypeName, (int32 *)&fSecondarySortType); message.FindBool(kViewStateReverseSortName, &fReverseSort); + message.FindInt32(kViewStateIconSizeName, (int32 *)&fIconSize); + // assure a sane state + if (fIconSize < 16) + fIconSize = 16; + if (fIconSize > 64) + fIconSize = 64; + fStateNeedsSaving = false; } @@ -304,6 +322,7 @@ BViewState::ArchiveToStream(BMallocIO *stream) const stream->Write(&fSecondarySortAttr, sizeof(uint32)); stream->Write(&fSecondarySortType, sizeof(uint32)); stream->Write(&fReverseSort, sizeof(bool)); + stream->Write(&fIconSize, sizeof(uint32)); } @@ -321,6 +340,7 @@ BViewState::ArchiveToMessage(BMessage &message) const message.AddInt32(kViewStateSecondarySortAttrName, static_cast(fSecondarySortAttr)); message.AddInt32(kViewStateSecondarySortTypeName, static_cast(fSecondarySortType)); message.AddBool(kViewStateReverseSortName, fReverseSort); + message.AddInt32(kViewStateIconSizeName, static_cast(fIconSize)); } @@ -346,10 +366,12 @@ BViewState::InstantiateFromStream(BMallocIO *stream, bool endianSwap) if ((result->fViewMode != kListMode && result->fViewMode != kIconMode && result->fViewMode != kMiniIconMode + && result->fViewMode != kScaleIconMode && result->fViewMode != 0) || (result->fLastIconMode != kListMode && result->fLastIconMode != kIconMode && result->fLastIconMode != kMiniIconMode + && result->fLastIconMode != kScaleIconMode && result->fLastIconMode != 0)) { PRINT(("Bad data instantiating ViewState, view mode %x, lastIconMode %x\n", @@ -384,12 +406,14 @@ BViewState::InstantiateFromMessage(const BMessage &message) if ((result->fViewMode != kListMode && result->fViewMode != kIconMode && result->fViewMode != kMiniIconMode + && result->fViewMode != kScaleIconMode && result->fViewMode != 0) || (result->fLastIconMode != kListMode && result->fLastIconMode != kIconMode && result->fLastIconMode != kMiniIconMode + && result->fLastIconMode != kScaleIconMode && result->fLastIconMode != 0)) { - + PRINT(("Bad data instantiating ViewState, view mode %x, lastIconMode %x\n", result->fViewMode, result->fLastIconMode)); diff --git a/src/kits/tracker/ViewState.h b/src/kits/tracker/ViewState.h index 9b290fcc66..6aa1201bec 100644 --- a/src/kits/tracker/ViewState.h +++ b/src/kits/tracker/ViewState.h @@ -99,6 +99,7 @@ class BViewState { uint32 ViewMode() const; uint32 LastIconMode() const; + uint32 IconSize() const; BPoint ListOrigin() const; BPoint IconOrigin() const; uint32 PrimarySort() const; @@ -109,6 +110,7 @@ class BViewState { void SetViewMode(uint32); void SetLastIconMode(uint32); + void SetIconSize(uint32); void SetListOrigin(BPoint); void SetIconOrigin(BPoint); void SetPrimarySort(uint32); @@ -123,6 +125,7 @@ class BViewState { private: uint32 fViewMode; uint32 fLastIconMode; + uint32 fIconSize; BPoint fListOrigin; BPoint fIconOrigin; uint32 fPrimarySortAttr; @@ -211,6 +214,12 @@ BViewState::LastIconMode() const return fLastIconMode; } +inline uint32 +BViewState::IconSize() const +{ + return fIconSize; +} + inline BPoint BViewState::ListOrigin() const { @@ -271,6 +280,12 @@ BViewState::SetLastIconMode(uint32 mode) fLastIconMode = mode; } +inline void +BViewState::SetIconSize(uint32 size) +{ + fIconSize = size; +} + inline void BViewState::SetListOrigin(BPoint newOrigin) { diff --git a/src/libs/icon/IconUtils.cpp b/src/libs/icon/IconUtils.cpp index afc96c646c..ede70ae81a 100644 --- a/src/libs/icon/IconUtils.cpp +++ b/src/libs/icon/IconUtils.cpp @@ -334,10 +334,10 @@ BIconUtils::ConvertFromCMAP8(const uint8* src, const rgb_color* colorMap = system_colors()->color_list; - for (uint32 y = 0; y < dstHeight; y++) { + for (uint32 y = 0; y < height; y++) { uint32* d = (uint32*)dst; const uint8* s = src; - for (uint32 x = 0; x < dstWidth; x++) { + for (uint32 x = 0; x < width; x++) { const rgb_color c = colorMap[*s]; uint8 alpha = 255; if (*s == B_TRANSPARENT_MAGIC_CMAP8) diff --git a/src/servers/registrar/MIMEManager.cpp b/src/servers/registrar/MIMEManager.cpp index 861b4a3ce1..58d4c50334 100644 --- a/src/servers/registrar/MIMEManager.cpp +++ b/src/servers/registrar/MIMEManager.cpp @@ -353,11 +353,16 @@ MIMEManager::HandleSetParam(BMessage *message) if (!err) err = message->FindString("file type", &fileType); if (!err) - err = fDatabase.SetIconForType(type, fileType, data, - dataSize, (icon_size)size); + err = size == -1 ? + fDatabase.SetIconForType(type, fileType, data, + dataSize) : + fDatabase.SetIconForType(type, fileType, data, + dataSize, (icon_size)size); } else { if (!err) - err = fDatabase.SetIcon(type, data, dataSize, + err = size == -1 ? + fDatabase.SetIcon(type, data, dataSize) : + fDatabase.SetIcon(type, data, dataSize, (icon_size)size); } break; @@ -457,10 +462,14 @@ MIMEManager::HandleDeleteParam(BMessage *message) if (!err) err = message->FindString("file type", &fileType); if (!err) - err = fDatabase.DeleteIconForType(type, fileType, (icon_size)size); + err = (size == -1) ? + fDatabase.DeleteIconForType(type, fileType) : + fDatabase.DeleteIconForType(type, fileType, (icon_size)size); } else { if (!err) - err = fDatabase.DeleteIcon(type, (icon_size)size); + err = (size == -1) ? + fDatabase.DeleteIcon(type) : + fDatabase.DeleteIcon(type, (icon_size)size); } break; }