Added initial implementation of Undo for OBOS ShowImage! Now, users can Undo/Redo merge/paste operations. Still need to enhance Undo further so that other operations can be undone, also need to account for image rotations and similar operations.
git-svn-id: file:///srv/svn/repos/haiku/trunk/current@5693 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -6,6 +6,7 @@ App ShowImage : ShowImageApp.cpp
|
||||
ShowImageConstants.cpp
|
||||
ShowImageSettings.cpp
|
||||
ShowImageStatusView.cpp
|
||||
ShowImageUndo.cpp
|
||||
ShowImageView.cpp
|
||||
ShowImageWindow.cpp
|
||||
PrintOptionsWindow.cpp
|
||||
|
||||
@@ -44,6 +44,7 @@ const uint32 MSG_CLIPBOARD_CHANGED = 'mCLP';
|
||||
const uint32 MSG_DITHER_IMAGE = 'mDIM';
|
||||
const uint32 MSG_MODIFIED = 'mMOD';
|
||||
const uint32 MSG_UPDATE_STATUS = 'mUPS';
|
||||
const uint32 MSG_UNDO_STATE = 'mUNS';
|
||||
const uint32 MSG_SELECTION = 'mSEL';
|
||||
const uint32 MSG_SELECTION_BITMAP = 'mSBT';
|
||||
const uint32 MSG_PAGE_FIRST = 'mPGF';
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
/*****************************************************************************/
|
||||
// ShowImageUndo
|
||||
// Written by Michael Wilber
|
||||
//
|
||||
// ShowImageUndo.cpp
|
||||
//
|
||||
//
|
||||
// Copyright (c) 2003 OpenBeOS 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#include "ShowImageUndo.h"
|
||||
|
||||
ShowImageUndo::ShowImageUndo()
|
||||
{
|
||||
fWindow = NULL;
|
||||
fUndoType = 0;
|
||||
fRestore = NULL;
|
||||
fSelection = NULL;
|
||||
}
|
||||
|
||||
ShowImageUndo::~ShowImageUndo()
|
||||
{
|
||||
InternalClear();
|
||||
}
|
||||
|
||||
void
|
||||
ShowImageUndo::InternalClear()
|
||||
{
|
||||
fUndoType = 0;
|
||||
delete fRestore;
|
||||
fRestore = NULL;
|
||||
delete fSelection;
|
||||
fSelection = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
ShowImageUndo::Clear()
|
||||
{
|
||||
InternalClear();
|
||||
SendUndoStateMessage(false);
|
||||
}
|
||||
|
||||
void
|
||||
ShowImageUndo::SendUndoStateMessage(bool bCanUndo)
|
||||
{
|
||||
if (fWindow) {
|
||||
BMessage msg(MSG_UNDO_STATE);
|
||||
msg.AddBool("can_undo", bCanUndo);
|
||||
BMessenger msgr(fWindow);
|
||||
msgr.SendMessage(&msg);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ShowImageUndo::SetTo(BRect rect, BBitmap *restore, BBitmap *selection)
|
||||
{
|
||||
// NOTE: THIS FUNCTION DOES NOT MAKE COPIES OF THE BITMAPS PASSED TO IT
|
||||
InternalClear();
|
||||
|
||||
fUndoType = UNDO_UNDO;
|
||||
fRect = rect;
|
||||
fRestore = restore;
|
||||
fSelection = selection;
|
||||
|
||||
SendUndoStateMessage(true);
|
||||
}
|
||||
|
||||
void
|
||||
ShowImageUndo::Undo(BRect rect, BBitmap *restore, BBitmap *selection)
|
||||
{
|
||||
// NOTE: THIS FUNCTION DOES NOT MAKE COPIES OF THE BITMAPS PASSED TO IT
|
||||
fUndoType = UNDO_REDO;
|
||||
fRect = rect;
|
||||
delete fRestore;
|
||||
fRestore = restore;
|
||||
fSelection = selection;
|
||||
// NOTE: fSelection isn't deleted here because ShowImageView
|
||||
// takes ownership of it during an Undo
|
||||
}
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/*****************************************************************************/
|
||||
// ShowImageUndo
|
||||
// Written by Michael Wilber
|
||||
//
|
||||
// ShowImageUndo.h
|
||||
//
|
||||
//
|
||||
// Copyright (c) 2003 OpenBeOS 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.
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifndef _ShowImageUndo_h
|
||||
#define _ShowImageUndo_h
|
||||
|
||||
#include <Rect.h>
|
||||
#include <Bitmap.h>
|
||||
#include <Window.h>
|
||||
#include <Message.h>
|
||||
#include <Messenger.h>
|
||||
#include "ShowImageConstants.h"
|
||||
|
||||
// for Undo
|
||||
#define UNDO_UNDO 1
|
||||
#define UNDO_REDO 2
|
||||
|
||||
class ShowImageUndo {
|
||||
public:
|
||||
ShowImageUndo();
|
||||
~ShowImageUndo();
|
||||
|
||||
void SetWindow(BWindow *win) { fWindow = win; }
|
||||
|
||||
void Clear();
|
||||
|
||||
// NOTE: THESE TWO FUNCTIONS DO NOT MAKE COPIES OF THE
|
||||
// BITMAPS PASSED TO THEM
|
||||
void SetTo(BRect rect, BBitmap *restore, BBitmap *selection);
|
||||
void Undo(BRect rect, BBitmap *restore, BBitmap *selection);
|
||||
|
||||
int32 GetType() { return fUndoType; }
|
||||
BRect GetRect() { return fRect; }
|
||||
BBitmap *GetRestoreBitmap() { return fRestore; }
|
||||
BBitmap *GetSelectionBitmap() { return fSelection; }
|
||||
|
||||
private:
|
||||
void InternalClear();
|
||||
void SendUndoStateMessage(bool bCanUndo);
|
||||
|
||||
BWindow *fWindow;
|
||||
// Window to which notification messages are sent
|
||||
int32 fUndoType;
|
||||
// Nothing, Undo or Redo
|
||||
BRect fRect;
|
||||
// Area of background bitmap where change took place
|
||||
BBitmap *fRestore;
|
||||
// Changed portion of background bitmap, before change took place
|
||||
BBitmap *fSelection;
|
||||
// Selection present before change took place
|
||||
};
|
||||
|
||||
#endif /* _ShowImageUndo_h */
|
||||
|
||||
@@ -299,6 +299,7 @@ void ShowImageView::DeleteSelBitmap()
|
||||
void
|
||||
ShowImageView::SetImage(const entry_ref *pref)
|
||||
{
|
||||
fUndo.Clear();
|
||||
DeleteBitmap();
|
||||
SetHasSelection(false);
|
||||
fMakesSelection = false;
|
||||
@@ -509,6 +510,7 @@ ShowImageView::SetScaleBilinear(bool s)
|
||||
void
|
||||
ShowImageView::AttachedToWindow()
|
||||
{
|
||||
fUndo.SetWindow(Window());
|
||||
FixupScrollBars();
|
||||
}
|
||||
|
||||
@@ -814,6 +816,25 @@ ShowImageView::ConstrainToImage(BRect &rect)
|
||||
rect.SetRightBottom(rightBottom);
|
||||
}
|
||||
|
||||
BBitmap*
|
||||
ShowImageView::CopyFromRect(BRect srcRect)
|
||||
{
|
||||
BRect rect(0, 0, srcRect.Width(), srcRect.Height());
|
||||
BView view(rect, NULL, B_FOLLOW_NONE, B_WILL_DRAW);
|
||||
BBitmap *bitmap = new BBitmap(rect, fBitmap->ColorSpace(), true);
|
||||
if (bitmap == NULL) return NULL;
|
||||
|
||||
if (bitmap->Lock()) {
|
||||
bitmap->AddChild(&view);
|
||||
view.DrawBitmap(fBitmap, srcRect, rect);
|
||||
view.Sync();
|
||||
bitmap->RemoveChild(&view);
|
||||
bitmap->Unlock();
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
BBitmap*
|
||||
ShowImageView::CopySelection(uchar alpha, bool imageSize)
|
||||
{
|
||||
@@ -1038,12 +1059,12 @@ ShowImageView::GetMouseButtons()
|
||||
}
|
||||
|
||||
void
|
||||
ShowImageView::GetSelMergeRects(BRect &srcBits, BRect &destRect)
|
||||
ShowImageView::GetMergeRects(BBitmap *merge, BRect selection, BRect &srcBits, BRect &destRect)
|
||||
{
|
||||
destRect = fSelectionRect;
|
||||
destRect = selection;
|
||||
ConstrainToImage(destRect);
|
||||
|
||||
srcBits = fSelectionRect;
|
||||
srcBits = selection;
|
||||
if (srcBits.left < 0)
|
||||
srcBits.left = -(srcBits.left);
|
||||
else
|
||||
@@ -1055,20 +1076,22 @@ ShowImageView::GetSelMergeRects(BRect &srcBits, BRect &destRect)
|
||||
if (srcBits.right > fBitmap->Bounds().right)
|
||||
srcBits.right = srcBits.left + destRect.Width();
|
||||
else
|
||||
srcBits.right = fSelBitmap->Bounds().right;
|
||||
srcBits.right = merge->Bounds().right;
|
||||
if (srcBits.bottom > fBitmap->Bounds().bottom)
|
||||
srcBits.bottom = srcBits.top + destRect.Height();
|
||||
else
|
||||
srcBits.bottom = fSelBitmap->Bounds().bottom;
|
||||
srcBits.bottom = merge->Bounds().bottom;
|
||||
}
|
||||
|
||||
void
|
||||
ShowImageView::MergeSelection()
|
||||
ShowImageView::GetSelMergeRects(BRect &srcBits, BRect &destRect)
|
||||
{
|
||||
if (!HasSelection() || !fSelBitmap)
|
||||
return;
|
||||
GetMergeRects(fSelBitmap, fSelectionRect, srcBits, destRect);
|
||||
}
|
||||
|
||||
// Merge selection with background
|
||||
void
|
||||
ShowImageView::MergeWithBitmap(BBitmap *merge, BRect selection)
|
||||
{
|
||||
BView view(fBitmap->Bounds(), NULL, B_FOLLOW_NONE, B_WILL_DRAW);
|
||||
BBitmap *bitmap = new BBitmap(fBitmap->Bounds(), fBitmap->ColorSpace(), true);
|
||||
if (bitmap == NULL)
|
||||
@@ -1077,10 +1100,9 @@ ShowImageView::MergeSelection()
|
||||
if (bitmap->Lock()) {
|
||||
bitmap->AddChild(&view);
|
||||
view.DrawBitmap(fBitmap, fBitmap->Bounds());
|
||||
|
||||
BRect srcBits, destRect;
|
||||
GetSelMergeRects(srcBits, destRect);
|
||||
view.DrawBitmap(fSelBitmap, srcBits, destRect);
|
||||
GetMergeRects(merge, selection, srcBits, destRect);
|
||||
view.DrawBitmap(merge, srcBits, destRect);
|
||||
|
||||
view.Sync();
|
||||
bitmap->RemoveChild(&view);
|
||||
@@ -1095,6 +1117,25 @@ ShowImageView::MergeSelection()
|
||||
delete bitmap;
|
||||
}
|
||||
|
||||
void
|
||||
ShowImageView::MergeSelection()
|
||||
{
|
||||
if (!HasSelection())
|
||||
return;
|
||||
|
||||
if (!fSelBitmap) {
|
||||
// Even though the merge will not change
|
||||
// the background image, I still need to save
|
||||
// some undo information here
|
||||
fUndo.SetTo(fSelectionRect, NULL, CopySelection());
|
||||
return;
|
||||
}
|
||||
|
||||
// Merge selection with background
|
||||
fUndo.SetTo(fSelectionRect, CopyFromRect(fSelectionRect), CopySelection());
|
||||
MergeWithBitmap(fSelBitmap, fSelectionRect);
|
||||
}
|
||||
|
||||
void
|
||||
ShowImageView::MouseDown(BPoint position)
|
||||
{
|
||||
@@ -1485,6 +1526,45 @@ ShowImageView::PageCount()
|
||||
return fDocumentCount;
|
||||
}
|
||||
|
||||
void
|
||||
ShowImageView::Undo()
|
||||
{
|
||||
int32 undoType = fUndo.GetType();
|
||||
if (undoType != UNDO_UNDO && undoType != UNDO_REDO)
|
||||
return;
|
||||
|
||||
// backup current selection
|
||||
BRect undoneSelRect;
|
||||
BBitmap *undoneSelection;
|
||||
undoneSelRect = fSelectionRect;
|
||||
undoneSelection = CopySelection();
|
||||
|
||||
if (undoType == UNDO_UNDO) {
|
||||
BBitmap *undoRestore;
|
||||
undoRestore = fUndo.GetRestoreBitmap();
|
||||
if (undoRestore)
|
||||
MergeWithBitmap(undoRestore, fUndo.GetRect());
|
||||
}
|
||||
|
||||
// restore previous image/selection
|
||||
BBitmap *undoSelection;
|
||||
undoSelection = fUndo.GetSelectionBitmap();
|
||||
// NOTE: ShowImageView is responsible for deleting this bitmap
|
||||
// (Which it will, as it would with a fSelBitmap that it allocated itself)
|
||||
if (!undoSelection)
|
||||
SetHasSelection(false);
|
||||
else {
|
||||
SetHasSelection(true);
|
||||
fCopyFromRect = BRect();
|
||||
fSelectionRect = fUndo.GetRect();
|
||||
fSelBitmap = undoSelection;
|
||||
}
|
||||
|
||||
fUndo.Undo(undoneSelRect, NULL, undoneSelection);
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void
|
||||
ShowImageView::AddWhiteRect(BRect &rect)
|
||||
{
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <TranslatorRoster.h>
|
||||
|
||||
#include "Filter.h"
|
||||
#include "ShowImageUndo.h"
|
||||
|
||||
#define DELAYED_SCALING 1
|
||||
|
||||
@@ -82,6 +83,7 @@ public:
|
||||
int32 CurrentPage();
|
||||
int32 PageCount();
|
||||
|
||||
void Undo();
|
||||
void Cut();
|
||||
void Paste();
|
||||
void SelectAll();
|
||||
@@ -113,6 +115,7 @@ public:
|
||||
void SetIcon(bool clear);
|
||||
|
||||
private:
|
||||
ShowImageUndo fUndo;
|
||||
enum image_orientation {
|
||||
k0, // 0
|
||||
k90, // 1
|
||||
@@ -132,8 +135,10 @@ private:
|
||||
void Notify(const char* status);
|
||||
void AddToRecentDocuments();
|
||||
void AddWhiteRect(BRect &rect);
|
||||
void GetMergeRects(BBitmap *merge, BRect selection, BRect &srcBits, BRect &destRect);
|
||||
void GetSelMergeRects(BRect &srcBits, BRect &destRect);
|
||||
void PasteBitmap(BBitmap *bitmap, BPoint point);
|
||||
void MergeWithBitmap(BBitmap *merge, BRect selection);
|
||||
void MergeSelection();
|
||||
void DeleteScaler();
|
||||
void DeleteBitmap();
|
||||
@@ -155,6 +160,7 @@ private:
|
||||
bool FirstFile();
|
||||
void ConstrainToImage(BPoint &point);
|
||||
void ConstrainToImage(BRect &rect);
|
||||
BBitmap* CopyFromRect(BRect srcRect);
|
||||
BBitmap* CopySelection(uchar alpha = 255, bool imageSize = true);
|
||||
bool AddSupportedTypes(BMessage* msg, BBitmap* bitmap);
|
||||
void BeginDrag(BPoint sourcePoint);
|
||||
|
||||
@@ -568,6 +568,14 @@ ShowImageWindow::MessageReceived(BMessage *pmsg)
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_UNDO_STATE:
|
||||
{
|
||||
bool benable;
|
||||
if (pmsg->FindBool("can_undo", &benable) == B_OK)
|
||||
EnableMenuItem(fBar, B_UNDO, benable);
|
||||
break;
|
||||
}
|
||||
|
||||
case MSG_CLIPBOARD_CHANGED:
|
||||
{
|
||||
// The app sends this message after it examines
|
||||
@@ -580,6 +588,7 @@ ShowImageWindow::MessageReceived(BMessage *pmsg)
|
||||
}
|
||||
|
||||
case B_UNDO:
|
||||
fImageView->Undo();
|
||||
break;
|
||||
case B_CUT:
|
||||
fImageView->Cut();
|
||||
|
||||
Reference in New Issue
Block a user