1/* 2 * Copyright 2003-2010, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Fernando Francisco de Oliveira 7 * Michael Wilber 8 * Michael Pfeiffer 9 * Ryan Leavengood 10 */ 11 12 13#include "ShowImageApp.h" 14 15#include <stdio.h> 16 17#include <Catalog.h> 18#include <Clipboard.h> 19#include <FilePanel.h> 20#include <Locale.h> 21#include <Path.h> 22#include <Screen.h> 23#include <String.h> 24 25#include "ShowImageConstants.h" 26#include "ShowImageWindow.h" 27#include "ToolBarIcons.h" 28 29 30const char* kApplicationSignature = "application/x-vnd.Haiku-ShowImage"; 31const int32 kWindowsToIgnore = 1; 32 // ignore the always open file panel 33 34 35ShowImageApp::ShowImageApp() 36 : 37 BApplication(kApplicationSignature), 38 fOpenPanel(new BFilePanel(B_OPEN_PANEL)), 39 fPulseStarted(false), 40 fLastWindowFrame(BRect(30, 30, 430, 330)) 41{ 42 B_TRANSLATE_MARK_SYSTEM_NAME_VOID("ShowImage"); 43 _UpdateLastWindowFrame(); 44 // BBitmap can be created after there is a BApplication instance. 45 init_tool_bar_icons(); 46} 47 48 49ShowImageApp::~ShowImageApp() 50{ 51 // BBitmap must be deleted while there is still a BApplication instance. 52 uninit_tool_bar_icons(); 53} 54 55 56void 57ShowImageApp::ArgvReceived(int32 argc, char **argv) 58{ 59 BMessage message; 60 bool hasRefs = false; 61 62 // get current working directory 63 const char* cwd; 64 if (CurrentMessage() == NULL 65 || CurrentMessage()->FindString("cwd", &cwd) != B_OK) 66 cwd = ""; 67 68 for (int32 i = 1; i < argc; i++) { 69 BPath path; 70 if (argv[i][0] == '/') { 71 // absolute path 72 path.SetTo(argv[i]); 73 } else { 74 // relative path 75 path.SetTo(cwd); 76 path.Append(argv[i]); 77 } 78 79 entry_ref ref; 80 status_t err = get_ref_for_path(path.Path(), &ref); 81 if (err == B_OK) { 82 message.AddRef("refs", &ref); 83 hasRefs = true; 84 } 85 } 86 87 if (hasRefs) 88 RefsReceived(&message); 89} 90 91 92void 93ShowImageApp::ReadyToRun() 94{ 95 if (CountWindows() == kWindowsToIgnore) 96 fOpenPanel->Show(); 97 else { 98 // If image windows are already open 99 // (paths supplied on the command line) 100 // start checking the number of open windows 101 _StartPulse(); 102 } 103 104 be_clipboard->StartWatching(be_app_messenger); 105 // tell the clipboard to notify this app when its contents change 106} 107 108 109void 110ShowImageApp::MessageReceived(BMessage* message) 111{ 112 switch (message->what) { 113 case MSG_FILE_OPEN: 114 fOpenPanel->Show(); 115 break; 116 117 case B_CANCEL: 118 // File open panel was closed, 119 // start checking count of open windows 120 _StartPulse(); 121 break; 122 123 case B_CLIPBOARD_CHANGED: 124 _CheckClipboard(); 125 break; 126 127 case MSG_WINDOW_HAS_QUIT: 128 // Make sure that new windows open with the location/size of the 129 // last closed window. 130 _UpdateLastWindowFrame(); 131 break; 132 133 default: 134 BApplication::MessageReceived(message); 135 break; 136 } 137} 138 139 140void 141ShowImageApp::Pulse() 142{ 143 // Bug: The BFilePanel is automatically closed if the volume that 144 // is displayed is unmounted. 145 if (!IsLaunching() && CountWindows() <= kWindowsToIgnore) { 146 // If the application is not launching and 147 // all windows are closed except for the file open panel, 148 // quit the application 149 PostMessage(B_QUIT_REQUESTED); 150 } 151} 152 153 154void 155ShowImageApp::RefsReceived(BMessage* message) 156{ 157 // If a tracker window opened me, get a messenger from it. 158 BMessenger trackerMessenger; 159 if (message->HasMessenger("TrackerViewToken")) 160 message->FindMessenger("TrackerViewToken", &trackerMessenger); 161 162 entry_ref ref; 163 for (int32 i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) 164 _Open(ref, trackerMessenger); 165} 166 167 168bool 169ShowImageApp::QuitRequested() 170{ 171 // Give the windows a chance to prompt the user if there are changes 172 bool result = BApplication::QuitRequested(); 173 if (result) { 174 be_clipboard->StopWatching(be_app_messenger); 175 // tell clipboard we don't want anymore notification 176 } 177 DefaultCache().Stop(); 178 179 return result; 180} 181 182 183void 184ShowImageApp::_StartPulse() 185{ 186 if (!fPulseStarted) { 187 // Tell the app to begin checking 188 // for the number of open windows 189 fPulseStarted = true; 190 SetPulseRate(250000); 191 // Set pulse to every 1/4 second 192 } 193} 194 195 196void 197ShowImageApp::_Open(const entry_ref& ref, const BMessenger& trackerMessenger) 198{ 199 fLastWindowFrame.OffsetBy(20, 20); 200 if (!BScreen(B_MAIN_SCREEN_ID).Frame().Contains(fLastWindowFrame)) 201 fLastWindowFrame.OffsetTo(50, 50); 202 203 new ShowImageWindow(fLastWindowFrame, ref, trackerMessenger); 204} 205 206 207void 208ShowImageApp::_BroadcastToWindows(BMessage* message) 209{ 210 const int32 count = CountWindows(); 211 for (int32 i = 0; i < count; i++) { 212 // BMessenger checks for us if BWindow is still a valid object 213 BMessenger messenger(WindowAt(i)); 214 messenger.SendMessage(message); 215 } 216} 217 218 219void 220ShowImageApp::_CheckClipboard() 221{ 222 // Determines if the contents of the clipboard contain 223 // data that is useful to this application. 224 // After checking the clipboard, a message is sent to 225 // all windows indicating that the clipboard has changed 226 // and whether or not the clipboard contains useful data. 227 bool dataAvailable = false; 228 229 if (be_clipboard->Lock()) { 230 BMessage* clip = be_clipboard->Data(); 231 if (clip != NULL) { 232 dataAvailable = clip->HasMessage("image/bitmap") 233 || clip->HasMessage("image/x-be-bitmap"); 234 } 235 236 be_clipboard->Unlock(); 237 } 238 239 BMessage msg(B_CLIPBOARD_CHANGED); 240 msg.AddBool("data_available", dataAvailable); 241 _BroadcastToWindows(&msg); 242} 243 244 245void 246ShowImageApp::_UpdateLastWindowFrame() 247{ 248 fLastWindowFrame = fSettings.GetRect("WindowFrame", fLastWindowFrame); 249 // Compensate the offset which we always add to new windows. 250 fLastWindowFrame.OffsetBy(-20, -20); 251} 252 253 254// #pragma mark - 255 256 257int 258main(int, char**) 259{ 260 ShowImageApp app; 261 app.Run(); 262 return 0; 263} 264 265