Page 1 of 1

Undo of set editor background

Posted: Mon Oct 23, 2006 11:05 am
by ahasoft
Is there a way to implement undo/redo for changes to the editor background?

Nick Sullivan
AHA! Software

Posted: Tue Oct 24, 2006 9:06 am
by Sergey Tkachenko
This function is not implemented, but I can show how to implement it.

Code: Select all

uses RVUndo, RVRVData, RVERVData;

type
  TRVUndoBackgroundColor = class (TRVUndoInfo)
    private
      FBackgroundColor: TColor;
    public
      function RequiresFormat: Boolean; override;
      procedure Undo(RVData: TRichViewRVData); override;
  end;

procedure DoChangeBackgroundColor(RVData: TRichViewRVData; Color: TColor);
var UndoItem: TRVUndoBackgroundColor;
    List: TRVUndoList;
    Edit: TCustomRichViewEdit;
begin
  Edit := TRichViewRVData(RVData.GetAbsoluteRootData).RichView as TCustomRichViewEdit;
  List := TRVEditRVData(RVData).GetUndoList;
  if List<>nil then begin
    UndoItem := TRVUndoBackgroundColor.Create;
    UndoItem.Action := rvuMisc;
    UndoItem.FBackgroundColor := Edit.Color;
    List.AddInfo(UndoItem, Edit);
  end;
  Edit.Color := Color;
end;

procedure ChangeBackgroundColor(Edit: TCustomRichViewEdit; Color: TColor);
begin
  Edit.BeginUndoCustomGroup('Change Background Color');
  DoChangeBackgroundColor(Edit.RVData, Color);
  while Edit<>nil do begin
    Edit.Invalidate;
    Edit := TCustomRichViewEdit(Edit.InplaceEditor);
  end;
end;

procedure TRVUndoBackgroundColor.Undo(RVData: TRichViewRVData);
begin
  DoChangeBackgroundColor(RVData, FBackgroundColor);
end;

function TRVUndoBackgroundColor.RequiresFormat: Boolean;
begin
  Result := False;
end;
How to use:

Code: Select all

  ChangeBackgroundColor(RichViewEdit1, clRed);
Assignment of other background properties (BackgroundBitmap, BackgroundStyle) can be implemented in the same way (for bitmap, do not forget to implement destructor freeing the stored bitmap)

Posted: Wed Oct 05, 2011 8:02 am
by Pieter E.
Below you find the translation to C++. Have fun! :D

UndoBackgroundColorUnit.h

Code: Select all

//---------------------------------------------------------------------------
#include "RVUndo.hpp"
#include "RVRVData.hpp"
#include "RVERVData.hpp"
//---------------------------------------------------------------------------
class TRVUndoBackgroundColor : public TRVUndoInfo
{
  private:
	TColor FBackgroundColor;
  public:
	DYNAMIC bool __fastcall RequiresFormat(void);
	DYNAMIC void __fastcall Undo(Rvrvdata::TRichViewRVData* RVData);
	void __fastcall DoChangeBackgroundColor(TRichViewRVData *RVData, TColor Color);
};
//---------------------------------------------------------------------------
UndoBackgroundColorUnit.cpp

Code: Select all

void __fastcall TRVUndoBackgroundColor::Undo(Rvrvdata::TRichViewRVData* RVData)
{
  DoChangeBackgroundColor(RVData, FBackgroundColor);
}
//---------------------------------------------------------------------------

bool __fastcall TRVUndoBackgroundColor::RequiresFormat()
{
  return false;
}
//---------------------------------------------------------------------------

void __fastcall TRVUndoBackgroundColor::DoChangeBackgroundColor(TRichViewRVData *RVData, TColor Color)
{
  TCustomRichViewEdit *Edit = (TCustomRichViewEdit *) ((TRichViewRVData *)RVData->GetAbsoluteRootData())->RichView;
  TRVUndoList *List = ((TRVEditRVData *)RVData)->GetUndoList();
  if(List != NULL)
	{
	  TRVUndoBackgroundColor *UndoItem = new TRVUndoBackgroundColor();
	  UndoItem->Action = rvuMisc;
	  UndoItem->FBackgroundColor = Edit->Color;
	  List->AddInfo(UndoItem, Edit);
	}
  Edit->Color = Color;
}
//---------------------------------------------------------------------------

