xref: /haiku/src/apps/showimage/ShowImageApp.cpp (revision 62f5ba006a08b0df30631375878effaf67ae5dbc)
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 extern const char* kApplicationSignature = "application/x-vnd.Haiku-ShowImage";
32 
33 
34 ShowImageApp::ShowImageApp()
35 	:
36 	BApplication(kApplicationSignature)
37 {
38 	be_locale->GetAppCatalog(&fCatalog);
39 
40 	fPulseStarted = false;
41 	fOpenPanel = new BFilePanel(B_OPEN_PANEL);
42 }
43 
44 
45 ShowImageApp::~ShowImageApp()
46 {
47 }
48 
49 
50 #undef TR_CONTEXT
51 #define TR_CONTEXT "AboutWindow"
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(TR("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 			BString className;
230 			if (clip->FindString("class", &className) == B_OK) {
231 				if (className == "BBitmap")
232 					dataAvailable = true;
233 			}
234 		}
235 
236 		be_clipboard->Unlock();
237 	}
238 
239 	BMessage msg(MSG_CLIPBOARD_CHANGED);
240 	msg.AddBool("data_available", dataAvailable);
241 	BroadcastToWindows(&msg);
242 }
243 
244 
245 bool
246 ShowImageApp::QuitRequested()
247 {
248 	// Give the windows a chance to prompt the user if there are changes
249 	bool result = BApplication::QuitRequested();
250 	if (result)
251 		be_clipboard->StopWatching(be_app_messenger);
252 			// tell clipboard we don't want anymore notification
253 
254 	return result;
255 }
256 
257 
258 //	#pragma mark -
259 
260 
261 int
262 main(int, char **)
263 {
264 	ShowImageApp theApp;
265 	theApp.Run();
266 	return 0;
267 }
268 
269