xref: /haiku/src/apps/showimage/ShowImageWindow.cpp (revision d10d59475c9216c2d639424014cefcf98bde7271)
1cdb89ebbSMatthew Wilber /*****************************************************************************/
2cdb89ebbSMatthew Wilber // ShowImageWindow
3ad13f387SMichael Pfeiffer // Written by Fernando Francisco de Oliveira, Michael Wilber, Michael Pfeiffer
4cdb89ebbSMatthew Wilber //
5cdb89ebbSMatthew Wilber // ShowImageWindow.cpp
6cdb89ebbSMatthew Wilber //
7cdb89ebbSMatthew Wilber //
8cdb89ebbSMatthew Wilber // Copyright (c) 2003 OpenBeOS Project
9cdb89ebbSMatthew Wilber //
10cdb89ebbSMatthew Wilber // Permission is hereby granted, free of charge, to any person obtaining a
11cdb89ebbSMatthew Wilber // copy of this software and associated documentation files (the "Software"),
12cdb89ebbSMatthew Wilber // to deal in the Software without restriction, including without limitation
13cdb89ebbSMatthew Wilber // the rights to use, copy, modify, merge, publish, distribute, sublicense,
14cdb89ebbSMatthew Wilber // and/or sell copies of the Software, and to permit persons to whom the
15cdb89ebbSMatthew Wilber // Software is furnished to do so, subject to the following conditions:
16cdb89ebbSMatthew Wilber //
17cdb89ebbSMatthew Wilber // The above copyright notice and this permission notice shall be included
18cdb89ebbSMatthew Wilber // in all copies or substantial portions of the Software.
19cdb89ebbSMatthew Wilber //
20cdb89ebbSMatthew Wilber // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21cdb89ebbSMatthew Wilber // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22cdb89ebbSMatthew Wilber // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23cdb89ebbSMatthew Wilber // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24cdb89ebbSMatthew Wilber // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25cdb89ebbSMatthew Wilber // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26cdb89ebbSMatthew Wilber // DEALINGS IN THE SOFTWARE.
27cdb89ebbSMatthew Wilber /*****************************************************************************/
2813afa642SPhil Greenway 
2913afa642SPhil Greenway #include <algobase.h>
3007caaa8eSMatthew Wilber #include <stdio.h>
3113afa642SPhil Greenway #include <Application.h>
3213afa642SPhil Greenway #include <Bitmap.h>
33fc0a275bSMatthew Wilber #include <BitmapStream.h>
3413afa642SPhil Greenway #include <Entry.h>
35fc0a275bSMatthew Wilber #include <File.h>
3613afa642SPhil Greenway #include <Menu.h>
3713afa642SPhil Greenway #include <MenuBar.h>
3813afa642SPhil Greenway #include <MenuItem.h>
3913afa642SPhil Greenway #include <Path.h>
4013afa642SPhil Greenway #include <ScrollView.h>
4113afa642SPhil Greenway #include <TranslationUtils.h>
4213afa642SPhil Greenway #include <TranslatorRoster.h>
4313afa642SPhil Greenway #include <Alert.h>
4407caaa8eSMatthew Wilber #include <SupportDefs.h>
45ad13f387SMichael Pfeiffer #include <Screen.h>
46*d10d5947SMichael Pfeiffer #include <Roster.h>
4713afa642SPhil Greenway 
4813afa642SPhil Greenway #include "ShowImageConstants.h"
4913afa642SPhil Greenway #include "ShowImageWindow.h"
5013afa642SPhil Greenway #include "ShowImageView.h"
5113afa642SPhil Greenway #include "ShowImageStatusView.h"
5213afa642SPhil Greenway 
5303839579SMatthew Wilber ShowImageWindow::ShowImageWindow(const entry_ref *pref)
54cdb89ebbSMatthew Wilber 	: BWindow(BRect(50, 50, 350, 250), "", B_DOCUMENT_WINDOW, 0)
5513afa642SPhil Greenway {
567eca0987SMichael Pfeiffer 	fpSavePanel = NULL;
577eca0987SMichael Pfeiffer 	fpRef = NULL;
58ad13f387SMichael Pfeiffer 	fFullScreen = false;
59fc0a275bSMatthew Wilber 
6013afa642SPhil Greenway 	// create menu bar
617eca0987SMichael Pfeiffer 	fpBar = new BMenuBar(BRect(0, 0, Bounds().right, 20), "menu_bar");
627eca0987SMichael Pfeiffer 	LoadMenus(fpBar);
637eca0987SMichael Pfeiffer 	AddChild(fpBar);
6413afa642SPhil Greenway 
6513afa642SPhil Greenway 	BRect viewFrame = Bounds();
667eca0987SMichael Pfeiffer 	viewFrame.top		= fpBar->Bounds().bottom + 1;
6713afa642SPhil Greenway 	viewFrame.right		-= B_V_SCROLL_BAR_WIDTH;
6813afa642SPhil Greenway 	viewFrame.bottom	-= B_H_SCROLL_BAR_HEIGHT;
6913afa642SPhil Greenway 
7013afa642SPhil Greenway 	// create the image view
717eca0987SMichael Pfeiffer 	fpImageView = new ShowImageView(viewFrame, "image_view", B_FOLLOW_ALL,
727eca0987SMichael Pfeiffer 		B_WILL_DRAW | B_FRAME_EVENTS | B_FULL_UPDATE_ON_RESIZE | B_PULSE_NEEDED);
7313afa642SPhil Greenway 	// wrap a scroll view around the view
747eca0987SMichael Pfeiffer 	BScrollView *pscrollView = new BScrollView("image_scroller", fpImageView,
75cdb89ebbSMatthew Wilber 		B_FOLLOW_ALL, 0, false, false, B_PLAIN_BORDER);
76cdb89ebbSMatthew Wilber 	AddChild(pscrollView);
7713afa642SPhil Greenway 
7807caaa8eSMatthew Wilber 	const int32 kstatusWidth = 190;
79cdb89ebbSMatthew Wilber 	BRect rect;
8013afa642SPhil Greenway 	rect = Bounds();
8113afa642SPhil Greenway 	rect.top	= viewFrame.bottom + 1;
8207caaa8eSMatthew Wilber 	rect.left 	= viewFrame.left + kstatusWidth;
8313afa642SPhil Greenway 	rect.right	= viewFrame.right;
84cdb89ebbSMatthew Wilber 	BScrollBar *phscroll;
857eca0987SMichael Pfeiffer 	phscroll = new BScrollBar(rect, "hscroll", fpImageView, 0, 150,
86cdb89ebbSMatthew Wilber 		B_HORIZONTAL);
87cdb89ebbSMatthew Wilber 	AddChild(phscroll);
8813afa642SPhil Greenway 
8913afa642SPhil Greenway 	rect.left = 0;
9007caaa8eSMatthew Wilber 	rect.right = kstatusWidth - 1;
917eca0987SMichael Pfeiffer 	fpStatusView = new ShowImageStatusView(rect, "status_view", B_FOLLOW_BOTTOM,
92cdb89ebbSMatthew Wilber 		B_WILL_DRAW);
937eca0987SMichael Pfeiffer 	fpStatusView->SetViewColor(ui_color(B_MENU_BACKGROUND_COLOR));
947eca0987SMichael Pfeiffer 	AddChild(fpStatusView);
9513afa642SPhil Greenway 
9613afa642SPhil Greenway 	rect = Bounds();
9713afa642SPhil Greenway 	rect.top    = viewFrame.top;
9813afa642SPhil Greenway 	rect.left 	= viewFrame.right + 1;
9913afa642SPhil Greenway 	rect.bottom	= viewFrame.bottom;
100cdb89ebbSMatthew Wilber 	BScrollBar *pvscroll;
1017eca0987SMichael Pfeiffer 	pvscroll = new BScrollBar(rect, "vscroll", fpImageView, 0, 150, B_VERTICAL);
102cdb89ebbSMatthew Wilber 	AddChild(pvscroll);
10313afa642SPhil Greenway 
10403839579SMatthew Wilber 	SetSizeLimits(250, 100000, 100, 100000);
10513afa642SPhil Greenway 
10613afa642SPhil Greenway 	// finish creating window
107cdb89ebbSMatthew Wilber 	SetRef(pref);
10813afa642SPhil Greenway 	UpdateTitle();
10913afa642SPhil Greenway 
1107eca0987SMichael Pfeiffer 	fpImageView->SetImage(pref);
1117eca0987SMichael Pfeiffer 
1127eca0987SMichael Pfeiffer 	SetPulseRate(100000); // every 1/10 second; ShowImageView needs it for marching ants
11303839579SMatthew Wilber 
114*d10d5947SMichael Pfeiffer 	if (InitCheck() == B_OK) {
115*d10d5947SMichael Pfeiffer 		fpImageView->FlushToLeftTop();
116*d10d5947SMichael Pfeiffer 		WindowRedimension(fpImageView->GetBitmap());
11713afa642SPhil Greenway 		Show();
118*d10d5947SMichael Pfeiffer 	} else {
119*d10d5947SMichael Pfeiffer 		// exit if file could not be opened
120*d10d5947SMichael Pfeiffer 		Quit();
121*d10d5947SMichael Pfeiffer 	}
12213afa642SPhil Greenway }
12313afa642SPhil Greenway 
12413afa642SPhil Greenway ShowImageWindow::~ShowImageWindow()
12513afa642SPhil Greenway {
1267eca0987SMichael Pfeiffer 	delete fpRef;
12713afa642SPhil Greenway }
12813afa642SPhil Greenway 
129cdb89ebbSMatthew Wilber status_t
130cdb89ebbSMatthew Wilber ShowImageWindow::InitCheck()
13113afa642SPhil Greenway {
132*d10d5947SMichael Pfeiffer 	if (!fpRef || !fpImageView || fpImageView->GetBitmap() == NULL)
13313afa642SPhil Greenway 		return B_ERROR;
134cdb89ebbSMatthew Wilber 	else
13513afa642SPhil Greenway 		return B_OK;
13613afa642SPhil Greenway }
137cdb89ebbSMatthew Wilber 
138cdb89ebbSMatthew Wilber void
139cdb89ebbSMatthew Wilber ShowImageWindow::SetRef(const entry_ref *pref)
140cdb89ebbSMatthew Wilber {
1417eca0987SMichael Pfeiffer 	if (!fpRef)
1427eca0987SMichael Pfeiffer 		fpRef = new entry_ref(*pref);
143cdb89ebbSMatthew Wilber 	else
1447eca0987SMichael Pfeiffer 		*fpRef = *pref;
14513afa642SPhil Greenway }
14613afa642SPhil Greenway 
147cdb89ebbSMatthew Wilber void
148cdb89ebbSMatthew Wilber ShowImageWindow::UpdateTitle()
14913afa642SPhil Greenway {
1507eca0987SMichael Pfeiffer 	BEntry entry(fpRef);
15113afa642SPhil Greenway 	if (entry.InitCheck() == B_OK) {
15213afa642SPhil Greenway 		BPath path;
15313afa642SPhil Greenway 		entry.GetPath(&path);
154cdb89ebbSMatthew Wilber 		if (path.InitCheck() == B_OK)
15513afa642SPhil Greenway 			SetTitle(path.Path());
15613afa642SPhil Greenway 	}
15713afa642SPhil Greenway }
15813afa642SPhil Greenway 
159cdb89ebbSMatthew Wilber void
160*d10d5947SMichael Pfeiffer ShowImageWindow::UpdateRecentDocumentsMenu()
161*d10d5947SMichael Pfeiffer {
162*d10d5947SMichael Pfeiffer 	BMenuItem *item;
163*d10d5947SMichael Pfeiffer 	BMessage list, *msg;
164*d10d5947SMichael Pfeiffer 	entry_ref ref;
165*d10d5947SMichael Pfeiffer 	char name[B_FILE_NAME_LENGTH];
166*d10d5947SMichael Pfeiffer 
167*d10d5947SMichael Pfeiffer 	while ((item = fpOpenMenu->RemoveItem((int32)0)) != NULL) {
168*d10d5947SMichael Pfeiffer 		delete item;
169*d10d5947SMichael Pfeiffer 	}
170*d10d5947SMichael Pfeiffer 
171*d10d5947SMichael Pfeiffer 	be_roster->GetRecentDocuments(&list, 20, NULL, APP_SIG);
172*d10d5947SMichael Pfeiffer 	for (int i = 0; list.FindRef("refs", i, &ref) == B_OK; i++) {
173*d10d5947SMichael Pfeiffer 		BEntry entry(&ref);
174*d10d5947SMichael Pfeiffer 		entry.GetName(name);
175*d10d5947SMichael Pfeiffer 		msg = new BMessage(B_REFS_RECEIVED);
176*d10d5947SMichael Pfeiffer 		msg->AddRef("refs", &ref);
177*d10d5947SMichael Pfeiffer 		item =  new BMenuItem(name, msg, 0, 0);
178*d10d5947SMichael Pfeiffer 		fpOpenMenu->AddItem(item);
179*d10d5947SMichael Pfeiffer 		item->SetTarget(be_app, NULL);
180*d10d5947SMichael Pfeiffer 	}
181*d10d5947SMichael Pfeiffer }
182*d10d5947SMichael Pfeiffer 
183*d10d5947SMichael Pfeiffer void
184cdb89ebbSMatthew Wilber ShowImageWindow::LoadMenus(BMenuBar *pbar)
18513afa642SPhil Greenway {
186cdb89ebbSMatthew Wilber 	BMenu *pmenu = new BMenu("File");
187*d10d5947SMichael Pfeiffer 	fpOpenMenu = new BMenu("Open");
188*d10d5947SMichael Pfeiffer 	pmenu->AddItem(fpOpenMenu);
189*d10d5947SMichael Pfeiffer 	fpOpenMenu->Superitem()->SetTrigger('O');
190*d10d5947SMichael Pfeiffer 	fpOpenMenu->Superitem()->SetMessage(new BMessage(MSG_FILE_OPEN));
191*d10d5947SMichael Pfeiffer 	fpOpenMenu->Superitem()->SetTarget(be_app);
192*d10d5947SMichael Pfeiffer 	fpOpenMenu->Superitem()->SetShortcut('O', 0);
193cdb89ebbSMatthew Wilber 	pmenu->AddSeparatorItem();
194ad13f387SMichael Pfeiffer 	AddItemMenu(pmenu, "Dia Show", MSG_DIA_SHOW, 0, 0, 'W', true);
195ad13f387SMichael Pfeiffer 	BMenu* pDelay = new BMenu("Delay");
196ad13f387SMichael Pfeiffer 	pDelay->SetRadioMode(true);
197ad13f387SMichael Pfeiffer 	// Note: ShowImage loades images in window thread so it becomes unresponsive if
198ad13f387SMichael Pfeiffer 	// dia show delay is too short! (Especially if loading the image takes as long as
199ad13f387SMichael Pfeiffer 	// or longer than the dia show delay). Should load in background thread!
200ad13f387SMichael Pfeiffer 	// AddDelayItem(pDelay, "Half a Second", 0.5, false);
201ad13f387SMichael Pfeiffer 	// AddDelayItem(pDelay, "One Second", 1, false);
202ad13f387SMichael Pfeiffer 	// AddDelayItem(pDelay, "Two Second", 2, false);
203ad13f387SMichael Pfeiffer 	AddDelayItem(pDelay, "Three Seconds", 3, true);
204ad13f387SMichael Pfeiffer 	AddDelayItem(pDelay, "Four Second", 4, false);
205ad13f387SMichael Pfeiffer 	AddDelayItem(pDelay, "Five Seconds", 5, false);
206ad13f387SMichael Pfeiffer 	AddDelayItem(pDelay, "Six Seconds", 6, false);
207ad13f387SMichael Pfeiffer 	AddDelayItem(pDelay, "Seven Seconds", 7, false);
208ad13f387SMichael Pfeiffer 	AddDelayItem(pDelay, "Eight Seconds", 8, false);
209ad13f387SMichael Pfeiffer 	AddDelayItem(pDelay, "Nine Seconds", 9, false);
210ad13f387SMichael Pfeiffer 	AddDelayItem(pDelay, "Ten Seconds", 10, false);
211ad13f387SMichael Pfeiffer 	AddDelayItem(pDelay, "Tweenty Seconds", 20, false);
212ad13f387SMichael Pfeiffer 	pmenu->AddItem(pDelay);
213ad13f387SMichael Pfeiffer 	pmenu->AddSeparatorItem();
214ad13f387SMichael Pfeiffer 	AddItemMenu(pmenu, "Next", MSG_FILE_NEXT, B_DOWN_ARROW, 0, 'W', true);
215ad13f387SMichael Pfeiffer 	AddItemMenu(pmenu, "Previous", MSG_FILE_PREV, B_UP_ARROW, 0, 'W', true);
216ad13f387SMichael Pfeiffer 	pmenu->AddSeparatorItem();
217cdb89ebbSMatthew Wilber 	BMenu *pmenuSaveAs = new BMenu("Save As...", B_ITEMS_IN_COLUMN);
218cdb89ebbSMatthew Wilber 	BTranslationUtils::AddTranslationItems(pmenuSaveAs, B_TRANSLATOR_BITMAP);
219fc0a275bSMatthew Wilber 		// Fill Save As submenu with all types that can be converted
220fc0a275bSMatthew Wilber 		// to from the Be bitmap image format
221cdb89ebbSMatthew Wilber 	pmenu->AddItem(pmenuSaveAs);
222cdb89ebbSMatthew Wilber 	AddItemMenu(pmenu, "Close", MSG_CLOSE, 'W', 0, 'W', true);
223cdb89ebbSMatthew Wilber 	pmenu->AddSeparatorItem();
224cdb89ebbSMatthew Wilber 	AddItemMenu(pmenu, "About ShowImage...", B_ABOUT_REQUESTED, 0, 0, 'A', true);
225cdb89ebbSMatthew Wilber 	pmenu->AddSeparatorItem();
226cdb89ebbSMatthew Wilber 	AddItemMenu(pmenu, "Quit", B_QUIT_REQUESTED, 'Q', 0, 'A', true);
227cdb89ebbSMatthew Wilber 	pbar->AddItem(pmenu);
22813afa642SPhil Greenway 
229cdb89ebbSMatthew Wilber 	pmenu = new BMenu("Edit");
230cdb89ebbSMatthew Wilber 	AddItemMenu(pmenu, "Undo", B_UNDO, 'Z', 0, 'W', false);
231cdb89ebbSMatthew Wilber 	pmenu->AddSeparatorItem();
232cdb89ebbSMatthew Wilber 	AddItemMenu(pmenu, "Cut", B_CUT, 'X', 0, 'W', false);
233*d10d5947SMichael Pfeiffer 	AddItemMenu(pmenu, "Copy", B_COPY, 'C', 0, 'W', true);
234cdb89ebbSMatthew Wilber 	AddItemMenu(pmenu, "Paste", B_PASTE, 'V', 0, 'W', false);
235*d10d5947SMichael Pfeiffer 	AddItemMenu(pmenu, "Clear", MSG_CLEAR_SELECT, 0, 0, 'W', true);
236cdb89ebbSMatthew Wilber 	pmenu->AddSeparatorItem();
237*d10d5947SMichael Pfeiffer 	AddItemMenu(pmenu, "Select All", MSG_SELECT_ALL, 'A', 0, 'W', true);
238cdb89ebbSMatthew Wilber 	pbar->AddItem(pmenu);
23913afa642SPhil Greenway 
2407eca0987SMichael Pfeiffer 	pmenu = fpPageMenu = new BMenu("Page");
24103839579SMatthew Wilber 	AddItemMenu(pmenu, "First", MSG_PAGE_FIRST, 'F', 0, 'W', true);
24203839579SMatthew Wilber 	AddItemMenu(pmenu, "Last", MSG_PAGE_LAST, 'L', 0, 'W', true);
24303839579SMatthew Wilber 	AddItemMenu(pmenu, "Next", MSG_PAGE_NEXT, 'N', 0, 'W', true);
24403839579SMatthew Wilber 	AddItemMenu(pmenu, "Previous", MSG_PAGE_PREV, 'P', 0, 'W', true);
24503839579SMatthew Wilber 	pbar->AddItem(pmenu);
24603839579SMatthew Wilber 
247cdb89ebbSMatthew Wilber 	pmenu = new BMenu("Image");
248cdb89ebbSMatthew Wilber 	AddItemMenu(pmenu, "Dither Image", MSG_DITHER_IMAGE, 0, 0, 'W', true);
249ad13f387SMichael Pfeiffer 	pmenu->AddSeparatorItem();
250ad13f387SMichael Pfeiffer 	AddItemMenu(pmenu, "Rotate Clockwise", MSG_ROTATE_CLOCKWISE, B_RIGHT_ARROW, 0, 'W', true);
251ad13f387SMichael Pfeiffer 	AddItemMenu(pmenu, "Rotate Anticlockwise", MSG_ROTATE_ACLKWISE, B_LEFT_ARROW, 0, 'W', true);
252ad13f387SMichael Pfeiffer 	pmenu->AddSeparatorItem();
253ad13f387SMichael Pfeiffer 	AddItemMenu(pmenu, "Mirror Vertical", MSG_MIRROR_VERTICAL, 0, 0, 'W', true);
254ad13f387SMichael Pfeiffer 	AddItemMenu(pmenu, "Mirror Horizontal", MSG_MIRROR_HORIZONTAL, 0, 0, 'W', true);
255ad13f387SMichael Pfeiffer 	pmenu->AddSeparatorItem();
256ad13f387SMichael Pfeiffer 	AddItemMenu(pmenu, "Invert", MSG_INVERT, 0, 0, 'W', true);
257ad13f387SMichael Pfeiffer 	pbar->AddItem(pmenu);
258ad13f387SMichael Pfeiffer 
259ad13f387SMichael Pfeiffer 	pmenu = new BMenu("View");
2607eca0987SMichael Pfeiffer 	AddItemMenu(pmenu, "Fit To Window Size", MSG_FIT_TO_WINDOW_SIZE, 0, 0, 'W', true);
261ad13f387SMichael Pfeiffer 	AddItemMenu(pmenu, "Full Screen", MSG_FULL_SCREEN, B_ENTER, 0, 'W', true);
262cdb89ebbSMatthew Wilber 	pbar->AddItem(pmenu);
263*d10d5947SMichael Pfeiffer 
264*d10d5947SMichael Pfeiffer 	UpdateRecentDocumentsMenu();
26513afa642SPhil Greenway }
26613afa642SPhil Greenway 
267cdb89ebbSMatthew Wilber BMenuItem *
268cdb89ebbSMatthew Wilber ShowImageWindow::AddItemMenu(BMenu *pmenu, char *caption, long unsigned int msg,
269cdb89ebbSMatthew Wilber 	char shortcut, uint32 modifier, char target, bool benabled)
270cdb89ebbSMatthew Wilber {
271cdb89ebbSMatthew Wilber 	BMenuItem* pitem;
272cdb89ebbSMatthew Wilber 	pitem = new BMenuItem(caption, new BMessage(msg), shortcut);
27313afa642SPhil Greenway 
27413afa642SPhil Greenway 	if (target == 'A')
275cdb89ebbSMatthew Wilber 	   pitem->SetTarget(be_app);
27613afa642SPhil Greenway 
277cdb89ebbSMatthew Wilber 	pitem->SetEnabled(benabled);
278cdb89ebbSMatthew Wilber 	pmenu->AddItem(pitem);
27913afa642SPhil Greenway 
280cdb89ebbSMatthew Wilber 	return pitem;
28113afa642SPhil Greenway }
28213afa642SPhil Greenway 
283ad13f387SMichael Pfeiffer BMenuItem*
284ad13f387SMichael Pfeiffer ShowImageWindow::AddDelayItem(BMenu *pmenu, char *caption, float value, bool marked)
285ad13f387SMichael Pfeiffer {
286ad13f387SMichael Pfeiffer 	BMenuItem* pitem;
287ad13f387SMichael Pfeiffer 	BMessage* pmsg;
288ad13f387SMichael Pfeiffer 	pmsg = new BMessage(MSG_DIA_SHOW_DELAY);
289ad13f387SMichael Pfeiffer 	pmsg->AddFloat("value", value);
290ad13f387SMichael Pfeiffer 
291ad13f387SMichael Pfeiffer 	pitem = new BMenuItem(caption, pmsg, 0);
292ad13f387SMichael Pfeiffer 
293ad13f387SMichael Pfeiffer 	if (marked) pitem->SetMarked(true);
294ad13f387SMichael Pfeiffer 	pmenu->AddItem(pitem);
295ad13f387SMichael Pfeiffer 
296ad13f387SMichael Pfeiffer 	return pitem;
297ad13f387SMichael Pfeiffer }
298ad13f387SMichael Pfeiffer 
299cdb89ebbSMatthew Wilber void
300cdb89ebbSMatthew Wilber ShowImageWindow::WindowRedimension(BBitmap *pbitmap)
30113afa642SPhil Greenway {
302*d10d5947SMichael Pfeiffer 	BScreen screen;
303*d10d5947SMichael Pfeiffer 	BRect r(pbitmap->Bounds());
304*d10d5947SMichael Pfeiffer 	float width, height;
305*d10d5947SMichael Pfeiffer 	float maxWidth, maxHeight;
306*d10d5947SMichael Pfeiffer 	const float windowBorderWidth = 5;
307*d10d5947SMichael Pfeiffer 	const float windowBorderHeight = 5;
30813afa642SPhil Greenway 
309*d10d5947SMichael Pfeiffer 	if (screen.Frame().right == 0.0) {
310*d10d5947SMichael Pfeiffer 		return; // invalid screen object
311*d10d5947SMichael Pfeiffer 	}
312cdb89ebbSMatthew Wilber 
313*d10d5947SMichael Pfeiffer 	width = r.Width() + B_V_SCROLL_BAR_WIDTH;
314*d10d5947SMichael Pfeiffer 	height = r.Height() + 1 + fpBar->Frame().Height() + B_H_SCROLL_BAR_HEIGHT;
315cdb89ebbSMatthew Wilber 
316*d10d5947SMichael Pfeiffer 	// dimensions so that window does not reach outside of screen
317*d10d5947SMichael Pfeiffer 	maxWidth = screen.Frame().Width() + 1 - windowBorderWidth - Frame().left;
318*d10d5947SMichael Pfeiffer 	maxHeight = screen.Frame().Height() + 1 - windowBorderHeight - Frame().top;
319cdb89ebbSMatthew Wilber 
320*d10d5947SMichael Pfeiffer 	if (width > maxWidth) width = maxWidth;
321*d10d5947SMichael Pfeiffer 	if (height > maxHeight) height = maxHeight;
322*d10d5947SMichael Pfeiffer 
323*d10d5947SMichael Pfeiffer 	ResizeTo(width, height);
32413afa642SPhil Greenway }
32513afa642SPhil Greenway 
326cdb89ebbSMatthew Wilber void
327cdb89ebbSMatthew Wilber ShowImageWindow::FrameResized(float width, float height)
32813afa642SPhil Greenway {
32913afa642SPhil Greenway }
33013afa642SPhil Greenway 
3317eca0987SMichael Pfeiffer bool
3327eca0987SMichael Pfeiffer ShowImageWindow::ToggleMenuItem(uint32 what)
3337eca0987SMichael Pfeiffer {
3347eca0987SMichael Pfeiffer 	BMenuItem *item;
3357eca0987SMichael Pfeiffer 	bool marked = false;
3367eca0987SMichael Pfeiffer 	item = fpBar->FindItem(what);
3377eca0987SMichael Pfeiffer 	if (item != NULL) {
3387eca0987SMichael Pfeiffer 		marked = !item->IsMarked();
3397eca0987SMichael Pfeiffer 		item->SetMarked(marked);
3407eca0987SMichael Pfeiffer 	}
3417eca0987SMichael Pfeiffer 	return marked;
3427eca0987SMichael Pfeiffer }
3437eca0987SMichael Pfeiffer 
344cdb89ebbSMatthew Wilber void
345cdb89ebbSMatthew Wilber ShowImageWindow::MessageReceived(BMessage *pmsg)
34613afa642SPhil Greenway {
347cdb89ebbSMatthew Wilber 	switch (pmsg->what) {
348fc0a275bSMatthew Wilber 		case MSG_OUTPUT_TYPE:
349fc0a275bSMatthew Wilber 			// User clicked Save As then choose an output format
3507eca0987SMichael Pfeiffer 			if (!fpSavePanel)
351cdb89ebbSMatthew Wilber 				// If user doesn't already have a save panel open
352cdb89ebbSMatthew Wilber 				SaveAs(pmsg);
35313afa642SPhil Greenway 			break;
354fc0a275bSMatthew Wilber 
355fc0a275bSMatthew Wilber 		case MSG_SAVE_PANEL:
356fc0a275bSMatthew Wilber 			// User specified where to save the output image
357cdb89ebbSMatthew Wilber 			SaveToFile(pmsg);
358fc0a275bSMatthew Wilber 			break;
359fc0a275bSMatthew Wilber 
36007caaa8eSMatthew Wilber 		case MSG_CLOSE:
361cdb89ebbSMatthew Wilber 			if (CanQuit())
36207caaa8eSMatthew Wilber 				Quit();
36307caaa8eSMatthew Wilber 			break;
36407caaa8eSMatthew Wilber 
365cdb89ebbSMatthew Wilber 		case B_CANCEL:
3667eca0987SMichael Pfeiffer 			delete fpSavePanel;
3677eca0987SMichael Pfeiffer 			fpSavePanel = NULL;
368cdb89ebbSMatthew Wilber 			break;
369cdb89ebbSMatthew Wilber 
37003839579SMatthew Wilber 		case MSG_UPDATE_STATUS:
37103839579SMatthew Wilber 		{
3727eca0987SMichael Pfeiffer 			bool benable = (fpImageView->PageCount() > 1) ? true : false;
3737eca0987SMichael Pfeiffer 			if (fpPageMenu->IsEnabled() != benable)
3741d592070SMatthew Wilber 				// Only call this function if the state is changing
3751d592070SMatthew Wilber 				// to avoid flickering
3767eca0987SMichael Pfeiffer 				fpPageMenu->SetEnabled(benable);
3771d592070SMatthew Wilber 
37803839579SMatthew Wilber 			BString str;
37903839579SMatthew Wilber 			if (pmsg->FindString("status", &str) == B_OK)
3807eca0987SMichael Pfeiffer 				fpStatusView->SetText(str);
3817eca0987SMichael Pfeiffer 
3827eca0987SMichael Pfeiffer 			entry_ref ref;
3837eca0987SMichael Pfeiffer 			if (pmsg->FindRef("ref", &ref) == B_OK) {
3847eca0987SMichael Pfeiffer 				SetRef(&ref);
3857eca0987SMichael Pfeiffer 				UpdateTitle();
3867eca0987SMichael Pfeiffer 			}
38703839579SMatthew Wilber 			break;
38803839579SMatthew Wilber 		}
38903839579SMatthew Wilber 
39013afa642SPhil Greenway 		case B_UNDO:
39113afa642SPhil Greenway 			break;
39213afa642SPhil Greenway 		case B_CUT:
39313afa642SPhil Greenway 			break;
39413afa642SPhil Greenway 		case B_COPY:
395*d10d5947SMichael Pfeiffer 			fpImageView->CopySelectionToClipboard();
39613afa642SPhil Greenway 			break;
39713afa642SPhil Greenway 		case B_PASTE:
39813afa642SPhil Greenway 			break;
39913afa642SPhil Greenway 		case MSG_CLEAR_SELECT:
400*d10d5947SMichael Pfeiffer 			fpImageView->Unselect();
40113afa642SPhil Greenway 			break;
40213afa642SPhil Greenway 		case MSG_SELECT_ALL:
403*d10d5947SMichael Pfeiffer 			fpImageView->SelectAll();
40413afa642SPhil Greenway 			break;
40513afa642SPhil Greenway 
40603839579SMatthew Wilber 		case MSG_PAGE_FIRST:
4077eca0987SMichael Pfeiffer 			fpImageView->FirstPage();
40803839579SMatthew Wilber 			break;
40903839579SMatthew Wilber 
41003839579SMatthew Wilber 		case MSG_PAGE_LAST:
4117eca0987SMichael Pfeiffer 			fpImageView->LastPage();
41203839579SMatthew Wilber 			break;
41303839579SMatthew Wilber 
41403839579SMatthew Wilber 		case MSG_PAGE_NEXT:
4157eca0987SMichael Pfeiffer 			fpImageView->NextPage();
41603839579SMatthew Wilber 			break;
41703839579SMatthew Wilber 
41803839579SMatthew Wilber 		case MSG_PAGE_PREV:
4197eca0987SMichael Pfeiffer 			fpImageView->PrevPage();
42003839579SMatthew Wilber 			break;
42103839579SMatthew Wilber 
422cdb89ebbSMatthew Wilber 		case MSG_DITHER_IMAGE:
4237eca0987SMichael Pfeiffer 			ToggleMenuItem(pmsg->what);
4247eca0987SMichael Pfeiffer 			break;
4257eca0987SMichael Pfeiffer 
4267eca0987SMichael Pfeiffer 		case MSG_FIT_TO_WINDOW_SIZE:
4277eca0987SMichael Pfeiffer 			{
4287eca0987SMichael Pfeiffer 				bool resize;
4297eca0987SMichael Pfeiffer 				resize = ToggleMenuItem(pmsg->what);
4307eca0987SMichael Pfeiffer 				fpImageView->ResizeToViewBounds(resize);
4317eca0987SMichael Pfeiffer 			}
4327eca0987SMichael Pfeiffer 			break;
4337eca0987SMichael Pfeiffer 
4347eca0987SMichael Pfeiffer 		case MSG_FILE_PREV:
4357eca0987SMichael Pfeiffer 			fpImageView->PrevFile();
4367eca0987SMichael Pfeiffer 			break;
4377eca0987SMichael Pfeiffer 
4387eca0987SMichael Pfeiffer 		case MSG_FILE_NEXT:
4397eca0987SMichael Pfeiffer 			fpImageView->NextFile();
44013afa642SPhil Greenway 			break;
44113afa642SPhil Greenway 
442ad13f387SMichael Pfeiffer 		case MSG_ROTATE_CLOCKWISE:
443ad13f387SMichael Pfeiffer 			fpImageView->Rotate(90);
444ad13f387SMichael Pfeiffer 			break;
445ad13f387SMichael Pfeiffer 		case MSG_ROTATE_ACLKWISE:
446ad13f387SMichael Pfeiffer 			fpImageView->Rotate(270);
447ad13f387SMichael Pfeiffer 			break;
448ad13f387SMichael Pfeiffer 		case MSG_MIRROR_VERTICAL:
449ad13f387SMichael Pfeiffer 			fpImageView->Mirror(true);
450ad13f387SMichael Pfeiffer 			break;
451ad13f387SMichael Pfeiffer 		case MSG_MIRROR_HORIZONTAL:
452ad13f387SMichael Pfeiffer 			fpImageView->Mirror(false);
453ad13f387SMichael Pfeiffer 			break;
454ad13f387SMichael Pfeiffer 		case MSG_INVERT:
455ad13f387SMichael Pfeiffer 			fpImageView->Invert();
456ad13f387SMichael Pfeiffer 			break;
457ad13f387SMichael Pfeiffer 		case MSG_DIA_SHOW:
458ad13f387SMichael Pfeiffer 			if (ToggleMenuItem(pmsg->what)) {
459ad13f387SMichael Pfeiffer 				fpImageView->StartDiaShow();
460ad13f387SMichael Pfeiffer 			} else {
461ad13f387SMichael Pfeiffer 				fpImageView->StopDiaShow();
462ad13f387SMichael Pfeiffer 			}
463ad13f387SMichael Pfeiffer 		case MSG_DIA_SHOW_DELAY:
464ad13f387SMichael Pfeiffer 			{
465ad13f387SMichael Pfeiffer 				float value;
466ad13f387SMichael Pfeiffer 				if (pmsg->FindFloat("value", &value) == B_OK) {
467ad13f387SMichael Pfeiffer 					fpImageView->SetDiaShowDelay(value);
468ad13f387SMichael Pfeiffer 				}
469ad13f387SMichael Pfeiffer 			}
470ad13f387SMichael Pfeiffer 			break;
471ad13f387SMichael Pfeiffer 
472ad13f387SMichael Pfeiffer 		case MSG_FULL_SCREEN:
473ad13f387SMichael Pfeiffer 			ToggleFullScreen();
474ad13f387SMichael Pfeiffer 			break;
475ad13f387SMichael Pfeiffer 
476*d10d5947SMichael Pfeiffer 		case MSG_UPDATE_RECENT_DOCUMENTS:
477*d10d5947SMichael Pfeiffer 			UpdateRecentDocumentsMenu();
478*d10d5947SMichael Pfeiffer 			break;
479*d10d5947SMichael Pfeiffer 
48013afa642SPhil Greenway 		default:
481cdb89ebbSMatthew Wilber 			BWindow::MessageReceived(pmsg);
48213afa642SPhil Greenway 			break;
48313afa642SPhil Greenway 	}
48413afa642SPhil Greenway }
485fc0a275bSMatthew Wilber 
486fc0a275bSMatthew Wilber void
487fc0a275bSMatthew Wilber ShowImageWindow::SaveAs(BMessage *pmsg)
488fc0a275bSMatthew Wilber {
489cdb89ebbSMatthew Wilber 	// Read the translator and output type the user chose
490cdb89ebbSMatthew Wilber 	translator_id outTranslator;
491cdb89ebbSMatthew Wilber 	uint32 outType;
492cdb89ebbSMatthew Wilber 	if (pmsg->FindInt32(TRANSLATOR_FLD,
493cdb89ebbSMatthew Wilber 		reinterpret_cast<int32 *>(&outTranslator)) != B_OK)
494fc0a275bSMatthew Wilber 		return;
495cdb89ebbSMatthew Wilber 	if (pmsg->FindInt32(TYPE_FLD,
496cdb89ebbSMatthew Wilber 		reinterpret_cast<int32 *>(&outType)) != B_OK)
497fc0a275bSMatthew Wilber 		return;
498fc0a275bSMatthew Wilber 
499cdb89ebbSMatthew Wilber 	// Add the chosen translator and output type to the
500cdb89ebbSMatthew Wilber 	// message that the save panel will send back
501cdb89ebbSMatthew Wilber 	BMessage *ppanelMsg = new BMessage(MSG_SAVE_PANEL);
502cdb89ebbSMatthew Wilber 	ppanelMsg->AddInt32(TRANSLATOR_FLD, outTranslator);
503cdb89ebbSMatthew Wilber 	ppanelMsg->AddInt32(TYPE_FLD, outType);
504cdb89ebbSMatthew Wilber 
505cdb89ebbSMatthew Wilber 	// Create save panel and show it
5067eca0987SMichael Pfeiffer 	fpSavePanel = new BFilePanel(B_SAVE_PANEL, new BMessenger(this), NULL, 0,
507cdb89ebbSMatthew Wilber 		false, ppanelMsg);
5087eca0987SMichael Pfeiffer 	if (!fpSavePanel)
509fc0a275bSMatthew Wilber 		return;
5107eca0987SMichael Pfeiffer 	fpSavePanel->Window()->SetWorkspaces(B_CURRENT_WORKSPACE);
5117eca0987SMichael Pfeiffer 	fpSavePanel->Show();
512fc0a275bSMatthew Wilber }
513fc0a275bSMatthew Wilber 
514fc0a275bSMatthew Wilber void
515fc0a275bSMatthew Wilber ShowImageWindow::SaveToFile(BMessage *pmsg)
516fc0a275bSMatthew Wilber {
517cdb89ebbSMatthew Wilber 	// Read in where the file should be saved
518fc0a275bSMatthew Wilber 	entry_ref dirref;
519fc0a275bSMatthew Wilber 	if (pmsg->FindRef("directory", &dirref) != B_OK)
520fc0a275bSMatthew Wilber 		return;
521fc0a275bSMatthew Wilber 	const char *filename;
522fc0a275bSMatthew Wilber 	if (pmsg->FindString("name", &filename) != B_OK)
523fc0a275bSMatthew Wilber 		return;
524fc0a275bSMatthew Wilber 
525cdb89ebbSMatthew Wilber 	// Read in the translator and type to be used
526cdb89ebbSMatthew Wilber 	// to save the output image
527cdb89ebbSMatthew Wilber 	translator_id outTranslator;
528cdb89ebbSMatthew Wilber 	uint32 outType;
529cdb89ebbSMatthew Wilber 	if (pmsg->FindInt32(TRANSLATOR_FLD,
530cdb89ebbSMatthew Wilber 		reinterpret_cast<int32 *>(&outTranslator)) != B_OK)
531cdb89ebbSMatthew Wilber 		return;
532cdb89ebbSMatthew Wilber 	if (pmsg->FindInt32(TYPE_FLD,
533cdb89ebbSMatthew Wilber 		reinterpret_cast<int32 *>(&outType)) != B_OK)
534cdb89ebbSMatthew Wilber 		return;
535cdb89ebbSMatthew Wilber 
536cdb89ebbSMatthew Wilber 	// Create the output file
537fc0a275bSMatthew Wilber 	BDirectory dir(&dirref);
538fc0a275bSMatthew Wilber 	BFile file(&dir, filename, B_WRITE_ONLY | B_CREATE_FILE | B_ERASE_FILE);
539fc0a275bSMatthew Wilber 	if (file.InitCheck() != B_OK)
540fc0a275bSMatthew Wilber 		return;
541fc0a275bSMatthew Wilber 
542cdb89ebbSMatthew Wilber 	// Translate the image and write it out to the output file
5437eca0987SMichael Pfeiffer 	BBitmapStream stream(fpImageView->GetBitmap());
544fc0a275bSMatthew Wilber 	BTranslatorRoster *proster = BTranslatorRoster::Default();
545cdb89ebbSMatthew Wilber 	if (proster->Translate(outTranslator, &stream, NULL,
546cdb89ebbSMatthew Wilber 		&file, outType) != B_OK) {
547fc0a275bSMatthew Wilber 		BAlert *palert = new BAlert(NULL, "Error writing image file.", "Ok");
548fc0a275bSMatthew Wilber 		palert->Go();
549fc0a275bSMatthew Wilber 	}
550fc0a275bSMatthew Wilber 
551fc0a275bSMatthew Wilber 	BBitmap *pout = NULL;
552fc0a275bSMatthew Wilber 	stream.DetachBitmap(&pout);
553fc0a275bSMatthew Wilber 		// bitmap used by stream still belongs to the view,
554fc0a275bSMatthew Wilber 		// detach so it doesn't get deleted
555fc0a275bSMatthew Wilber }
556fc0a275bSMatthew Wilber 
557cdb89ebbSMatthew Wilber bool
558cdb89ebbSMatthew Wilber ShowImageWindow::CanQuit()
559cdb89ebbSMatthew Wilber {
5607eca0987SMichael Pfeiffer 	if (fpSavePanel)
561cdb89ebbSMatthew Wilber 		// Don't allow this window to be closed if a save panel is open
562cdb89ebbSMatthew Wilber 		return false;
563cdb89ebbSMatthew Wilber 	else
564cdb89ebbSMatthew Wilber 		return true;
565cdb89ebbSMatthew Wilber }
566cdb89ebbSMatthew Wilber 
567ad13f387SMichael Pfeiffer void
568ad13f387SMichael Pfeiffer ShowImageWindow::ToggleFullScreen()
569ad13f387SMichael Pfeiffer {
570ad13f387SMichael Pfeiffer 	BRect frame;
571ad13f387SMichael Pfeiffer 	fFullScreen = !fFullScreen;
572ad13f387SMichael Pfeiffer 	if (fFullScreen) {
573ad13f387SMichael Pfeiffer 		BScreen screen;
574ad13f387SMichael Pfeiffer 		fWindowFrame = Frame();
575ad13f387SMichael Pfeiffer 		frame = screen.Frame();
576ad13f387SMichael Pfeiffer 		frame.top -= fpBar->Bounds().Height()+1;
577ad13f387SMichael Pfeiffer 		frame.right += B_V_SCROLL_BAR_WIDTH;
578ad13f387SMichael Pfeiffer 		frame.bottom += B_H_SCROLL_BAR_HEIGHT;
579ad13f387SMichael Pfeiffer 		frame.InsetBy(-1, -1); // PEN_SIZE in ShowImageView
580ad13f387SMichael Pfeiffer 
581ad13f387SMichael Pfeiffer 		SetFlags(Flags() | B_NOT_RESIZABLE | B_NOT_MOVABLE);
582ad13f387SMichael Pfeiffer 	} else {
583ad13f387SMichael Pfeiffer 		frame = fWindowFrame;
584ad13f387SMichael Pfeiffer 
585ad13f387SMichael Pfeiffer 		SetFlags(Flags() & ~(B_NOT_RESIZABLE | B_NOT_MOVABLE));
586ad13f387SMichael Pfeiffer 	}
587ad13f387SMichael Pfeiffer 	MoveTo(frame.left, frame.top);
588ad13f387SMichael Pfeiffer 	ResizeTo(frame.Width(), frame.Height());
589ad13f387SMichael Pfeiffer }
590ad13f387SMichael Pfeiffer 
591cdb89ebbSMatthew Wilber bool
592cdb89ebbSMatthew Wilber ShowImageWindow::QuitRequested()
593cdb89ebbSMatthew Wilber {
594cdb89ebbSMatthew Wilber 	return CanQuit();
595cdb89ebbSMatthew Wilber }
596cdb89ebbSMatthew Wilber 
59707caaa8eSMatthew Wilber void
59807caaa8eSMatthew Wilber ShowImageWindow::Quit()
59907caaa8eSMatthew Wilber {
60007caaa8eSMatthew Wilber 	// tell the app to forget about this window
60107caaa8eSMatthew Wilber 	be_app->PostMessage(MSG_WINDOW_QUIT);
60207caaa8eSMatthew Wilber 	BWindow::Quit();
60307caaa8eSMatthew Wilber }
604fc0a275bSMatthew Wilber 
605