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 30 const char* kApplicationSignature = "application/x-vnd.Haiku-ShowImage"; 31 const int32 kWindowsToIgnore = 1; 32 // ignore the always open file panel 33 34 35 ShowImageApp::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 49 ShowImageApp::~ShowImageApp() 50 { 51 // BBitmap must be deleted while there is still a BApplication instance. 52 uninit_tool_bar_icons(); 53 } 54 55 56 void 57 ShowImageApp::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 92 void 93 ShowImageApp::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 109 void 110 ShowImageApp::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 140 void 141 ShowImageApp::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 154 void 155 ShowImageApp::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 168 bool 169 ShowImageApp::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 183 void 184 ShowImageApp::_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 196 void 197 ShowImageApp::_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 207 void 208 ShowImageApp::_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 219 void 220 ShowImageApp::_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 245 void 246 ShowImageApp::_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 257 int 258 main(int, char**) 259 { 260 ShowImageApp app; 261 app.Run(); 262 return 0; 263 } 264 265