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