Undo of set editor background

General TRichView support forum. Please post your questions here
Post Reply
ahasoft
Posts: 1
Joined: Mon Oct 23, 2006 10:57 am

Undo of set editor background

Post by ahasoft »

Is there a way to implement undo/redo for changes to the editor background?

Nick Sullivan
AHA! Software
Sergey Tkachenko
Site Admin
Posts: 17564
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post 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)
Pieter E.
Posts: 835
Joined: Sun Aug 28, 2005 9:34 am

Post 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);
}
//---------------------------------------------------------------------------
Sergey Tkachenko
Site Admin
Posts: 17564
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post by Sergey Tkachenko »

Thank you!
Pieter E.
Posts: 835
Joined: Sun Aug 28, 2005 9:34 am

Post by Pieter E. »

You're welcome. :wink:
Darken
Posts: 11
Joined: Tue Jul 22, 2014 1:30 pm

Post 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 уже нельзя (конечно можно дополнительно сохранять копию изображения и т.д.), но хотелось бы что бы изменения те что касаются и изображения ставали в очередь операций "Отменить/Вернуть".

Заранее спасибо!
)
Sergey Tkachenko
Site Admin
Posts: 17564
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Post 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);
Kverde
Posts: 53
Joined: Wed Dec 25, 2013 3:02 am

Re:

Post 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 доступно}
Sergey Tkachenko
Site Admin
Posts: 17564
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Re: Undo of set editor background

Post 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.
Kverde
Posts: 53
Joined: Wed Dec 25, 2013 3:02 am

Re: Undo of set editor background

Post by Kverde »

Sergey Tkachenko wrote: Fri Jun 14, 2019 11:32 am Чтобы все было правильно, в конец DoChangeBackgroundColor нужно добавить Editor.Change.
в этом случае Redo очередь не активизируется
есть какое нибудь решение?
в лоб вижу класс добавить TRedoBackColor
Sergey Tkachenko
Site Admin
Posts: 17564
Joined: Sat Aug 27, 2005 10:28 am
Contact:

Re: Undo of set editor background

Post 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;
Post Reply