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:
Matthew Wilber
2003-12-18 03:31:28 +00:00
parent a08013c09a
commit 7598450e4f
7 changed files with 286 additions and 12 deletions
+1
View File
@@ -6,6 +6,7 @@ App ShowImage : ShowImageApp.cpp
ShowImageConstants.cpp
ShowImageSettings.cpp
ShowImageStatusView.cpp
ShowImageUndo.cpp
ShowImageView.cpp
ShowImageWindow.cpp
PrintOptionsWindow.cpp
+1
View File
@@ -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';
+98
View File
@@ -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
}
+79
View File
@@ -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 */
+92 -12
View File
@@ -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)
{
+6
View File
@@ -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);
+9
View File
@@ -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();