xref: /haiku/src/apps/showimage/ShowImageWindow.cpp (revision 58ee42e9df38c59277416ccd2e448c0393947c79)
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,
181*58ee42e9SAugustin Cavalier 		tool_bar_icon(kIconGoPrevious), B_TRANSLATE("Previous file"));
18294a4c1c4SAugustin Cavalier 	fToolBar->AddAction(MSG_FILE_NEXT, this, tool_bar_icon(kIconGoNext),
183*58ee42e9SAugustin Cavalier 		B_TRANSLATE("Next file"));
184a877c0e7SStephan Aßmus 	BMessage* fullScreenSlideShow = new BMessage(MSG_SLIDE_SHOW);
185a877c0e7SStephan Aßmus 	fullScreenSlideShow->AddBool("full screen", true);
18694a4c1c4SAugustin Cavalier 	fToolBar->AddAction(fullScreenSlideShow, this,
187*58ee42e9SAugustin Cavalier 		tool_bar_icon(kIconMediaMovieLibrary), B_TRANSLATE("Slide show"));
18894a4c1c4SAugustin Cavalier 	fToolBar->AddSeparator();
18994a4c1c4SAugustin Cavalier 	fToolBar->AddAction(MSG_SELECTION_MODE, this,
190cf0d8308SStephan Aßmus 		tool_bar_icon(kIconDrawRectangularSelection),
191*58ee42e9SAugustin Cavalier 		B_TRANSLATE("Selection mode"));
19294a4c1c4SAugustin Cavalier 	fToolBar->AddSeparator();
19394a4c1c4SAugustin Cavalier 	fToolBar->AddAction(kMsgOriginalSize, this,
194*58ee42e9SAugustin Cavalier 		tool_bar_icon(kIconZoomOriginal), B_TRANSLATE("Original size"), NULL,
195*58ee42e9SAugustin Cavalier 		true);
19694a4c1c4SAugustin Cavalier 	fToolBar->AddAction(kMsgFitToWindow, this,
197*58ee42e9SAugustin Cavalier 		tool_bar_icon(kIconZoomFitBest), B_TRANSLATE("Fit to window"));
19894a4c1c4SAugustin Cavalier 	fToolBar->AddAction(MSG_ZOOM_IN, this, tool_bar_icon(kIconZoomIn),
199*58ee42e9SAugustin Cavalier 		B_TRANSLATE("Zoom in"));
20094a4c1c4SAugustin Cavalier 	fToolBar->AddAction(MSG_ZOOM_OUT, this, tool_bar_icon(kIconZoomOut),
201*58ee42e9SAugustin Cavalier 		B_TRANSLATE("Zoom out"));
202442e457dSGerasim Troeglazov 	fToolBar->AddSeparator();
203442e457dSGerasim Troeglazov 	fToolBar->AddAction(MSG_PAGE_PREV, this, tool_bar_icon(kIconPagePrevious),
204*58ee42e9SAugustin Cavalier 		B_TRANSLATE("Previous page"));
205442e457dSGerasim Troeglazov 	fToolBar->AddAction(MSG_PAGE_NEXT, this, tool_bar_icon(kIconPageNext),
206*58ee42e9SAugustin Cavalier 		B_TRANSLATE("Next page"));
20794a4c1c4SAugustin Cavalier 	fToolBar->AddGlue();
20894a4c1c4SAugustin Cavalier 	fToolBar->AddAction(MSG_FULL_SCREEN, this,
209*58ee42e9SAugustin Cavalier 		tool_bar_icon(kIconViewWindowed), B_TRANSLATE("Leave full screen"));
21094a4c1c4SAugustin Cavalier 	fToolBar->SetActionVisible(MSG_FULL_SCREEN, false);
211cf0d8308SStephan Aßmus 
21294a4c1c4SAugustin Cavalier 	fToolBar->ResizeTo(viewFrame.Width(), fToolBar->MinSize().height);
213cf0d8308SStephan Aßmus 
21494a4c1c4SAugustin Cavalier 	contentView->AddChild(fToolBar);
215cf0d8308SStephan Aßmus 
216cf0d8308SStephan Aßmus 	if (fShowToolBar)
21794a4c1c4SAugustin Cavalier 		viewFrame.top = fToolBar->Frame().bottom + 1;
218cf0d8308SStephan Aßmus 	else
21994a4c1c4SAugustin Cavalier 		fToolBar->Hide();
220cf0d8308SStephan Aßmus 
22195667008SJanus 	fToolBarVisible = fShowToolBar;
22295667008SJanus 
22394fd9498SStephan Aßmus 	viewFrame.bottom = contentView->Bounds().bottom;
22413afa642SPhil Greenway 	viewFrame.bottom -= B_H_SCROLL_BAR_HEIGHT;
22513afa642SPhil Greenway 
22613afa642SPhil Greenway 	// create the image view
227d3046f7dSMichael Pfeiffer 	fImageView = new ShowImageView(viewFrame, "image_view", B_FOLLOW_ALL,
228e2069723SAxel Dörfler 		B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE | B_PULSE_NEEDED
229e2069723SAxel Dörfler 			| B_FRAME_EVENTS);
23013afa642SPhil Greenway 	// wrap a scroll view around the view
231cf0d8308SStephan Aßmus 	fScrollView = new BScrollView("image_scroller", fImageView,
232cae52eadSJanus 		B_FOLLOW_ALL, 0, true, true, B_PLAIN_BORDER);
23394fd9498SStephan Aßmus 	contentView->AddChild(fScrollView);
23413afa642SPhil Greenway 
235cae52eadSJanus 	fStatusView = new ShowImageStatusView(fScrollView);
236cae52eadSJanus 	fScrollView->AddChild(fStatusView);
23713afa642SPhil Greenway 
2389b13c418SStephan Aßmus 	// Update minimum window size
23994a4c1c4SAugustin Cavalier 	float toolBarMinWidth = fToolBar->MinSize().width;
2409b13c418SStephan Aßmus 	SetSizeLimits(std::max(menuBarMinWidth, toolBarMinWidth), 100000, 100,
2419b13c418SStephan Aßmus 		100000);
24213afa642SPhil Greenway 
243134d6076SMichael Pfeiffer 	// finish creating the window
244b9767a83SAxel Dörfler 	if (_LoadImage() != B_OK) {
245ba3217eeSAxel Dörfler 		_LoadError(ref);
2465e09d5dbSRyan Leavengood 		Quit();
24701939af6SAxel Dörfler 		return;
248d10d5947SMichael Pfeiffer 	}
249402c09e5SMatthew Wilber 
250d9f6762dSMichael Pfeiffer 	// add View menu here so it can access ShowImageView methods
251546208a5SOliver Tappe 	BMenu* menu = new BMenu(B_TRANSLATE_CONTEXT("View", "Menus"));
252fd952aefSRyan Leavengood 	_BuildViewMenu(menu, false);
253d9f6762dSMichael Pfeiffer 	fBar->AddItem(menu);
254d9f6762dSMichael Pfeiffer 
2555b76e505SStephan Aßmus 	fBar->AddItem(_BuildRatingMenu());
2565b76e505SStephan Aßmus 
257d9f6762dSMichael Pfeiffer 	SetPulseRate(100000);
258d9f6762dSMichael Pfeiffer 		// every 1/10 second; ShowImageView needs it for marching ants
259d9f6762dSMichael Pfeiffer 
2606db01936SAxel Dörfler 	_MarkMenuItem(menu, MSG_SELECTION_MODE,
2616db01936SAxel Dörfler 		fImageView->IsSelectionModeEnabled());
2626db01936SAxel Dörfler 
263402c09e5SMatthew Wilber 	// Tell application object to query the clipboard
264402c09e5SMatthew Wilber 	// and tell this window if it contains interesting data or not
265402c09e5SMatthew Wilber 	be_app_messenger.SendMessage(B_CLIPBOARD_CHANGED);
266cd6b5cdeSAxel Dörfler 
267cd6b5cdeSAxel Dörfler 	// The window will be shown on screen automatically
268cd6b5cdeSAxel Dörfler 	Run();
26913afa642SPhil Greenway }
27013afa642SPhil Greenway 
271efa8b4f3SAxel Dörfler 
27213afa642SPhil Greenway ShowImageWindow::~ShowImageWindow()
27313afa642SPhil Greenway {
274e2069723SAxel Dörfler 	fProgressWindow->Lock();
275e2069723SAxel Dörfler 	fProgressWindow->Quit();
2764aa63633SAxel Dörfler 
2774aa63633SAxel Dörfler 	_StopSlideShow();
27813afa642SPhil Greenway }
27913afa642SPhil Greenway 
280efa8b4f3SAxel Dörfler 
281cdb89ebbSMatthew Wilber void
282d9f6762dSMichael Pfeiffer ShowImageWindow::BuildContextMenu(BMenu* menu)
283d9f6762dSMichael Pfeiffer {
284fd952aefSRyan Leavengood 	_BuildViewMenu(menu, true);
285d9f6762dSMichael Pfeiffer }
286efa8b4f3SAxel Dörfler 
28756b0c7b9SKarsten Heimrich 
288cdb89ebbSMatthew Wilber void
289fd952aefSRyan Leavengood ShowImageWindow::_BuildViewMenu(BMenu* menu, bool popupMenu)
290da87390fSMichael Pfeiffer {
291905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Slide show"), MSG_SLIDE_SHOW, 0, 0, this);
2924aa63633SAxel Dörfler 	_MarkMenuItem(menu, MSG_SLIDE_SHOW, fSlideShowRunner != NULL);
293905c8c8cSMatt Madia 	BMenu* delayMenu = new BMenu(B_TRANSLATE("Slide delay"));
2944aa63633SAxel Dörfler 	if (fSlideShowDelayMenu == NULL)
2954aa63633SAxel Dörfler 		fSlideShowDelayMenu = delayMenu;
296efa8b4f3SAxel Dörfler 
297efa8b4f3SAxel Dörfler 	delayMenu->SetRadioMode(true);
2984aa63633SAxel Dörfler 
2994aa63633SAxel Dörfler 	int32 kDelays[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 20};
3004aa63633SAxel Dörfler 	for (uint32 i = 0; i < sizeof(kDelays) / sizeof(kDelays[0]); i++) {
30103ad73fcSAdrien Destugues 		BString text;
30203ad73fcSAdrien Destugues 		BDurationFormat format;
30303ad73fcSAdrien Destugues 		text.Truncate(0);
30403ad73fcSAdrien Destugues 		format.Format(text, 0, kDelays[i] * 1000000LL);
3054aa63633SAxel Dörfler 
3064aa63633SAxel Dörfler 		_AddDelayItem(delayMenu, text.String(), kDelays[i] * 1000000LL);
3074aa63633SAxel Dörfler 	}
308efa8b4f3SAxel Dörfler 	menu->AddItem(delayMenu);
30930060f17SMatthew Wilber 
310efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
311efa8b4f3SAxel Dörfler 
312905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Original size"),
313e2069723SAxel Dörfler 		kMsgOriginalSize, '1', 0, this);
314e2069723SAxel Dörfler 	_AddItemMenu(menu, B_TRANSLATE("Fit to window"),
315e2069723SAxel Dörfler 		kMsgFitToWindow, '0', 0, this);
316905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Zoom in"), MSG_ZOOM_IN, '+', 0, this);
317905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Zoom out"), MSG_ZOOM_OUT, '-', 0, this);
318efa8b4f3SAxel Dörfler 
319efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
320efa8b4f3SAxel Dörfler 
3214fd570d3SAxel Dörfler 	if (!popupMenu || fFullScreen) {
322905c8c8cSMatt Madia 		_AddItemMenu(menu, B_TRANSLATE("High-quality zooming"),
323905c8c8cSMatt Madia 			MSG_SCALE_BILINEAR, 0, 0, this);
3244fd570d3SAxel Dörfler 		_AddItemMenu(menu, B_TRANSLATE("Stretch to window"),
325e2069723SAxel Dörfler 			kMsgStretchToWindow, 0, 0, this);
326efa8b4f3SAxel Dörfler 
327efa8b4f3SAxel Dörfler 		menu->AddSeparatorItem();
32832c22143SAxel Dörfler 	}
329efa8b4f3SAxel Dörfler 
330905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Full screen"),
331905c8c8cSMatt Madia 		MSG_FULL_SCREEN, B_ENTER, 0, this);
332fd952aefSRyan Leavengood 	_MarkMenuItem(menu, MSG_FULL_SCREEN, fFullScreen);
333efa8b4f3SAxel Dörfler 
334905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Show caption in full screen mode"),
335905c8c8cSMatt Madia 		MSG_SHOW_CAPTION, 0, 0, this);
336fd952aefSRyan Leavengood 	_MarkMenuItem(menu, MSG_SHOW_CAPTION, fShowCaption);
337efa8b4f3SAxel Dörfler 
338e2069723SAxel Dörfler 	_MarkMenuItem(menu, MSG_SCALE_BILINEAR, fImageView->ScaleBilinear());
339e2069723SAxel Dörfler 	_MarkMenuItem(menu, kMsgStretchToWindow, fImageView->StretchesToBounds());
340a60adbf9SAxel Dörfler 
341cf0d8308SStephan Aßmus 	if (!popupMenu) {
34294fd9498SStephan Aßmus 		_AddItemMenu(menu, B_TRANSLATE("Show tool bar"), kMsgToggleToolBar,
343d5647665SHumdinger 			'B', 0, this);
344cf0d8308SStephan Aßmus 		_MarkMenuItem(menu, kMsgToggleToolBar,
34594a4c1c4SAugustin Cavalier 			!fToolBar->IsHidden(fToolBar));
346cf0d8308SStephan Aßmus 	}
347cf0d8308SStephan Aßmus 
348d9f6762dSMichael Pfeiffer 	if (popupMenu) {
349a60adbf9SAxel Dörfler 		menu->AddSeparatorItem();
350905c8c8cSMatt Madia 		_AddItemMenu(menu, B_TRANSLATE("Use as background" B_UTF8_ELLIPSIS),
3511ed4535fSStephan Aßmus 			MSG_DESKTOP_BACKGROUND, 0, 0, this);
352d9f6762dSMichael Pfeiffer 	}
353da87390fSMichael Pfeiffer }
354da87390fSMichael Pfeiffer 
355efa8b4f3SAxel Dörfler 
3565b76e505SStephan Aßmus BMenu*
3575b76e505SStephan Aßmus ShowImageWindow::_BuildRatingMenu()
3585b76e505SStephan Aßmus {
3595b76e505SStephan Aßmus 	fRatingMenu = new BMenu(B_TRANSLATE("Rating"));
3605b76e505SStephan Aßmus 	for (int32 i = 1; i <= 10; i++) {
3615b76e505SStephan Aßmus 		BString label;
3625b76e505SStephan Aßmus 		label << i;
3635b76e505SStephan Aßmus 		BMessage* message = new BMessage(MSG_SET_RATING);
3645b76e505SStephan Aßmus 		message->AddInt32("rating", i);
3655b76e505SStephan Aßmus 		fRatingMenu->AddItem(new BMenuItem(label.String(), message));
3665b76e505SStephan Aßmus 	}
3675b76e505SStephan Aßmus 	// NOTE: We may want to encapsulate the Rating menu within a more
3685b76e505SStephan Aßmus 	// general "Attributes" menu.
3695b76e505SStephan Aßmus 	return fRatingMenu;
3705b76e505SStephan Aßmus }
3715b76e505SStephan Aßmus 
3725b76e505SStephan Aßmus 
373da87390fSMichael Pfeiffer void
374b9767a83SAxel Dörfler ShowImageWindow::_AddMenus(BMenuBar* bar)
37513afa642SPhil Greenway {
376905c8c8cSMatt Madia 	BMenu* menu = new BMenu(B_TRANSLATE("File"));
37736272f0dSAxel Dörfler 
37836272f0dSAxel Dörfler 	// Add recent files to "Open File" entry as sub-menu.
37936272f0dSAxel Dörfler 	BMenuItem* item = new BMenuItem(BRecentFilesList::NewFileListMenu(
38036272f0dSAxel Dörfler 		B_TRANSLATE("Open" B_UTF8_ELLIPSIS), NULL, NULL, be_app, 10, true,
38136272f0dSAxel Dörfler 		NULL, kApplicationSignature), new BMessage(MSG_FILE_OPEN));
38236272f0dSAxel Dörfler 	item->SetShortcut('O', 0);
38336272f0dSAxel Dörfler 	item->SetTarget(be_app);
38436272f0dSAxel Dörfler 	menu->AddItem(item);
385efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
38636272f0dSAxel Dörfler 
3876db01936SAxel Dörfler 	BMenu* menuSaveAs = new BMenu(B_TRANSLATE("Save as" B_UTF8_ELLIPSIS),
3881ed4535fSStephan Aßmus 		B_ITEMS_IN_COLUMN);
3896db01936SAxel Dörfler 	BTranslationUtils::AddTranslationItems(menuSaveAs, B_TRANSLATOR_BITMAP);
390fc0a275bSMatthew Wilber 		// Fill Save As submenu with all types that can be converted
391fc0a275bSMatthew Wilber 		// to from the Be bitmap image format
3926db01936SAxel Dörfler 	menu->AddItem(menuSaveAs);
393905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Close"), B_QUIT_REQUESTED, 'W', 0, this);
394d5647665SHumdinger 	_AddItemMenu(menu, B_TRANSLATE("Move to Trash"), kMsgDeleteCurrentFile, 'T', 0, this);
395efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
396905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Page setup" B_UTF8_ELLIPSIS),
3971ed4535fSStephan Aßmus 		MSG_PAGE_SETUP, 0, 0, this);
398905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Print" B_UTF8_ELLIPSIS),
3991ed4535fSStephan Aßmus 		MSG_PREPARE_PRINT, 'P', 0, this);
400efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
401905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Quit"), B_QUIT_REQUESTED, 'Q', 0, be_app);
402efa8b4f3SAxel Dörfler 	bar->AddItem(menu);
40313afa642SPhil Greenway 
404905c8c8cSMatt Madia 	menu = new BMenu(B_TRANSLATE("Edit"));
405905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Copy"), B_COPY, 'C', 0, this, false);
406efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
407cf0d8308SStephan Aßmus 	_AddItemMenu(menu, B_TRANSLATE("Selection mode"), MSG_SELECTION_MODE, 0, 0,
4086db01936SAxel Dörfler 		this);
40932c22143SAxel Dörfler 	_AddItemMenu(menu, B_TRANSLATE("Clear selection"),
41032c22143SAxel Dörfler 		MSG_CLEAR_SELECT, 0, 0, this, false);
411905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Select all"),
412905c8c8cSMatt Madia 		MSG_SELECT_ALL, 'A', 0, this);
413efa8b4f3SAxel Dörfler 	bar->AddItem(menu);
41413afa642SPhil Greenway 
415905c8c8cSMatt Madia 	menu = fBrowseMenu = new BMenu(B_TRANSLATE("Browse"));
416905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("First page"),
4171ed4535fSStephan Aßmus 		MSG_PAGE_FIRST, B_LEFT_ARROW, B_SHIFT_KEY, this);
418905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Last page"),
4191ed4535fSStephan Aßmus 		MSG_PAGE_LAST, B_RIGHT_ARROW, B_SHIFT_KEY, this);
420905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Previous page"),
421905c8c8cSMatt Madia 		MSG_PAGE_PREV, B_LEFT_ARROW, 0, this);
422905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Next page"),
423905c8c8cSMatt Madia 		MSG_PAGE_NEXT, B_RIGHT_ARROW, 0, this);
424905c8c8cSMatt Madia 	fGoToPageMenu = new BMenu(B_TRANSLATE("Go to page"));
4255e427b6aSMichael Pfeiffer 	fGoToPageMenu->SetRadioMode(true);
426efa8b4f3SAxel Dörfler 	menu->AddItem(fGoToPageMenu);
427efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
428905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Previous file"),
429905c8c8cSMatt Madia 		MSG_FILE_PREV, B_UP_ARROW, 0, this);
430905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Next file"),
431905c8c8cSMatt Madia 		MSG_FILE_NEXT, B_DOWN_ARROW, 0, this);
432efa8b4f3SAxel Dörfler 	bar->AddItem(menu);
43303839579SMatthew Wilber 
434905c8c8cSMatt Madia 	menu = new BMenu(B_TRANSLATE("Image"));
435905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Rotate clockwise"),
436905c8c8cSMatt Madia 		MSG_ROTATE_90, 'R', 0, this);
437905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Rotate counterclockwise"),
4381ed4535fSStephan Aßmus 		MSG_ROTATE_270, 'R', B_SHIFT_KEY, this);
439efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
440905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Flip left to right"),
4411ed4535fSStephan Aßmus 		MSG_FLIP_LEFT_TO_RIGHT, 0, 0, this);
442905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Flip top to bottom"),
4431ed4535fSStephan Aßmus 		MSG_FLIP_TOP_TO_BOTTOM, 0, 0, this);
444efa8b4f3SAxel Dörfler 	menu->AddSeparatorItem();
445905c8c8cSMatt Madia 	_AddItemMenu(menu, B_TRANSLATE("Use as background" B_UTF8_ELLIPSIS),
4461ed4535fSStephan Aßmus 		MSG_DESKTOP_BACKGROUND, 0, 0, this);
44704f96544SAxel Dörfler 
44804f96544SAxel Dörfler 	bar->AddItem(menu);
44913afa642SPhil Greenway }
45013afa642SPhil Greenway 
451efa8b4f3SAxel Dörfler 
452cdb89ebbSMatthew Wilber BMenuItem*
453fd952aefSRyan Leavengood ShowImageWindow::_AddItemMenu(BMenu* menu, const char* label, uint32 what,
4544fd570d3SAxel Dörfler 	char shortcut, uint32 modifier, const BHandler* target, bool enabled)
455cdb89ebbSMatthew Wilber {
4564fd570d3SAxel Dörfler 	BMenuItem* item = new BMenuItem(label, new BMessage(what), shortcut,
4574fd570d3SAxel Dörfler 		modifier);
458efa8b4f3SAxel Dörfler 	menu->AddItem(item);
459efa8b4f3SAxel Dörfler 
4606163f333SKarsten Heimrich 	item->SetTarget(target);
4616163f333SKarsten Heimrich 	item->SetEnabled(enabled);
4626163f333SKarsten Heimrich 
463efa8b4f3SAxel Dörfler 	return item;
46413afa642SPhil Greenway }
46513afa642SPhil Greenway 
466efa8b4f3SAxel Dörfler 
467ad13f387SMichael Pfeiffer BMenuItem*
4684aa63633SAxel Dörfler ShowImageWindow::_AddDelayItem(BMenu* menu, const char* label, bigtime_t delay)
469ad13f387SMichael Pfeiffer {
470efa8b4f3SAxel Dörfler 	BMessage* message = new BMessage(MSG_SLIDE_SHOW_DELAY);
4714aa63633SAxel Dörfler 	message->AddInt64("delay", delay);
472ad13f387SMichael Pfeiffer 
4736163f333SKarsten Heimrich 	BMenuItem* item = new BMenuItem(label, message, 0);
474efa8b4f3SAxel Dörfler 	item->SetTarget(this);
475ad13f387SMichael Pfeiffer 
4764aa63633SAxel Dörfler 	if (delay == fSlideShowDelay)
477efa8b4f3SAxel Dörfler 		item->SetMarked(true);
478ad13f387SMichael Pfeiffer 
479efa8b4f3SAxel Dörfler 	menu->AddItem(item);
480efa8b4f3SAxel Dörfler 	return item;
481ad13f387SMichael Pfeiffer }
482ad13f387SMichael Pfeiffer 
483efa8b4f3SAxel Dörfler 
484cdb89ebbSMatthew Wilber void
485e2069723SAxel Dörfler ShowImageWindow::_ResizeWindowToImage()
48613afa642SPhil Greenway {
487e2069723SAxel Dörfler 	BBitmap* bitmap = fImageView->Bitmap();
488d10d5947SMichael Pfeiffer 	BScreen screen;
489e2069723SAxel Dörfler 	if (bitmap == NULL || !screen.IsValid())
490efa8b4f3SAxel Dörfler 		return;
491efa8b4f3SAxel Dörfler 
4921076d97bSAxel Dörfler 	// TODO: use View::GetPreferredSize() instead?
4931076d97bSAxel Dörfler 	BRect r(bitmap->Bounds());
4941076d97bSAxel Dörfler 	float width = r.Width() + B_V_SCROLL_BAR_WIDTH;
4951076d97bSAxel Dörfler 	float height = r.Height() + 1 + fBar->Frame().Height()
4961076d97bSAxel Dörfler 		+ B_H_SCROLL_BAR_HEIGHT;
497cdb89ebbSMatthew Wilber 
4986163f333SKarsten Heimrich 	BRect frame = screen.Frame();
4996163f333SKarsten Heimrich 	const float windowBorder = 5;
500d10d5947SMichael Pfeiffer 	// dimensions so that window does not reach outside of screen
5016163f333SKarsten Heimrich 	float maxWidth = frame.Width() + 1 - windowBorder - Frame().left;
5026163f333SKarsten Heimrich 	float maxHeight = frame.Height() + 1 - windowBorder - Frame().top;
503cdb89ebbSMatthew Wilber 
504a8fc7138SMichael Pfeiffer 	// We have to check size limits manually, otherwise
505a8fc7138SMichael Pfeiffer 	// menu bar will be too short for small images.
506efa8b4f3SAxel Dörfler 
507fc5ca95dSStephan Aßmus 	float minW, maxW, minH, maxH;
508a8fc7138SMichael Pfeiffer 	GetSizeLimits(&minW, &maxW, &minH, &maxH);
509efa8b4f3SAxel Dörfler 	if (maxWidth > maxW)
510efa8b4f3SAxel Dörfler 		maxWidth = maxW;
511efa8b4f3SAxel Dörfler 	if (maxHeight > maxH)
512efa8b4f3SAxel Dörfler 		maxHeight = maxH;
513efa8b4f3SAxel Dörfler 	if (width < minW)
514efa8b4f3SAxel Dörfler 		width = minW;
515efa8b4f3SAxel Dörfler 	if (height < minH)
516efa8b4f3SAxel Dörfler 		height = minH;
517a8fc7138SMichael Pfeiffer 
518efa8b4f3SAxel Dörfler 	if (width > maxWidth)
519efa8b4f3SAxel Dörfler 		width = maxWidth;
520efa8b4f3SAxel Dörfler 	if (height > maxHeight)
521efa8b4f3SAxel Dörfler 		height = maxHeight;
522d10d5947SMichael Pfeiffer 
523d10d5947SMichael Pfeiffer 	ResizeTo(width, height);
52413afa642SPhil Greenway }
52513afa642SPhil Greenway 
526efa8b4f3SAxel Dörfler 
5277eca0987SMichael Pfeiffer bool
528fd952aefSRyan Leavengood ShowImageWindow::_ToggleMenuItem(uint32 what)
5297eca0987SMichael Pfeiffer {
5307eca0987SMichael Pfeiffer 	bool marked = false;
5316163f333SKarsten Heimrich 	BMenuItem* item = fBar->FindItem(what);
5327eca0987SMichael Pfeiffer 	if (item != NULL) {
5337eca0987SMichael Pfeiffer 		marked = !item->IsMarked();
5347eca0987SMichael Pfeiffer 		item->SetMarked(marked);
5357eca0987SMichael Pfeiffer 	}
53694a4c1c4SAugustin Cavalier 	fToolBar->SetActionPressed(what, marked);
5377eca0987SMichael Pfeiffer 	return marked;
5387eca0987SMichael Pfeiffer }
5397eca0987SMichael Pfeiffer 
540efa8b4f3SAxel Dörfler 
541cdb89ebbSMatthew Wilber void
542fd952aefSRyan Leavengood ShowImageWindow::_EnableMenuItem(BMenu* menu, uint32 what, bool enable)
543e6a50d9cSMichael Pfeiffer {
5446163f333SKarsten Heimrich 	BMenuItem* item = menu->FindItem(what);
5456163f333SKarsten Heimrich 	if (item && item->IsEnabled() != enable)
546e6a50d9cSMichael Pfeiffer 		item->SetEnabled(enable);
54794a4c1c4SAugustin Cavalier 	fToolBar->SetActionEnabled(what, enable);
548e6a50d9cSMichael Pfeiffer }
549e6a50d9cSMichael Pfeiffer 
550efa8b4f3SAxel Dörfler 
551e6a50d9cSMichael Pfeiffer void
552fd952aefSRyan Leavengood ShowImageWindow::_MarkMenuItem(BMenu* menu, uint32 what, bool marked)
553e6a50d9cSMichael Pfeiffer {
5546163f333SKarsten Heimrich 	BMenuItem* item = menu->FindItem(what);
5556163f333SKarsten Heimrich 	if (item && item->IsMarked() != marked)
556e6a50d9cSMichael Pfeiffer 		item->SetMarked(marked);
55794a4c1c4SAugustin Cavalier 	fToolBar->SetActionPressed(what, marked);
558e6a50d9cSMichael Pfeiffer }
559e6a50d9cSMichael Pfeiffer 
560efa8b4f3SAxel Dörfler 
561da87390fSMichael Pfeiffer void
5624aa63633SAxel Dörfler ShowImageWindow::_MarkSlideShowDelay(bigtime_t delay)
563da87390fSMichael Pfeiffer {
5644aa63633SAxel Dörfler 	const int32 count = fSlideShowDelayMenu->CountItems();
5654aa63633SAxel Dörfler 	for (int32 i = 0; i < count; i ++) {
5664aa63633SAxel Dörfler 		BMenuItem* item = fSlideShowDelayMenu->ItemAt(i);
5674aa63633SAxel Dörfler 		if (item != NULL) {
5684aa63633SAxel Dörfler 			bigtime_t itemDelay;
5694aa63633SAxel Dörfler 			if (item->Message()->FindInt64("delay", &itemDelay) == B_OK
5704aa63633SAxel Dörfler 				&& itemDelay == delay) {
571da87390fSMichael Pfeiffer 				item->SetMarked(true);
572da87390fSMichael Pfeiffer 				return;
573da87390fSMichael Pfeiffer 			}
574da87390fSMichael Pfeiffer 		}
575da87390fSMichael Pfeiffer 	}
576da87390fSMichael Pfeiffer }
577e6a50d9cSMichael Pfeiffer 
57819c76de4SMichael Pfeiffer 
57919c76de4SMichael Pfeiffer void
580e2069723SAxel Dörfler ShowImageWindow::Zoom(BPoint origin, float width, float height)
58119c76de4SMichael Pfeiffer {
582e2069723SAxel Dörfler 	_ToggleFullScreen();
58319c76de4SMichael Pfeiffer }
58419c76de4SMichael Pfeiffer 
585efa8b4f3SAxel Dörfler 
586e6a50d9cSMichael Pfeiffer void
587efa8b4f3SAxel Dörfler ShowImageWindow::MessageReceived(BMessage* message)
58813afa642SPhil Greenway {
589e2069723SAxel Dörfler 	if (message->WasDropped()) {
590e2069723SAxel Dörfler 		uint32 type;
591e2069723SAxel Dörfler 		int32 count;
592e2069723SAxel Dörfler 		status_t status = message->GetInfo("refs", &type, &count);
593e2069723SAxel Dörfler 		if (status == B_OK && type == B_REF_TYPE) {
594e2069723SAxel Dörfler 			message->what = B_REFS_RECEIVED;
595e2069723SAxel Dörfler 			be_app->PostMessage(message);
596e2069723SAxel Dörfler 		}
597e2069723SAxel Dörfler 	}
598e2069723SAxel Dörfler 
599efa8b4f3SAxel Dörfler 	switch (message->what) {
600e2069723SAxel Dörfler 		case kMsgImageCacheImageLoaded:
601cd6b5cdeSAxel Dörfler 		{
602e2069723SAxel Dörfler 			fProgressWindow->Stop();
603e2069723SAxel Dörfler 
604df942b3eSAxel Dörfler 			BitmapOwner* bitmapOwner = NULL;
605df942b3eSAxel Dörfler 			message->FindPointer("bitmapOwner", (void**)&bitmapOwner);
606df942b3eSAxel Dörfler 
607cd6b5cdeSAxel Dörfler 			bool first = fImageView->Bitmap() == NULL;
608b9767a83SAxel Dörfler 			entry_ref ref;
609b9767a83SAxel Dörfler 			message->FindRef("ref", &ref);
610b9767a83SAxel Dörfler 			if (!first && ref != fNavigator.CurrentRef()) {
611b9767a83SAxel Dörfler 				// ignore older images
612df942b3eSAxel Dörfler 				if (bitmapOwner != NULL)
613df942b3eSAxel Dörfler 					bitmapOwner->ReleaseReference();
614b9767a83SAxel Dörfler 				break;
615b9767a83SAxel Dörfler 			}
616cd6b5cdeSAxel Dörfler 
617baa27ccbSJanus 			int32 page = message->FindInt32("page");
618baa27ccbSJanus 			int32 pageCount = message->FindInt32("pageCount");
619baa27ccbSJanus 			if (!first && page != fNavigator.CurrentPage()) {
620baa27ccbSJanus 				// ignore older pages
621baa27ccbSJanus 				if (bitmapOwner != NULL)
622baa27ccbSJanus 					bitmapOwner->ReleaseReference();
623baa27ccbSJanus 				break;
624baa27ccbSJanus 			}
625baa27ccbSJanus 
626cd6b5cdeSAxel Dörfler 			status_t status = fImageView->SetImage(message);
627cd6b5cdeSAxel Dörfler 			if (status != B_OK) {
628df942b3eSAxel Dörfler 				if (bitmapOwner != NULL)
629df942b3eSAxel Dörfler 					bitmapOwner->ReleaseReference();
630df942b3eSAxel Dörfler 
631cd6b5cdeSAxel Dörfler 				_LoadError(ref);
632cd6b5cdeSAxel Dörfler 
633cd6b5cdeSAxel Dörfler 				// quit if file could not be opened
634cd6b5cdeSAxel Dörfler 				if (first)
635cd6b5cdeSAxel Dörfler 					Quit();
636cd6b5cdeSAxel Dörfler 				break;
637cd6b5cdeSAxel Dörfler 			}
638cd6b5cdeSAxel Dörfler 
639cd6b5cdeSAxel Dörfler 			fImageType = message->FindString("type");
640baa27ccbSJanus 			fNavigator.SetTo(ref, page, pageCount);
641cd6b5cdeSAxel Dörfler 
642e2069723SAxel Dörfler 			fImageView->FitToBounds();
643cd6b5cdeSAxel Dörfler 			if (first) {
644cd6b5cdeSAxel Dörfler 				fImageView->MakeFocus(true);
645cd6b5cdeSAxel Dörfler 					// to receive key messages
646cd6b5cdeSAxel Dörfler 				Show();
647e2069723SAxel Dörfler 			}
6485b76e505SStephan Aßmus 			_UpdateRatingMenu();
649e62a6973SJanus 			// Set width and height attributes of the currently showed file.
650e62a6973SJanus 			// This should only be a temporary solution.
651e62a6973SJanus 			_SaveWidthAndHeight();
652e2069723SAxel Dörfler 			break;
653e2069723SAxel Dörfler 		}
654e2069723SAxel Dörfler 
655e2069723SAxel Dörfler 		case kMsgImageCacheProgressUpdate:
656e2069723SAxel Dörfler 		{
657e2069723SAxel Dörfler 			entry_ref ref;
658e2069723SAxel Dörfler 			if (message->FindRef("ref", &ref) == B_OK
659e2069723SAxel Dörfler 				&& ref == fNavigator.CurrentRef()) {
660e2069723SAxel Dörfler 				message->what = kMsgProgressUpdate;
661e2069723SAxel Dörfler 				fProgressWindow->PostMessage(message);
662cd6b5cdeSAxel Dörfler 			}
663cd6b5cdeSAxel Dörfler 			break;
664cd6b5cdeSAxel Dörfler 		}
665cd6b5cdeSAxel Dörfler 
666ee7b4f39SMatthew Wilber 		case MSG_MODIFIED:
667ee7b4f39SMatthew Wilber 			// If image has been modified due to a Cut or Paste
668ee7b4f39SMatthew Wilber 			fModified = true;
669ee7b4f39SMatthew Wilber 			break;
670ee7b4f39SMatthew Wilber 
671fc0a275bSMatthew Wilber 		case MSG_OUTPUT_TYPE:
672fc0a275bSMatthew Wilber 			// User clicked Save As then choose an output format
673d3046f7dSMichael Pfeiffer 			if (!fSavePanel)
674cdb89ebbSMatthew Wilber 				// If user doesn't already have a save panel open
675fd952aefSRyan Leavengood 				_SaveAs(message);
67613afa642SPhil Greenway 			break;
677fc0a275bSMatthew Wilber 
678fc0a275bSMatthew Wilber 		case MSG_SAVE_PANEL:
679fc0a275bSMatthew Wilber 			// User specified where to save the output image
680fd952aefSRyan Leavengood 			_SaveToFile(message);
68107caaa8eSMatthew Wilber 			break;
68207caaa8eSMatthew Wilber 
683cdb89ebbSMatthew Wilber 		case B_CANCEL:
684d3046f7dSMichael Pfeiffer 			delete fSavePanel;
685d3046f7dSMichael Pfeiffer 			fSavePanel = NULL;
686cdb89ebbSMatthew Wilber 			break;
687cdb89ebbSMatthew Wilber 
6886db01936SAxel Dörfler 		case MSG_UPDATE_STATUS:
6896db01936SAxel Dörfler 		{
690cd6b5cdeSAxel Dörfler 			int32 pages = fNavigator.PageCount();
691cd6b5cdeSAxel Dörfler 			int32 currentPage = fNavigator.CurrentPage();
6926c305411SMatthew Wilber 
693baa27ccbSJanus 			_EnableMenuItem(fBar, MSG_PAGE_FIRST,
694baa27ccbSJanus 				fNavigator.HasPreviousPage());
695baa27ccbSJanus 			_EnableMenuItem(fBar, MSG_PAGE_LAST, fNavigator.HasNextPage());
696baa27ccbSJanus 			_EnableMenuItem(fBar, MSG_PAGE_NEXT, fNavigator.HasNextPage());
697baa27ccbSJanus 			_EnableMenuItem(fBar, MSG_PAGE_PREV, fNavigator.HasPreviousPage());
698baa27ccbSJanus 			fGoToPageMenu->SetEnabled(pages > 1);
6991d592070SMatthew Wilber 
700cd6b5cdeSAxel Dörfler 			_EnableMenuItem(fBar, MSG_FILE_NEXT, fNavigator.HasNextFile());
701cd6b5cdeSAxel Dörfler 			_EnableMenuItem(fBar, MSG_FILE_PREV, fNavigator.HasPreviousFile());
702134d6076SMichael Pfeiffer 
703d3046f7dSMichael Pfeiffer 			if (fGoToPageMenu->CountItems() != pages) {
7046c305411SMatthew Wilber 				// Only rebuild the submenu if the number of
7056c305411SMatthew Wilber 				// pages is different
7066c305411SMatthew Wilber 
707cd6b5cdeSAxel Dörfler 				while (fGoToPageMenu->CountItems() > 0) {
7086c305411SMatthew Wilber 					// Remove all page numbers
7097f4d1af4SSergei Reznikov 					delete fGoToPageMenu->RemoveItem((int32)0);
710cd6b5cdeSAxel Dörfler 				}
7116c305411SMatthew Wilber 
712780d8a62SMichael Pfeiffer 				for (int32 i = 1; i <= pages; i++) {
7136c305411SMatthew Wilber 					// Fill Go To page submenu with an entry for each page
714cd6b5cdeSAxel Dörfler 					BMessage* goTo = new BMessage(MSG_GOTO_PAGE);
715cd6b5cdeSAxel Dörfler 					goTo->AddInt32("page", i);
7166163f333SKarsten Heimrich 
7176163f333SKarsten Heimrich 					char shortcut = 0;
718cd6b5cdeSAxel Dörfler 					if (i < 10)
719780d8a62SMichael Pfeiffer 						shortcut = '0' + i;
7206163f333SKarsten Heimrich 
7216163f333SKarsten Heimrich 					BString strCaption;
7226163f333SKarsten Heimrich 					strCaption << i;
7236163f333SKarsten Heimrich 
724cd6b5cdeSAxel Dörfler 					BMenuItem* item = new BMenuItem(strCaption.String(), goTo,
725a8199d69Sthreedeyes 						shortcut, B_SHIFT_KEY);
726cd6b5cdeSAxel Dörfler 					if (currentPage == i)
727efa8b4f3SAxel Dörfler 						item->SetMarked(true);
728efa8b4f3SAxel Dörfler 					fGoToPageMenu->AddItem(item);
7296c305411SMatthew Wilber 				}
7306c305411SMatthew Wilber 			} else {
7316c305411SMatthew Wilber 				// Make sure the correct page is marked
732cd6b5cdeSAxel Dörfler 				BMenuItem* currentItem = fGoToPageMenu->ItemAt(currentPage - 1);
733cd6b5cdeSAxel Dörfler 				if (currentItem != NULL && !currentItem->IsMarked())
734cd6b5cdeSAxel Dörfler 					currentItem->SetMarked(true);
7356c305411SMatthew Wilber 			}
7366c305411SMatthew Wilber 
737cd6b5cdeSAxel Dörfler 			_UpdateStatusText(message);
738b9767a83SAxel Dörfler 
739b9767a83SAxel Dörfler 			BPath path(fImageView->Image());
740b9767a83SAxel Dörfler 			SetTitle(path.Path());
7416db01936SAxel Dörfler 			break;
7426db01936SAxel Dörfler 		}
74303839579SMatthew Wilber 
7446db01936SAxel Dörfler 		case MSG_UPDATE_STATUS_TEXT:
7456db01936SAxel Dörfler 		{
746cd6b5cdeSAxel Dörfler 			_UpdateStatusText(message);
7476db01936SAxel Dörfler 			break;
7486db01936SAxel Dörfler 		}
7498f5fd23fSRyan Leavengood 
7506db01936SAxel Dörfler 		case MSG_SELECTION:
7516db01936SAxel Dörfler 		{
7528ad30bcfSMatthew Wilber 			// The view sends this message when a selection is
7538ad30bcfSMatthew Wilber 			// made or the selection is cleared so that the window
7548ad30bcfSMatthew Wilber 			// can update the state of the appropriate menu items
7556db01936SAxel Dörfler 			bool enable;
7566db01936SAxel Dörfler 			if (message->FindBool("has_selection", &enable) == B_OK) {
7576db01936SAxel Dörfler 				_EnableMenuItem(fBar, B_COPY, enable);
7586db01936SAxel Dörfler 				_EnableMenuItem(fBar, MSG_CLEAR_SELECT, enable);
7598ad30bcfSMatthew Wilber 			}
7606db01936SAxel Dörfler 			break;
7616db01936SAxel Dörfler 		}
7628ad30bcfSMatthew Wilber 
76313afa642SPhil Greenway 		case B_COPY:
764d3046f7dSMichael Pfeiffer 			fImageView->CopySelectionToClipboard();
76513afa642SPhil Greenway 			break;
7666163f333SKarsten Heimrich 
7676db01936SAxel Dörfler 		case MSG_SELECTION_MODE:
768cf0d8308SStephan Aßmus 		{
769cf0d8308SStephan Aßmus 			bool selectionMode = _ToggleMenuItem(MSG_SELECTION_MODE);
770cf0d8308SStephan Aßmus 			fImageView->SetSelectionMode(selectionMode);
771cf0d8308SStephan Aßmus 			if (!selectionMode)
772cf0d8308SStephan Aßmus 				fImageView->ClearSelection();
7736db01936SAxel Dörfler 			break;
774cf0d8308SStephan Aßmus 		}
7756db01936SAxel Dörfler 
77613afa642SPhil Greenway 		case MSG_CLEAR_SELECT:
777d3046f7dSMichael Pfeiffer 			fImageView->ClearSelection();
77813afa642SPhil Greenway 			break;
7796163f333SKarsten Heimrich 
78013afa642SPhil Greenway 		case MSG_SELECT_ALL:
781d3046f7dSMichael Pfeiffer 			fImageView->SelectAll();
78213afa642SPhil Greenway 			break;
78313afa642SPhil Greenway 
78403839579SMatthew Wilber 		case MSG_PAGE_FIRST:
785b9767a83SAxel Dörfler 			if (_ClosePrompt() && fNavigator.FirstPage())
786b9767a83SAxel Dörfler 				_LoadImage();
78703839579SMatthew Wilber 			break;
78803839579SMatthew Wilber 
78903839579SMatthew Wilber 		case MSG_PAGE_LAST:
790b9767a83SAxel Dörfler 			if (_ClosePrompt() && fNavigator.LastPage())
791b9767a83SAxel Dörfler 				_LoadImage();
79203839579SMatthew Wilber 			break;
79303839579SMatthew Wilber 
79403839579SMatthew Wilber 		case MSG_PAGE_NEXT:
795b9767a83SAxel Dörfler 			if (_ClosePrompt() && fNavigator.NextPage())
796b9767a83SAxel Dörfler 				_LoadImage();
79703839579SMatthew Wilber 			break;
79803839579SMatthew Wilber 
79903839579SMatthew Wilber 		case MSG_PAGE_PREV:
800b9767a83SAxel Dörfler 			if (_ClosePrompt() && fNavigator.PreviousPage())
801b9767a83SAxel Dörfler 				_LoadImage();
80203839579SMatthew Wilber 			break;
80303839579SMatthew Wilber 
804cd6b5cdeSAxel Dörfler 		case MSG_GOTO_PAGE:
805cd6b5cdeSAxel Dörfler 		{
806fd952aefSRyan Leavengood 			if (!_ClosePrompt())
807ee7b4f39SMatthew Wilber 				break;
808ee7b4f39SMatthew Wilber 
8096163f333SKarsten Heimrich 			int32 newPage;
8106163f333SKarsten Heimrich 			if (message->FindInt32("page", &newPage) != B_OK)
8116163f333SKarsten Heimrich 				break;
8126163f333SKarsten Heimrich 
813cd6b5cdeSAxel Dörfler 			int32 currentPage = fNavigator.CurrentPage();
814cd6b5cdeSAxel Dörfler 			int32 pages = fNavigator.PageCount();
8156c305411SMatthew Wilber 
816b9767a83SAxel Dörfler 			// TODO: use radio mode instead!
8176c305411SMatthew Wilber 			if (newPage > 0 && newPage <= pages) {
818cd6b5cdeSAxel Dörfler 				BMenuItem* currentItem = fGoToPageMenu->ItemAt(currentPage - 1);
819cd6b5cdeSAxel Dörfler 				BMenuItem* newItem = fGoToPageMenu->ItemAt(newPage - 1);
820cd6b5cdeSAxel Dörfler 				if (currentItem != NULL && newItem != NULL) {
821cd6b5cdeSAxel Dörfler 					currentItem->SetMarked(false);
822cd6b5cdeSAxel Dörfler 					newItem->SetMarked(true);
823b9767a83SAxel Dörfler 					if (fNavigator.GoToPage(newPage))
824b9767a83SAxel Dörfler 						_LoadImage();
8256c305411SMatthew Wilber 				}
8266c305411SMatthew Wilber 			}
827cd6b5cdeSAxel Dörfler 			break;
828cd6b5cdeSAxel Dörfler 		}
8296c305411SMatthew Wilber 
830e2069723SAxel Dörfler 		case kMsgFitToWindow:
831e2069723SAxel Dörfler 			fImageView->FitToBounds();
83219c76de4SMichael Pfeiffer 			break;
8336163f333SKarsten Heimrich 
834e2069723SAxel Dörfler 		case kMsgStretchToWindow:
835e2069723SAxel Dörfler 			fImageView->SetStretchToBounds(
836e2069723SAxel Dörfler 				_ToggleMenuItem(kMsgStretchToWindow));
8377eca0987SMichael Pfeiffer 			break;
8387eca0987SMichael Pfeiffer 
8397eca0987SMichael Pfeiffer 		case MSG_FILE_PREV:
840b9767a83SAxel Dörfler 			if (_ClosePrompt() && fNavigator.PreviousFile())
841a569816bSAxel Dörfler 				_LoadImage(false);
8427eca0987SMichael Pfeiffer 			break;
8437eca0987SMichael Pfeiffer 
8447eca0987SMichael Pfeiffer 		case MSG_FILE_NEXT:
8454aa63633SAxel Dörfler 		case kMsgNextSlide:
846b9767a83SAxel Dörfler 			if (_ClosePrompt() && fNavigator.NextFile())
847b9767a83SAxel Dörfler 				_LoadImage();
84813afa642SPhil Greenway 			break;
84913afa642SPhil Greenway 
850328932acSAxel Dörfler 		case kMsgDeleteCurrentFile:
851b9767a83SAxel Dörfler 		{
852b9767a83SAxel Dörfler 			if (fNavigator.MoveFileToTrash())
853b9767a83SAxel Dörfler 				_LoadImage();
854b9767a83SAxel Dörfler 			else
855328932acSAxel Dörfler 				PostMessage(B_QUIT_REQUESTED);
856328932acSAxel Dörfler 			break;
857b9767a83SAxel Dörfler 		}
858328932acSAxel Dörfler 
859bf461dbeSMatthew Wilber 		case MSG_ROTATE_90:
860d3046f7dSMichael Pfeiffer 			fImageView->Rotate(90);
861ad13f387SMichael Pfeiffer 			break;
8626163f333SKarsten Heimrich 
863bf461dbeSMatthew Wilber 		case MSG_ROTATE_270:
864d3046f7dSMichael Pfeiffer 			fImageView->Rotate(270);
865ad13f387SMichael Pfeiffer 			break;
8666163f333SKarsten Heimrich 
86769eee339SRyan Leavengood 		case MSG_FLIP_LEFT_TO_RIGHT:
86861ddc257SRyan Leavengood 			fImageView->Flip(true);
869ad13f387SMichael Pfeiffer 			break;
8706163f333SKarsten Heimrich 
87169eee339SRyan Leavengood 		case MSG_FLIP_TOP_TO_BOTTOM:
87261ddc257SRyan Leavengood 			fImageView->Flip(false);
873ad13f387SMichael Pfeiffer 			break;
8746163f333SKarsten Heimrich 
8751076d97bSAxel Dörfler 		case MSG_SLIDE_SHOW:
8761076d97bSAxel Dörfler 		{
87794fd9498SStephan Aßmus 			bool fullScreen = false;
87894fd9498SStephan Aßmus 			message->FindBool("full screen", &fullScreen);
879a877c0e7SStephan Aßmus 
8806163f333SKarsten Heimrich 			BMenuItem* item = fBar->FindItem(message->what);
8814aa63633SAxel Dörfler 			if (item == NULL)
882ee7b4f39SMatthew Wilber 				break;
8834aa63633SAxel Dörfler 
884ee7b4f39SMatthew Wilber 			if (item->IsMarked()) {
885ee7b4f39SMatthew Wilber 				item->SetMarked(false);
8864aa63633SAxel Dörfler 				_StopSlideShow();
88794a4c1c4SAugustin Cavalier 				fToolBar->SetActionPressed(MSG_SLIDE_SHOW, false);
888fd952aefSRyan Leavengood 			} else if (_ClosePrompt()) {
889ee7b4f39SMatthew Wilber 				item->SetMarked(true);
89094fd9498SStephan Aßmus 				if (!fFullScreen && fullScreen)
89194fd9498SStephan Aßmus 					_ToggleFullScreen();
8924aa63633SAxel Dörfler 				_StartSlideShow();
89394a4c1c4SAugustin Cavalier 				fToolBar->SetActionPressed(MSG_SLIDE_SHOW, true);
894ad13f387SMichael Pfeiffer 			}
8951076d97bSAxel Dörfler 			break;
8961076d97bSAxel Dörfler 		}
897ee7b4f39SMatthew Wilber 
8984aa63633SAxel Dörfler 		case kMsgStopSlideShow:
8994aa63633SAxel Dörfler 		{
9004aa63633SAxel Dörfler 			BMenuItem* item = fBar->FindItem(MSG_SLIDE_SHOW);
9014aa63633SAxel Dörfler 			if (item != NULL)
9024aa63633SAxel Dörfler 				item->SetMarked(false);
9034aa63633SAxel Dörfler 
9044aa63633SAxel Dörfler 			_StopSlideShow();
90594a4c1c4SAugustin Cavalier 			fToolBar->SetActionPressed(MSG_SLIDE_SHOW, false);
9064aa63633SAxel Dörfler 			break;
9074aa63633SAxel Dörfler 		}
9084aa63633SAxel Dörfler 
9091076d97bSAxel Dörfler 		case MSG_SLIDE_SHOW_DELAY:
9101076d97bSAxel Dörfler 		{
9114aa63633SAxel Dörfler 			bigtime_t delay;
9124aa63633SAxel Dörfler 			if (message->FindInt64("delay", &delay) == B_OK) {
9134aa63633SAxel Dörfler 				_SetSlideShowDelay(delay);
914da87390fSMichael Pfeiffer 				// in case message is sent from popup menu
9154aa63633SAxel Dörfler 				_MarkSlideShowDelay(delay);
916ad13f387SMichael Pfeiffer 			}
9171076d97bSAxel Dörfler 			break;
9181076d97bSAxel Dörfler 		}
919ad13f387SMichael Pfeiffer 
920ad13f387SMichael Pfeiffer 		case MSG_FULL_SCREEN:
921fd952aefSRyan Leavengood 			_ToggleFullScreen();
922ad13f387SMichael Pfeiffer 			break;
9236163f333SKarsten Heimrich 
924fc5ca95dSStephan Aßmus 		case MSG_EXIT_FULL_SCREEN:
925fc5ca95dSStephan Aßmus 			if (fFullScreen)
926fd952aefSRyan Leavengood 				_ToggleFullScreen();
927fc5ca95dSStephan Aßmus 			break;
9286163f333SKarsten Heimrich 
929cf0d8308SStephan Aßmus 		case MSG_SHOW_CAPTION:
930cf0d8308SStephan Aßmus 		{
931fd952aefSRyan Leavengood 			fShowCaption = _ToggleMenuItem(message->what);
932efa8b4f3SAxel Dörfler 			ShowImageSettings* settings = my_app->Settings();
933efa8b4f3SAxel Dörfler 
934d3046f7dSMichael Pfeiffer 			if (settings->Lock()) {
935d3046f7dSMichael Pfeiffer 				settings->SetBool("ShowCaption", fShowCaption);
936d3046f7dSMichael Pfeiffer 				settings->Unlock();
937d3046f7dSMichael Pfeiffer 			}
938efa8b4f3SAxel Dörfler 			if (fFullScreen)
939d3046f7dSMichael Pfeiffer 				fImageView->SetShowCaption(fShowCaption);
9406163f333SKarsten Heimrich 		}	break;
941ad13f387SMichael Pfeiffer 
942780d8a62SMichael Pfeiffer 		case MSG_PAGE_SETUP:
943fd952aefSRyan Leavengood 			_PageSetup();
944780d8a62SMichael Pfeiffer 			break;
9456163f333SKarsten Heimrich 
946780d8a62SMichael Pfeiffer 		case MSG_PREPARE_PRINT:
947fd952aefSRyan Leavengood 			_PrepareForPrint();
948780d8a62SMichael Pfeiffer 			break;
9496163f333SKarsten Heimrich 
950780d8a62SMichael Pfeiffer 		case MSG_PRINT:
951fd952aefSRyan Leavengood 			_Print(message);
952780d8a62SMichael Pfeiffer 			break;
953780d8a62SMichael Pfeiffer 
954780d8a62SMichael Pfeiffer 		case MSG_ZOOM_IN:
955d3046f7dSMichael Pfeiffer 			fImageView->ZoomIn();
956780d8a62SMichael Pfeiffer 			break;
9576163f333SKarsten Heimrich 
958780d8a62SMichael Pfeiffer 		case MSG_ZOOM_OUT:
959d3046f7dSMichael Pfeiffer 			fImageView->ZoomOut();
960780d8a62SMichael Pfeiffer 			break;
9616163f333SKarsten Heimrich 
962cae52eadSJanus 		case MSG_UPDATE_STATUS_ZOOM:
963cae52eadSJanus 			fStatusView->SetZoom(fImageView->Zoom());
964cae52eadSJanus 			break;
965cae52eadSJanus 
966e2069723SAxel Dörfler 		case kMsgOriginalSize:
9678073fcbbSAdrien Destugues 			if (message->FindInt32("behavior") == BButton::B_TOGGLE_BEHAVIOR) {
9688073fcbbSAdrien Destugues 				bool force = (message->FindInt32("be:value") == B_CONTROL_ON);
969554e2073SAdrien Destugues 				fImageView->ForceOriginalSize(force);
970554e2073SAdrien Destugues 				if (!force)
971554e2073SAdrien Destugues 					break;
972554e2073SAdrien Destugues 			}
9734fd570d3SAxel Dörfler 			fImageView->SetZoom(1.0);
974780d8a62SMichael Pfeiffer 			break;
9756163f333SKarsten Heimrich 
97681b9c776SMichael Pfeiffer 		case MSG_SCALE_BILINEAR:
977fd952aefSRyan Leavengood 			fImageView->SetScaleBilinear(_ToggleMenuItem(message->what));
97881b9c776SMichael Pfeiffer 			break;
979780d8a62SMichael Pfeiffer 
980cd6b5cdeSAxel Dörfler 		case MSG_DESKTOP_BACKGROUND:
981cd6b5cdeSAxel Dörfler 		{
9829617074cSRyan Leavengood 			BMessage backgroundsMessage(B_REFS_RECEIVED);
9839617074cSRyan Leavengood 			backgroundsMessage.AddRef("refs", fImageView->Image());
9840a74004cSRyan Leavengood 			// This is used in the Backgrounds code for scaled placement
9859617074cSRyan Leavengood 			backgroundsMessage.AddInt32("placement", 'scpl');
986537a273cSHumdinger 			be_roster->Launch("application/x-vnd.haiku-backgrounds",
987537a273cSHumdinger 				&backgroundsMessage);
988cd6b5cdeSAxel Dörfler 			break;
989cd6b5cdeSAxel Dörfler 		}
990a60adbf9SAxel Dörfler 
9915b76e505SStephan Aßmus 		case MSG_SET_RATING:
9925b76e505SStephan Aßmus 		{
9935b76e505SStephan Aßmus 			int32 rating;
9945b76e505SStephan Aßmus 			if (message->FindInt32("rating", &rating) != B_OK)
9955b76e505SStephan Aßmus 				break;
9965b76e505SStephan Aßmus 			BFile file(&fNavigator.CurrentRef(), B_WRITE_ONLY);
9975b76e505SStephan Aßmus 			if (file.InitCheck() != B_OK)
9985b76e505SStephan Aßmus 				break;
9995b76e505SStephan Aßmus 			file.WriteAttr("Media:Rating", B_INT32_TYPE, 0, &rating,
10005b76e505SStephan Aßmus 				sizeof(rating));
10015b76e505SStephan Aßmus 			_UpdateRatingMenu();
10025b76e505SStephan Aßmus 			break;
10035b76e505SStephan Aßmus 		}
10045b76e505SStephan Aßmus 
1005cf0d8308SStephan Aßmus 		case kMsgToggleToolBar:
1006cf0d8308SStephan Aßmus 		{
1007cf0d8308SStephan Aßmus 			fShowToolBar = _ToggleMenuItem(message->what);
100894fd9498SStephan Aßmus 			_SetToolBarVisible(fShowToolBar, true);
1009cf0d8308SStephan Aßmus 
1010cf0d8308SStephan Aßmus 			ShowImageSettings* settings = my_app->Settings();
1011cf0d8308SStephan Aßmus 
1012cf0d8308SStephan Aßmus 			if (settings->Lock()) {
1013cf0d8308SStephan Aßmus 				settings->SetBool("ShowToolBar", fShowToolBar);
1014cf0d8308SStephan Aßmus 				settings->Unlock();
1015cf0d8308SStephan Aßmus 			}
1016cf0d8308SStephan Aßmus 			break;
1017cf0d8308SStephan Aßmus 		}
101894fd9498SStephan Aßmus 		case kShowToolBarIfEnabled:
101994fd9498SStephan Aßmus 		{
102094fd9498SStephan Aßmus 			bool show;
102194fd9498SStephan Aßmus 			if (message->FindBool("show", &show) != B_OK)
102294fd9498SStephan Aßmus 				break;
102394fd9498SStephan Aßmus 			_SetToolBarVisible(fShowToolBar && show, true);
102494fd9498SStephan Aßmus 			break;
102594fd9498SStephan Aßmus 		}
102694fd9498SStephan Aßmus 		case kMsgSlideToolBar:
102794fd9498SStephan Aßmus 		{
102894fd9498SStephan Aßmus 			float offset;
102994fd9498SStephan Aßmus 			if (message->FindFloat("offset", &offset) == B_OK) {
103094a4c1c4SAugustin Cavalier 				fToolBar->MoveBy(0, offset);
103194fd9498SStephan Aßmus 				fScrollView->ResizeBy(0, -offset);
103294fd9498SStephan Aßmus 				fScrollView->MoveBy(0, offset);
103394fd9498SStephan Aßmus 				UpdateIfNeeded();
103494fd9498SStephan Aßmus 				snooze(15000);
103594fd9498SStephan Aßmus 			}
103694fd9498SStephan Aßmus 			break;
103794fd9498SStephan Aßmus 		}
103894fd9498SStephan Aßmus 		case kMsgFinishSlidingToolBar:
103994fd9498SStephan Aßmus 		{
104094fd9498SStephan Aßmus 			float offset;
104194fd9498SStephan Aßmus 			bool show;
104294fd9498SStephan Aßmus 			if (message->FindFloat("offset", &offset) == B_OK
104394fd9498SStephan Aßmus 				&& message->FindBool("show", &show) == B_OK) {
104494fd9498SStephan Aßmus 				// Compensate rounding errors with the final placement
104594a4c1c4SAugustin Cavalier 				fToolBar->MoveTo(fToolBar->Frame().left, offset);
104695667008SJanus 				if (!show)
104794a4c1c4SAugustin Cavalier 					fToolBar->Hide();
104894a4c1c4SAugustin Cavalier 				BRect frame = fToolBar->Parent()->Bounds();
104994a4c1c4SAugustin Cavalier 				frame.top = fToolBar->Frame().bottom + 1;
10502804cb33SRyan Leavengood 				fScrollView->MoveTo(fScrollView->Frame().left, frame.top);
105194fd9498SStephan Aßmus 				fScrollView->ResizeTo(fScrollView->Bounds().Width(),
1052cae52eadSJanus 					frame.Height() + 1);
105394fd9498SStephan Aßmus 			}
105494fd9498SStephan Aßmus 			break;
105594fd9498SStephan Aßmus 		}
1056cf0d8308SStephan Aßmus 
105713afa642SPhil Greenway 		default:
1058efa8b4f3SAxel Dörfler 			BWindow::MessageReceived(message);
105913afa642SPhil Greenway 			break;
106013afa642SPhil Greenway 	}
106113afa642SPhil Greenway }
1062fc0a275bSMatthew Wilber 
1063efa8b4f3SAxel Dörfler 
1064fc0a275bSMatthew Wilber void
1065cd6b5cdeSAxel Dörfler ShowImageWindow::_UpdateStatusText(const BMessage* message)
1066cd6b5cdeSAxel Dörfler {
1067baa27ccbSJanus 	BString frameText;
1068cd6b5cdeSAxel Dörfler 	if (fImageView->Bitmap() != NULL) {
1069cd6b5cdeSAxel Dörfler 		BRect bounds = fImageView->Bitmap()->Bounds();
1070baa27ccbSJanus 		frameText << bounds.IntegerWidth() + 1
1071cae52eadSJanus 			<< "x" << bounds.IntegerHeight() + 1;
1072cd6b5cdeSAxel Dörfler 	}
1073baa27ccbSJanus 	BString pages;
1074baa27ccbSJanus 	if (fNavigator.PageCount() > 1)
1075baa27ccbSJanus 		pages << fNavigator.CurrentPage() << "/" << fNavigator.PageCount();
1076baa27ccbSJanus 	fStatusView->Update(fNavigator.CurrentRef(), frameText, pages, fImageType,
1077cae52eadSJanus 		fImageView->Zoom());
1078cd6b5cdeSAxel Dörfler }
1079cd6b5cdeSAxel Dörfler 
1080cd6b5cdeSAxel Dörfler 
1081cd6b5cdeSAxel Dörfler void
1082cd6b5cdeSAxel Dörfler ShowImageWindow::_LoadError(const entry_ref& ref)
1083cd6b5cdeSAxel Dörfler {
1084cd6b5cdeSAxel Dörfler 	// TODO: give a better error message!
1085560ff447SJonas Sundström 	BAlert* alert = new BAlert(B_TRANSLATE_SYSTEM_NAME("ShowImage"),
1086546208a5SOliver Tappe 		B_TRANSLATE_CONTEXT("Could not load image! Either the "
1087ddcb5a2cSAxel Dörfler 			"file or an image translator for it does not exist.",
1088ddcb5a2cSAxel Dörfler 			"LoadAlerts"),
1089546208a5SOliver Tappe 		B_TRANSLATE_CONTEXT("OK", "Alerts"), NULL, NULL,
10905df9097aSJohn Scipione 		B_WIDTH_AS_USUAL, B_STOP_ALERT);
1091aed35104SHumdinger 	alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
1092cd6b5cdeSAxel Dörfler 	alert->Go();
1093cd6b5cdeSAxel Dörfler }
1094cd6b5cdeSAxel Dörfler 
1095cd6b5cdeSAxel Dörfler 
1096cd6b5cdeSAxel Dörfler void
1097fd952aefSRyan Leavengood ShowImageWindow::_SaveAs(BMessage* message)
1098fc0a275bSMatthew Wilber {
1099cdb89ebbSMatthew Wilber 	// Read the translator and output type the user chose
1100cdb89ebbSMatthew Wilber 	translator_id outTranslator;
1101cdb89ebbSMatthew Wilber 	uint32 outType;
11026163f333SKarsten Heimrich 	if (message->FindInt32(kTranslatorField,
1103efa8b4f3SAxel Dörfler 			reinterpret_cast<int32 *>(&outTranslator)) != B_OK
11046163f333SKarsten Heimrich 		|| message->FindInt32(kTypeField,
1105cdb89ebbSMatthew Wilber 			reinterpret_cast<int32 *>(&outType)) != B_OK)
1106fc0a275bSMatthew Wilber 		return;
1107fc0a275bSMatthew Wilber 
1108cdb89ebbSMatthew Wilber 	// Add the chosen translator and output type to the
1109cdb89ebbSMatthew Wilber 	// message that the save panel will send back
1110c1a10c14SKarsten Heimrich 	BMessage panelMsg(MSG_SAVE_PANEL);
1111c1a10c14SKarsten Heimrich 	panelMsg.AddInt32(kTranslatorField, outTranslator);
1112c1a10c14SKarsten Heimrich 	panelMsg.AddInt32(kTypeField, outType);
1113cdb89ebbSMatthew Wilber 
1114cdb89ebbSMatthew Wilber 	// Create save panel and show it
11156163f333SKarsten Heimrich 	BMessenger target(this);
1116efa8b4f3SAxel Dörfler 	fSavePanel = new (std::nothrow) BFilePanel(B_SAVE_PANEL,
1117c1a10c14SKarsten Heimrich 		&target, NULL, 0, false, &panelMsg);
1118d3046f7dSMichael Pfeiffer 	if (!fSavePanel)
1119fc0a275bSMatthew Wilber 		return;
1120a60adbf9SAxel Dörfler 
11213000afd7SJanus 	// Retrieve save directory from settings;
11223000afd7SJanus 	ShowImageSettings* settings = my_app->Settings();
11233000afd7SJanus 	if (settings->Lock()) {
11243000afd7SJanus 		fSavePanel->SetPanelDirectory(
11253000afd7SJanus 			settings->GetString("SaveDirectory", NULL));
11263000afd7SJanus 		settings->Unlock();
11273000afd7SJanus 	}
11283000afd7SJanus 
1129d3046f7dSMichael Pfeiffer 	fSavePanel->Window()->SetWorkspaces(B_CURRENT_WORKSPACE);
1130d3046f7dSMichael Pfeiffer 	fSavePanel->Show();
1131fc0a275bSMatthew Wilber }
1132fc0a275bSMatthew Wilber 
1133efa8b4f3SAxel Dörfler 
1134fc0a275bSMatthew Wilber void
1135fd952aefSRyan Leavengood ShowImageWindow::_SaveToFile(BMessage* message)
1136fc0a275bSMatthew Wilber {
1137cdb89ebbSMatthew Wilber 	// Read in where the file should be saved
1138efa8b4f3SAxel Dörfler 	entry_ref dirRef;
1139efa8b4f3SAxel Dörfler 	if (message->FindRef("directory", &dirRef) != B_OK)
1140fc0a275bSMatthew Wilber 		return;
1141efa8b4f3SAxel Dörfler 
1142fc0a275bSMatthew Wilber 	const char* filename;
1143efa8b4f3SAxel Dörfler 	if (message->FindString("name", &filename) != B_OK)
1144fc0a275bSMatthew Wilber 		return;
1145fc0a275bSMatthew Wilber 
1146cdb89ebbSMatthew Wilber 	// Read in the translator and type to be used
1147cdb89ebbSMatthew Wilber 	// to save the output image
1148cdb89ebbSMatthew Wilber 	translator_id outTranslator;
1149cdb89ebbSMatthew Wilber 	uint32 outType;
11506163f333SKarsten Heimrich 	if (message->FindInt32(kTranslatorField,
1151efa8b4f3SAxel Dörfler 			reinterpret_cast<int32 *>(&outTranslator)) != B_OK
11526163f333SKarsten Heimrich 		|| message->FindInt32(kTypeField,
1153cdb89ebbSMatthew Wilber 			reinterpret_cast<int32 *>(&outType)) != B_OK)
1154cdb89ebbSMatthew Wilber 		return;
1155cdb89ebbSMatthew Wilber 
1156a7e78e3bSMatthew Wilber 	// Find the translator_format information needed to
1157a7e78e3bSMatthew Wilber 	// write a MIME attribute for the image file
1158a7e78e3bSMatthew Wilber 	BTranslatorRoster* roster = BTranslatorRoster::Default();
1159efa8b4f3SAxel Dörfler 	const translation_format* outFormat = NULL;
1160efa8b4f3SAxel Dörfler 	int32 outCount = 0;
1161efa8b4f3SAxel Dörfler 	if (roster->GetOutputFormats(outTranslator, &outFormat, &outCount) != B_OK
1162efa8b4f3SAxel Dörfler 		|| outCount < 1)
1163a7e78e3bSMatthew Wilber 		return;
1164efa8b4f3SAxel Dörfler 
1165a7e78e3bSMatthew Wilber 	int32 i;
1166efa8b4f3SAxel Dörfler 	for (i = 0; i < outCount; i++) {
1167537a273cSHumdinger 		if (outFormat[i].group == B_TRANSLATOR_BITMAP && outFormat[i].type
1168537a273cSHumdinger 				== outType)
1169a7e78e3bSMatthew Wilber 			break;
1170a7e78e3bSMatthew Wilber 	}
1171efa8b4f3SAxel Dörfler 	if (i == outCount)
1172fc0a275bSMatthew Wilber 		return;
1173fc0a275bSMatthew Wilber 
1174a7e78e3bSMatthew Wilber 	// Write out the image file
1175efa8b4f3SAxel Dörfler 	BDirectory dir(&dirRef);
1176efa8b4f3SAxel Dörfler 	fImageView->SaveToFile(&dir, filename, NULL, &outFormat[i]);
11773000afd7SJanus 
11783000afd7SJanus 	// Store Save directory in settings;
11793000afd7SJanus 	ShowImageSettings* settings = my_app->Settings();
11803000afd7SJanus 	if (settings->Lock()) {
11813000afd7SJanus 		BPath path(&dirRef);
11823000afd7SJanus 		settings->SetString("SaveDirectory", path.Path());
11833000afd7SJanus 		settings->Unlock();
11843000afd7SJanus 	}
1185fc0a275bSMatthew Wilber }
1186fc0a275bSMatthew Wilber 
1187efa8b4f3SAxel Dörfler 
1188546208a5SOliver Tappe #undef B_TRANSLATION_CONTEXT
1189546208a5SOliver Tappe #define B_TRANSLATION_CONTEXT "ClosePrompt"
11901ed4535fSStephan Aßmus 
1191b9767a83SAxel Dörfler 
1192cdb89ebbSMatthew Wilber bool
1193fd952aefSRyan Leavengood ShowImageWindow::_ClosePrompt()
1194ee7b4f39SMatthew Wilber {
1195ee7b4f39SMatthew Wilber 	if (!fModified)
1196ee7b4f39SMatthew Wilber 		return true;
1197efa8b4f3SAxel Dörfler 
1198cd6b5cdeSAxel Dörfler 	int32 count = fNavigator.PageCount();
1199cd6b5cdeSAxel Dörfler 	int32 page = fNavigator.CurrentPage();
1200cd6b5cdeSAxel Dörfler 	BString prompt;
1201efa8b4f3SAxel Dörfler 
12021ed4535fSStephan Aßmus 	if (count > 1) {
12031ed4535fSStephan Aßmus 		bs_printf(&prompt,
1204905c8c8cSMatt Madia 			B_TRANSLATE("The document '%s' (page %d) has been changed. Do you "
1205905c8c8cSMatt Madia 				"want to close the document?"),
1206cd6b5cdeSAxel Dörfler 			fImageView->Image()->name, page);
12071ed4535fSStephan Aßmus 	} else {
12081ed4535fSStephan Aßmus 		bs_printf(&prompt,
1209905c8c8cSMatt Madia 			B_TRANSLATE("The document '%s' has been changed. Do you want to "
1210905c8c8cSMatt Madia 				"close the document?"),
1211cd6b5cdeSAxel Dörfler 			fImageView->Image()->name);
12121ed4535fSStephan Aßmus 	}
12131ed4535fSStephan Aßmus 
1214cd6b5cdeSAxel Dörfler 	BAlert* alert = new BAlert(B_TRANSLATE("Close document"), prompt.String(),
1215905c8c8cSMatt Madia 		B_TRANSLATE("Cancel"), B_TRANSLATE("Close"));
1216aed35104SHumdinger 	alert->SetShortcut(0, B_ESCAPE);
1217aed35104SHumdinger 
1218cd6b5cdeSAxel Dörfler 	if (alert->Go() == 0) {
1219ee7b4f39SMatthew Wilber 		// Cancel
1220ee7b4f39SMatthew Wilber 		return false;
1221cd6b5cdeSAxel Dörfler 	}
1222cd6b5cdeSAxel Dörfler 
1223ee7b4f39SMatthew Wilber 	// Close
1224187f0b8aSMatthew Wilber 	fModified = false;
1225ee7b4f39SMatthew Wilber 	return true;
1226ee7b4f39SMatthew Wilber }
1227ee7b4f39SMatthew Wilber 
1228cdb89ebbSMatthew Wilber 
1229b9767a83SAxel Dörfler status_t
1230a569816bSAxel Dörfler ShowImageWindow::_LoadImage(bool forward)
1231b9767a83SAxel Dörfler {
1232b9767a83SAxel Dörfler 	BMessenger us(this);
1233be63ec85SJanus 	status_t status = my_app->DefaultCache().RetrieveImage(
1234a569816bSAxel Dörfler 		fNavigator.CurrentRef(), fNavigator.CurrentPage(), &us);
1235a569816bSAxel Dörfler 	if (status != B_OK)
1236a569816bSAxel Dörfler 		return status;
1237a569816bSAxel Dörfler 
1238e2069723SAxel Dörfler 	fProgressWindow->Start(this);
1239e2069723SAxel Dörfler 
1240a569816bSAxel Dörfler 	// Preload previous/next images - two in the navigation direction, one
1241a569816bSAxel Dörfler 	// in the opposite direction.
1242a569816bSAxel Dörfler 
1243a569816bSAxel Dörfler 	entry_ref nextRef = fNavigator.CurrentRef();
1244a569816bSAxel Dörfler 	if (_PreloadImage(forward, nextRef))
1245a569816bSAxel Dörfler 		_PreloadImage(forward, nextRef);
1246a569816bSAxel Dörfler 
1247a569816bSAxel Dörfler 	entry_ref previousRef = fNavigator.CurrentRef();
1248a569816bSAxel Dörfler 	_PreloadImage(!forward, previousRef);
1249a569816bSAxel Dörfler 
1250a569816bSAxel Dörfler 	return B_OK;
1251a569816bSAxel Dörfler }
1252a569816bSAxel Dörfler 
1253a569816bSAxel Dörfler 
1254a569816bSAxel Dörfler bool
1255a569816bSAxel Dörfler ShowImageWindow::_PreloadImage(bool forward, entry_ref& ref)
1256a569816bSAxel Dörfler {
1257a569816bSAxel Dörfler 	entry_ref currentRef = ref;
1258a569816bSAxel Dörfler 	if ((forward && !fNavigator.GetNextFile(currentRef, ref))
1259a569816bSAxel Dörfler 		|| (!forward && !fNavigator.GetPreviousFile(currentRef, ref)))
1260a569816bSAxel Dörfler 		return false;
1261a569816bSAxel Dörfler 
1262be63ec85SJanus 	return my_app->DefaultCache().RetrieveImage(ref) == B_OK;
1263b9767a83SAxel Dörfler }
1264b9767a83SAxel Dörfler 
1265b9767a83SAxel Dörfler 
1266ad13f387SMichael Pfeiffer void
1267fd952aefSRyan Leavengood ShowImageWindow::_ToggleFullScreen()
1268ad13f387SMichael Pfeiffer {
1269ad13f387SMichael Pfeiffer 	BRect frame;
1270ad13f387SMichael Pfeiffer 	fFullScreen = !fFullScreen;
1271ad13f387SMichael Pfeiffer 	if (fFullScreen) {
1272ad13f387SMichael Pfeiffer 		BScreen screen;
1273ad13f387SMichael Pfeiffer 		fWindowFrame = Frame();
1274ad13f387SMichael Pfeiffer 		frame = screen.Frame();
1275d3046f7dSMichael Pfeiffer 		frame.top -= fBar->Bounds().Height() + 1;
127667eb2a04SHumdinger 		frame.right += B_V_SCROLL_BAR_WIDTH;
1277ad13f387SMichael Pfeiffer 		frame.bottom += B_H_SCROLL_BAR_HEIGHT;
1278ad13f387SMichael Pfeiffer 
1279ad13f387SMichael Pfeiffer 		SetFlags(Flags() | B_NOT_RESIZABLE | B_NOT_MOVABLE);
1280c0b16687SAxel Dörfler 
1281c0b16687SAxel Dörfler 		Activate();
1282c0b16687SAxel Dörfler 			// make the window frontmost
1283ad13f387SMichael Pfeiffer 	} else {
1284ad13f387SMichael Pfeiffer 		frame = fWindowFrame;
1285ad13f387SMichael Pfeiffer 
1286ad13f387SMichael Pfeiffer 		SetFlags(Flags() & ~(B_NOT_RESIZABLE | B_NOT_MOVABLE));
1287ad13f387SMichael Pfeiffer 	}
1288efa8b4f3SAxel Dörfler 
128994a4c1c4SAugustin Cavalier 	fToolBar->SetActionVisible(MSG_FULL_SCREEN, fFullScreen);
1290cf0d8308SStephan Aßmus 	_SetToolBarVisible(!fFullScreen && fShowToolBar);
129160c23976SJanus 	_SetToolBarBorder(!fFullScreen);
1292cf0d8308SStephan Aßmus 
1293ad13f387SMichael Pfeiffer 	MoveTo(frame.left, frame.top);
1294ad13f387SMichael Pfeiffer 	ResizeTo(frame.Width(), frame.Height());
1295e2069723SAxel Dörfler 
1296e2069723SAxel Dörfler 	fImageView->SetHideIdlingCursor(fFullScreen);
1297e2069723SAxel Dörfler 	fImageView->SetShowCaption(fFullScreen && fShowCaption);
1298eaa910c5SAxel Dörfler 
129948ae3e38SAxel Dörfler 	Layout(false);
130048ae3e38SAxel Dörfler 		// We need to manually relayout here, as the views are layouted
130148ae3e38SAxel Dörfler 		// asynchronously, and FitToBounds() would still have the wrong size
1302e2069723SAxel Dörfler 	fImageView->FitToBounds();
1303ad13f387SMichael Pfeiffer }
1304ad13f387SMichael Pfeiffer 
1305efa8b4f3SAxel Dörfler 
1306d3046f7dSMichael Pfeiffer void
13072281340dSAxel Dörfler ShowImageWindow::_ApplySettings()
1308d3046f7dSMichael Pfeiffer {
1309efa8b4f3SAxel Dörfler 	ShowImageSettings* settings = my_app->Settings();
1310efa8b4f3SAxel Dörfler 
1311d3046f7dSMichael Pfeiffer 	if (settings->Lock()) {
1312d3046f7dSMichael Pfeiffer 		fShowCaption = settings->GetBool("ShowCaption", fShowCaption);
1313d3046f7dSMichael Pfeiffer 		fPrintOptions.SetBounds(BRect(0, 0, 1023, 767));
1314d3046f7dSMichael Pfeiffer 
13154aa63633SAxel Dörfler 		fSlideShowDelay = settings->GetTime("SlideShowDelay", fSlideShowDelay);
1316d3046f7dSMichael Pfeiffer 
13174aa63633SAxel Dörfler 		fPrintOptions.SetOption((enum PrintOptions::Option)settings->GetInt32(
13184aa63633SAxel Dörfler 			"PO:Option", fPrintOptions.Option()));
13194aa63633SAxel Dörfler 		fPrintOptions.SetZoomFactor(
13204aa63633SAxel Dörfler 			settings->GetFloat("PO:ZoomFactor", fPrintOptions.ZoomFactor()));
13214aa63633SAxel Dörfler 		fPrintOptions.SetDPI(settings->GetFloat("PO:DPI", fPrintOptions.DPI()));
13224aa63633SAxel Dörfler 		fPrintOptions.SetWidth(
13234aa63633SAxel Dörfler 			settings->GetFloat("PO:Width", fPrintOptions.Width()));
13244aa63633SAxel Dörfler 		fPrintOptions.SetHeight(
13254aa63633SAxel Dörfler 			settings->GetFloat("PO:Height", fPrintOptions.Height()));
1326d3046f7dSMichael Pfeiffer 
1327cf0d8308SStephan Aßmus 		fShowToolBar = settings->GetBool("ShowToolBar", fShowToolBar);
1328cf0d8308SStephan Aßmus 
1329d3046f7dSMichael Pfeiffer 		settings->Unlock();
1330d3046f7dSMichael Pfeiffer 	}
1331d3046f7dSMichael Pfeiffer }
1332d3046f7dSMichael Pfeiffer 
1333efa8b4f3SAxel Dörfler 
1334d3046f7dSMichael Pfeiffer void
1335fd952aefSRyan Leavengood ShowImageWindow::_SavePrintOptions()
1336d3046f7dSMichael Pfeiffer {
1337efa8b4f3SAxel Dörfler 	ShowImageSettings* settings = my_app->Settings();
1338efa8b4f3SAxel Dörfler 
1339d3046f7dSMichael Pfeiffer 	if (settings->Lock()) {
1340d3046f7dSMichael Pfeiffer 		settings->SetInt32("PO:Option", fPrintOptions.Option());
1341d3046f7dSMichael Pfeiffer 		settings->SetFloat("PO:ZoomFactor", fPrintOptions.ZoomFactor());
1342d3046f7dSMichael Pfeiffer 		settings->SetFloat("PO:DPI", fPrintOptions.DPI());
1343d3046f7dSMichael Pfeiffer 		settings->SetFloat("PO:Width", fPrintOptions.Width());
1344d3046f7dSMichael Pfeiffer 		settings->SetFloat("PO:Height", fPrintOptions.Height());
1345d3046f7dSMichael Pfeiffer 		settings->Unlock();
1346d3046f7dSMichael Pfeiffer 	}
1347d3046f7dSMichael Pfeiffer }
1348d3046f7dSMichael Pfeiffer 
1349efa8b4f3SAxel Dörfler 
1350cdb89ebbSMatthew Wilber bool
1351fd952aefSRyan Leavengood ShowImageWindow::_PageSetup()
1352780d8a62SMichael Pfeiffer {
1353cd6b5cdeSAxel Dörfler 	BPrintJob printJob(fImageView->Image()->name);
1354efa8b4f3SAxel Dörfler 	if (fPrintSettings != NULL)
1355780d8a62SMichael Pfeiffer 		printJob.SetSettings(new BMessage(*fPrintSettings));
1356efa8b4f3SAxel Dörfler 
13576163f333SKarsten Heimrich 	status_t status = printJob.ConfigPage();
13586163f333SKarsten Heimrich 	if (status == B_OK) {
1359780d8a62SMichael Pfeiffer 		delete fPrintSettings;
1360780d8a62SMichael Pfeiffer 		fPrintSettings = printJob.Settings();
1361780d8a62SMichael Pfeiffer 	}
1362efa8b4f3SAxel Dörfler 
13636163f333SKarsten Heimrich 	return status == B_OK;
1364780d8a62SMichael Pfeiffer }
1365780d8a62SMichael Pfeiffer 
1366efa8b4f3SAxel Dörfler 
1367780d8a62SMichael Pfeiffer void
1368fd952aefSRyan Leavengood ShowImageWindow::_PrepareForPrint()
1369780d8a62SMichael Pfeiffer {
13706163f333SKarsten Heimrich 	if (fPrintSettings == NULL) {
1371cd6b5cdeSAxel Dörfler 		BPrintJob printJob(fImageView->Image()->name);
13726163f333SKarsten Heimrich 		if (printJob.ConfigJob() == B_OK)
13736163f333SKarsten Heimrich 			fPrintSettings = printJob.Settings();
13746163f333SKarsten Heimrich 	}
1375780d8a62SMichael Pfeiffer 
1376cd6b5cdeSAxel Dörfler 	fPrintOptions.SetBounds(fImageView->Bitmap()->Bounds());
1377cd6b5cdeSAxel Dörfler 	fPrintOptions.SetWidth(fImageView->Bitmap()->Bounds().Width() + 1);
1378780d8a62SMichael Pfeiffer 
1379efa8b4f3SAxel Dörfler 	new PrintOptionsWindow(BPoint(Frame().left + 30, Frame().top + 50),
1380efa8b4f3SAxel Dörfler 		&fPrintOptions, this);
1381780d8a62SMichael Pfeiffer }
1382780d8a62SMichael Pfeiffer 
1383efa8b4f3SAxel Dörfler 
1384780d8a62SMichael Pfeiffer void
1385fd952aefSRyan Leavengood ShowImageWindow::_Print(BMessage* msg)
1386780d8a62SMichael Pfeiffer {
1387780d8a62SMichael Pfeiffer 	status_t st;
1388efa8b4f3SAxel Dörfler 	if (msg->FindInt32("status", &st) != B_OK || st != B_OK)
1389780d8a62SMichael Pfeiffer 		return;
1390780d8a62SMichael Pfeiffer 
1391fd952aefSRyan Leavengood 	_SavePrintOptions();
1392d3046f7dSMichael Pfeiffer 
1393cd6b5cdeSAxel Dörfler 	BPrintJob printJob(fImageView->Image()->name);
13946163f333SKarsten Heimrich 	if (fPrintSettings)
1395780d8a62SMichael Pfeiffer 		printJob.SetSettings(new BMessage(*fPrintSettings));
13966163f333SKarsten Heimrich 
1397780d8a62SMichael Pfeiffer 	if (printJob.ConfigJob() == B_OK) {
13986163f333SKarsten Heimrich 		delete fPrintSettings;
13996163f333SKarsten Heimrich 		fPrintSettings = printJob.Settings();
1400780d8a62SMichael Pfeiffer 
1401780d8a62SMichael Pfeiffer 		// first/lastPage is unused for now
14023177ae77SStefano Ceccherini 		int32 firstPage = printJob.FirstPage();
14033177ae77SStefano Ceccherini 		int32 lastPage = printJob.LastPage();
14046163f333SKarsten Heimrich 		BRect printableRect = printJob.PrintableRect();
14056163f333SKarsten Heimrich 
1406efa8b4f3SAxel Dörfler 		if (firstPage < 1)
1407780d8a62SMichael Pfeiffer 			firstPage = 1;
1408efa8b4f3SAxel Dörfler 		if (lastPage < firstPage)
1409780d8a62SMichael Pfeiffer 			lastPage = firstPage;
1410780d8a62SMichael Pfeiffer 
1411cd6b5cdeSAxel Dörfler 		BBitmap* bitmap = fImageView->Bitmap();
14123177ae77SStefano Ceccherini 		float imageWidth = bitmap->Bounds().Width() + 1.0;
14133177ae77SStefano Ceccherini 		float imageHeight = bitmap->Bounds().Height() + 1.0;
1414780d8a62SMichael Pfeiffer 
14156163f333SKarsten Heimrich 		float width;
1416780d8a62SMichael Pfeiffer 		switch (fPrintOptions.Option()) {
14176163f333SKarsten Heimrich 			case PrintOptions::kFitToPage: {
14186163f333SKarsten Heimrich 				float w1 = printableRect.Width() + 1;
1419cd6b5cdeSAxel Dörfler 				float w2 = imageWidth * (printableRect.Height() + 1)
1420cd6b5cdeSAxel Dörfler 					/ imageHeight;
1421efa8b4f3SAxel Dörfler 				if (w2 < w1)
1422780d8a62SMichael Pfeiffer 					width = w2;
1423efa8b4f3SAxel Dörfler 				else
1424780d8a62SMichael Pfeiffer 					width = w1;
14256163f333SKarsten Heimrich 			}	break;
1426780d8a62SMichael Pfeiffer 			case PrintOptions::kZoomFactor:
1427780d8a62SMichael Pfeiffer 				width = imageWidth * fPrintOptions.ZoomFactor();
1428780d8a62SMichael Pfeiffer 				break;
1429780d8a62SMichael Pfeiffer 			case PrintOptions::kDPI:
1430780d8a62SMichael Pfeiffer 				width = imageWidth * 72.0 / fPrintOptions.DPI();
1431780d8a62SMichael Pfeiffer 				break;
1432780d8a62SMichael Pfeiffer 			case PrintOptions::kWidth:
1433780d8a62SMichael Pfeiffer 			case PrintOptions::kHeight:
1434780d8a62SMichael Pfeiffer 				width = fPrintOptions.Width();
1435780d8a62SMichael Pfeiffer 				break;
1436efa8b4f3SAxel Dörfler 
1437780d8a62SMichael Pfeiffer 			default:
1438780d8a62SMichael Pfeiffer 				// keep compiler silent; should not reach here
1439780d8a62SMichael Pfeiffer 				width = imageWidth;
1440780d8a62SMichael Pfeiffer 		}
1441780d8a62SMichael Pfeiffer 
1442efa8b4f3SAxel Dörfler 		// TODO: eventually print large images on several pages
1443780d8a62SMichael Pfeiffer 		printJob.BeginJob();
1444d3046f7dSMichael Pfeiffer 		fImageView->SetScale(width / imageWidth);
14455eb50e46SMichael Pfeiffer 		// coordinates are relative to printable rectangle
14465eb50e46SMichael Pfeiffer 		BRect bounds(bitmap->Bounds());
14475eb50e46SMichael Pfeiffer 		printJob.DrawView(fImageView, bounds, BPoint(0, 0));
1448d3046f7dSMichael Pfeiffer 		fImageView->SetScale(1.0);
1449780d8a62SMichael Pfeiffer 		printJob.SpoolPage();
1450780d8a62SMichael Pfeiffer 		printJob.CommitJob();
1451780d8a62SMichael Pfeiffer 	}
1452780d8a62SMichael Pfeiffer }
1453780d8a62SMichael Pfeiffer 
145456b0c7b9SKarsten Heimrich 
14554aa63633SAxel Dörfler void
14564aa63633SAxel Dörfler ShowImageWindow::_SetSlideShowDelay(bigtime_t delay)
14574aa63633SAxel Dörfler {
14584aa63633SAxel Dörfler 	if (fSlideShowDelay == delay)
14594aa63633SAxel Dörfler 		return;
14604aa63633SAxel Dörfler 
14614aa63633SAxel Dörfler 	fSlideShowDelay = delay;
14624aa63633SAxel Dörfler 
14634aa63633SAxel Dörfler 	ShowImageSettings* settings = my_app->Settings();
14644aa63633SAxel Dörfler 	if (settings->Lock()) {
14654aa63633SAxel Dörfler 		settings->SetTime("SlideShowDelay", fSlideShowDelay);
14664aa63633SAxel Dörfler 		settings->Unlock();
14674aa63633SAxel Dörfler 	}
14684aa63633SAxel Dörfler 
14694aa63633SAxel Dörfler 	if (fSlideShowRunner != NULL)
14704aa63633SAxel Dörfler 		_StartSlideShow();
14714aa63633SAxel Dörfler }
14724aa63633SAxel Dörfler 
14734aa63633SAxel Dörfler 
14744aa63633SAxel Dörfler void
14754aa63633SAxel Dörfler ShowImageWindow::_StartSlideShow()
14764aa63633SAxel Dörfler {
14774aa63633SAxel Dörfler 	_StopSlideShow();
14784aa63633SAxel Dörfler 
14794aa63633SAxel Dörfler 	BMessage nextSlide(kMsgNextSlide);
14804aa63633SAxel Dörfler 	fSlideShowRunner = new BMessageRunner(this, &nextSlide, fSlideShowDelay);
14814aa63633SAxel Dörfler }
14824aa63633SAxel Dörfler 
14834aa63633SAxel Dörfler 
14844aa63633SAxel Dörfler void
14854aa63633SAxel Dörfler ShowImageWindow::_StopSlideShow()
14864aa63633SAxel Dörfler {
14874aa63633SAxel Dörfler 	if (fSlideShowRunner != NULL) {
14884aa63633SAxel Dörfler 		delete fSlideShowRunner;
14894aa63633SAxel Dörfler 		fSlideShowRunner = NULL;
14904aa63633SAxel Dörfler 	}
14914aa63633SAxel Dörfler }
14924aa63633SAxel Dörfler 
14934aa63633SAxel Dörfler 
14945b76e505SStephan Aßmus void
14955b76e505SStephan Aßmus ShowImageWindow::_UpdateRatingMenu()
14965b76e505SStephan Aßmus {
14975b76e505SStephan Aßmus 	BFile file(&fNavigator.CurrentRef(), B_READ_ONLY);
14985b76e505SStephan Aßmus 	if (file.InitCheck() != B_OK)
14995b76e505SStephan Aßmus 		return;
15005b76e505SStephan Aßmus 	int32 rating;
15015b76e505SStephan Aßmus 	ssize_t size = sizeof(rating);
15025b76e505SStephan Aßmus 	if (file.ReadAttr("Media:Rating", B_INT32_TYPE, 0, &rating, size) != size)
15035b76e505SStephan Aßmus 		rating = 0;
15045b76e505SStephan Aßmus 	// TODO: Finding the correct item could be more robust, like by looking
15055b76e505SStephan Aßmus 	// at the message of each item.
15065b76e505SStephan Aßmus 	for (int32 i = 1; i <= 10; i++) {
15075b76e505SStephan Aßmus 		BMenuItem* item = fRatingMenu->ItemAt(i - 1);
15085b76e505SStephan Aßmus 		if (item == NULL)
15095b76e505SStephan Aßmus 			break;
15105b76e505SStephan Aßmus 		item->SetMarked(i == rating);
15115b76e505SStephan Aßmus 	}
15125b76e505SStephan Aßmus }
15135b76e505SStephan Aßmus 
15145b76e505SStephan Aßmus 
1515cf0d8308SStephan Aßmus void
1516e62a6973SJanus ShowImageWindow::_SaveWidthAndHeight()
1517e62a6973SJanus {
1518e62a6973SJanus 	if (fNavigator.CurrentPage() != 1)
1519e62a6973SJanus 		return;
1520e62a6973SJanus 
1521e62a6973SJanus 	if (fImageView->Bitmap() == NULL)
1522e62a6973SJanus 		return;
1523e62a6973SJanus 
1524e62a6973SJanus 	BRect bounds = fImageView->Bitmap()->Bounds();
1525c1994be8SJanus 	int32 width = bounds.IntegerWidth() + 1;
1526c1994be8SJanus 	int32 height = bounds.IntegerHeight() + 1;
1527e62a6973SJanus 
15289c1f5f4dSJanus 	BNode node(&fNavigator.CurrentRef());
15299c1f5f4dSJanus 	if (node.InitCheck() != B_OK)
1530e62a6973SJanus 		return;
1531e62a6973SJanus 
15329c1f5f4dSJanus 	const char* kWidthAttrName = "Media:Width";
15339c1f5f4dSJanus 	const char* kHeightAttrName = "Media:Height";
15349c1f5f4dSJanus 
15359c1f5f4dSJanus 	int32 widthAttr;
1536b41cdcb3SJanus 	ssize_t attrSize = node.ReadAttr(kWidthAttrName, B_INT32_TYPE, 0,
1537b41cdcb3SJanus 		&widthAttr, sizeof(widthAttr));
15389c1f5f4dSJanus 	if (attrSize <= 0 || widthAttr != width)
15399c1f5f4dSJanus 		node.WriteAttr(kWidthAttrName, B_INT32_TYPE, 0, &width, sizeof(width));
15409c1f5f4dSJanus 
15419c1f5f4dSJanus 	int32 heightAttr;
1542b41cdcb3SJanus 	attrSize = node.ReadAttr(kHeightAttrName, B_INT32_TYPE, 0,
1543b41cdcb3SJanus 		&heightAttr, sizeof(heightAttr));
15449c1f5f4dSJanus 	if (attrSize <= 0 || heightAttr != height)
15459c1f5f4dSJanus 		node.WriteAttr(kHeightAttrName, B_INT32_TYPE, 0, &height, sizeof(height));
1546e62a6973SJanus }
1547e62a6973SJanus 
1548e62a6973SJanus 
1549e62a6973SJanus void
155094fd9498SStephan Aßmus ShowImageWindow::_SetToolBarVisible(bool visible, bool animate)
1551cf0d8308SStephan Aßmus {
155295667008SJanus 	if (visible == fToolBarVisible)
1553cf0d8308SStephan Aßmus 		return;
1554cf0d8308SStephan Aßmus 
155595667008SJanus 	fToolBarVisible = visible;
155694a4c1c4SAugustin Cavalier 	float diff = fToolBar->Bounds().Height() + 2;
155794fd9498SStephan Aßmus 	if (!visible)
1558cf0d8308SStephan Aßmus 		diff = -diff;
155994fd9498SStephan Aßmus 	else
156094a4c1c4SAugustin Cavalier 		fToolBar->Show();
1561cf0d8308SStephan Aßmus 
156294fd9498SStephan Aßmus 	if (animate) {
156394fd9498SStephan Aßmus 		// Slide the controls into view. We do this with messages in order
156494fd9498SStephan Aßmus 		// not to block the window thread.
156594fd9498SStephan Aßmus 		const float kAnimationOffsets[] = { 0.05, 0.2, 0.5, 0.2, 0.05 };
156694fd9498SStephan Aßmus 		const int32 steps = sizeof(kAnimationOffsets) / sizeof(float);
156794fd9498SStephan Aßmus 		for (int32 i = 0; i < steps; i++) {
156894fd9498SStephan Aßmus 			BMessage message(kMsgSlideToolBar);
156994fd9498SStephan Aßmus 			message.AddFloat("offset", floorf(diff * kAnimationOffsets[i]));
157094fd9498SStephan Aßmus 			PostMessage(&message, this);
157194fd9498SStephan Aßmus 		}
157294fd9498SStephan Aßmus 		BMessage finalMessage(kMsgFinishSlidingToolBar);
157395667008SJanus 		finalMessage.AddFloat("offset", visible ? 0 : diff);
157494fd9498SStephan Aßmus 		finalMessage.AddBool("show", visible);
157594fd9498SStephan Aßmus 		PostMessage(&finalMessage, this);
157694fd9498SStephan Aßmus 	} else {
1577cf0d8308SStephan Aßmus 		fScrollView->ResizeBy(0, -diff);
1578cf0d8308SStephan Aßmus 		fScrollView->MoveBy(0, diff);
157994a4c1c4SAugustin Cavalier 		fToolBar->MoveBy(0, diff);
158094fd9498SStephan Aßmus 		if (!visible)
158194a4c1c4SAugustin Cavalier 			fToolBar->Hide();
158294fd9498SStephan Aßmus 	}
1583cf0d8308SStephan Aßmus }
1584cf0d8308SStephan Aßmus 
1585cf0d8308SStephan Aßmus 
158660c23976SJanus void
158760c23976SJanus ShowImageWindow::_SetToolBarBorder(bool visible)
158860c23976SJanus {
158960c23976SJanus 	float inset = visible
159060c23976SJanus 		? ceilf(be_control_look->DefaultItemSpacing() / 2) : 0;
159160c23976SJanus 
159260c23976SJanus 	fToolBar->GroupLayout()->SetInsets(inset, 0, inset, 0);
159360c23976SJanus }
159460c23976SJanus 
159560c23976SJanus 
1596780d8a62SMichael Pfeiffer bool
1597cdb89ebbSMatthew Wilber ShowImageWindow::QuitRequested()
1598cdb89ebbSMatthew Wilber {
1599efa8b4f3SAxel Dörfler 	if (fSavePanel) {
1600efa8b4f3SAxel Dörfler 		// Don't allow this window to be closed if a save panel is open
1601efa8b4f3SAxel Dörfler 		return false;
1602cdb89ebbSMatthew Wilber 	}
1603cdb89ebbSMatthew Wilber 
16045b76e505SStephan Aßmus 	if (!_ClosePrompt())
16055b76e505SStephan Aßmus 		return false;
16065b76e505SStephan Aßmus 
16075b76e505SStephan Aßmus 	ShowImageSettings* settings = my_app->Settings();
16085b76e505SStephan Aßmus 	if (settings->Lock()) {
1609c418e2beSStephan Aßmus 		if (fFullScreen)
1610c418e2beSStephan Aßmus 			settings->SetRect("WindowFrame", fWindowFrame);
1611c418e2beSStephan Aßmus 		else
16125b76e505SStephan Aßmus 			settings->SetRect("WindowFrame", Frame());
16135b76e505SStephan Aßmus 		settings->Unlock();
16145b76e505SStephan Aßmus 	}
16155b76e505SStephan Aßmus 
16165b76e505SStephan Aßmus 	be_app->PostMessage(MSG_WINDOW_HAS_QUIT);
16175b76e505SStephan Aßmus 
16185b76e505SStephan Aßmus 	return true;
1619efa8b4f3SAxel Dörfler }
1620