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