#include "RecentItems.h"
#include <Roster.h>
#include "Attributes.h"
#include "IconMenuItem.h"
#include "Model.h"
#include "NavMenu.h"
#include "PoseView.h"
#include "SlowMenu.h"
#include "Tracker.h"
#include "Utilities.h"
class RecentItemsMenu : public BSlowMenu {
public:
RecentItemsMenu(const char* title, BMessage* openMessage,
BHandler* itemTarget, int32 maxItems);
virtual ~RecentItemsMenu();
virtual bool StartBuildingItemList();
virtual bool AddNextItem();
virtual void DoneBuildingItemList() {}
virtual void ClearMenuBuildingState();
protected:
virtual const BMessage* FileMessage()
{
return fTargetMesage;
}
virtual const BMessage* ContainerMessage()
{
return fTargetMesage;
}
BRecentItemsList* fIterator;
BMessage* fTargetMesage;
BHandler* fItemTarget;
int32 fCount;
int32 fSanityCount;
int32 fMaxCount;
};
class RecentFilesMenu : public RecentItemsMenu {
public:
RecentFilesMenu(const char* title, BMessage* openFileMessage,
BMessage* openFolderMessage, BHandler* target,
int32 maxItems, bool navMenuFolders, const char* ofType,
const char* openedByAppSig);
RecentFilesMenu(const char* title, BMessage* openFileMessage,
BMessage* openFolderMessage, BHandler* target,
int32 maxItems, bool navMenuFolders, const char* ofTypeList[],
int32 ofTypeListCount, const char* openedByAppSig);
virtual ~RecentFilesMenu();
protected:
virtual const BMessage* ContainerMessage()
{ return openFolderMessage; }
private:
BMessage* openFolderMessage;
};
class RecentFoldersMenu : public RecentItemsMenu {
public:
RecentFoldersMenu(const char* title, BMessage* openMessage,
BHandler* target, int32 maxItems, bool navMenuFolders,
const char* openedByAppSig);
};
class RecentAppsMenu : public RecentItemsMenu {
public:
RecentAppsMenu(const char* title, BMessage* openMessage,
BHandler* target, int32 maxItems);
};
RecentItemsMenu::RecentItemsMenu(const char* title, BMessage* openMessage,
BHandler* itemTarget, int32 maxItems)
:
BSlowMenu(title),
fIterator(NULL),
fTargetMesage(openMessage),
fItemTarget(itemTarget),
fCount(-1),
fSanityCount(-1),
fMaxCount(maxItems)
{
}
RecentItemsMenu::~RecentItemsMenu()
{
delete fIterator;
delete fTargetMesage;
}
bool
RecentItemsMenu::AddNextItem()
{
BMenuItem* item = fIterator->GetNextMenuItem(FileMessage(),
ContainerMessage(), fItemTarget);
if (item != NULL) {
AddItem(item);
fCount++;
}
fSanityCount++;
return fCount < fMaxCount - 1 && (fSanityCount < fMaxCount + 20);
}
bool
RecentItemsMenu::StartBuildingItemList()
{
int32 itemCount = CountItems();
while (itemCount--)
delete RemoveItem((int32)0);
fCount = 0;
fSanityCount = 0;
fIterator->Rewind();
return true;
}
void
RecentItemsMenu::ClearMenuBuildingState()
{
fMenuBuilt = false;
fIterator->Rewind();
}
RecentFilesMenu::RecentFilesMenu(const char* title, BMessage* openFileMessage,
BMessage* openFolderMessage, BHandler* target, int32 maxItems,
bool navMenuFolders, const char* ofType, const char* openedByAppSig)
:
RecentItemsMenu(title, openFileMessage, target, maxItems),
openFolderMessage(openFolderMessage)
{
fIterator = new BRecentFilesList(maxItems + 10, navMenuFolders,
ofType, openedByAppSig);
}
RecentFilesMenu::RecentFilesMenu(const char* title, BMessage* openFileMessage,
BMessage* openFolderMessage, BHandler* target, int32 maxItems,
bool navMenuFolders, const char* ofTypeList[], int32 ofTypeListCount,
const char* openedByAppSig)
:
RecentItemsMenu(title, openFileMessage, target, maxItems),
openFolderMessage(openFolderMessage)
{
fIterator = new BRecentFilesList(maxItems + 10, navMenuFolders,
ofTypeList, ofTypeListCount, openedByAppSig);
}
RecentFilesMenu::~RecentFilesMenu()
{
delete openFolderMessage;
}
RecentFoldersMenu::RecentFoldersMenu(const char* title, BMessage* openMessage,
BHandler* target, int32 maxItems, bool navMenuFolders,
const char* openedByAppSig)
:
RecentItemsMenu(title, openMessage, target, maxItems)
{
fIterator = new BRecentFoldersList(maxItems + 10, navMenuFolders,
openedByAppSig);
}
RecentAppsMenu::RecentAppsMenu(const char* title, BMessage* openMessage,
BHandler* target, int32 maxItems)
:
RecentItemsMenu(title, openMessage, target, maxItems)
{
fIterator = new BRecentAppsList(maxItems);
}
BRecentItemsList::BRecentItemsList(int32 maxItems, bool navMenuFolders)
:
fMaxItems(maxItems),
fNavMenuFolders(navMenuFolders)
{
InitIconPreloader();
Rewind();
}
void
BRecentItemsList::Rewind()
{
fIndex = 0;
fItems.MakeEmpty();
}
BMenuItem*
BRecentItemsList::GetNextMenuItem(const BMessage* fileOpenInvokeMessage,
const BMessage* containerOpenInvokeMessage, BHandler* target,
entry_ref* currentItemRef)
{
entry_ref ref;
if (GetNextRef(&ref) != B_OK)
return NULL;
Model model(&ref, true);
if (model.InitCheck() != B_OK)
return NULL;
bool container = false;
if (model.IsSymLink()) {
Model* newResolvedModel = NULL;
Model* result = model.LinkTo();
if (result == NULL) {
newResolvedModel = new Model(model.EntryRef(), true, true);
if (newResolvedModel->InitCheck() != B_OK) {
delete newResolvedModel;
result = NULL;
} else
result = newResolvedModel;
} else {
BModelOpener opener(result);
PoseInfo poseInfo;
BNode* resultNode = result->Node();
if (resultNode != NULL) {
resultNode->ReadAttr(kAttrPoseInfo, B_RAW_TYPE, 0,
&poseInfo, sizeof(poseInfo));
}
result->CloseNode();
ref = *result->EntryRef();
container = result->IsContainer();
}
model.SetLinkTo(result);
} else {
ref = *model.EntryRef();
container = model.IsContainer();
}
if (currentItemRef != NULL)
*currentItemRef = ref;
BMessage* message;
if (container && containerOpenInvokeMessage)
message = new BMessage(*containerOpenInvokeMessage);
else if (!container && fileOpenInvokeMessage)
message = new BMessage(*fileOpenInvokeMessage);
else
message = new BMessage(B_REFS_RECEIVED);
message->AddRef("refs", model.EntryRef());
menu_info info;
get_menu_info(&info);
BFont menuFont;
menuFont.SetFamilyAndStyle(info.f_family, info.f_style);
menuFont.SetSize(info.font_size);
BString truncatedString(model.Name());
menuFont.TruncateString(&truncatedString, B_TRUNCATE_END, BNavMenu::GetMaxMenuWidth());
ModelMenuItem* item = NULL;
if (!container || !fNavMenuFolders)
item = new ModelMenuItem(&model, truncatedString.String(), message);
else {
BNavMenu* menu = new BNavMenu(truncatedString.String(), message->what,
target, 0);
menu->SetNavDir(&ref);
item = new ModelMenuItem(&model, menu);
item->SetMessage(message);
}
if (item != NULL && target != NULL)
item->SetTarget(target);
return item;
}
status_t
BRecentItemsList::GetNextRef(entry_ref* result)
{
return fItems.FindRef("refs", fIndex++, result);
}
BRecentFilesList::BRecentFilesList(int32 maxItems, bool navMenuFolders,
const char* ofType, const char* openedByAppSig)
:
BRecentItemsList(maxItems, navMenuFolders),
fType(ofType),
fTypes(NULL),
fTypeCount(0),
fAppSig(openedByAppSig)
{
}
BRecentFilesList::BRecentFilesList(int32 maxItems, bool navMenuFolders,
const char* ofTypeList[], int32 ofTypeListCount,
const char* openedByAppSig)
:
BRecentItemsList(maxItems, navMenuFolders),
fType(NULL),
fTypes(NULL),
fTypeCount(ofTypeListCount),
fAppSig(openedByAppSig)
{
if (fTypeCount > 0) {
fTypes = new char *[ofTypeListCount];
for (int32 index = 0; index < ofTypeListCount; index++)
fTypes[index] = strdup(ofTypeList[index]);
}
}
BRecentFilesList::~BRecentFilesList()
{
if (fTypeCount > 0) {
for (int32 index = 0; index < fTypeCount; index++)
free(fTypes[index]);
delete[] fTypes;
}
}
status_t
BRecentFilesList::GetNextRef(entry_ref* ref)
{
if (fIndex == 0) {
if (fTypes != NULL) {
BRoster().GetRecentDocuments(&fItems, fMaxItems,
const_cast<const char**>(fTypes),
fTypeCount, fAppSig.Length() ? fAppSig.String() : NULL);
} else {
BRoster().GetRecentDocuments(&fItems, fMaxItems,
fType.Length() ? fType.String() : NULL,
fAppSig.Length() ? fAppSig.String() : NULL);
}
}
return BRecentItemsList::GetNextRef(ref);
}
BMenu*
BRecentFilesList::NewFileListMenu(const char* title,
BMessage* openFileMessage, BMessage* openFolderMessage,
BHandler* target, int32 maxItems, bool navMenuFolders, const char* ofType,
const char* openedByAppSig)
{
return new RecentFilesMenu(title, openFileMessage,
openFolderMessage, target, maxItems, navMenuFolders, ofType,
openedByAppSig);
}
BMenu*
BRecentFilesList::NewFileListMenu(const char* title,
BMessage* openFileMessage, BMessage* openFolderMessage,
BHandler* target, int32 maxItems, bool navMenuFolders,
const char* ofTypeList[], int32 ofTypeListCount,
const char* openedByAppSig)
{
return new RecentFilesMenu(title, openFileMessage,
openFolderMessage, target, maxItems, navMenuFolders, ofTypeList,
ofTypeListCount, openedByAppSig);
}
BMenu*
BRecentFoldersList::NewFolderListMenu(const char* title,
BMessage* openMessage, BHandler* target, int32 maxItems,
bool navMenuFolders, const char* openedByAppSig)
{
return new RecentFoldersMenu(title, openMessage, target, maxItems,
navMenuFolders, openedByAppSig);
}
BRecentFoldersList::BRecentFoldersList(int32 maxItems, bool navMenuFolders,
const char* openedByAppSig)
:
BRecentItemsList(maxItems, navMenuFolders),
fAppSig(openedByAppSig)
{
}
status_t
BRecentFoldersList::GetNextRef(entry_ref* ref)
{
if (fIndex == 0) {
BRoster().GetRecentFolders(&fItems, fMaxItems,
fAppSig.Length() ? fAppSig.String() : NULL);
}
return BRecentItemsList::GetNextRef(ref);
}
BRecentAppsList::BRecentAppsList(int32 maxItems)
:
BRecentItemsList(maxItems, false)
{
}
status_t
BRecentAppsList::GetNextRef(entry_ref* ref)
{
if (fIndex == 0) {
BRoster().GetRecentApps(&fItems, fMaxItems);
}
return BRecentItemsList::GetNextRef(ref);
}
BMenu*
BRecentAppsList::NewAppListMenu(const char* title, BMessage* openMessage,
BHandler* target, int32 maxItems)
{
return new RecentAppsMenu(title, openMessage, target, maxItems);
}