/* * Copyright 2003-2010, Haiku, Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: * Fernando Francisco de Oliveira * Michael Wilber * Michael Pfeiffer * Ryan Leavengood */ #include "ShowImageApp.h" #include #include #include #include #include #include #include #include #include "ShowImageConstants.h" #include "ShowImageWindow.h" #include "ToolBarIcons.h" const char* kApplicationSignature = "application/x-vnd.Haiku-ShowImage"; const int32 kWindowsToIgnore = 1; // ignore the always open file panel ShowImageApp::ShowImageApp() : BApplication(kApplicationSignature), fOpenPanel(new BFilePanel(B_OPEN_PANEL)), fPulseStarted(false), fLastWindowFrame(BRect(30, 30, 430, 330)) { B_TRANSLATE_MARK_SYSTEM_NAME_VOID("ShowImage"); _UpdateLastWindowFrame(); // BBitmap can be created after there is a BApplication instance. init_tool_bar_icons(); } ShowImageApp::~ShowImageApp() { // BBitmap must be deleted while there is still a BApplication instance. uninit_tool_bar_icons(); } void ShowImageApp::ArgvReceived(int32 argc, char **argv) { BMessage message; bool hasRefs = false; // get current working directory const char* cwd; if (CurrentMessage() == NULL || CurrentMessage()->FindString("cwd", &cwd) != B_OK) cwd = ""; for (int32 i = 1; i < argc; i++) { BPath path; if (argv[i][0] == '/') { // absolute path path.SetTo(argv[i]); } else { // relative path path.SetTo(cwd); path.Append(argv[i]); } entry_ref ref; status_t err = get_ref_for_path(path.Path(), &ref); if (err == B_OK) { message.AddRef("refs", &ref); hasRefs = true; } } if (hasRefs) RefsReceived(&message); } void ShowImageApp::ReadyToRun() { if (CountWindows() == kWindowsToIgnore) fOpenPanel->Show(); else { // If image windows are already open // (paths supplied on the command line) // start checking the number of open windows _StartPulse(); } be_clipboard->StartWatching(be_app_messenger); // tell the clipboard to notify this app when its contents change } void ShowImageApp::MessageReceived(BMessage* message) { switch (message->what) { case MSG_FILE_OPEN: fOpenPanel->Show(); break; case B_CANCEL: // File open panel was closed, // start checking count of open windows _StartPulse(); break; case B_CLIPBOARD_CHANGED: _CheckClipboard(); break; case MSG_WINDOW_HAS_QUIT: // Make sure that new windows open with the location/size of the // last closed window. _UpdateLastWindowFrame(); break; default: BApplication::MessageReceived(message); break; } } void ShowImageApp::Pulse() { // Bug: The BFilePanel is automatically closed if the volume that // is displayed is unmounted. if (!IsLaunching() && CountWindows() <= kWindowsToIgnore) { // If the application is not launching and // all windows are closed except for the file open panel, // quit the application PostMessage(B_QUIT_REQUESTED); } } void ShowImageApp::RefsReceived(BMessage* message) { // If a tracker window opened me, get a messenger from it. BMessenger trackerMessenger; if (message->HasMessenger("TrackerViewToken")) message->FindMessenger("TrackerViewToken", &trackerMessenger); entry_ref ref; for (int32 i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) _Open(ref, trackerMessenger); } bool ShowImageApp::QuitRequested() { // Give the windows a chance to prompt the user if there are changes bool result = BApplication::QuitRequested(); if (result) { be_clipboard->StopWatching(be_app_messenger); // tell clipboard we don't want anymore notification } DefaultCache().Stop(); return result; } void ShowImageApp::_StartPulse() { if (!fPulseStarted) { // Tell the app to begin checking // for the number of open windows fPulseStarted = true; SetPulseRate(250000); // Set pulse to every 1/4 second } } void ShowImageApp::_Open(const entry_ref& ref, const BMessenger& trackerMessenger) { fLastWindowFrame.OffsetBy(20, 20); if (!BScreen(B_MAIN_SCREEN_ID).Frame().Contains(fLastWindowFrame)) fLastWindowFrame.OffsetTo(50, 50); new ShowImageWindow(fLastWindowFrame, ref, trackerMessenger); } void ShowImageApp::_BroadcastToWindows(BMessage* message) { const int32 count = CountWindows(); for (int32 i = 0; i < count; i++) { // BMessenger checks for us if BWindow is still a valid object BMessenger messenger(WindowAt(i)); messenger.SendMessage(message); } } void ShowImageApp::_CheckClipboard() { // Determines if the contents of the clipboard contain // data that is useful to this application. // After checking the clipboard, a message is sent to // all windows indicating that the clipboard has changed // and whether or not the clipboard contains useful data. bool dataAvailable = false; if (be_clipboard->Lock()) { BMessage* clip = be_clipboard->Data(); if (clip != NULL) { dataAvailable = clip->HasMessage("image/bitmap") || clip->HasMessage("image/x-be-bitmap"); } be_clipboard->Unlock(); } BMessage msg(B_CLIPBOARD_CHANGED); msg.AddBool("data_available", dataAvailable); _BroadcastToWindows(&msg); } void ShowImageApp::_UpdateLastWindowFrame() { fLastWindowFrame = fSettings.GetRect("WindowFrame", fLastWindowFrame); // Compensate the offset which we always add to new windows. fLastWindowFrame.OffsetBy(-20, -20); } // #pragma mark - int main(int, char**) { ShowImageApp app; app.Run(); return 0; }