#include "Navigator.h"
#include <ControlLook.h>
#include <TextControl.h>
#include <Window.h>
#include "Bitmaps.h"
#include "Commands.h"
#include "FSUtils.h"
#include "Tracker.h"
namespace BPrivate {
static const int32 kMaxHistory = 32;
}
BNavigator::BNavigator(const Model* model)
:
BToolBar(),
fBackHistory(8),
fForwHistory(8)
{
model->GetPath(&fPath);
fLocation = new BTextControl("Location", "", "",
new BMessage(kNavigatorCommandLocation));
fLocation->SetDivider(0);
GroupLayout()->SetInsets(0.0f, 0.0f, B_USE_HALF_ITEM_INSETS, 1.0f);
SetFlags(Flags() | B_WILL_DRAW);
}
BNavigator::~BNavigator()
{
}
void
BNavigator::AttachedToWindow()
{
BToolBar::AttachedToWindow();
const BRect iconRect(BPoint(0, 0),
be_control_look->ComposeIconSize(20));
BBitmap* bmpBack = new BBitmap(iconRect, B_RGBA32);
GetTrackerResources()->GetIconResource(R_ResBackNav, B_MINI_ICON, bmpBack);
AddAction(kNavigatorCommandBackward, this, bmpBack);
SetActionEnabled(kNavigatorCommandBackward, false);
delete bmpBack;
BBitmap* bmpForw = new BBitmap(iconRect, B_RGBA32);
GetTrackerResources()->GetIconResource(R_ResForwNav, B_MINI_ICON, bmpForw);
AddAction(kNavigatorCommandForward, this, bmpForw);
SetActionEnabled(kNavigatorCommandForward, false);
delete bmpForw;
BBitmap* bmpUp = new BBitmap(iconRect, B_RGBA32);
GetTrackerResources()->GetIconResource(R_ResUpNav, B_MINI_ICON, bmpUp);
AddAction(kNavigatorCommandUp, this, bmpUp);
SetActionEnabled(kNavigatorCommandUp, false);
delete bmpUp;
AddView(fLocation);
fLocation->SetTarget(this);
}
void
BNavigator::AllAttached()
{
UpdateLocation(0, kActionSet);
}
void
BNavigator::Draw(BRect updateRect)
{
BRect rect(Bounds());
rgb_color base = LowColor();
uint32 flags = 0;
be_control_look->DrawBorder(this, rect, updateRect, base,
B_PLAIN_BORDER, flags, BControlLook::B_BOTTOM_BORDER);
_inherited::Draw(rect & updateRect);
}
void
BNavigator::MessageReceived(BMessage* message)
{
switch (message->what) {
case kNavigatorCommandBackward:
GoBackward((modifiers() & B_OPTION_KEY) == B_OPTION_KEY);
break;
case kNavigatorCommandForward:
GoForward((modifiers() & B_OPTION_KEY) == B_OPTION_KEY);
break;
case kNavigatorCommandUp:
GoUp((modifiers() & B_OPTION_KEY) == B_OPTION_KEY);
break;
case kNavigatorCommandLocation:
GoTo();
break;
case kNavigatorCommandSetFocus:
fLocation->MakeFocus();
break;
default:
{
entry_ref ref;
if (message->FindRef("refs", &ref) == B_OK) {
BMessage message(kSwitchDirectory);
BEntry entry(&ref, true);
if (!entry.IsDirectory()) {
entry.GetRef(&ref);
BPath path(&ref);
path.GetParent(&path);
get_ref_for_path(path.Path(), &ref);
}
message.AddRef("refs", &ref);
message.AddInt32("action", kActionSet);
Window()->PostMessage(&message);
}
}
}
}
void
BNavigator::GoBackward(bool option)
{
int32 itemCount = fBackHistory.CountItems();
if (itemCount >= 2 && fBackHistory.ItemAt(itemCount - 2)) {
BEntry entry;
if (entry.SetTo(fBackHistory.ItemAt(itemCount - 2)->Path()) == B_OK)
SendNavigationMessage(kActionBackward, &entry, option);
}
}
void
BNavigator::GoForward(bool option)
{
if (fForwHistory.CountItems() >= 1) {
BEntry entry;
if (entry.SetTo(fForwHistory.LastItem()->Path()) == B_OK)
SendNavigationMessage(kActionForward, &entry, option);
}
}
void
BNavigator::GoUp(bool option)
{
BEntry entry;
if (entry.SetTo(fPath.Path()) == B_OK) {
BEntry parentEntry;
if (entry.GetParent(&parentEntry) == B_OK) {
SendNavigationMessage(kActionUp, &parentEntry, option);
}
}
}
void
BNavigator::SendNavigationMessage(NavigationAction action, BEntry* entry,
bool option)
{
entry_ref ref;
if (entry->GetRef(&ref) == B_OK) {
BMessage message;
message.AddRef("refs", &ref);
message.AddInt32("action", action);
const node_ref* nodeRef;
if (Window() && Window()->TargetModel())
nodeRef = Window()->TargetModel()->NodeRef();
else
nodeRef = NULL;
if (option) {
message.what = B_REFS_RECEIVED;
if (nodeRef != NULL) {
message.AddData("nodeRefToSelect", B_RAW_TYPE, nodeRef,
sizeof(node_ref));
}
be_app->PostMessage(&message);
} else {
message.what = kSwitchDirectory;
Window()->PostMessage(&message);
UnlockLooper();
if (nodeRef != NULL) {
TTracker* tracker = dynamic_cast<TTracker*>(be_app);
if (tracker != NULL)
tracker->SelectChildInParentSoon(&ref, nodeRef);
}
LockLooper();
}
}
}
void
BNavigator::GoTo()
{
BString pathname = fLocation->Text();
if (pathname.Compare("") == 0)
pathname = "/";
BEntry entry;
entry_ref ref;
if (entry.SetTo(pathname.String()) == B_OK
&& entry.GetRef(&ref) == B_OK) {
BMessage message(kSwitchDirectory);
message.AddRef("refs", &ref);
message.AddInt32("action", kActionLocation);
Window()->PostMessage(&message);
} else {
BPath path;
if (Window() && Window()->TargetModel()) {
Window()->TargetModel()->GetPath(&path);
fLocation->SetText(path.Path());
}
}
}
void
BNavigator::UpdateLocation(const Model* newmodel, int32 action)
{
if (newmodel)
newmodel->GetPath(&fPath);
switch (action) {
case kActionBackward:
fForwHistory.AddItem(fBackHistory.RemoveItemAt(
fBackHistory.CountItems() - 1));
break;
case kActionForward:
fBackHistory.AddItem(fForwHistory.RemoveItemAt(
fForwHistory.CountItems() - 1));
break;
case kActionUpdatePath:
break;
default:
fForwHistory.MakeEmpty();
fBackHistory.AddItem(new BPath(fPath));
while (fBackHistory.CountItems() > kMaxHistory)
fBackHistory.RemoveItem(fBackHistory.FirstItem(), true);
break;
}
BEntry entry;
if (entry.SetTo(fPath.Path()) == B_OK) {
BEntry parentEntry;
bool enable = entry.GetParent(&parentEntry) == B_OK;
SetActionEnabled(kNavigatorCommandUp, enable);
}
SetActionEnabled(kNavigatorCommandForward, fForwHistory.CountItems() > 0);
SetActionEnabled(kNavigatorCommandBackward, fBackHistory.CountItems() > 1);
if (action != kActionLocation)
fLocation->SetText(fPath.Path());
}