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