WebPositive: draggable page icon
* Enable user to drag the WebPositive web page icon to the bookmark bar to create a bookmark there, or drag it to a Tracker window to create a bookmark in the displayed directory. * Send a message to the drag target that can be handled by Tracker's generic drop routine. * Overload _CreateBookmark with a more flexible version and a _CreateBookmark(BMessage*) that handles both the icon being dropped on the bookmark bar, and the message that Tracker sends if the icon is dropped on Tracker. * Account for the fact that, when _CreateBookmark(BMessage*) is called, Tracker may or may not have already determined the file name to use and created the file, depending on whether the icon was dragged to Tracker or not. * Use page-specific small and large icons for the bookmark file, if they are available (currently Haiku WebKit doesn't seem to provide them though). * Follows CharacterMap as a model for dragging an icon and ShowImage for dragging to Tracker. * Fixes #10795. Change-Id: I7f32013cc1372dab1894b5d92335d3a4cbfb671f Reviewed-on: https://review.haiku-os.org/c/haiku/+/6007 Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org> Reviewed-by: Adrien Destugues <pulkomandy@pulkomandy.tk>
This commit is contained in:
parent
88f36b2dd9
commit
5214106737
@ -146,6 +146,7 @@ static const char* kHandledProtocols[] = {
|
|||||||
"gopher"
|
"gopher"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char* kBookmarkBarSubdir = B_TRANSLATE("Bookmark bar");
|
||||||
|
|
||||||
static BLayoutItem*
|
static BLayoutItem*
|
||||||
layoutItemFor(BView* view)
|
layoutItemFor(BView* view)
|
||||||
@ -500,7 +501,7 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings,
|
|||||||
mainMenu->AddItem(bookmarkMenu);
|
mainMenu->AddItem(bookmarkMenu);
|
||||||
|
|
||||||
BDirectory barDir(&bookmarkRef);
|
BDirectory barDir(&bookmarkRef);
|
||||||
BEntry bookmarkBar(&barDir, "Bookmark bar");
|
BEntry bookmarkBar(&barDir, kBookmarkBarSubdir);
|
||||||
entry_ref bookmarkBarRef;
|
entry_ref bookmarkBarRef;
|
||||||
// TODO we could also check if the folder is empty here.
|
// TODO we could also check if the folder is empty here.
|
||||||
if (bookmarkBar.Exists() && bookmarkBar.GetRef(&bookmarkBarRef)
|
if (bookmarkBar.Exists() && bookmarkBar.GetRef(&bookmarkBarRef)
|
||||||
@ -966,6 +967,25 @@ BrowserWindow::MessageReceived(BMessage* message)
|
|||||||
|
|
||||||
case B_SIMPLE_DATA:
|
case B_SIMPLE_DATA:
|
||||||
{
|
{
|
||||||
|
const char* filetype = message->GetString("be:filetypes");
|
||||||
|
if (filetype != NULL
|
||||||
|
&& strcmp(filetype, "application/x-vnd.Be-bookmark") == 0
|
||||||
|
&& LastMouseMovedView() == fBookmarkBar) {
|
||||||
|
// Something that can be made into a bookmark (e.g. the page icon)
|
||||||
|
// was dragged and dropped on the bookmark bar.
|
||||||
|
BPath path;
|
||||||
|
if (_BookmarkPath(path) == B_OK && path.Append(kBookmarkBarSubdir) == B_OK) {
|
||||||
|
entry_ref ref;
|
||||||
|
if (BEntry(path.Path()).GetRef(&ref) == B_OK) {
|
||||||
|
message->AddRef("directory", &ref);
|
||||||
|
// Add under the same name that Tracker would use, if
|
||||||
|
// the ref had been added by dragging and dropping to Tracker.
|
||||||
|
_CreateBookmark(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// User possibly dropped files on this window.
|
// User possibly dropped files on this window.
|
||||||
// If there is more than one entry_ref, let the app handle it
|
// If there is more than one entry_ref, let the app handle it
|
||||||
// (open one new page per ref). If there is one ref, open it in
|
// (open one new page per ref). If there is one ref, open it in
|
||||||
@ -1195,6 +1215,20 @@ BrowserWindow::MessageReceived(BMessage* message)
|
|||||||
BWebWindow::MessageReceived(message);
|
BWebWindow::MessageReceived(message);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case B_COPY_TARGET:
|
||||||
|
{
|
||||||
|
const char* filetype = message->GetString("be:filetypes");
|
||||||
|
if (filetype != NULL && strcmp(filetype, "application/x-vnd.Be-bookmark") == 0) {
|
||||||
|
// Tracker replied after the user dragged and dropped something
|
||||||
|
// that can be bookmarked (e.g. the page icon) to a Tracker window.
|
||||||
|
_CreateBookmark(message);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
BWebWindow::MessageReceived(message);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
BWebWindow::MessageReceived(message);
|
BWebWindow::MessageReceived(message);
|
||||||
break;
|
break;
|
||||||
@ -1900,76 +1934,69 @@ BrowserWindow::_BookmarkPath(BPath& path) const
|
|||||||
return create_directory(path.Path(), 0777);
|
return create_directory(path.Path(), 0777);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! If fileName is an empty BString, a valid file name will be derived from title.
|
||||||
|
miniIcon and largeIcon may be NULL.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
BrowserWindow::_CreateBookmark()
|
BrowserWindow::_CreateBookmark(const BPath& path, BString fileName, const BString& title,
|
||||||
|
const BString& url, const BBitmap* miniIcon, const BBitmap* largeIcon)
|
||||||
{
|
{
|
||||||
BPath path;
|
// Determine the file name if one was not provided
|
||||||
status_t status = _BookmarkPath(path);
|
bool presetFileName = true;
|
||||||
if (status != B_OK) {
|
if (fileName.IsEmpty() == true) {
|
||||||
BString message(B_TRANSLATE_COMMENT("There was an error retrieving "
|
presetFileName = false;
|
||||||
"the bookmark folder.\n\nError: %error", "Don't translate the "
|
fileName = title;
|
||||||
"variable %error"));
|
if (fileName.Length() == 0) {
|
||||||
message.ReplaceFirst("%error", strerror(status));
|
fileName = url;
|
||||||
BAlert* alert = new BAlert(B_TRANSLATE("Bookmark error"),
|
int32 leafPos = fileName.FindLast('/');
|
||||||
message.String(), B_TRANSLATE("OK"), NULL, NULL,
|
if (leafPos >= 0)
|
||||||
B_WIDTH_AS_USUAL, B_STOP_ALERT);
|
fileName.Remove(0, leafPos + 1);
|
||||||
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
|
}
|
||||||
alert->Go();
|
fileName.ReplaceAll('/', '-');
|
||||||
return;
|
fileName.Truncate(B_FILE_NAME_LENGTH - 1);
|
||||||
}
|
|
||||||
BWebView* webView = CurrentWebView();
|
|
||||||
BString url(webView->MainFrameURL());
|
|
||||||
// Create a bookmark file
|
|
||||||
BFile bookmarkFile;
|
|
||||||
BString bookmarkName(webView->MainFrameTitle());
|
|
||||||
if (bookmarkName.Length() == 0) {
|
|
||||||
bookmarkName = url;
|
|
||||||
int32 leafPos = bookmarkName.FindLast('/');
|
|
||||||
if (leafPos >= 0)
|
|
||||||
bookmarkName.Remove(0, leafPos + 1);
|
|
||||||
}
|
|
||||||
// Make sure the bookmark title does not contain chars that are not
|
|
||||||
// allowed in file names, and is within allowed name length.
|
|
||||||
bookmarkName.ReplaceAll('/', '-');
|
|
||||||
bookmarkName.Truncate(B_FILE_NAME_LENGTH - 1);
|
|
||||||
|
|
||||||
// Check that the bookmark exists nowhere in the bookmark hierarchy,
|
|
||||||
// though the intended file name must match, we don't search the stored
|
|
||||||
// URLs, only for matching file names.
|
|
||||||
BDirectory directory(path.Path());
|
|
||||||
if (status == B_OK && _CheckBookmarkExists(directory, bookmarkName, url)) {
|
|
||||||
BString message(B_TRANSLATE_COMMENT("A bookmark for this page "
|
|
||||||
"(%bookmarkName) already exists.", "Don't translate variable "
|
|
||||||
"%bookmarkName"));
|
|
||||||
message.ReplaceFirst("%bookmarkName", bookmarkName);
|
|
||||||
BAlert* alert = new BAlert(B_TRANSLATE("Bookmark info"),
|
|
||||||
message.String(), B_TRANSLATE("OK"));
|
|
||||||
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
|
|
||||||
alert->Go();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BPath entryPath(path);
|
BPath entryPath(path);
|
||||||
status = entryPath.Append(bookmarkName);
|
status_t status = entryPath.Append(fileName);
|
||||||
BEntry entry;
|
BEntry entry;
|
||||||
if (status == B_OK)
|
if (status == B_OK)
|
||||||
status = entry.SetTo(entryPath.Path(), true);
|
status = entry.SetTo(entryPath.Path(), true);
|
||||||
if (status == B_OK) {
|
|
||||||
int32 tries = 1;
|
// There are several reasons why an entry matching the path argument could already exist.
|
||||||
while (entry.Exists()) {
|
if (status == B_OK && entry.Exists() == true) {
|
||||||
// Find a unique name for the bookmark, there may still be a
|
off_t size;
|
||||||
// file in the way that stores a different URL.
|
entry.GetSize(&size);
|
||||||
bookmarkName = webView->MainFrameTitle();
|
char attrName[B_ATTR_NAME_LENGTH];
|
||||||
bookmarkName << " " << tries++;
|
BNode node(&entry);
|
||||||
entryPath = path;
|
status_t attrStatus = node.GetNextAttrName(attrName);
|
||||||
status = entryPath.Append(bookmarkName);
|
if (strcmp(attrName, "_trk/pinfo_le") == 0)
|
||||||
if (status == B_OK)
|
attrStatus = node.GetNextAttrName(attrName);
|
||||||
status = entry.SetTo(entryPath.Path(), true);
|
|
||||||
if (status != B_OK)
|
if (presetFileName == true && size == 0 && attrStatus == B_ENTRY_NOT_FOUND) {
|
||||||
break;
|
// Tracker's drag-and-drop routine created an empty entry for us to fill in.
|
||||||
|
// Go ahead and write to the existing entry.
|
||||||
|
} else {
|
||||||
|
BDirectory directory(path.Path());
|
||||||
|
if (_CheckBookmarkExists(directory, fileName, url) == true) {
|
||||||
|
// The existing entry is a bookmark with the same URL. No further action needed.
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
// Find a unique name for the bookmark.
|
||||||
|
int32 tries = 1;
|
||||||
|
while (entry.Exists()) {
|
||||||
|
fileName << " " << tries++;
|
||||||
|
entryPath = path;
|
||||||
|
status = entryPath.Append(fileName);
|
||||||
|
if (status == B_OK)
|
||||||
|
status = entry.SetTo(entryPath.Path(), true);
|
||||||
|
if (status != B_OK)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BFile bookmarkFile;
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
status = bookmarkFile.SetTo(&entry,
|
status = bookmarkFile.SetTo(&entry,
|
||||||
B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY);
|
B_CREATE_FILE | B_ERASE_FILE | B_WRITE_ONLY);
|
||||||
@ -1979,33 +2006,33 @@ BrowserWindow::_CreateBookmark()
|
|||||||
if (status == B_OK)
|
if (status == B_OK)
|
||||||
status = bookmarkFile.WriteAttrString("META:url", &url);
|
status = bookmarkFile.WriteAttrString("META:url", &url);
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
BString title = webView->MainFrameTitle();
|
|
||||||
bookmarkFile.WriteAttrString("META:title", &title);
|
bookmarkFile.WriteAttrString("META:title", &title);
|
||||||
}
|
}
|
||||||
|
|
||||||
BNodeInfo nodeInfo(&bookmarkFile);
|
BNodeInfo nodeInfo(&bookmarkFile);
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
status = nodeInfo.SetType("application/x-vnd.Be-bookmark");
|
status = nodeInfo.SetType("application/x-vnd.Be-bookmark");
|
||||||
|
// Replace the standard Be-bookmark file icons with the argument icons,
|
||||||
|
// if any were provided.
|
||||||
if (status == B_OK) {
|
if (status == B_OK) {
|
||||||
PageUserData* userData = static_cast<PageUserData*>(
|
status_t ret = B_OK;
|
||||||
webView->GetUserData());
|
if (miniIcon != NULL) {
|
||||||
if (userData != NULL && userData->PageIcon() != NULL) {
|
ret = nodeInfo.SetIcon(miniIcon, B_MINI_ICON);
|
||||||
BBitmap miniIcon(BRect(0, 0, 15, 15), B_BITMAP_NO_SERVER_LINK,
|
|
||||||
B_CMAP8);
|
|
||||||
status_t ret = miniIcon.ImportBits(userData->PageIcon());
|
|
||||||
if (ret == B_OK)
|
|
||||||
ret = nodeInfo.SetIcon(&miniIcon, B_MINI_ICON);
|
|
||||||
if (ret != B_OK) {
|
if (ret != B_OK) {
|
||||||
fprintf(stderr, "Failed to store mini icon for bookmark: "
|
fprintf(stderr, "Failed to store mini icon for bookmark: "
|
||||||
"%s\n", strerror(ret));
|
"%s\n", strerror(ret));
|
||||||
}
|
}
|
||||||
BBitmap largeIcon(BRect(0, 0, 31, 31), B_BITMAP_NO_SERVER_LINK,
|
}
|
||||||
|
if (largeIcon != NULL && ret == B_OK)
|
||||||
|
ret = nodeInfo.SetIcon(largeIcon, B_LARGE_ICON);
|
||||||
|
else if (largeIcon == NULL && miniIcon != NULL && ret == B_OK) {
|
||||||
|
// If largeIcon is not available but miniIcon is, use a magnified miniIcon instead.
|
||||||
|
BBitmap substituteLargeIcon(BRect(0, 0, 31, 31), B_BITMAP_NO_SERVER_LINK,
|
||||||
B_CMAP8);
|
B_CMAP8);
|
||||||
// TODO: Store 32x32 favicon which is often provided by sites.
|
const uint8* src = (const uint8*)miniIcon->Bits();
|
||||||
const uint8* src = (const uint8*)miniIcon.Bits();
|
uint32 srcBPR = miniIcon->BytesPerRow();
|
||||||
uint32 srcBPR = miniIcon.BytesPerRow();
|
uint8* dst = (uint8*)substituteLargeIcon.Bits();
|
||||||
uint8* dst = (uint8*)largeIcon.Bits();
|
uint32 dstBPR = substituteLargeIcon.BytesPerRow();
|
||||||
uint32 dstBPR = largeIcon.BytesPerRow();
|
|
||||||
for (uint32 y = 0; y < 16; y++) {
|
for (uint32 y = 0; y < 16; y++) {
|
||||||
const uint8* s = src;
|
const uint8* s = src;
|
||||||
uint8* d = dst;
|
uint8* d = dst;
|
||||||
@ -2022,12 +2049,12 @@ BrowserWindow::_CreateBookmark()
|
|||||||
dst += dstBPR;
|
dst += dstBPR;
|
||||||
src += srcBPR;
|
src += srcBPR;
|
||||||
}
|
}
|
||||||
if (ret == B_OK)
|
ret = nodeInfo.SetIcon(&substituteLargeIcon, B_LARGE_ICON);
|
||||||
ret = nodeInfo.SetIcon(&largeIcon, B_LARGE_ICON);
|
} else
|
||||||
if (ret != B_OK) {
|
ret = B_OK;
|
||||||
fprintf(stderr, "Failed to store large icon for bookmark: "
|
if (ret != B_OK) {
|
||||||
"%s\n", strerror(ret));
|
fprintf(stderr, "Failed to store large icon for bookmark: "
|
||||||
}
|
"%s\n", strerror(ret));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2047,6 +2074,83 @@ BrowserWindow::_CreateBookmark()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BrowserWindow::_CreateBookmark(BMessage* message)
|
||||||
|
{
|
||||||
|
entry_ref ref;
|
||||||
|
BMessage originatorData;
|
||||||
|
const char* url;
|
||||||
|
const char* title;
|
||||||
|
bool validData = (message->FindRef("directory", &ref) == B_OK
|
||||||
|
&& message->FindMessage("be:originator-data", &originatorData) == B_OK
|
||||||
|
&& originatorData.FindString("url", &url) == B_OK
|
||||||
|
&& originatorData.FindString("title", &title) == B_OK);
|
||||||
|
|
||||||
|
// Optional data
|
||||||
|
const char* fileName;
|
||||||
|
if (message->FindString("name", &fileName) != B_OK) {
|
||||||
|
// This string is only present if the message originated from Tracker (drag and drop).
|
||||||
|
fileName = "";
|
||||||
|
}
|
||||||
|
const BBitmap* miniIcon = NULL;
|
||||||
|
const BBitmap* largeIcon = NULL;
|
||||||
|
originatorData.FindData("miniIcon", B_COLOR_8_BIT_TYPE,
|
||||||
|
reinterpret_cast<const void**>(&miniIcon), NULL);
|
||||||
|
originatorData.FindData("largeIcon", B_COLOR_8_BIT_TYPE,
|
||||||
|
reinterpret_cast<const void**>(&miniIcon), NULL);
|
||||||
|
|
||||||
|
if (validData == true) {
|
||||||
|
_CreateBookmark(BPath(&ref), BString(fileName), BString(title), BString(url),
|
||||||
|
miniIcon, largeIcon);
|
||||||
|
} else {
|
||||||
|
BString message(B_TRANSLATE("There was an error setting up "
|
||||||
|
"the bookmark."));
|
||||||
|
BAlert* alert = new BAlert(B_TRANSLATE("Bookmark error"),
|
||||||
|
message.String(), B_TRANSLATE("OK"), NULL, NULL,
|
||||||
|
B_WIDTH_AS_USUAL, B_STOP_ALERT);
|
||||||
|
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
|
||||||
|
alert->Go();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
BrowserWindow::_CreateBookmark()
|
||||||
|
{
|
||||||
|
BString fileName;
|
||||||
|
// A name will be derived from the title later.
|
||||||
|
BString title(CurrentWebView()->MainFrameTitle());
|
||||||
|
BString url(CurrentWebView()->MainFrameURL());
|
||||||
|
BPath path;
|
||||||
|
status_t status = _BookmarkPath(path);
|
||||||
|
|
||||||
|
BBitmap* miniIcon = NULL;
|
||||||
|
BBitmap* largeIcon = NULL;
|
||||||
|
PageUserData* userData = static_cast<PageUserData*>(CurrentWebView()->GetUserData());
|
||||||
|
if (userData != NULL && userData->PageIcon() != NULL) {
|
||||||
|
miniIcon = new BBitmap(BRect(0, 0, 15, 15), B_BITMAP_NO_SERVER_LINK, B_CMAP8);
|
||||||
|
miniIcon->ImportBits(userData->PageIcon());
|
||||||
|
// TODO: retrieve the large icon too, once PageUserData can provide it.
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == B_OK)
|
||||||
|
_CreateBookmark(path, fileName, title, url, miniIcon, largeIcon);
|
||||||
|
else {
|
||||||
|
BString message(B_TRANSLATE_COMMENT("There was an error retrieving "
|
||||||
|
"the bookmark folder.\n\nError: %error", "Don't translate the "
|
||||||
|
"variable %error"));
|
||||||
|
message.ReplaceFirst("%error", strerror(status));
|
||||||
|
BAlert* alert = new BAlert(B_TRANSLATE("Bookmark error"),
|
||||||
|
message.String(), B_TRANSLATE("OK"), NULL, NULL,
|
||||||
|
B_WIDTH_AS_USUAL, B_STOP_ALERT);
|
||||||
|
alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
|
||||||
|
alert->Go();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
BrowserWindow::_ShowBookmarks()
|
BrowserWindow::_ShowBookmarks()
|
||||||
{
|
{
|
||||||
@ -2078,25 +2182,15 @@ bool BrowserWindow::_CheckBookmarkExists(BDirectory& directory,
|
|||||||
{
|
{
|
||||||
BEntry entry;
|
BEntry entry;
|
||||||
while (directory.GetNextEntry(&entry) == B_OK) {
|
while (directory.GetNextEntry(&entry) == B_OK) {
|
||||||
if (entry.IsDirectory()) {
|
char entryName[B_FILE_NAME_LENGTH];
|
||||||
BDirectory subBirectory(&entry);
|
if (entry.GetName(entryName) != B_OK || bookmarkName != entryName)
|
||||||
// At least preserve the entry file handle when recursing into
|
continue;
|
||||||
// sub-folders... eventually we will run out, though, with very
|
BString storedURL;
|
||||||
// deep hierarchy.
|
BFile file(&entry, B_READ_ONLY);
|
||||||
entry.Unset();
|
if (_ReadURLAttr(file, storedURL)) {
|
||||||
if (_CheckBookmarkExists(subBirectory, bookmarkName, url))
|
// Just bail if the bookmark already exists
|
||||||
|
if (storedURL == url)
|
||||||
return true;
|
return true;
|
||||||
} else {
|
|
||||||
char entryName[B_FILE_NAME_LENGTH];
|
|
||||||
if (entry.GetName(entryName) != B_OK || bookmarkName != entryName)
|
|
||||||
continue;
|
|
||||||
BString storedURL;
|
|
||||||
BFile file(&entry, B_READ_ONLY);
|
|
||||||
if (_ReadURLAttr(file, storedURL)) {
|
|
||||||
// Just bail if the bookmark already exists
|
|
||||||
if (storedURL == url)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -179,6 +179,11 @@ private:
|
|||||||
void _TabChanged(int32 index);
|
void _TabChanged(int32 index);
|
||||||
|
|
||||||
status_t _BookmarkPath(BPath& path) const;
|
status_t _BookmarkPath(BPath& path) const;
|
||||||
|
void _CreateBookmark(const BPath& path,
|
||||||
|
BString fileName, const BString& title,
|
||||||
|
const BString& url, const BBitmap* miniIcon,
|
||||||
|
const BBitmap* largeIcon);
|
||||||
|
void _CreateBookmark(BMessage* message);
|
||||||
void _CreateBookmark();
|
void _CreateBookmark();
|
||||||
void _ShowBookmarks();
|
void _ShowBookmarks();
|
||||||
bool _CheckBookmarkExists(BDirectory& directory,
|
bool _CheckBookmarkExists(BDirectory& directory,
|
||||||
|
@ -25,10 +25,13 @@
|
|||||||
|
|
||||||
#include "BaseURL.h"
|
#include "BaseURL.h"
|
||||||
#include "BitmapButton.h"
|
#include "BitmapButton.h"
|
||||||
|
#include "BrowserWindow.h"
|
||||||
#include "BrowsingHistory.h"
|
#include "BrowsingHistory.h"
|
||||||
#include "IconButton.h"
|
#include "IconButton.h"
|
||||||
#include "IconUtils.h"
|
#include "IconUtils.h"
|
||||||
#include "TextViewCompleter.h"
|
#include "TextViewCompleter.h"
|
||||||
|
#include "WebView.h"
|
||||||
|
#include "WebWindow.h"
|
||||||
|
|
||||||
|
|
||||||
#undef B_TRANSLATION_CONTEXT
|
#undef B_TRANSLATION_CONTEXT
|
||||||
@ -499,7 +502,9 @@ public:
|
|||||||
PageIconView()
|
PageIconView()
|
||||||
:
|
:
|
||||||
BView("page icon view", B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
|
BView("page icon view", B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE),
|
||||||
fIcon(NULL)
|
fIcon(NULL),
|
||||||
|
fClickPoint(-1, 0),
|
||||||
|
fPageIconSet(false)
|
||||||
{
|
{
|
||||||
SetDrawingMode(B_OP_ALPHA);
|
SetDrawingMode(B_OP_ALPHA);
|
||||||
SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
|
SetBlendingMode(B_PIXEL_ALPHA, B_ALPHA_OVERLAY);
|
||||||
@ -539,21 +544,97 @@ public:
|
|||||||
return MinSize();
|
return MinSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MouseDown(BPoint where)
|
||||||
|
{
|
||||||
|
int32 buttons;
|
||||||
|
if (Window()->CurrentMessage()->FindInt32("buttons", &buttons) == B_OK) {
|
||||||
|
if ((buttons & B_PRIMARY_MOUSE_BUTTON) != 0) {
|
||||||
|
// Memorize click point for dragging
|
||||||
|
fClickPoint = where;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MouseUp(BPoint where)
|
||||||
|
{
|
||||||
|
fClickPoint.x = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void MouseMoved(BPoint where, uint32 code, const BMessage* dragMessage)
|
||||||
|
{
|
||||||
|
if (dragMessage != NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (fClickPoint.x >= 0
|
||||||
|
&& (fabs(where.x - fClickPoint.x) > 4 || fabs(where.y - fClickPoint.y) > 4)) {
|
||||||
|
// Start dragging
|
||||||
|
BPoint offset = fClickPoint - Frame().LeftTop();
|
||||||
|
|
||||||
|
const char* url = static_cast<URLInputGroup*>(Parent())->Text();
|
||||||
|
const char* title =
|
||||||
|
static_cast<BWebWindow*>(Window())->CurrentWebView()->MainFrameTitle();
|
||||||
|
|
||||||
|
// Validate the file name to be set for the clipping if user drags to Tracker.
|
||||||
|
BString fileName(title);
|
||||||
|
if (fileName.Length() == 0) {
|
||||||
|
fileName = url;
|
||||||
|
int32 leafPos = fileName.FindLast('/');
|
||||||
|
if (leafPos >= 0)
|
||||||
|
fileName.Remove(0, leafPos + 1);
|
||||||
|
}
|
||||||
|
fileName.ReplaceAll('/', '-');
|
||||||
|
fileName.Truncate(B_FILE_NAME_LENGTH - 1);
|
||||||
|
|
||||||
|
BBitmap miniIcon(BRect(0, 0, 15, 15), B_BITMAP_NO_SERVER_LINK,
|
||||||
|
B_CMAP8);
|
||||||
|
miniIcon.ImportBits(fIcon);
|
||||||
|
// TODO: obtain and send the large icon in addition to the mini icon.
|
||||||
|
// Currently PageUserData does not provide a function that returns this.
|
||||||
|
|
||||||
|
BMessage drag(B_SIMPLE_DATA);
|
||||||
|
drag.AddInt32("be:actions", B_COPY_TARGET);
|
||||||
|
drag.AddString("be:clip_name", fileName.String());
|
||||||
|
drag.AddString("be:filetypes", "application/x-vnd.Be-bookmark");
|
||||||
|
// Support the "Passing Data via File" protocol
|
||||||
|
drag.AddString("be:types", B_FILE_MIME_TYPE);
|
||||||
|
BMessage data(B_SIMPLE_DATA);
|
||||||
|
data.AddString("url", url);
|
||||||
|
data.AddString("title", title);
|
||||||
|
// The title may differ from the validated filename
|
||||||
|
if (fPageIconSet == true) {
|
||||||
|
// Don't bother sending the placeholder web icon, if that is all we have.
|
||||||
|
data.AddData("miniIcon", B_COLOR_8_BIT_TYPE, &miniIcon, sizeof(miniIcon));
|
||||||
|
}
|
||||||
|
drag.AddMessage("be:originator-data", &data);
|
||||||
|
|
||||||
|
BBitmap* iconClone = new BBitmap(fIcon);
|
||||||
|
// Needed because DragMessage will delete the bitmap when it's done.
|
||||||
|
|
||||||
|
DragMessage(&drag, iconClone, B_OP_ALPHA, offset);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
void SetIcon(const BBitmap* icon)
|
void SetIcon(const BBitmap* icon)
|
||||||
{
|
{
|
||||||
delete fIcon;
|
delete fIcon;
|
||||||
if (icon)
|
if (icon) {
|
||||||
fIcon = new BBitmap(icon);
|
fIcon = new BBitmap(icon);
|
||||||
else {
|
fPageIconSet = true;
|
||||||
|
} else {
|
||||||
fIcon = new BBitmap(BRect(0, 0, 15, 15), B_RGB32);
|
fIcon = new BBitmap(BRect(0, 0, 15, 15), B_RGB32);
|
||||||
BIconUtils::GetVectorIcon(kPlaceholderIcon,
|
BIconUtils::GetVectorIcon(kPlaceholderIcon,
|
||||||
sizeof(kPlaceholderIcon), fIcon);
|
sizeof(kPlaceholderIcon), fIcon);
|
||||||
|
fPageIconSet = false;
|
||||||
}
|
}
|
||||||
Invalidate();
|
Invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
BBitmap* fIcon;
|
BBitmap* fIcon;
|
||||||
|
BPoint fClickPoint;
|
||||||
|
bool fPageIconSet;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user