xref: /haiku/src/apps/showimage/ShowImageWindow.cpp (revision c1994be81793e18b7b46c03137a6d765d9267c9f)
1efa8b4f3SAxel Dörfler /*
2d5647665SHumdinger  * Copyright 2003-2014, 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>
28554e2073SAdrien Destugues #include <Button.h>
291ed4535fSStephan Aßmus #include <Catalog.h>
30efa8b4f3SAxel Dörfler #include <Clipboard.h>
3160c23976SJanus #include <ControlLook.h>
3203ad73fcSAdrien Destugues #include <DurationFormat.h>
3313afa642SPhil Greenway #include <Entry.h>
34fc0a275bSMatthew Wilber #include <File.h>
356163f333SKarsten Heimrich #include <FilePanel.h>
361ed4535fSStephan Aßmus #include <Locale.h>
3713afa642SPhil Greenway #include <Menu.h>
3813afa642SPhil Greenway #include <MenuBar.h>
3913afa642SPhil Greenway #include <MenuItem.h>
404aa63633SAxel Dörfler #include <MessageRunner.h>
4113afa642SPhil Greenway #include <Path.h>
42efa8b4f3SAxel Dörfler #include <PrintJob.h>
4336272f0dSAxel Dörfler #include <RecentItems.h>
44efa8b4f3SAxel Dörfler #include <Roster.h>
45efa8b4f3SAxel Dörfler #include <Screen.h>
4613afa642SPhil Greenway #include <ScrollView.h>
476163f333SKarsten Heimrich #include <String.h>
48efa8b4f3SAxel Dörfler #include <SupportDefs.h>
496163f333SKarsten Heimrich #include <TranslationDefs.h>
5013afa642SPhil Greenway #include <TranslationUtils.h>
5113afa642SPhil Greenway #include <TranslatorRoster.h>
5213afa642SPhil Greenway 
53b9767a83SAxel Dörfler #include "ImageCache.h"
54e2069723SAxel Dörfler #include "ProgressWindow.h"
55fd952aefSRyan Leavengood #include "ShowImageApp.h"
56fd952aefSRyan Leavengood #include "ShowImageConstants.h"
57fd952aefSRyan Leavengood #include "ShowImageStatusView.h"
58fd952aefSRyan Leavengood #include "ShowImageView.h"
59cf0d8308SStephan Aßmus #include "ToolBarIcons.h"
6013afa642SPhil Greenway 
61a8fc7138SMichael Pfeiffer 
62cd6b5cdeSAxel Dörfler // BMessage field names used in Save messages
63cd6b5cdeSAxel Dörfler const char* kTypeField = "be:type";
64cd6b5cdeSAxel Dörfler const char* kTranslatorField = "be:translator";
65cd6b5cdeSAxel Dörfler 
664aa63633SAxel Dörfler const bigtime_t kDefaultSlideShowDelay = 3000000;
674aa63633SAxel Dörfler 	// 3 seconds
684aa63633SAxel Dörfler 
69cd6b5cdeSAxel Dörfler 
70e2069723SAxel Dörfler // message constants
71e2069723SAxel Dörfler enum {
72e2069723SAxel Dörfler 	MSG_CAPTURE_MOUSE			= 'mCPM',
73e2069723SAxel Dörfler 	MSG_CHANGE_FOCUS			= 'mCFS',
74e2069723SAxel Dörfler 	MSG_WINDOW_QUIT				= 'mWQT',
75e2069723SAxel Dörfler 	MSG_OUTPUT_TYPE				= 'BTMN',
76e2069723SAxel Dörfler 	MSG_SAVE_PANEL				= 'mFSP',
77e2069723SAxel Dörfler 	MSG_CLEAR_SELECT			= 'mCSL',
78e2069723SAxel Dörfler 	MSG_SELECT_ALL				= 'mSAL',
79e2069723SAxel Dörfler 	MSG_SELECTION_MODE			= 'mSLM',
80e2069723SAxel Dörfler 	MSG_PAGE_FIRST				= 'mPGF',
81e2069723SAxel Dörfler 	MSG_PAGE_LAST				= 'mPGL',
82e2069723SAxel Dörfler 	MSG_PAGE_NEXT				= 'mPGN',
83e2069723SAxel Dörfler 	MSG_PAGE_PREV				= 'mPGP',
84e2069723SAxel Dörfler 	MSG_GOTO_PAGE				= 'mGTP',
85e2069723SAxel Dörfler 	MSG_ZOOM_IN					= 'mZIN',
86e2069723SAxel Dörfler 	MSG_ZOOM_OUT				= 'mZOU',
87e2069723SAxel Dörfler 	MSG_SCALE_BILINEAR			= 'mSBL',
88e2069723SAxel Dörfler 	MSG_DESKTOP_BACKGROUND		= 'mDBG',
89e2069723SAxel Dörfler 	MSG_ROTATE_90				= 'mR90',
90e2069723SAxel Dörfler 	MSG_ROTATE_270				= 'mR27',
91e2069723SAxel Dörfler 	MSG_FLIP_LEFT_TO_RIGHT		= 'mFLR',
92e2069723SAxel Dörfler 	MSG_FLIP_TOP_TO_BOTTOM		= 'mFTB',
93e2069723SAxel Dörfler 	MSG_SLIDE_SHOW_DELAY		= 'mSSD',
94e2069723SAxel Dörfler 	MSG_SHOW_CAPTION			= 'mSCP',
95e2069723SAxel Dörfler 	MSG_PAGE_SETUP				= 'mPSU',
96e2069723SAxel Dörfler 	MSG_PREPARE_PRINT			= 'mPPT',
975b76e505SStephan Aßmus 	MSG_SET_RATING				= 'mSRT',
98e2069723SAxel Dörfler 	kMsgFitToWindow				= 'mFtW',
99e2069723SAxel Dörfler 	kMsgOriginalSize			= 'mOSZ',
1004aa63633SAxel Dörfler 	kMsgStretchToWindow			= 'mStW',
101cf0d8308SStephan Aßmus 	kMsgNextSlide				= 'mNxS',
10294fd9498SStephan Aßmus 	kMsgToggleToolBar			= 'mTTB',
10394fd9498SStephan Aßmus 	kMsgSlideToolBar			= 'mSTB',
10494fd9498SStephan Aßmus 	kMsgFinishSlidingToolBar	= 'mFST'
105e2069723SAxel Dörfler };
106e2069723SAxel Dörfler 
107e2069723SAxel Dörfler 
108cd6b5cdeSAxel Dörfler // This is temporary solution for building BString with printf like format.
109cd6b5cdeSAxel Dörfler // will be removed in the future.
110cd6b5cdeSAxel Dörfler static void
111cd6b5cdeSAxel Dörfler bs_printf(BString* string, const char* format, ...)
112cd6b5cdeSAxel Dörfler {
113cd6b5cdeSAxel Dörfler 	va_list ap;
114cd6b5cdeSAxel Dörfler 	char* buf;
115cd6b5cdeSAxel Dörfler 
116cd6b5cdeSAxel Dörfler 	va_start(ap, format);
117cd6b5cdeSAxel Dörfler 	vasprintf(&buf, format, ap);
118cd6b5cdeSAxel Dörfler 	string->SetTo(buf);
119cd6b5cdeSAxel Dörfler 	free(buf);
120cd6b5cdeSAxel Dörfler 	va_end(ap);
121cd6b5cdeSAxel Dörfler }
122cd6b5cdeSAxel Dörfler 
123cd6b5cdeSAxel Dörfler 
1246163f333SKarsten Heimrich //	#pragma mark -- ShowImageWindow
1256163f333SKarsten Heimrich 
1266163f333SKarsten Heimrich 
127546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT
128546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "Menus"
129cf0d8308SStephan Aßmus 
130cf0d8308SStephan Aßmus 
1315b76e505SStephan Aßmus ShowImageWindow::ShowImageWindow(BRect frame, const entry_ref& ref,
132efa8b4f3SAxel Dörfler 	const BMessenger& trackerMessenger)
133fd952aefSRyan Leavengood 	:
13494fd9498SStephan Aßmus 	BWindow(frame, "", B_DOCUMENT_WINDOW, B_AUTO_UPDATE_SIZE_LIMITS),
135b9767a83SAxel Dörfler 	fNavigator(ref, trackerMessenger),
136fd952aefSRyan Leavengood 	fSavePanel(NULL),
137fd952aefSRyan Leavengood 	fBar(NULL),
138fd952aefSRyan Leavengood 	fBrowseMenu(NULL),
139fd952aefSRyan Leavengood 	fGoToPageMenu(NULL),
1404aa63633SAxel Dörfler 	fSlideShowDelayMenu(NULL),
14194a4c1c4SAugustin Cavalier 	fToolBar(NULL),
142fd952aefSRyan Leavengood 	fImageView(NULL),
143fd952aefSRyan Leavengood 	fStatusView(NULL),
144e2069723SAxel Dörfler 	fProgressWindow(new ProgressWindow()),
145fd952aefSRyan Leavengood 	fModified(false),
146fd952aefSRyan Leavengood 	fFullScreen(false),
147fd952aefSRyan Leavengood 	fShowCaption(true),
148cf0d8308SStephan Aßmus 	fShowToolBar(true),
1494aa63633SAxel Dörfler 	fPrintSettings(NULL),
1504aa63633SAxel Dörfler 	fSlideShowRunner(NULL),
1514aa63633SAxel Dörfler 	fSlideShowDelay(kDefaultSlideShowDelay)
15213afa642SPhil Greenway {
1532281340dSAxel Dörfler 	_ApplySettings();
154fc0a275bSMatthew Wilber 
15594fd9498SStephan Aßmus 	SetLayout(new BGroupLayout(B_VERTICAL, 0));
15694fd9498SStephan Aßmus 
15713afa642SPhil Greenway 	// create menu bar
15894fd9498SStephan Aßmus 	fBar = new BMenuBar("menu_bar");
159b9767a83SAxel Dörfler 	_AddMenus(fBar);
16094fd9498SStephan Aßmus 	float menuBarMinWidth = fBar->MinSize().width;
161e9dcd874SAxel Dörfler 	AddChild(fBar);
16213afa642SPhil Greenway 
16394fd9498SStephan Aßmus 	// Add a content view so the tool bar can be moved outside of the
16494fd9498SStephan Aßmus 	// visible portion without colliding with the menu bar.
165cf0d8308SStephan Aßmus 
16694fd9498SStephan Aßmus 	BView* contentView = new BView(BRect(), "content", B_FOLLOW_NONE, 0);
16794fd9498SStephan Aßmus 	contentView->SetViewColor(ui_color(B_PANEL_BACKGROUND_COLOR));
16894fd9498SStephan Aßmus 	contentView->SetExplicitMinSize(BSize(250, 100));
16994fd9498SStephan Aßmus 	AddChild(contentView);
17094fd9498SStephan Aßmus 
17194fd9498SStephan Aßmus 	// Create the tool bar
17294fd9498SStephan Aßmus 	BRect viewFrame = contentView->Bounds();
17394fd9498SStephan Aßmus 	viewFrame.right -= B_V_SCROLL_BAR_WIDTH;
17494a4c1c4SAugustin Cavalier 	fToolBar = new BToolBar(viewFrame);
175cf0d8308SStephan Aßmus 
176cf0d8308SStephan Aßmus 	// Add the tool icons.
177cf0d8308SStephan Aßmus 
17894a4c1c4SAugustin Cavalier //	fToolBar->AddAction(MSG_FILE_OPEN, be_app,
179cf0d8308SStephan Aßmus //		tool_bar_icon(kIconDocumentOpen), B_TRANSLATE("Open" B_UTF8_ELLIPSIS));
18094a4c1c4SAugustin Cavalier 	fToolBar->AddAction(MSG_FILE_PREV, this,
181554e2073SAdrien Destugues 		tool_bar_icon(kIconGoPrevious), B_TRANSLATE("Previous file"), false);
18294a4c1c4SAugustin Cavalier 	fToolBar->AddAction(MSG_FILE_NEXT, this, tool_bar_icon(kIconGoNext),
183554e2073SAdrien Destugues 		B_TRANSLATE("Next file"), false);
184a877c0e7SStephan Aßmus 	BMessage* fullScreenSlideShow = new BMessage(MSG_SLIDE_SHOW);
185a877c0e7SStephan Aßmus 	fullScreenSlideShow->AddBool("full screen", true);
18694a4c1c4SAugustin Cavalier 	fToolBar->AddAction(fullScreenSlideShow, this,
187554e2073SAdrien Destugues 		tool_bar_icon(kIconMediaMovieLibrary), B_TRANSLATE("Slide show"),
188554e2073SAdrien Destugues 		false);
18994a4c1c4SAugustin Cavalier 	fToolBar->AddSeparator();
19094a4c1c4SAugustin Cavalier 	fToolBar->AddAction(MSG_SELECTION_MODE, this,
191cf0d8308SStephan Aßmus 		tool_bar_icon(kIconDrawRectangularSelection),
192554e2073SAdrien Destugues 		B_TRANSLATE("Selection mode"), false);
19394a4c1c4SAugustin Cavalier 	fToolBar->AddSeparator();
19494a4c1c4SAugustin Cavalier 	fToolBar->AddAction(kMsgOriginalSize, this,
195554e2073SAdrien Destugues 		tool_bar_icon(kIconZoomOriginal), B_TRANSLATE("Original size"), true);
19694a4c1c4SAugustin Cavalier 	fToolBar->AddAction(kMsgFitToWindow, this,
197554e2073SAdrien Destugues 		tool_bar_icon(kIconZoomFitBest), B_TRANSLATE("Fit to window"), false);
19894a4c1c4SAugustin Cavalier 	fToolBar->AddAction(MSG_ZOOM_IN, this, tool_bar_icon(kIconZoomIn),
199554e2073SAdrien Destugues 		B_TRANSLATE("Zoom in"), false);
20094a4c1c4SAugustin Cavalier 	fToolBar->AddAction(MSG_ZOOM_OUT, this, tool_bar_icon(kIconZoomOut),
201554e2073SAdrien Destugues 		B_TRANSLATE("Zoom out"), false);
202442e457dSGerasim Troeglazov 	fToolBar->AddSeparator();
203442e457dSGerasim Troeglazov 	fToolBar->AddAction(MSG_PAGE_PREV, this, tool_bar_icon(kIconPagePrevious),
204442e457dSGerasim Troeglazov 		B_TRANSLATE("Previous page"), false);
205442e457dSGerasim Troeglazov 	fToolBar->AddAction(MSG_PAGE_NEXT, this, tool_bar_icon(kIconPageNext),
206442e457dSGerasim Troeglazov 		B_TRANSLATE("Next page"), false);
20794a4c1c4SAugustin Cavalier 	fToolBar->AddGlue();
20894a4c1c4SAugustin Cavalier 	fToolBar->AddAction(MSG_FULL_SCREEN, this,
209554e2073SAdrien Destugues 		tool_bar_icon(kIconViewWindowed), B_TRANSLATE("Leave full screen"),
210554e2073SAdrien Destugues 		false);
21194a4c1c4SAugustin Cavalier 	fToolBar->SetActionVisible(MSG_FULL_SCREEN, false);
212cf0d8308SStephan Aßmus 
21394a4c1c4SAugustin Cavalier 	fToolBar->ResizeTo(viewFrame.Width(), fToolBar->MinSize().height);
214cf0d8308SStephan Aßmus 
21594a4c1c4SAugustin Cavalier 	contentView->AddChild(fToolBar);
216cf0d8308SStephan Aßmus 
217cf0d8308SStephan Aßmus 	if (fShowToolBar)
21894a4c1c4SAugustin Cavalier 		viewFrame.top = fToolBar->Frame().bottom + 1;
219cf0d8308SStephan Aßmus 	else
22094a4c1c4SAugustin Cavalier 		fToolBar->Hide();
221cf0d8308SStephan Aßmus 
22295667008SJanus 	fToolBarVisible = fShowToolBar;
22395667008SJanus 
22494fd9498SStephan Aßmus 	viewFrame.bottom = contentView->Bounds().bottom;
22513afa642SPhil Greenway 	viewFrame.bottom -= B_H_SCROLL_BAR_HEIGHT;
22613afa642SPhil Greenway 
22713afa642SPhil Greenway 	// create the image view
228d3046f7dSMichael Pfeiffer 	fImageView = new ShowImageView(viewFrame, "image_view", B_FOLLOW_ALL,
229e2069723SAxel Dörfler 		B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_PULSE_NEEDED
230e2069723SAxel Dörfler 			| B_FRAME_EVENTS);
23113afa642SPhil Greenway 	// wrap a scroll view around the view
232cf0d8308SStephan Aßmus 	fScrollView = new BScrollView("image_scroller", fImageView,
233cae52eadSJanus 		B_FOLLOW_ALL, 0, true, true, B_PLAIN_BORDER);
23494fd9498SStephan Aßmus 	contentView->AddChild(fScrollView);
23513afa642SPhil Greenway 
236cae52eadSJanus 	fStatusView = new ShowImageStatusView(fScrollView);
237cae52eadSJanus 	fScrollView->AddChild(fStatusView);
23813afa642SPhil Greenway 
2399b13c418SStephan Aßmus 	// Update minimum window size
24094a4c1c4SAugustin Cavalier 	float toolBarMinWidth = fToolBar->MinSize().width;
2419b13c418SStephan Aßmus 	SetSizeLimits(std::max(menuBarMinWidth, toolBarMinWidth), 100000, 100,
2429b13c418SStephan Aßmus 		100000);
24313afa642SPhil Greenway 
244134d6076SMichael Pfeiffer 	// finish creating the window
245b9767a83SAxel Dörfler 	if (_LoadImage() != B_OK) {
246ba3217eeSAxel Dörfler 		_LoadError(ref);
2475e09d5dbSRyan Leavengood 		Quit();
24801939af6SAxel Dörfler 		return;
249d10d5947SMichael Pfeiffer 	}
250402c09e5SMatthew Wilber 
251d9f6762dSMichael Pfeiffer 	// add View menu here so it can access ShowImageView methods
252546208a5SOliver Tappe 	BMenu* menu = new BMenu(B_TRANSLATE_CONTEXT("View", "Menus"));
253fd952aefSRyan Leavengood 	_BuildViewMenu(menu, false);
254d9f6762dSMichael Pfeiffer 	fBar->AddItem(menu);
255d9f6762dSMichael Pfeiffer 
2565b76e505SStephan Aßmus 	fBar->AddItem(_BuildRatingMenu());
2575b76e505SStephan Aßmus 
258d9f6762dSMichael Pfeiffer 	SetPulseRate(100000);
259d9f6762dSMichael Pfeiffer 		// every 1/10 second; ShowImageView needs it for marching ants
260d9f6762dSMichael Pfeiffer 
2616db01936SAxel Dörfler 	_MarkMenuItem(menu, MSG_SELECTION_MODE,
2626db01936SAxel Dörfler 		fImageView->IsSelectionModeEnabled());
2636db01936SAxel Dörfler 
264402c09e5SMatthew Wilber 	// Tell application object to query the clipboard
265402c09e5SMatthew Wilber 	// and tell this window if it contains interesting data or not
266402c09e5SMatthew Wilber 	be_app_messenger.SendMessage(B_CLIPBOARD_CHANGED);
267cd6b5cdeSAxel Dörfler 
268cd6b5cdeSAxel Dörfler 	// The window will be shown on screen automatically
269cd6b5cdeSAxel Dörfler 	Run();
27013afa642SPhil Greenway }
27113afa642SPhil Greenway 
272efa8b4f3SAxel Dörfler 
27313afa642SPhil Greenway ShowImageWindow::~ShowImageWindow()
27413afa642SPhil Greenway {
275e2069723SAxel Dörfler 	fProgressWindow->Lock();
276e2069723SAxel Dörfler 	fProgressWindow->Quit();
2774aa63633SAxel Dörfler 
2784aa63633SAxel Dörfler 	_StopSlideShow();
27913afa642SPhil Greenway }
28013afa642SPhil Greenway 
281efa8b4f3SAxel Dörfler 
282cdb89ebbSMatthew Wilber void
283d9f6762dSMichael Pfeiffer ShowImageWindow::BuildContextMenu(BMenu* menu)
284d9f6762dSMichael Pfeiffer {
285fd952aefSRyan Leavengood 	_BuildViewMenu(menu, true);
286d9f6762dSMichael Pfeiffer }
287efa8b4f3SAxel Dörfler 
28856b0c7b9SKarsten Heimrich 
289cdb89ebbSMatthew Wilber void
290fd952aefSRyan Leavengood ShowImageWindow::_BuildViewMenu(BMenu* menu, bool popupMenu)
291da87390fSMichael Pfeiffer {
292905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Slide show"), MSG_SLIDE_SHOW, 0, 0, this);
2934aa63633SAxel Dörfler 	_MarkMenuItem(menu, MSG_SLIDE_SHOW, fSlideShowRunner != NULL);
294905c8c8cSMatt Madia 	BMenu* delayMenu = new BMenu(B_TRANSLATE("Slide delay"));
2954aa63633SAxel Dörfler 	if (fSlideShowDelayMenu == NULL)
2964aa63633SAxel Dörfler 		fSlideShowDelayMenu = delayMenu;
297efa8b4f3SAxel Dörfler 
298efa8b4f3SAxel Dörfler 	delayMenu->SetRadioMode(true);
2994aa63633SAxel Dörfler 
3004aa63633SAxel Dörfler 	int32 kDelays[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 20};
3014aa63633SAxel Dörfler 	for (uint32 i = 0; i < sizeof(kDelays) / sizeof(kDelays[0]); i++) {
30203ad73fcSAdrien Destugues 		BString text;
30303ad73fcSAdrien Destugues 		BDurationFormat format;
30403ad73fcSAdrien Destugues 		text.Truncate(0);
30503ad73fcSAdrien Destugues 		format.Format(text, 0, kDelays[i] * 1000000LL);
3064aa63633SAxel Dörfler 
3074aa63633SAxel Dörfler 		_AddDelayItem(delayMenu, text.String(), kDelays[i] * 1000000LL);
3084aa63633SAxel Dörfler 	}
309efa8b4f3SAxel Dörfler 	menu->AddItem(delayMenu);
31030060f17SMatthew Wilber 
311efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
312efa8b4f3SAxel Dörfler 
313905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Original size"),
314e2069723SAxel Dörfler 		kMsgOriginalSize, '1', 0, this);
315e2069723SAxel Dörfler 	_AddItemMenu(menu, B_TRANSLATE("Fit to window"),
316e2069723SAxel Dörfler 		kMsgFitToWindow, '0', 0, this);
317905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Zoom in"), MSG_ZOOM_IN, '+', 0, this);
318905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Zoom out"), MSG_ZOOM_OUT, '-', 0, this);
319efa8b4f3SAxel Dörfler 
320efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
321efa8b4f3SAxel Dörfler 
3224fd570d3SAxel Dörfler 	if (!popupMenu || fFullScreen) {
323905c8c8cSMatt Madia 		_AddItemMenu(menu, B_TRANSLATE("High-quality zooming"),
324905c8c8cSMatt Madia 			MSG_SCALE_BILINEAR, 0, 0, this);
3254fd570d3SAxel Dörfler 		_AddItemMenu(menu, B_TRANSLATE("Stretch to window"),
326e2069723SAxel Dörfler 			kMsgStretchToWindow, 0, 0, this);
327efa8b4f3SAxel Dörfler 
328efa8b4f3SAxel Dörfler 		menu->AddSeparatorItem();
32932c22143SAxel Dörfler 	}
330efa8b4f3SAxel Dörfler 
331905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Full screen"),
332905c8c8cSMatt Madia 		MSG_FULL_SCREEN, B_ENTER, 0, this);
333fd952aefSRyan Leavengood 	_MarkMenuItem(menu, MSG_FULL_SCREEN, fFullScreen);
334efa8b4f3SAxel Dörfler 
335905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Show caption in full screen mode"),
336905c8c8cSMatt Madia 		MSG_SHOW_CAPTION, 0, 0, this);
337fd952aefSRyan Leavengood 	_MarkMenuItem(menu, MSG_SHOW_CAPTION, fShowCaption);
338efa8b4f3SAxel Dörfler 
339e2069723SAxel Dörfler 	_MarkMenuItem(menu, MSG_SCALE_BILINEAR, fImageView->ScaleBilinear());
340e2069723SAxel Dörfler 	_MarkMenuItem(menu, kMsgStretchToWindow, fImageView->StretchesToBounds());
341a60adbf9SAxel Dörfler 
342cf0d8308SStephan Aßmus 	if (!popupMenu) {
34394fd9498SStephan Aßmus 		_AddItemMenu(menu, B_TRANSLATE("Show tool bar"), kMsgToggleToolBar,
344d5647665SHumdinger 			'B', 0, this);
345cf0d8308SStephan Aßmus 		_MarkMenuItem(menu, kMsgToggleToolBar,
34694a4c1c4SAugustin Cavalier 			!fToolBar->IsHidden(fToolBar));
347cf0d8308SStephan Aßmus 	}
348cf0d8308SStephan Aßmus 
349d9f6762dSMichael Pfeiffer 	if (popupMenu) {
350a60adbf9SAxel Dörfler 		menu->AddSeparatorItem();
351905c8c8cSMatt Madia 		_AddItemMenu(menu, B_TRANSLATE("Use as background" B_UTF8_ELLIPSIS),
3521ed4535fSStephan Aßmus 			MSG_DESKTOP_BACKGROUND, 0, 0, this);
353d9f6762dSMichael Pfeiffer 	}
354da87390fSMichael Pfeiffer }
355da87390fSMichael Pfeiffer 
356efa8b4f3SAxel Dörfler 
3575b76e505SStephan Aßmus BMenu*
3585b76e505SStephan Aßmus ShowImageWindow::_BuildRatingMenu()
3595b76e505SStephan Aßmus {
3605b76e505SStephan Aßmus 	fRatingMenu = new BMenu(B_TRANSLATE("Rating"));
3615b76e505SStephan Aßmus 	for (int32 i = 1; i <= 10; i++) {
3625b76e505SStephan Aßmus 		BString label;
3635b76e505SStephan Aßmus 		label << i;
3645b76e505SStephan Aßmus 		BMessage* message = new BMessage(MSG_SET_RATING);
3655b76e505SStephan Aßmus 		message->AddInt32("rating", i);
3665b76e505SStephan Aßmus 		fRatingMenu->AddItem(new BMenuItem(label.String(), message));
3675b76e505SStephan Aßmus 	}
3685b76e505SStephan Aßmus 	// NOTE: We may want to encapsulate the Rating menu within a more
3695b76e505SStephan Aßmus 	// general "Attributes" menu.
3705b76e505SStephan Aßmus 	return fRatingMenu;
3715b76e505SStephan Aßmus }
3725b76e505SStephan Aßmus 
3735b76e505SStephan Aßmus 
374da87390fSMichael Pfeiffer void
375b9767a83SAxel Dörfler ShowImageWindow::_AddMenus(BMenuBar* bar)
37613afa642SPhil Greenway {
377905c8c8cSMatt Madia 	BMenu* menu = new BMenu(B_TRANSLATE("File"));
37836272f0dSAxel Dörfler 
37936272f0dSAxel Dörfler 	// Add recent files to "Open File" entry as sub-menu.
38036272f0dSAxel Dörfler 	BMenuItem* item = new BMenuItem(BRecentFilesList::NewFileListMenu(
38136272f0dSAxel Dörfler 		B_TRANSLATE("Open" B_UTF8_ELLIPSIS), NULL, NULL, be_app, 10, true,
38236272f0dSAxel Dörfler 		NULL, kApplicationSignature), new BMessage(MSG_FILE_OPEN));
38336272f0dSAxel Dörfler 	item->SetShortcut('O', 0);
38436272f0dSAxel Dörfler 	item->SetTarget(be_app);
38536272f0dSAxel Dörfler 	menu->AddItem(item);
386efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
38736272f0dSAxel Dörfler 
3886db01936SAxel Dörfler 	BMenu* menuSaveAs = new BMenu(B_TRANSLATE("Save as" B_UTF8_ELLIPSIS),
3891ed4535fSStephan Aßmus 		B_ITEMS_IN_COLUMN);
3906db01936SAxel Dörfler 	BTranslationUtils::AddTranslationItems(menuSaveAs, B_TRANSLATOR_BITMAP);
391fc0a275bSMatthew Wilber 		// Fill Save As submenu with all types that can be converted
392fc0a275bSMatthew Wilber 		// to from the Be bitmap image format
3936db01936SAxel Dörfler 	menu->AddItem(menuSaveAs);
394905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Close"), B_QUIT_REQUESTED, 'W', 0, this);
395d5647665SHumdinger 	_AddItemMenu(menu, B_TRANSLATE("Move to Trash"), kMsgDeleteCurrentFile, 'T', 0, this);
396efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
397905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Page setup" B_UTF8_ELLIPSIS),
3981ed4535fSStephan Aßmus 		MSG_PAGE_SETUP, 0, 0, this);
399905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Print" B_UTF8_ELLIPSIS),
4001ed4535fSStephan Aßmus 		MSG_PREPARE_PRINT, 'P', 0, this);
401efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
402905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Quit"), B_QUIT_REQUESTED, 'Q', 0, be_app);
403efa8b4f3SAxel Dörfler 	bar->AddItem(menu);
40413afa642SPhil Greenway 
405905c8c8cSMatt Madia 	menu = new BMenu(B_TRANSLATE("Edit"));
406905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Copy"), B_COPY, 'C', 0, this, false);
407efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
408cf0d8308SStephan Aßmus 	_AddItemMenu(menu, B_TRANSLATE("Selection mode"), MSG_SELECTION_MODE, 0, 0,
4096db01936SAxel Dörfler 		this);
41032c22143SAxel Dörfler 	_AddItemMenu(menu, B_TRANSLATE("Clear selection"),
41132c22143SAxel Dörfler 		MSG_CLEAR_SELECT, 0, 0, this, false);
412905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Select all"),
413905c8c8cSMatt Madia 		MSG_SELECT_ALL, 'A', 0, this);
414efa8b4f3SAxel Dörfler 	bar->AddItem(menu);
41513afa642SPhil Greenway 
416905c8c8cSMatt Madia 	menu = fBrowseMenu = new BMenu(B_TRANSLATE("Browse"));
417905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("First page"),
4181ed4535fSStephan Aßmus 		MSG_PAGE_FIRST, B_LEFT_ARROW, B_SHIFT_KEY, this);
419905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Last page"),
4201ed4535fSStephan Aßmus 		MSG_PAGE_LAST, B_RIGHT_ARROW, B_SHIFT_KEY, this);
421905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Previous page"),
422905c8c8cSMatt Madia 		MSG_PAGE_PREV, B_LEFT_ARROW, 0, this);
423905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Next page"),
424905c8c8cSMatt Madia 		MSG_PAGE_NEXT, B_RIGHT_ARROW, 0, this);
425905c8c8cSMatt Madia 	fGoToPageMenu = new BMenu(B_TRANSLATE("Go to page"));
4265e427b6aSMichael Pfeiffer 	fGoToPageMenu->SetRadioMode(true);
427efa8b4f3SAxel Dörfler 	menu->AddItem(fGoToPageMenu);
428efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
429905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Previous file"),
430905c8c8cSMatt Madia 		MSG_FILE_PREV, B_UP_ARROW, 0, this);
431905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Next file"),
432905c8c8cSMatt Madia 		MSG_FILE_NEXT, B_DOWN_ARROW, 0, this);
433efa8b4f3SAxel Dörfler 	bar->AddItem(menu);
43403839579SMatthew Wilber 
435905c8c8cSMatt Madia 	menu = new BMenu(B_TRANSLATE("Image"));
436905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Rotate clockwise"),
437905c8c8cSMatt Madia 		MSG_ROTATE_90, 'R', 0, this);
438905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Rotate counterclockwise"),
4391ed4535fSStephan Aßmus 		MSG_ROTATE_270, 'R', B_SHIFT_KEY, this);
440efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
441905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Flip left to right"),
4421ed4535fSStephan Aßmus 		MSG_FLIP_LEFT_TO_RIGHT, 0, 0, this);
443905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Flip top to bottom"),
4441ed4535fSStephan Aßmus 		MSG_FLIP_TOP_TO_BOTTOM, 0, 0, this);
445efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
446905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Use as background" B_UTF8_ELLIPSIS),
4471ed4535fSStephan Aßmus 		MSG_DESKTOP_BACKGROUND, 0, 0, this);
44804f96544SAxel Dörfler 
44904f96544SAxel Dörfler 	bar->AddItem(menu);
45013afa642SPhil Greenway }
45113afa642SPhil Greenway 
452efa8b4f3SAxel Dörfler 
453cdb89ebbSMatthew Wilber BMenuItem*
454fd952aefSRyan Leavengood ShowImageWindow::_AddItemMenu(BMenu* menu, const char* label, uint32 what,
4554fd570d3SAxel Dörfler 	char shortcut, uint32 modifier, const BHandler* target, bool enabled)
456cdb89ebbSMatthew Wilber {
4574fd570d3SAxel Dörfler 	BMenuItem* item = new BMenuItem(label, new BMessage(what), shortcut,
4584fd570d3SAxel Dörfler 		modifier);
459efa8b4f3SAxel Dörfler 	menu->AddItem(item);
460efa8b4f3SAxel Dörfler 
4616163f333SKarsten Heimrich 	item->SetTarget(target);
4626163f333SKarsten Heimrich 	item->SetEnabled(enabled);
4636163f333SKarsten Heimrich 
464efa8b4f3SAxel Dörfler 	return item;
46513afa642SPhil Greenway }
46613afa642SPhil Greenway 
467efa8b4f3SAxel Dörfler 
468ad13f387SMichael Pfeiffer BMenuItem*
4694aa63633SAxel Dörfler ShowImageWindow::_AddDelayItem(BMenu* menu, const char* label, bigtime_t delay)
470ad13f387SMichael Pfeiffer {
471efa8b4f3SAxel Dörfler 	BMessage* message = new BMessage(MSG_SLIDE_SHOW_DELAY);
4724aa63633SAxel Dörfler 	message->AddInt64("delay", delay);
473ad13f387SMichael Pfeiffer 
4746163f333SKarsten Heimrich 	BMenuItem* item = new BMenuItem(label, message, 0);
475efa8b4f3SAxel Dörfler 	item->SetTarget(this);
476ad13f387SMichael Pfeiffer 
4774aa63633SAxel Dörfler 	if (delay == fSlideShowDelay)
478efa8b4f3SAxel Dörfler 		item->SetMarked(true);
479ad13f387SMichael Pfeiffer 
480efa8b4f3SAxel Dörfler 	menu->AddItem(item);
481efa8b4f3SAxel Dörfler 	return item;
482ad13f387SMichael Pfeiffer }
483ad13f387SMichael Pfeiffer 
484efa8b4f3SAxel Dörfler 
485cdb89ebbSMatthew Wilber void
486e2069723SAxel Dörfler ShowImageWindow::_ResizeWindowToImage()
48713afa642SPhil Greenway {
488e2069723SAxel Dörfler 	BBitmap* bitmap = fImageView->Bitmap();
489d10d5947SMichael Pfeiffer 	BScreen screen;
490e2069723SAxel Dörfler 	if (bitmap == NULL || !screen.IsValid())
491efa8b4f3SAxel Dörfler 		return;
492efa8b4f3SAxel Dörfler 
4931076d97bSAxel Dörfler 	// TODO: use View::GetPreferredSize() instead?
4941076d97bSAxel Dörfler 	BRect r(bitmap->Bounds());
4951076d97bSAxel Dörfler 	float width = r.Width() + B_V_SCROLL_BAR_WIDTH;
4961076d97bSAxel Dörfler 	float height = r.Height() + 1 + fBar->Frame().Height()
4971076d97bSAxel Dörfler 		+ B_H_SCROLL_BAR_HEIGHT;
498cdb89ebbSMatthew Wilber 
4996163f333SKarsten Heimrich 	BRect frame = screen.Frame();
5006163f333SKarsten Heimrich 	const float windowBorder = 5;
501d10d5947SMichael Pfeiffer 	// dimensions so that window does not reach outside of screen
5026163f333SKarsten Heimrich 	float maxWidth = frame.Width() + 1 - windowBorder - Frame().left;
5036163f333SKarsten Heimrich 	float maxHeight = frame.Height() + 1 - windowBorder - Frame().top;
504cdb89ebbSMatthew Wilber 
505a8fc7138SMichael Pfeiffer 	// We have to check size limits manually, otherwise
506a8fc7138SMichael Pfeiffer 	// menu bar will be too short for small images.
507efa8b4f3SAxel Dörfler 
508fc5ca95dSStephan Aßmus 	float minW, maxW, minH, maxH;
509a8fc7138SMichael Pfeiffer 	GetSizeLimits(&minW, &maxW, &minH, &maxH);
510efa8b4f3SAxel Dörfler 	if (maxWidth > maxW)
511efa8b4f3SAxel Dörfler 		maxWidth = maxW;
512efa8b4f3SAxel Dörfler 	if (maxHeight > maxH)
513efa8b4f3SAxel Dörfler 		maxHeight = maxH;
514efa8b4f3SAxel Dörfler 	if (width < minW)
515efa8b4f3SAxel Dörfler 		width = minW;
516efa8b4f3SAxel Dörfler 	if (height < minH)
517efa8b4f3SAxel Dörfler 		height = minH;
518a8fc7138SMichael Pfeiffer 
519efa8b4f3SAxel Dörfler 	if (width > maxWidth)
520efa8b4f3SAxel Dörfler 		width = maxWidth;
521efa8b4f3SAxel Dörfler 	if (height > maxHeight)
522efa8b4f3SAxel Dörfler 		height = maxHeight;
523d10d5947SMichael Pfeiffer 
524d10d5947SMichael Pfeiffer 	ResizeTo(width, height);
52513afa642SPhil Greenway }
52613afa642SPhil Greenway 
527efa8b4f3SAxel Dörfler 
5287eca0987SMichael Pfeiffer bool
529fd952aefSRyan Leavengood ShowImageWindow::_ToggleMenuItem(uint32 what)
5307eca0987SMichael Pfeiffer {
5317eca0987SMichael Pfeiffer 	bool marked = false;
5326163f333SKarsten Heimrich 	BMenuItem* item = fBar->FindItem(what);
5337eca0987SMichael Pfeiffer 	if (item != NULL) {
5347eca0987SMichael Pfeiffer 		marked = !item->IsMarked();
5357eca0987SMichael Pfeiffer 		item->SetMarked(marked);
5367eca0987SMichael Pfeiffer 	}
53794a4c1c4SAugustin Cavalier 	fToolBar->SetActionPressed(what, marked);
5387eca0987SMichael Pfeiffer 	return marked;
5397eca0987SMichael Pfeiffer }
5407eca0987SMichael Pfeiffer 
541efa8b4f3SAxel Dörfler 
542cdb89ebbSMatthew Wilber void
543fd952aefSRyan Leavengood ShowImageWindow::_EnableMenuItem(BMenu* menu, uint32 what, bool enable)
544e6a50d9cSMichael Pfeiffer {
5456163f333SKarsten Heimrich 	BMenuItem* item = menu->FindItem(what);
5466163f333SKarsten Heimrich 	if (item && item->IsEnabled() != enable)
547e6a50d9cSMichael Pfeiffer 		item->SetEnabled(enable);
54894a4c1c4SAugustin Cavalier 	fToolBar->SetActionEnabled(what, enable);
549e6a50d9cSMichael Pfeiffer }
550e6a50d9cSMichael Pfeiffer 
551efa8b4f3SAxel Dörfler 
552e6a50d9cSMichael Pfeiffer void
553fd952aefSRyan Leavengood ShowImageWindow::_MarkMenuItem(BMenu* menu, uint32 what, bool marked)
554e6a50d9cSMichael Pfeiffer {
5556163f333SKarsten Heimrich 	BMenuItem* item = menu->FindItem(what);
5566163f333SKarsten Heimrich 	if (item && item->IsMarked() != marked)
557e6a50d9cSMichael Pfeiffer 		item->SetMarked(marked);
55894a4c1c4SAugustin Cavalier 	fToolBar->SetActionPressed(what, marked);
559e6a50d9cSMichael Pfeiffer }
560e6a50d9cSMichael Pfeiffer 
561efa8b4f3SAxel Dörfler 
562da87390fSMichael Pfeiffer void
5634aa63633SAxel Dörfler ShowImageWindow::_MarkSlideShowDelay(bigtime_t delay)
564da87390fSMichael Pfeiffer {
5654aa63633SAxel Dörfler 	const int32 count = fSlideShowDelayMenu->CountItems();
5664aa63633SAxel Dörfler 	for (int32 i = 0; i < count; i ++) {
5674aa63633SAxel Dörfler 		BMenuItem* item = fSlideShowDelayMenu->ItemAt(i);
5684aa63633SAxel Dörfler 		if (item != NULL) {
5694aa63633SAxel Dörfler 			bigtime_t itemDelay;
5704aa63633SAxel Dörfler 			if (item->Message()->FindInt64("delay", &itemDelay) == B_OK
5714aa63633SAxel Dörfler 				&& itemDelay == delay) {
572da87390fSMichael Pfeiffer 				item->SetMarked(true);
573da87390fSMichael Pfeiffer 				return;
574da87390fSMichael Pfeiffer 			}
575da87390fSMichael Pfeiffer 		}
576da87390fSMichael Pfeiffer 	}
577da87390fSMichael Pfeiffer }
578e6a50d9cSMichael Pfeiffer 
57919c76de4SMichael Pfeiffer 
58019c76de4SMichael Pfeiffer void
581e2069723SAxel Dörfler ShowImageWindow::Zoom(BPoint origin, float width, float height)
58219c76de4SMichael Pfeiffer {
583e2069723SAxel Dörfler 	_ToggleFullScreen();
58419c76de4SMichael Pfeiffer }
58519c76de4SMichael Pfeiffer 
586efa8b4f3SAxel Dörfler 
587e6a50d9cSMichael Pfeiffer void
588efa8b4f3SAxel Dörfler ShowImageWindow::MessageReceived(BMessage* message)
58913afa642SPhil Greenway {
590e2069723SAxel Dörfler 	if (message->WasDropped()) {
591e2069723SAxel Dörfler 		uint32 type;
592e2069723SAxel Dörfler 		int32 count;
593e2069723SAxel Dörfler 		status_t status = message->GetInfo("refs", &type, &count);
594e2069723SAxel Dörfler 		if (status == B_OK && type == B_REF_TYPE) {
595e2069723SAxel Dörfler 			message->what = B_REFS_RECEIVED;
596e2069723SAxel Dörfler 			be_app->PostMessage(message);
597e2069723SAxel Dörfler 		}
598e2069723SAxel Dörfler 	}
599e2069723SAxel Dörfler 
600efa8b4f3SAxel Dörfler 	switch (message->what) {
601e2069723SAxel Dörfler 		case kMsgImageCacheImageLoaded:
602cd6b5cdeSAxel Dörfler 		{
603e2069723SAxel Dörfler 			fProgressWindow->Stop();
604e2069723SAxel Dörfler 
605df942b3eSAxel Dörfler 			BitmapOwner* bitmapOwner = NULL;
606df942b3eSAxel Dörfler 			message->FindPointer("bitmapOwner", (void**)&bitmapOwner);
607df942b3eSAxel Dörfler 
608cd6b5cdeSAxel Dörfler 			bool first = fImageView->Bitmap() == NULL;
609b9767a83SAxel Dörfler 			entry_ref ref;
610b9767a83SAxel Dörfler 			message->FindRef("ref", &ref);
611b9767a83SAxel Dörfler 			if (!first && ref != fNavigator.CurrentRef()) {
612b9767a83SAxel Dörfler 				// ignore older images
613df942b3eSAxel Dörfler 				if (bitmapOwner != NULL)
614df942b3eSAxel Dörfler 					bitmapOwner->ReleaseReference();
615b9767a83SAxel Dörfler 				break;
616b9767a83SAxel Dörfler 			}
617cd6b5cdeSAxel Dörfler 
618baa27ccbSJanus 			int32 page = message->FindInt32("page");
619baa27ccbSJanus 			int32 pageCount = message->FindInt32("pageCount");
620baa27ccbSJanus 			if (!first && page != fNavigator.CurrentPage()) {
621baa27ccbSJanus 				// ignore older pages
622baa27ccbSJanus 				if (bitmapOwner != NULL)
623baa27ccbSJanus 					bitmapOwner->ReleaseReference();
624baa27ccbSJanus 				break;
625baa27ccbSJanus 			}
626baa27ccbSJanus 
627cd6b5cdeSAxel Dörfler 			status_t status = fImageView->SetImage(message);
628cd6b5cdeSAxel Dörfler 			if (status != B_OK) {
629df942b3eSAxel Dörfler 				if (bitmapOwner != NULL)
630df942b3eSAxel Dörfler 					bitmapOwner->ReleaseReference();
631df942b3eSAxel Dörfler 
632cd6b5cdeSAxel Dörfler 				_LoadError(ref);
633cd6b5cdeSAxel Dörfler 
634cd6b5cdeSAxel Dörfler 				// quit if file could not be opened
635cd6b5cdeSAxel Dörfler 				if (first)
636cd6b5cdeSAxel Dörfler 					Quit();
637cd6b5cdeSAxel Dörfler 				break;
638cd6b5cdeSAxel Dörfler 			}
639cd6b5cdeSAxel Dörfler 
640cd6b5cdeSAxel Dörfler 			fImageType = message->FindString("type");
641baa27ccbSJanus 			fNavigator.SetTo(ref, page, pageCount);
642cd6b5cdeSAxel Dörfler 
643e2069723SAxel Dörfler 			fImageView->FitToBounds();
644cd6b5cdeSAxel Dörfler 			if (first) {
645cd6b5cdeSAxel Dörfler 				fImageView->MakeFocus(true);
646cd6b5cdeSAxel Dörfler 					// to receive key messages
647cd6b5cdeSAxel Dörfler 				Show();
648e2069723SAxel Dörfler 			}
6495b76e505SStephan Aßmus 			_UpdateRatingMenu();
650e62a6973SJanus 			// Set width and height attributes of the currently showed file.
651e62a6973SJanus 			// This should only be a temporary solution.
652e62a6973SJanus 			_SaveWidthAndHeight();
653e2069723SAxel Dörfler 			break;
654e2069723SAxel Dörfler 		}
655e2069723SAxel Dörfler 
656e2069723SAxel Dörfler 		case kMsgImageCacheProgressUpdate:
657e2069723SAxel Dörfler 		{
658e2069723SAxel Dörfler 			entry_ref ref;
659e2069723SAxel Dörfler 			if (message->FindRef("ref", &ref) == B_OK
660e2069723SAxel Dörfler 				&& ref == fNavigator.CurrentRef()) {
661e2069723SAxel Dörfler 				message->what = kMsgProgressUpdate;
662e2069723SAxel Dörfler 				fProgressWindow->PostMessage(message);
663cd6b5cdeSAxel Dörfler 			}
664cd6b5cdeSAxel Dörfler 			break;
665cd6b5cdeSAxel Dörfler 		}
666cd6b5cdeSAxel Dörfler 
667ee7b4f39SMatthew Wilber 		case MSG_MODIFIED:
668ee7b4f39SMatthew Wilber 			// If image has been modified due to a Cut or Paste
669ee7b4f39SMatthew Wilber 			fModified = true;
670ee7b4f39SMatthew Wilber 			break;
671ee7b4f39SMatthew Wilber 
672fc0a275bSMatthew Wilber 		case MSG_OUTPUT_TYPE:
673fc0a275bSMatthew Wilber 			// User clicked Save As then choose an output format
674d3046f7dSMichael Pfeiffer 			if (!fSavePanel)
675cdb89ebbSMatthew Wilber 				// If user doesn't already have a save panel open
676fd952aefSRyan Leavengood 				_SaveAs(message);
67713afa642SPhil Greenway 			break;
678fc0a275bSMatthew Wilber 
679fc0a275bSMatthew Wilber 		case MSG_SAVE_PANEL:
680fc0a275bSMatthew Wilber 			// User specified where to save the output image
681fd952aefSRyan Leavengood 			_SaveToFile(message);
68207caaa8eSMatthew Wilber 			break;
68307caaa8eSMatthew Wilber 
684cdb89ebbSMatthew Wilber 		case B_CANCEL:
685d3046f7dSMichael Pfeiffer 			delete fSavePanel;
686d3046f7dSMichael Pfeiffer 			fSavePanel = NULL;
687cdb89ebbSMatthew Wilber 			break;
688cdb89ebbSMatthew Wilber 
6896db01936SAxel Dörfler 		case MSG_UPDATE_STATUS:
6906db01936SAxel Dörfler 		{
691cd6b5cdeSAxel Dörfler 			int32 pages = fNavigator.PageCount();
692cd6b5cdeSAxel Dörfler 			int32 currentPage = fNavigator.CurrentPage();
6936c305411SMatthew Wilber 
694baa27ccbSJanus 			_EnableMenuItem(fBar, MSG_PAGE_FIRST,
695baa27ccbSJanus 				fNavigator.HasPreviousPage());
696baa27ccbSJanus 			_EnableMenuItem(fBar, MSG_PAGE_LAST, fNavigator.HasNextPage());
697baa27ccbSJanus 			_EnableMenuItem(fBar, MSG_PAGE_NEXT, fNavigator.HasNextPage());
698baa27ccbSJanus 			_EnableMenuItem(fBar, MSG_PAGE_PREV, fNavigator.HasPreviousPage());
699baa27ccbSJanus 			fGoToPageMenu->SetEnabled(pages > 1);
7001d592070SMatthew Wilber 
701cd6b5cdeSAxel Dörfler 			_EnableMenuItem(fBar, MSG_FILE_NEXT, fNavigator.HasNextFile());
702cd6b5cdeSAxel Dörfler 			_EnableMenuItem(fBar, MSG_FILE_PREV, fNavigator.HasPreviousFile());
703134d6076SMichael Pfeiffer 
704d3046f7dSMichael Pfeiffer 			if (fGoToPageMenu->CountItems() != pages) {
7056c305411SMatthew Wilber 				// Only rebuild the submenu if the number of
7066c305411SMatthew Wilber 				// pages is different
7076c305411SMatthew Wilber 
708cd6b5cdeSAxel Dörfler 				while (fGoToPageMenu->CountItems() > 0) {
7096c305411SMatthew Wilber 					// Remove all page numbers
7107f4d1af4SSergei Reznikov 					delete fGoToPageMenu->RemoveItem((int32)0);
711cd6b5cdeSAxel Dörfler 				}
7126c305411SMatthew Wilber 
713780d8a62SMichael Pfeiffer 				for (int32 i = 1; i <= pages; i++) {
7146c305411SMatthew Wilber 					// Fill Go To page submenu with an entry for each page
715cd6b5cdeSAxel Dörfler 					BMessage* goTo = new BMessage(MSG_GOTO_PAGE);
716cd6b5cdeSAxel Dörfler 					goTo->AddInt32("page", i);
7176163f333SKarsten Heimrich 
7186163f333SKarsten Heimrich 					char shortcut = 0;
719cd6b5cdeSAxel Dörfler 					if (i < 10)
720780d8a62SMichael Pfeiffer 						shortcut = '0' + i;
7216163f333SKarsten Heimrich 
7226163f333SKarsten Heimrich 					BString strCaption;
7236163f333SKarsten Heimrich 					strCaption << i;
7246163f333SKarsten Heimrich 
725cd6b5cdeSAxel Dörfler 					BMenuItem* item = new BMenuItem(strCaption.String(), goTo,
726a8199d69Sthreedeyes 						shortcut, B_SHIFT_KEY);
727cd6b5cdeSAxel Dörfler 					if (currentPage == i)
728efa8b4f3SAxel Dörfler 						item->SetMarked(true);
729efa8b4f3SAxel Dörfler 					fGoToPageMenu->AddItem(item);
7306c305411SMatthew Wilber 				}
7316c305411SMatthew Wilber 			} else {
7326c305411SMatthew Wilber 				// Make sure the correct page is marked
733cd6b5cdeSAxel Dörfler 				BMenuItem* currentItem = fGoToPageMenu->ItemAt(currentPage - 1);
734cd6b5cdeSAxel Dörfler 				if (currentItem != NULL && !currentItem->IsMarked())
735cd6b5cdeSAxel Dörfler 					currentItem->SetMarked(true);
7366c305411SMatthew Wilber 			}
7376c305411SMatthew Wilber 
738cd6b5cdeSAxel Dörfler 			_UpdateStatusText(message);
739b9767a83SAxel Dörfler 
740b9767a83SAxel Dörfler 			BPath path(fImageView->Image());
741b9767a83SAxel Dörfler 			SetTitle(path.Path());
7426db01936SAxel Dörfler 			break;
7436db01936SAxel Dörfler 		}
74403839579SMatthew Wilber 
7456db01936SAxel Dörfler 		case MSG_UPDATE_STATUS_TEXT:
7466db01936SAxel Dörfler 		{
747cd6b5cdeSAxel Dörfler 			_UpdateStatusText(message);
7486db01936SAxel Dörfler 			break;
7496db01936SAxel Dörfler 		}
7508f5fd23fSRyan Leavengood 
7516db01936SAxel Dörfler 		case MSG_SELECTION:
7526db01936SAxel Dörfler 		{
7538ad30bcfSMatthew Wilber 			// The view sends this message when a selection is
7548ad30bcfSMatthew Wilber 			// made or the selection is cleared so that the window
7558ad30bcfSMatthew Wilber 			// can update the state of the appropriate menu items
7566db01936SAxel Dörfler 			bool enable;
7576db01936SAxel Dörfler 			if (message->FindBool("has_selection", &enable) == B_OK) {
7586db01936SAxel Dörfler 				_EnableMenuItem(fBar, B_COPY, enable);
7596db01936SAxel Dörfler 				_EnableMenuItem(fBar, MSG_CLEAR_SELECT, enable);
7608ad30bcfSMatthew Wilber 			}
7616db01936SAxel Dörfler 			break;
7626db01936SAxel Dörfler 		}
7638ad30bcfSMatthew Wilber 
76413afa642SPhil Greenway 		case B_COPY:
765d3046f7dSMichael Pfeiffer 			fImageView->CopySelectionToClipboard();
76613afa642SPhil Greenway 			break;
7676163f333SKarsten Heimrich 
7686db01936SAxel Dörfler 		case MSG_SELECTION_MODE:
769cf0d8308SStephan Aßmus 		{
770cf0d8308SStephan Aßmus 			bool selectionMode = _ToggleMenuItem(MSG_SELECTION_MODE);
771cf0d8308SStephan Aßmus 			fImageView->SetSelectionMode(selectionMode);
772cf0d8308SStephan Aßmus 			if (!selectionMode)
773cf0d8308SStephan Aßmus 				fImageView->ClearSelection();
7746db01936SAxel Dörfler 			break;
775cf0d8308SStephan Aßmus 		}
7766db01936SAxel Dörfler 
77713afa642SPhil Greenway 		case MSG_CLEAR_SELECT:
778d3046f7dSMichael Pfeiffer 			fImageView->ClearSelection();
77913afa642SPhil Greenway 			break;
7806163f333SKarsten Heimrich 
78113afa642SPhil Greenway 		case MSG_SELECT_ALL:
782d3046f7dSMichael Pfeiffer 			fImageView->SelectAll();
78313afa642SPhil Greenway 			break;
78413afa642SPhil Greenway 
78503839579SMatthew Wilber 		case MSG_PAGE_FIRST:
786b9767a83SAxel Dörfler 			if (_ClosePrompt() && fNavigator.FirstPage())
787b9767a83SAxel Dörfler 				_LoadImage();
78803839579SMatthew Wilber 			break;
78903839579SMatthew Wilber 
79003839579SMatthew Wilber 		case MSG_PAGE_LAST:
791b9767a83SAxel Dörfler 			if (_ClosePrompt() && fNavigator.LastPage())
792b9767a83SAxel Dörfler 				_LoadImage();
79303839579SMatthew Wilber 			break;
79403839579SMatthew Wilber 
79503839579SMatthew Wilber 		case MSG_PAGE_NEXT:
796b9767a83SAxel Dörfler 			if (_ClosePrompt() && fNavigator.NextPage())
797b9767a83SAxel Dörfler 				_LoadImage();
79803839579SMatthew Wilber 			break;
79903839579SMatthew Wilber 
80003839579SMatthew Wilber 		case MSG_PAGE_PREV:
801b9767a83SAxel Dörfler 			if (_ClosePrompt() && fNavigator.PreviousPage())
802b9767a83SAxel Dörfler 				_LoadImage();
80303839579SMatthew Wilber 			break;
80403839579SMatthew Wilber 
805cd6b5cdeSAxel Dörfler 		case MSG_GOTO_PAGE:
806cd6b5cdeSAxel Dörfler 		{
807fd952aefSRyan Leavengood 			if (!_ClosePrompt())
808ee7b4f39SMatthew Wilber 				break;
809ee7b4f39SMatthew Wilber 
8106163f333SKarsten Heimrich 			int32 newPage;
8116163f333SKarsten Heimrich 			if (message->FindInt32("page", &newPage) != B_OK)
8126163f333SKarsten Heimrich 				break;
8136163f333SKarsten Heimrich 
814cd6b5cdeSAxel Dörfler 			int32 currentPage = fNavigator.CurrentPage();
815cd6b5cdeSAxel Dörfler 			int32 pages = fNavigator.PageCount();
8166c305411SMatthew Wilber 
817b9767a83SAxel Dörfler 			// TODO: use radio mode instead!
8186c305411SMatthew Wilber 			if (newPage > 0 && newPage <= pages) {
819cd6b5cdeSAxel Dörfler 				BMenuItem* currentItem = fGoToPageMenu->ItemAt(currentPage - 1);
820cd6b5cdeSAxel Dörfler 				BMenuItem* newItem = fGoToPageMenu->ItemAt(newPage - 1);
821cd6b5cdeSAxel Dörfler 				if (currentItem != NULL && newItem != NULL) {
822cd6b5cdeSAxel Dörfler 					currentItem->SetMarked(false);
823cd6b5cdeSAxel Dörfler 					newItem->SetMarked(true);
824b9767a83SAxel Dörfler 					if (fNavigator.GoToPage(newPage))
825b9767a83SAxel Dörfler 						_LoadImage();
8266c305411SMatthew Wilber 				}
8276c305411SMatthew Wilber 			}
828cd6b5cdeSAxel Dörfler 			break;
829cd6b5cdeSAxel Dörfler 		}
8306c305411SMatthew Wilber 
831e2069723SAxel Dörfler 		case kMsgFitToWindow:
832e2069723SAxel Dörfler 			fImageView->FitToBounds();
83319c76de4SMichael Pfeiffer 			break;
8346163f333SKarsten Heimrich 
835e2069723SAxel Dörfler 		case kMsgStretchToWindow:
836e2069723SAxel Dörfler 			fImageView->SetStretchToBounds(
837e2069723SAxel Dörfler 				_ToggleMenuItem(kMsgStretchToWindow));
8387eca0987SMichael Pfeiffer 			break;
8397eca0987SMichael Pfeiffer 
8407eca0987SMichael Pfeiffer 		case MSG_FILE_PREV:
841b9767a83SAxel Dörfler 			if (_ClosePrompt() && fNavigator.PreviousFile())
842a569816bSAxel Dörfler 				_LoadImage(false);
8437eca0987SMichael Pfeiffer 			break;
8447eca0987SMichael Pfeiffer 
8457eca0987SMichael Pfeiffer 		case MSG_FILE_NEXT:
8464aa63633SAxel Dörfler 		case kMsgNextSlide:
847b9767a83SAxel Dörfler 			if (_ClosePrompt() && fNavigator.NextFile())
848b9767a83SAxel Dörfler 				_LoadImage();
84913afa642SPhil Greenway 			break;
85013afa642SPhil Greenway 
851328932acSAxel Dörfler 		case kMsgDeleteCurrentFile:
852b9767a83SAxel Dörfler 		{
853b9767a83SAxel Dörfler 			if (fNavigator.MoveFileToTrash())
854b9767a83SAxel Dörfler 				_LoadImage();
855b9767a83SAxel Dörfler 			else
856328932acSAxel Dörfler 				PostMessage(B_QUIT_REQUESTED);
857328932acSAxel Dörfler 			break;
858b9767a83SAxel Dörfler 		}
859328932acSAxel Dörfler 
860bf461dbeSMatthew Wilber 		case MSG_ROTATE_90:
861d3046f7dSMichael Pfeiffer 			fImageView->Rotate(90);
862ad13f387SMichael Pfeiffer 			break;
8636163f333SKarsten Heimrich 
864bf461dbeSMatthew Wilber 		case MSG_ROTATE_270:
865d3046f7dSMichael Pfeiffer 			fImageView->Rotate(270);
866ad13f387SMichael Pfeiffer 			break;
8676163f333SKarsten Heimrich 
86869eee339SRyan Leavengood 		case MSG_FLIP_LEFT_TO_RIGHT:
86961ddc257SRyan Leavengood 			fImageView->Flip(true);
870ad13f387SMichael Pfeiffer 			break;
8716163f333SKarsten Heimrich 
87269eee339SRyan Leavengood 		case MSG_FLIP_TOP_TO_BOTTOM:
87361ddc257SRyan Leavengood 			fImageView->Flip(false);
874ad13f387SMichael Pfeiffer 			break;
8756163f333SKarsten Heimrich 
8761076d97bSAxel Dörfler 		case MSG_SLIDE_SHOW:
8771076d97bSAxel Dörfler 		{
87894fd9498SStephan Aßmus 			bool fullScreen = false;
87994fd9498SStephan Aßmus 			message->FindBool("full screen", &fullScreen);
880a877c0e7SStephan Aßmus 
8816163f333SKarsten Heimrich 			BMenuItem* item = fBar->FindItem(message->what);
8824aa63633SAxel Dörfler 			if (item == NULL)
883ee7b4f39SMatthew Wilber 				break;
8844aa63633SAxel Dörfler 
885ee7b4f39SMatthew Wilber 			if (item->IsMarked()) {
886ee7b4f39SMatthew Wilber 				item->SetMarked(false);
8874aa63633SAxel Dörfler 				_StopSlideShow();
88894a4c1c4SAugustin Cavalier 				fToolBar->SetActionPressed(MSG_SLIDE_SHOW, false);
889fd952aefSRyan Leavengood 			} else if (_ClosePrompt()) {
890ee7b4f39SMatthew Wilber 				item->SetMarked(true);
89194fd9498SStephan Aßmus 				if (!fFullScreen && fullScreen)
89294fd9498SStephan Aßmus 					_ToggleFullScreen();
8934aa63633SAxel Dörfler 				_StartSlideShow();
89494a4c1c4SAugustin Cavalier 				fToolBar->SetActionPressed(MSG_SLIDE_SHOW, true);
895ad13f387SMichael Pfeiffer 			}
8961076d97bSAxel Dörfler 			break;
8971076d97bSAxel Dörfler 		}
898ee7b4f39SMatthew Wilber 
8994aa63633SAxel Dörfler 		case kMsgStopSlideShow:
9004aa63633SAxel Dörfler 		{
9014aa63633SAxel Dörfler 			BMenuItem* item = fBar->FindItem(MSG_SLIDE_SHOW);
9024aa63633SAxel Dörfler 			if (item != NULL)
9034aa63633SAxel Dörfler 				item->SetMarked(false);
9044aa63633SAxel Dörfler 
9054aa63633SAxel Dörfler 			_StopSlideShow();
90694a4c1c4SAugustin Cavalier 			fToolBar->SetActionPressed(MSG_SLIDE_SHOW, false);
9074aa63633SAxel Dörfler 			break;
9084aa63633SAxel Dörfler 		}
9094aa63633SAxel Dörfler 
9101076d97bSAxel Dörfler 		case MSG_SLIDE_SHOW_DELAY:
9111076d97bSAxel Dörfler 		{
9124aa63633SAxel Dörfler 			bigtime_t delay;
9134aa63633SAxel Dörfler 			if (message->FindInt64("delay", &delay) == B_OK) {
9144aa63633SAxel Dörfler 				_SetSlideShowDelay(delay);
915da87390fSMichael Pfeiffer 				// in case message is sent from popup menu
9164aa63633SAxel Dörfler 				_MarkSlideShowDelay(delay);
917ad13f387SMichael Pfeiffer 			}
9181076d97bSAxel Dörfler 			break;
9191076d97bSAxel Dörfler 		}
920ad13f387SMichael Pfeiffer 
921ad13f387SMichael Pfeiffer 		case MSG_FULL_SCREEN:
922fd952aefSRyan Leavengood 			_ToggleFullScreen();
923ad13f387SMichael Pfeiffer 			break;
9246163f333SKarsten Heimrich 
925fc5ca95dSStephan Aßmus 		case MSG_EXIT_FULL_SCREEN:
926fc5ca95dSStephan Aßmus 			if (fFullScreen)
927fd952aefSRyan Leavengood 				_ToggleFullScreen();
928fc5ca95dSStephan Aßmus 			break;
9296163f333SKarsten Heimrich 
930cf0d8308SStephan Aßmus 		case MSG_SHOW_CAPTION:
931cf0d8308SStephan Aßmus 		{
932fd952aefSRyan Leavengood 			fShowCaption = _ToggleMenuItem(message->what);
933efa8b4f3SAxel Dörfler 			ShowImageSettings* settings = my_app->Settings();
934efa8b4f3SAxel Dörfler 
935d3046f7dSMichael Pfeiffer 			if (settings->Lock()) {
936d3046f7dSMichael Pfeiffer 				settings->SetBool("ShowCaption", fShowCaption);
937d3046f7dSMichael Pfeiffer 				settings->Unlock();
938d3046f7dSMichael Pfeiffer 			}
939efa8b4f3SAxel Dörfler 			if (fFullScreen)
940d3046f7dSMichael Pfeiffer 				fImageView->SetShowCaption(fShowCaption);
9416163f333SKarsten Heimrich 		}	break;
942ad13f387SMichael Pfeiffer 
943780d8a62SMichael Pfeiffer 		case MSG_PAGE_SETUP:
944fd952aefSRyan Leavengood 			_PageSetup();
945780d8a62SMichael Pfeiffer 			break;
9466163f333SKarsten Heimrich 
947780d8a62SMichael Pfeiffer 		case MSG_PREPARE_PRINT:
948fd952aefSRyan Leavengood 			_PrepareForPrint();
949780d8a62SMichael Pfeiffer 			break;
9506163f333SKarsten Heimrich 
951780d8a62SMichael Pfeiffer 		case MSG_PRINT:
952fd952aefSRyan Leavengood 			_Print(message);
953780d8a62SMichael Pfeiffer 			break;
954780d8a62SMichael Pfeiffer 
955780d8a62SMichael Pfeiffer 		case MSG_ZOOM_IN:
956d3046f7dSMichael Pfeiffer 			fImageView->ZoomIn();
957780d8a62SMichael Pfeiffer 			break;
9586163f333SKarsten Heimrich 
959780d8a62SMichael Pfeiffer 		case MSG_ZOOM_OUT:
960d3046f7dSMichael Pfeiffer 			fImageView->ZoomOut();
961780d8a62SMichael Pfeiffer 			break;
9626163f333SKarsten Heimrich 
963cae52eadSJanus 		case MSG_UPDATE_STATUS_ZOOM:
964cae52eadSJanus 			fStatusView->SetZoom(fImageView->Zoom());
965cae52eadSJanus 			break;
966cae52eadSJanus 
967e2069723SAxel Dörfler 		case kMsgOriginalSize:
9688073fcbbSAdrien Destugues 			if (message->FindInt32("behavior") == BButton::B_TOGGLE_BEHAVIOR) {
9698073fcbbSAdrien Destugues 				bool force = (message->FindInt32("be:value") == B_CONTROL_ON);
970554e2073SAdrien Destugues 				fImageView->ForceOriginalSize(force);
971554e2073SAdrien Destugues 				if (!force)
972554e2073SAdrien Destugues 					break;
973554e2073SAdrien Destugues 			}
9744fd570d3SAxel Dörfler 			fImageView->SetZoom(1.0);
975780d8a62SMichael Pfeiffer 			break;
9766163f333SKarsten Heimrich 
97781b9c776SMichael Pfeiffer 		case MSG_SCALE_BILINEAR:
978fd952aefSRyan Leavengood 			fImageView->SetScaleBilinear(_ToggleMenuItem(message->what));
97981b9c776SMichael Pfeiffer 			break;
980780d8a62SMichael Pfeiffer 
981cd6b5cdeSAxel Dörfler 		case MSG_DESKTOP_BACKGROUND:
982cd6b5cdeSAxel Dörfler 		{
9839617074cSRyan Leavengood 			BMessage backgroundsMessage(B_REFS_RECEIVED);
9849617074cSRyan Leavengood 			backgroundsMessage.AddRef("refs", fImageView->Image());
9850a74004cSRyan Leavengood 			// This is used in the Backgrounds code for scaled placement
9869617074cSRyan Leavengood 			backgroundsMessage.AddInt32("placement", 'scpl');
987537a273cSHumdinger 			be_roster->Launch("application/x-vnd.haiku-backgrounds",
988537a273cSHumdinger 				&backgroundsMessage);
989cd6b5cdeSAxel Dörfler 			break;
990cd6b5cdeSAxel Dörfler 		}
991a60adbf9SAxel Dörfler 
9925b76e505SStephan Aßmus 		case MSG_SET_RATING:
9935b76e505SStephan Aßmus 		{
9945b76e505SStephan Aßmus 			int32 rating;
9955b76e505SStephan Aßmus 			if (message->FindInt32("rating", &rating) != B_OK)
9965b76e505SStephan Aßmus 				break;
9975b76e505SStephan Aßmus 			BFile file(&fNavigator.CurrentRef(), B_WRITE_ONLY);
9985b76e505SStephan Aßmus 			if (file.InitCheck() != B_OK)
9995b76e505SStephan Aßmus 				break;
10005b76e505SStephan Aßmus 			file.WriteAttr("Media:Rating", B_INT32_TYPE, 0, &rating,
10015b76e505SStephan Aßmus 				sizeof(rating));
10025b76e505SStephan Aßmus 			_UpdateRatingMenu();
10035b76e505SStephan Aßmus 			break;
10045b76e505SStephan Aßmus 		}
10055b76e505SStephan Aßmus 
1006cf0d8308SStephan Aßmus 		case kMsgToggleToolBar:
1007cf0d8308SStephan Aßmus 		{
1008cf0d8308SStephan Aßmus 			fShowToolBar = _ToggleMenuItem(message->what);
100994fd9498SStephan Aßmus 			_SetToolBarVisible(fShowToolBar, true);
1010cf0d8308SStephan Aßmus 
1011cf0d8308SStephan Aßmus 			ShowImageSettings* settings = my_app->Settings();
1012cf0d8308SStephan Aßmus 
1013cf0d8308SStephan Aßmus 			if (settings->Lock()) {
1014cf0d8308SStephan Aßmus 				settings->SetBool("ShowToolBar", fShowToolBar);
1015cf0d8308SStephan Aßmus 				settings->Unlock();
1016cf0d8308SStephan Aßmus 			}
1017cf0d8308SStephan Aßmus 			break;
1018cf0d8308SStephan Aßmus 		}
101994fd9498SStephan Aßmus 		case kShowToolBarIfEnabled:
102094fd9498SStephan Aßmus 		{
102194fd9498SStephan Aßmus 			bool show;
102294fd9498SStephan Aßmus 			if (message->FindBool("show", &show) != B_OK)
102394fd9498SStephan Aßmus 				break;
102494fd9498SStephan Aßmus 			_SetToolBarVisible(fShowToolBar && show, true);
102594fd9498SStephan Aßmus 			break;
102694fd9498SStephan Aßmus 		}
102794fd9498SStephan Aßmus 		case kMsgSlideToolBar:
102894fd9498SStephan Aßmus 		{
102994fd9498SStephan Aßmus 			float offset;
103094fd9498SStephan Aßmus 			if (message->FindFloat("offset", &offset) == B_OK) {
103194a4c1c4SAugustin Cavalier 				fToolBar->MoveBy(0, offset);
103294fd9498SStephan Aßmus 				fScrollView->ResizeBy(0, -offset);
103394fd9498SStephan Aßmus 				fScrollView->MoveBy(0, offset);
103494fd9498SStephan Aßmus 				UpdateIfNeeded();
103594fd9498SStephan Aßmus 				snooze(15000);
103694fd9498SStephan Aßmus 			}
103794fd9498SStephan Aßmus 			break;
103894fd9498SStephan Aßmus 		}
103994fd9498SStephan Aßmus 		case kMsgFinishSlidingToolBar:
104094fd9498SStephan Aßmus 		{
104194fd9498SStephan Aßmus 			float offset;
104294fd9498SStephan Aßmus 			bool show;
104394fd9498SStephan Aßmus 			if (message->FindFloat("offset", &offset) == B_OK
104494fd9498SStephan Aßmus 				&& message->FindBool("show", &show) == B_OK) {
104594fd9498SStephan Aßmus 				// Compensate rounding errors with the final placement
104694a4c1c4SAugustin Cavalier 				fToolBar->MoveTo(fToolBar->Frame().left, offset);
104795667008SJanus 				if (!show)
104894a4c1c4SAugustin Cavalier 					fToolBar->Hide();
104994a4c1c4SAugustin Cavalier 				BRect frame = fToolBar->Parent()->Bounds();
105094a4c1c4SAugustin Cavalier 				frame.top = fToolBar->Frame().bottom + 1;
10512804cb33SRyan Leavengood 				fScrollView->MoveTo(fScrollView->Frame().left, frame.top);
105294fd9498SStephan Aßmus 				fScrollView->ResizeTo(fScrollView->Bounds().Width(),
1053cae52eadSJanus 					frame.Height() + 1);
105494fd9498SStephan Aßmus 			}
105594fd9498SStephan Aßmus 			break;
105694fd9498SStephan Aßmus 		}
1057cf0d8308SStephan Aßmus 
105813afa642SPhil Greenway 		default:
1059efa8b4f3SAxel Dörfler 			BWindow::MessageReceived(message);
106013afa642SPhil Greenway 			break;
106113afa642SPhil Greenway 	}
106213afa642SPhil Greenway }
1063fc0a275bSMatthew Wilber 
1064efa8b4f3SAxel Dörfler 
1065fc0a275bSMatthew Wilber void
1066cd6b5cdeSAxel Dörfler ShowImageWindow::_UpdateStatusText(const BMessage* message)
1067cd6b5cdeSAxel Dörfler {
1068baa27ccbSJanus 	BString frameText;
1069cd6b5cdeSAxel Dörfler 	if (fImageView->Bitmap() != NULL) {
1070cd6b5cdeSAxel Dörfler 		BRect bounds = fImageView->Bitmap()->Bounds();
1071baa27ccbSJanus 		frameText << bounds.IntegerWidth() + 1
1072cae52eadSJanus 			<< "x" << bounds.IntegerHeight() + 1;
1073cd6b5cdeSAxel Dörfler 	}
1074baa27ccbSJanus 	BString pages;
1075baa27ccbSJanus 	if (fNavigator.PageCount() > 1)
1076baa27ccbSJanus 		pages << fNavigator.CurrentPage() << "/" << fNavigator.PageCount();
1077baa27ccbSJanus 	fStatusView->Update(fNavigator.CurrentRef(), frameText, pages, fImageType,
1078cae52eadSJanus 		fImageView->Zoom());
1079cd6b5cdeSAxel Dörfler }
1080cd6b5cdeSAxel Dörfler 
1081cd6b5cdeSAxel Dörfler 
1082cd6b5cdeSAxel Dörfler void
1083cd6b5cdeSAxel Dörfler ShowImageWindow::_LoadError(const entry_ref& ref)
1084cd6b5cdeSAxel Dörfler {
1085cd6b5cdeSAxel Dörfler 	// TODO: give a better error message!
1086560ff447SJonas Sundström 	BAlert* alert = new BAlert(B_TRANSLATE_SYSTEM_NAME("ShowImage"),
1087546208a5SOliver Tappe 		B_TRANSLATE_CONTEXT("Could not load image! Either the "
1088ddcb5a2cSAxel Dörfler 			"file or an image translator for it does not exist.",
1089ddcb5a2cSAxel Dörfler 			"LoadAlerts"),
1090546208a5SOliver Tappe 		B_TRANSLATE_CONTEXT("OK", "Alerts"), NULL, NULL,
10915df9097aSJohn Scipione 		B_WIDTH_AS_USUAL, B_STOP_ALERT);
1092aed35104SHumdinger 	alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
1093cd6b5cdeSAxel Dörfler 	alert->Go();
1094cd6b5cdeSAxel Dörfler }
1095cd6b5cdeSAxel Dörfler 
1096cd6b5cdeSAxel Dörfler 
1097cd6b5cdeSAxel Dörfler void
1098fd952aefSRyan Leavengood ShowImageWindow::_SaveAs(BMessage* message)
1099fc0a275bSMatthew Wilber {
1100cdb89ebbSMatthew Wilber 	// Read the translator and output type the user chose
1101cdb89ebbSMatthew Wilber 	translator_id outTranslator;
1102cdb89ebbSMatthew Wilber 	uint32 outType;
11036163f333SKarsten Heimrich 	if (message->FindInt32(kTranslatorField,
1104efa8b4f3SAxel Dörfler 			reinterpret_cast<int32 *>(&outTranslator)) != B_OK
11056163f333SKarsten Heimrich 		|| message->FindInt32(kTypeField,
1106cdb89ebbSMatthew Wilber 			reinterpret_cast<int32 *>(&outType)) != B_OK)
1107fc0a275bSMatthew Wilber 		return;
1108fc0a275bSMatthew Wilber 
1109cdb89ebbSMatthew Wilber 	// Add the chosen translator and output type to the
1110cdb89ebbSMatthew Wilber 	// message that the save panel will send back
1111c1a10c14SKarsten Heimrich 	BMessage panelMsg(MSG_SAVE_PANEL);
1112c1a10c14SKarsten Heimrich 	panelMsg.AddInt32(kTranslatorField, outTranslator);
1113c1a10c14SKarsten Heimrich 	panelMsg.AddInt32(kTypeField, outType);
1114cdb89ebbSMatthew Wilber 
1115cdb89ebbSMatthew Wilber 	// Create save panel and show it
11166163f333SKarsten Heimrich 	BMessenger target(this);
1117efa8b4f3SAxel Dörfler 	fSavePanel = new (std::nothrow) BFilePanel(B_SAVE_PANEL,
1118c1a10c14SKarsten Heimrich 		&target, NULL, 0, false, &panelMsg);
1119d3046f7dSMichael Pfeiffer 	if (!fSavePanel)
1120fc0a275bSMatthew Wilber 		return;
1121a60adbf9SAxel Dörfler 
11223000afd7SJanus 	// Retrieve save directory from settings;
11233000afd7SJanus 	ShowImageSettings* settings = my_app->Settings();
11243000afd7SJanus 	if (settings->Lock()) {
11253000afd7SJanus 		fSavePanel->SetPanelDirectory(
11263000afd7SJanus 			settings->GetString("SaveDirectory", NULL));
11273000afd7SJanus 		settings->Unlock();
11283000afd7SJanus 	}
11293000afd7SJanus 
1130d3046f7dSMichael Pfeiffer 	fSavePanel->Window()->SetWorkspaces(B_CURRENT_WORKSPACE);
1131d3046f7dSMichael Pfeiffer 	fSavePanel->Show();
1132fc0a275bSMatthew Wilber }
1133fc0a275bSMatthew Wilber 
1134efa8b4f3SAxel Dörfler 
1135fc0a275bSMatthew Wilber void
1136fd952aefSRyan Leavengood ShowImageWindow::_SaveToFile(BMessage* message)
1137fc0a275bSMatthew Wilber {
1138cdb89ebbSMatthew Wilber 	// Read in where the file should be saved
1139efa8b4f3SAxel Dörfler 	entry_ref dirRef;
1140efa8b4f3SAxel Dörfler 	if (message->FindRef("directory", &dirRef) != B_OK)
1141fc0a275bSMatthew Wilber 		return;
1142efa8b4f3SAxel Dörfler 
1143fc0a275bSMatthew Wilber 	const char* filename;
1144efa8b4f3SAxel Dörfler 	if (message->FindString("name", &filename) != B_OK)
1145fc0a275bSMatthew Wilber 		return;
1146fc0a275bSMatthew Wilber 
1147cdb89ebbSMatthew Wilber 	// Read in the translator and type to be used
1148cdb89ebbSMatthew Wilber 	// to save the output image
1149cdb89ebbSMatthew Wilber 	translator_id outTranslator;
1150cdb89ebbSMatthew Wilber 	uint32 outType;
11516163f333SKarsten Heimrich 	if (message->FindInt32(kTranslatorField,
1152efa8b4f3SAxel Dörfler 			reinterpret_cast<int32 *>(&outTranslator)) != B_OK
11536163f333SKarsten Heimrich 		|| message->FindInt32(kTypeField,
1154cdb89ebbSMatthew Wilber 			reinterpret_cast<int32 *>(&outType)) != B_OK)
1155cdb89ebbSMatthew Wilber 		return;
1156cdb89ebbSMatthew Wilber 
1157a7e78e3bSMatthew Wilber 	// Find the translator_format information needed to
1158a7e78e3bSMatthew Wilber 	// write a MIME attribute for the image file
1159a7e78e3bSMatthew Wilber 	BTranslatorRoster* roster = BTranslatorRoster::Default();
1160efa8b4f3SAxel Dörfler 	const translation_format* outFormat = NULL;
1161efa8b4f3SAxel Dörfler 	int32 outCount = 0;
1162efa8b4f3SAxel Dörfler 	if (roster->GetOutputFormats(outTranslator, &outFormat, &outCount) != B_OK
1163efa8b4f3SAxel Dörfler 		|| outCount < 1)
1164a7e78e3bSMatthew Wilber 		return;
1165efa8b4f3SAxel Dörfler 
1166a7e78e3bSMatthew Wilber 	int32 i;
1167efa8b4f3SAxel Dörfler 	for (i = 0; i < outCount; i++) {
1168537a273cSHumdinger 		if (outFormat[i].group == B_TRANSLATOR_BITMAP && outFormat[i].type
1169537a273cSHumdinger 				== outType)
1170a7e78e3bSMatthew Wilber 			break;
1171a7e78e3bSMatthew Wilber 	}
1172efa8b4f3SAxel Dörfler 	if (i == outCount)
1173fc0a275bSMatthew Wilber 		return;
1174fc0a275bSMatthew Wilber 
1175a7e78e3bSMatthew Wilber 	// Write out the image file
1176efa8b4f3SAxel Dörfler 	BDirectory dir(&dirRef);
1177efa8b4f3SAxel Dörfler 	fImageView->SaveToFile(&dir, filename, NULL, &outFormat[i]);
11783000afd7SJanus 
11793000afd7SJanus 	// Store Save directory in settings;
11803000afd7SJanus 	ShowImageSettings* settings = my_app->Settings();
11813000afd7SJanus 	if (settings->Lock()) {
11823000afd7SJanus 		BPath path(&dirRef);
11833000afd7SJanus 		settings->SetString("SaveDirectory", path.Path());
11843000afd7SJanus 		settings->Unlock();
11853000afd7SJanus 	}
1186fc0a275bSMatthew Wilber }
1187fc0a275bSMatthew Wilber 
1188efa8b4f3SAxel Dörfler 
1189546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT
1190546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "ClosePrompt"
11911ed4535fSStephan Aßmus 
1192b9767a83SAxel Dörfler 
1193cdb89ebbSMatthew Wilber bool
1194fd952aefSRyan Leavengood ShowImageWindow::_ClosePrompt()
1195ee7b4f39SMatthew Wilber {
1196ee7b4f39SMatthew Wilber 	if (!fModified)
1197ee7b4f39SMatthew Wilber 		return true;
1198efa8b4f3SAxel Dörfler 
1199cd6b5cdeSAxel Dörfler 	int32 count = fNavigator.PageCount();
1200cd6b5cdeSAxel Dörfler 	int32 page = fNavigator.CurrentPage();
1201cd6b5cdeSAxel Dörfler 	BString prompt;
1202efa8b4f3SAxel Dörfler 
12031ed4535fSStephan Aßmus 	if (count > 1) {
12041ed4535fSStephan Aßmus 		bs_printf(&prompt,
1205905c8c8cSMatt Madia 			B_TRANSLATE("The document '%s' (page %d) has been changed. Do you "
1206905c8c8cSMatt Madia 				"want to close the document?"),
1207cd6b5cdeSAxel Dörfler 			fImageView->Image()->name, page);
12081ed4535fSStephan Aßmus 	} else {
12091ed4535fSStephan Aßmus 		bs_printf(&prompt,
1210905c8c8cSMatt Madia 			B_TRANSLATE("The document '%s' has been changed. Do you want to "
1211905c8c8cSMatt Madia 				"close the document?"),
1212cd6b5cdeSAxel Dörfler 			fImageView->Image()->name);
12131ed4535fSStephan Aßmus 	}
12141ed4535fSStephan Aßmus 
1215cd6b5cdeSAxel Dörfler 	BAlert* alert = new BAlert(B_TRANSLATE("Close document"), prompt.String(),
1216905c8c8cSMatt Madia 		B_TRANSLATE("Cancel"), B_TRANSLATE("Close"));
1217aed35104SHumdinger 	alert->SetShortcut(0, B_ESCAPE);
1218aed35104SHumdinger 
1219cd6b5cdeSAxel Dörfler 	if (alert->Go() == 0) {
1220ee7b4f39SMatthew Wilber 		// Cancel
1221ee7b4f39SMatthew Wilber 		return false;
1222cd6b5cdeSAxel Dörfler 	}
1223cd6b5cdeSAxel Dörfler 
1224ee7b4f39SMatthew Wilber 	// Close
1225187f0b8aSMatthew Wilber 	fModified = false;
1226ee7b4f39SMatthew Wilber 	return true;
1227ee7b4f39SMatthew Wilber }
1228ee7b4f39SMatthew Wilber 
1229cdb89ebbSMatthew Wilber 
1230b9767a83SAxel Dörfler status_t
1231a569816bSAxel Dörfler ShowImageWindow::_LoadImage(bool forward)
1232b9767a83SAxel Dörfler {
1233b9767a83SAxel Dörfler 	BMessenger us(this);
1234be63ec85SJanus 	status_t status = my_app->DefaultCache().RetrieveImage(
1235a569816bSAxel Dörfler 		fNavigator.CurrentRef(), fNavigator.CurrentPage(), &us);
1236a569816bSAxel Dörfler 	if (status != B_OK)
1237a569816bSAxel Dörfler 		return status;
1238a569816bSAxel Dörfler 
1239e2069723SAxel Dörfler 	fProgressWindow->Start(this);
1240e2069723SAxel Dörfler 
1241a569816bSAxel Dörfler 	// Preload previous/next images - two in the navigation direction, one
1242a569816bSAxel Dörfler 	// in the opposite direction.
1243a569816bSAxel Dörfler 
1244a569816bSAxel Dörfler 	entry_ref nextRef = fNavigator.CurrentRef();
1245a569816bSAxel Dörfler 	if (_PreloadImage(forward, nextRef))
1246a569816bSAxel Dörfler 		_PreloadImage(forward, nextRef);
1247a569816bSAxel Dörfler 
1248a569816bSAxel Dörfler 	entry_ref previousRef = fNavigator.CurrentRef();
1249a569816bSAxel Dörfler 	_PreloadImage(!forward, previousRef);
1250a569816bSAxel Dörfler 
1251a569816bSAxel Dörfler 	return B_OK;
1252a569816bSAxel Dörfler }
1253a569816bSAxel Dörfler 
1254a569816bSAxel Dörfler 
1255a569816bSAxel Dörfler bool
1256a569816bSAxel Dörfler ShowImageWindow::_PreloadImage(bool forward, entry_ref& ref)
1257a569816bSAxel Dörfler {
1258a569816bSAxel Dörfler 	entry_ref currentRef = ref;
1259a569816bSAxel Dörfler 	if ((forward && !fNavigator.GetNextFile(currentRef, ref))
1260a569816bSAxel Dörfler 		|| (!forward && !fNavigator.GetPreviousFile(currentRef, ref)))
1261a569816bSAxel Dörfler 		return false;
1262a569816bSAxel Dörfler 
1263be63ec85SJanus 	return my_app->DefaultCache().RetrieveImage(ref) == B_OK;
1264b9767a83SAxel Dörfler }
1265b9767a83SAxel Dörfler 
1266b9767a83SAxel Dörfler 
1267ad13f387SMichael Pfeiffer void
1268fd952aefSRyan Leavengood ShowImageWindow::_ToggleFullScreen()
1269ad13f387SMichael Pfeiffer {
1270ad13f387SMichael Pfeiffer 	BRect frame;
1271ad13f387SMichael Pfeiffer 	fFullScreen = !fFullScreen;
1272ad13f387SMichael Pfeiffer 	if (fFullScreen) {
1273ad13f387SMichael Pfeiffer 		BScreen screen;
1274ad13f387SMichael Pfeiffer 		fWindowFrame = Frame();
1275ad13f387SMichael Pfeiffer 		frame = screen.Frame();
1276d3046f7dSMichael Pfeiffer 		frame.top -= fBar->Bounds().Height() + 1;
127767eb2a04SHumdinger 		frame.right += B_V_SCROLL_BAR_WIDTH;
1278ad13f387SMichael Pfeiffer 		frame.bottom += B_H_SCROLL_BAR_HEIGHT;
1279ad13f387SMichael Pfeiffer 
1280ad13f387SMichael Pfeiffer 		SetFlags(Flags() | B_NOT_RESIZABLE | B_NOT_MOVABLE);
1281c0b16687SAxel Dörfler 
1282c0b16687SAxel Dörfler 		Activate();
1283c0b16687SAxel Dörfler 			// make the window frontmost
1284ad13f387SMichael Pfeiffer 	} else {
1285ad13f387SMichael Pfeiffer 		frame = fWindowFrame;
1286ad13f387SMichael Pfeiffer 
1287ad13f387SMichael Pfeiffer 		SetFlags(Flags() & ~(B_NOT_RESIZABLE | B_NOT_MOVABLE));
1288ad13f387SMichael Pfeiffer 	}
1289efa8b4f3SAxel Dörfler 
129094a4c1c4SAugustin Cavalier 	fToolBar->SetActionVisible(MSG_FULL_SCREEN, fFullScreen);
1291cf0d8308SStephan Aßmus 	_SetToolBarVisible(!fFullScreen && fShowToolBar);
129260c23976SJanus 	_SetToolBarBorder(!fFullScreen);
1293cf0d8308SStephan Aßmus 
1294ad13f387SMichael Pfeiffer 	MoveTo(frame.left, frame.top);
1295ad13f387SMichael Pfeiffer 	ResizeTo(frame.Width(), frame.Height());
1296e2069723SAxel Dörfler 
1297e2069723SAxel Dörfler 	fImageView->SetHideIdlingCursor(fFullScreen);
1298e2069723SAxel Dörfler 	fImageView->SetShowCaption(fFullScreen && fShowCaption);
1299eaa910c5SAxel Dörfler 
130048ae3e38SAxel Dörfler 	Layout(false);
130148ae3e38SAxel Dörfler 		// We need to manually relayout here, as the views are layouted
130248ae3e38SAxel Dörfler 		// asynchronously, and FitToBounds() would still have the wrong size
1303e2069723SAxel Dörfler 	fImageView->FitToBounds();
1304ad13f387SMichael Pfeiffer }
1305ad13f387SMichael Pfeiffer 
1306efa8b4f3SAxel Dörfler 
1307d3046f7dSMichael Pfeiffer void
13082281340dSAxel Dörfler ShowImageWindow::_ApplySettings()
1309d3046f7dSMichael Pfeiffer {
1310efa8b4f3SAxel Dörfler 	ShowImageSettings* settings = my_app->Settings();
1311efa8b4f3SAxel Dörfler 
1312d3046f7dSMichael Pfeiffer 	if (settings->Lock()) {
1313d3046f7dSMichael Pfeiffer 		fShowCaption = settings->GetBool("ShowCaption", fShowCaption);
1314d3046f7dSMichael Pfeiffer 		fPrintOptions.SetBounds(BRect(0, 0, 1023, 767));
1315d3046f7dSMichael Pfeiffer 
13164aa63633SAxel Dörfler 		fSlideShowDelay = settings->GetTime("SlideShowDelay", fSlideShowDelay);
1317d3046f7dSMichael Pfeiffer 
13184aa63633SAxel Dörfler 		fPrintOptions.SetOption((enum PrintOptions::Option)settings->GetInt32(
13194aa63633SAxel Dörfler 			"PO:Option", fPrintOptions.Option()));
13204aa63633SAxel Dörfler 		fPrintOptions.SetZoomFactor(
13214aa63633SAxel Dörfler 			settings->GetFloat("PO:ZoomFactor", fPrintOptions.ZoomFactor()));
13224aa63633SAxel Dörfler 		fPrintOptions.SetDPI(settings->GetFloat("PO:DPI", fPrintOptions.DPI()));
13234aa63633SAxel Dörfler 		fPrintOptions.SetWidth(
13244aa63633SAxel Dörfler 			settings->GetFloat("PO:Width", fPrintOptions.Width()));
13254aa63633SAxel Dörfler 		fPrintOptions.SetHeight(
13264aa63633SAxel Dörfler 			settings->GetFloat("PO:Height", fPrintOptions.Height()));
1327d3046f7dSMichael Pfeiffer 
1328cf0d8308SStephan Aßmus 		fShowToolBar = settings->GetBool("ShowToolBar", fShowToolBar);
1329cf0d8308SStephan Aßmus 
1330d3046f7dSMichael Pfeiffer 		settings->Unlock();
1331d3046f7dSMichael Pfeiffer 	}
1332d3046f7dSMichael Pfeiffer }
1333d3046f7dSMichael Pfeiffer 
1334efa8b4f3SAxel Dörfler 
1335d3046f7dSMichael Pfeiffer void
1336fd952aefSRyan Leavengood ShowImageWindow::_SavePrintOptions()
1337d3046f7dSMichael Pfeiffer {
1338efa8b4f3SAxel Dörfler 	ShowImageSettings* settings = my_app->Settings();
1339efa8b4f3SAxel Dörfler 
1340d3046f7dSMichael Pfeiffer 	if (settings->Lock()) {
1341d3046f7dSMichael Pfeiffer 		settings->SetInt32("PO:Option", fPrintOptions.Option());
1342d3046f7dSMichael Pfeiffer 		settings->SetFloat("PO:ZoomFactor", fPrintOptions.ZoomFactor());
1343d3046f7dSMichael Pfeiffer 		settings->SetFloat("PO:DPI", fPrintOptions.DPI());
1344d3046f7dSMichael Pfeiffer 		settings->SetFloat("PO:Width", fPrintOptions.Width());
1345d3046f7dSMichael Pfeiffer 		settings->SetFloat("PO:Height", fPrintOptions.Height());
1346d3046f7dSMichael Pfeiffer 		settings->Unlock();
1347d3046f7dSMichael Pfeiffer 	}
1348d3046f7dSMichael Pfeiffer }
1349d3046f7dSMichael Pfeiffer 
1350efa8b4f3SAxel Dörfler 
1351cdb89ebbSMatthew Wilber bool
1352fd952aefSRyan Leavengood ShowImageWindow::_PageSetup()
1353780d8a62SMichael Pfeiffer {
1354cd6b5cdeSAxel Dörfler 	BPrintJob printJob(fImageView->Image()->name);
1355efa8b4f3SAxel Dörfler 	if (fPrintSettings != NULL)
1356780d8a62SMichael Pfeiffer 		printJob.SetSettings(new BMessage(*fPrintSettings));
1357efa8b4f3SAxel Dörfler 
13586163f333SKarsten Heimrich 	status_t status = printJob.ConfigPage();
13596163f333SKarsten Heimrich 	if (status == B_OK) {
1360780d8a62SMichael Pfeiffer 		delete fPrintSettings;
1361780d8a62SMichael Pfeiffer 		fPrintSettings = printJob.Settings();
1362780d8a62SMichael Pfeiffer 	}
1363efa8b4f3SAxel Dörfler 
13646163f333SKarsten Heimrich 	return status == B_OK;
1365780d8a62SMichael Pfeiffer }
1366780d8a62SMichael Pfeiffer 
1367efa8b4f3SAxel Dörfler 
1368780d8a62SMichael Pfeiffer void
1369fd952aefSRyan Leavengood ShowImageWindow::_PrepareForPrint()
1370780d8a62SMichael Pfeiffer {
13716163f333SKarsten Heimrich 	if (fPrintSettings == NULL) {
1372cd6b5cdeSAxel Dörfler 		BPrintJob printJob(fImageView->Image()->name);
13736163f333SKarsten Heimrich 		if (printJob.ConfigJob() == B_OK)
13746163f333SKarsten Heimrich 			fPrintSettings = printJob.Settings();
13756163f333SKarsten Heimrich 	}
1376780d8a62SMichael Pfeiffer 
1377cd6b5cdeSAxel Dörfler 	fPrintOptions.SetBounds(fImageView->Bitmap()->Bounds());
1378cd6b5cdeSAxel Dörfler 	fPrintOptions.SetWidth(fImageView->Bitmap()->Bounds().Width() + 1);
1379780d8a62SMichael Pfeiffer 
1380efa8b4f3SAxel Dörfler 	new PrintOptionsWindow(BPoint(Frame().left + 30, Frame().top + 50),
1381efa8b4f3SAxel Dörfler 		&fPrintOptions, this);
1382780d8a62SMichael Pfeiffer }
1383780d8a62SMichael Pfeiffer 
1384efa8b4f3SAxel Dörfler 
1385780d8a62SMichael Pfeiffer void
1386fd952aefSRyan Leavengood ShowImageWindow::_Print(BMessage* msg)
1387780d8a62SMichael Pfeiffer {
1388780d8a62SMichael Pfeiffer 	status_t st;
1389efa8b4f3SAxel Dörfler 	if (msg->FindInt32("status", &st) != B_OK || st != B_OK)
1390780d8a62SMichael Pfeiffer 		return;
1391780d8a62SMichael Pfeiffer 
1392fd952aefSRyan Leavengood 	_SavePrintOptions();
1393d3046f7dSMichael Pfeiffer 
1394cd6b5cdeSAxel Dörfler 	BPrintJob printJob(fImageView->Image()->name);
13956163f333SKarsten Heimrich 	if (fPrintSettings)
1396780d8a62SMichael Pfeiffer 		printJob.SetSettings(new BMessage(*fPrintSettings));
13976163f333SKarsten Heimrich 
1398780d8a62SMichael Pfeiffer 	if (printJob.ConfigJob() == B_OK) {
13996163f333SKarsten Heimrich 		delete fPrintSettings;
14006163f333SKarsten Heimrich 		fPrintSettings = printJob.Settings();
1401780d8a62SMichael Pfeiffer 
1402780d8a62SMichael Pfeiffer 		// first/lastPage is unused for now
14033177ae77SStefano Ceccherini 		int32 firstPage = printJob.FirstPage();
14043177ae77SStefano Ceccherini 		int32 lastPage = printJob.LastPage();
14056163f333SKarsten Heimrich 		BRect printableRect = printJob.PrintableRect();
14066163f333SKarsten Heimrich 
1407efa8b4f3SAxel Dörfler 		if (firstPage < 1)
1408780d8a62SMichael Pfeiffer 			firstPage = 1;
1409efa8b4f3SAxel Dörfler 		if (lastPage < firstPage)
1410780d8a62SMichael Pfeiffer 			lastPage = firstPage;
1411780d8a62SMichael Pfeiffer 
1412cd6b5cdeSAxel Dörfler 		BBitmap* bitmap = fImageView->Bitmap();
14133177ae77SStefano Ceccherini 		float imageWidth = bitmap->Bounds().Width() + 1.0;
14143177ae77SStefano Ceccherini 		float imageHeight = bitmap->Bounds().Height() + 1.0;
1415780d8a62SMichael Pfeiffer 
14166163f333SKarsten Heimrich 		float width;
1417780d8a62SMichael Pfeiffer 		switch (fPrintOptions.Option()) {
14186163f333SKarsten Heimrich 			case PrintOptions::kFitToPage: {
14196163f333SKarsten Heimrich 				float w1 = printableRect.Width() + 1;
1420cd6b5cdeSAxel Dörfler 				float w2 = imageWidth * (printableRect.Height() + 1)
1421cd6b5cdeSAxel Dörfler 					/ imageHeight;
1422efa8b4f3SAxel Dörfler 				if (w2 < w1)
1423780d8a62SMichael Pfeiffer 					width = w2;
1424efa8b4f3SAxel Dörfler 				else
1425780d8a62SMichael Pfeiffer 					width = w1;
14266163f333SKarsten Heimrich 			}	break;
1427780d8a62SMichael Pfeiffer 			case PrintOptions::kZoomFactor:
1428780d8a62SMichael Pfeiffer 				width = imageWidth * fPrintOptions.ZoomFactor();
1429780d8a62SMichael Pfeiffer 				break;
1430780d8a62SMichael Pfeiffer 			case PrintOptions::kDPI:
1431780d8a62SMichael Pfeiffer 				width = imageWidth * 72.0 / fPrintOptions.DPI();
1432780d8a62SMichael Pfeiffer 				break;
1433780d8a62SMichael Pfeiffer 			case PrintOptions::kWidth:
1434780d8a62SMichael Pfeiffer 			case PrintOptions::kHeight:
1435780d8a62SMichael Pfeiffer 				width = fPrintOptions.Width();
1436780d8a62SMichael Pfeiffer 				break;
1437efa8b4f3SAxel Dörfler 
1438780d8a62SMichael Pfeiffer 			default:
1439780d8a62SMichael Pfeiffer 				// keep compiler silent; should not reach here
1440780d8a62SMichael Pfeiffer 				width = imageWidth;
1441780d8a62SMichael Pfeiffer 		}
1442780d8a62SMichael Pfeiffer 
1443efa8b4f3SAxel Dörfler 		// TODO: eventually print large images on several pages
1444780d8a62SMichael Pfeiffer 		printJob.BeginJob();
1445d3046f7dSMichael Pfeiffer 		fImageView->SetScale(width / imageWidth);
14465eb50e46SMichael Pfeiffer 		// coordinates are relative to printable rectangle
14475eb50e46SMichael Pfeiffer 		BRect bounds(bitmap->Bounds());
14485eb50e46SMichael Pfeiffer 		printJob.DrawView(fImageView, bounds, BPoint(0, 0));
1449d3046f7dSMichael Pfeiffer 		fImageView->SetScale(1.0);
1450780d8a62SMichael Pfeiffer 		printJob.SpoolPage();
1451780d8a62SMichael Pfeiffer 		printJob.CommitJob();
1452780d8a62SMichael Pfeiffer 	}
1453780d8a62SMichael Pfeiffer }
1454780d8a62SMichael Pfeiffer 
145556b0c7b9SKarsten Heimrich 
14564aa63633SAxel Dörfler void
14574aa63633SAxel Dörfler ShowImageWindow::_SetSlideShowDelay(bigtime_t delay)
14584aa63633SAxel Dörfler {
14594aa63633SAxel Dörfler 	if (fSlideShowDelay == delay)
14604aa63633SAxel Dörfler 		return;
14614aa63633SAxel Dörfler 
14624aa63633SAxel Dörfler 	fSlideShowDelay = delay;
14634aa63633SAxel Dörfler 
14644aa63633SAxel Dörfler 	ShowImageSettings* settings = my_app->Settings();
14654aa63633SAxel Dörfler 	if (settings->Lock()) {
14664aa63633SAxel Dörfler 		settings->SetTime("SlideShowDelay", fSlideShowDelay);
14674aa63633SAxel Dörfler 		settings->Unlock();
14684aa63633SAxel Dörfler 	}
14694aa63633SAxel Dörfler 
14704aa63633SAxel Dörfler 	if (fSlideShowRunner != NULL)
14714aa63633SAxel Dörfler 		_StartSlideShow();
14724aa63633SAxel Dörfler }
14734aa63633SAxel Dörfler 
14744aa63633SAxel Dörfler 
14754aa63633SAxel Dörfler void
14764aa63633SAxel Dörfler ShowImageWindow::_StartSlideShow()
14774aa63633SAxel Dörfler {
14784aa63633SAxel Dörfler 	_StopSlideShow();
14794aa63633SAxel Dörfler 
14804aa63633SAxel Dörfler 	BMessage nextSlide(kMsgNextSlide);
14814aa63633SAxel Dörfler 	fSlideShowRunner = new BMessageRunner(this, &nextSlide, fSlideShowDelay);
14824aa63633SAxel Dörfler }
14834aa63633SAxel Dörfler 
14844aa63633SAxel Dörfler 
14854aa63633SAxel Dörfler void
14864aa63633SAxel Dörfler ShowImageWindow::_StopSlideShow()
14874aa63633SAxel Dörfler {
14884aa63633SAxel Dörfler 	if (fSlideShowRunner != NULL) {
14894aa63633SAxel Dörfler 		delete fSlideShowRunner;
14904aa63633SAxel Dörfler 		fSlideShowRunner = NULL;
14914aa63633SAxel Dörfler 	}
14924aa63633SAxel Dörfler }
14934aa63633SAxel Dörfler 
14944aa63633SAxel Dörfler 
14955b76e505SStephan Aßmus void
14965b76e505SStephan Aßmus ShowImageWindow::_UpdateRatingMenu()
14975b76e505SStephan Aßmus {
14985b76e505SStephan Aßmus 	BFile file(&fNavigator.CurrentRef(), B_READ_ONLY);
14995b76e505SStephan Aßmus 	if (file.InitCheck() != B_OK)
15005b76e505SStephan Aßmus 		return;
15015b76e505SStephan Aßmus 	int32 rating;
15025b76e505SStephan Aßmus 	ssize_t size = sizeof(rating);
15035b76e505SStephan Aßmus 	if (file.ReadAttr("Media:Rating", B_INT32_TYPE, 0, &rating, size) != size)
15045b76e505SStephan Aßmus 		rating = 0;
15055b76e505SStephan Aßmus 	// TODO: Finding the correct item could be more robust, like by looking
15065b76e505SStephan Aßmus 	// at the message of each item.
15075b76e505SStephan Aßmus 	for (int32 i = 1; i <= 10; i++) {
15085b76e505SStephan Aßmus 		BMenuItem* item = fRatingMenu->ItemAt(i - 1);
15095b76e505SStephan Aßmus 		if (item == NULL)
15105b76e505SStephan Aßmus 			break;
15115b76e505SStephan Aßmus 		item->SetMarked(i == rating);
15125b76e505SStephan Aßmus 	}
15135b76e505SStephan Aßmus }
15145b76e505SStephan Aßmus 
15155b76e505SStephan Aßmus 
1516cf0d8308SStephan Aßmus void
1517e62a6973SJanus ShowImageWindow::_SaveWidthAndHeight()
1518e62a6973SJanus {
1519e62a6973SJanus 	if (fNavigator.CurrentPage() != 1)
1520e62a6973SJanus 		return;
1521e62a6973SJanus 
1522e62a6973SJanus 	if (fImageView->Bitmap() == NULL)
1523e62a6973SJanus 		return;
1524e62a6973SJanus 
1525e62a6973SJanus 	BRect bounds = fImageView->Bitmap()->Bounds();
1526*c1994be8SJanus 	int32 width = bounds.IntegerWidth() + 1;
1527*c1994be8SJanus 	int32 height = bounds.IntegerHeight() + 1;
1528e62a6973SJanus 
1529e62a6973SJanus 	BFile file(&fNavigator.CurrentRef(), B_WRITE_ONLY);
1530e62a6973SJanus 	if (file.InitCheck() != B_OK)
1531e62a6973SJanus 		return;
1532e62a6973SJanus 
1533e62a6973SJanus 	file.WriteAttr("Media:Width", B_INT32_TYPE, 0, &width, sizeof(width));
1534e62a6973SJanus 	file.WriteAttr("Media:Height", B_INT32_TYPE, 0, &height, sizeof(height));
1535e62a6973SJanus }
1536e62a6973SJanus 
1537e62a6973SJanus 
1538e62a6973SJanus void
153994fd9498SStephan Aßmus ShowImageWindow::_SetToolBarVisible(bool visible, bool animate)
1540cf0d8308SStephan Aßmus {
154195667008SJanus 	if (visible == fToolBarVisible)
1542cf0d8308SStephan Aßmus 		return;
1543cf0d8308SStephan Aßmus 
154495667008SJanus 	fToolBarVisible = visible;
154594a4c1c4SAugustin Cavalier 	float diff = fToolBar->Bounds().Height() + 2;
154694fd9498SStephan Aßmus 	if (!visible)
1547cf0d8308SStephan Aßmus 		diff = -diff;
154894fd9498SStephan Aßmus 	else
154994a4c1c4SAugustin Cavalier 		fToolBar->Show();
1550cf0d8308SStephan Aßmus 
155194fd9498SStephan Aßmus 	if (animate) {
155294fd9498SStephan Aßmus 		// Slide the controls into view. We do this with messages in order
155394fd9498SStephan Aßmus 		// not to block the window thread.
155494fd9498SStephan Aßmus 		const float kAnimationOffsets[] = { 0.05, 0.2, 0.5, 0.2, 0.05 };
155594fd9498SStephan Aßmus 		const int32 steps = sizeof(kAnimationOffsets) / sizeof(float);
155694fd9498SStephan Aßmus 		for (int32 i = 0; i < steps; i++) {
155794fd9498SStephan Aßmus 			BMessage message(kMsgSlideToolBar);
155894fd9498SStephan Aßmus 			message.AddFloat("offset", floorf(diff * kAnimationOffsets[i]));
155994fd9498SStephan Aßmus 			PostMessage(&message, this);
156094fd9498SStephan Aßmus 		}
156194fd9498SStephan Aßmus 		BMessage finalMessage(kMsgFinishSlidingToolBar);
156295667008SJanus 		finalMessage.AddFloat("offset", visible ? 0 : diff);
156394fd9498SStephan Aßmus 		finalMessage.AddBool("show", visible);
156494fd9498SStephan Aßmus 		PostMessage(&finalMessage, this);
156594fd9498SStephan Aßmus 	} else {
1566cf0d8308SStephan Aßmus 		fScrollView->ResizeBy(0, -diff);
1567cf0d8308SStephan Aßmus 		fScrollView->MoveBy(0, diff);
156894a4c1c4SAugustin Cavalier 		fToolBar->MoveBy(0, diff);
156994fd9498SStephan Aßmus 		if (!visible)
157094a4c1c4SAugustin Cavalier 			fToolBar->Hide();
157194fd9498SStephan Aßmus 	}
1572cf0d8308SStephan Aßmus }
1573cf0d8308SStephan Aßmus 
1574cf0d8308SStephan Aßmus 
157560c23976SJanus void
157660c23976SJanus ShowImageWindow::_SetToolBarBorder(bool visible)
157760c23976SJanus {
157860c23976SJanus 	float inset = visible
157960c23976SJanus 		? ceilf(be_control_look->DefaultItemSpacing() / 2) : 0;
158060c23976SJanus 
158160c23976SJanus 	fToolBar->GroupLayout()->SetInsets(inset, 0, inset, 0);
158260c23976SJanus }
158360c23976SJanus 
158460c23976SJanus 
1585780d8a62SMichael Pfeiffer bool
1586cdb89ebbSMatthew Wilber ShowImageWindow::QuitRequested()
1587cdb89ebbSMatthew Wilber {
1588efa8b4f3SAxel Dörfler 	if (fSavePanel) {
1589efa8b4f3SAxel Dörfler 		// Don't allow this window to be closed if a save panel is open
1590efa8b4f3SAxel Dörfler 		return false;
1591cdb89ebbSMatthew Wilber 	}
1592cdb89ebbSMatthew Wilber 
15935b76e505SStephan Aßmus 	if (!_ClosePrompt())
15945b76e505SStephan Aßmus 		return false;
15955b76e505SStephan Aßmus 
15965b76e505SStephan Aßmus 	ShowImageSettings* settings = my_app->Settings();
15975b76e505SStephan Aßmus 	if (settings->Lock()) {
1598c418e2beSStephan Aßmus 		if (fFullScreen)
1599c418e2beSStephan Aßmus 			settings->SetRect("WindowFrame", fWindowFrame);
1600c418e2beSStephan Aßmus 		else
16015b76e505SStephan Aßmus 			settings->SetRect("WindowFrame", Frame());
16025b76e505SStephan Aßmus 		settings->Unlock();
16035b76e505SStephan Aßmus 	}
16045b76e505SStephan Aßmus 
16055b76e505SStephan Aßmus 	be_app->PostMessage(MSG_WINDOW_HAS_QUIT);
16065b76e505SStephan Aßmus 
16075b76e505SStephan Aßmus 	return true;
1608efa8b4f3SAxel Dörfler }
1609