#include <Beep.h>
#include <File.h>
#include <Resources.h>
#include <StorageKit.h>
#include <SupportKit.h>
#include <AppKit.h>
#include <iostream.h>
#include "InfoWindow.h"
struct IDItem : public BStringItem
{
IDItem(const char *name, int32 i);
int32 id;
};
struct match_info
{
match_info(image_id i) { id = i; found = false; };
image_id id;
bool found;
};
bool match_id(BListItem *item, void *data)
{
match_info *mi = (match_info *) (data);
IDItem *my = dynamic_cast<IDItem*>(item);
if (my->id == (mi)->id)
{
(mi)->found = true;
return true;
}
return false;
}
IDItem :: IDItem(const char *name, int32 i)
: BStringItem(name)
{
id = i;
};
InfoWindow :: InfoWindow(void)
: IEWindow("InfoWindow"),
fTickToken( BMessenger(this), new BMessage(CMD_TICK), 500000 ),
fImportLoc(10,15)
{
Lock();
CreateViews();
Unlock();
}
InfoWindow::~InfoWindow(void)
{
SetPrefs();
if (fPrefs != NULL) delete fPrefs;
}
bool InfoWindow :: QuitRequested()
{
long c = be_app->CountWindows();
if (c == 1)
{
be_app->PostMessage(B_QUIT_REQUESTED);
}
return true;
}
void InfoWindow::MessageReceived(BMessage *msg)
{
switch(msg->what)
{
case CMD_UPDATE_CONTAINER_ITEM:
{
BMenu *theMenu =(BMenu *)(fMenuField -> Menu());
BMenuItem *theItem = theMenu -> FindItem(IE_POPUPMENU_TARGETPOPUP_XCONTAINER_WINDOW);
theItem -> SetMarked(true);
PostMessage(IE_POPUPMENU_TARGETPOPUP_XCONTAINER_WINDOW);
}
break;
case CMD_TICK:
{
UpdateLists(false);
break;
}
case IE_INFOWINDOW_DELETEBUTTON:
{
int32 sel = fReplicantList->CurrentSelection();
IDItem *item = dynamic_cast<IDItem*>(fReplicantList->ItemAt(sel));
ASSERT(sel >= 0);
ASSERT(item);
DeleteReplicant(item->id);
}
break;
case IE_INFOWINDOW_COPYBUTTON:
{
BAlert *alert = new BAlert("",
"Warning, not all replicants are importable. Importing a "
"replicant can crash the Container Demo application. Are you "
"willing to give it a try?", "Cancel", "Import", NULL,
B_WIDTH_AS_USUAL, B_OFFSET_SPACING, B_WARNING_ALERT);
BInvoker *inv = new BInvoker(new BMessage(CMD_IMPORT_REPLICANT),this);
alert->Go(inv);
}
break;
case CMD_IMPORT_REPLICANT:
{
int32 r = msg->FindInt32("which");
if (r == 1)
{
int32 sel = fReplicantList->CurrentSelection();
IDItem *item = dynamic_cast<IDItem*>(fReplicantList->ItemAt(sel));
ASSERT(sel >= 0);
ASSERT(item);
ImportReplicant(item->id);
}
}
break;
case IE_INFOWINDOW_REPLICANTLIST_SELECTION:
{
bool enabled;
enabled = (fReplicantList->CurrentSelection() >= 0);
fDeleteRep->SetEnabled(enabled);
fCopyRep -> SetEnabled(enabled);
}
break;
case IE_INFOWINDOW_REPLICANTLIST_INVOCATION:
break;
case IE_INFOWINDOW_LIBRARYLIST_SELECTION:
{
bool enabled;
enabled = (fLibraryList->CurrentSelection() >= 0);
fUnloadLib->SetEnabled(enabled);
}
break;
case IE_INFOWINDOW_LIBRARYLIST_INVOCATION:
break;
case IE_INFOWINDOW_UNLOADBUTTON:
{
BAlert *alert = new BAlert("",
"Warning, unloading a library that is still in use is pretty bad. "
"Are you sure you want to unload this library?",
"Cancel", "Unload", NULL,
B_WIDTH_AS_USUAL, B_OFFSET_SPACING, B_WARNING_ALERT);
BInvoker *inv = new BInvoker(new BMessage(CMD_UNLOAD_LIBRARY),this);
alert->Go(inv);
}
break;
case CMD_UNLOAD_LIBRARY:
{
int32 r = msg->FindInt32("which");
if (r == 1)
{
int32 sel = fLibraryList->CurrentSelection();
IDItem *item = dynamic_cast<IDItem*>(fLibraryList->ItemAt(sel));
ASSERT(sel >= 0);
ASSERT(item);
unload_add_on(item->id);
}
break;
}
case IE_POPUPMENU_TARGETPOPUP_XCONTAINER_WINDOW:
case IE_POPUPMENU_TARGETPOPUP_DESKBAR:
case IE_POPUPMENU_TARGETPOPUP_DESKTOP_WINDOW:
{
fTarget = MessengerForTarget(msg->what);
UpdateLists(true);
}
break;
case IE_INFOWINDOW_MAINBAR_FILE_NEW:
break;
case IE_INFOWINDOW_MAINBAR_FILE_OPEN___:
break;
case IE_INFOWINDOW_MAINBAR_FILE_SAVE:
break;
case IE_INFOWINDOW_MAINBAR_FILE_SAVE_AS___:
break;
case IE_INFOWINDOW_MAINBAR_FILE_ABOUT___:
PostMessage(B_ABOUT_REQUESTED);
break;
case IE_INFOWINDOW_MAINBAR_FILE_QUIT:
PostMessage(B_QUIT_REQUESTED);
break;
case IE_INFOWINDOW_MAINBAR_EDIT_UNDO:
break;
case IE_INFOWINDOW_MAINBAR_EDIT_CUT:
break;
case IE_INFOWINDOW_MAINBAR_EDIT_COPY:
break;
case IE_INFOWINDOW_MAINBAR_EDIT_PASTE:
break;
case B_ABOUT_REQUESTED:
{
BAlert *alert = new BAlert("", "XShelfInspector (H.Reh, dr.hartmut.reh@gmx.de) " "\n" "\n"
"Based upon ShelfInspector from Be Inc." "\n"
"The GUI was created with InterfaceElements (Attila Mezei)" "\n"
"Please read the ***Be Sample Code License*** " "\n"
,"OK");
alert -> Go(NULL);
}
break;
default:
inherited::MessageReceived(msg);
break;
}
}
void InfoWindow :: EmptyLists()
{
fReplicantList -> MakeEmpty();
fLibraryList -> MakeEmpty();
}
void InfoWindow::UpdateLists(bool make_empty)
{
bool deleted_something = false;
if (!fTarget.IsValid())
{
EmptyLists();
PostMessage(IE_INFOWINDOW_REPLICANTLIST_SELECTION);
PostMessage(IE_INFOWINDOW_LIBRARYLIST_SELECTION);
return;
}
if (make_empty)
{
EmptyLists();
deleted_something = true;
}
I'm not worried about the allgorithms used below to maintain the 2 lists.
That isn't the point of this sample app.
*/
image_info info;
if (!make_empty)
{
IDItem *item;
int32 i = fLibraryList->CountItems();
while ((item = dynamic_cast<IDItem*>(fLibraryList->ItemAt(--i))) != NULL)
{
image_id id = (image_id) item->id;
if (get_image_info(id, &info) != B_OK)
{
fLibraryList->RemoveItem(item);
delete item;
deleted_something = true;
}
}
}
team_id team = fTarget.Team();
int32 cookie = 0;
while (get_next_image_info(team, &cookie, &info) == B_OK)
{
match_info mi(info.id);
fLibraryList->DoForEach(match_id, &mi);
if (!mi.found)
{
fLibraryList->AddItem(new IDItem(info.name, info.id));
}
}
if (!make_empty)
{
IDItem *item;
int32 i = fReplicantList->CountItems();
while ((item = dynamic_cast<IDItem*>(fReplicantList->ItemAt(--i))) != NULL)
{
int32 uid = item->id;
if (IsReplicantLoaded(uid) == false)
{
fReplicantList->RemoveItem(item);
delete item;
deleted_something = true;
}
}
}
int32 index = 0;
int32 uid;
while ((uid = GetReplicantAt(index++)) >= B_OK)
{
match_info mi(uid);
fReplicantList->DoForEach(match_id, &mi);
if (mi.found)
{
continue;
}
BMessage rep_info;
if (GetReplicantName(uid, &rep_info) != B_OK)
{
continue;
}
const char *name;
if (rep_info.FindString("result", &name) == B_OK)
{
fReplicantList->AddItem(new IDItem(name, uid));
}
}
if (deleted_something)
{
PostMessage(IE_INFOWINDOW_REPLICANTLIST_SELECTION);
PostMessage(IE_INFOWINDOW_LIBRARYLIST_SELECTION);
}
}
status_t InfoWindow :: GetReplicantName(int32 uid, BMessage *reply) const
{
We send a message to the target shelf, asking it for the Name of the
replicant with the given unique id.
*/
BMessage request(B_GET_PROPERTY);
BMessage uid_specifier(B_ID_SPECIFIER);
status_t err;
status_t e;
request.AddSpecifier("Name");
uid_specifier.AddInt32("id", uid);
uid_specifier.AddString("property", "Replicant");
request.AddSpecifier(&uid_specifier);
if ((err = fTarget.SendMessage(&request, reply)) != B_OK)
return err;
if (((err = reply->FindInt32("error", &e)) != B_OK) || (e != B_OK))
return err ? err : e;
return B_OK;
}
bool InfoWindow :: IsReplicantLoaded(int32 uid) const
{
determine if the specified replicant (the unique ID of the replicant)
still exists in the target container/shelf. If we can get the name then the
replicant still exists.
*/
BMessage reply;
status_t err = GetReplicantName(uid, &reply);
return (err == B_OK);
}
int32 InfoWindow::GetReplicantAt(int32 index) const
{
So here we want to get the Unique ID of the replicant at the given index
in the target Shelf.
*/
BMessage request(B_GET_PROPERTY);
BMessage reply;
status_t err;
request.AddSpecifier("ID");
request.AddSpecifier("Replicant", index);
if ((err = fTarget.SendMessage(&request, &reply)) != B_OK)
return err;
int32 uid;
if ((err = reply.FindInt32("result", &uid)) != B_OK)
return err;
return uid;
}
BMessenger InfoWindow :: MessengerForTarget(type_code w) const
{
This function determines the BMessenger to the various Shelf objects
that this app can talk with.
*/
BMessage request(B_GET_PROPERTY);
BMessenger to;
BMessenger result;
request.AddSpecifier("Messenger");
request.AddSpecifier("Shelf");
switch (w)
{
case IE_POPUPMENU_TARGETPOPUP_DESKBAR:
{
request.AddSpecifier("View", "Status");
request.AddSpecifier("Window", "Deskbar");
to = BMessenger("application/x-vnd.Be-TSKB", -1);
break;
}
case IE_POPUPMENU_TARGETPOPUP_DESKTOP_WINDOW:
{
request.AddSpecifier("View", "PoseView");
request.AddSpecifier("Window", "/boot/home/Desktop");
to = BMessenger("application/x-vnd.Be-TRAK", -1);
break;
}
case IE_POPUPMENU_TARGETPOPUP_XCONTAINER_WINDOW:
{
request.AddSpecifier("View", "ContainerView");
request.AddSpecifier("Window", (int32) 0);
to = BMessenger(XCONTAINER_APP, -1);
break;
}
}
BMessage reply;
if (to.SendMessage(&request, &reply) == B_OK)
{
reply.FindMessenger("result", &result);
}
return result;
}
status_t InfoWindow :: DeleteReplicant(int32 uid)
{
BMessage request(B_DELETE_PROPERTY);
BMessage uid_specifier(B_ID_SPECIFIER);
BMessage reply;
status_t err;
status_t e;
uid_specifier.AddInt32("id", uid);
uid_specifier.AddString("property", "Replicant");
request.AddSpecifier(&uid_specifier);
if ((err = fTarget.SendMessage(&request, &reply)) != B_OK)
return err;
if ((err = reply.FindInt32("error", &e)) != B_OK)
return err;
return e;
}
status_t InfoWindow :: ImportReplicant(int32 uid)
{
BMessage request(B_GET_PROPERTY);
BMessage uid_specifier(B_ID_SPECIFIER);
BMessage reply;
status_t err;
status_t e;
uid_specifier.AddInt32("id", uid);
uid_specifier.AddString("property", "Replicant");
request.AddSpecifier(&uid_specifier);
if ((err = fTarget.SendMessage(&request, &reply)) != B_OK)
return err;
if (((err = reply.FindInt32("error", &e)) != B_OK) || (e != B_OK))
return err;
BMessage data;
reply.FindMessage("result", &data);
BMessenger mess = MessengerForTarget(IE_POPUPMENU_TARGETPOPUP_XCONTAINER_WINDOW);
BMessage msg(B_CREATE_PROPERTY);
msg.AddMessage("data", &data);
msg.AddPoint("location", fImportLoc);
fImportLoc.y += 40;
return mess.SendMessage(&msg, &reply);
}
void InfoWindow::MenusBeginning()
{
KeyMenuBar()->FindItem(IE_INFOWINDOW_MAINBAR_FILE_NEW)->SetEnabled(false);
KeyMenuBar()->FindItem(IE_INFOWINDOW_MAINBAR_FILE_OPEN___)->SetEnabled(false);
KeyMenuBar()->FindItem(IE_INFOWINDOW_MAINBAR_FILE_SAVE)->SetEnabled(false);
KeyMenuBar()->FindItem(IE_INFOWINDOW_MAINBAR_FILE_SAVE_AS___)->SetEnabled(false);
KeyMenuBar()->FindItem(IE_INFOWINDOW_MAINBAR_FILE_ABOUT___)->SetEnabled(true);
KeyMenuBar()->FindItem(IE_INFOWINDOW_MAINBAR_FILE_QUIT)->SetEnabled(true);
KeyMenuBar()->FindItem(IE_INFOWINDOW_MAINBAR_EDIT_UNDO)->SetEnabled(false);
KeyMenuBar()->FindItem(IE_INFOWINDOW_MAINBAR_EDIT_CUT)->SetEnabled(false);
KeyMenuBar()->FindItem(IE_INFOWINDOW_MAINBAR_EDIT_COPY)->SetEnabled(false);
KeyMenuBar()->FindItem(IE_INFOWINDOW_MAINBAR_EDIT_PASTE)->SetEnabled(false);
}
BMessage *InfoWindow :: ReadMessageFromResource(const char *resName)
{
app_info ai;
BFile file;
BResources res;
size_t res_size;
const void* res_addr;
BMessage* archive = new BMessage;
if( (be_app->GetAppInfo(&ai) != B_OK)
||(file.SetTo(&ai.ref,B_READ_ONLY) != B_OK)
||(res.SetTo(&file) != B_OK)
||((res_addr = res.LoadResource('ARCV',resName,&res_size)) == NULL)
||(archive -> Unflatten((const char*)res_addr) != B_OK) )
{
delete archive;
return NULL;
}
return archive;
}
void InfoWindow:: CreateViews()
{
BMessage *archive = ReadMessageFromResource("PopUpMenu");
if (archive)
{
fMenuField = new BMenuField(archive);
delete archive;
}
fMainBox = (BBox *)FindView("MainBox");
fMainBox->SetLabel(fMenuField);
fReplicantList = (BListView *) FindView("ReplicantList");
fLibraryList = (BListView *) FindView("LibraryList");
fDeleteRep = (BButton *) FindView("DeleteButton");
fCopyRep = (BButton *) FindView("CopyButton");
fUnloadLib = (BButton *) FindView("UnloadButton");
BScrollView *libScrollView = (BScrollView *)FindView("LibraryScroll");
BScrollBar *horLibScrollBar = libScrollView -> ScrollBar(B_HORIZONTAL);
horLibScrollBar -> SetRange(0, 400);
horLibScrollBar -> SetProportion(0.4);
BScrollView *repScrollView = (BScrollView *)FindView("ReplicantScroll");
BScrollBar *horRepScrollBar = repScrollView -> ScrollBar(B_HORIZONTAL);
horRepScrollBar -> SetRange(0, 400);
horRepScrollBar -> SetProportion(0.4);
}
void InfoWindow :: GetPrefs()
{
status_t err;
BRect windFrame;
int32 targetShelf;
fPrefs = new TPreferences ("XShelfInspector/preferences");
if (fPrefs -> InitCheck() != B_OK)
{
windFrame = Frame();
fPrefs -> SetRect ("WindowFrame", windFrame );
targetShelf = IE_POPUPMENU_TARGETPOPUP_XCONTAINER_WINDOW;
fPrefs -> SetInt32 ("TargetShelf", targetShelf );
}
err = (fPrefs -> FindRect ("WindowFrame", &windFrame) );
if (err == B_OK)
{
ResizeTo(windFrame.Width(), windFrame.Height() );
MoveTo(windFrame.left, windFrame.top);
}
err = (fPrefs -> FindInt32 ("TargetShelf", &targetShelf ) );
if (err == B_OK)
{
BMenu *theMenu =(BMenu *)(fMenuField -> Menu());
BMenuItem *theItem = theMenu -> FindItem(targetShelf);
theItem -> SetMarked(true);
PostMessage(targetShelf);
}
}
void InfoWindow :: SetPrefs()
{
fPrefs -> SetRect ("WindowFrame", Frame() );
BMenu *theMenu =(BMenu *)(fMenuField -> Menu());
BMenuItem *theItem = theMenu -> FindMarked();
int32 targetShelf = theItem -> Command();
fPrefs -> SetInt32("TargetShelf", targetShelf);
}