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