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