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