void __fastcall TForm1::ChangeBackgroundColor(TCustomRichViewEdit *Edit, TColor Color)
{
  Edit->BeginUndoCustomGroup("Change Background Color");
  TRVUndoBackgroundColor *pUndoColor = new TRVUndoBackgroundColor();
  try
	{
	  pUndoColor->DoChangeBackgroundColor(Edit->RVData, Color);
	  while(Edit != NULL)
		{
		  Edit->Invalidate();
		  Edit = (TCustomRichViewEdit *) Edit->InplaceEditor;
		}
	}
  __finally
	{
	  pUndoColor->Free();
	}
}
//---------------------------------------------------------------------------
How to use:

Code: Select all

void __fastcall TForm1::Button1Click(TObject *Sender)
{
  ChangeBackgroundColor(rve, clRed);
}
//---------------------------------------------------------------------------

Posted: Wed Oct 05, 2011 1:01 pm
by Sergey Tkachenko
Thank you!

Posted: Wed Oct 05, 2011 4:43 pm
by Pieter E.
You're welcome. :wink:

Posted: Thu Jul 24, 2014 11:38 am
by Darken
Hello Sergey!

I have problem with undo/redo. I'm edit inserted image in my image Editor. But if base image changes undo does't work.
-----------------------
var
gr: TGraphic;
bmp: TBitmap;
----------------------
gr := RVE.GetSelectedImage;

if gr = nil then exit;
bmp := TBitmap.Create;
bmp.Assign(gr);

// now change image in outer image editor

gr.Assign(bmp);

(Еще на русском напишу, мой английский к сожалению далек от совершенства.

Редактирую изображение, после редактирования возвращаю его обратно. Но отменить эту операцию TRichViewEdit уже нельзя (конечно можно дополнительно сохранять копию изображения и т.д.), но хотелось бы что бы изменения те что касаются и изображения ставали в очередь операций "Отменить/Вернуть".

Заранее спасибо!
)

Posted: Thu Jul 24, 2014 3:27 pm
by Sergey Tkachenko
Since this old topic is revived, I want to say that the new version of TRichViewEdit you can change background properties as an editing operation. The methods are SetBackgroundImageEd for changing image, SetIntPropertyEd for changing background style and color.

As for the last question. If you simply change an image, this operation cannot be undone. You need to create a new image and call SetCurrentPicture or SetPictureEd to assign this new image to the item.

If you want to work with the selected picture, you cannot use SetCurrentPicture, because the current item is not necessary the selected item (the current item is item to the left of the caret; if the selection was made from bottom to top, the previous item is current).

If you want to use only documented methods, you should get the selection using RVE.TopLevelEditor.GetSelectionBounds and check, if a single image is selected.
I simplify this task by using undocumented GetSingleSelectedItem method

Code: Select all

uses CRVFData, RVTypes;

var RVData: TCustomRVFormattedData;
     ItemNo: Integer;
    AVAlign: TRVValign;
    AName: TRVAnsiString;
    ATag: TRVTag;

gr := RVE.GetSelectedImage; 
if gr = nil then
  exit; 

bmp := TBitmap.Create; 
bmp.Assign(gr); 

RVE.RVData.GetSingleSelectedItem(RVData, ItemNo);
// we can use TopLevelEditor, because the selected image can be only in it
RVE.TopLevelEditor.GetPictureInfo(ItemNo, AName, gr, AVAlign, ATag);
RVE.TopLevelEditor.SetPictureInfoEd(ItemNo, AName, bmp, AVAlign, ATag);

Re:

Posted: Fri Jun 14, 2019 8:26 am
by Kverde
Sergey Tkachenko wrote: Tue Oct 24, 2006 9:06 am This function is not implemented, but I can show how to implement it.

Code: Select all

uses RVUndo, RVRVData, RVERVData;

type
  TRVUndoBackgroundColor = class (TRVUndoInfo)
    private
      FBackgroundColor: TColor;
    public
      function RequiresFormat: Boolean; override;
      procedure Undo(RVData: TRichViewRVData); override;
  end;

procedure DoChangeBackgroundColor(RVData: TRichViewRVData; Color: TColor);
var UndoItem: TRVUndoBackgroundColor;
    List: TRVUndoList;
    Edit: TCustomRichViewEdit;
