2 * Copyright 2014, Adrien Destugues <pulkomandy@pulkomandy.tk>.
3 * Distributed under the terms of the MIT License.
7 #include "BookmarkBar.h"
11 #include <IconMenuItem.h>
12 #include <Messenger.h>
20 BookmarkBar::BookmarkBar(const char* title
, BHandler
* target
,
21 const entry_ref
* navDir
)
25 SetFlags(Flags() | B_FRAME_EVENTS
);
26 BEntry(navDir
).GetNodeRef(&fNodeRef
);
28 fOverflowMenu
= new BMenu(B_UTF8_ELLIPSIS
);
29 AddItem(fOverflowMenu
);
33 BookmarkBar::~BookmarkBar()
35 stop_watching(BMessenger(this));
40 BookmarkBar::AttachedToWindow()
42 BMenuBar::AttachedToWindow();
43 watch_node(&fNodeRef
, B_WATCH_DIRECTORY
, BMessenger(this));
45 // Enumerate initial directory content
46 BDirectory
dir(&fNodeRef
);
48 while (dir
.GetNextEntry(&bookmark
, true) == B_OK
) {
50 if (bookmark
.GetNodeRef(&ref
) == B_OK
)
51 _AddItem(ref
.node
, &bookmark
);
57 BookmarkBar::MessageReceived(BMessage
* message
)
59 switch (message
->what
) {
62 int32 opcode
= message
->FindInt32("opcode");
63 ino_t inode
= message
->FindInt64("node");
70 message
->FindInt32("device", &ref
.device
);
71 message
->FindInt64("directory", &ref
.directory
);
72 message
->FindString("name", &name
);
75 BEntry
entry(&ref
, true);
76 if (entry
.InitCheck() == B_OK
)
77 _AddItem(inode
, &entry
);
85 message
->FindInt32("device", &ref
.device
);
86 message
->FindInt64("to directory", &ref
.directory
);
87 message
->FindString("name", &name
);
90 if (fItemsMap
[inode
] == NULL
) {
91 BEntry
entry(&ref
, true);
92 _AddItem(inode
, &entry
);
95 // Existing item. Check if it's a rename or a move
96 // to some other folder.
98 message
->FindInt64("to directory", &to
);
99 message
->FindInt64("from directory", &from
);
102 if (message
->FindString("name", &name
) == B_OK
)
103 fItemsMap
[inode
]->SetLabel(name
);
105 BMessage
* itemMessage
= new BMessage(
107 itemMessage
->AddRef("refs", &ref
);
108 fItemsMap
[inode
]->SetMessage(itemMessage
);
114 // fall through: the item was moved from here to
115 // elsewhere, remove it from the bar.
117 case B_ENTRY_REMOVED
:
119 IconMenuItem
* item
= fItemsMap
[inode
];
121 fOverflowMenu
->RemoveItem(item
);
122 fItemsMap
.erase(inode
);
130 BMenuBar::MessageReceived(message
);
135 BookmarkBar::FrameResized(float width
, float height
)
137 int32 count
= CountItems() - 1;
138 // We don't touch the "more" menu
140 float rightmost
= 0.f
;
142 BMenuItem
* item
= ItemAt(i
);
143 BRect frame
= item
->Frame();
144 if (frame
.right
> width
- 32)
146 rightmost
= frame
.right
;
151 // See if we can move some items from the "more" menu in the remaining
153 BMenuItem
* extraItem
= fOverflowMenu
->ItemAt(0);
154 while (extraItem
!= NULL
) {
155 BRect frame
= extraItem
->Frame();
156 if (frame
.Width() + rightmost
> width
- 32)
159 AddItem(fOverflowMenu
->RemoveItem((int32
)0), i
);
162 extraItem
= fOverflowMenu
->ItemAt(0);
165 // Remove any overflowing item and move them to the "more" menu.
166 for (int j
= i
; j
< count
; j
++)
167 fOverflowMenu
->AddItem(RemoveItem(j
));
173 BookmarkBar::MinSize()
175 BSize size
= BMenuBar::MinSize();
177 // We only need space to show the "more" button.
180 // We need enough vertical space to show bookmark icons.
181 if (size
.height
< 20)
188 // #pragma mark - private methods
192 BookmarkBar::_AddItem(ino_t inode
, BEntry
* entry
)
194 char name
[B_FILE_NAME_LENGTH
];
195 entry
->GetName(name
);
197 // make sure the item doesn't already exists
198 if (fItemsMap
[inode
] != NULL
)
204 IconMenuItem
* item
= NULL
;
206 if (entry
->IsDirectory()) {
207 BNavMenu
* menu
= new BNavMenu(name
, B_REFS_RECEIVED
, Window());
208 menu
->SetNavDir(&ref
);
209 item
= new IconMenuItem(menu
, NULL
,
210 "application/x-vnd.Be-directory", B_MINI_ICON
);
214 BNodeInfo
info(&node
);
216 BMessage
* message
= new BMessage(B_REFS_RECEIVED
);
217 message
->AddRef("refs", &ref
);
218 item
= new IconMenuItem(name
, message
, &info
, B_MINI_ICON
);
221 int32 count
= CountItems();
223 BMenuBar::AddItem(item
, count
- 1);
224 fItemsMap
[inode
] = item
;
226 // Move the item to the "more" menu if it overflows.
228 FrameResized(r
.Width(), r
.Height());