// InfoWindow.cpp // Generated by Interface Elements (Window v2.3) on Feb 23 2004 // This is a user written class and will not be overwritten. #include #include #include #include #include #include #include #include "InfoWindow.h" // A couple helpers classes and functions. 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(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 ), // send message periodically fImportLoc(10,15) // position of imported replicant { Lock(); CreateViews(); Unlock(); } InfoWindow::~InfoWindow(void) { SetPrefs(); if (fPrefs != NULL) delete fPrefs; // now prefs are saved } bool InfoWindow :: QuitRequested() { long c = be_app->CountWindows(); if (c == 1) { be_app->PostMessage(B_QUIT_REQUESTED); } return true; } // Handling of user interface and other events 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: // 'DeleteButton' is pressed... { int32 sel = fReplicantList->CurrentSelection(); IDItem *item = dynamic_cast(fReplicantList->ItemAt(sel)); ASSERT(sel >= 0); ASSERT(item); DeleteReplicant(item->id); } break; case IE_INFOWINDOW_COPYBUTTON: // 'CopyButton' is pressed... { 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: { // This message was posted by the Alert above. If 'which' is 1 then // the user pressed the Import button. Otherwise they pressed Cancel. int32 r = msg->FindInt32("which"); if (r == 1) { int32 sel = fReplicantList->CurrentSelection(); IDItem *item = dynamic_cast(fReplicantList->ItemAt(sel)); ASSERT(sel >= 0); ASSERT(item); ImportReplicant(item->id); } } break; case IE_INFOWINDOW_REPLICANTLIST_SELECTION: // list item is selected in 'ReplicantList' { bool enabled; enabled = (fReplicantList->CurrentSelection() >= 0); fDeleteRep->SetEnabled(enabled); fCopyRep -> SetEnabled(enabled); } break; case IE_INFOWINDOW_REPLICANTLIST_INVOCATION: // list item is invoked in 'ReplicantList' break; case IE_INFOWINDOW_LIBRARYLIST_SELECTION: // list item is selected in 'LibraryList' { bool enabled; enabled = (fLibraryList->CurrentSelection() >= 0); fUnloadLib->SetEnabled(enabled); } break; case IE_INFOWINDOW_LIBRARYLIST_INVOCATION: // list item is invoked in 'LibraryList' break; case IE_INFOWINDOW_UNLOADBUTTON: // 'UnloadButton' is pressed... { 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: { // This message was posted by the Alert above. If 'which' is 1 then // the user pressed the Import button. Otherwise they pressed Cancel. int32 r = msg->FindInt32("which"); if (r == 1) { int32 sel = fLibraryList->CurrentSelection(); IDItem *item = dynamic_cast(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: // "New" is selected from menu… break; case IE_INFOWINDOW_MAINBAR_FILE_OPEN___: // "Open…" is selected from menu… break; case IE_INFOWINDOW_MAINBAR_FILE_SAVE: // "Save" is selected from menu… break; case IE_INFOWINDOW_MAINBAR_FILE_SAVE_AS___: // "Save As…" is selected from menu… break; case IE_INFOWINDOW_MAINBAR_FILE_ABOUT___: // "About…" is selected from menu… PostMessage(B_ABOUT_REQUESTED); break; case IE_INFOWINDOW_MAINBAR_FILE_QUIT: // "Quit" is selected from menu… PostMessage(B_QUIT_REQUESTED); break; case IE_INFOWINDOW_MAINBAR_EDIT_UNDO: // "Undo" is selected from menu… break; case IE_INFOWINDOW_MAINBAR_EDIT_CUT: // "Cut" is selected from menu… break; case IE_INFOWINDOW_MAINBAR_EDIT_COPY: // "Copy" is selected from menu… break; case IE_INFOWINDOW_MAINBAR_EDIT_PASTE: // "Paste" is selected from menu… 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) { // walk through the current list of images and remove any that are // no longer loaded IDItem *item; int32 i = fLibraryList->CountItems(); while ((item = dynamic_cast(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; } } } // get all the images for the 'team' of the target. If the image isn't in the // list then add 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)); } } // Now it's time to deal with the replicant list if (!make_empty) { // walk through the current list of replicants and remove any that are // no longer loaded IDItem *item; int32 i = fReplicantList->CountItems(); while ((item = dynamic_cast(fReplicantList->ItemAt(--i))) != NULL) { int32 uid = item->id; if (IsReplicantLoaded(uid) == false) { fReplicantList->RemoveItem(item); delete item; deleted_something = true; } } } // Now get all the replicants from the shelf and make sure that they are in // the list int32 index = 0; int32 uid; while ((uid = GetReplicantAt(index++)) >= B_OK) { // if this uid is already in the list then skip it 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); // specifying via ID status_t err; status_t e; request.AddSpecifier("Name"); // ask for the Name of the replicant // IDs are specified using code like the following 3 lines: 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); // We're getting the ID property BMessage reply; status_t err; request.AddSpecifier("ID"); // want the ID request.AddSpecifier("Replicant", index); // of the index'th replicant 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: { // The Desktop is owned by Tracker and the Shelf is in the // View "PoseView" in Window "Desktop" 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: { // In the COntainer Demo app the View "MainView" in the only window // is the Shelf. request.AddSpecifier("View", "ContainerView"); // Hier werden Replikanten abgelegt request.AddSpecifier("Window", (int32) 0); to = BMessenger(XCONTAINER_APP, -1); // This demo app isn't worried about the Container app going away // (quitting) unexpectedly. break; } } BMessage reply; if (to.SendMessage(&request, &reply) == B_OK) { //reply.PrintToStream(); reply.FindMessenger("result", &result); } return result; } status_t InfoWindow :: DeleteReplicant(int32 uid) { // delete the given replicant from the current target shelf BMessage request(B_DELETE_PROPERTY); // Delete BMessage uid_specifier(B_ID_SPECIFIER); // specifying via ID BMessage reply; status_t err; status_t e; // IDs are specified using code like the following 3 lines: 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) { // Import the given replicant from the current target shelf // That is get a copy and recreate it in the "Container" window of // this app. BMessage request(B_GET_PROPERTY); // Get will return the archive msg BMessage uid_specifier(B_ID_SPECIFIER); // specifying via ID BMessage reply; status_t err; status_t e; // IDs are specified using code like the following 3 lines: 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; // OK, let's get the archive message BMessage data; reply.FindMessage("result", &data); // Now send this to the container window. If someone closed it then the // Send will fail. Oh well. BMessenger mess = MessengerForTarget(IE_POPUPMENU_TARGETPOPUP_XCONTAINER_WINDOW); BMessage msg(B_CREATE_PROPERTY); msg.AddMessage("data", &data); // As this is a Demo I'm not going to worry about some fancy layout // algorithm. Just keep placing new replicants going down the window msg.AddPoint("location", fImportLoc); fImportLoc.y += 40; return mess.SendMessage(&msg, &reply); } // Update the menu items before they appear on screen void InfoWindow::MenusBeginning() { // Complete the SetEnabled argument or do anything with the source below... KeyMenuBar()->FindItem(IE_INFOWINDOW_MAINBAR_FILE_NEW)->SetEnabled(false); // "New" KeyMenuBar()->FindItem(IE_INFOWINDOW_MAINBAR_FILE_OPEN___)->SetEnabled(false); // "Open…" KeyMenuBar()->FindItem(IE_INFOWINDOW_MAINBAR_FILE_SAVE)->SetEnabled(false); // "Save" KeyMenuBar()->FindItem(IE_INFOWINDOW_MAINBAR_FILE_SAVE_AS___)->SetEnabled(false); // "Save As…" KeyMenuBar()->FindItem(IE_INFOWINDOW_MAINBAR_FILE_ABOUT___)->SetEnabled(true); // "About…" KeyMenuBar()->FindItem(IE_INFOWINDOW_MAINBAR_FILE_QUIT)->SetEnabled(true); // "Quit" KeyMenuBar()->FindItem(IE_INFOWINDOW_MAINBAR_EDIT_UNDO)->SetEnabled(false); // "Undo" KeyMenuBar()->FindItem(IE_INFOWINDOW_MAINBAR_EDIT_CUT)->SetEnabled(false); // "Cut" KeyMenuBar()->FindItem(IE_INFOWINDOW_MAINBAR_EDIT_COPY)->SetEnabled(false); // "Copy" KeyMenuBar()->FindItem(IE_INFOWINDOW_MAINBAR_EDIT_PASTE)->SetEnabled(false); // "Paste" } BMessage *InfoWindow :: ReadMessageFromResource(const char *resName) { // Hier wird aus der Resource die Message gelesen 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) ) // Resource muss 'ARCV' - Typ sein -> in IE einstellen // Resource of type 'ARCV' { delete archive; return NULL; } return archive; } void InfoWindow:: CreateViews() { BMessage *archive = ReadMessageFromResource("PopUpMenu"); // Menu Feld from Resource if (archive) { fMenuField = new BMenuField(archive); delete archive; } fMainBox = (BBox *)FindView("MainBox"); // Pointer to MainBox fMainBox->SetLabel(fMenuField); // Replace Label 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"); // Name des Prefs-Files if (fPrefs -> InitCheck() != B_OK) // falls keine Prefs -> erzeugen { windFrame = Frame(); // Window Frame aus Resource ermitteln fPrefs -> SetRect ("WindowFrame", windFrame ); targetShelf = IE_POPUPMENU_TARGETPOPUP_XCONTAINER_WINDOW; // XContainerWindow fPrefs -> SetInt32 ("TargetShelf", targetShelf ); } err = (fPrefs -> FindRect ("WindowFrame", &windFrame) ); if (err == B_OK) { ResizeTo(windFrame.Width(), windFrame.Height() ); // Fensterposition und Größe MoveTo(windFrame.left, windFrame.top); // aus Preferences } err = (fPrefs -> FindInt32 ("TargetShelf", &targetShelf ) ); if (err == B_OK) { BMenu *theMenu =(BMenu *)(fMenuField -> Menu()); BMenuItem *theItem = theMenu -> FindItem(targetShelf); theItem -> SetMarked(true); PostMessage(targetShelf); // 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); }