begin
  Edit := TRichViewRVData(RVData.GetAbsoluteRootData).RichView as TCustomRichViewEdit;
  List := TRVEditRVData(RVData).GetUndoList;
  if List<>nil then begin
    UndoItem := TRVUndoBackgroundColor.Create;
    UndoItem.Action := rvuMisc;
    UndoItem.FBackgroundColor := Edit.Color;
    List.AddInfo(UndoItem, Edit);
  end;
  Edit.Color := Color;
end;

procedure ChangeBackgroundColor(Edit: TCustomRichViewEdit; Color: TColor);
begin
  Edit.BeginUndoCustomGroup('Change Background Color');
  DoChangeBackgroundColor(Edit.RVData, Color);
  while Edit<>nil do begin
    Edit.Invalidate;
    Edit := TCustomRichViewEdit(Edit.InplaceEditor);
  end;
end;

procedure TRVUndoBackgroundColor.Undo(RVData: TRichViewRVData);
begin
  DoChangeBackgroundColor(RVData, FBackgroundColor);
end;

function TRVUndoBackgroundColor.RequiresFormat: Boolean;
begin
  Result := False;
end;
How to use:

Code: Select all

  ChangeBackgroundColor(RichViewEdit1, clRed);
Assignment of other background properties (BackgroundBitmap, BackgroundStyle) can be implemented in the same way (for bitmap, do not forget to implement destructor freeing the stored bitmap)
Доброго дня суток!

Не совсем понял Ваш пример.
При добавлении TRVUndoBackgroundColor в очередь Undo, вроде бы логично почистить очередь Redo?
{проверяется так набрать несколько символов нажать несколько раз Undo, выполнить ChangeBackgroundColor, результат Redo доступно}

Re: Undo of set editor background

Posted: Fri Jun 14, 2019 11:32 am
by Sergey Tkachenko
Чтобы все было правильно, в конец DoChangeBackgroundColor нужно добавить Editor.Change.
Как я писал выше, теперь рекомендованный способ поменять цвет фона с возможностью отмены это
MyRichViewEdit.SetIntPropertyEd(rvipColor, ord(clYellow), True);
Приведенный код может быть полезен только если вы хотите на его основе реализовать отмену своих нестандартных операций.

---

The question was about not clearing a redo buffer. The fix is adding the line Editor.Change to the end of DoChangeBackgroundColor.
But as I wrote above, the new version has a special function to change background color as an editing operation:
MyRichViewEdit.SetIntPropertyEd(rvipColor, ord(clYellow), True);
The code sample is this topic is only useful as an example of implementation of undo of your own operations.

Re: Undo of set editor background

Posted: Fri Jun 14, 2019 12:41 pm
by Kverde
Sergey Tkachenko wrote: Fri Jun 14, 2019 11:32 am Чтобы все было правильно, в конец DoChangeBackgroundColor нужно добавить Editor.Change.
в этом случае Redo очередь не активизируется
есть какое нибудь решение?
в лоб вижу класс добавить TRedoBackColor

Re: Undo of set editor background

Posted: Fri Jun 14, 2019 4:31 pm
by Sergey Tkachenko
My mistake, Edit.Change must be in ChangeBackgroundColor, not in DoChangeBackgroundColor.
Also, I added CanChange check (it is especially important for TDBRichViewEdit).

(Я ошибся, Edit.Change нужно добавить в ChangeBackgroundColor, а не в DoChangeBackgroundColor.
Кроме того, следует добавить проверку на CanChange, это особенно важно, если код будет использоваться в TDBRichViewEdit).

Code: Select all

procedure DoChangeBackgroundColor(RVData: TRichViewRVData; Color: TColor);
var UndoItem: TRVUndoBackgroundColor;
    List: TRVUndoList;
    Edit: TCustomRichViewEdit;
begin
  Edit := TRichViewRVData(RVData.GetAbsoluteRootData).RichView as TCustomRichViewEdit;
  List := TRVEditRVData(RVData).GetUndoList;
  if List<>nil then begin
    UndoItem := TRVUndoBackgroundColor.Create;
    UndoItem.Action := rvuMisc;
    UndoItem.FBackgroundColor := Edit.Color;
    List.AddInfo(UndoItem, Edit);
  end;
  Edit.Color := Color;
end;

procedure ChangeBackgroundColor(Edit: TCustomRichViewEdit; Color: TColor);
begin
  if Edit.CanChange then
  begin
    Edit.BeginUndoCustomGroup('Change Background Color');
    DoChangeBackgroundColor(Edit.RVData, Color);
    Edit.Change;
    Edit.RefreshAll;
  end;
end;