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