From d9f6762d46c0e7c25d011460bef442ec2d00bfe9 Mon Sep 17 00:00:00 2001 From: Michael Pfeiffer Date: Sun, 17 Dec 2006 15:18:32 +0000 Subject: [PATCH] Integrated "resize" feature from Zetas version of ShowImage, however used our bilinear scaler instead of Zetas implementation and made ResizerWindow font sensitive and removed the radio buttons with predefined sizes. Kudos to Bernd Korz for providing the ShowImage Zeta source code under MIT license. Moved menu item "As Desktop Background" into "Image" menu from "View" menu. Removed unused metod ShowImageWindow::Zoom(...). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19540 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/apps/showimage/Filter.cpp | 63 +++---- src/apps/showimage/ResizerWindow.cpp | 234 ++++++++++++++++++++++++ src/apps/showimage/ResizerWindow.h | 78 ++++++++ src/apps/showimage/ShowImageConstants.h | 3 + src/apps/showimage/ShowImageUndo.cpp | 9 +- src/apps/showimage/ShowImageView.cpp | 41 ++++- src/apps/showimage/ShowImageView.h | 7 + src/apps/showimage/ShowImageWindow.cpp | 124 ++++++++++--- src/apps/showimage/ShowImageWindow.h | 10 +- 9 files changed, 501 insertions(+), 68 deletions(-) create mode 100644 src/apps/showimage/ResizerWindow.cpp create mode 100644 src/apps/showimage/ResizerWindow.h diff --git a/src/apps/showimage/Filter.cpp b/src/apps/showimage/Filter.cpp index dbd78352f4..d63a087fcf 100644 --- a/src/apps/showimage/Filter.cpp +++ b/src/apps/showimage/Filter.cpp @@ -1,30 +1,14 @@ -/*****************************************************************************/ -// Filter -// Written by Michael Pfeiffer -// -// Filter.cpp -// -// -// Copyright (c) 2003-2005 Haiku Project -// -// Permission is hereby granted, free of charge, to any person obtaining a -// copy of this software and associated documentation files (the "Software"), -// to deal in the Software without restriction, including without limitation -// the rights to use, copy, modify, merge, publish, distribute, sublicense, -// and/or sell copies of the Software, and to permit persons to whom the -// Software is furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included -// in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS -// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -// DEALINGS IN THE SOFTWARE. -/*****************************************************************************/ +/* + * Copyright 2003-2006, Haiku. + * Copyright 2004-2005 yellowTAB GmbH. All Rights Reserverd. + * Copyright 2006 Bernd Korz. All Rights Reserved + * Distributed under the terms of the MIT License. + * + * Authors: + * Michael Pfeiffer, laplace@haiku-os.org + * yellowTAB GmbH + * Bernd Korz + */ #include #include @@ -275,13 +259,14 @@ Scaler::~Scaler() { if (GetDestImage() != fScaledImage) { delete fScaledImage; + fScaledImage = NULL; } } BBitmap* Scaler::CreateDestImage(BBitmap* srcImage) { - if (srcImage == NULL || srcImage->ColorSpace() != B_RGB32 && srcImage->ColorSpace() !=B_RGBA32) return NULL; + if (srcImage == NULL || srcImage->ColorSpace() != B_RGB32 && srcImage->ColorSpace() != B_RGBA32) return NULL; BRect dest(0, 0, fRect.IntegerWidth(), fRect.IntegerHeight()); BBitmap* destImage = new BBitmap(dest, fDither ? B_CMAP8 : srcImage->ColorSpace()); @@ -291,9 +276,10 @@ Scaler::CreateDestImage(BBitmap* srcImage) return NULL; } - if (fDither) { - BRect dest(0, 0, fRect.IntegerWidth(), fRect.IntegerHeight()); - fScaledImage = new BBitmap(dest, srcImage->ColorSpace()); + if (fDither) + { + BRect dest_rect(0, 0, fRect.IntegerWidth(), fRect.IntegerHeight()); + fScaledImage = new BBitmap(dest_rect, srcImage->ColorSpace()); if (!IsBitmapValid(fScaledImage)) { delete destImage; delete fScaledImage; @@ -404,6 +390,9 @@ Scaler::ScaleBilinear(intType fromRow, int32 toRow) destData[2] = static_cast( (a[2] * a0 + b[2] * a1) * alpha0 + (c[2] * a0 + d[2] * a1) * alpha1); + destData[3] = static_cast( + (a[3] * a0 + b[3] * a1) * alpha0 + + (c[3] * a0 + d[3] * a1) * alpha1); } // right column @@ -413,6 +402,7 @@ Scaler::ScaleBilinear(intType fromRow, int32 toRow) destData[0] = static_cast(a[0] * alpha0 + c[0] * alpha1); destData[1] = static_cast(a[1] * alpha0 + c[1] * alpha1); destData[2] = static_cast(a[2] * alpha0 + c[2] * alpha1); + destData[3] = static_cast(a[3] * alpha0 + c[3] * alpha1); } else { float a0, a1; const uchar *a, *b; @@ -426,6 +416,7 @@ Scaler::ScaleBilinear(intType fromRow, int32 toRow) destData[0] = static_cast(a[0] * a0 + b[0] * a1); destData[1] = static_cast(a[1] * a0 + b[1] * a1); destData[2] = static_cast(a[2] * a0 + b[2] * a1); + destData[3] = static_cast(a[3] * a0 + b[3] * a1); } // bottom, right pixel @@ -434,6 +425,7 @@ Scaler::ScaleBilinear(intType fromRow, int32 toRow) destData[0] = a[0]; destData[1] = a[1]; destData[2] = a[2]; + destData[3] = a[3]; } } @@ -538,6 +530,7 @@ Scaler::ScaleBilinearFP(intType fromRow, int32 toRow) destData[0] = I4(0); destData[1] = I4(1); destData[2] = I4(2); + destData[3] = I4(3); } // right column @@ -547,6 +540,7 @@ Scaler::ScaleBilinearFP(intType fromRow, int32 toRow) destData[0] = V2(0); destData[1] = V2(1); destData[2] = V2(2); + destData[3] = V2(3); } else { fixed_point a0, a1; const uchar *a, *b; @@ -560,6 +554,7 @@ Scaler::ScaleBilinearFP(intType fromRow, int32 toRow) destData[0] = H2(0); destData[1] = H2(1); destData[2] = H2(2); + destData[3] = H2(3); } // bottom, right pixel @@ -568,6 +563,7 @@ Scaler::ScaleBilinearFP(intType fromRow, int32 toRow) destData[0] = a[0]; destData[1] = a[1]; destData[2] = a[2]; + destData[3] = a[3]; } } @@ -915,8 +911,9 @@ void Scaler::Completed() { if (GetDestImage() != fScaledImage) { - delete fScaledImage; fScaledImage = NULL; + delete fScaledImage; } + fScaledImage = NULL; } // Implementation of ImageProcessor @@ -927,7 +924,7 @@ ImageProcessor::ImageProcessor(enum operation op, BBitmap* image, BMessenger lis } BBitmap* -ImageProcessor::CreateDestImage(BBitmap* srcImage) +ImageProcessor::CreateDestImage(BBitmap* /* srcImage */) { color_space cs; BBitmap* bm; diff --git a/src/apps/showimage/ResizerWindow.cpp b/src/apps/showimage/ResizerWindow.cpp new file mode 100644 index 0000000000..cdc341ba83 --- /dev/null +++ b/src/apps/showimage/ResizerWindow.cpp @@ -0,0 +1,234 @@ +/* + * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Copyright 2004-2005 yellowTAB GmbH. All Rights Reserverd. + * Copyright 2006 Bernd Korz. All Rights Reserved + * Distributed under the terms of the MIT License. + * + * Authors: + * yellowTAB GmbH + * Bernd Korz + * Michael Pfeiffer + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ResizerWindow.h" +#include "ShowImageConstants.h" + +static const char* kWidthLabel = "Width:"; +static const char* kHeightLabel = "Height:"; +static const char* kKeepAspectRatioLabel = "Keep Aspect Ratio"; +static const char* kApplyLabel = "Apply"; + +static const float kLineDistance = 5; +static const float kHorizontalIndent = 10; +static const float kVerticalIndent = 10; + +ResizerWindow::ResizerWindow(BMessenger target, float width, float height) + : BWindow(BRect(100, 100, 300, 300), "Resize", B_FLOATING_WINDOW, B_NOT_ZOOMABLE | B_NOT_RESIZABLE) + , fRatio(width / height) + , fTarget(target) +{ + BView* back_view = new BBox(Bounds(), "", B_FOLLOW_ALL); + AddChild(back_view); + + const float widthLabelWidth = back_view->StringWidth(kWidthLabel); + const float heightLabelWidth = back_view->StringWidth(kHeightLabel); + const float column2 = max_c(widthLabelWidth, heightLabelWidth); + + const float textControlWidth = column2 + back_view->StringWidth("999999"); + const float keepAspectRatioLabelWidth = back_view->StringWidth(kKeepAspectRatioLabel); + const float width = 2 * kHorizontalIndent + max_c(textControlWidth, keepAspectRatioLabelWidth); + + ResizeTo(width+1, Bounds().Height()+1); + + const float top = kVerticalIndent; + const float left = kHorizontalIndent; + BRect rect(left, top, width - kHorizontalIndent, top + 10); + + BString widthValue; + widthValue << (int)width; + fWidth = new BTextControl(rect, "width", kWidthLabel, widthValue.String(), NULL); + fWidth->SetModificationMessage(new BMessage(kWidthModifiedMsg)); + AddControl(back_view, fWidth, column2, rect); + + BString heightValue; + heightValue << (int)height; + fHeight = new BTextControl(rect, "height", kHeightLabel, heightValue.String(), NULL); + fHeight->SetModificationMessage(new BMessage(kHeightModifiedMsg)); + AddControl(back_view, fHeight, column2, rect); + + fAspectRatio = new BCheckBox(rect, "Ratio", kKeepAspectRatioLabel, new BMessage(kWidthModifiedMsg)); + fAspectRatio->SetValue(B_CONTROL_ON); + AddControl(back_view, fAspectRatio, column2, rect); + + AddSeparatorLine(back_view, rect); + + fApply = new BButton(rect, "apply", kApplyLabel, new BMessage(kApplyMsg)); + fApply->MakeDefault(true); + AddControl(back_view, fApply, column2, rect); + LeftAlign(fApply); + + fWidth->MakeFocus(); + + ResizeTo(width, rect.top); +} + +void +ResizerWindow::AddControl(BView* view, BControl* control, float column2, BRect& rect) +{ + float width, height; + view->AddChild(control); + control->GetPreferredSize(&width, &height); + if (dynamic_cast(control) != NULL) { + control->ResizeTo(width, height); + } else { + control->ResizeTo(control->Bounds().Width(), height); + } + float top = control->Frame().bottom + kLineDistance; + rect.OffsetTo(rect.left, top); + + if (dynamic_cast(control) != NULL) { + ((BTextControl*)control)->SetDivider(column2); + } +} + +void +ResizerWindow::AddSeparatorLine(BView* view, BRect& rect) +{ + const float lineWidth = 3; + BRect line(Bounds()); + line.left += 3; + line.right -= 3; + line.top = rect.top; + line.bottom = line.top + lineWidth - 1; + BBox* separatorLine = new BBox(line, "", B_FOLLOW_LEFT_RIGHT, B_WILL_DRAW | B_FRAME_EVENTS, B_PLAIN_BORDER); + view->AddChild(separatorLine); + rect.OffsetBy(0, kLineDistance + lineWidth); +} + +void +ResizerWindow::LeftAlign(BControl* control) +{ + BRect frame = control->Frame(); + float left = Bounds().Width() - frame.Width() - kHorizontalIndent; + control->MoveTo(left, frame.top); +} + +void +ResizerWindow::MessageReceived(BMessage* message) +{ + switch (message->what) + { + // public actions + case kActivateMsg: + Activate(); + break; + + case kUpdateMsg: + { + // update aspect ratio, width and height + float width, height; + if (message->FindFloat("width", &width) == B_OK && + message->FindFloat("height", &height) == B_OK) { + + fRatio = width / height; + + BString widthText, heightText; + widthText << (int)width; + heightText << (int)height; + // here the statement order is important: + // in case keep aspect ratio is enabled, + // the width should determine the height + fHeight->SetText(heightText.String()); + fWidth->SetText(widthText.String()); + } + break; + } + + // private actions + case kResolutionMsg: + { fAspectRatio->SetValue(B_CONTROL_OFF); + BString width, height; + width << message->FindInt32("w"); + height << message->FindInt32("h"); + fWidth->SetText(width.String()); + fHeight->SetText(height.String()); + break; + } + case kWidthModifiedMsg: + if (fAspectRatio->Value() == B_CONTROL_ON) + { + int w = atoi(fWidth->Text()); + int h = (int)(w / fRatio); + BString height; + height << h; + BMessage* msg = new BMessage(*fHeight->ModificationMessage()); + fHeight->SetModificationMessage(NULL); + fHeight->SetText(height.String()); + fHeight->SetModificationMessage(msg); + } + break; + case kHeightModifiedMsg: + if (fAspectRatio->Value() == B_CONTROL_ON) + { + int h = atoi(fHeight->Text()); + int w = (int)(h * fRatio); + BString width; + width << w; + BMessage* msg = new BMessage(*fWidth->ModificationMessage()); + fWidth->SetModificationMessage(NULL); + fWidth->SetText(width.String()); + fWidth->SetModificationMessage(msg); + } + break; + case kApplyMsg: + { + BMessage resizeRequest(MSG_RESIZE); + resizeRequest.AddInt32("h", atoi(fHeight->Text())); + resizeRequest.AddInt32("w", atoi(fWidth->Text())); + fTarget.SendMessage(&resizeRequest); + PostMessage(B_QUIT_REQUESTED); + break; + } + default: + BWindow::MessageReceived(message); + } +} + +ResizerWindow::~ResizerWindow() +{ +} + +bool +ResizerWindow::QuitRequested() +{ + fTarget.SendMessage(MSG_RESIZER_WINDOW_QUITED); + return true; +} diff --git a/src/apps/showimage/ResizerWindow.h b/src/apps/showimage/ResizerWindow.h new file mode 100644 index 0000000000..9e6614220d --- /dev/null +++ b/src/apps/showimage/ResizerWindow.h @@ -0,0 +1,78 @@ +/* + * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Copyright 2004-2005 yellowTAB GmbH. All Rights Reserverd. + * Copyright 2006 Bernd Korz. All Rights Reserved + * Distributed under the terms of the MIT License. + * + * Authors: + * yellowTAB GmbH + * Bernd Korz + * Michael Pfeiffer + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef _resizer_window_h +#define _resizer_window_h + +#include +#include + + +class BTextControl; +class BCheckBox; + +class ResizerWindow : public BWindow +{ + public: + ResizerWindow(BMessenger target, float width, float height ); + + virtual void MessageReceived(BMessage* msg); + virtual bool QuitRequested(); + + virtual ~ResizerWindow(); + + // the public message command constants ('what') + enum { + kActivateMsg = 'RSRa', + // activates the window + kUpdateMsg, + // provides the new size of the image in two float fields "width" and "height" + }; + private: + enum { + kResolutionMsg = 'Rszr', + kWidthModifiedMsg, + kHeightModifiedMsg, + kApplyMsg, + }; + + void AddControl(BView* parent, BControl* control, float column2, BRect& rect); + void AddSeparatorLine(BView* parent, BRect& rect); + void LeftAlign(BControl* control); + + BTextControl* fWidth; + BTextControl* fHeight; + BCheckBox* fAspectRatio; + BButton* fApply; + float fRatio; + BMessenger fTarget; +}; + +#endif diff --git a/src/apps/showimage/ShowImageConstants.h b/src/apps/showimage/ShowImageConstants.h index 46a8ca5d8c..d2091f31df 100644 --- a/src/apps/showimage/ShowImageConstants.h +++ b/src/apps/showimage/ShowImageConstants.h @@ -57,5 +57,8 @@ const uint32 MSG_ORIGINAL_SIZE = 'mOSZ'; const uint32 MSG_INVALIDATE = 'mIVD'; const uint32 MSG_SCALE_BILINEAR = 'mSBL'; const uint32 MSG_DESKTOP_BACKGROUND = 'mDBG'; +const uint32 MSG_OPEN_RESIZER_WINDOW = 'mORS'; +const uint32 MSG_RESIZER_WINDOW_QUITED = 'mRSQ'; +const uint32 MSG_RESIZE = 'mRSZ'; #endif // SHOW_IMAGE_CONSTANTS_H diff --git a/src/apps/showimage/ShowImageUndo.cpp b/src/apps/showimage/ShowImageUndo.cpp index d1ce6f5d7d..0ac787c1c5 100644 --- a/src/apps/showimage/ShowImageUndo.cpp +++ b/src/apps/showimage/ShowImageUndo.cpp @@ -28,6 +28,8 @@ #include "ShowImageUndo.h" +#include + ShowImageUndo::ShowImageUndo() { fWindow = NULL; @@ -62,10 +64,13 @@ void ShowImageUndo::SendUndoStateMessage(bool bCanUndo) { if (fWindow) { + if (!fWindow->IsLocked()) { + fprintf(stderr, "ShowImageUndo::SendUndoStateMessage: window must be locked!"); + exit(-1); + } BMessage msg(MSG_UNDO_STATE); msg.AddBool("can_undo", bCanUndo); - BMessenger msgr(fWindow); - msgr.SendMessage(&msg); + fWindow->PostMessage(&msg); } } diff --git a/src/apps/showimage/ShowImageView.cpp b/src/apps/showimage/ShowImageView.cpp index 0d996e4656..50b1c46cb6 100644 --- a/src/apps/showimage/ShowImageView.cpp +++ b/src/apps/showimage/ShowImageView.cpp @@ -1,11 +1,15 @@ /* * Copyright 2003-2006, Haiku, Inc. All Rights Reserved. + * Copyright 2004-2005 yellowTAB GmbH. All Rights Reserverd. + * Copyright 2006 Bernd Korz. All Rights Reserved * Distributed under the terms of the MIT License. * * Authors: * Fernando Francisco de Oliveira * Michael Wilber * Michael Pfeiffer + * yellowTAB GmbH + * Bernd Korz */ @@ -188,7 +192,7 @@ ShowImageView::ShowImageView(BRect rect, const char *name, uint32 resizingMode, fScaleBilinear = false; fScaler = NULL; #if DELAYED_SCALING - fScalingCountDown = 10; + fScalingCountDown = SCALING_DELAY_TIME; #endif if (settings->Lock()) { @@ -303,9 +307,11 @@ ShowImageView::Pulse() #if DELAYED_SCALING if (fBitmap && (fScaleBilinear || fDither) && fScalingCountDown > 0) { - fScalingCountDown --; - if (fScalingCountDown == 0) { + if (fScalingCountDown == 1) { + fScalingCountDown = 0; GetScaler(AlignBitmap()); + } else { + fScalingCountDown --; } } #endif @@ -383,7 +389,7 @@ ShowImageView::DeleteScaler() fScaler = NULL; } #if DELAYED_SCALING - fScalingCountDown = 3; // delay for 3/10 seconds + fScalingCountDown = SCALING_DELAY_TIME; #endif } @@ -1634,7 +1640,7 @@ ShowImageView::ShowPopUpMenu(BPoint screen) ShowImageWindow* showImage = dynamic_cast(Window()); if (showImage) - showImage->BuildViewMenu(menu); + showImage->BuildContextMenu(menu); screen -= BPoint(10, 10); menu->Go(screen, true, false, true); @@ -2427,6 +2433,31 @@ ShowImageView::Invert() } } +void +ShowImageView::ResizeImage(int w, int h) +{ + if (fBitmap == NULL || w < 1 || h < 1) + return; + + Scaler scaler(fBitmap, BRect(0, 0, w-1, h-1), BMessenger(), 0, false); + scaler.Start(false); + BBitmap* scaled = scaler.DetachBitmap(); + if (scaled == NULL) { + // operation failed + return; + } + + // remove selection + SetHasSelection(false); + fUndo.Clear(); + DeleteBitmap(); + fBitmap = scaled; + + BMessenger msgr(Window()); + msgr.SendMessage(MSG_MODIFIED); + + Notify(NULL); +} void ShowImageView::SetIcon(bool clear, icon_size which) diff --git a/src/apps/showimage/ShowImageView.h b/src/apps/showimage/ShowImageView.h index 8f3a20c9a8..269833afde 100644 --- a/src/apps/showimage/ShowImageView.h +++ b/src/apps/showimage/ShowImageView.h @@ -1,11 +1,15 @@ /* * Copyright 2003-2006, Haiku, Inc. All Rights Reserved. + * Copyright 2004-2005 yellowTAB GmbH. All Rights Reserverd. + * Copyright 2006 Bernd Korz. All Rights Reserved * Distributed under the terms of the MIT License. * * Authors: * Fernando Francisco de Oliveira * Michael Wilber * Michael Pfeiffer + * yellowTAB GmbH + * Bernd Korz */ #ifndef SHOW_IMAGE_VIEW_H #define SHOW_IMAGE_VIEW_H @@ -24,6 +28,8 @@ // delay scaling operation, so that a sequence of zoom in/out operations works smoother #define DELAYED_SCALING 1 +// the delay time in 1/10 seconds +#define SCALING_DELAY_TIME 3 // width of the black border stroked arround the bitmap #define PEN_SIZE 1.0f @@ -100,6 +106,7 @@ class ShowImageView : public BView { void Rotate(int degree); // 90 and 270 only void Flip(bool vertical); void Invert(); + void ResizeImage(int w, int h); void SetIcon(bool clear); diff --git a/src/apps/showimage/ShowImageWindow.cpp b/src/apps/showimage/ShowImageWindow.cpp index f013157a8f..c663c40da5 100644 --- a/src/apps/showimage/ShowImageWindow.cpp +++ b/src/apps/showimage/ShowImageWindow.cpp @@ -1,16 +1,21 @@ /* * Copyright 2003-2006, Haiku, Inc. All Rights Reserved. + * Copyright 2004-2005 yellowTAB GmbH. All Rights Reserverd. + * Copyright 2006 Bernd Korz. All Rights Reserved * Distributed under the terms of the MIT License. * * Authors: * Fernando Francisco de Oliveira * Michael Wilber * Michael Pfeiffer + * yellowTAB GmbH + * Bernd Korz */ #include "BackgroundImage.h" #include "EntryMenuItem.h" +#include "ResizerWindow.h" #include "ShowImageApp.h" #include "ShowImageConstants.h" #include "ShowImageStatusView.h" @@ -91,7 +96,8 @@ ShowImageWindow::ShowImageWindow(const entry_ref *ref, fPrintSettings = NULL; fImageView = NULL; fSlideShowDelay = NULL; - + fResizerWindowMessenger = NULL; + LoadSettings(); // create menu bar @@ -145,21 +151,7 @@ ShowImageWindow::ShowImageWindow(const entry_ref *ref, fImageView->SetImage(ref); fImageView->SetTrackerMessenger(trackerMessenger); - if (InitCheck() == B_OK) { - // add View menu here so it can access ShowImageView methods - BMenu* menu = new BMenu("View"); - BuildViewMenu(menu); - fBar->AddItem(menu); - MarkMenuItem(fBar, MSG_DITHER_IMAGE, fImageView->GetDither()); - UpdateTitle(); - - SetPulseRate(100000); - // every 1/10 second; ShowImageView needs it for marching ants - - WindowRedimension(fImageView->GetBitmap()); - fImageView->MakeFocus(true); // to receive KeyDown messages - Show(); - } else { + if (InitCheck() != B_OK) { BAlert* alert; alert = new BAlert("ShowImage", "Could not load image! Either the file or an image translator for it does not exist.", @@ -172,6 +164,20 @@ ShowImageWindow::ShowImageWindow(const entry_ref *ref, return; } + // add View menu here so it can access ShowImageView methods + BMenu* menu = new BMenu("View"); + BuildViewMenu(menu, false); + fBar->AddItem(menu); + MarkMenuItem(fBar, MSG_DITHER_IMAGE, fImageView->GetDither()); + UpdateTitle(); + + SetPulseRate(100000); + // every 1/10 second; ShowImageView needs it for marching ants + + WindowRedimension(fImageView->GetBitmap()); + fImageView->MakeFocus(true); // to receive KeyDown messages + Show(); + // Tell application object to query the clipboard // and tell this window if it contains interesting data or not be_app_messenger.SendMessage(B_CLIPBOARD_CHANGED); @@ -201,9 +207,14 @@ ShowImageWindow::UpdateTitle() SetTitle(path.String()); } +void +ShowImageWindow::BuildContextMenu(BMenu *menu) +{ + BuildViewMenu(menu, true); +} void -ShowImageWindow::BuildViewMenu(BMenu *menu) +ShowImageWindow::BuildViewMenu(BMenu *menu, bool popupMenu) { AddItemMenu(menu, "Slide Show", MSG_SLIDE_SHOW, 0, 0, 'W', true); MarkMenuItem(menu, MSG_SLIDE_SHOW, fImageView->SlideShowStarted()); @@ -265,10 +276,11 @@ ShowImageWindow::BuildViewMenu(BMenu *menu) EnableMenuItem(menu, MSG_ZOOM_IN, enabled); EnableMenuItem(menu, MSG_ZOOM_OUT, enabled); - menu->AddSeparatorItem(); + if (popupMenu) { + menu->AddSeparatorItem(); - AddItemMenu(menu, "As Desktop Background", MSG_DESKTOP_BACKGROUND, 0, 0, 'W', - true); + AddItemMenu(menu, "As Desktop Background", MSG_DESKTOP_BACKGROUND, 0, 0, 'W', true); + } } @@ -332,7 +344,11 @@ ShowImageWindow::AddMenus(BMenuBar *bar) AddItemMenu(menu, "Flip Top To Bottom", MSG_FLIP_TOP_TO_BOTTOM, 0, 0, 'W', true); menu->AddSeparatorItem(); AddItemMenu(menu, "Invert", MSG_INVERT, 0, 0, 'W', true); + menu->AddSeparatorItem(); + AddItemMenu(menu, "Resize " B_UTF8_ELLIPSIS, MSG_OPEN_RESIZER_WINDOW, 0, 0, 'W', true); bar->AddItem(menu); + menu->AddSeparatorItem(); + AddItemMenu(menu, "As Desktop Background", MSG_DESKTOP_BACKGROUND, 0, 0, 'W', true); } @@ -576,10 +592,12 @@ ShowImageWindow::MessageReceived(BMessage *message) EnableMenuItem(fBar, MSG_INVERT, (colors != B_CMAP8)); BString status; + bool messageProvidesSize = false; int32 width, height; if (message->FindInt32("width", &width) >= B_OK && message->FindInt32("height", &height) >= B_OK) { status << width << "x" << height << ", "; + messageProvidesSize = true; } BString str; @@ -587,6 +605,10 @@ ShowImageWindow::MessageReceived(BMessage *message) status << str; } + if (messageProvidesSize) { + UpdateResizerWindow(width, height); + } + fStatusView->SetText(status); UpdateTitle(); @@ -796,6 +818,24 @@ ShowImageWindow::MessageReceived(BMessage *message) fImageView->SetScaleBilinear(ToggleMenuItem(message->what)); break; + case MSG_OPEN_RESIZER_WINDOW: + if (fImageView->GetBitmap() != NULL) + { + BRect rect = fImageView->GetBitmap()->Bounds(); + OpenResizerWindow(rect.Width(), rect.Height()); + } + break; + case MSG_RESIZE: + { + int w = message->FindInt32("w"); + int h = message->FindInt32("h"); + fImageView->ResizeImage(w, h); + break; + } + case MSG_RESIZER_WINDOW_QUITED: + fResizerWindowMessenger = NULL; + break; + case MSG_DESKTOP_BACKGROUND: { BPath path; @@ -1098,7 +1138,43 @@ ShowImageWindow::Print(BMessage *msg) } } +void +ShowImageWindow::OpenResizerWindow(float width, float height) +{ + if (fResizerWindowMessenger == NULL) { + // open window if it is not already opened + BWindow* window = new ResizerWindow(this, width, height); + fResizerWindowMessenger = new BMessenger(window); + window->Show(); + } else + fResizerWindowMessenger->SendMessage(ResizerWindow::kActivateMsg); +} +void +ShowImageWindow::UpdateResizerWindow(float width, float height) +{ + if (fResizerWindowMessenger == NULL) { + // window not opened + return; + } + + BMessage updateMsg(ResizerWindow::kUpdateMsg); + updateMsg.AddFloat("width", width); + updateMsg.AddFloat("height", height); + fResizerWindowMessenger->SendMessage(&updateMsg); +} + +void +ShowImageWindow::CloseResizerWindow() +{ + if (fResizerWindowMessenger == NULL) { + // window not opened + return; + } + fResizerWindowMessenger->SendMessage(B_QUIT_REQUESTED); + fResizerWindowMessenger = NULL; +} + bool ShowImageWindow::QuitRequested() { @@ -1110,6 +1186,8 @@ ShowImageWindow::QuitRequested() bool quit = ClosePrompt(); if (quit) { + CloseResizerWindow(); + // tell the app to forget about this window be_app->PostMessage(MSG_WINDOW_QUIT); } @@ -1118,10 +1196,4 @@ ShowImageWindow::QuitRequested() } -void -ShowImageWindow::Zoom(BPoint origin, float width, float height) -{ - // just go into fullscreen - ToggleFullScreen(); -} diff --git a/src/apps/showimage/ShowImageWindow.h b/src/apps/showimage/ShowImageWindow.h index c122851e54..900990fd72 100644 --- a/src/apps/showimage/ShowImageWindow.h +++ b/src/apps/showimage/ShowImageWindow.h @@ -43,17 +43,18 @@ class ShowImageWindow : public BWindow { virtual void FrameResized(float width, float height); virtual void MessageReceived(BMessage *message); virtual bool QuitRequested(); - virtual void Zoom(BPoint origin, float width, float height); + // virtual void Zoom(BPoint origin, float width, float height); status_t InitCheck(); ShowImageView *GetShowImageView() const { return fImageView; } void UpdateTitle(); - void BuildViewMenu(BMenu *menu); void AddMenus(BMenuBar *bar); + void BuildContextMenu(BMenu *menu); void WindowRedimension(BBitmap *bitmap); private: + void BuildViewMenu(BMenu *menu, bool popupMenu); BMenuItem *AddItemMenu(BMenu *menu, char *caption, uint32 command, char shortcut, uint32 modifier, char target, bool enabled); @@ -76,6 +77,10 @@ class ShowImageWindow : public BWindow { bool PageSetup(); void PrepareForPrint(); void Print(BMessage *msg); + + void OpenResizerWindow(float width, float height); + void UpdateResizerWindow(float width, float height); + void CloseResizerWindow(); BFilePanel *fSavePanel; BMenuBar *fBar; @@ -91,6 +96,7 @@ class ShowImageWindow : public BWindow { bool fShowCaption; BMessage *fPrintSettings; PrintOptions fPrintOptions; + BMessenger* fResizerWindowMessenger; }; #endif // SHOW_IMAGE_WINDOW_H