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