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