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