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; }