WebPositive: add a bookmark bar.
* This is a BMenuBar with IconMenuItems. * Uses node monitoring to live-update the bar as bookmarks are modified. * Bookmark folders are BNavMenus and can be browsed. * This needs some improvements, for example handling more bookmarks than the window width allows us to show (with an extra menu like for tabs?) Fixes #10232.
This commit is contained in:
@@ -47,6 +47,7 @@
|
||||
#include <GridLayoutBuilder.h>
|
||||
#include <GroupLayout.h>
|
||||
#include <GroupLayoutBuilder.h>
|
||||
#include <IconMenuItem.h>
|
||||
#include <Keymap.h>
|
||||
#include <LayoutBuilder.h>
|
||||
#include <Locale.h>
|
||||
@@ -55,6 +56,7 @@
|
||||
#include <MenuItem.h>
|
||||
#include <MessageRunner.h>
|
||||
#include <NodeInfo.h>
|
||||
#include <NodeMonitor.h>
|
||||
#include <Path.h>
|
||||
#include <Roster.h>
|
||||
#include <Screen.h>
|
||||
@@ -66,6 +68,7 @@
|
||||
#include <TextControl.h>
|
||||
#include <UnicodeChar.h>
|
||||
|
||||
#include <map>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "AuthenticationPanel.h"
|
||||
@@ -172,6 +175,142 @@ private:
|
||||
};
|
||||
|
||||
|
||||
class BookmarkBar: public BMenuBar {
|
||||
public:
|
||||
BookmarkBar(const char* title, BHandler* target, const entry_ref* navDir)
|
||||
: BMenuBar(title)
|
||||
{
|
||||
BEntry(navDir).GetNodeRef(&fNodeRef);
|
||||
}
|
||||
|
||||
~BookmarkBar()
|
||||
{
|
||||
stop_watching(BMessenger(this));
|
||||
}
|
||||
|
||||
void AttachedToWindow()
|
||||
{
|
||||
BMenuBar::AttachedToWindow();
|
||||
watch_node(&fNodeRef, B_WATCH_DIRECTORY, BMessenger(this));
|
||||
|
||||
// Enumerate initial directory content
|
||||
BDirectory dir(&fNodeRef);
|
||||
BEntry bookmark;
|
||||
while(dir.GetNextEntry(&bookmark) == B_OK) {
|
||||
node_ref ref;
|
||||
bookmark.GetNodeRef(&ref);
|
||||
AddItem(ref.node, &bookmark);
|
||||
}
|
||||
}
|
||||
|
||||
void MessageReceived(BMessage* message)
|
||||
{
|
||||
switch(message->what) {
|
||||
case B_NODE_MONITOR:
|
||||
int32 opcode = message->FindInt32("opcode");
|
||||
ino_t inode = message->FindInt64("node");
|
||||
switch(opcode) {
|
||||
case B_ENTRY_CREATED:
|
||||
{
|
||||
entry_ref ref;
|
||||
const char *name;
|
||||
|
||||
message->FindInt32("device", &ref.device);
|
||||
message->FindInt64("directory", &ref.directory);
|
||||
message->FindString("name", &name);
|
||||
ref.set_name(name);
|
||||
|
||||
BEntry entry(&ref);
|
||||
AddItem(inode, &entry);
|
||||
break;
|
||||
}
|
||||
case B_ENTRY_MOVED:
|
||||
{
|
||||
if (fItemsMap[inode] == NULL)
|
||||
{
|
||||
entry_ref ref;
|
||||
const char *name;
|
||||
|
||||
message->FindInt32("device", &ref.device);
|
||||
message->FindInt64("to directory", &ref.directory);
|
||||
message->FindString("name", &name);
|
||||
ref.set_name(name);
|
||||
|
||||
BEntry entry(&ref);
|
||||
AddItem(inode, &entry);
|
||||
break;
|
||||
} else {
|
||||
// Existing item. Check if it's a rename or a move
|
||||
// to some other folder.
|
||||
ino_t from, to;
|
||||
message->FindInt64("to directory", &to);
|
||||
message->FindInt64("from directory", &from);
|
||||
if (from == to)
|
||||
{
|
||||
const char *name;
|
||||
message->FindString("name", &name);
|
||||
fItemsMap[inode]->SetLabel(name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// fall through: the item was moved from here to
|
||||
// elsewhere, remove it from the bar.
|
||||
}
|
||||
case B_ENTRY_REMOVED:
|
||||
{
|
||||
IconMenuItem* item = fItemsMap[inode];
|
||||
RemoveItem(item);
|
||||
fItemsMap.erase(inode);
|
||||
delete item;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
BMenuBar::MessageReceived(message);
|
||||
}
|
||||
|
||||
private:
|
||||
void AddItem(ino_t inode, BEntry* entry)
|
||||
{
|
||||
char name[B_FILE_NAME_LENGTH];
|
||||
entry->GetName(name);
|
||||
|
||||
// make sure the item doesn't already exists
|
||||
if (fItemsMap[inode] != NULL)
|
||||
return;
|
||||
|
||||
entry_ref ref;
|
||||
entry->GetRef(&ref);
|
||||
|
||||
IconMenuItem* item = NULL;
|
||||
|
||||
if(entry->IsDirectory()) {
|
||||
BNavMenu* menu = new BNavMenu(name, B_REFS_RECEIVED, Window());
|
||||
menu->SetNavDir(&ref);
|
||||
item = new IconMenuItem(menu, NULL,
|
||||
"application/x-vnd.Be-directory", B_MINI_ICON);
|
||||
|
||||
} else {
|
||||
BNode node(entry);
|
||||
BNodeInfo info(&node);
|
||||
|
||||
BMessage* message = new BMessage(B_REFS_RECEIVED);
|
||||
message->AddRef("refs", &ref);
|
||||
item = new IconMenuItem(name, message, &info,
|
||||
B_MINI_ICON);
|
||||
}
|
||||
|
||||
BMenuBar::AddItem(item);
|
||||
fItemsMap[inode] = item;
|
||||
}
|
||||
|
||||
node_ref fNodeRef;
|
||||
std::map<ino_t, IconMenuItem*> fItemsMap;
|
||||
};
|
||||
|
||||
|
||||
class PageUserData : public BWebView::UserData {
|
||||
public:
|
||||
PageUserData(BView* focusedView)
|
||||
@@ -581,6 +720,8 @@ BrowserWindow::BrowserWindow(BRect frame, SettingsMessage* appSettings,
|
||||
#if !INTEGRATE_MENU_INTO_TAB_BAR
|
||||
.Add(menuBarGroup)
|
||||
#endif
|
||||
.Add(new BookmarkBar(B_TRANSLATE("Bookmarks"), this,
|
||||
&bookmarkRef))
|
||||
.Add(fTabManager->TabGroup())
|
||||
.Add(navigationGroup)
|
||||
.Add(fTabManager->ContainerView())
|
||||
|
||||
Reference in New Issue
Block a user