Example #1
0
void
ShowImageWindow::MessageReceived(BMessage* message)
{
	if (message->WasDropped()) {
		uint32 type;
		int32 count;
		status_t status = message->GetInfo("refs", &type, &count);
		if (status == B_OK && type == B_REF_TYPE) {
			message->what = B_REFS_RECEIVED;
			be_app->PostMessage(message);
		}
	}

	switch (message->what) {
		case kMsgImageCacheImageLoaded:
		{
			fProgressWindow->Stop();

			BitmapOwner* bitmapOwner = NULL;
			message->FindPointer("bitmapOwner", (void**)&bitmapOwner);

			bool first = fImageView->Bitmap() == NULL;
			entry_ref ref;
			message->FindRef("ref", &ref);
			if (!first && ref != fNavigator.CurrentRef()) {
				// ignore older images
				if (bitmapOwner != NULL)
					bitmapOwner->ReleaseReference();
				break;
			}

			int32 page = message->FindInt32("page");
			int32 pageCount = message->FindInt32("pageCount");
			if (!first && page != fNavigator.CurrentPage()) {
				// ignore older pages
				if (bitmapOwner != NULL)
					bitmapOwner->ReleaseReference();
				break;
			}

			status_t status = fImageView->SetImage(message);
			if (status != B_OK) {
				if (bitmapOwner != NULL)
					bitmapOwner->ReleaseReference();

				_LoadError(ref);

				// quit if file could not be opened
				if (first)
					Quit();
				break;
			}

			fImageType = message->FindString("type");
			fNavigator.SetTo(ref, page, pageCount);

			fImageView->FitToBounds();
			if (first) {
				fImageView->MakeFocus(true);
					// to receive key messages
				Show();
			}
			_UpdateRatingMenu();
			// Set width and height attributes of the currently showed file.
			// This should only be a temporary solution.
			_SaveWidthAndHeight();
			break;
		}

		case kMsgImageCacheProgressUpdate:
		{
			entry_ref ref;
			if (message->FindRef("ref", &ref) == B_OK
				&& ref == fNavigator.CurrentRef()) {
				message->what = kMsgProgressUpdate;
				fProgressWindow->PostMessage(message);
			}
			break;
		}

		case MSG_MODIFIED:
			// If image has been modified due to a Cut or Paste
			fModified = true;
			break;

		case MSG_OUTPUT_TYPE:
			// User clicked Save As then choose an output format
			if (!fSavePanel)
				// If user doesn't already have a save panel open
				_SaveAs(message);
			break;

		case MSG_SAVE_PANEL:
			// User specified where to save the output image
			_SaveToFile(message);
			break;

		case B_CANCEL:
			delete fSavePanel;
			fSavePanel = NULL;
			break;

		case MSG_UPDATE_STATUS:
		{
			int32 pages = fNavigator.PageCount();
			int32 currentPage = fNavigator.CurrentPage();

			_EnableMenuItem(fBar, MSG_PAGE_FIRST,
				fNavigator.HasPreviousPage());
			_EnableMenuItem(fBar, MSG_PAGE_LAST, fNavigator.HasNextPage());
			_EnableMenuItem(fBar, MSG_PAGE_NEXT, fNavigator.HasNextPage());
			_EnableMenuItem(fBar, MSG_PAGE_PREV, fNavigator.HasPreviousPage());
			fGoToPageMenu->SetEnabled(pages > 1);

			_EnableMenuItem(fBar, MSG_FILE_NEXT, fNavigator.HasNextFile());
			_EnableMenuItem(fBar, MSG_FILE_PREV, fNavigator.HasPreviousFile());

			if (fGoToPageMenu->CountItems() != pages) {
				// Only rebuild the submenu if the number of
				// pages is different

				while (fGoToPageMenu->CountItems() > 0) {
					// Remove all page numbers
					delete fGoToPageMenu->RemoveItem((int32)0);
				}

				for (int32 i = 1; i <= pages; i++) {
					// Fill Go To page submenu with an entry for each page
					BMessage* goTo = new BMessage(MSG_GOTO_PAGE);
					goTo->AddInt32("page", i);

					char shortcut = 0;
					if (i < 10)
						shortcut = '0' + i;

					BString strCaption;
					strCaption << i;

					BMenuItem* item = new BMenuItem(strCaption.String(), goTo,
						shortcut, B_SHIFT_KEY);
					if (currentPage == i)
						item->SetMarked(true);
					fGoToPageMenu->AddItem(item);
				}
			} else {
				// Make sure the correct page is marked
				BMenuItem* currentItem = fGoToPageMenu->ItemAt(currentPage - 1);
				if (currentItem != NULL && !currentItem->IsMarked())
					currentItem->SetMarked(true);
			}

			_UpdateStatusText(message);

			BPath path(fImageView->Image());
			SetTitle(path.Path());
			break;
		}

		case MSG_UPDATE_STATUS_TEXT:
		{
			_UpdateStatusText(message);
			break;
		}

		case MSG_SELECTION:
		{
			// The view sends this message when a selection is
			// made or the selection is cleared so that the window
			// can update the state of the appropriate menu items
			bool enable;
			if (message->FindBool("has_selection", &enable) == B_OK) {
				_EnableMenuItem(fBar, B_COPY, enable);
				_EnableMenuItem(fBar, MSG_CLEAR_SELECT, enable);
			}
			break;
		}

		case B_COPY:
			fImageView->CopySelectionToClipboard();
			break;

		case MSG_SELECTION_MODE:
		{
			bool selectionMode = _ToggleMenuItem(MSG_SELECTION_MODE);
			fImageView->SetSelectionMode(selectionMode);
			if (!selectionMode)
				fImageView->ClearSelection();
			break;
		}

		case MSG_CLEAR_SELECT:
			fImageView->ClearSelection();
			break;

		case MSG_SELECT_ALL:
			fImageView->SelectAll();
			break;

		case MSG_PAGE_FIRST:
			if (_ClosePrompt() && fNavigator.FirstPage())
				_LoadImage();
			break;

		case MSG_PAGE_LAST:
			if (_ClosePrompt() && fNavigator.LastPage())
				_LoadImage();
			break;

		case MSG_PAGE_NEXT:
			if (_ClosePrompt() && fNavigator.NextPage())
				_LoadImage();
			break;

		case MSG_PAGE_PREV:
			if (_ClosePrompt() && fNavigator.PreviousPage())
				_LoadImage();
			break;

		case MSG_GOTO_PAGE:
		{
			if (!_ClosePrompt())
				break;

			int32 newPage;
			if (message->FindInt32("page", &newPage) != B_OK)
				break;

			int32 currentPage = fNavigator.CurrentPage();
			int32 pages = fNavigator.PageCount();

			// TODO: use radio mode instead!
			if (newPage > 0 && newPage <= pages) {
				BMenuItem* currentItem = fGoToPageMenu->ItemAt(currentPage - 1);
				BMenuItem* newItem = fGoToPageMenu->ItemAt(newPage - 1);
				if (currentItem != NULL && newItem != NULL) {
					currentItem->SetMarked(false);
					newItem->SetMarked(true);
					if (fNavigator.GoToPage(newPage))
						_LoadImage();
				}
			}
			break;
		}

		case kMsgFitToWindow:
			fImageView->FitToBounds();
			break;

		case kMsgStretchToWindow:
			fImageView->SetStretchToBounds(
				_ToggleMenuItem(kMsgStretchToWindow));
			break;

		case MSG_FILE_PREV:
			if (_ClosePrompt() && fNavigator.PreviousFile())
				_LoadImage(false);
			break;

		case MSG_FILE_NEXT:
		case kMsgNextSlide:
			if (_ClosePrompt() && fNavigator.NextFile())
				_LoadImage();
			break;

		case kMsgDeleteCurrentFile:
		{
			if (fNavigator.MoveFileToTrash())
				_LoadImage();
			else
				PostMessage(B_QUIT_REQUESTED);
			break;
		}

		case MSG_ROTATE_90:
			fImageView->Rotate(90);
			break;

		case MSG_ROTATE_270:
			fImageView->Rotate(270);
			break;

		case MSG_FLIP_LEFT_TO_RIGHT:
			fImageView->Flip(true);
			break;

		case MSG_FLIP_TOP_TO_BOTTOM:
			fImageView->Flip(false);
			break;

		case MSG_SLIDE_SHOW:
		{
			bool fullScreen = false;
			message->FindBool("full screen", &fullScreen);

			BMenuItem* item = fBar->FindItem(message->what);
			if (item == NULL)
				break;

			if (item->IsMarked()) {
				item->SetMarked(false);
				_StopSlideShow();
				fToolBar->SetActionPressed(MSG_SLIDE_SHOW, false);
			} else if (_ClosePrompt()) {
				item->SetMarked(true);
				if (!fFullScreen && fullScreen)
					_ToggleFullScreen();
				_StartSlideShow();
				fToolBar->SetActionPressed(MSG_SLIDE_SHOW, true);
			}
			break;
		}

		case kMsgStopSlideShow:
		{
			BMenuItem* item = fBar->FindItem(MSG_SLIDE_SHOW);
			if (item != NULL)
				item->SetMarked(false);

			_StopSlideShow();
			fToolBar->SetActionPressed(MSG_SLIDE_SHOW, false);
			break;
		}

		case MSG_SLIDE_SHOW_DELAY:
		{
			bigtime_t delay;
			if (message->FindInt64("delay", &delay) == B_OK) {
				_SetSlideShowDelay(delay);
				// in case message is sent from popup menu
				_MarkSlideShowDelay(delay);
			}
			break;
		}

		case MSG_FULL_SCREEN:
			_ToggleFullScreen();
			break;

		case MSG_EXIT_FULL_SCREEN:
			if (fFullScreen)
				_ToggleFullScreen();
			break;

		case MSG_SHOW_CAPTION:
		{
			fShowCaption = _ToggleMenuItem(message->what);
			ShowImageSettings* settings = my_app->Settings();

			if (settings->Lock()) {
				settings->SetBool("ShowCaption", fShowCaption);
				settings->Unlock();
			}
			if (fFullScreen)
				fImageView->SetShowCaption(fShowCaption);
		}	break;

		case MSG_PAGE_SETUP:
			_PageSetup();
			break;

		case MSG_PREPARE_PRINT:
			_PrepareForPrint();
			break;

		case MSG_PRINT:
			_Print(message);
			break;

		case MSG_ZOOM_IN:
			fImageView->ZoomIn();
			break;

		case MSG_ZOOM_OUT:
			fImageView->ZoomOut();
			break;

		case MSG_UPDATE_STATUS_ZOOM:
			fStatusView->SetZoom(fImageView->Zoom());
			break;

		case kMsgOriginalSize:
			if (message->FindInt32("behavior") == BButton::B_TOGGLE_BEHAVIOR) {
				bool force = (message->FindInt32("be:value") == B_CONTROL_ON);
				fImageView->ForceOriginalSize(force);
				if (!force)
					break;
			}
			fImageView->SetZoom(1.0);
			break;

		case MSG_SCALE_BILINEAR:
			fImageView->SetScaleBilinear(_ToggleMenuItem(message->what));
			break;

		case MSG_DESKTOP_BACKGROUND:
		{
			BMessage backgroundsMessage(B_REFS_RECEIVED);
			backgroundsMessage.AddRef("refs", fImageView->Image());
			// This is used in the Backgrounds code for scaled placement
			backgroundsMessage.AddInt32("placement", 'scpl');
			be_roster->Launch("application/x-vnd.haiku-backgrounds",
				&backgroundsMessage);
			break;
		}

		case MSG_SET_RATING:
		{
			int32 rating;
			if (message->FindInt32("rating", &rating) != B_OK)
				break;
			BFile file(&fNavigator.CurrentRef(), B_WRITE_ONLY);
			if (file.InitCheck() != B_OK)
				break;
			file.WriteAttr("Media:Rating", B_INT32_TYPE, 0, &rating,
				sizeof(rating));
			_UpdateRatingMenu();
			break;
		}

		case kMsgToggleToolBar:
		{
			fShowToolBar = _ToggleMenuItem(message->what);
			_SetToolBarVisible(fShowToolBar, true);

			ShowImageSettings* settings = my_app->Settings();

			if (settings->Lock()) {
				settings->SetBool("ShowToolBar", fShowToolBar);
				settings->Unlock();
			}
			break;
		}
		case kShowToolBarIfEnabled:
		{
			bool show;
			if (message->FindBool("show", &show) != B_OK)
				break;
			_SetToolBarVisible(fShowToolBar && show, true);
			break;
		}
		case kMsgSlideToolBar:
		{
			float offset;
			if (message->FindFloat("offset", &offset) == B_OK) {
				fToolBar->MoveBy(0, offset);
				fScrollView->ResizeBy(0, -offset);
				fScrollView->MoveBy(0, offset);
				UpdateIfNeeded();
				snooze(15000);
			}
			break;
		}
		case kMsgFinishSlidingToolBar:
		{
			float offset;
			bool show;
			if (message->FindFloat("offset", &offset) == B_OK
				&& message->FindBool("show", &show) == B_OK) {
				// Compensate rounding errors with the final placement
				fToolBar->MoveTo(fToolBar->Frame().left, offset);
				if (!show)
					fToolBar->Hide();
				BRect frame = fToolBar->Parent()->Bounds();
				frame.top = fToolBar->Frame().bottom + 1;
				fScrollView->MoveTo(fScrollView->Frame().left, frame.top);
				fScrollView->ResizeTo(fScrollView->Bounds().Width(),
					frame.Height() + 1);
			}
			break;
		}

		default:
			BWindow::MessageReceived(message);
			break;
	}
}
Example #2
0
void
ShowImageWindow::MessageReceived(BMessage *message)
{
	switch (message->what) {
		case MSG_MODIFIED:
			// If image has been modified due to a Cut or Paste
			fModified = true;
			break;

		case MSG_OUTPUT_TYPE:
			// User clicked Save As then choose an output format
			if (!fSavePanel)
				// If user doesn't already have a save panel open
				_SaveAs(message);
			break;

		case MSG_SAVE_PANEL:
			// User specified where to save the output image
			_SaveToFile(message);
			break;

		case B_CANCEL:
			delete fSavePanel;
			fSavePanel = NULL;
			break;

		case MSG_UPDATE_STATUS: {
			int32 pages = fImageView->PageCount();
			int32 curPage = fImageView->CurrentPage();

			bool benable = (pages > 1) ? true : false;
			_EnableMenuItem(fBar, MSG_PAGE_FIRST, benable);
			_EnableMenuItem(fBar, MSG_PAGE_LAST, benable);
			_EnableMenuItem(fBar, MSG_PAGE_NEXT, benable);
			_EnableMenuItem(fBar, MSG_PAGE_PREV, benable);

			_EnableMenuItem(fBar, MSG_FILE_NEXT, fImageView->HasNextFile());
			_EnableMenuItem(fBar, MSG_FILE_PREV, fImageView->HasPrevFile());

			if (fGoToPageMenu->CountItems() != pages) {
				// Only rebuild the submenu if the number of
				// pages is different

				while (fGoToPageMenu->CountItems() > 0)
					// Remove all page numbers
					delete fGoToPageMenu->RemoveItem(0L);

				for (int32 i = 1; i <= pages; i++) {
					// Fill Go To page submenu with an entry for each page
					BMessage *pgomsg = new BMessage(MSG_GOTO_PAGE);
					pgomsg->AddInt32("page", i);

					char shortcut = 0;
					if (i < 10) {
						shortcut = '0' + i;
					} else if (i == 10) {
						shortcut = '0';
					}

					BString strCaption;
					strCaption << i;

					BMenuItem *item = new BMenuItem(strCaption.String(), pgomsg,
						shortcut);
					if (curPage == i)
						item->SetMarked(true);
					fGoToPageMenu->AddItem(item);
				}
			} else {
				// Make sure the correct page is marked
				BMenuItem *pcurItem;
				pcurItem = fGoToPageMenu->ItemAt(curPage - 1);
				if (!pcurItem->IsMarked()) {
					pcurItem->SetMarked(true);
				}
			}

			// Disable the Invert menu item if the bitmap color space
			// is B_CMAP8. (B_CMAP8 is currently unsupported by the
			// invert algorithm)
			color_space colors = B_NO_COLOR_SPACE;
			message->FindInt32("colors", reinterpret_cast<int32 *>(&colors));
			_EnableMenuItem(fBar, MSG_INVERT, (colors != B_CMAP8));

			BString status;
			bool messageProvidesSize = false;
			if (message->FindInt32("width", &fWidth) >= B_OK
				&& message->FindInt32("height", &fHeight) >= B_OK) {
				status << fWidth << "x" << fHeight;
				messageProvidesSize = true;
			}

			BString str;
			if (message->FindString("status", &str) == B_OK && str.Length() > 0) {
				if (status.Length() > 0)
					status << ", ";
				status << str;
			}

			if (messageProvidesSize) {
				_UpdateResizerWindow(fWidth, fHeight);
				if (!fImageView->GetZoomToBounds()
					&& !fImageView->GetShrinkToBounds()
					&& !fFullScreen)
					WindowRedimension(fImageView->GetBitmap());
			}

			fStatusView->SetText(status);

			UpdateTitle();
		}	break;

		case MSG_UPDATE_STATUS_TEXT: {
			BString status;
			status << fWidth << "x" << fHeight;
			BString str;
			if (message->FindString("status", &str) == B_OK && str.Length() > 0) {
				status << ", " << str;
				fStatusView->SetText(status);
			}
		}	break;

		case MSG_SELECTION: {
			// The view sends this message when a selection is
			// made or the selection is cleared so that the window
			// can update the state of the appropriate menu items
			bool benable;
			if (message->FindBool("has_selection", &benable) == B_OK) {
				_EnableMenuItem(fBar, B_CUT, benable);
				_EnableMenuItem(fBar, B_COPY, benable);
				_EnableMenuItem(fBar, MSG_CLEAR_SELECT, benable);
			}
		}	break;

		case MSG_UNDO_STATE: {
			bool benable;
			if (message->FindBool("can_undo", &benable) == B_OK)
				_EnableMenuItem(fBar, B_UNDO, benable);
		}	break;

		case MSG_CLIPBOARD_CHANGED: {
			// The app sends this message after it examines the clipboard in
			// response to a B_CLIPBOARD_CHANGED message
			bool bdata;
			if (message->FindBool("data_available", &bdata) == B_OK)
				_EnableMenuItem(fBar, B_PASTE, bdata);
		}	break;

		case B_UNDO:
			fImageView->Undo();
			break;

		case B_CUT:
			fImageView->Cut();
			break;

		case B_COPY:
			fImageView->CopySelectionToClipboard();
			break;

		case B_PASTE:
			fImageView->Paste();
			break;

		case MSG_CLEAR_SELECT:
			fImageView->ClearSelection();
			break;

		case MSG_SELECT_ALL:
			fImageView->SelectAll();
			break;

		case MSG_PAGE_FIRST:
			if (_ClosePrompt())
				fImageView->FirstPage();
			break;

		case MSG_PAGE_LAST:
			if (_ClosePrompt())
				fImageView->LastPage();
			break;

		case MSG_PAGE_NEXT:
			if (_ClosePrompt())
				fImageView->NextPage();
			break;

		case MSG_PAGE_PREV:
			if (_ClosePrompt())
				fImageView->PrevPage();
			break;

		case MSG_GOTO_PAGE: {
			if (!_ClosePrompt())
				break;

			int32 newPage;
			if (message->FindInt32("page", &newPage) != B_OK)
				break;

			int32 curPage = fImageView->CurrentPage();
			int32 pages = fImageView->PageCount();

			if (newPage > 0 && newPage <= pages) {
				BMenuItem* pcurItem = fGoToPageMenu->ItemAt(curPage - 1);
				BMenuItem* pnewItem = fGoToPageMenu->ItemAt(newPage - 1);
				if (pcurItem && pnewItem) {
					pcurItem->SetMarked(false);
					pnewItem->SetMarked(true);
					fImageView->GoToPage(newPage);
				}
			}
		}	break;

		case MSG_DITHER_IMAGE:
			fImageView->SetDither(_ToggleMenuItem(message->what));
			break;

		case MSG_SHRINK_TO_WINDOW:
			_ResizeToWindow(true, message->what);
			break;

		case MSG_ZOOM_TO_WINDOW:
			_ResizeToWindow(false, message->what);
			break;

		case MSG_FILE_PREV:
			if (_ClosePrompt())
				fImageView->PrevFile();
			break;

		case MSG_FILE_NEXT:
			if (_ClosePrompt())
				fImageView->NextFile();
			break;

		case MSG_ROTATE_90:
			fImageView->Rotate(90);
			break;

		case MSG_ROTATE_270:
			fImageView->Rotate(270);
			break;

		case MSG_FLIP_LEFT_TO_RIGHT:
			fImageView->Flip(true);
			break;

		case MSG_FLIP_TOP_TO_BOTTOM:
			fImageView->Flip(false);
			break;

		case MSG_INVERT:
			fImageView->Invert();
			break;

		case MSG_SLIDE_SHOW: {
			BMenuItem *item = fBar->FindItem(message->what);
			if (!item)
				break;
			if (item->IsMarked()) {
				item->SetMarked(false);
				fResizeItem->SetEnabled(true);
				fImageView->StopSlideShow();
			} else if (_ClosePrompt()) {
				item->SetMarked(true);
				fResizeItem->SetEnabled(false);
				fImageView->StartSlideShow();
			}
		}	break;

		case MSG_SLIDE_SHOW_DELAY: {
			float value;
			if (message->FindFloat("value", &value) == B_OK) {
				fImageView->SetSlideShowDelay(value);
				// in case message is sent from popup menu
				_MarkSlideShowDelay(value);
			}
		}	break;

		case MSG_FULL_SCREEN:
			_ToggleFullScreen();
			break;

		case MSG_EXIT_FULL_SCREEN:
			if (fFullScreen)
				_ToggleFullScreen();
			break;

		case MSG_SHOW_CAPTION: {
			fShowCaption = _ToggleMenuItem(message->what);
			ShowImageSettings* settings = my_app->Settings();

			if (settings->Lock()) {
				settings->SetBool("ShowCaption", fShowCaption);
				settings->Unlock();
			}
			if (fFullScreen)
				fImageView->SetShowCaption(fShowCaption);
		}	break;

		case MSG_PAGE_SETUP:
			_PageSetup();
			break;

		case MSG_PREPARE_PRINT:
			_PrepareForPrint();
			break;

		case MSG_PRINT:
			_Print(message);
			break;

		case MSG_ZOOM_IN:
			fImageView->ZoomIn();
			break;

		case MSG_ZOOM_OUT:
			fImageView->ZoomOut();
			break;

		case MSG_ORIGINAL_SIZE:
			fImageView->SetZoom(1.0);
			break;

		case MSG_SCALE_BILINEAR:
			fImageView->SetScaleBilinear(_ToggleMenuItem(message->what));
			break;

		case MSG_OPEN_RESIZER_WINDOW: {
			if (fImageView->GetBitmap() != NULL) {
				BRect rect = fImageView->GetBitmap()->Bounds();
				_OpenResizerWindow(rect.IntegerWidth()+1, rect.IntegerHeight()+1);
			}
		}	break;

		case MSG_RESIZE: {
			int w = message->FindInt32("w");
			int h = message->FindInt32("h");
			fImageView->ResizeImage(w, h);
		} break;

		case MSG_RESIZER_WINDOW_QUIT:
			delete fResizerWindowMessenger;
			fResizerWindowMessenger = NULL;
			break;

		case MSG_DESKTOP_BACKGROUND: {
			BMessage message(B_REFS_RECEIVED);
			message.AddRef("refs", fImageView->Image());
			// This is used in the Backgrounds code for scaled placement
			message.AddInt32("placement", 'scpl');
			be_roster->Launch("application/x-vnd.antares-backgrounds", &message);
		}	break;

		default:
			BWindow::MessageReceived(message);
			break;
	}
}
Example #3
0
void
ShowImageWindow::Zoom(BPoint origin, float width, float height)
{
	_ToggleFullScreen();
}