xref: /haiku/src/apps/showimage/ShowImageWindow.cpp (revision a4462d205de643f75a82d4dcabbf2e1e5c74cdbd)
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',
97fb94ed11SAvi Brenner 	MSG_GET_INFO				= 'mGFI',
985b76e505SStephan Aßmus 	MSG_SET_RATING				= 'mSRT',
99e2069723SAxel Dörfler 	kMsgFitToWindow				= 'mFtW',
100e2069723SAxel Dörfler 	kMsgOriginalSize			= 'mOSZ',
1014aa63633SAxel Dörfler 	kMsgStretchToWindow			= 'mStW',
102cf0d8308SStephan Aßmus 	kMsgNextSlide				= 'mNxS',
10394fd9498SStephan Aßmus 	kMsgToggleToolBar			= 'mTTB',
10494fd9498SStephan Aßmus 	kMsgSlideToolBar			= 'mSTB',
10594fd9498SStephan Aßmus 	kMsgFinishSlidingToolBar	= 'mFST'
106e2069723SAxel Dörfler };
107e2069723SAxel Dörfler 
108e2069723SAxel Dörfler 
109cd6b5cdeSAxel Dörfler // This is temporary solution for building BString with printf like format.
110cd6b5cdeSAxel Dörfler // will be removed in the future.
111cd6b5cdeSAxel Dörfler static void
112cd6b5cdeSAxel Dörfler bs_printf(BString* string, const char* format, ...)
113cd6b5cdeSAxel Dörfler {
114cd6b5cdeSAxel Dörfler 	va_list ap;
115cd6b5cdeSAxel Dörfler 	char* buf;
116cd6b5cdeSAxel Dörfler 
117cd6b5cdeSAxel Dörfler 	va_start(ap, format);
118cd6b5cdeSAxel Dörfler 	vasprintf(&buf, format, ap);
119cd6b5cdeSAxel Dörfler 	string->SetTo(buf);
120cd6b5cdeSAxel Dörfler 	free(buf);
121cd6b5cdeSAxel Dörfler 	va_end(ap);
122cd6b5cdeSAxel Dörfler }
123cd6b5cdeSAxel Dörfler 
124cd6b5cdeSAxel Dörfler 
1256163f333SKarsten Heimrich //	#pragma mark -- ShowImageWindow
1266163f333SKarsten Heimrich 
1276163f333SKarsten Heimrich 
128546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT
129546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "Menus"
130cf0d8308SStephan Aßmus 
131cf0d8308SStephan Aßmus 
1325b76e505SStephan Aßmus ShowImageWindow::ShowImageWindow(BRect frame, const entry_ref& ref,
133efa8b4f3SAxel Dörfler 	const BMessenger& trackerMessenger)
134fd952aefSRyan Leavengood 	:
13594fd9498SStephan Aßmus 	BWindow(frame, "", B_DOCUMENT_WINDOW, B_AUTO_UPDATE_SIZE_LIMITS),
136b9767a83SAxel Dörfler 	fNavigator(ref, trackerMessenger),
137fd952aefSRyan Leavengood 	fSavePanel(NULL),
138fd952aefSRyan Leavengood 	fBar(NULL),
139fd952aefSRyan Leavengood 	fBrowseMenu(NULL),
140fd952aefSRyan Leavengood 	fGoToPageMenu(NULL),
1414aa63633SAxel Dörfler 	fSlideShowDelayMenu(NULL),
14294a4c1c4SAugustin Cavalier 	fToolBar(NULL),
143fd952aefSRyan Leavengood 	fImageView(NULL),
144fd952aefSRyan Leavengood 	fStatusView(NULL),
145e2069723SAxel Dörfler 	fProgressWindow(new ProgressWindow()),
146fd952aefSRyan Leavengood 	fModified(false),
147fd952aefSRyan Leavengood 	fFullScreen(false),
148fd952aefSRyan Leavengood 	fShowCaption(true),
149cf0d8308SStephan Aßmus 	fShowToolBar(true),
1504aa63633SAxel Dörfler 	fPrintSettings(NULL),
1514aa63633SAxel Dörfler 	fSlideShowRunner(NULL),
1524aa63633SAxel Dörfler 	fSlideShowDelay(kDefaultSlideShowDelay)
15313afa642SPhil Greenway {
1542281340dSAxel Dörfler 	_ApplySettings();
155fc0a275bSMatthew Wilber 
15694fd9498SStephan Aßmus 	SetLayout(new BGroupLayout(B_VERTICAL, 0));
15794fd9498SStephan Aßmus 
15813afa642SPhil Greenway 	// create menu bar
15994fd9498SStephan Aßmus 	fBar = new BMenuBar("menu_bar");
160b9767a83SAxel Dörfler 	_AddMenus(fBar);
16194fd9498SStephan Aßmus 	float menuBarMinWidth = fBar->MinSize().width;
162e9dcd874SAxel Dörfler 	AddChild(fBar);
16313afa642SPhil Greenway 
16494fd9498SStephan Aßmus 	// Add a content view so the tool bar can be moved outside of the
16594fd9498SStephan Aßmus 	// visible portion without colliding with the menu bar.
166cf0d8308SStephan Aßmus 
16794fd9498SStephan Aßmus 	BView* contentView = new BView(BRect(), "content", B_FOLLOW_NONE, 0);
168fa19dd44Slooncraz 	contentView->SetViewUIColor(B_PANEL_BACKGROUND_COLOR);
16994fd9498SStephan Aßmus 	contentView->SetExplicitMinSize(BSize(250, 100));
17094fd9498SStephan Aßmus 	AddChild(contentView);
17194fd9498SStephan Aßmus 
17294fd9498SStephan Aßmus 	// Create the tool bar
17394fd9498SStephan Aßmus 	BRect viewFrame = contentView->Bounds();
17494fd9498SStephan Aßmus 	viewFrame.right -= B_V_SCROLL_BAR_WIDTH;
17594a4c1c4SAugustin Cavalier 	fToolBar = new BToolBar(viewFrame);
176cf0d8308SStephan Aßmus 
177cf0d8308SStephan Aßmus 	// Add the tool icons.
178cf0d8308SStephan Aßmus 
17994a4c1c4SAugustin Cavalier //	fToolBar->AddAction(MSG_FILE_OPEN, be_app,
180cf0d8308SStephan Aßmus //		tool_bar_icon(kIconDocumentOpen), B_TRANSLATE("Open" B_UTF8_ELLIPSIS));
18194a4c1c4SAugustin Cavalier 	fToolBar->AddAction(MSG_FILE_PREV, this,
18258ee42e9SAugustin Cavalier 		tool_bar_icon(kIconGoPrevious), B_TRANSLATE("Previous file"));
18394a4c1c4SAugustin Cavalier 	fToolBar->AddAction(MSG_FILE_NEXT, this, tool_bar_icon(kIconGoNext),
18458ee42e9SAugustin Cavalier 		B_TRANSLATE("Next file"));
185a877c0e7SStephan Aßmus 	BMessage* fullScreenSlideShow = new BMessage(MSG_SLIDE_SHOW);
186a877c0e7SStephan Aßmus 	fullScreenSlideShow->AddBool("full screen", true);
18794a4c1c4SAugustin Cavalier 	fToolBar->AddAction(fullScreenSlideShow, this,
18858ee42e9SAugustin Cavalier 		tool_bar_icon(kIconMediaMovieLibrary), B_TRANSLATE("Slide show"));
18994a4c1c4SAugustin Cavalier 	fToolBar->AddSeparator();
19094a4c1c4SAugustin Cavalier 	fToolBar->AddAction(MSG_SELECTION_MODE, this,
191cf0d8308SStephan Aßmus 		tool_bar_icon(kIconDrawRectangularSelection),
19258ee42e9SAugustin Cavalier 		B_TRANSLATE("Selection mode"));
19394a4c1c4SAugustin Cavalier 	fToolBar->AddSeparator();
19494a4c1c4SAugustin Cavalier 	fToolBar->AddAction(kMsgOriginalSize, this,
19558ee42e9SAugustin Cavalier 		tool_bar_icon(kIconZoomOriginal), B_TRANSLATE("Original size"), NULL,
19658ee42e9SAugustin Cavalier 		true);
19794a4c1c4SAugustin Cavalier 	fToolBar->AddAction(kMsgFitToWindow, this,
19858ee42e9SAugustin Cavalier 		tool_bar_icon(kIconZoomFitBest), B_TRANSLATE("Fit to window"));
19994a4c1c4SAugustin Cavalier 	fToolBar->AddAction(MSG_ZOOM_IN, this, tool_bar_icon(kIconZoomIn),
20058ee42e9SAugustin Cavalier 		B_TRANSLATE("Zoom in"));
20194a4c1c4SAugustin Cavalier 	fToolBar->AddAction(MSG_ZOOM_OUT, this, tool_bar_icon(kIconZoomOut),
20258ee42e9SAugustin Cavalier 		B_TRANSLATE("Zoom out"));
203442e457dSGerasim Troeglazov 	fToolBar->AddSeparator();
204442e457dSGerasim Troeglazov 	fToolBar->AddAction(MSG_PAGE_PREV, this, tool_bar_icon(kIconPagePrevious),
20558ee42e9SAugustin Cavalier 		B_TRANSLATE("Previous page"));
206442e457dSGerasim Troeglazov 	fToolBar->AddAction(MSG_PAGE_NEXT, this, tool_bar_icon(kIconPageNext),
20758ee42e9SAugustin Cavalier 		B_TRANSLATE("Next page"));
20894a4c1c4SAugustin Cavalier 	fToolBar->AddGlue();
20994a4c1c4SAugustin Cavalier 	fToolBar->AddAction(MSG_FULL_SCREEN, this,
21058ee42e9SAugustin Cavalier 		tool_bar_icon(kIconViewWindowed), B_TRANSLATE("Leave full screen"));
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);
396fb94ed11SAvi Brenner 	_AddItemMenu(menu, B_TRANSLATE("Get info" B_UTF8_ELLIPSIS),
397fb94ed11SAvi Brenner 		MSG_GET_INFO, 'I', 0, this);
398efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
399905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Page setup" B_UTF8_ELLIPSIS),
4001ed4535fSStephan Aßmus 		MSG_PAGE_SETUP, 0, 0, this);
401905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Print" B_UTF8_ELLIPSIS),
4021ed4535fSStephan Aßmus 		MSG_PREPARE_PRINT, 'P', 0, this);
403efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
404905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Quit"), B_QUIT_REQUESTED, 'Q', 0, be_app);
405efa8b4f3SAxel Dörfler 	bar->AddItem(menu);
40613afa642SPhil Greenway 
407905c8c8cSMatt Madia 	menu = new BMenu(B_TRANSLATE("Edit"));
408905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Copy"), B_COPY, 'C', 0, this, false);
409efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
410cf0d8308SStephan Aßmus 	_AddItemMenu(menu, B_TRANSLATE("Selection mode"), MSG_SELECTION_MODE, 0, 0,
4116db01936SAxel Dörfler 		this);
41232c22143SAxel Dörfler 	_AddItemMenu(menu, B_TRANSLATE("Clear selection"),
41332c22143SAxel Dörfler 		MSG_CLEAR_SELECT, 0, 0, this, false);
414905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Select all"),
415905c8c8cSMatt Madia 		MSG_SELECT_ALL, 'A', 0, this);
416efa8b4f3SAxel Dörfler 	bar->AddItem(menu);
41713afa642SPhil Greenway 
418905c8c8cSMatt Madia 	menu = fBrowseMenu = new BMenu(B_TRANSLATE("Browse"));
419905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("First page"),
4201ed4535fSStephan Aßmus 		MSG_PAGE_FIRST, B_LEFT_ARROW, B_SHIFT_KEY, this);
421905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Last page"),
4221ed4535fSStephan Aßmus 		MSG_PAGE_LAST, B_RIGHT_ARROW, B_SHIFT_KEY, this);
423905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Previous page"),
424905c8c8cSMatt Madia 		MSG_PAGE_PREV, B_LEFT_ARROW, 0, this);
425905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Next page"),
426905c8c8cSMatt Madia 		MSG_PAGE_NEXT, B_RIGHT_ARROW, 0, this);
427905c8c8cSMatt Madia 	fGoToPageMenu = new BMenu(B_TRANSLATE("Go to page"));
4285e427b6aSMichael Pfeiffer 	fGoToPageMenu->SetRadioMode(true);
429efa8b4f3SAxel Dörfler 	menu->AddItem(fGoToPageMenu);
430efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
431905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Previous file"),
432905c8c8cSMatt Madia 		MSG_FILE_PREV, B_UP_ARROW, 0, this);
433905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Next file"),
434905c8c8cSMatt Madia 		MSG_FILE_NEXT, B_DOWN_ARROW, 0, this);
435efa8b4f3SAxel Dörfler 	bar->AddItem(menu);
43603839579SMatthew Wilber 
437905c8c8cSMatt Madia 	menu = new BMenu(B_TRANSLATE("Image"));
438905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Rotate clockwise"),
439905c8c8cSMatt Madia 		MSG_ROTATE_90, 'R', 0, this);
440905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Rotate counterclockwise"),
4411ed4535fSStephan Aßmus 		MSG_ROTATE_270, 'R', B_SHIFT_KEY, this);
442efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
443905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Flip left to right"),
4441ed4535fSStephan Aßmus 		MSG_FLIP_LEFT_TO_RIGHT, 0, 0, this);
445905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Flip top to bottom"),
4461ed4535fSStephan Aßmus 		MSG_FLIP_TOP_TO_BOTTOM, 0, 0, this);
447efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
448905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Use as background" B_UTF8_ELLIPSIS),
4491ed4535fSStephan Aßmus 		MSG_DESKTOP_BACKGROUND, 0, 0, this);
45004f96544SAxel Dörfler 
45104f96544SAxel Dörfler 	bar->AddItem(menu);
45213afa642SPhil Greenway }
45313afa642SPhil Greenway 
454efa8b4f3SAxel Dörfler 
455cdb89ebbSMatthew Wilber BMenuItem*
456fd952aefSRyan Leavengood ShowImageWindow::_AddItemMenu(BMenu* menu, const char* label, uint32 what,
4574fd570d3SAxel Dörfler 	char shortcut, uint32 modifier, const BHandler* target, bool enabled)
458cdb89ebbSMatthew Wilber {
4594fd570d3SAxel Dörfler 	BMenuItem* item = new BMenuItem(label, new BMessage(what), shortcut,
4604fd570d3SAxel Dörfler 		modifier);
461efa8b4f3SAxel Dörfler 	menu->AddItem(item);
462efa8b4f3SAxel Dörfler 
4636163f333SKarsten Heimrich 	item->SetTarget(target);
4646163f333SKarsten Heimrich 	item->SetEnabled(enabled);
4656163f333SKarsten Heimrich 
466efa8b4f3SAxel Dörfler 	return item;
46713afa642SPhil Greenway }
46813afa642SPhil Greenway 
469efa8b4f3SAxel Dörfler 
470ad13f387SMichael Pfeiffer BMenuItem*
4714aa63633SAxel Dörfler ShowImageWindow::_AddDelayItem(BMenu* menu, const char* label, bigtime_t delay)
472ad13f387SMichael Pfeiffer {
473efa8b4f3SAxel Dörfler 	BMessage* message = new BMessage(MSG_SLIDE_SHOW_DELAY);
4744aa63633SAxel Dörfler 	message->AddInt64("delay", delay);
475ad13f387SMichael Pfeiffer 
4766163f333SKarsten Heimrich 	BMenuItem* item = new BMenuItem(label, message, 0);
477efa8b4f3SAxel Dörfler 	item->SetTarget(this);
478ad13f387SMichael Pfeiffer 
4794aa63633SAxel Dörfler 	if (delay == fSlideShowDelay)
480efa8b4f3SAxel Dörfler 		item->SetMarked(true);
481ad13f387SMichael Pfeiffer 
482efa8b4f3SAxel Dörfler 	menu->AddItem(item);
483efa8b4f3SAxel Dörfler 	return item;
484ad13f387SMichael Pfeiffer }
485ad13f387SMichael Pfeiffer 
486efa8b4f3SAxel Dörfler 
487cdb89ebbSMatthew Wilber void
488e2069723SAxel Dörfler ShowImageWindow::_ResizeWindowToImage()
48913afa642SPhil Greenway {
490e2069723SAxel Dörfler 	BBitmap* bitmap = fImageView->Bitmap();
491d10d5947SMichael Pfeiffer 	BScreen screen;
492e2069723SAxel Dörfler 	if (bitmap == NULL || !screen.IsValid())
493efa8b4f3SAxel Dörfler 		return;
494efa8b4f3SAxel Dörfler 
4951076d97bSAxel Dörfler 	// TODO: use View::GetPreferredSize() instead?
4961076d97bSAxel Dörfler 	BRect r(bitmap->Bounds());
4971076d97bSAxel Dörfler 	float width = r.Width() + B_V_SCROLL_BAR_WIDTH;
4981076d97bSAxel Dörfler 	float height = r.Height() + 1 + fBar->Frame().Height()
4991076d97bSAxel Dörfler 		+ B_H_SCROLL_BAR_HEIGHT;
500cdb89ebbSMatthew Wilber 
5016163f333SKarsten Heimrich 	BRect frame = screen.Frame();
5026163f333SKarsten Heimrich 	const float windowBorder = 5;
503d10d5947SMichael Pfeiffer 	// dimensions so that window does not reach outside of screen
5046163f333SKarsten Heimrich 	float maxWidth = frame.Width() + 1 - windowBorder - Frame().left;
5056163f333SKarsten Heimrich 	float maxHeight = frame.Height() + 1 - windowBorder - Frame().top;
506cdb89ebbSMatthew Wilber 
507a8fc7138SMichael Pfeiffer 	// We have to check size limits manually, otherwise
508a8fc7138SMichael Pfeiffer 	// menu bar will be too short for small images.
509efa8b4f3SAxel Dörfler 
510fc5ca95dSStephan Aßmus 	float minW, maxW, minH, maxH;
511a8fc7138SMichael Pfeiffer 	GetSizeLimits(&minW, &maxW, &minH, &maxH);
512efa8b4f3SAxel Dörfler 	if (maxWidth > maxW)
513efa8b4f3SAxel Dörfler 		maxWidth = maxW;
514efa8b4f3SAxel Dörfler 	if (maxHeight > maxH)
515efa8b4f3SAxel Dörfler 		maxHeight = maxH;
516efa8b4f3SAxel Dörfler 	if (width < minW)
517efa8b4f3SAxel Dörfler 		width = minW;
518efa8b4f3SAxel Dörfler 	if (height < minH)
519efa8b4f3SAxel Dörfler 		height = minH;
520a8fc7138SMichael Pfeiffer 
521efa8b4f3SAxel Dörfler 	if (width > maxWidth)
522efa8b4f3SAxel Dörfler 		width = maxWidth;
523efa8b4f3SAxel Dörfler 	if (height > maxHeight)
524efa8b4f3SAxel Dörfler 		height = maxHeight;
525d10d5947SMichael Pfeiffer 
526d10d5947SMichael Pfeiffer 	ResizeTo(width, height);
52713afa642SPhil Greenway }
52813afa642SPhil Greenway 
529efa8b4f3SAxel Dörfler 
5307eca0987SMichael Pfeiffer bool
531fd952aefSRyan Leavengood ShowImageWindow::_ToggleMenuItem(uint32 what)
5327eca0987SMichael Pfeiffer {
5337eca0987SMichael Pfeiffer 	bool marked = false;
5346163f333SKarsten Heimrich 	BMenuItem* item = fBar->FindItem(what);
5357eca0987SMichael Pfeiffer 	if (item != NULL) {
5367eca0987SMichael Pfeiffer 		marked = !item->IsMarked();
5377eca0987SMichael Pfeiffer 		item->SetMarked(marked);
5387eca0987SMichael Pfeiffer 	}
53994a4c1c4SAugustin Cavalier 	fToolBar->SetActionPressed(what, marked);
5407eca0987SMichael Pfeiffer 	return marked;
5417eca0987SMichael Pfeiffer }
5427eca0987SMichael Pfeiffer 
543efa8b4f3SAxel Dörfler 
544cdb89ebbSMatthew Wilber void
545fd952aefSRyan Leavengood ShowImageWindow::_EnableMenuItem(BMenu* menu, uint32 what, bool enable)
546e6a50d9cSMichael Pfeiffer {
5476163f333SKarsten Heimrich 	BMenuItem* item = menu->FindItem(what);
5486163f333SKarsten Heimrich 	if (item && item->IsEnabled() != enable)
549e6a50d9cSMichael Pfeiffer 		item->SetEnabled(enable);
55094a4c1c4SAugustin Cavalier 	fToolBar->SetActionEnabled(what, enable);
551e6a50d9cSMichael Pfeiffer }
552e6a50d9cSMichael Pfeiffer 
553efa8b4f3SAxel Dörfler 
554e6a50d9cSMichael Pfeiffer void
555fd952aefSRyan Leavengood ShowImageWindow::_MarkMenuItem(BMenu* menu, uint32 what, bool marked)
556e6a50d9cSMichael Pfeiffer {
5576163f333SKarsten Heimrich 	BMenuItem* item = menu->FindItem(what);
5586163f333SKarsten Heimrich 	if (item && item->IsMarked() != marked)
559e6a50d9cSMichael Pfeiffer 		item->SetMarked(marked);
56094a4c1c4SAugustin Cavalier 	fToolBar->SetActionPressed(what, marked);
561e6a50d9cSMichael Pfeiffer }
562e6a50d9cSMichael Pfeiffer 
563efa8b4f3SAxel Dörfler 
564da87390fSMichael Pfeiffer void
5654aa63633SAxel Dörfler ShowImageWindow::_MarkSlideShowDelay(bigtime_t delay)
566da87390fSMichael Pfeiffer {
5674aa63633SAxel Dörfler 	const int32 count = fSlideShowDelayMenu->CountItems();
5684aa63633SAxel Dörfler 	for (int32 i = 0; i < count; i ++) {
5694aa63633SAxel Dörfler 		BMenuItem* item = fSlideShowDelayMenu->ItemAt(i);
5704aa63633SAxel Dörfler 		if (item != NULL) {
5714aa63633SAxel Dörfler 			bigtime_t itemDelay;
5724aa63633SAxel Dörfler 			if (item->Message()->FindInt64("delay", &itemDelay) == B_OK
5734aa63633SAxel Dörfler 				&& itemDelay == delay) {
574da87390fSMichael Pfeiffer 				item->SetMarked(true);
575da87390fSMichael Pfeiffer 				return;
576da87390fSMichael Pfeiffer 			}
577da87390fSMichael Pfeiffer 		}
578da87390fSMichael Pfeiffer 	}
579da87390fSMichael Pfeiffer }
580e6a50d9cSMichael Pfeiffer 
58119c76de4SMichael Pfeiffer 
58219c76de4SMichael Pfeiffer void
583e2069723SAxel Dörfler ShowImageWindow::Zoom(BPoint origin, float width, float height)
58419c76de4SMichael Pfeiffer {
585e2069723SAxel Dörfler 	_ToggleFullScreen();
58619c76de4SMichael Pfeiffer }
58719c76de4SMichael Pfeiffer 
588efa8b4f3SAxel Dörfler 
589e6a50d9cSMichael Pfeiffer void
590efa8b4f3SAxel Dörfler ShowImageWindow::MessageReceived(BMessage* message)
59113afa642SPhil Greenway {
592e2069723SAxel Dörfler 	if (message->WasDropped()) {
593e2069723SAxel Dörfler 		uint32 type;
594e2069723SAxel Dörfler 		int32 count;
595e2069723SAxel Dörfler 		status_t status = message->GetInfo("refs", &type, &count);
596e2069723SAxel Dörfler 		if (status == B_OK && type == B_REF_TYPE) {
597e2069723SAxel Dörfler 			message->what = B_REFS_RECEIVED;
598e2069723SAxel Dörfler 			be_app->PostMessage(message);
599e2069723SAxel Dörfler 		}
600e2069723SAxel Dörfler 	}
601e2069723SAxel Dörfler 
602efa8b4f3SAxel Dörfler 	switch (message->what) {
603e2069723SAxel Dörfler 		case kMsgImageCacheImageLoaded:
604cd6b5cdeSAxel Dörfler 		{
605e2069723SAxel Dörfler 			fProgressWindow->Stop();
606e2069723SAxel Dörfler 
607df942b3eSAxel Dörfler 			BitmapOwner* bitmapOwner = NULL;
608df942b3eSAxel Dörfler 			message->FindPointer("bitmapOwner", (void**)&bitmapOwner);
609df942b3eSAxel Dörfler 
610cd6b5cdeSAxel Dörfler 			bool first = fImageView->Bitmap() == NULL;
611b9767a83SAxel Dörfler 			entry_ref ref;
612b9767a83SAxel Dörfler 			message->FindRef("ref", &ref);
613b9767a83SAxel Dörfler 			if (!first && ref != fNavigator.CurrentRef()) {
614b9767a83SAxel Dörfler 				// ignore older images
615df942b3eSAxel Dörfler 				if (bitmapOwner != NULL)
616df942b3eSAxel Dörfler 					bitmapOwner->ReleaseReference();
617b9767a83SAxel Dörfler 				break;
618b9767a83SAxel Dörfler 			}
619cd6b5cdeSAxel Dörfler 
620baa27ccbSJanus 			int32 page = message->FindInt32("page");
621baa27ccbSJanus 			int32 pageCount = message->FindInt32("pageCount");
622baa27ccbSJanus 			if (!first && page != fNavigator.CurrentPage()) {
623baa27ccbSJanus 				// ignore older pages
624baa27ccbSJanus 				if (bitmapOwner != NULL)
625baa27ccbSJanus 					bitmapOwner->ReleaseReference();
626baa27ccbSJanus 				break;
627baa27ccbSJanus 			}
628baa27ccbSJanus 
629cd6b5cdeSAxel Dörfler 			status_t status = fImageView->SetImage(message);
630cd6b5cdeSAxel Dörfler 			if (status != B_OK) {
631df942b3eSAxel Dörfler 				if (bitmapOwner != NULL)
632df942b3eSAxel Dörfler 					bitmapOwner->ReleaseReference();
633df942b3eSAxel Dörfler 
634cd6b5cdeSAxel Dörfler 				_LoadError(ref);
635cd6b5cdeSAxel Dörfler 
636cd6b5cdeSAxel Dörfler 				// quit if file could not be opened
637cd6b5cdeSAxel Dörfler 				if (first)
638cd6b5cdeSAxel Dörfler 					Quit();
639cd6b5cdeSAxel Dörfler 				break;
640cd6b5cdeSAxel Dörfler 			}
641cd6b5cdeSAxel Dörfler 
642cd6b5cdeSAxel Dörfler 			fImageType = message->FindString("type");
643baa27ccbSJanus 			fNavigator.SetTo(ref, page, pageCount);
644cd6b5cdeSAxel Dörfler 
645e2069723SAxel Dörfler 			fImageView->FitToBounds();
646cd6b5cdeSAxel Dörfler 			if (first) {
647cd6b5cdeSAxel Dörfler 				fImageView->MakeFocus(true);
648cd6b5cdeSAxel Dörfler 					// to receive key messages
649cd6b5cdeSAxel Dörfler 				Show();
650e2069723SAxel Dörfler 			}
6515b76e505SStephan Aßmus 			_UpdateRatingMenu();
652e62a6973SJanus 			// Set width and height attributes of the currently showed file.
653e62a6973SJanus 			// This should only be a temporary solution.
654e62a6973SJanus 			_SaveWidthAndHeight();
655e2069723SAxel Dörfler 			break;
656e2069723SAxel Dörfler 		}
657e2069723SAxel Dörfler 
658e2069723SAxel Dörfler 		case kMsgImageCacheProgressUpdate:
659e2069723SAxel Dörfler 		{
660e2069723SAxel Dörfler 			entry_ref ref;
661e2069723SAxel Dörfler 			if (message->FindRef("ref", &ref) == B_OK
662e2069723SAxel Dörfler 				&& ref == fNavigator.CurrentRef()) {
663e2069723SAxel Dörfler 				message->what = kMsgProgressUpdate;
664e2069723SAxel Dörfler 				fProgressWindow->PostMessage(message);
665cd6b5cdeSAxel Dörfler 			}
666cd6b5cdeSAxel Dörfler 			break;
667cd6b5cdeSAxel Dörfler 		}
668cd6b5cdeSAxel Dörfler 
669ee7b4f39SMatthew Wilber 		case MSG_MODIFIED:
670ee7b4f39SMatthew Wilber 			// If image has been modified due to a Cut or Paste
671ee7b4f39SMatthew Wilber 			fModified = true;
672ee7b4f39SMatthew Wilber 			break;
673ee7b4f39SMatthew Wilber 
674fc0a275bSMatthew Wilber 		case MSG_OUTPUT_TYPE:
675fc0a275bSMatthew Wilber 			// User clicked Save As then choose an output format
676d3046f7dSMichael Pfeiffer 			if (!fSavePanel)
677cdb89ebbSMatthew Wilber 				// If user doesn't already have a save panel open
678fd952aefSRyan Leavengood 				_SaveAs(message);
67913afa642SPhil Greenway 			break;
680fc0a275bSMatthew Wilber 
681fc0a275bSMatthew Wilber 		case MSG_SAVE_PANEL:
682fc0a275bSMatthew Wilber 			// User specified where to save the output image
683fd952aefSRyan Leavengood 			_SaveToFile(message);
68407caaa8eSMatthew Wilber 			break;
68507caaa8eSMatthew Wilber 
686cdb89ebbSMatthew Wilber 		case B_CANCEL:
687d3046f7dSMichael Pfeiffer 			delete fSavePanel;
688d3046f7dSMichael Pfeiffer 			fSavePanel = NULL;
689cdb89ebbSMatthew Wilber 			break;
690cdb89ebbSMatthew Wilber 
6916db01936SAxel Dörfler 		case MSG_UPDATE_STATUS:
6926db01936SAxel Dörfler 		{
693cd6b5cdeSAxel Dörfler 			int32 pages = fNavigator.PageCount();
694cd6b5cdeSAxel Dörfler 			int32 currentPage = fNavigator.CurrentPage();
6956c305411SMatthew Wilber 
696baa27ccbSJanus 			_EnableMenuItem(fBar, MSG_PAGE_FIRST,
697baa27ccbSJanus 				fNavigator.HasPreviousPage());
698baa27ccbSJanus 			_EnableMenuItem(fBar, MSG_PAGE_LAST, fNavigator.HasNextPage());
699baa27ccbSJanus 			_EnableMenuItem(fBar, MSG_PAGE_NEXT, fNavigator.HasNextPage());
700baa27ccbSJanus 			_EnableMenuItem(fBar, MSG_PAGE_PREV, fNavigator.HasPreviousPage());
701baa27ccbSJanus 			fGoToPageMenu->SetEnabled(pages > 1);
7021d592070SMatthew Wilber 
703cd6b5cdeSAxel Dörfler 			_EnableMenuItem(fBar, MSG_FILE_NEXT, fNavigator.HasNextFile());
704cd6b5cdeSAxel Dörfler 			_EnableMenuItem(fBar, MSG_FILE_PREV, fNavigator.HasPreviousFile());
705134d6076SMichael Pfeiffer 
706d3046f7dSMichael Pfeiffer 			if (fGoToPageMenu->CountItems() != pages) {
7076c305411SMatthew Wilber 				// Only rebuild the submenu if the number of
7086c305411SMatthew Wilber 				// pages is different
7096c305411SMatthew Wilber 
710cd6b5cdeSAxel Dörfler 				while (fGoToPageMenu->CountItems() > 0) {
7116c305411SMatthew Wilber 					// Remove all page numbers
7127f4d1af4SSergei Reznikov 					delete fGoToPageMenu->RemoveItem((int32)0);
713cd6b5cdeSAxel Dörfler 				}
7146c305411SMatthew Wilber 
715780d8a62SMichael Pfeiffer 				for (int32 i = 1; i <= pages; i++) {
7166c305411SMatthew Wilber 					// Fill Go To page submenu with an entry for each page
717cd6b5cdeSAxel Dörfler 					BMessage* goTo = new BMessage(MSG_GOTO_PAGE);
718cd6b5cdeSAxel Dörfler 					goTo->AddInt32("page", i);
7196163f333SKarsten Heimrich 
7206163f333SKarsten Heimrich 					char shortcut = 0;
721cd6b5cdeSAxel Dörfler 					if (i < 10)
722780d8a62SMichael Pfeiffer 						shortcut = '0' + i;
7236163f333SKarsten Heimrich 
7246163f333SKarsten Heimrich 					BString strCaption;
7256163f333SKarsten Heimrich 					strCaption << i;
7266163f333SKarsten Heimrich 
727cd6b5cdeSAxel Dörfler 					BMenuItem* item = new BMenuItem(strCaption.String(), goTo,
728a8199d69Sthreedeyes 						shortcut, B_SHIFT_KEY);
729cd6b5cdeSAxel Dörfler 					if (currentPage == i)
730efa8b4f3SAxel Dörfler 						item->SetMarked(true);
731efa8b4f3SAxel Dörfler 					fGoToPageMenu->AddItem(item);
7326c305411SMatthew Wilber 				}
7336c305411SMatthew Wilber 			} else {
7346c305411SMatthew Wilber 				// Make sure the correct page is marked
735cd6b5cdeSAxel Dörfler 				BMenuItem* currentItem = fGoToPageMenu->ItemAt(currentPage - 1);
736cd6b5cdeSAxel Dörfler 				if (currentItem != NULL && !currentItem->IsMarked())
737cd6b5cdeSAxel Dörfler 					currentItem->SetMarked(true);
7386c305411SMatthew Wilber 			}
7396c305411SMatthew Wilber 
740cd6b5cdeSAxel Dörfler 			_UpdateStatusText(message);
741b9767a83SAxel Dörfler 
742b9767a83SAxel Dörfler 			BPath path(fImageView->Image());
743b9767a83SAxel Dörfler 			SetTitle(path.Path());
7446db01936SAxel Dörfler 			break;
7456db01936SAxel Dörfler 		}
74603839579SMatthew Wilber 
7476db01936SAxel Dörfler 		case MSG_UPDATE_STATUS_TEXT:
7486db01936SAxel Dörfler 		{
749cd6b5cdeSAxel Dörfler 			_UpdateStatusText(message);
7506db01936SAxel Dörfler 			break;
7516db01936SAxel Dörfler 		}
7528f5fd23fSRyan Leavengood 
7536db01936SAxel Dörfler 		case MSG_SELECTION:
7546db01936SAxel Dörfler 		{
7558ad30bcfSMatthew Wilber 			// The view sends this message when a selection is
7568ad30bcfSMatthew Wilber 			// made or the selection is cleared so that the window
7578ad30bcfSMatthew Wilber 			// can update the state of the appropriate menu items
7586db01936SAxel Dörfler 			bool enable;
7596db01936SAxel Dörfler 			if (message->FindBool("has_selection", &enable) == B_OK) {
7606db01936SAxel Dörfler 				_EnableMenuItem(fBar, B_COPY, enable);
7616db01936SAxel Dörfler 				_EnableMenuItem(fBar, MSG_CLEAR_SELECT, enable);
7628ad30bcfSMatthew Wilber 			}
7636db01936SAxel Dörfler 			break;
7646db01936SAxel Dörfler 		}
7658ad30bcfSMatthew Wilber 
76613afa642SPhil Greenway 		case B_COPY:
767d3046f7dSMichael Pfeiffer 			fImageView->CopySelectionToClipboard();
76813afa642SPhil Greenway 			break;
7696163f333SKarsten Heimrich 
7706db01936SAxel Dörfler 		case MSG_SELECTION_MODE:
771cf0d8308SStephan Aßmus 		{
772cf0d8308SStephan Aßmus 			bool selectionMode = _ToggleMenuItem(MSG_SELECTION_MODE);
773cf0d8308SStephan Aßmus 			fImageView->SetSelectionMode(selectionMode);
774cf0d8308SStephan Aßmus 			if (!selectionMode)
775cf0d8308SStephan Aßmus 				fImageView->ClearSelection();
7766db01936SAxel Dörfler 			break;
777cf0d8308SStephan Aßmus 		}
7786db01936SAxel Dörfler 
77913afa642SPhil Greenway 		case MSG_CLEAR_SELECT:
780d3046f7dSMichael Pfeiffer 			fImageView->ClearSelection();
78113afa642SPhil Greenway 			break;
7826163f333SKarsten Heimrich 
78313afa642SPhil Greenway 		case MSG_SELECT_ALL:
784d3046f7dSMichael Pfeiffer 			fImageView->SelectAll();
78513afa642SPhil Greenway 			break;
78613afa642SPhil Greenway 
78703839579SMatthew Wilber 		case MSG_PAGE_FIRST:
788b9767a83SAxel Dörfler 			if (_ClosePrompt() && fNavigator.FirstPage())
789b9767a83SAxel Dörfler 				_LoadImage();
79003839579SMatthew Wilber 			break;
79103839579SMatthew Wilber 
79203839579SMatthew Wilber 		case MSG_PAGE_LAST:
793b9767a83SAxel Dörfler 			if (_ClosePrompt() && fNavigator.LastPage())
794b9767a83SAxel Dörfler 				_LoadImage();
79503839579SMatthew Wilber 			break;
79603839579SMatthew Wilber 
79703839579SMatthew Wilber 		case MSG_PAGE_NEXT:
798b9767a83SAxel Dörfler 			if (_ClosePrompt() && fNavigator.NextPage())
799b9767a83SAxel Dörfler 				_LoadImage();
80003839579SMatthew Wilber 			break;
80103839579SMatthew Wilber 
80203839579SMatthew Wilber 		case MSG_PAGE_PREV:
803b9767a83SAxel Dörfler 			if (_ClosePrompt() && fNavigator.PreviousPage())
804b9767a83SAxel Dörfler 				_LoadImage();
80503839579SMatthew Wilber 			break;
80603839579SMatthew Wilber 
807cd6b5cdeSAxel Dörfler 		case MSG_GOTO_PAGE:
808cd6b5cdeSAxel Dörfler 		{
809fd952aefSRyan Leavengood 			if (!_ClosePrompt())
810ee7b4f39SMatthew Wilber 				break;
811ee7b4f39SMatthew Wilber 
8126163f333SKarsten Heimrich 			int32 newPage;
8136163f333SKarsten Heimrich 			if (message->FindInt32("page", &newPage) != B_OK)
8146163f333SKarsten Heimrich 				break;
8156163f333SKarsten Heimrich 
816cd6b5cdeSAxel Dörfler 			int32 currentPage = fNavigator.CurrentPage();
817cd6b5cdeSAxel Dörfler 			int32 pages = fNavigator.PageCount();
8186c305411SMatthew Wilber 
819b9767a83SAxel Dörfler 			// TODO: use radio mode instead!
8206c305411SMatthew Wilber 			if (newPage > 0 && newPage <= pages) {
821cd6b5cdeSAxel Dörfler 				BMenuItem* currentItem = fGoToPageMenu->ItemAt(currentPage - 1);
822cd6b5cdeSAxel Dörfler 				BMenuItem* newItem = fGoToPageMenu->ItemAt(newPage - 1);
823cd6b5cdeSAxel Dörfler 				if (currentItem != NULL && newItem != NULL) {
824cd6b5cdeSAxel Dörfler 					currentItem->SetMarked(false);
825cd6b5cdeSAxel Dörfler 					newItem->SetMarked(true);
826b9767a83SAxel Dörfler 					if (fNavigator.GoToPage(newPage))
827b9767a83SAxel Dörfler 						_LoadImage();
8286c305411SMatthew Wilber 				}
8296c305411SMatthew Wilber 			}
830cd6b5cdeSAxel Dörfler 			break;
831cd6b5cdeSAxel Dörfler 		}
8326c305411SMatthew Wilber 
833e2069723SAxel Dörfler 		case kMsgFitToWindow:
834e2069723SAxel Dörfler 			fImageView->FitToBounds();
83519c76de4SMichael Pfeiffer 			break;
8366163f333SKarsten Heimrich 
837e2069723SAxel Dörfler 		case kMsgStretchToWindow:
838e2069723SAxel Dörfler 			fImageView->SetStretchToBounds(
839e2069723SAxel Dörfler 				_ToggleMenuItem(kMsgStretchToWindow));
8407eca0987SMichael Pfeiffer 			break;
8417eca0987SMichael Pfeiffer 
8427eca0987SMichael Pfeiffer 		case MSG_FILE_PREV:
843b9767a83SAxel Dörfler 			if (_ClosePrompt() && fNavigator.PreviousFile())
844a569816bSAxel Dörfler 				_LoadImage(false);
8457eca0987SMichael Pfeiffer 			break;
8467eca0987SMichael Pfeiffer 
8477eca0987SMichael Pfeiffer 		case MSG_FILE_NEXT:
8484aa63633SAxel Dörfler 		case kMsgNextSlide:
84947df2afbSRyan Leavengood 			if (_ClosePrompt()) {
85047df2afbSRyan Leavengood 				if (!fNavigator.NextFile()) {
85147df2afbSRyan Leavengood 					// Wrap back around
85247df2afbSRyan Leavengood 					fNavigator.FirstFile();
85347df2afbSRyan Leavengood 				}
854b9767a83SAxel Dörfler 				_LoadImage();
85547df2afbSRyan Leavengood 			}
85613afa642SPhil Greenway 			break;
85713afa642SPhil Greenway 
858328932acSAxel Dörfler 		case kMsgDeleteCurrentFile:
859b9767a83SAxel Dörfler 		{
860b9767a83SAxel Dörfler 			if (fNavigator.MoveFileToTrash())
861b9767a83SAxel Dörfler 				_LoadImage();
862b9767a83SAxel Dörfler 			else
863328932acSAxel Dörfler 				PostMessage(B_QUIT_REQUESTED);
864328932acSAxel Dörfler 			break;
865b9767a83SAxel Dörfler 		}
866328932acSAxel Dörfler 
867bf461dbeSMatthew Wilber 		case MSG_ROTATE_90:
868d3046f7dSMichael Pfeiffer 			fImageView->Rotate(90);
869ad13f387SMichael Pfeiffer 			break;
8706163f333SKarsten Heimrich 
871bf461dbeSMatthew Wilber 		case MSG_ROTATE_270:
872d3046f7dSMichael Pfeiffer 			fImageView->Rotate(270);
873ad13f387SMichael Pfeiffer 			break;
8746163f333SKarsten Heimrich 
87569eee339SRyan Leavengood 		case MSG_FLIP_LEFT_TO_RIGHT:
87661ddc257SRyan Leavengood 			fImageView->Flip(true);
877ad13f387SMichael Pfeiffer 			break;
8786163f333SKarsten Heimrich 
87969eee339SRyan Leavengood 		case MSG_FLIP_TOP_TO_BOTTOM:
88061ddc257SRyan Leavengood 			fImageView->Flip(false);
881ad13f387SMichael Pfeiffer 			break;
8826163f333SKarsten Heimrich 
883fb94ed11SAvi Brenner 		case MSG_GET_INFO:
884fb94ed11SAvi Brenner 			_GetFileInfo(fNavigator.CurrentRef());
885fb94ed11SAvi Brenner 			break;
886fb94ed11SAvi Brenner 
8871076d97bSAxel Dörfler 		case MSG_SLIDE_SHOW:
8881076d97bSAxel Dörfler 		{
88994fd9498SStephan Aßmus 			bool fullScreen = false;
89094fd9498SStephan Aßmus 			message->FindBool("full screen", &fullScreen);
891a877c0e7SStephan Aßmus 
8926163f333SKarsten Heimrich 			BMenuItem* item = fBar->FindItem(message->what);
8934aa63633SAxel Dörfler 			if (item == NULL)
894ee7b4f39SMatthew Wilber 				break;
8954aa63633SAxel Dörfler 
896ee7b4f39SMatthew Wilber 			if (item->IsMarked()) {
897ee7b4f39SMatthew Wilber 				item->SetMarked(false);
8984aa63633SAxel Dörfler 				_StopSlideShow();
89994a4c1c4SAugustin Cavalier 				fToolBar->SetActionPressed(MSG_SLIDE_SHOW, false);
900fd952aefSRyan Leavengood 			} else if (_ClosePrompt()) {
901ee7b4f39SMatthew Wilber 				item->SetMarked(true);
90294fd9498SStephan Aßmus 				if (!fFullScreen && fullScreen)
90394fd9498SStephan Aßmus 					_ToggleFullScreen();
9044aa63633SAxel Dörfler 				_StartSlideShow();
90594a4c1c4SAugustin Cavalier 				fToolBar->SetActionPressed(MSG_SLIDE_SHOW, true);
906ad13f387SMichael Pfeiffer 			}
9071076d97bSAxel Dörfler 			break;
9081076d97bSAxel Dörfler 		}
909ee7b4f39SMatthew Wilber 
9104aa63633SAxel Dörfler 		case kMsgStopSlideShow:
9114aa63633SAxel Dörfler 		{
9124aa63633SAxel Dörfler 			BMenuItem* item = fBar->FindItem(MSG_SLIDE_SHOW);
9134aa63633SAxel Dörfler 			if (item != NULL)
9144aa63633SAxel Dörfler 				item->SetMarked(false);
9154aa63633SAxel Dörfler 
9164aa63633SAxel Dörfler 			_StopSlideShow();
91794a4c1c4SAugustin Cavalier 			fToolBar->SetActionPressed(MSG_SLIDE_SHOW, false);
9184aa63633SAxel Dörfler 			break;
9194aa63633SAxel Dörfler 		}
9204aa63633SAxel Dörfler 
9211076d97bSAxel Dörfler 		case MSG_SLIDE_SHOW_DELAY:
9221076d97bSAxel Dörfler 		{
9234aa63633SAxel Dörfler 			bigtime_t delay;
9244aa63633SAxel Dörfler 			if (message->FindInt64("delay", &delay) == B_OK) {
9254aa63633SAxel Dörfler 				_SetSlideShowDelay(delay);
926da87390fSMichael Pfeiffer 				// in case message is sent from popup menu
9274aa63633SAxel Dörfler 				_MarkSlideShowDelay(delay);
928ad13f387SMichael Pfeiffer 			}
9291076d97bSAxel Dörfler 			break;
9301076d97bSAxel Dörfler 		}
931ad13f387SMichael Pfeiffer 
932ad13f387SMichael Pfeiffer 		case MSG_FULL_SCREEN:
933fd952aefSRyan Leavengood 			_ToggleFullScreen();
934ad13f387SMichael Pfeiffer 			break;
9356163f333SKarsten Heimrich 
936fc5ca95dSStephan Aßmus 		case MSG_EXIT_FULL_SCREEN:
937fc5ca95dSStephan Aßmus 			if (fFullScreen)
938fd952aefSRyan Leavengood 				_ToggleFullScreen();
939fc5ca95dSStephan Aßmus 			break;
9406163f333SKarsten Heimrich 
941cf0d8308SStephan Aßmus 		case MSG_SHOW_CAPTION:
942cf0d8308SStephan Aßmus 		{
943fd952aefSRyan Leavengood 			fShowCaption = _ToggleMenuItem(message->what);
944efa8b4f3SAxel Dörfler 			ShowImageSettings* settings = my_app->Settings();
945efa8b4f3SAxel Dörfler 
946d3046f7dSMichael Pfeiffer 			if (settings->Lock()) {
947d3046f7dSMichael Pfeiffer 				settings->SetBool("ShowCaption", fShowCaption);
948d3046f7dSMichael Pfeiffer 				settings->Unlock();
949d3046f7dSMichael Pfeiffer 			}
950efa8b4f3SAxel Dörfler 			if (fFullScreen)
951d3046f7dSMichael Pfeiffer 				fImageView->SetShowCaption(fShowCaption);
9526163f333SKarsten Heimrich 		}	break;
953ad13f387SMichael Pfeiffer 
954780d8a62SMichael Pfeiffer 		case MSG_PAGE_SETUP:
955fd952aefSRyan Leavengood 			_PageSetup();
956780d8a62SMichael Pfeiffer 			break;
9576163f333SKarsten Heimrich 
958780d8a62SMichael Pfeiffer 		case MSG_PREPARE_PRINT:
959fd952aefSRyan Leavengood 			_PrepareForPrint();
960780d8a62SMichael Pfeiffer 			break;
9616163f333SKarsten Heimrich 
962780d8a62SMichael Pfeiffer 		case MSG_PRINT:
963fd952aefSRyan Leavengood 			_Print(message);
964780d8a62SMichael Pfeiffer 			break;
965780d8a62SMichael Pfeiffer 
966780d8a62SMichael Pfeiffer 		case MSG_ZOOM_IN:
967d3046f7dSMichael Pfeiffer 			fImageView->ZoomIn();
968780d8a62SMichael Pfeiffer 			break;
9696163f333SKarsten Heimrich 
970780d8a62SMichael Pfeiffer 		case MSG_ZOOM_OUT:
971d3046f7dSMichael Pfeiffer 			fImageView->ZoomOut();
972780d8a62SMichael Pfeiffer 			break;
9736163f333SKarsten Heimrich 
974cae52eadSJanus 		case MSG_UPDATE_STATUS_ZOOM:
975cae52eadSJanus 			fStatusView->SetZoom(fImageView->Zoom());
976cae52eadSJanus 			break;
977cae52eadSJanus 
978e2069723SAxel Dörfler 		case kMsgOriginalSize:
9798073fcbbSAdrien Destugues 			if (message->FindInt32("behavior") == BButton::B_TOGGLE_BEHAVIOR) {
9808073fcbbSAdrien Destugues 				bool force = (message->FindInt32("be:value") == B_CONTROL_ON);
981554e2073SAdrien Destugues 				fImageView->ForceOriginalSize(force);
982554e2073SAdrien Destugues 				if (!force)
983554e2073SAdrien Destugues 					break;
984554e2073SAdrien Destugues 			}
9854fd570d3SAxel Dörfler 			fImageView->SetZoom(1.0);
986780d8a62SMichael Pfeiffer 			break;
9876163f333SKarsten Heimrich 
98881b9c776SMichael Pfeiffer 		case MSG_SCALE_BILINEAR:
989fd952aefSRyan Leavengood 			fImageView->SetScaleBilinear(_ToggleMenuItem(message->what));
99081b9c776SMichael Pfeiffer 			break;
991780d8a62SMichael Pfeiffer 
992cd6b5cdeSAxel Dörfler 		case MSG_DESKTOP_BACKGROUND:
993cd6b5cdeSAxel Dörfler 		{
9949617074cSRyan Leavengood 			BMessage backgroundsMessage(B_REFS_RECEIVED);
9959617074cSRyan Leavengood 			backgroundsMessage.AddRef("refs", fImageView->Image());
9960a74004cSRyan Leavengood 			// This is used in the Backgrounds code for scaled placement
9979617074cSRyan Leavengood 			backgroundsMessage.AddInt32("placement", 'scpl');
998537a273cSHumdinger 			be_roster->Launch("application/x-vnd.haiku-backgrounds",
999537a273cSHumdinger 				&backgroundsMessage);
1000cd6b5cdeSAxel Dörfler 			break;
1001cd6b5cdeSAxel Dörfler 		}
1002a60adbf9SAxel Dörfler 
10035b76e505SStephan Aßmus 		case MSG_SET_RATING:
10045b76e505SStephan Aßmus 		{
10055b76e505SStephan Aßmus 			int32 rating;
10065b76e505SStephan Aßmus 			if (message->FindInt32("rating", &rating) != B_OK)
10075b76e505SStephan Aßmus 				break;
10085b76e505SStephan Aßmus 			BFile file(&fNavigator.CurrentRef(), B_WRITE_ONLY);
10095b76e505SStephan Aßmus 			if (file.InitCheck() != B_OK)
10105b76e505SStephan Aßmus 				break;
10115b76e505SStephan Aßmus 			file.WriteAttr("Media:Rating", B_INT32_TYPE, 0, &rating,
10125b76e505SStephan Aßmus 				sizeof(rating));
10135b76e505SStephan Aßmus 			_UpdateRatingMenu();
10145b76e505SStephan Aßmus 			break;
10155b76e505SStephan Aßmus 		}
10165b76e505SStephan Aßmus 
1017cf0d8308SStephan Aßmus 		case kMsgToggleToolBar:
1018cf0d8308SStephan Aßmus 		{
1019cf0d8308SStephan Aßmus 			fShowToolBar = _ToggleMenuItem(message->what);
102094fd9498SStephan Aßmus 			_SetToolBarVisible(fShowToolBar, true);
1021cf0d8308SStephan Aßmus 
1022cf0d8308SStephan Aßmus 			ShowImageSettings* settings = my_app->Settings();
1023cf0d8308SStephan Aßmus 
1024cf0d8308SStephan Aßmus 			if (settings->Lock()) {
1025cf0d8308SStephan Aßmus 				settings->SetBool("ShowToolBar", fShowToolBar);
1026cf0d8308SStephan Aßmus 				settings->Unlock();
1027cf0d8308SStephan Aßmus 			}
1028cf0d8308SStephan Aßmus 			break;
1029cf0d8308SStephan Aßmus 		}
103094fd9498SStephan Aßmus 		case kShowToolBarIfEnabled:
103194fd9498SStephan Aßmus 		{
103294fd9498SStephan Aßmus 			bool show;
103394fd9498SStephan Aßmus 			if (message->FindBool("show", &show) != B_OK)
103494fd9498SStephan Aßmus 				break;
103594fd9498SStephan Aßmus 			_SetToolBarVisible(fShowToolBar && show, true);
103694fd9498SStephan Aßmus 			break;
103794fd9498SStephan Aßmus 		}
103894fd9498SStephan Aßmus 		case kMsgSlideToolBar:
103994fd9498SStephan Aßmus 		{
104094fd9498SStephan Aßmus 			float offset;
104194fd9498SStephan Aßmus 			if (message->FindFloat("offset", &offset) == B_OK) {
104294a4c1c4SAugustin Cavalier 				fToolBar->MoveBy(0, offset);
104394fd9498SStephan Aßmus 				fScrollView->ResizeBy(0, -offset);
104494fd9498SStephan Aßmus 				fScrollView->MoveBy(0, offset);
104594fd9498SStephan Aßmus 				UpdateIfNeeded();
104694fd9498SStephan Aßmus 				snooze(15000);
104794fd9498SStephan Aßmus 			}
104894fd9498SStephan Aßmus 			break;
104994fd9498SStephan Aßmus 		}
105094fd9498SStephan Aßmus 		case kMsgFinishSlidingToolBar:
105194fd9498SStephan Aßmus 		{
105294fd9498SStephan Aßmus 			float offset;
105394fd9498SStephan Aßmus 			bool show;
105494fd9498SStephan Aßmus 			if (message->FindFloat("offset", &offset) == B_OK
105594fd9498SStephan Aßmus 				&& message->FindBool("show", &show) == B_OK) {
105694fd9498SStephan Aßmus 				// Compensate rounding errors with the final placement
105794a4c1c4SAugustin Cavalier 				fToolBar->MoveTo(fToolBar->Frame().left, offset);
105895667008SJanus 				if (!show)
105994a4c1c4SAugustin Cavalier 					fToolBar->Hide();
106094a4c1c4SAugustin Cavalier 				BRect frame = fToolBar->Parent()->Bounds();
106194a4c1c4SAugustin Cavalier 				frame.top = fToolBar->Frame().bottom + 1;
10622804cb33SRyan Leavengood 				fScrollView->MoveTo(fScrollView->Frame().left, frame.top);
106394fd9498SStephan Aßmus 				fScrollView->ResizeTo(fScrollView->Bounds().Width(),
1064cae52eadSJanus 					frame.Height() + 1);
106594fd9498SStephan Aßmus 			}
106694fd9498SStephan Aßmus 			break;
106794fd9498SStephan Aßmus 		}
1068cf0d8308SStephan Aßmus 
106913afa642SPhil Greenway 		default:
1070efa8b4f3SAxel Dörfler 			BWindow::MessageReceived(message);
107113afa642SPhil Greenway 			break;
107213afa642SPhil Greenway 	}
107313afa642SPhil Greenway }
1074fc0a275bSMatthew Wilber 
1075efa8b4f3SAxel Dörfler 
1076fc0a275bSMatthew Wilber void
1077fb94ed11SAvi Brenner ShowImageWindow::_GetFileInfo(const entry_ref& ref)
1078fb94ed11SAvi Brenner {
1079fb94ed11SAvi Brenner 	BMessage message('Tinf');
1080fb94ed11SAvi Brenner 	BMessenger tracker("application/x-vnd.Be-TRAK");
1081fb94ed11SAvi Brenner 	message.AddRef("refs", &ref);
1082fb94ed11SAvi Brenner 	tracker.SendMessage(&message);
1083fb94ed11SAvi Brenner }
1084fb94ed11SAvi Brenner 
1085fb94ed11SAvi Brenner 
1086fb94ed11SAvi Brenner void
1087cd6b5cdeSAxel Dörfler ShowImageWindow::_UpdateStatusText(const BMessage* message)
1088cd6b5cdeSAxel Dörfler {
1089baa27ccbSJanus 	BString frameText;
1090cd6b5cdeSAxel Dörfler 	if (fImageView->Bitmap() != NULL) {
1091cd6b5cdeSAxel Dörfler 		BRect bounds = fImageView->Bitmap()->Bounds();
1092baa27ccbSJanus 		frameText << bounds.IntegerWidth() + 1
1093cae52eadSJanus 			<< "x" << bounds.IntegerHeight() + 1;
1094cd6b5cdeSAxel Dörfler 	}
1095baa27ccbSJanus 	BString pages;
1096baa27ccbSJanus 	if (fNavigator.PageCount() > 1)
1097baa27ccbSJanus 		pages << fNavigator.CurrentPage() << "/" << fNavigator.PageCount();
1098baa27ccbSJanus 	fStatusView->Update(fNavigator.CurrentRef(), frameText, pages, fImageType,
1099cae52eadSJanus 		fImageView->Zoom());
1100cd6b5cdeSAxel Dörfler }
1101cd6b5cdeSAxel Dörfler 
1102cd6b5cdeSAxel Dörfler 
1103cd6b5cdeSAxel Dörfler void
1104cd6b5cdeSAxel Dörfler ShowImageWindow::_LoadError(const entry_ref& ref)
1105cd6b5cdeSAxel Dörfler {
1106cd6b5cdeSAxel Dörfler 	// TODO: give a better error message!
1107560ff447SJonas Sundström 	BAlert* alert = new BAlert(B_TRANSLATE_SYSTEM_NAME("ShowImage"),
1108546208a5SOliver Tappe 		B_TRANSLATE_CONTEXT("Could not load image! Either the "
1109ddcb5a2cSAxel Dörfler 			"file or an image translator for it does not exist.",
1110ddcb5a2cSAxel Dörfler 			"LoadAlerts"),
1111546208a5SOliver Tappe 		B_TRANSLATE_CONTEXT("OK", "Alerts"), NULL, NULL,
11125df9097aSJohn Scipione 		B_WIDTH_AS_USUAL, B_STOP_ALERT);
1113aed35104SHumdinger 	alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
1114cd6b5cdeSAxel Dörfler 	alert->Go();
1115cd6b5cdeSAxel Dörfler }
1116cd6b5cdeSAxel Dörfler 
1117cd6b5cdeSAxel Dörfler 
1118cd6b5cdeSAxel Dörfler void
1119fd952aefSRyan Leavengood ShowImageWindow::_SaveAs(BMessage* message)
1120fc0a275bSMatthew Wilber {
1121cdb89ebbSMatthew Wilber 	// Read the translator and output type the user chose
1122cdb89ebbSMatthew Wilber 	translator_id outTranslator;
1123cdb89ebbSMatthew Wilber 	uint32 outType;
11246163f333SKarsten Heimrich 	if (message->FindInt32(kTranslatorField,
1125efa8b4f3SAxel Dörfler 			reinterpret_cast<int32 *>(&outTranslator)) != B_OK
11266163f333SKarsten Heimrich 		|| message->FindInt32(kTypeField,
1127cdb89ebbSMatthew Wilber 			reinterpret_cast<int32 *>(&outType)) != B_OK)
1128fc0a275bSMatthew Wilber 		return;
1129fc0a275bSMatthew Wilber 
1130cdb89ebbSMatthew Wilber 	// Add the chosen translator and output type to the
1131cdb89ebbSMatthew Wilber 	// message that the save panel will send back
1132c1a10c14SKarsten Heimrich 	BMessage panelMsg(MSG_SAVE_PANEL);
1133c1a10c14SKarsten Heimrich 	panelMsg.AddInt32(kTranslatorField, outTranslator);
1134c1a10c14SKarsten Heimrich 	panelMsg.AddInt32(kTypeField, outType);
1135cdb89ebbSMatthew Wilber 
1136cdb89ebbSMatthew Wilber 	// Create save panel and show it
11376163f333SKarsten Heimrich 	BMessenger target(this);
1138efa8b4f3SAxel Dörfler 	fSavePanel = new (std::nothrow) BFilePanel(B_SAVE_PANEL,
1139c1a10c14SKarsten Heimrich 		&target, NULL, 0, false, &panelMsg);
1140d3046f7dSMichael Pfeiffer 	if (!fSavePanel)
1141fc0a275bSMatthew Wilber 		return;
1142a60adbf9SAxel Dörfler 
11433000afd7SJanus 	// Retrieve save directory from settings;
11443000afd7SJanus 	ShowImageSettings* settings = my_app->Settings();
11453000afd7SJanus 	if (settings->Lock()) {
11463000afd7SJanus 		fSavePanel->SetPanelDirectory(
11473000afd7SJanus 			settings->GetString("SaveDirectory", NULL));
11483000afd7SJanus 		settings->Unlock();
11493000afd7SJanus 	}
11503000afd7SJanus 
1151d3046f7dSMichael Pfeiffer 	fSavePanel->Window()->SetWorkspaces(B_CURRENT_WORKSPACE);
1152d3046f7dSMichael Pfeiffer 	fSavePanel->Show();
1153fc0a275bSMatthew Wilber }
1154fc0a275bSMatthew Wilber 
1155efa8b4f3SAxel Dörfler 
1156fc0a275bSMatthew Wilber void
1157fd952aefSRyan Leavengood ShowImageWindow::_SaveToFile(BMessage* message)
1158fc0a275bSMatthew Wilber {
1159cdb89ebbSMatthew Wilber 	// Read in where the file should be saved
1160efa8b4f3SAxel Dörfler 	entry_ref dirRef;
1161efa8b4f3SAxel Dörfler 	if (message->FindRef("directory", &dirRef) != B_OK)
1162fc0a275bSMatthew Wilber 		return;
1163efa8b4f3SAxel Dörfler 
1164fc0a275bSMatthew Wilber 	const char* filename;
1165efa8b4f3SAxel Dörfler 	if (message->FindString("name", &filename) != B_OK)
1166fc0a275bSMatthew Wilber 		return;
1167fc0a275bSMatthew Wilber 
1168cdb89ebbSMatthew Wilber 	// Read in the translator and type to be used
1169cdb89ebbSMatthew Wilber 	// to save the output image
1170cdb89ebbSMatthew Wilber 	translator_id outTranslator;
1171cdb89ebbSMatthew Wilber 	uint32 outType;
11726163f333SKarsten Heimrich 	if (message->FindInt32(kTranslatorField,
1173efa8b4f3SAxel Dörfler 			reinterpret_cast<int32 *>(&outTranslator)) != B_OK
11746163f333SKarsten Heimrich 		|| message->FindInt32(kTypeField,
1175cdb89ebbSMatthew Wilber 			reinterpret_cast<int32 *>(&outType)) != B_OK)
1176cdb89ebbSMatthew Wilber 		return;
1177cdb89ebbSMatthew Wilber 
1178a7e78e3bSMatthew Wilber 	// Find the translator_format information needed to
1179a7e78e3bSMatthew Wilber 	// write a MIME attribute for the image file
1180a7e78e3bSMatthew Wilber 	BTranslatorRoster* roster = BTranslatorRoster::Default();
1181efa8b4f3SAxel Dörfler 	const translation_format* outFormat = NULL;
1182efa8b4f3SAxel Dörfler 	int32 outCount = 0;
1183efa8b4f3SAxel Dörfler 	if (roster->GetOutputFormats(outTranslator, &outFormat, &outCount) != B_OK
1184efa8b4f3SAxel Dörfler 		|| outCount < 1)
1185a7e78e3bSMatthew Wilber 		return;
1186efa8b4f3SAxel Dörfler 
1187a7e78e3bSMatthew Wilber 	int32 i;
1188efa8b4f3SAxel Dörfler 	for (i = 0; i < outCount; i++) {
1189537a273cSHumdinger 		if (outFormat[i].group == B_TRANSLATOR_BITMAP && outFormat[i].type
1190537a273cSHumdinger 				== outType)
1191a7e78e3bSMatthew Wilber 			break;
1192a7e78e3bSMatthew Wilber 	}
1193efa8b4f3SAxel Dörfler 	if (i == outCount)
1194fc0a275bSMatthew Wilber 		return;
1195fc0a275bSMatthew Wilber 
1196a7e78e3bSMatthew Wilber 	// Write out the image file
1197efa8b4f3SAxel Dörfler 	BDirectory dir(&dirRef);
1198efa8b4f3SAxel Dörfler 	fImageView->SaveToFile(&dir, filename, NULL, &outFormat[i]);
11993000afd7SJanus 
12003000afd7SJanus 	// Store Save directory in settings;
12013000afd7SJanus 	ShowImageSettings* settings = my_app->Settings();
12023000afd7SJanus 	if (settings->Lock()) {
12033000afd7SJanus 		BPath path(&dirRef);
12043000afd7SJanus 		settings->SetString("SaveDirectory", path.Path());
12053000afd7SJanus 		settings->Unlock();
12063000afd7SJanus 	}
1207fc0a275bSMatthew Wilber }
1208fc0a275bSMatthew Wilber 
1209efa8b4f3SAxel Dörfler 
1210546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT
1211546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "ClosePrompt"
12121ed4535fSStephan Aßmus 
1213b9767a83SAxel Dörfler 
1214cdb89ebbSMatthew Wilber bool
1215fd952aefSRyan Leavengood ShowImageWindow::_ClosePrompt()
1216ee7b4f39SMatthew Wilber {
1217ee7b4f39SMatthew Wilber 	if (!fModified)
1218ee7b4f39SMatthew Wilber 		return true;
1219efa8b4f3SAxel Dörfler 
1220cd6b5cdeSAxel Dörfler 	int32 count = fNavigator.PageCount();
1221cd6b5cdeSAxel Dörfler 	int32 page = fNavigator.CurrentPage();
1222cd6b5cdeSAxel Dörfler 	BString prompt;
1223efa8b4f3SAxel Dörfler 
12241ed4535fSStephan Aßmus 	if (count > 1) {
12251ed4535fSStephan Aßmus 		bs_printf(&prompt,
1226905c8c8cSMatt Madia 			B_TRANSLATE("The document '%s' (page %d) has been changed. Do you "
1227905c8c8cSMatt Madia 				"want to close the document?"),
1228cd6b5cdeSAxel Dörfler 			fImageView->Image()->name, page);
12291ed4535fSStephan Aßmus 	} else {
12301ed4535fSStephan Aßmus 		bs_printf(&prompt,
1231905c8c8cSMatt Madia 			B_TRANSLATE("The document '%s' has been changed. Do you want to "
1232905c8c8cSMatt Madia 				"close the document?"),
1233cd6b5cdeSAxel Dörfler 			fImageView->Image()->name);
12341ed4535fSStephan Aßmus 	}
12351ed4535fSStephan Aßmus 
1236cd6b5cdeSAxel Dörfler 	BAlert* alert = new BAlert(B_TRANSLATE("Close document"), prompt.String(),
1237905c8c8cSMatt Madia 		B_TRANSLATE("Cancel"), B_TRANSLATE("Close"));
1238aed35104SHumdinger 	alert->SetShortcut(0, B_ESCAPE);
1239aed35104SHumdinger 
1240cd6b5cdeSAxel Dörfler 	if (alert->Go() == 0) {
1241ee7b4f39SMatthew Wilber 		// Cancel
1242ee7b4f39SMatthew Wilber 		return false;
1243cd6b5cdeSAxel Dörfler 	}
1244cd6b5cdeSAxel Dörfler 
1245ee7b4f39SMatthew Wilber 	// Close
1246187f0b8aSMatthew Wilber 	fModified = false;
1247ee7b4f39SMatthew Wilber 	return true;
1248ee7b4f39SMatthew Wilber }
1249ee7b4f39SMatthew Wilber 
1250cdb89ebbSMatthew Wilber 
1251b9767a83SAxel Dörfler status_t
1252a569816bSAxel Dörfler ShowImageWindow::_LoadImage(bool forward)
1253b9767a83SAxel Dörfler {
1254*a4462d20SHumdinger 	// If the user triggered a _LoadImage while in a slide show,
1255*a4462d20SHumdinger 	// make sure the new image is shown for the set delay:
1256*a4462d20SHumdinger 	_ResetSlideShowDelay();
1257*a4462d20SHumdinger 
1258b9767a83SAxel Dörfler 	BMessenger us(this);
1259be63ec85SJanus 	status_t status = my_app->DefaultCache().RetrieveImage(
1260a569816bSAxel Dörfler 		fNavigator.CurrentRef(), fNavigator.CurrentPage(), &us);
1261a569816bSAxel Dörfler 	if (status != B_OK)
1262a569816bSAxel Dörfler 		return status;
1263a569816bSAxel Dörfler 
1264e2069723SAxel Dörfler 	fProgressWindow->Start(this);
1265e2069723SAxel Dörfler 
1266a569816bSAxel Dörfler 	// Preload previous/next images - two in the navigation direction, one
1267a569816bSAxel Dörfler 	// in the opposite direction.
1268a569816bSAxel Dörfler 
1269a569816bSAxel Dörfler 	entry_ref nextRef = fNavigator.CurrentRef();
1270a569816bSAxel Dörfler 	if (_PreloadImage(forward, nextRef))
1271a569816bSAxel Dörfler 		_PreloadImage(forward, nextRef);
1272a569816bSAxel Dörfler 
1273a569816bSAxel Dörfler 	entry_ref previousRef = fNavigator.CurrentRef();
1274a569816bSAxel Dörfler 	_PreloadImage(!forward, previousRef);
1275a569816bSAxel Dörfler 
1276a569816bSAxel Dörfler 	return B_OK;
1277a569816bSAxel Dörfler }
1278a569816bSAxel Dörfler 
1279a569816bSAxel Dörfler 
1280a569816bSAxel Dörfler bool
1281a569816bSAxel Dörfler ShowImageWindow::_PreloadImage(bool forward, entry_ref& ref)
1282a569816bSAxel Dörfler {
1283a569816bSAxel Dörfler 	entry_ref currentRef = ref;
1284a569816bSAxel Dörfler 	if ((forward && !fNavigator.GetNextFile(currentRef, ref))
1285a569816bSAxel Dörfler 		|| (!forward && !fNavigator.GetPreviousFile(currentRef, ref)))
1286a569816bSAxel Dörfler 		return false;
1287a569816bSAxel Dörfler 
1288be63ec85SJanus 	return my_app->DefaultCache().RetrieveImage(ref) == B_OK;
1289b9767a83SAxel Dörfler }
1290b9767a83SAxel Dörfler 
1291b9767a83SAxel Dörfler 
1292ad13f387SMichael Pfeiffer void
1293fd952aefSRyan Leavengood ShowImageWindow::_ToggleFullScreen()
1294ad13f387SMichael Pfeiffer {
1295ad13f387SMichael Pfeiffer 	BRect frame;
1296ad13f387SMichael Pfeiffer 	fFullScreen = !fFullScreen;
1297ad13f387SMichael Pfeiffer 	if (fFullScreen) {
1298ad13f387SMichael Pfeiffer 		BScreen screen;
1299ad13f387SMichael Pfeiffer 		fWindowFrame = Frame();
1300ad13f387SMichael Pfeiffer 		frame = screen.Frame();
1301d3046f7dSMichael Pfeiffer 		frame.top -= fBar->Bounds().Height() + 1;
130267eb2a04SHumdinger 		frame.right += B_V_SCROLL_BAR_WIDTH;
1303ad13f387SMichael Pfeiffer 		frame.bottom += B_H_SCROLL_BAR_HEIGHT;
1304ad13f387SMichael Pfeiffer 
1305ad13f387SMichael Pfeiffer 		SetFlags(Flags() | B_NOT_RESIZABLE | B_NOT_MOVABLE);
1306c0b16687SAxel Dörfler 
1307c0b16687SAxel Dörfler 		Activate();
1308c0b16687SAxel Dörfler 			// make the window frontmost
1309ad13f387SMichael Pfeiffer 	} else {
1310ad13f387SMichael Pfeiffer 		frame = fWindowFrame;
1311ad13f387SMichael Pfeiffer 
1312ad13f387SMichael Pfeiffer 		SetFlags(Flags() & ~(B_NOT_RESIZABLE | B_NOT_MOVABLE));
1313ad13f387SMichael Pfeiffer 	}
1314efa8b4f3SAxel Dörfler 
131594a4c1c4SAugustin Cavalier 	fToolBar->SetActionVisible(MSG_FULL_SCREEN, fFullScreen);
1316cf0d8308SStephan Aßmus 	_SetToolBarVisible(!fFullScreen && fShowToolBar);
131760c23976SJanus 	_SetToolBarBorder(!fFullScreen);
1318cf0d8308SStephan Aßmus 
1319ad13f387SMichael Pfeiffer 	MoveTo(frame.left, frame.top);
1320ad13f387SMichael Pfeiffer 	ResizeTo(frame.Width(), frame.Height());
1321e2069723SAxel Dörfler 
1322e2069723SAxel Dörfler 	fImageView->SetHideIdlingCursor(fFullScreen);
1323e2069723SAxel Dörfler 	fImageView->SetShowCaption(fFullScreen && fShowCaption);
1324eaa910c5SAxel Dörfler 
132548ae3e38SAxel Dörfler 	Layout(false);
132648ae3e38SAxel Dörfler 		// We need to manually relayout here, as the views are layouted
132748ae3e38SAxel Dörfler 		// asynchronously, and FitToBounds() would still have the wrong size
1328e2069723SAxel Dörfler 	fImageView->FitToBounds();
1329ad13f387SMichael Pfeiffer }
1330ad13f387SMichael Pfeiffer 
1331efa8b4f3SAxel Dörfler 
1332d3046f7dSMichael Pfeiffer void
13332281340dSAxel Dörfler ShowImageWindow::_ApplySettings()
1334d3046f7dSMichael Pfeiffer {
1335efa8b4f3SAxel Dörfler 	ShowImageSettings* settings = my_app->Settings();
1336efa8b4f3SAxel Dörfler 
1337d3046f7dSMichael Pfeiffer 	if (settings->Lock()) {
1338d3046f7dSMichael Pfeiffer 		fShowCaption = settings->GetBool("ShowCaption", fShowCaption);
1339d3046f7dSMichael Pfeiffer 		fPrintOptions.SetBounds(BRect(0, 0, 1023, 767));
1340d3046f7dSMichael Pfeiffer 
13414aa63633SAxel Dörfler 		fSlideShowDelay = settings->GetTime("SlideShowDelay", fSlideShowDelay);
1342d3046f7dSMichael Pfeiffer 
13434aa63633SAxel Dörfler 		fPrintOptions.SetOption((enum PrintOptions::Option)settings->GetInt32(
13444aa63633SAxel Dörfler 			"PO:Option", fPrintOptions.Option()));
13454aa63633SAxel Dörfler 		fPrintOptions.SetZoomFactor(
13464aa63633SAxel Dörfler 			settings->GetFloat("PO:ZoomFactor", fPrintOptions.ZoomFactor()));
13474aa63633SAxel Dörfler 		fPrintOptions.SetDPI(settings->GetFloat("PO:DPI", fPrintOptions.DPI()));
13484aa63633SAxel Dörfler 		fPrintOptions.SetWidth(
13494aa63633SAxel Dörfler 			settings->GetFloat("PO:Width", fPrintOptions.Width()));
13504aa63633SAxel Dörfler 		fPrintOptions.SetHeight(
13514aa63633SAxel Dörfler 			settings->GetFloat("PO:Height", fPrintOptions.Height()));
1352d3046f7dSMichael Pfeiffer 
1353cf0d8308SStephan Aßmus 		fShowToolBar = settings->GetBool("ShowToolBar", fShowToolBar);
1354cf0d8308SStephan Aßmus 
1355d3046f7dSMichael Pfeiffer 		settings->Unlock();
1356d3046f7dSMichael Pfeiffer 	}
1357d3046f7dSMichael Pfeiffer }
1358d3046f7dSMichael Pfeiffer 
1359efa8b4f3SAxel Dörfler 
1360d3046f7dSMichael Pfeiffer void
1361fd952aefSRyan Leavengood ShowImageWindow::_SavePrintOptions()
1362d3046f7dSMichael Pfeiffer {
1363efa8b4f3SAxel Dörfler 	ShowImageSettings* settings = my_app->Settings();
1364efa8b4f3SAxel Dörfler 
1365d3046f7dSMichael Pfeiffer 	if (settings->Lock()) {
1366d3046f7dSMichael Pfeiffer 		settings->SetInt32("PO:Option", fPrintOptions.Option());
1367d3046f7dSMichael Pfeiffer 		settings->SetFloat("PO:ZoomFactor", fPrintOptions.ZoomFactor());
1368d3046f7dSMichael Pfeiffer 		settings->SetFloat("PO:DPI", fPrintOptions.DPI());
1369d3046f7dSMichael Pfeiffer 		settings->SetFloat("PO:Width", fPrintOptions.Width());
1370d3046f7dSMichael Pfeiffer 		settings->SetFloat("PO:Height", fPrintOptions.Height());
1371d3046f7dSMichael Pfeiffer 		settings->Unlock();
1372d3046f7dSMichael Pfeiffer 	}
1373d3046f7dSMichael Pfeiffer }
1374d3046f7dSMichael Pfeiffer 
1375efa8b4f3SAxel Dörfler 
1376cdb89ebbSMatthew Wilber bool
1377fd952aefSRyan Leavengood ShowImageWindow::_PageSetup()
1378780d8a62SMichael Pfeiffer {
1379cd6b5cdeSAxel Dörfler 	BPrintJob printJob(fImageView->Image()->name);
1380efa8b4f3SAxel Dörfler 	if (fPrintSettings != NULL)
1381780d8a62SMichael Pfeiffer 		printJob.SetSettings(new BMessage(*fPrintSettings));
1382efa8b4f3SAxel Dörfler 
13836163f333SKarsten Heimrich 	status_t status = printJob.ConfigPage();
13846163f333SKarsten Heimrich 	if (status == B_OK) {
1385780d8a62SMichael Pfeiffer 		delete fPrintSettings;
1386780d8a62SMichael Pfeiffer 		fPrintSettings = printJob.Settings();
1387780d8a62SMichael Pfeiffer 	}
1388efa8b4f3SAxel Dörfler 
13896163f333SKarsten Heimrich 	return status == B_OK;
1390780d8a62SMichael Pfeiffer }
1391780d8a62SMichael Pfeiffer 
1392efa8b4f3SAxel Dörfler 
1393780d8a62SMichael Pfeiffer void
1394fd952aefSRyan Leavengood ShowImageWindow::_PrepareForPrint()
1395780d8a62SMichael Pfeiffer {
13966163f333SKarsten Heimrich 	if (fPrintSettings == NULL) {
1397cd6b5cdeSAxel Dörfler 		BPrintJob printJob(fImageView->Image()->name);
13986163f333SKarsten Heimrich 		if (printJob.ConfigJob() == B_OK)
13996163f333SKarsten Heimrich 			fPrintSettings = printJob.Settings();
14006163f333SKarsten Heimrich 	}
1401780d8a62SMichael Pfeiffer 
1402cd6b5cdeSAxel Dörfler 	fPrintOptions.SetBounds(fImageView->Bitmap()->Bounds());
1403cd6b5cdeSAxel Dörfler 	fPrintOptions.SetWidth(fImageView->Bitmap()->Bounds().Width() + 1);
1404780d8a62SMichael Pfeiffer 
1405efa8b4f3SAxel Dörfler 	new PrintOptionsWindow(BPoint(Frame().left + 30, Frame().top + 50),
1406efa8b4f3SAxel Dörfler 		&fPrintOptions, this);
1407780d8a62SMichael Pfeiffer }
1408780d8a62SMichael Pfeiffer 
1409efa8b4f3SAxel Dörfler 
1410780d8a62SMichael Pfeiffer void
1411fd952aefSRyan Leavengood ShowImageWindow::_Print(BMessage* msg)
1412780d8a62SMichael Pfeiffer {
1413780d8a62SMichael Pfeiffer 	status_t st;
1414efa8b4f3SAxel Dörfler 	if (msg->FindInt32("status", &st) != B_OK || st != B_OK)
1415780d8a62SMichael Pfeiffer 		return;
1416780d8a62SMichael Pfeiffer 
1417fd952aefSRyan Leavengood 	_SavePrintOptions();
1418d3046f7dSMichael Pfeiffer 
1419cd6b5cdeSAxel Dörfler 	BPrintJob printJob(fImageView->Image()->name);
14206163f333SKarsten Heimrich 	if (fPrintSettings)
1421780d8a62SMichael Pfeiffer 		printJob.SetSettings(new BMessage(*fPrintSettings));
14226163f333SKarsten Heimrich 
1423780d8a62SMichael Pfeiffer 	if (printJob.ConfigJob() == B_OK) {
14246163f333SKarsten Heimrich 		delete fPrintSettings;
14256163f333SKarsten Heimrich 		fPrintSettings = printJob.Settings();
1426780d8a62SMichael Pfeiffer 
1427780d8a62SMichael Pfeiffer 		// first/lastPage is unused for now
14283177ae77SStefano Ceccherini 		int32 firstPage = printJob.FirstPage();
14293177ae77SStefano Ceccherini 		int32 lastPage = printJob.LastPage();
14306163f333SKarsten Heimrich 		BRect printableRect = printJob.PrintableRect();
14316163f333SKarsten Heimrich 
1432efa8b4f3SAxel Dörfler 		if (firstPage < 1)
1433780d8a62SMichael Pfeiffer 			firstPage = 1;
1434efa8b4f3SAxel Dörfler 		if (lastPage < firstPage)
1435780d8a62SMichael Pfeiffer 			lastPage = firstPage;
1436780d8a62SMichael Pfeiffer 
1437cd6b5cdeSAxel Dörfler 		BBitmap* bitmap = fImageView->Bitmap();
14383177ae77SStefano Ceccherini 		float imageWidth = bitmap->Bounds().Width() + 1.0;
14393177ae77SStefano Ceccherini 		float imageHeight = bitmap->Bounds().Height() + 1.0;
1440780d8a62SMichael Pfeiffer 
14416163f333SKarsten Heimrich 		float width;
1442780d8a62SMichael Pfeiffer 		switch (fPrintOptions.Option()) {
14436163f333SKarsten Heimrich 			case PrintOptions::kFitToPage: {
14446163f333SKarsten Heimrich 				float w1 = printableRect.Width() + 1;
1445cd6b5cdeSAxel Dörfler 				float w2 = imageWidth * (printableRect.Height() + 1)
1446cd6b5cdeSAxel Dörfler 					/ imageHeight;
1447efa8b4f3SAxel Dörfler 				if (w2 < w1)
1448780d8a62SMichael Pfeiffer 					width = w2;
1449efa8b4f3SAxel Dörfler 				else
1450780d8a62SMichael Pfeiffer 					width = w1;
14516163f333SKarsten Heimrich 			}	break;
1452780d8a62SMichael Pfeiffer 			case PrintOptions::kZoomFactor:
1453780d8a62SMichael Pfeiffer 				width = imageWidth * fPrintOptions.ZoomFactor();
1454780d8a62SMichael Pfeiffer 				break;
1455780d8a62SMichael Pfeiffer 			case PrintOptions::kDPI:
1456780d8a62SMichael Pfeiffer 				width = imageWidth * 72.0 / fPrintOptions.DPI();
1457780d8a62SMichael Pfeiffer 				break;
1458780d8a62SMichael Pfeiffer 			case PrintOptions::kWidth:
1459780d8a62SMichael Pfeiffer 			case PrintOptions::kHeight:
1460780d8a62SMichael Pfeiffer 				width = fPrintOptions.Width();
1461780d8a62SMichael Pfeiffer 				break;
1462efa8b4f3SAxel Dörfler 
1463780d8a62SMichael Pfeiffer 			default:
1464780d8a62SMichael Pfeiffer 				// keep compiler silent; should not reach here
1465780d8a62SMichael Pfeiffer 				width = imageWidth;
1466780d8a62SMichael Pfeiffer 		}
1467780d8a62SMichael Pfeiffer 
1468efa8b4f3SAxel Dörfler 		// TODO: eventually print large images on several pages
1469780d8a62SMichael Pfeiffer 		printJob.BeginJob();
1470d3046f7dSMichael Pfeiffer 		fImageView->SetScale(width / imageWidth);
14715eb50e46SMichael Pfeiffer 		// coordinates are relative to printable rectangle
14725eb50e46SMichael Pfeiffer 		BRect bounds(bitmap->Bounds());
14735eb50e46SMichael Pfeiffer 		printJob.DrawView(fImageView, bounds, BPoint(0, 0));
1474d3046f7dSMichael Pfeiffer 		fImageView->SetScale(1.0);
1475780d8a62SMichael Pfeiffer 		printJob.SpoolPage();
1476780d8a62SMichael Pfeiffer 		printJob.CommitJob();
1477780d8a62SMichael Pfeiffer 	}
1478780d8a62SMichael Pfeiffer }
1479780d8a62SMichael Pfeiffer 
148056b0c7b9SKarsten Heimrich 
14814aa63633SAxel Dörfler void
14824aa63633SAxel Dörfler ShowImageWindow::_SetSlideShowDelay(bigtime_t delay)
14834aa63633SAxel Dörfler {
14844aa63633SAxel Dörfler 	if (fSlideShowDelay == delay)
14854aa63633SAxel Dörfler 		return;
14864aa63633SAxel Dörfler 
14874aa63633SAxel Dörfler 	fSlideShowDelay = delay;
14884aa63633SAxel Dörfler 
14894aa63633SAxel Dörfler 	ShowImageSettings* settings = my_app->Settings();
14904aa63633SAxel Dörfler 	if (settings->Lock()) {
14914aa63633SAxel Dörfler 		settings->SetTime("SlideShowDelay", fSlideShowDelay);
14924aa63633SAxel Dörfler 		settings->Unlock();
14934aa63633SAxel Dörfler 	}
14944aa63633SAxel Dörfler 
14954aa63633SAxel Dörfler 	if (fSlideShowRunner != NULL)
14964aa63633SAxel Dörfler 		_StartSlideShow();
14974aa63633SAxel Dörfler }
14984aa63633SAxel Dörfler 
14994aa63633SAxel Dörfler 
15004aa63633SAxel Dörfler void
15014aa63633SAxel Dörfler ShowImageWindow::_StartSlideShow()
15024aa63633SAxel Dörfler {
15034aa63633SAxel Dörfler 	_StopSlideShow();
15044aa63633SAxel Dörfler 
15054aa63633SAxel Dörfler 	BMessage nextSlide(kMsgNextSlide);
15064aa63633SAxel Dörfler 	fSlideShowRunner = new BMessageRunner(this, &nextSlide, fSlideShowDelay);
15074aa63633SAxel Dörfler }
15084aa63633SAxel Dörfler 
15094aa63633SAxel Dörfler 
15104aa63633SAxel Dörfler void
15114aa63633SAxel Dörfler ShowImageWindow::_StopSlideShow()
15124aa63633SAxel Dörfler {
15134aa63633SAxel Dörfler 	if (fSlideShowRunner != NULL) {
15144aa63633SAxel Dörfler 		delete fSlideShowRunner;
15154aa63633SAxel Dörfler 		fSlideShowRunner = NULL;
15164aa63633SAxel Dörfler 	}
15174aa63633SAxel Dörfler }
15184aa63633SAxel Dörfler 
15194aa63633SAxel Dörfler 
15205b76e505SStephan Aßmus void
1521*a4462d20SHumdinger ShowImageWindow::_ResetSlideShowDelay()
1522*a4462d20SHumdinger {
1523*a4462d20SHumdinger 	if (fSlideShowRunner != NULL)
1524*a4462d20SHumdinger 		fSlideShowRunner->SetInterval(fSlideShowDelay);
1525*a4462d20SHumdinger }
1526*a4462d20SHumdinger 
1527*a4462d20SHumdinger 
1528*a4462d20SHumdinger void
15295b76e505SStephan Aßmus ShowImageWindow::_UpdateRatingMenu()
15305b76e505SStephan Aßmus {
15315b76e505SStephan Aßmus 	BFile file(&fNavigator.CurrentRef(), B_READ_ONLY);
15325b76e505SStephan Aßmus 	if (file.InitCheck() != B_OK)
15335b76e505SStephan Aßmus 		return;
15345b76e505SStephan Aßmus 	int32 rating;
15355b76e505SStephan Aßmus 	ssize_t size = sizeof(rating);
15365b76e505SStephan Aßmus 	if (file.ReadAttr("Media:Rating", B_INT32_TYPE, 0, &rating, size) != size)
15375b76e505SStephan Aßmus 		rating = 0;
15385b76e505SStephan Aßmus 	// TODO: Finding the correct item could be more robust, like by looking
15395b76e505SStephan Aßmus 	// at the message of each item.
15405b76e505SStephan Aßmus 	for (int32 i = 1; i <= 10; i++) {
15415b76e505SStephan Aßmus 		BMenuItem* item = fRatingMenu->ItemAt(i - 1);
15425b76e505SStephan Aßmus 		if (item == NULL)
15435b76e505SStephan Aßmus 			break;
15445b76e505SStephan Aßmus 		item->SetMarked(i == rating);
15455b76e505SStephan Aßmus 	}
15465b76e505SStephan Aßmus }
15475b76e505SStephan Aßmus 
15485b76e505SStephan Aßmus 
1549cf0d8308SStephan Aßmus void
1550e62a6973SJanus ShowImageWindow::_SaveWidthAndHeight()
1551e62a6973SJanus {
1552e62a6973SJanus 	if (fNavigator.CurrentPage() != 1)
1553e62a6973SJanus 		return;
1554e62a6973SJanus 
1555e62a6973SJanus 	if (fImageView->Bitmap() == NULL)
1556e62a6973SJanus 		return;
1557e62a6973SJanus 
1558e62a6973SJanus 	BRect bounds = fImageView->Bitmap()->Bounds();
1559c1994be8SJanus 	int32 width = bounds.IntegerWidth() + 1;
1560c1994be8SJanus 	int32 height = bounds.IntegerHeight() + 1;
1561e62a6973SJanus 
15629c1f5f4dSJanus 	BNode node(&fNavigator.CurrentRef());
15639c1f5f4dSJanus 	if (node.InitCheck() != B_OK)
1564e62a6973SJanus 		return;
1565e62a6973SJanus 
15669c1f5f4dSJanus 	const char* kWidthAttrName = "Media:Width";
15679c1f5f4dSJanus 	const char* kHeightAttrName = "Media:Height";
15689c1f5f4dSJanus 
15699c1f5f4dSJanus 	int32 widthAttr;
1570b41cdcb3SJanus 	ssize_t attrSize = node.ReadAttr(kWidthAttrName, B_INT32_TYPE, 0,
1571b41cdcb3SJanus 		&widthAttr, sizeof(widthAttr));
15729c1f5f4dSJanus 	if (attrSize <= 0 || widthAttr != width)
15739c1f5f4dSJanus 		node.WriteAttr(kWidthAttrName, B_INT32_TYPE, 0, &width, sizeof(width));
15749c1f5f4dSJanus 
15759c1f5f4dSJanus 	int32 heightAttr;
1576b41cdcb3SJanus 	attrSize = node.ReadAttr(kHeightAttrName, B_INT32_TYPE, 0,
1577b41cdcb3SJanus 		&heightAttr, sizeof(heightAttr));
15789c1f5f4dSJanus 	if (attrSize <= 0 || heightAttr != height)
15799c1f5f4dSJanus 		node.WriteAttr(kHeightAttrName, B_INT32_TYPE, 0, &height, sizeof(height));
1580e62a6973SJanus }
1581e62a6973SJanus 
1582e62a6973SJanus 
1583e62a6973SJanus void
158494fd9498SStephan Aßmus ShowImageWindow::_SetToolBarVisible(bool visible, bool animate)
1585cf0d8308SStephan Aßmus {
158695667008SJanus 	if (visible == fToolBarVisible)
1587cf0d8308SStephan Aßmus 		return;
1588cf0d8308SStephan Aßmus 
158995667008SJanus 	fToolBarVisible = visible;
159094a4c1c4SAugustin Cavalier 	float diff = fToolBar->Bounds().Height() + 2;
159194fd9498SStephan Aßmus 	if (!visible)
1592cf0d8308SStephan Aßmus 		diff = -diff;
159394fd9498SStephan Aßmus 	else
159494a4c1c4SAugustin Cavalier 		fToolBar->Show();
1595cf0d8308SStephan Aßmus 
159694fd9498SStephan Aßmus 	if (animate) {
159794fd9498SStephan Aßmus 		// Slide the controls into view. We do this with messages in order
159894fd9498SStephan Aßmus 		// not to block the window thread.
159994fd9498SStephan Aßmus 		const float kAnimationOffsets[] = { 0.05, 0.2, 0.5, 0.2, 0.05 };
160094fd9498SStephan Aßmus 		const int32 steps = sizeof(kAnimationOffsets) / sizeof(float);
160194fd9498SStephan Aßmus 		for (int32 i = 0; i < steps; i++) {
160294fd9498SStephan Aßmus 			BMessage message(kMsgSlideToolBar);
160394fd9498SStephan Aßmus 			message.AddFloat("offset", floorf(diff * kAnimationOffsets[i]));
160494fd9498SStephan Aßmus 			PostMessage(&message, this);
160594fd9498SStephan Aßmus 		}
160694fd9498SStephan Aßmus 		BMessage finalMessage(kMsgFinishSlidingToolBar);
160795667008SJanus 		finalMessage.AddFloat("offset", visible ? 0 : diff);
160894fd9498SStephan Aßmus 		finalMessage.AddBool("show", visible);
160994fd9498SStephan Aßmus 		PostMessage(&finalMessage, this);
161094fd9498SStephan Aßmus 	} else {
1611cf0d8308SStephan Aßmus 		fScrollView->ResizeBy(0, -diff);
1612cf0d8308SStephan Aßmus 		fScrollView->MoveBy(0, diff);
161394a4c1c4SAugustin Cavalier 		fToolBar->MoveBy(0, diff);
161494fd9498SStephan Aßmus 		if (!visible)
161594a4c1c4SAugustin Cavalier 			fToolBar->Hide();
161694fd9498SStephan Aßmus 	}
1617cf0d8308SStephan Aßmus }
1618cf0d8308SStephan Aßmus 
1619cf0d8308SStephan Aßmus 
162060c23976SJanus void
162160c23976SJanus ShowImageWindow::_SetToolBarBorder(bool visible)
162260c23976SJanus {
162360c23976SJanus 	float inset = visible
162460c23976SJanus 		? ceilf(be_control_look->DefaultItemSpacing() / 2) : 0;
162560c23976SJanus 
162660c23976SJanus 	fToolBar->GroupLayout()->SetInsets(inset, 0, inset, 0);
162760c23976SJanus }
162860c23976SJanus 
162960c23976SJanus 
1630780d8a62SMichael Pfeiffer bool
1631cdb89ebbSMatthew Wilber ShowImageWindow::QuitRequested()
1632cdb89ebbSMatthew Wilber {
1633efa8b4f3SAxel Dörfler 	if (fSavePanel) {
1634efa8b4f3SAxel Dörfler 		// Don't allow this window to be closed if a save panel is open
1635efa8b4f3SAxel Dörfler 		return false;
1636cdb89ebbSMatthew Wilber 	}
1637cdb89ebbSMatthew Wilber 
16385b76e505SStephan Aßmus 	if (!_ClosePrompt())
16395b76e505SStephan Aßmus 		return false;
16405b76e505SStephan Aßmus 
16415b76e505SStephan Aßmus 	ShowImageSettings* settings = my_app->Settings();
16425b76e505SStephan Aßmus 	if (settings->Lock()) {
1643c418e2beSStephan Aßmus 		if (fFullScreen)
1644c418e2beSStephan Aßmus 			settings->SetRect("WindowFrame", fWindowFrame);
1645c418e2beSStephan Aßmus 		else
16465b76e505SStephan Aßmus 			settings->SetRect("WindowFrame", Frame());
16475b76e505SStephan Aßmus 		settings->Unlock();
16485b76e505SStephan Aßmus 	}
16495b76e505SStephan Aßmus 
16505b76e505SStephan Aßmus 	be_app->PostMessage(MSG_WINDOW_HAS_QUIT);
16515b76e505SStephan Aßmus 
16525b76e505SStephan Aßmus 	return true;
1653efa8b4f3SAxel Dörfler }
1654