xref: /haiku/src/apps/showimage/ShowImageWindow.cpp (revision a8199d692aa28895e7e9a4cbd77121c8879ba4a4)
1efa8b4f3SAxel Dörfler /*
24aa63633SAxel Dörfler  * Copyright 2003-2011, Haiku, Inc. All Rights Reserved.
3d9f6762dSMichael Pfeiffer  * Copyright 2004-2005 yellowTAB GmbH. All Rights Reserverd.
4d9f6762dSMichael Pfeiffer  * Copyright 2006 Bernd Korz. All Rights Reserved
5efa8b4f3SAxel Dörfler  * Distributed under the terms of the MIT License.
6efa8b4f3SAxel Dörfler  *
7efa8b4f3SAxel Dörfler  * Authors:
8efa8b4f3SAxel Dörfler  *		Fernando Francisco de Oliveira
9efa8b4f3SAxel Dörfler  *		Michael Wilber
10efa8b4f3SAxel Dörfler  *		Michael Pfeiffer
11d9f6762dSMichael Pfeiffer  *		yellowTAB GmbH
12d9f6762dSMichael Pfeiffer  *		Bernd Korz
13e2069723SAxel Dörfler  *		Axel Dörfler, axeld@pinc-software.de
149b13c418SStephan Aßmus  *		Stephan Aßmus <superstippi@gmx.de>
15efa8b4f3SAxel Dörfler  */
1613afa642SPhil Greenway 
174fd570d3SAxel Dörfler 
18efa8b4f3SAxel Dörfler #include "ShowImageWindow.h"
19efa8b4f3SAxel Dörfler 
20fd952aefSRyan Leavengood #include <new>
21fd952aefSRyan Leavengood #include <stdio.h>
2204f96544SAxel Dörfler #include <stdlib.h>
236163f333SKarsten Heimrich 
24efa8b4f3SAxel Dörfler #include <Alert.h>
2513afa642SPhil Greenway #include <Application.h>
2613afa642SPhil Greenway #include <Bitmap.h>
27fc0a275bSMatthew Wilber #include <BitmapStream.h>
281ed4535fSStephan Aßmus #include <Catalog.h>
29efa8b4f3SAxel Dörfler #include <Clipboard.h>
3013afa642SPhil Greenway #include <Entry.h>
31fc0a275bSMatthew Wilber #include <File.h>
326163f333SKarsten Heimrich #include <FilePanel.h>
331ed4535fSStephan Aßmus #include <Locale.h>
3413afa642SPhil Greenway #include <Menu.h>
3513afa642SPhil Greenway #include <MenuBar.h>
3613afa642SPhil Greenway #include <MenuItem.h>
374aa63633SAxel Dörfler #include <MessageRunner.h>
3813afa642SPhil Greenway #include <Path.h>
39efa8b4f3SAxel Dörfler #include <PrintJob.h>
4036272f0dSAxel Dörfler #include <RecentItems.h>
41efa8b4f3SAxel Dörfler #include <Roster.h>
42efa8b4f3SAxel Dörfler #include <Screen.h>
4313afa642SPhil Greenway #include <ScrollView.h>
446163f333SKarsten Heimrich #include <String.h>
45efa8b4f3SAxel Dörfler #include <SupportDefs.h>
466163f333SKarsten Heimrich #include <TranslationDefs.h>
4713afa642SPhil Greenway #include <TranslationUtils.h>
4813afa642SPhil Greenway #include <TranslatorRoster.h>
4913afa642SPhil Greenway 
50b9767a83SAxel Dörfler #include "ImageCache.h"
51e2069723SAxel Dörfler #include "ProgressWindow.h"
52fd952aefSRyan Leavengood #include "ShowImageApp.h"
53fd952aefSRyan Leavengood #include "ShowImageConstants.h"
54fd952aefSRyan Leavengood #include "ShowImageStatusView.h"
55fd952aefSRyan Leavengood #include "ShowImageView.h"
56cf0d8308SStephan Aßmus #include "ToolBarIcons.h"
57cf0d8308SStephan Aßmus #include "ToolBarView.h"
5813afa642SPhil Greenway 
59a8fc7138SMichael Pfeiffer 
60cd6b5cdeSAxel Dörfler // BMessage field names used in Save messages
61cd6b5cdeSAxel Dörfler const char* kTypeField = "be:type";
62cd6b5cdeSAxel Dörfler const char* kTranslatorField = "be:translator";
63cd6b5cdeSAxel Dörfler 
644aa63633SAxel Dörfler const bigtime_t kDefaultSlideShowDelay = 3000000;
654aa63633SAxel Dörfler 	// 3 seconds
664aa63633SAxel Dörfler 
67cd6b5cdeSAxel Dörfler 
68e2069723SAxel Dörfler // message constants
69e2069723SAxel Dörfler enum {
70e2069723SAxel Dörfler 	MSG_CAPTURE_MOUSE			= 'mCPM',
71e2069723SAxel Dörfler 	MSG_CHANGE_FOCUS			= 'mCFS',
72e2069723SAxel Dörfler 	MSG_WINDOW_QUIT				= 'mWQT',
73e2069723SAxel Dörfler 	MSG_OUTPUT_TYPE				= 'BTMN',
74e2069723SAxel Dörfler 	MSG_SAVE_PANEL				= 'mFSP',
75e2069723SAxel Dörfler 	MSG_CLEAR_SELECT			= 'mCSL',
76e2069723SAxel Dörfler 	MSG_SELECT_ALL				= 'mSAL',
77e2069723SAxel Dörfler 	MSG_SELECTION_MODE			= 'mSLM',
78e2069723SAxel Dörfler 	MSG_PAGE_FIRST				= 'mPGF',
79e2069723SAxel Dörfler 	MSG_PAGE_LAST				= 'mPGL',
80e2069723SAxel Dörfler 	MSG_PAGE_NEXT				= 'mPGN',
81e2069723SAxel Dörfler 	MSG_PAGE_PREV				= 'mPGP',
82e2069723SAxel Dörfler 	MSG_GOTO_PAGE				= 'mGTP',
83e2069723SAxel Dörfler 	MSG_ZOOM_IN					= 'mZIN',
84e2069723SAxel Dörfler 	MSG_ZOOM_OUT				= 'mZOU',
85e2069723SAxel Dörfler 	MSG_SCALE_BILINEAR			= 'mSBL',
86e2069723SAxel Dörfler 	MSG_DESKTOP_BACKGROUND		= 'mDBG',
87e2069723SAxel Dörfler 	MSG_ROTATE_90				= 'mR90',
88e2069723SAxel Dörfler 	MSG_ROTATE_270				= 'mR27',
89e2069723SAxel Dörfler 	MSG_FLIP_LEFT_TO_RIGHT		= 'mFLR',
90e2069723SAxel Dörfler 	MSG_FLIP_TOP_TO_BOTTOM		= 'mFTB',
91e2069723SAxel Dörfler 	MSG_SLIDE_SHOW_DELAY		= 'mSSD',
92e2069723SAxel Dörfler 	MSG_SHOW_CAPTION			= 'mSCP',
93e2069723SAxel Dörfler 	MSG_PAGE_SETUP				= 'mPSU',
94e2069723SAxel Dörfler 	MSG_PREPARE_PRINT			= 'mPPT',
955b76e505SStephan Aßmus 	MSG_SET_RATING				= 'mSRT',
96e2069723SAxel Dörfler 	kMsgFitToWindow				= 'mFtW',
97e2069723SAxel Dörfler 	kMsgOriginalSize			= 'mOSZ',
984aa63633SAxel Dörfler 	kMsgStretchToWindow			= 'mStW',
99cf0d8308SStephan Aßmus 	kMsgNextSlide				= 'mNxS',
10094fd9498SStephan Aßmus 	kMsgToggleToolBar			= 'mTTB',
10194fd9498SStephan Aßmus 	kMsgSlideToolBar			= 'mSTB',
10294fd9498SStephan Aßmus 	kMsgFinishSlidingToolBar	= 'mFST'
103e2069723SAxel Dörfler };
104e2069723SAxel Dörfler 
105e2069723SAxel Dörfler 
106cd6b5cdeSAxel Dörfler // This is temporary solution for building BString with printf like format.
107cd6b5cdeSAxel Dörfler // will be removed in the future.
108cd6b5cdeSAxel Dörfler static void
109cd6b5cdeSAxel Dörfler bs_printf(BString* string, const char* format, ...)
110cd6b5cdeSAxel Dörfler {
111cd6b5cdeSAxel Dörfler 	va_list ap;
112cd6b5cdeSAxel Dörfler 	char* buf;
113cd6b5cdeSAxel Dörfler 
114cd6b5cdeSAxel Dörfler 	va_start(ap, format);
115cd6b5cdeSAxel Dörfler 	vasprintf(&buf, format, ap);
116cd6b5cdeSAxel Dörfler 	string->SetTo(buf);
117cd6b5cdeSAxel Dörfler 	free(buf);
118cd6b5cdeSAxel Dörfler 	va_end(ap);
119cd6b5cdeSAxel Dörfler }
120cd6b5cdeSAxel Dörfler 
121cd6b5cdeSAxel Dörfler 
1226163f333SKarsten Heimrich //	#pragma mark -- ShowImageWindow
1236163f333SKarsten Heimrich 
1246163f333SKarsten Heimrich 
125546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT
126546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "Menus"
127cf0d8308SStephan Aßmus 
128cf0d8308SStephan Aßmus 
1295b76e505SStephan Aßmus ShowImageWindow::ShowImageWindow(BRect frame, const entry_ref& ref,
130efa8b4f3SAxel Dörfler 	const BMessenger& trackerMessenger)
131fd952aefSRyan Leavengood 	:
13294fd9498SStephan Aßmus 	BWindow(frame, "", B_DOCUMENT_WINDOW, B_AUTO_UPDATE_SIZE_LIMITS),
133b9767a83SAxel Dörfler 	fNavigator(ref, trackerMessenger),
134fd952aefSRyan Leavengood 	fSavePanel(NULL),
135fd952aefSRyan Leavengood 	fBar(NULL),
136fd952aefSRyan Leavengood 	fBrowseMenu(NULL),
137fd952aefSRyan Leavengood 	fGoToPageMenu(NULL),
1384aa63633SAxel Dörfler 	fSlideShowDelayMenu(NULL),
139cf0d8308SStephan Aßmus 	fToolBarView(NULL),
140fd952aefSRyan Leavengood 	fImageView(NULL),
141fd952aefSRyan Leavengood 	fStatusView(NULL),
142e2069723SAxel Dörfler 	fProgressWindow(new ProgressWindow()),
143fd952aefSRyan Leavengood 	fModified(false),
144fd952aefSRyan Leavengood 	fFullScreen(false),
145fd952aefSRyan Leavengood 	fShowCaption(true),
146cf0d8308SStephan Aßmus 	fShowToolBar(true),
1474aa63633SAxel Dörfler 	fPrintSettings(NULL),
1484aa63633SAxel Dörfler 	fSlideShowRunner(NULL),
1494aa63633SAxel Dörfler 	fSlideShowDelay(kDefaultSlideShowDelay)
15013afa642SPhil Greenway {
1512281340dSAxel Dörfler 	_ApplySettings();
152fc0a275bSMatthew Wilber 
15394fd9498SStephan Aßmus 	SetLayout(new BGroupLayout(B_VERTICAL, 0));
15494fd9498SStephan Aßmus 
15513afa642SPhil Greenway 	// create menu bar
15694fd9498SStephan Aßmus 	fBar = new BMenuBar("menu_bar");
157b9767a83SAxel Dörfler 	_AddMenus(fBar);
15894fd9498SStephan Aßmus 	float menuBarMinWidth = fBar->MinSize().width;
159e9dcd874SAxel Dörfler 	AddChild(fBar);
16013afa642SPhil Greenway 
16194fd9498SStephan Aßmus 	// Add a content view so the tool bar can be moved outside of the
16294fd9498SStephan Aßmus 	// visible portion without colliding with the menu bar.
163cf0d8308SStephan Aßmus 
16494fd9498SStephan Aßmus 	BView* contentView = new BView(BRect(), "content", B_FOLLOW_NONE, 0);
16594fd9498SStephan Aßmus 	contentView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
16694fd9498SStephan Aßmus 	contentView->SetExplicitMinSize(BSize(250, 100));
16794fd9498SStephan Aßmus 	AddChild(contentView);
16894fd9498SStephan Aßmus 
16994fd9498SStephan Aßmus 	// Create the tool bar
17094fd9498SStephan Aßmus 	BRect viewFrame = contentView->Bounds();
17194fd9498SStephan Aßmus 	viewFrame.right -= B_V_SCROLL_BAR_WIDTH;
172cf0d8308SStephan Aßmus 	fToolBarView = new ToolBarView(viewFrame);
173cf0d8308SStephan Aßmus 
174cf0d8308SStephan Aßmus 	// Add the tool icons.
175cf0d8308SStephan Aßmus 
176cf0d8308SStephan Aßmus //	fToolBarView->AddAction(MSG_FILE_OPEN, be_app,
177cf0d8308SStephan Aßmus //		tool_bar_icon(kIconDocumentOpen), B_TRANSLATE("Open"B_UTF8_ELLIPSIS));
178a877c0e7SStephan Aßmus 	fToolBarView->AddAction(MSG_FILE_PREV, this,
179a877c0e7SStephan Aßmus 		tool_bar_icon(kIconGoPrevious), B_TRANSLATE("Previous file"));
180a877c0e7SStephan Aßmus 	fToolBarView->AddAction(MSG_FILE_NEXT, this, tool_bar_icon(kIconGoNext),
181cf0d8308SStephan Aßmus 		B_TRANSLATE("Next file"));
182a877c0e7SStephan Aßmus 	BMessage* fullScreenSlideShow = new BMessage(MSG_SLIDE_SHOW);
183a877c0e7SStephan Aßmus 	fullScreenSlideShow->AddBool("full screen", true);
184a877c0e7SStephan Aßmus 	fToolBarView->AddAction(fullScreenSlideShow, this,
185a877c0e7SStephan Aßmus 		tool_bar_icon(kIconMediaMovieLibrary), B_TRANSLATE("Slide show"));
186cf0d8308SStephan Aßmus 	fToolBarView->AddSeparator();
187cf0d8308SStephan Aßmus 	fToolBarView->AddAction(MSG_SELECTION_MODE, this,
188cf0d8308SStephan Aßmus 		tool_bar_icon(kIconDrawRectangularSelection),
189cf0d8308SStephan Aßmus 		B_TRANSLATE("Selection mode"));
190cf0d8308SStephan Aßmus 	fToolBarView->AddSeparator();
191cf0d8308SStephan Aßmus 	fToolBarView->AddAction(kMsgOriginalSize, this,
192cf0d8308SStephan Aßmus 		tool_bar_icon(kIconZoomOriginal), B_TRANSLATE("Original size"));
193cf0d8308SStephan Aßmus 	fToolBarView->AddAction(kMsgFitToWindow, this,
194cf0d8308SStephan Aßmus 		tool_bar_icon(kIconZoomFitBest), B_TRANSLATE("Fit to window"));
195cf0d8308SStephan Aßmus 	fToolBarView->AddAction(MSG_ZOOM_IN, this, tool_bar_icon(kIconZoomIn),
196cf0d8308SStephan Aßmus 		B_TRANSLATE("Zoom in"));
197cf0d8308SStephan Aßmus 	fToolBarView->AddAction(MSG_ZOOM_OUT, this, tool_bar_icon(kIconZoomOut),
198cf0d8308SStephan Aßmus 		B_TRANSLATE("Zoom out"));
19994fd9498SStephan Aßmus 	fToolBarView->AddGlue();
20094fd9498SStephan Aßmus 	fToolBarView->AddAction(MSG_FULL_SCREEN, this,
20194fd9498SStephan Aßmus 		tool_bar_icon(kIconViewWindowed), B_TRANSLATE("Leave full screen"));
20294fd9498SStephan Aßmus 	fToolBarView->SetActionVisible(MSG_FULL_SCREEN, false);
203cf0d8308SStephan Aßmus 
204cf0d8308SStephan Aßmus 	fToolBarView->ResizeTo(viewFrame.Width(), fToolBarView->MinSize().height);
205cf0d8308SStephan Aßmus 
20694fd9498SStephan Aßmus 	contentView->AddChild(fToolBarView);
207cf0d8308SStephan Aßmus 
208cf0d8308SStephan Aßmus 	if (fShowToolBar)
209cf0d8308SStephan Aßmus 		viewFrame.top = fToolBarView->Frame().bottom + 1;
210cf0d8308SStephan Aßmus 	else
211cf0d8308SStephan Aßmus 		fToolBarView->Hide();
212cf0d8308SStephan Aßmus 
21394fd9498SStephan Aßmus 	viewFrame.bottom = contentView->Bounds().bottom;
21413afa642SPhil Greenway 	viewFrame.bottom -= B_H_SCROLL_BAR_HEIGHT;
21513afa642SPhil Greenway 
21613afa642SPhil Greenway 	// create the image view
217d3046f7dSMichael Pfeiffer 	fImageView = new ShowImageView(viewFrame, "image_view", B_FOLLOW_ALL,
218e2069723SAxel Dörfler 		B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_PULSE_NEEDED
219e2069723SAxel Dörfler 			| B_FRAME_EVENTS);
22013afa642SPhil Greenway 	// wrap a scroll view around the view
221cf0d8308SStephan Aßmus 	fScrollView = new BScrollView("image_scroller", fImageView,
222cdb89ebbSMatthew Wilber 		B_FOLLOW_ALL, 0, false, false, B_PLAIN_BORDER);
22394fd9498SStephan Aßmus 	contentView->AddChild(fScrollView);
22413afa642SPhil Greenway 
22507caaa8eSMatthew Wilber 	const int32 kstatusWidth = 190;
226cdb89ebbSMatthew Wilber 	BRect rect;
22794fd9498SStephan Aßmus 	rect = contentView->Bounds();
22813afa642SPhil Greenway 	rect.top = viewFrame.bottom + 1;
22907caaa8eSMatthew Wilber 	rect.left = viewFrame.left + kstatusWidth;
2300916ab53SMatthew Wilber 	rect.right = viewFrame.right + 1;
2310916ab53SMatthew Wilber 	rect.bottom += 1;
232efa8b4f3SAxel Dörfler 	BScrollBar* horizontalScrollBar = new BScrollBar(rect, "hscroll",
233efa8b4f3SAxel Dörfler 		fImageView, 0, 150, B_HORIZONTAL);
23494fd9498SStephan Aßmus 	contentView->AddChild(horizontalScrollBar);
23513afa642SPhil Greenway 
23613afa642SPhil Greenway 	rect.left = 0;
23707caaa8eSMatthew Wilber 	rect.right = kstatusWidth - 1;
2380cd4ecd8SStephan Aßmus 	rect.bottom -= 1;
239d3046f7dSMichael Pfeiffer 	fStatusView = new ShowImageStatusView(rect, "status_view", B_FOLLOW_BOTTOM,
240cdb89ebbSMatthew Wilber 		B_WILL_DRAW);
24194fd9498SStephan Aßmus 	contentView->AddChild(fStatusView);
24213afa642SPhil Greenway 
24394fd9498SStephan Aßmus 	rect = contentView->Bounds();
2440916ab53SMatthew Wilber 	rect.top = viewFrame.top - 1;
24513afa642SPhil Greenway 	rect.left = viewFrame.right + 1;
2460916ab53SMatthew Wilber 	rect.bottom = viewFrame.bottom + 1;
2470916ab53SMatthew Wilber 	rect.right += 1;
248cf0d8308SStephan Aßmus 	fVerticalScrollBar = new BScrollBar(rect, "vscroll", fImageView,
249efa8b4f3SAxel Dörfler 		0, 150, B_VERTICAL);
25094fd9498SStephan Aßmus 	contentView->AddChild(fVerticalScrollBar);
25113afa642SPhil Greenway 
2529b13c418SStephan Aßmus 	// Update minimum window size
25394fd9498SStephan Aßmus 	float toolBarMinWidth = fToolBarView->MinSize().width;
2549b13c418SStephan Aßmus 	SetSizeLimits(std::max(menuBarMinWidth, toolBarMinWidth), 100000, 100,
2559b13c418SStephan Aßmus 		100000);
25613afa642SPhil Greenway 
257134d6076SMichael Pfeiffer 	// finish creating the window
258b9767a83SAxel Dörfler 	if (_LoadImage() != B_OK) {
259ba3217eeSAxel Dörfler 		_LoadError(ref);
2605e09d5dbSRyan Leavengood 		Quit();
26101939af6SAxel Dörfler 		return;
262d10d5947SMichael Pfeiffer 	}
263402c09e5SMatthew Wilber 
264d9f6762dSMichael Pfeiffer 	// add View menu here so it can access ShowImageView methods
265546208a5SOliver Tappe 	BMenu* menu = new BMenu(B_TRANSLATE_CONTEXT("View", "Menus"));
266fd952aefSRyan Leavengood 	_BuildViewMenu(menu, false);
267d9f6762dSMichael Pfeiffer 	fBar->AddItem(menu);
268d9f6762dSMichael Pfeiffer 
2695b76e505SStephan Aßmus 	fBar->AddItem(_BuildRatingMenu());
2705b76e505SStephan Aßmus 
271d9f6762dSMichael Pfeiffer 	SetPulseRate(100000);
272d9f6762dSMichael Pfeiffer 		// every 1/10 second; ShowImageView needs it for marching ants
273d9f6762dSMichael Pfeiffer 
2746db01936SAxel Dörfler 	_MarkMenuItem(menu, MSG_SELECTION_MODE,
2756db01936SAxel Dörfler 		fImageView->IsSelectionModeEnabled());
2766db01936SAxel Dörfler 
277402c09e5SMatthew Wilber 	// Tell application object to query the clipboard
278402c09e5SMatthew Wilber 	// and tell this window if it contains interesting data or not
279402c09e5SMatthew Wilber 	be_app_messenger.SendMessage(B_CLIPBOARD_CHANGED);
280cd6b5cdeSAxel Dörfler 
281cd6b5cdeSAxel Dörfler 	// The window will be shown on screen automatically
282cd6b5cdeSAxel Dörfler 	Run();
28313afa642SPhil Greenway }
28413afa642SPhil Greenway 
285efa8b4f3SAxel Dörfler 
28613afa642SPhil Greenway ShowImageWindow::~ShowImageWindow()
28713afa642SPhil Greenway {
288e2069723SAxel Dörfler 	fProgressWindow->Lock();
289e2069723SAxel Dörfler 	fProgressWindow->Quit();
2904aa63633SAxel Dörfler 
2914aa63633SAxel Dörfler 	_StopSlideShow();
29213afa642SPhil Greenway }
29313afa642SPhil Greenway 
294efa8b4f3SAxel Dörfler 
295cdb89ebbSMatthew Wilber void
296d9f6762dSMichael Pfeiffer ShowImageWindow::BuildContextMenu(BMenu* menu)
297d9f6762dSMichael Pfeiffer {
298fd952aefSRyan Leavengood 	_BuildViewMenu(menu, true);
299d9f6762dSMichael Pfeiffer }
300efa8b4f3SAxel Dörfler 
30156b0c7b9SKarsten Heimrich 
302cdb89ebbSMatthew Wilber void
303fd952aefSRyan Leavengood ShowImageWindow::_BuildViewMenu(BMenu* menu, bool popupMenu)
304da87390fSMichael Pfeiffer {
305905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Slide show"), MSG_SLIDE_SHOW, 0, 0, this);
3064aa63633SAxel Dörfler 	_MarkMenuItem(menu, MSG_SLIDE_SHOW, fSlideShowRunner != NULL);
307905c8c8cSMatt Madia 	BMenu* delayMenu = new BMenu(B_TRANSLATE("Slide delay"));
3084aa63633SAxel Dörfler 	if (fSlideShowDelayMenu == NULL)
3094aa63633SAxel Dörfler 		fSlideShowDelayMenu = delayMenu;
310efa8b4f3SAxel Dörfler 
311efa8b4f3SAxel Dörfler 	delayMenu->SetRadioMode(true);
3124aa63633SAxel Dörfler 
3134aa63633SAxel Dörfler 	int32 kDelays[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 20};
3144aa63633SAxel Dörfler 	for (uint32 i = 0; i < sizeof(kDelays) / sizeof(kDelays[0]); i++) {
3154aa63633SAxel Dörfler 		BString text(B_TRANSLATE_COMMENT("%SECONDS seconds",
3164aa63633SAxel Dörfler 			"Don't translate %SECONDS"));
3174aa63633SAxel Dörfler 		char seconds[32];
3184aa63633SAxel Dörfler 		snprintf(seconds, sizeof(seconds), "%" B_PRIi32, kDelays[i]);
3194aa63633SAxel Dörfler 		text.ReplaceFirst("%SECONDS", seconds);
3204aa63633SAxel Dörfler 
3214aa63633SAxel Dörfler 		_AddDelayItem(delayMenu, text.String(), kDelays[i] * 1000000LL);
3224aa63633SAxel Dörfler 	}
323efa8b4f3SAxel Dörfler 	menu->AddItem(delayMenu);
32430060f17SMatthew Wilber 
325efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
326efa8b4f3SAxel Dörfler 
327905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Original size"),
328e2069723SAxel Dörfler 		kMsgOriginalSize, '1', 0, this);
329e2069723SAxel Dörfler 	_AddItemMenu(menu, B_TRANSLATE("Fit to window"),
330e2069723SAxel Dörfler 		kMsgFitToWindow, '0', 0, this);
331905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Zoom in"), MSG_ZOOM_IN, '+', 0, this);
332905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Zoom out"), MSG_ZOOM_OUT, '-', 0, this);
333efa8b4f3SAxel Dörfler 
334efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
335efa8b4f3SAxel Dörfler 
3364fd570d3SAxel Dörfler 	if (!popupMenu || fFullScreen) {
337905c8c8cSMatt Madia 		_AddItemMenu(menu, B_TRANSLATE("High-quality zooming"),
338905c8c8cSMatt Madia 			MSG_SCALE_BILINEAR, 0, 0, this);
3394fd570d3SAxel Dörfler 		_AddItemMenu(menu, B_TRANSLATE("Stretch to window"),
340e2069723SAxel Dörfler 			kMsgStretchToWindow, 0, 0, this);
341efa8b4f3SAxel Dörfler 
342efa8b4f3SAxel Dörfler 		menu->AddSeparatorItem();
34332c22143SAxel Dörfler 	}
344efa8b4f3SAxel Dörfler 
345905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Full screen"),
346905c8c8cSMatt Madia 		MSG_FULL_SCREEN, B_ENTER, 0, this);
347fd952aefSRyan Leavengood 	_MarkMenuItem(menu, MSG_FULL_SCREEN, fFullScreen);
348efa8b4f3SAxel Dörfler 
349905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Show caption in full screen mode"),
350905c8c8cSMatt Madia 		MSG_SHOW_CAPTION, 0, 0, this);
351fd952aefSRyan Leavengood 	_MarkMenuItem(menu, MSG_SHOW_CAPTION, fShowCaption);
352efa8b4f3SAxel Dörfler 
353e2069723SAxel Dörfler 	_MarkMenuItem(menu, MSG_SCALE_BILINEAR, fImageView->ScaleBilinear());
354e2069723SAxel Dörfler 	_MarkMenuItem(menu, kMsgStretchToWindow, fImageView->StretchesToBounds());
355a60adbf9SAxel Dörfler 
356cf0d8308SStephan Aßmus 	if (!popupMenu) {
35794fd9498SStephan Aßmus 		_AddItemMenu(menu, B_TRANSLATE("Show tool bar"), kMsgToggleToolBar,
35894fd9498SStephan Aßmus 			'T', 0, this);
359cf0d8308SStephan Aßmus 		_MarkMenuItem(menu, kMsgToggleToolBar,
360cf0d8308SStephan Aßmus 			!fToolBarView->IsHidden(fToolBarView));
361cf0d8308SStephan Aßmus 	}
362cf0d8308SStephan Aßmus 
363d9f6762dSMichael Pfeiffer 	if (popupMenu) {
364a60adbf9SAxel Dörfler 		menu->AddSeparatorItem();
365905c8c8cSMatt Madia 		_AddItemMenu(menu, B_TRANSLATE("Use as background" B_UTF8_ELLIPSIS),
3661ed4535fSStephan Aßmus 			MSG_DESKTOP_BACKGROUND, 0, 0, this);
367d9f6762dSMichael Pfeiffer 	}
368da87390fSMichael Pfeiffer }
369da87390fSMichael Pfeiffer 
370efa8b4f3SAxel Dörfler 
3715b76e505SStephan Aßmus BMenu*
3725b76e505SStephan Aßmus ShowImageWindow::_BuildRatingMenu()
3735b76e505SStephan Aßmus {
3745b76e505SStephan Aßmus 	fRatingMenu = new BMenu(B_TRANSLATE("Rating"));
3755b76e505SStephan Aßmus 	for (int32 i = 1; i <= 10; i++) {
3765b76e505SStephan Aßmus 		BString label;
3775b76e505SStephan Aßmus 		label << i;
3785b76e505SStephan Aßmus 		BMessage* message = new BMessage(MSG_SET_RATING);
3795b76e505SStephan Aßmus 		message->AddInt32("rating", i);
3805b76e505SStephan Aßmus 		fRatingMenu->AddItem(new BMenuItem(label.String(), message));
3815b76e505SStephan Aßmus 	}
3825b76e505SStephan Aßmus 	// NOTE: We may want to encapsulate the Rating menu within a more
3835b76e505SStephan Aßmus 	// general "Attributes" menu.
3845b76e505SStephan Aßmus 	return fRatingMenu;
3855b76e505SStephan Aßmus }
3865b76e505SStephan Aßmus 
3875b76e505SStephan Aßmus 
388da87390fSMichael Pfeiffer void
389b9767a83SAxel Dörfler ShowImageWindow::_AddMenus(BMenuBar* bar)
39013afa642SPhil Greenway {
391905c8c8cSMatt Madia 	BMenu* menu = new BMenu(B_TRANSLATE("File"));
39236272f0dSAxel Dörfler 
39336272f0dSAxel Dörfler 	// Add recent files to "Open File" entry as sub-menu.
39436272f0dSAxel Dörfler 	BMenuItem* item = new BMenuItem(BRecentFilesList::NewFileListMenu(
39536272f0dSAxel Dörfler 		B_TRANSLATE("Open"B_UTF8_ELLIPSIS), NULL, NULL, be_app, 10, true,
39636272f0dSAxel Dörfler 		NULL, kApplicationSignature), new BMessage(MSG_FILE_OPEN));
39736272f0dSAxel Dörfler 	item->SetShortcut('O', 0);
39836272f0dSAxel Dörfler 	item->SetTarget(be_app);
39936272f0dSAxel Dörfler 	menu->AddItem(item);
400efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
40136272f0dSAxel Dörfler 
4026db01936SAxel Dörfler 	BMenu* menuSaveAs = new BMenu(B_TRANSLATE("Save as" B_UTF8_ELLIPSIS),
4031ed4535fSStephan Aßmus 		B_ITEMS_IN_COLUMN);
4046db01936SAxel Dörfler 	BTranslationUtils::AddTranslationItems(menuSaveAs, B_TRANSLATOR_BITMAP);
405fc0a275bSMatthew Wilber 		// Fill Save As submenu with all types that can be converted
406fc0a275bSMatthew Wilber 		// to from the Be bitmap image format
4076db01936SAxel Dörfler 	menu->AddItem(menuSaveAs);
408905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Close"), B_QUIT_REQUESTED, 'W', 0, this);
409efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
410905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Page setup" B_UTF8_ELLIPSIS),
4111ed4535fSStephan Aßmus 		MSG_PAGE_SETUP, 0, 0, this);
412905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Print" B_UTF8_ELLIPSIS),
4131ed4535fSStephan Aßmus 		MSG_PREPARE_PRINT, 'P', 0, this);
414efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
415905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Quit"), B_QUIT_REQUESTED, 'Q', 0, be_app);
416efa8b4f3SAxel Dörfler 	bar->AddItem(menu);
41713afa642SPhil Greenway 
418905c8c8cSMatt Madia 	menu = new BMenu(B_TRANSLATE("Edit"));
419905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Undo"), B_UNDO, 'Z', 0, this, false);
420efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
421905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Copy"), B_COPY, 'C', 0, this, false);
422efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
423cf0d8308SStephan Aßmus 	_AddItemMenu(menu, B_TRANSLATE("Selection mode"), MSG_SELECTION_MODE, 0, 0,
4246db01936SAxel Dörfler 		this);
42532c22143SAxel Dörfler 	_AddItemMenu(menu, B_TRANSLATE("Clear selection"),
42632c22143SAxel Dörfler 		MSG_CLEAR_SELECT, 0, 0, this, false);
427905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Select all"),
428905c8c8cSMatt Madia 		MSG_SELECT_ALL, 'A', 0, this);
429efa8b4f3SAxel Dörfler 	bar->AddItem(menu);
43013afa642SPhil Greenway 
431905c8c8cSMatt Madia 	menu = fBrowseMenu = new BMenu(B_TRANSLATE("Browse"));
432905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("First page"),
4331ed4535fSStephan Aßmus 		MSG_PAGE_FIRST, B_LEFT_ARROW, B_SHIFT_KEY, this);
434905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Last page"),
4351ed4535fSStephan Aßmus 		MSG_PAGE_LAST, B_RIGHT_ARROW, B_SHIFT_KEY, this);
436905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Previous page"),
437905c8c8cSMatt Madia 		MSG_PAGE_PREV, B_LEFT_ARROW, 0, this);
438905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Next page"),
439905c8c8cSMatt Madia 		MSG_PAGE_NEXT, B_RIGHT_ARROW, 0, this);
440905c8c8cSMatt Madia 	fGoToPageMenu = new BMenu(B_TRANSLATE("Go to page"));
4415e427b6aSMichael Pfeiffer 	fGoToPageMenu->SetRadioMode(true);
442efa8b4f3SAxel Dörfler 	menu->AddItem(fGoToPageMenu);
443efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
444905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Previous file"),
445905c8c8cSMatt Madia 		MSG_FILE_PREV, B_UP_ARROW, 0, this);
446905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Next file"),
447905c8c8cSMatt Madia 		MSG_FILE_NEXT, B_DOWN_ARROW, 0, this);
448efa8b4f3SAxel Dörfler 	bar->AddItem(menu);
44903839579SMatthew Wilber 
450905c8c8cSMatt Madia 	menu = new BMenu(B_TRANSLATE("Image"));
451905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Rotate clockwise"),
452905c8c8cSMatt Madia 		MSG_ROTATE_90, 'R', 0, this);
453905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Rotate counterclockwise"),
4541ed4535fSStephan Aßmus 		MSG_ROTATE_270, 'R', B_SHIFT_KEY, this);
455efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
456905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Flip left to right"),
4571ed4535fSStephan Aßmus 		MSG_FLIP_LEFT_TO_RIGHT, 0, 0, this);
458905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Flip top to bottom"),
4591ed4535fSStephan Aßmus 		MSG_FLIP_TOP_TO_BOTTOM, 0, 0, this);
460efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
461905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Use as background" B_UTF8_ELLIPSIS),
4621ed4535fSStephan Aßmus 		MSG_DESKTOP_BACKGROUND, 0, 0, this);
46304f96544SAxel Dörfler 
46404f96544SAxel Dörfler 	bar->AddItem(menu);
46513afa642SPhil Greenway }
46613afa642SPhil Greenway 
467efa8b4f3SAxel Dörfler 
468cdb89ebbSMatthew Wilber BMenuItem*
469fd952aefSRyan Leavengood ShowImageWindow::_AddItemMenu(BMenu* menu, const char* label, uint32 what,
4704fd570d3SAxel Dörfler 	char shortcut, uint32 modifier, const BHandler* target, bool enabled)
471cdb89ebbSMatthew Wilber {
4724fd570d3SAxel Dörfler 	BMenuItem* item = new BMenuItem(label, new BMessage(what), shortcut,
4734fd570d3SAxel Dörfler 		modifier);
474efa8b4f3SAxel Dörfler 	menu->AddItem(item);
475efa8b4f3SAxel Dörfler 
4766163f333SKarsten Heimrich 	item->SetTarget(target);
4776163f333SKarsten Heimrich 	item->SetEnabled(enabled);
4786163f333SKarsten Heimrich 
479efa8b4f3SAxel Dörfler 	return item;
48013afa642SPhil Greenway }
48113afa642SPhil Greenway 
482efa8b4f3SAxel Dörfler 
483ad13f387SMichael Pfeiffer BMenuItem*
4844aa63633SAxel Dörfler ShowImageWindow::_AddDelayItem(BMenu* menu, const char* label, bigtime_t delay)
485ad13f387SMichael Pfeiffer {
486efa8b4f3SAxel Dörfler 	BMessage* message = new BMessage(MSG_SLIDE_SHOW_DELAY);
4874aa63633SAxel Dörfler 	message->AddInt64("delay", delay);
488ad13f387SMichael Pfeiffer 
4896163f333SKarsten Heimrich 	BMenuItem* item = new BMenuItem(label, message, 0);
490efa8b4f3SAxel Dörfler 	item->SetTarget(this);
491ad13f387SMichael Pfeiffer 
4924aa63633SAxel Dörfler 	if (delay == fSlideShowDelay)
493efa8b4f3SAxel Dörfler 		item->SetMarked(true);
494ad13f387SMichael Pfeiffer 
495efa8b4f3SAxel Dörfler 	menu->AddItem(item);
496efa8b4f3SAxel Dörfler 	return item;
497ad13f387SMichael Pfeiffer }
498ad13f387SMichael Pfeiffer 
499efa8b4f3SAxel Dörfler 
500cdb89ebbSMatthew Wilber void
501e2069723SAxel Dörfler ShowImageWindow::_ResizeWindowToImage()
50213afa642SPhil Greenway {
503e2069723SAxel Dörfler 	BBitmap* bitmap = fImageView->Bitmap();
504d10d5947SMichael Pfeiffer 	BScreen screen;
505e2069723SAxel Dörfler 	if (bitmap == NULL || !screen.IsValid())
506efa8b4f3SAxel Dörfler 		return;
507efa8b4f3SAxel Dörfler 
5081076d97bSAxel Dörfler 	// TODO: use View::GetPreferredSize() instead?
5091076d97bSAxel Dörfler 	BRect r(bitmap->Bounds());
5101076d97bSAxel Dörfler 	float width = r.Width() + B_V_SCROLL_BAR_WIDTH;
5111076d97bSAxel Dörfler 	float height = r.Height() + 1 + fBar->Frame().Height()
5121076d97bSAxel Dörfler 		+ B_H_SCROLL_BAR_HEIGHT;
513cdb89ebbSMatthew Wilber 
5146163f333SKarsten Heimrich 	BRect frame = screen.Frame();
5156163f333SKarsten Heimrich 	const float windowBorder = 5;
516d10d5947SMichael Pfeiffer 	// dimensions so that window does not reach outside of screen
5176163f333SKarsten Heimrich 	float maxWidth = frame.Width() + 1 - windowBorder - Frame().left;
5186163f333SKarsten Heimrich 	float maxHeight = frame.Height() + 1 - windowBorder - Frame().top;
519cdb89ebbSMatthew Wilber 
520a8fc7138SMichael Pfeiffer 	// We have to check size limits manually, otherwise
521a8fc7138SMichael Pfeiffer 	// menu bar will be too short for small images.
522efa8b4f3SAxel Dörfler 
523fc5ca95dSStephan Aßmus 	float minW, maxW, minH, maxH;
524a8fc7138SMichael Pfeiffer 	GetSizeLimits(&minW, &maxW, &minH, &maxH);
525efa8b4f3SAxel Dörfler 	if (maxWidth > maxW)
526efa8b4f3SAxel Dörfler 		maxWidth = maxW;
527efa8b4f3SAxel Dörfler 	if (maxHeight > maxH)
528efa8b4f3SAxel Dörfler 		maxHeight = maxH;
529efa8b4f3SAxel Dörfler 	if (width < minW)
530efa8b4f3SAxel Dörfler 		width = minW;
531efa8b4f3SAxel Dörfler 	if (height < minH)
532efa8b4f3SAxel Dörfler 		height = minH;
533a8fc7138SMichael Pfeiffer 
534efa8b4f3SAxel Dörfler 	if (width > maxWidth)
535efa8b4f3SAxel Dörfler 		width = maxWidth;
536efa8b4f3SAxel Dörfler 	if (height > maxHeight)
537efa8b4f3SAxel Dörfler 		height = maxHeight;
538d10d5947SMichael Pfeiffer 
539d10d5947SMichael Pfeiffer 	ResizeTo(width, height);
54013afa642SPhil Greenway }
54113afa642SPhil Greenway 
542efa8b4f3SAxel Dörfler 
5437eca0987SMichael Pfeiffer bool
544fd952aefSRyan Leavengood ShowImageWindow::_ToggleMenuItem(uint32 what)
5457eca0987SMichael Pfeiffer {
5467eca0987SMichael Pfeiffer 	bool marked = false;
5476163f333SKarsten Heimrich 	BMenuItem* item = fBar->FindItem(what);
5487eca0987SMichael Pfeiffer 	if (item != NULL) {
5497eca0987SMichael Pfeiffer 		marked = !item->IsMarked();
5507eca0987SMichael Pfeiffer 		item->SetMarked(marked);
5517eca0987SMichael Pfeiffer 	}
552cf0d8308SStephan Aßmus 	fToolBarView->SetActionPressed(what, marked);
5537eca0987SMichael Pfeiffer 	return marked;
5547eca0987SMichael Pfeiffer }
5557eca0987SMichael Pfeiffer 
556efa8b4f3SAxel Dörfler 
557cdb89ebbSMatthew Wilber void
558fd952aefSRyan Leavengood ShowImageWindow::_EnableMenuItem(BMenu* menu, uint32 what, bool enable)
559e6a50d9cSMichael Pfeiffer {
5606163f333SKarsten Heimrich 	BMenuItem* item = menu->FindItem(what);
5616163f333SKarsten Heimrich 	if (item && item->IsEnabled() != enable)
562e6a50d9cSMichael Pfeiffer 		item->SetEnabled(enable);
563cf0d8308SStephan Aßmus 	fToolBarView->SetActionEnabled(what, enable);
564e6a50d9cSMichael Pfeiffer }
565e6a50d9cSMichael Pfeiffer 
566efa8b4f3SAxel Dörfler 
567e6a50d9cSMichael Pfeiffer void
568fd952aefSRyan Leavengood ShowImageWindow::_MarkMenuItem(BMenu* menu, uint32 what, bool marked)
569e6a50d9cSMichael Pfeiffer {
5706163f333SKarsten Heimrich 	BMenuItem* item = menu->FindItem(what);
5716163f333SKarsten Heimrich 	if (item && item->IsMarked() != marked)
572e6a50d9cSMichael Pfeiffer 		item->SetMarked(marked);
573cf0d8308SStephan Aßmus 	fToolBarView->SetActionPressed(what, marked);
574e6a50d9cSMichael Pfeiffer }
575e6a50d9cSMichael Pfeiffer 
576efa8b4f3SAxel Dörfler 
577da87390fSMichael Pfeiffer void
5784aa63633SAxel Dörfler ShowImageWindow::_MarkSlideShowDelay(bigtime_t delay)
579da87390fSMichael Pfeiffer {
5804aa63633SAxel Dörfler 	const int32 count = fSlideShowDelayMenu->CountItems();
5814aa63633SAxel Dörfler 	for (int32 i = 0; i < count; i ++) {
5824aa63633SAxel Dörfler 		BMenuItem* item = fSlideShowDelayMenu->ItemAt(i);
5834aa63633SAxel Dörfler 		if (item != NULL) {
5844aa63633SAxel Dörfler 			bigtime_t itemDelay;
5854aa63633SAxel Dörfler 			if (item->Message()->FindInt64("delay", &itemDelay) == B_OK
5864aa63633SAxel Dörfler 				&& itemDelay == delay) {
587da87390fSMichael Pfeiffer 				item->SetMarked(true);
588da87390fSMichael Pfeiffer 				return;
589da87390fSMichael Pfeiffer 			}
590da87390fSMichael Pfeiffer 		}
591da87390fSMichael Pfeiffer 	}
592da87390fSMichael Pfeiffer }
593e6a50d9cSMichael Pfeiffer 
59419c76de4SMichael Pfeiffer 
59519c76de4SMichael Pfeiffer void
596e2069723SAxel Dörfler ShowImageWindow::Zoom(BPoint origin, float width, float height)
59719c76de4SMichael Pfeiffer {
598e2069723SAxel Dörfler 	_ToggleFullScreen();
59919c76de4SMichael Pfeiffer }
60019c76de4SMichael Pfeiffer 
601efa8b4f3SAxel Dörfler 
602e6a50d9cSMichael Pfeiffer void
603efa8b4f3SAxel Dörfler ShowImageWindow::MessageReceived(BMessage* message)
60413afa642SPhil Greenway {
605e2069723SAxel Dörfler 	if (message->WasDropped()) {
606e2069723SAxel Dörfler 		uint32 type;
607e2069723SAxel Dörfler 		int32 count;
608e2069723SAxel Dörfler 		status_t status = message->GetInfo("refs", &type, &count);
609e2069723SAxel Dörfler 		if (status == B_OK && type == B_REF_TYPE) {
610e2069723SAxel Dörfler 			message->what = B_REFS_RECEIVED;
611e2069723SAxel Dörfler 			be_app->PostMessage(message);
612e2069723SAxel Dörfler 		}
613e2069723SAxel Dörfler 	}
614e2069723SAxel Dörfler 
615efa8b4f3SAxel Dörfler 	switch (message->what) {
616e2069723SAxel Dörfler 		case kMsgImageCacheImageLoaded:
617cd6b5cdeSAxel Dörfler 		{
618e2069723SAxel Dörfler 			fProgressWindow->Stop();
619e2069723SAxel Dörfler 
620df942b3eSAxel Dörfler 			BitmapOwner* bitmapOwner = NULL;
621df942b3eSAxel Dörfler 			message->FindPointer("bitmapOwner", (void**)&bitmapOwner);
622df942b3eSAxel Dörfler 
623cd6b5cdeSAxel Dörfler 			bool first = fImageView->Bitmap() == NULL;
624b9767a83SAxel Dörfler 			entry_ref ref;
625b9767a83SAxel Dörfler 			message->FindRef("ref", &ref);
626b9767a83SAxel Dörfler 			if (!first && ref != fNavigator.CurrentRef()) {
627b9767a83SAxel Dörfler 				// ignore older images
628df942b3eSAxel Dörfler 				if (bitmapOwner != NULL)
629df942b3eSAxel Dörfler 					bitmapOwner->ReleaseReference();
630b9767a83SAxel Dörfler 				break;
631b9767a83SAxel Dörfler 			}
632cd6b5cdeSAxel Dörfler 
633cd6b5cdeSAxel Dörfler 			status_t status = fImageView->SetImage(message);
634cd6b5cdeSAxel Dörfler 			if (status != B_OK) {
635df942b3eSAxel Dörfler 				if (bitmapOwner != NULL)
636df942b3eSAxel Dörfler 					bitmapOwner->ReleaseReference();
637df942b3eSAxel Dörfler 
638cd6b5cdeSAxel Dörfler 				_LoadError(ref);
639cd6b5cdeSAxel Dörfler 
640cd6b5cdeSAxel Dörfler 				// quit if file could not be opened
641cd6b5cdeSAxel Dörfler 				if (first)
642cd6b5cdeSAxel Dörfler 					Quit();
643cd6b5cdeSAxel Dörfler 				break;
644cd6b5cdeSAxel Dörfler 			}
645cd6b5cdeSAxel Dörfler 
646cd6b5cdeSAxel Dörfler 			fImageType = message->FindString("type");
647b9767a83SAxel Dörfler 			fNavigator.SetTo(ref, message->FindInt32("page"),
648b9767a83SAxel Dörfler 				message->FindInt32("pageCount"));
649cd6b5cdeSAxel Dörfler 
650e2069723SAxel Dörfler 			fImageView->FitToBounds();
651cd6b5cdeSAxel Dörfler 			if (first) {
652cd6b5cdeSAxel Dörfler 				fImageView->MakeFocus(true);
653cd6b5cdeSAxel Dörfler 					// to receive key messages
654cd6b5cdeSAxel Dörfler 				Show();
655e2069723SAxel Dörfler 			}
6565b76e505SStephan Aßmus 			_UpdateRatingMenu();
657e2069723SAxel Dörfler 			break;
658e2069723SAxel Dörfler 		}
659e2069723SAxel Dörfler 
660e2069723SAxel Dörfler 		case kMsgImageCacheProgressUpdate:
661e2069723SAxel Dörfler 		{
662e2069723SAxel Dörfler 			entry_ref ref;
663e2069723SAxel Dörfler 			if (message->FindRef("ref", &ref) == B_OK
664e2069723SAxel Dörfler 				&& ref == fNavigator.CurrentRef()) {
665e2069723SAxel Dörfler 				message->what = kMsgProgressUpdate;
666e2069723SAxel Dörfler 				fProgressWindow->PostMessage(message);
667cd6b5cdeSAxel Dörfler 			}
668cd6b5cdeSAxel Dörfler 			break;
669cd6b5cdeSAxel Dörfler 		}
670cd6b5cdeSAxel Dörfler 
671ee7b4f39SMatthew Wilber 		case MSG_MODIFIED:
672ee7b4f39SMatthew Wilber 			// If image has been modified due to a Cut or Paste
673ee7b4f39SMatthew Wilber 			fModified = true;
674ee7b4f39SMatthew Wilber 			break;
675ee7b4f39SMatthew Wilber 
676fc0a275bSMatthew Wilber 		case MSG_OUTPUT_TYPE:
677fc0a275bSMatthew Wilber 			// User clicked Save As then choose an output format
678d3046f7dSMichael Pfeiffer 			if (!fSavePanel)
679cdb89ebbSMatthew Wilber 				// If user doesn't already have a save panel open
680fd952aefSRyan Leavengood 				_SaveAs(message);
68113afa642SPhil Greenway 			break;
682fc0a275bSMatthew Wilber 
683fc0a275bSMatthew Wilber 		case MSG_SAVE_PANEL:
684fc0a275bSMatthew Wilber 			// User specified where to save the output image
685fd952aefSRyan Leavengood 			_SaveToFile(message);
68607caaa8eSMatthew Wilber 			break;
68707caaa8eSMatthew Wilber 
688cdb89ebbSMatthew Wilber 		case B_CANCEL:
689d3046f7dSMichael Pfeiffer 			delete fSavePanel;
690d3046f7dSMichael Pfeiffer 			fSavePanel = NULL;
691cdb89ebbSMatthew Wilber 			break;
692cdb89ebbSMatthew Wilber 
6936db01936SAxel Dörfler 		case MSG_UPDATE_STATUS:
6946db01936SAxel Dörfler 		{
695cd6b5cdeSAxel Dörfler 			int32 pages = fNavigator.PageCount();
696cd6b5cdeSAxel Dörfler 			int32 currentPage = fNavigator.CurrentPage();
6976c305411SMatthew Wilber 
698cd6b5cdeSAxel Dörfler 			bool enable = pages > 1 ? true : false;
69936c17651SRyan Leavengood 			_EnableMenuItem(fBar, MSG_PAGE_FIRST, enable);
70036c17651SRyan Leavengood 			_EnableMenuItem(fBar, MSG_PAGE_LAST, enable);
70136c17651SRyan Leavengood 			_EnableMenuItem(fBar, MSG_PAGE_NEXT, enable);
70236c17651SRyan Leavengood 			_EnableMenuItem(fBar, MSG_PAGE_PREV, enable);
70336c17651SRyan Leavengood 			fGoToPageMenu->SetEnabled(enable);
7041d592070SMatthew Wilber 
705cd6b5cdeSAxel Dörfler 			_EnableMenuItem(fBar, MSG_FILE_NEXT, fNavigator.HasNextFile());
706cd6b5cdeSAxel Dörfler 			_EnableMenuItem(fBar, MSG_FILE_PREV, fNavigator.HasPreviousFile());
707134d6076SMichael Pfeiffer 
708d3046f7dSMichael Pfeiffer 			if (fGoToPageMenu->CountItems() != pages) {
7096c305411SMatthew Wilber 				// Only rebuild the submenu if the number of
7106c305411SMatthew Wilber 				// pages is different
7116c305411SMatthew Wilber 
712cd6b5cdeSAxel Dörfler 				while (fGoToPageMenu->CountItems() > 0) {
7136c305411SMatthew Wilber 					// Remove all page numbers
714d3046f7dSMichael Pfeiffer 					delete fGoToPageMenu->RemoveItem(0L);
715cd6b5cdeSAxel Dörfler 				}
7166c305411SMatthew Wilber 
717780d8a62SMichael Pfeiffer 				for (int32 i = 1; i <= pages; i++) {
7186c305411SMatthew Wilber 					// Fill Go To page submenu with an entry for each page
719cd6b5cdeSAxel Dörfler 					BMessage* goTo = new BMessage(MSG_GOTO_PAGE);
720cd6b5cdeSAxel Dörfler 					goTo->AddInt32("page", i);
7216163f333SKarsten Heimrich 
7226163f333SKarsten Heimrich 					char shortcut = 0;
723cd6b5cdeSAxel Dörfler 					if (i < 10)
724780d8a62SMichael Pfeiffer 						shortcut = '0' + i;
7256163f333SKarsten Heimrich 
7266163f333SKarsten Heimrich 					BString strCaption;
7276163f333SKarsten Heimrich 					strCaption << i;
7286163f333SKarsten Heimrich 
729cd6b5cdeSAxel Dörfler 					BMenuItem* item = new BMenuItem(strCaption.String(), goTo,
730*a8199d69Sthreedeyes 						shortcut, B_SHIFT_KEY);
731cd6b5cdeSAxel Dörfler 					if (currentPage == i)
732efa8b4f3SAxel Dörfler 						item->SetMarked(true);
733efa8b4f3SAxel Dörfler 					fGoToPageMenu->AddItem(item);
7346c305411SMatthew Wilber 				}
7356c305411SMatthew Wilber 			} else {
7366c305411SMatthew Wilber 				// Make sure the correct page is marked
737cd6b5cdeSAxel Dörfler 				BMenuItem* currentItem = fGoToPageMenu->ItemAt(currentPage - 1);
738cd6b5cdeSAxel Dörfler 				if (currentItem != NULL && !currentItem->IsMarked())
739cd6b5cdeSAxel Dörfler 					currentItem->SetMarked(true);
7406c305411SMatthew Wilber 			}
7416c305411SMatthew Wilber 
742cd6b5cdeSAxel Dörfler 			_UpdateStatusText(message);
743b9767a83SAxel Dörfler 
744b9767a83SAxel Dörfler 			BPath path(fImageView->Image());
745b9767a83SAxel Dörfler 			SetTitle(path.Path());
7466db01936SAxel Dörfler 			break;
7476db01936SAxel Dörfler 		}
74803839579SMatthew Wilber 
7496db01936SAxel Dörfler 		case MSG_UPDATE_STATUS_TEXT:
7506db01936SAxel Dörfler 		{
751cd6b5cdeSAxel Dörfler 			_UpdateStatusText(message);
7526db01936SAxel Dörfler 			break;
7536db01936SAxel Dörfler 		}
7548f5fd23fSRyan Leavengood 
7556db01936SAxel Dörfler 		case MSG_SELECTION:
7566db01936SAxel Dörfler 		{
7578ad30bcfSMatthew Wilber 			// The view sends this message when a selection is
7588ad30bcfSMatthew Wilber 			// made or the selection is cleared so that the window
7598ad30bcfSMatthew Wilber 			// can update the state of the appropriate menu items
7606db01936SAxel Dörfler 			bool enable;
7616db01936SAxel Dörfler 			if (message->FindBool("has_selection", &enable) == B_OK) {
7626db01936SAxel Dörfler 				_EnableMenuItem(fBar, B_COPY, enable);
7636db01936SAxel Dörfler 				_EnableMenuItem(fBar, MSG_CLEAR_SELECT, enable);
7648ad30bcfSMatthew Wilber 			}
7656db01936SAxel Dörfler 			break;
7666db01936SAxel Dörfler 		}
7678ad30bcfSMatthew Wilber 
7686db01936SAxel Dörfler 		case MSG_UNDO_STATE:
7696db01936SAxel Dörfler 		{
7706db01936SAxel Dörfler 			bool enable;
7716db01936SAxel Dörfler 			if (message->FindBool("can_undo", &enable) == B_OK)
7726db01936SAxel Dörfler 				_EnableMenuItem(fBar, B_UNDO, enable);
7736db01936SAxel Dörfler 			break;
7746db01936SAxel Dörfler 		}
775402c09e5SMatthew Wilber 
77613afa642SPhil Greenway 		case B_UNDO:
7777598450eSMatthew Wilber 			fImageView->Undo();
77813afa642SPhil Greenway 			break;
7796163f333SKarsten Heimrich 
78013afa642SPhil Greenway 		case B_COPY:
781d3046f7dSMichael Pfeiffer 			fImageView->CopySelectionToClipboard();
78213afa642SPhil Greenway 			break;
7836163f333SKarsten Heimrich 
7846db01936SAxel Dörfler 		case MSG_SELECTION_MODE:
785cf0d8308SStephan Aßmus 		{
786cf0d8308SStephan Aßmus 			bool selectionMode = _ToggleMenuItem(MSG_SELECTION_MODE);
787cf0d8308SStephan Aßmus 			fImageView->SetSelectionMode(selectionMode);
788cf0d8308SStephan Aßmus 			if (!selectionMode)
789cf0d8308SStephan Aßmus 				fImageView->ClearSelection();
7906db01936SAxel Dörfler 			break;
791cf0d8308SStephan Aßmus 		}
7926db01936SAxel Dörfler 
79313afa642SPhil Greenway 		case MSG_CLEAR_SELECT:
794d3046f7dSMichael Pfeiffer 			fImageView->ClearSelection();
79513afa642SPhil Greenway 			break;
7966163f333SKarsten Heimrich 
79713afa642SPhil Greenway 		case MSG_SELECT_ALL:
798d3046f7dSMichael Pfeiffer 			fImageView->SelectAll();
79913afa642SPhil Greenway 			break;
80013afa642SPhil Greenway 
80103839579SMatthew Wilber 		case MSG_PAGE_FIRST:
802b9767a83SAxel Dörfler 			if (_ClosePrompt() && fNavigator.FirstPage())
803b9767a83SAxel Dörfler 				_LoadImage();
80403839579SMatthew Wilber 			break;
80503839579SMatthew Wilber 
80603839579SMatthew Wilber 		case MSG_PAGE_LAST:
807b9767a83SAxel Dörfler 			if (_ClosePrompt() && fNavigator.LastPage())
808b9767a83SAxel Dörfler 				_LoadImage();
80903839579SMatthew Wilber 			break;
81003839579SMatthew Wilber 
81103839579SMatthew Wilber 		case MSG_PAGE_NEXT:
812b9767a83SAxel Dörfler 			if (_ClosePrompt() && fNavigator.NextPage())
813b9767a83SAxel Dörfler 				_LoadImage();
81403839579SMatthew Wilber 			break;
81503839579SMatthew Wilber 
81603839579SMatthew Wilber 		case MSG_PAGE_PREV:
817b9767a83SAxel Dörfler 			if (_ClosePrompt() && fNavigator.PreviousPage())
818b9767a83SAxel Dörfler 				_LoadImage();
81903839579SMatthew Wilber 			break;
82003839579SMatthew Wilber 
821cd6b5cdeSAxel Dörfler 		case MSG_GOTO_PAGE:
822cd6b5cdeSAxel Dörfler 		{
823fd952aefSRyan Leavengood 			if (!_ClosePrompt())
824ee7b4f39SMatthew Wilber 				break;
825ee7b4f39SMatthew Wilber 
8266163f333SKarsten Heimrich 			int32 newPage;
8276163f333SKarsten Heimrich 			if (message->FindInt32("page", &newPage) != B_OK)
8286163f333SKarsten Heimrich 				break;
8296163f333SKarsten Heimrich 
830cd6b5cdeSAxel Dörfler 			int32 currentPage = fNavigator.CurrentPage();
831cd6b5cdeSAxel Dörfler 			int32 pages = fNavigator.PageCount();
8326c305411SMatthew Wilber 
833b9767a83SAxel Dörfler 			// TODO: use radio mode instead!
8346c305411SMatthew Wilber 			if (newPage > 0 && newPage <= pages) {
835cd6b5cdeSAxel Dörfler 				BMenuItem* currentItem = fGoToPageMenu->ItemAt(currentPage - 1);
836cd6b5cdeSAxel Dörfler 				BMenuItem* newItem = fGoToPageMenu->ItemAt(newPage - 1);
837cd6b5cdeSAxel Dörfler 				if (currentItem != NULL && newItem != NULL) {
838cd6b5cdeSAxel Dörfler 					currentItem->SetMarked(false);
839cd6b5cdeSAxel Dörfler 					newItem->SetMarked(true);
840b9767a83SAxel Dörfler 					if (fNavigator.GoToPage(newPage))
841b9767a83SAxel Dörfler 						_LoadImage();
8426c305411SMatthew Wilber 				}
8436c305411SMatthew Wilber 			}
844cd6b5cdeSAxel Dörfler 			break;
845cd6b5cdeSAxel Dörfler 		}
8466c305411SMatthew Wilber 
847e2069723SAxel Dörfler 		case kMsgFitToWindow:
848e2069723SAxel Dörfler 			fImageView->FitToBounds();
84919c76de4SMichael Pfeiffer 			break;
8506163f333SKarsten Heimrich 
851e2069723SAxel Dörfler 		case kMsgStretchToWindow:
852e2069723SAxel Dörfler 			fImageView->SetStretchToBounds(
853e2069723SAxel Dörfler 				_ToggleMenuItem(kMsgStretchToWindow));
8547eca0987SMichael Pfeiffer 			break;
8557eca0987SMichael Pfeiffer 
8567eca0987SMichael Pfeiffer 		case MSG_FILE_PREV:
857b9767a83SAxel Dörfler 			if (_ClosePrompt() && fNavigator.PreviousFile())
858a569816bSAxel Dörfler 				_LoadImage(false);
8597eca0987SMichael Pfeiffer 			break;
8607eca0987SMichael Pfeiffer 
8617eca0987SMichael Pfeiffer 		case MSG_FILE_NEXT:
8624aa63633SAxel Dörfler 		case kMsgNextSlide:
863b9767a83SAxel Dörfler 			if (_ClosePrompt() && fNavigator.NextFile())
864b9767a83SAxel Dörfler 				_LoadImage();
86513afa642SPhil Greenway 			break;
86613afa642SPhil Greenway 
867328932acSAxel Dörfler 		case kMsgDeleteCurrentFile:
868b9767a83SAxel Dörfler 		{
869b9767a83SAxel Dörfler 			if (fNavigator.MoveFileToTrash())
870b9767a83SAxel Dörfler 				_LoadImage();
871b9767a83SAxel Dörfler 			else
872328932acSAxel Dörfler 				PostMessage(B_QUIT_REQUESTED);
873328932acSAxel Dörfler 			break;
874b9767a83SAxel Dörfler 		}
875328932acSAxel Dörfler 
876bf461dbeSMatthew Wilber 		case MSG_ROTATE_90:
877d3046f7dSMichael Pfeiffer 			fImageView->Rotate(90);
878ad13f387SMichael Pfeiffer 			break;
8796163f333SKarsten Heimrich 
880bf461dbeSMatthew Wilber 		case MSG_ROTATE_270:
881d3046f7dSMichael Pfeiffer 			fImageView->Rotate(270);
882ad13f387SMichael Pfeiffer 			break;
8836163f333SKarsten Heimrich 
88469eee339SRyan Leavengood 		case MSG_FLIP_LEFT_TO_RIGHT:
88561ddc257SRyan Leavengood 			fImageView->Flip(true);
886ad13f387SMichael Pfeiffer 			break;
8876163f333SKarsten Heimrich 
88869eee339SRyan Leavengood 		case MSG_FLIP_TOP_TO_BOTTOM:
88961ddc257SRyan Leavengood 			fImageView->Flip(false);
890ad13f387SMichael Pfeiffer 			break;
8916163f333SKarsten Heimrich 
8921076d97bSAxel Dörfler 		case MSG_SLIDE_SHOW:
8931076d97bSAxel Dörfler 		{
89494fd9498SStephan Aßmus 			bool fullScreen = false;
89594fd9498SStephan Aßmus 			message->FindBool("full screen", &fullScreen);
896a877c0e7SStephan Aßmus 
8976163f333SKarsten Heimrich 			BMenuItem* item = fBar->FindItem(message->what);
8984aa63633SAxel Dörfler 			if (item == NULL)
899ee7b4f39SMatthew Wilber 				break;
9004aa63633SAxel Dörfler 
901ee7b4f39SMatthew Wilber 			if (item->IsMarked()) {
902ee7b4f39SMatthew Wilber 				item->SetMarked(false);
9034aa63633SAxel Dörfler 				_StopSlideShow();
90494fd9498SStephan Aßmus 				fToolBarView->SetActionPressed(MSG_SLIDE_SHOW, false);
905fd952aefSRyan Leavengood 			} else if (_ClosePrompt()) {
906ee7b4f39SMatthew Wilber 				item->SetMarked(true);
90794fd9498SStephan Aßmus 				if (!fFullScreen && fullScreen)
90894fd9498SStephan Aßmus 					_ToggleFullScreen();
9094aa63633SAxel Dörfler 				_StartSlideShow();
91094fd9498SStephan Aßmus 				fToolBarView->SetActionPressed(MSG_SLIDE_SHOW, true);
911ad13f387SMichael Pfeiffer 			}
9121076d97bSAxel Dörfler 			break;
9131076d97bSAxel Dörfler 		}
914ee7b4f39SMatthew Wilber 
9154aa63633SAxel Dörfler 		case kMsgStopSlideShow:
9164aa63633SAxel Dörfler 		{
9174aa63633SAxel Dörfler 			BMenuItem* item = fBar->FindItem(MSG_SLIDE_SHOW);
9184aa63633SAxel Dörfler 			if (item != NULL)
9194aa63633SAxel Dörfler 				item->SetMarked(false);
9204aa63633SAxel Dörfler 
9214aa63633SAxel Dörfler 			_StopSlideShow();
92294fd9498SStephan Aßmus 			fToolBarView->SetActionPressed(MSG_SLIDE_SHOW, false);
9234aa63633SAxel Dörfler 			break;
9244aa63633SAxel Dörfler 		}
9254aa63633SAxel Dörfler 
9261076d97bSAxel Dörfler 		case MSG_SLIDE_SHOW_DELAY:
9271076d97bSAxel Dörfler 		{
9284aa63633SAxel Dörfler 			bigtime_t delay;
9294aa63633SAxel Dörfler 			if (message->FindInt64("delay", &delay) == B_OK) {
9304aa63633SAxel Dörfler 				_SetSlideShowDelay(delay);
931da87390fSMichael Pfeiffer 				// in case message is sent from popup menu
9324aa63633SAxel Dörfler 				_MarkSlideShowDelay(delay);
933ad13f387SMichael Pfeiffer 			}
9341076d97bSAxel Dörfler 			break;
9351076d97bSAxel Dörfler 		}
936ad13f387SMichael Pfeiffer 
937ad13f387SMichael Pfeiffer 		case MSG_FULL_SCREEN:
938fd952aefSRyan Leavengood 			_ToggleFullScreen();
939ad13f387SMichael Pfeiffer 			break;
9406163f333SKarsten Heimrich 
941fc5ca95dSStephan Aßmus 		case MSG_EXIT_FULL_SCREEN:
942fc5ca95dSStephan Aßmus 			if (fFullScreen)
943fd952aefSRyan Leavengood 				_ToggleFullScreen();
944fc5ca95dSStephan Aßmus 			break;
9456163f333SKarsten Heimrich 
946cf0d8308SStephan Aßmus 		case MSG_SHOW_CAPTION:
947cf0d8308SStephan Aßmus 		{
948fd952aefSRyan Leavengood 			fShowCaption = _ToggleMenuItem(message->what);
949efa8b4f3SAxel Dörfler 			ShowImageSettings* settings = my_app->Settings();
950efa8b4f3SAxel Dörfler 
951d3046f7dSMichael Pfeiffer 			if (settings->Lock()) {
952d3046f7dSMichael Pfeiffer 				settings->SetBool("ShowCaption", fShowCaption);
953d3046f7dSMichael Pfeiffer 				settings->Unlock();
954d3046f7dSMichael Pfeiffer 			}
955efa8b4f3SAxel Dörfler 			if (fFullScreen)
956d3046f7dSMichael Pfeiffer 				fImageView->SetShowCaption(fShowCaption);
9576163f333SKarsten Heimrich 		}	break;
958ad13f387SMichael Pfeiffer 
959780d8a62SMichael Pfeiffer 		case MSG_PAGE_SETUP:
960fd952aefSRyan Leavengood 			_PageSetup();
961780d8a62SMichael Pfeiffer 			break;
9626163f333SKarsten Heimrich 
963780d8a62SMichael Pfeiffer 		case MSG_PREPARE_PRINT:
964fd952aefSRyan Leavengood 			_PrepareForPrint();
965780d8a62SMichael Pfeiffer 			break;
9666163f333SKarsten Heimrich 
967780d8a62SMichael Pfeiffer 		case MSG_PRINT:
968fd952aefSRyan Leavengood 			_Print(message);
969780d8a62SMichael Pfeiffer 			break;
970780d8a62SMichael Pfeiffer 
971780d8a62SMichael Pfeiffer 		case MSG_ZOOM_IN:
972d3046f7dSMichael Pfeiffer 			fImageView->ZoomIn();
973780d8a62SMichael Pfeiffer 			break;
9746163f333SKarsten Heimrich 
975780d8a62SMichael Pfeiffer 		case MSG_ZOOM_OUT:
976d3046f7dSMichael Pfeiffer 			fImageView->ZoomOut();
977780d8a62SMichael Pfeiffer 			break;
9786163f333SKarsten Heimrich 
979e2069723SAxel Dörfler 		case kMsgOriginalSize:
9804fd570d3SAxel Dörfler 			fImageView->SetZoom(1.0);
981780d8a62SMichael Pfeiffer 			break;
9826163f333SKarsten Heimrich 
98381b9c776SMichael Pfeiffer 		case MSG_SCALE_BILINEAR:
984fd952aefSRyan Leavengood 			fImageView->SetScaleBilinear(_ToggleMenuItem(message->what));
98581b9c776SMichael Pfeiffer 			break;
986780d8a62SMichael Pfeiffer 
987cd6b5cdeSAxel Dörfler 		case MSG_DESKTOP_BACKGROUND:
988cd6b5cdeSAxel Dörfler 		{
9899617074cSRyan Leavengood 			BMessage backgroundsMessage(B_REFS_RECEIVED);
9909617074cSRyan Leavengood 			backgroundsMessage.AddRef("refs", fImageView->Image());
9910a74004cSRyan Leavengood 			// This is used in the Backgrounds code for scaled placement
9929617074cSRyan Leavengood 			backgroundsMessage.AddInt32("placement", 'scpl');
993537a273cSHumdinger 			be_roster->Launch("application/x-vnd.haiku-backgrounds",
994537a273cSHumdinger 				&backgroundsMessage);
995cd6b5cdeSAxel Dörfler 			break;
996cd6b5cdeSAxel Dörfler 		}
997a60adbf9SAxel Dörfler 
9985b76e505SStephan Aßmus 		case MSG_SET_RATING:
9995b76e505SStephan Aßmus 		{
10005b76e505SStephan Aßmus 			int32 rating;
10015b76e505SStephan Aßmus 			if (message->FindInt32("rating", &rating) != B_OK)
10025b76e505SStephan Aßmus 				break;
10035b76e505SStephan Aßmus 			BFile file(&fNavigator.CurrentRef(), B_WRITE_ONLY);
10045b76e505SStephan Aßmus 			if (file.InitCheck() != B_OK)
10055b76e505SStephan Aßmus 				break;
10065b76e505SStephan Aßmus 			file.WriteAttr("Media:Rating", B_INT32_TYPE, 0, &rating,
10075b76e505SStephan Aßmus 				sizeof(rating));
10085b76e505SStephan Aßmus 			_UpdateRatingMenu();
10095b76e505SStephan Aßmus 			break;
10105b76e505SStephan Aßmus 		}
10115b76e505SStephan Aßmus 
1012cf0d8308SStephan Aßmus 		case kMsgToggleToolBar:
1013cf0d8308SStephan Aßmus 		{
1014cf0d8308SStephan Aßmus 			fShowToolBar = _ToggleMenuItem(message->what);
101594fd9498SStephan Aßmus 			_SetToolBarVisible(fShowToolBar, true);
1016cf0d8308SStephan Aßmus 
1017cf0d8308SStephan Aßmus 			ShowImageSettings* settings = my_app->Settings();
1018cf0d8308SStephan Aßmus 
1019cf0d8308SStephan Aßmus 			if (settings->Lock()) {
1020cf0d8308SStephan Aßmus 				settings->SetBool("ShowToolBar", fShowToolBar);
1021cf0d8308SStephan Aßmus 				settings->Unlock();
1022cf0d8308SStephan Aßmus 			}
1023cf0d8308SStephan Aßmus 			break;
1024cf0d8308SStephan Aßmus 		}
102594fd9498SStephan Aßmus 		case kShowToolBarIfEnabled:
102694fd9498SStephan Aßmus 		{
102794fd9498SStephan Aßmus 			bool show;
102894fd9498SStephan Aßmus 			if (message->FindBool("show", &show) != B_OK)
102994fd9498SStephan Aßmus 				break;
103094fd9498SStephan Aßmus 			_SetToolBarVisible(fShowToolBar && show, true);
103194fd9498SStephan Aßmus 			break;
103294fd9498SStephan Aßmus 		}
103394fd9498SStephan Aßmus 		case kMsgSlideToolBar:
103494fd9498SStephan Aßmus 		{
103594fd9498SStephan Aßmus 			float offset;
103694fd9498SStephan Aßmus 			if (message->FindFloat("offset", &offset) == B_OK) {
103794fd9498SStephan Aßmus 				fToolBarView->MoveBy(0, offset);
103894fd9498SStephan Aßmus 				fScrollView->ResizeBy(0, -offset);
103994fd9498SStephan Aßmus 				fScrollView->MoveBy(0, offset);
104094fd9498SStephan Aßmus 				fVerticalScrollBar->ResizeBy(0, -offset);
104194fd9498SStephan Aßmus 				fVerticalScrollBar->MoveBy(0, offset);
104294fd9498SStephan Aßmus 				UpdateIfNeeded();
104394fd9498SStephan Aßmus 				snooze(15000);
104494fd9498SStephan Aßmus 			}
104594fd9498SStephan Aßmus 			break;
104694fd9498SStephan Aßmus 		}
104794fd9498SStephan Aßmus 		case kMsgFinishSlidingToolBar:
104894fd9498SStephan Aßmus 		{
104994fd9498SStephan Aßmus 			float offset;
105094fd9498SStephan Aßmus 			bool show;
105194fd9498SStephan Aßmus 			if (message->FindFloat("offset", &offset) == B_OK
105294fd9498SStephan Aßmus 				&& message->FindBool("show", &show) == B_OK) {
105394fd9498SStephan Aßmus 				// Compensate rounding errors with the final placement
1054537a273cSHumdinger 				if (show)
105594fd9498SStephan Aßmus 					fToolBarView->MoveTo(fToolBarView->Frame().left, 0);
1056537a273cSHumdinger 				else {
105794fd9498SStephan Aßmus 					fToolBarView->MoveTo(fToolBarView->Frame().left, offset);
105894fd9498SStephan Aßmus 					fToolBarView->Hide();
105994fd9498SStephan Aßmus 				}
106094fd9498SStephan Aßmus 				BRect frame = fToolBarView->Parent()->Bounds();
106194fd9498SStephan Aßmus 				frame.top = fToolBarView->Frame().bottom + 1;
10622804cb33SRyan Leavengood 				fScrollView->MoveTo(fScrollView->Frame().left, frame.top);
106394fd9498SStephan Aßmus 				fScrollView->ResizeTo(fScrollView->Bounds().Width(),
106494fd9498SStephan Aßmus 					frame.Height() - B_H_SCROLL_BAR_HEIGHT + 1);
106594fd9498SStephan Aßmus 				fVerticalScrollBar->MoveTo(
106694fd9498SStephan Aßmus 					frame.right - B_V_SCROLL_BAR_WIDTH + 1, frame.top);
106794fd9498SStephan Aßmus 				fVerticalScrollBar->ResizeTo(
106894fd9498SStephan Aßmus 					fVerticalScrollBar->Bounds().Width(),
106994fd9498SStephan Aßmus 					frame.Height() - B_H_SCROLL_BAR_HEIGHT + 1);
107094fd9498SStephan Aßmus 			}
107194fd9498SStephan Aßmus 			break;
107294fd9498SStephan Aßmus 		}
1073cf0d8308SStephan Aßmus 
107413afa642SPhil Greenway 		default:
1075efa8b4f3SAxel Dörfler 			BWindow::MessageReceived(message);
107613afa642SPhil Greenway 			break;
107713afa642SPhil Greenway 	}
107813afa642SPhil Greenway }
1079fc0a275bSMatthew Wilber 
1080efa8b4f3SAxel Dörfler 
1081fc0a275bSMatthew Wilber void
1082cd6b5cdeSAxel Dörfler ShowImageWindow::_UpdateStatusText(const BMessage* message)
1083cd6b5cdeSAxel Dörfler {
1084cd6b5cdeSAxel Dörfler 	BString status;
1085cd6b5cdeSAxel Dörfler 	if (fImageView->Bitmap() != NULL) {
1086cd6b5cdeSAxel Dörfler 		BRect bounds = fImageView->Bitmap()->Bounds();
1087cd6b5cdeSAxel Dörfler 		status << bounds.IntegerWidth() + 1
1088cd6b5cdeSAxel Dörfler 			<< "x" << bounds.IntegerHeight() + 1 << ", " << fImageType;
1089cd6b5cdeSAxel Dörfler 	}
1090cd6b5cdeSAxel Dörfler 
1091cd6b5cdeSAxel Dörfler 	BString text;
1092cd6b5cdeSAxel Dörfler 	if (message != NULL && message->FindString("status", &text) == B_OK
1093cd6b5cdeSAxel Dörfler 		&& text.Length() > 0) {
1094cd6b5cdeSAxel Dörfler 		status << ", " << text;
1095cd6b5cdeSAxel Dörfler 	}
1096cd6b5cdeSAxel Dörfler 
1097b9767a83SAxel Dörfler 	fStatusView->Update(fNavigator.CurrentRef(), status);
1098cd6b5cdeSAxel Dörfler }
1099cd6b5cdeSAxel Dörfler 
1100cd6b5cdeSAxel Dörfler 
1101cd6b5cdeSAxel Dörfler void
1102cd6b5cdeSAxel Dörfler ShowImageWindow::_LoadError(const entry_ref& ref)
1103cd6b5cdeSAxel Dörfler {
1104cd6b5cdeSAxel Dörfler 	// TODO: give a better error message!
1105560ff447SJonas Sundström 	BAlert* alert = new BAlert(B_TRANSLATE_SYSTEM_NAME("ShowImage"),
1106546208a5SOliver Tappe 		B_TRANSLATE_CONTEXT("Could not load image! Either the "
1107ddcb5a2cSAxel Dörfler 			"file or an image translator for it does not exist.",
1108ddcb5a2cSAxel Dörfler 			"LoadAlerts"),
1109546208a5SOliver Tappe 		B_TRANSLATE_CONTEXT("OK", "Alerts"), NULL, NULL,
1110cd6b5cdeSAxel Dörfler 		B_WIDTH_AS_USUAL, B_INFO_ALERT);
1111aed35104SHumdinger 	alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
1112cd6b5cdeSAxel Dörfler 	alert->Go();
1113cd6b5cdeSAxel Dörfler }
1114cd6b5cdeSAxel Dörfler 
1115cd6b5cdeSAxel Dörfler 
1116cd6b5cdeSAxel Dörfler void
1117fd952aefSRyan Leavengood ShowImageWindow::_SaveAs(BMessage* message)
1118fc0a275bSMatthew Wilber {
1119cdb89ebbSMatthew Wilber 	// Read the translator and output type the user chose
1120cdb89ebbSMatthew Wilber 	translator_id outTranslator;
1121cdb89ebbSMatthew Wilber 	uint32 outType;
11226163f333SKarsten Heimrich 	if (message->FindInt32(kTranslatorField,
1123efa8b4f3SAxel Dörfler 			reinterpret_cast<int32 *>(&outTranslator)) != B_OK
11246163f333SKarsten Heimrich 		|| message->FindInt32(kTypeField,
1125cdb89ebbSMatthew Wilber 			reinterpret_cast<int32 *>(&outType)) != B_OK)
1126fc0a275bSMatthew Wilber 		return;
1127fc0a275bSMatthew Wilber 
1128cdb89ebbSMatthew Wilber 	// Add the chosen translator and output type to the
1129cdb89ebbSMatthew Wilber 	// message that the save panel will send back
1130c1a10c14SKarsten Heimrich 	BMessage panelMsg(MSG_SAVE_PANEL);
1131c1a10c14SKarsten Heimrich 	panelMsg.AddInt32(kTranslatorField, outTranslator);
1132c1a10c14SKarsten Heimrich 	panelMsg.AddInt32(kTypeField, outType);
1133cdb89ebbSMatthew Wilber 
1134cdb89ebbSMatthew Wilber 	// Create save panel and show it
11356163f333SKarsten Heimrich 	BMessenger target(this);
1136efa8b4f3SAxel Dörfler 	fSavePanel = new (std::nothrow) BFilePanel(B_SAVE_PANEL,
1137c1a10c14SKarsten Heimrich 		&target, NULL, 0, false, &panelMsg);
1138d3046f7dSMichael Pfeiffer 	if (!fSavePanel)
1139fc0a275bSMatthew Wilber 		return;
1140a60adbf9SAxel Dörfler 
1141d3046f7dSMichael Pfeiffer 	fSavePanel->Window()->SetWorkspaces(B_CURRENT_WORKSPACE);
1142d3046f7dSMichael Pfeiffer 	fSavePanel->Show();
1143fc0a275bSMatthew Wilber }
1144fc0a275bSMatthew Wilber 
1145efa8b4f3SAxel Dörfler 
1146fc0a275bSMatthew Wilber void
1147fd952aefSRyan Leavengood ShowImageWindow::_SaveToFile(BMessage* message)
1148fc0a275bSMatthew Wilber {
1149cdb89ebbSMatthew Wilber 	// Read in where the file should be saved
1150efa8b4f3SAxel Dörfler 	entry_ref dirRef;
1151efa8b4f3SAxel Dörfler 	if (message->FindRef("directory", &dirRef) != B_OK)
1152fc0a275bSMatthew Wilber 		return;
1153efa8b4f3SAxel Dörfler 
1154fc0a275bSMatthew Wilber 	const char* filename;
1155efa8b4f3SAxel Dörfler 	if (message->FindString("name", &filename) != B_OK)
1156fc0a275bSMatthew Wilber 		return;
1157fc0a275bSMatthew Wilber 
1158cdb89ebbSMatthew Wilber 	// Read in the translator and type to be used
1159cdb89ebbSMatthew Wilber 	// to save the output image
1160cdb89ebbSMatthew Wilber 	translator_id outTranslator;
1161cdb89ebbSMatthew Wilber 	uint32 outType;
11626163f333SKarsten Heimrich 	if (message->FindInt32(kTranslatorField,
1163efa8b4f3SAxel Dörfler 			reinterpret_cast<int32 *>(&outTranslator)) != B_OK
11646163f333SKarsten Heimrich 		|| message->FindInt32(kTypeField,
1165cdb89ebbSMatthew Wilber 			reinterpret_cast<int32 *>(&outType)) != B_OK)
1166cdb89ebbSMatthew Wilber 		return;
1167cdb89ebbSMatthew Wilber 
1168a7e78e3bSMatthew Wilber 	// Find the translator_format information needed to
1169a7e78e3bSMatthew Wilber 	// write a MIME attribute for the image file
1170a7e78e3bSMatthew Wilber 	BTranslatorRoster* roster = BTranslatorRoster::Default();
1171efa8b4f3SAxel Dörfler 	const translation_format* outFormat = NULL;
1172efa8b4f3SAxel Dörfler 	int32 outCount = 0;
1173efa8b4f3SAxel Dörfler 	if (roster->GetOutputFormats(outTranslator, &outFormat, &outCount) != B_OK
1174efa8b4f3SAxel Dörfler 		|| outCount < 1)
1175a7e78e3bSMatthew Wilber 		return;
1176efa8b4f3SAxel Dörfler 
1177a7e78e3bSMatthew Wilber 	int32 i;
1178efa8b4f3SAxel Dörfler 	for (i = 0; i < outCount; i++) {
1179537a273cSHumdinger 		if (outFormat[i].group == B_TRANSLATOR_BITMAP && outFormat[i].type
1180537a273cSHumdinger 				== outType)
1181a7e78e3bSMatthew Wilber 			break;
1182a7e78e3bSMatthew Wilber 	}
1183efa8b4f3SAxel Dörfler 	if (i == outCount)
1184fc0a275bSMatthew Wilber 		return;
1185fc0a275bSMatthew Wilber 
1186a7e78e3bSMatthew Wilber 	// Write out the image file
1187efa8b4f3SAxel Dörfler 	BDirectory dir(&dirRef);
1188efa8b4f3SAxel Dörfler 	fImageView->SaveToFile(&dir, filename, NULL, &outFormat[i]);
1189fc0a275bSMatthew Wilber }
1190fc0a275bSMatthew Wilber 
1191efa8b4f3SAxel Dörfler 
1192546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT
1193546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "ClosePrompt"
11941ed4535fSStephan Aßmus 
1195b9767a83SAxel Dörfler 
1196cdb89ebbSMatthew Wilber bool
1197fd952aefSRyan Leavengood ShowImageWindow::_ClosePrompt()
1198ee7b4f39SMatthew Wilber {
1199ee7b4f39SMatthew Wilber 	if (!fModified)
1200ee7b4f39SMatthew Wilber 		return true;
1201efa8b4f3SAxel Dörfler 
1202cd6b5cdeSAxel Dörfler 	int32 count = fNavigator.PageCount();
1203cd6b5cdeSAxel Dörfler 	int32 page = fNavigator.CurrentPage();
1204cd6b5cdeSAxel Dörfler 	BString prompt;
1205efa8b4f3SAxel Dörfler 
12061ed4535fSStephan Aßmus 	if (count > 1) {
12071ed4535fSStephan Aßmus 		bs_printf(&prompt,
1208905c8c8cSMatt Madia 			B_TRANSLATE("The document '%s' (page %d) has been changed. Do you "
1209905c8c8cSMatt Madia 				"want to close the document?"),
1210cd6b5cdeSAxel Dörfler 			fImageView->Image()->name, page);
12111ed4535fSStephan Aßmus 	} else {
12121ed4535fSStephan Aßmus 		bs_printf(&prompt,
1213905c8c8cSMatt Madia 			B_TRANSLATE("The document '%s' has been changed. Do you want to "
1214905c8c8cSMatt Madia 				"close the document?"),
1215cd6b5cdeSAxel Dörfler 			fImageView->Image()->name);
12161ed4535fSStephan Aßmus 	}
12171ed4535fSStephan Aßmus 
1218cd6b5cdeSAxel Dörfler 	BAlert* alert = new BAlert(B_TRANSLATE("Close document"), prompt.String(),
1219905c8c8cSMatt Madia 		B_TRANSLATE("Cancel"), B_TRANSLATE("Close"));
1220aed35104SHumdinger 	alert->SetShortcut(0, B_ESCAPE);
1221aed35104SHumdinger 
1222cd6b5cdeSAxel Dörfler 	if (alert->Go() == 0) {
1223ee7b4f39SMatthew Wilber 		// Cancel
1224ee7b4f39SMatthew Wilber 		return false;
1225cd6b5cdeSAxel Dörfler 	}
1226cd6b5cdeSAxel Dörfler 
1227ee7b4f39SMatthew Wilber 	// Close
1228187f0b8aSMatthew Wilber 	fModified = false;
1229ee7b4f39SMatthew Wilber 	return true;
1230ee7b4f39SMatthew Wilber }
1231ee7b4f39SMatthew Wilber 
1232cdb89ebbSMatthew Wilber 
1233b9767a83SAxel Dörfler status_t
1234a569816bSAxel Dörfler ShowImageWindow::_LoadImage(bool forward)
1235b9767a83SAxel Dörfler {
1236b9767a83SAxel Dörfler 	BMessenger us(this);
1237a569816bSAxel Dörfler 	status_t status = ImageCache::Default().RetrieveImage(
1238a569816bSAxel Dörfler 		fNavigator.CurrentRef(), fNavigator.CurrentPage(), &us);
1239a569816bSAxel Dörfler 	if (status != B_OK)
1240a569816bSAxel Dörfler 		return status;
1241a569816bSAxel Dörfler 
1242e2069723SAxel Dörfler 	fProgressWindow->Start(this);
1243e2069723SAxel Dörfler 
1244a569816bSAxel Dörfler 	// Preload previous/next images - two in the navigation direction, one
1245a569816bSAxel Dörfler 	// in the opposite direction.
1246a569816bSAxel Dörfler 
1247a569816bSAxel Dörfler 	entry_ref nextRef = fNavigator.CurrentRef();
1248a569816bSAxel Dörfler 	if (_PreloadImage(forward, nextRef))
1249a569816bSAxel Dörfler 		_PreloadImage(forward, nextRef);
1250a569816bSAxel Dörfler 
1251a569816bSAxel Dörfler 	entry_ref previousRef = fNavigator.CurrentRef();
1252a569816bSAxel Dörfler 	_PreloadImage(!forward, previousRef);
1253a569816bSAxel Dörfler 
1254a569816bSAxel Dörfler 	return B_OK;
1255a569816bSAxel Dörfler }
1256a569816bSAxel Dörfler 
1257a569816bSAxel Dörfler 
1258a569816bSAxel Dörfler bool
1259a569816bSAxel Dörfler ShowImageWindow::_PreloadImage(bool forward, entry_ref& ref)
1260a569816bSAxel Dörfler {
1261a569816bSAxel Dörfler 	entry_ref currentRef = ref;
1262a569816bSAxel Dörfler 	if ((forward && !fNavigator.GetNextFile(currentRef, ref))
1263a569816bSAxel Dörfler 		|| (!forward && !fNavigator.GetPreviousFile(currentRef, ref)))
1264a569816bSAxel Dörfler 		return false;
1265a569816bSAxel Dörfler 
1266a569816bSAxel Dörfler 	return ImageCache::Default().RetrieveImage(ref) == B_OK;
1267b9767a83SAxel Dörfler }
1268b9767a83SAxel Dörfler 
1269b9767a83SAxel Dörfler 
1270ad13f387SMichael Pfeiffer void
1271fd952aefSRyan Leavengood ShowImageWindow::_ToggleFullScreen()
1272ad13f387SMichael Pfeiffer {
1273ad13f387SMichael Pfeiffer 	BRect frame;
1274ad13f387SMichael Pfeiffer 	fFullScreen = !fFullScreen;
1275ad13f387SMichael Pfeiffer 	if (fFullScreen) {
1276ad13f387SMichael Pfeiffer 		BScreen screen;
1277ad13f387SMichael Pfeiffer 		fWindowFrame = Frame();
1278ad13f387SMichael Pfeiffer 		frame = screen.Frame();
1279d3046f7dSMichael Pfeiffer 		frame.top -= fBar->Bounds().Height() + 1;
128067eb2a04SHumdinger 		frame.right += B_V_SCROLL_BAR_WIDTH;
1281ad13f387SMichael Pfeiffer 		frame.bottom += B_H_SCROLL_BAR_HEIGHT;
1282ad13f387SMichael Pfeiffer 		frame.InsetBy(-1, -1); // PEN_SIZE in ShowImageView
1283ad13f387SMichael Pfeiffer 
1284ad13f387SMichael Pfeiffer 		SetFlags(Flags() | B_NOT_RESIZABLE | B_NOT_MOVABLE);
1285c0b16687SAxel Dörfler 
1286c0b16687SAxel Dörfler 		Activate();
1287c0b16687SAxel Dörfler 			// make the window frontmost
1288ad13f387SMichael Pfeiffer 	} else {
1289ad13f387SMichael Pfeiffer 		frame = fWindowFrame;
1290ad13f387SMichael Pfeiffer 
1291ad13f387SMichael Pfeiffer 		SetFlags(Flags() & ~(B_NOT_RESIZABLE | B_NOT_MOVABLE));
1292ad13f387SMichael Pfeiffer 	}
1293efa8b4f3SAxel Dörfler 
129494fd9498SStephan Aßmus 	fToolBarView->SetActionVisible(MSG_FULL_SCREEN, fFullScreen);
1295cf0d8308SStephan Aßmus 	_SetToolBarVisible(!fFullScreen && fShowToolBar);
1296cf0d8308SStephan Aßmus 
1297ad13f387SMichael Pfeiffer 	MoveTo(frame.left, frame.top);
1298ad13f387SMichael Pfeiffer 	ResizeTo(frame.Width(), frame.Height());
1299e2069723SAxel Dörfler 
1300e2069723SAxel Dörfler 	fImageView->SetHideIdlingCursor(fFullScreen);
1301e2069723SAxel Dörfler 	fImageView->SetShowCaption(fFullScreen && fShowCaption);
1302eaa910c5SAxel Dörfler 
130348ae3e38SAxel Dörfler 	Layout(false);
130448ae3e38SAxel Dörfler 		// We need to manually relayout here, as the views are layouted
130548ae3e38SAxel Dörfler 		// asynchronously, and FitToBounds() would still have the wrong size
1306e2069723SAxel Dörfler 	fImageView->FitToBounds();
1307ad13f387SMichael Pfeiffer }
1308ad13f387SMichael Pfeiffer 
1309efa8b4f3SAxel Dörfler 
1310d3046f7dSMichael Pfeiffer void
13112281340dSAxel Dörfler ShowImageWindow::_ApplySettings()
1312d3046f7dSMichael Pfeiffer {
1313efa8b4f3SAxel Dörfler 	ShowImageSettings* settings = my_app->Settings();
1314efa8b4f3SAxel Dörfler 
1315d3046f7dSMichael Pfeiffer 	if (settings->Lock()) {
1316d3046f7dSMichael Pfeiffer 		fShowCaption = settings->GetBool("ShowCaption", fShowCaption);
1317d3046f7dSMichael Pfeiffer 		fPrintOptions.SetBounds(BRect(0, 0, 1023, 767));
1318d3046f7dSMichael Pfeiffer 
13194aa63633SAxel Dörfler 		fSlideShowDelay = settings->GetTime("SlideShowDelay", fSlideShowDelay);
1320d3046f7dSMichael Pfeiffer 
13214aa63633SAxel Dörfler 		fPrintOptions.SetOption((enum PrintOptions::Option)settings->GetInt32(
13224aa63633SAxel Dörfler 			"PO:Option", fPrintOptions.Option()));
13234aa63633SAxel Dörfler 		fPrintOptions.SetZoomFactor(
13244aa63633SAxel Dörfler 			settings->GetFloat("PO:ZoomFactor", fPrintOptions.ZoomFactor()));
13254aa63633SAxel Dörfler 		fPrintOptions.SetDPI(settings->GetFloat("PO:DPI", fPrintOptions.DPI()));
13264aa63633SAxel Dörfler 		fPrintOptions.SetWidth(
13274aa63633SAxel Dörfler 			settings->GetFloat("PO:Width", fPrintOptions.Width()));
13284aa63633SAxel Dörfler 		fPrintOptions.SetHeight(
13294aa63633SAxel Dörfler 			settings->GetFloat("PO:Height", fPrintOptions.Height()));
1330d3046f7dSMichael Pfeiffer 
1331cf0d8308SStephan Aßmus 		fShowToolBar = settings->GetBool("ShowToolBar", fShowToolBar);
1332cf0d8308SStephan Aßmus 
1333d3046f7dSMichael Pfeiffer 		settings->Unlock();
1334d3046f7dSMichael Pfeiffer 	}
1335d3046f7dSMichael Pfeiffer }
1336d3046f7dSMichael Pfeiffer 
1337efa8b4f3SAxel Dörfler 
1338d3046f7dSMichael Pfeiffer void
1339fd952aefSRyan Leavengood ShowImageWindow::_SavePrintOptions()
1340d3046f7dSMichael Pfeiffer {
1341efa8b4f3SAxel Dörfler 	ShowImageSettings* settings = my_app->Settings();
1342efa8b4f3SAxel Dörfler 
1343d3046f7dSMichael Pfeiffer 	if (settings->Lock()) {
1344d3046f7dSMichael Pfeiffer 		settings->SetInt32("PO:Option", fPrintOptions.Option());
1345d3046f7dSMichael Pfeiffer 		settings->SetFloat("PO:ZoomFactor", fPrintOptions.ZoomFactor());
1346d3046f7dSMichael Pfeiffer 		settings->SetFloat("PO:DPI", fPrintOptions.DPI());
1347d3046f7dSMichael Pfeiffer 		settings->SetFloat("PO:Width", fPrintOptions.Width());
1348d3046f7dSMichael Pfeiffer 		settings->SetFloat("PO:Height", fPrintOptions.Height());
1349d3046f7dSMichael Pfeiffer 		settings->Unlock();
1350d3046f7dSMichael Pfeiffer 	}
1351d3046f7dSMichael Pfeiffer }
1352d3046f7dSMichael Pfeiffer 
1353efa8b4f3SAxel Dörfler 
1354cdb89ebbSMatthew Wilber bool
1355fd952aefSRyan Leavengood ShowImageWindow::_PageSetup()
1356780d8a62SMichael Pfeiffer {
1357cd6b5cdeSAxel Dörfler 	BPrintJob printJob(fImageView->Image()->name);
1358efa8b4f3SAxel Dörfler 	if (fPrintSettings != NULL)
1359780d8a62SMichael Pfeiffer 		printJob.SetSettings(new BMessage(*fPrintSettings));
1360efa8b4f3SAxel Dörfler 
13616163f333SKarsten Heimrich 	status_t status = printJob.ConfigPage();
13626163f333SKarsten Heimrich 	if (status == B_OK) {
1363780d8a62SMichael Pfeiffer 		delete fPrintSettings;
1364780d8a62SMichael Pfeiffer 		fPrintSettings = printJob.Settings();
1365780d8a62SMichael Pfeiffer 	}
1366efa8b4f3SAxel Dörfler 
13676163f333SKarsten Heimrich 	return status == B_OK;
1368780d8a62SMichael Pfeiffer }
1369780d8a62SMichael Pfeiffer 
1370efa8b4f3SAxel Dörfler 
1371780d8a62SMichael Pfeiffer void
1372fd952aefSRyan Leavengood ShowImageWindow::_PrepareForPrint()
1373780d8a62SMichael Pfeiffer {
13746163f333SKarsten Heimrich 	if (fPrintSettings == NULL) {
1375cd6b5cdeSAxel Dörfler 		BPrintJob printJob(fImageView->Image()->name);
13766163f333SKarsten Heimrich 		if (printJob.ConfigJob() == B_OK)
13776163f333SKarsten Heimrich 			fPrintSettings = printJob.Settings();
13786163f333SKarsten Heimrich 	}
1379780d8a62SMichael Pfeiffer 
1380cd6b5cdeSAxel Dörfler 	fPrintOptions.SetBounds(fImageView->Bitmap()->Bounds());
1381cd6b5cdeSAxel Dörfler 	fPrintOptions.SetWidth(fImageView->Bitmap()->Bounds().Width() + 1);
1382780d8a62SMichael Pfeiffer 
1383efa8b4f3SAxel Dörfler 	new PrintOptionsWindow(BPoint(Frame().left + 30, Frame().top + 50),
1384efa8b4f3SAxel Dörfler 		&fPrintOptions, this);
1385780d8a62SMichael Pfeiffer }
1386780d8a62SMichael Pfeiffer 
1387efa8b4f3SAxel Dörfler 
1388780d8a62SMichael Pfeiffer void
1389fd952aefSRyan Leavengood ShowImageWindow::_Print(BMessage* msg)
1390780d8a62SMichael Pfeiffer {
1391780d8a62SMichael Pfeiffer 	status_t st;
1392efa8b4f3SAxel Dörfler 	if (msg->FindInt32("status", &st) != B_OK || st != B_OK)
1393780d8a62SMichael Pfeiffer 		return;
1394780d8a62SMichael Pfeiffer 
1395fd952aefSRyan Leavengood 	_SavePrintOptions();
1396d3046f7dSMichael Pfeiffer 
1397cd6b5cdeSAxel Dörfler 	BPrintJob printJob(fImageView->Image()->name);
13986163f333SKarsten Heimrich 	if (fPrintSettings)
1399780d8a62SMichael Pfeiffer 		printJob.SetSettings(new BMessage(*fPrintSettings));
14006163f333SKarsten Heimrich 
1401780d8a62SMichael Pfeiffer 	if (printJob.ConfigJob() == B_OK) {
14026163f333SKarsten Heimrich 		delete fPrintSettings;
14036163f333SKarsten Heimrich 		fPrintSettings = printJob.Settings();
1404780d8a62SMichael Pfeiffer 
1405780d8a62SMichael Pfeiffer 		// first/lastPage is unused for now
14063177ae77SStefano Ceccherini 		int32 firstPage = printJob.FirstPage();
14073177ae77SStefano Ceccherini 		int32 lastPage = printJob.LastPage();
14086163f333SKarsten Heimrich 		BRect printableRect = printJob.PrintableRect();
14096163f333SKarsten Heimrich 
1410efa8b4f3SAxel Dörfler 		if (firstPage < 1)
1411780d8a62SMichael Pfeiffer 			firstPage = 1;
1412efa8b4f3SAxel Dörfler 		if (lastPage < firstPage)
1413780d8a62SMichael Pfeiffer 			lastPage = firstPage;
1414780d8a62SMichael Pfeiffer 
1415cd6b5cdeSAxel Dörfler 		BBitmap* bitmap = fImageView->Bitmap();
14163177ae77SStefano Ceccherini 		float imageWidth = bitmap->Bounds().Width() + 1.0;
14173177ae77SStefano Ceccherini 		float imageHeight = bitmap->Bounds().Height() + 1.0;
1418780d8a62SMichael Pfeiffer 
14196163f333SKarsten Heimrich 		float width;
1420780d8a62SMichael Pfeiffer 		switch (fPrintOptions.Option()) {
14216163f333SKarsten Heimrich 			case PrintOptions::kFitToPage: {
14226163f333SKarsten Heimrich 				float w1 = printableRect.Width() + 1;
1423cd6b5cdeSAxel Dörfler 				float w2 = imageWidth * (printableRect.Height() + 1)
1424cd6b5cdeSAxel Dörfler 					/ imageHeight;
1425efa8b4f3SAxel Dörfler 				if (w2 < w1)
1426780d8a62SMichael Pfeiffer 					width = w2;
1427efa8b4f3SAxel Dörfler 				else
1428780d8a62SMichael Pfeiffer 					width = w1;
14296163f333SKarsten Heimrich 			}	break;
1430780d8a62SMichael Pfeiffer 			case PrintOptions::kZoomFactor:
1431780d8a62SMichael Pfeiffer 				width = imageWidth * fPrintOptions.ZoomFactor();
1432780d8a62SMichael Pfeiffer 				break;
1433780d8a62SMichael Pfeiffer 			case PrintOptions::kDPI:
1434780d8a62SMichael Pfeiffer 				width = imageWidth * 72.0 / fPrintOptions.DPI();
1435780d8a62SMichael Pfeiffer 				break;
1436780d8a62SMichael Pfeiffer 			case PrintOptions::kWidth:
1437780d8a62SMichael Pfeiffer 			case PrintOptions::kHeight:
1438780d8a62SMichael Pfeiffer 				width = fPrintOptions.Width();
1439780d8a62SMichael Pfeiffer 				break;
1440efa8b4f3SAxel Dörfler 
1441780d8a62SMichael Pfeiffer 			default:
1442780d8a62SMichael Pfeiffer 				// keep compiler silent; should not reach here
1443780d8a62SMichael Pfeiffer 				width = imageWidth;
1444780d8a62SMichael Pfeiffer 		}
1445780d8a62SMichael Pfeiffer 
1446efa8b4f3SAxel Dörfler 		// TODO: eventually print large images on several pages
1447780d8a62SMichael Pfeiffer 		printJob.BeginJob();
1448d3046f7dSMichael Pfeiffer 		fImageView->SetScale(width / imageWidth);
14495eb50e46SMichael Pfeiffer 		// coordinates are relative to printable rectangle
14505eb50e46SMichael Pfeiffer 		BRect bounds(bitmap->Bounds());
14515eb50e46SMichael Pfeiffer 		printJob.DrawView(fImageView, bounds, BPoint(0, 0));
1452d3046f7dSMichael Pfeiffer 		fImageView->SetScale(1.0);
1453780d8a62SMichael Pfeiffer 		printJob.SpoolPage();
1454780d8a62SMichael Pfeiffer 		printJob.CommitJob();
1455780d8a62SMichael Pfeiffer 	}
1456780d8a62SMichael Pfeiffer }
1457780d8a62SMichael Pfeiffer 
145856b0c7b9SKarsten Heimrich 
14594aa63633SAxel Dörfler void
14604aa63633SAxel Dörfler ShowImageWindow::_SetSlideShowDelay(bigtime_t delay)
14614aa63633SAxel Dörfler {
14624aa63633SAxel Dörfler 	if (fSlideShowDelay == delay)
14634aa63633SAxel Dörfler 		return;
14644aa63633SAxel Dörfler 
14654aa63633SAxel Dörfler 	fSlideShowDelay = delay;
14664aa63633SAxel Dörfler 
14674aa63633SAxel Dörfler 	ShowImageSettings* settings = my_app->Settings();
14684aa63633SAxel Dörfler 	if (settings->Lock()) {
14694aa63633SAxel Dörfler 		settings->SetTime("SlideShowDelay", fSlideShowDelay);
14704aa63633SAxel Dörfler 		settings->Unlock();
14714aa63633SAxel Dörfler 	}
14724aa63633SAxel Dörfler 
14734aa63633SAxel Dörfler 	if (fSlideShowRunner != NULL)
14744aa63633SAxel Dörfler 		_StartSlideShow();
14754aa63633SAxel Dörfler }
14764aa63633SAxel Dörfler 
14774aa63633SAxel Dörfler 
14784aa63633SAxel Dörfler void
14794aa63633SAxel Dörfler ShowImageWindow::_StartSlideShow()
14804aa63633SAxel Dörfler {
14814aa63633SAxel Dörfler 	_StopSlideShow();
14824aa63633SAxel Dörfler 
14834aa63633SAxel Dörfler 	BMessage nextSlide(kMsgNextSlide);
14844aa63633SAxel Dörfler 	fSlideShowRunner = new BMessageRunner(this, &nextSlide, fSlideShowDelay);
14854aa63633SAxel Dörfler }
14864aa63633SAxel Dörfler 
14874aa63633SAxel Dörfler 
14884aa63633SAxel Dörfler void
14894aa63633SAxel Dörfler ShowImageWindow::_StopSlideShow()
14904aa63633SAxel Dörfler {
14914aa63633SAxel Dörfler 	if (fSlideShowRunner != NULL) {
14924aa63633SAxel Dörfler 		delete fSlideShowRunner;
14934aa63633SAxel Dörfler 		fSlideShowRunner = NULL;
14944aa63633SAxel Dörfler 	}
14954aa63633SAxel Dörfler }
14964aa63633SAxel Dörfler 
14974aa63633SAxel Dörfler 
14985b76e505SStephan Aßmus void
14995b76e505SStephan Aßmus ShowImageWindow::_UpdateRatingMenu()
15005b76e505SStephan Aßmus {
15015b76e505SStephan Aßmus 	BFile file(&fNavigator.CurrentRef(), B_READ_ONLY);
15025b76e505SStephan Aßmus 	if (file.InitCheck() != B_OK)
15035b76e505SStephan Aßmus 		return;
15045b76e505SStephan Aßmus 	int32 rating;
15055b76e505SStephan Aßmus 	ssize_t size = sizeof(rating);
15065b76e505SStephan Aßmus 	if (file.ReadAttr("Media:Rating", B_INT32_TYPE, 0, &rating, size) != size)
15075b76e505SStephan Aßmus 		rating = 0;
15085b76e505SStephan Aßmus 	// TODO: Finding the correct item could be more robust, like by looking
15095b76e505SStephan Aßmus 	// at the message of each item.
15105b76e505SStephan Aßmus 	for (int32 i = 1; i <= 10; i++) {
15115b76e505SStephan Aßmus 		BMenuItem* item = fRatingMenu->ItemAt(i - 1);
15125b76e505SStephan Aßmus 		if (item == NULL)
15135b76e505SStephan Aßmus 			break;
15145b76e505SStephan Aßmus 		item->SetMarked(i == rating);
15155b76e505SStephan Aßmus 	}
15165b76e505SStephan Aßmus }
15175b76e505SStephan Aßmus 
15185b76e505SStephan Aßmus 
1519cf0d8308SStephan Aßmus void
152094fd9498SStephan Aßmus ShowImageWindow::_SetToolBarVisible(bool visible, bool animate)
1521cf0d8308SStephan Aßmus {
1522cf0d8308SStephan Aßmus 	if (visible == !fToolBarView->IsHidden())
1523cf0d8308SStephan Aßmus 		return;
1524cf0d8308SStephan Aßmus 
152594fd9498SStephan Aßmus 	float diff = fToolBarView->Bounds().Height() + 2;
152694fd9498SStephan Aßmus 	if (!visible)
1527cf0d8308SStephan Aßmus 		diff = -diff;
152894fd9498SStephan Aßmus 	else
152994fd9498SStephan Aßmus 		fToolBarView->Show();
1530cf0d8308SStephan Aßmus 
153194fd9498SStephan Aßmus 	if (animate) {
153294fd9498SStephan Aßmus 		// Slide the controls into view. We do this with messages in order
153394fd9498SStephan Aßmus 		// not to block the window thread.
153494fd9498SStephan Aßmus 		const float kAnimationOffsets[] = { 0.05, 0.2, 0.5, 0.2, 0.05 };
153594fd9498SStephan Aßmus 		const int32 steps = sizeof(kAnimationOffsets) / sizeof(float);
153694fd9498SStephan Aßmus 		float originalY = fToolBarView->Frame().top;
153794fd9498SStephan Aßmus 		for (int32 i = 0; i < steps; i++) {
153894fd9498SStephan Aßmus 			BMessage message(kMsgSlideToolBar);
153994fd9498SStephan Aßmus 			message.AddFloat("offset", floorf(diff * kAnimationOffsets[i]));
154094fd9498SStephan Aßmus 			PostMessage(&message, this);
154194fd9498SStephan Aßmus 		}
154294fd9498SStephan Aßmus 		BMessage finalMessage(kMsgFinishSlidingToolBar);
154394fd9498SStephan Aßmus 		finalMessage.AddFloat("offset", originalY + diff);
154494fd9498SStephan Aßmus 		finalMessage.AddBool("show", visible);
154594fd9498SStephan Aßmus 		PostMessage(&finalMessage, this);
154694fd9498SStephan Aßmus 	} else {
1547cf0d8308SStephan Aßmus 		fScrollView->ResizeBy(0, -diff);
1548cf0d8308SStephan Aßmus 		fScrollView->MoveBy(0, diff);
1549cf0d8308SStephan Aßmus 		fVerticalScrollBar->ResizeBy(0, -diff);
1550cf0d8308SStephan Aßmus 		fVerticalScrollBar->MoveBy(0, diff);
1551162e5c80SRyan Leavengood 		fToolBarView->MoveBy(0, diff);
155294fd9498SStephan Aßmus 		if (!visible)
155394fd9498SStephan Aßmus 			fToolBarView->Hide();
155494fd9498SStephan Aßmus 	}
1555cf0d8308SStephan Aßmus }
1556cf0d8308SStephan Aßmus 
1557cf0d8308SStephan Aßmus 
1558780d8a62SMichael Pfeiffer bool
1559cdb89ebbSMatthew Wilber ShowImageWindow::QuitRequested()
1560cdb89ebbSMatthew Wilber {
1561efa8b4f3SAxel Dörfler 	if (fSavePanel) {
1562efa8b4f3SAxel Dörfler 		// Don't allow this window to be closed if a save panel is open
1563efa8b4f3SAxel Dörfler 		return false;
1564cdb89ebbSMatthew Wilber 	}
1565cdb89ebbSMatthew Wilber 
15665b76e505SStephan Aßmus 	if (!_ClosePrompt())
15675b76e505SStephan Aßmus 		return false;
15685b76e505SStephan Aßmus 
15695b76e505SStephan Aßmus 	ShowImageSettings* settings = my_app->Settings();
15705b76e505SStephan Aßmus 	if (settings->Lock()) {
1571c418e2beSStephan Aßmus 		if (fFullScreen)
1572c418e2beSStephan Aßmus 			settings->SetRect("WindowFrame", fWindowFrame);
1573c418e2beSStephan Aßmus 		else
15745b76e505SStephan Aßmus 			settings->SetRect("WindowFrame", Frame());
15755b76e505SStephan Aßmus 		settings->Unlock();
15765b76e505SStephan Aßmus 	}
15775b76e505SStephan Aßmus 
15785b76e505SStephan Aßmus 	be_app->PostMessage(MSG_WINDOW_HAS_QUIT);
15795b76e505SStephan Aßmus 
15805b76e505SStephan Aßmus 	return true;
1581efa8b4f3SAxel Dörfler }
1582