<< Click to Display Table of Contents >>
If the user should be able to edit multiple documents at the same time, very often the approach is to create multiple editor objects. Those can be on frames, MDI child windows or other different forms. WPTools supports this concept, i.e. it allows it to use just one toolbar for all editors and only the editor which was used last, will be active.
But often this approach is not wanted and also not used very much any more. Instead a tabbed user interface should be used:
With WPTools this interface can be developed easily, stable and straight forward. You do not need to create multiple TWPRichText objects.
You only need one TWPRichText and switch the attached RTFDataCollection.
This is a feature which is possible because of the consequent separation of display logic and data structures, sometimes some competing products do not have. Basically you have multiple documents in memory and let one editor edit one after the other. This has several advantages:
1) Save windows resources (handles)
2) Avoid focus problems (MDI children can take away the focus of a window)
3) Share paragraph styles between editors
4) It is easy to manipulate all documents by code within one loop
5) Create the GUI more quickly
6) More stable concept
We enhanced the "mini" editor to do so (see the demo "DynamicRTFData/SimulatedMDI"). We just added a tab-set to switch between the documents, some code to intercept the OPEN, CLOSE and NEW actions of the TWPToolbar and of course a list with RTFData objects handled by TStringlist.
Variables:
type
TForm1 = class(TForm)
...
public
FRTFDataCollections : TStringList;
function AddRTFData(name : string) : Integer;
procedure InitTabset;
procedure DelRTFData;
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
Add a document
function TForm1.AddRTFData(name : string) : Integer;
var element : TWPRTFDataCollection;
begin
element := TWPRTFDataCollection.Create(TWPRTFDataBlock);
element.MakeRTFProps;
Result := FRTFDataCollections.Count;
FRTFDataCollections.AddObject(name, element);
WPRichText1.RemoveRTFData;
WPRichText1.SetRTFData(element);
WPRichText1.ReformatAll(false, true);
InitTabSet;
end;
Delete current document, clear if it is last
procedure TForm1.DelRTFData;
var i : Integer;
element : TWPRTFDataCollection;
bNeedClear : Boolean;
begin
bNeedClear := true;
if FRTFDataCollections.Count>1 then
begin
i := FRTFDataCollections.IndexOfObject( WPRichText1.RTFData );
if i>=0 then
begin
element := WPRichText1.RTFData;
WPRichText1.RemoveRTFData;
FRTFDataCollections.Delete(i);
if i>0 then dec(i);
element.Free;
element := TWPRTFDataCollection(FRTFDataCollections.Objects[i]);
WPRichText1.SetRTFData(element);
WPRichText1.ReformatAll(false, true);
InitTabSet;
bNeedClear := false;
end;
end;
if bNeedClear then
begin
WPRichText1.Clear;
WPRichText1.CheckHasBody;
WPRichText1.SetFocus;
end;
end;
Update the tabset "TabControl1" and display current filenames. Select the current tab.
procedure TForm1.InitTabset;
var i : Integer;
begin
TabControl1.Tabs.Clear;
for i := 0 to FRTFDataCollections.Count-1 do
TabControl1.Tabs.Add(
TWPRTFDataCollection(FRTFDataCollections.Objects[i]).LastFileName
);
i := FRTFDataCollections.IndexOfObject( WPRichText1.RTFData );
if i>=0 then TabControl1.TabIndex := i
else TabControl1.Tabs.Add('#');
end;
Switch between documents - tabset OnChange event.
procedure TForm1.TabControl1Change(Sender: TObject);
begin
WPRichText1.SetRTFData(TWPRTFDataCollection(FRTFDataCollections.Objects[TabControl1.TabIndex]));
end;
Update display of filename after SaveAs
This code is called by the TWPRichText after a file was saved. It makes it easy to update the GUI with the new filename. Since our method InitTabset is reading the filenames from the DataCollection objects, the handling is very easy.
procedure TForm1.WPRichText1ChangeLastFileName(Sender: TObject);
begin
InitTabset;
end;
Intercept a click on tollbar button
This code is called by the TWPToolbar in the OnIconSelection event.
procedure TForm1.WPToolbar1IconSelection(Sender: TObject;
var Typ: TWpSelNr; const str: String; const group, num, index: Integer);
begin
if (typ=wptIconSel) and (group=WPI_GR_DISK) then
case num of
WPI_CO_Exit : Close;
WPI_CO_New :
begin
AddRTFData( '' );
Typ := wptIconDeSel;
end;
WPI_CO_Open :
begin
AddRTFData( '' );
if not WPRichText1.Load then DelRTFData;
Typ := wptIconDeSel;
end;
WPI_CO_Close:
begin
if WPRichText1.CanClose then
DelRTFData;
Typ := wptIconDeSel;
end;
end;
end;
Clean up the documents
procedure TForm1.FormDestroy(Sender: TObject);
var i : Integer;
begin
WPPreview1.WPRichText := nil;
WPRichText1.RemoveRTFData;
WPPreview1.RemoveRTFData;
for i:=0 to FRTFDataCollections.Count-1 do
FRTFDataCollections.Objects[i].Free;
FRTFDataCollections.Free;
end;
Initialize the document list in Form.OnCreate
procedure TForm1.FormCreate(Sender: TObject);
begin
FRTFDataCollections := TStringList.Create;
AddRTFData('');
...