mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-09-03 22:20:17 +02:00
TAChart series editor: adding, deleting and selection of series
issue #13214 part 3 git-svn-id: trunk@18775 -
This commit is contained in:
parent
7ab4967ab9
commit
ee315fb844
@ -198,6 +198,8 @@ type
|
||||
property Title: String read FTitle write FTitle;
|
||||
end;
|
||||
|
||||
TSeriesClass = class of TBasicChartSeries;
|
||||
|
||||
{ TChartSeriesList }
|
||||
|
||||
TChartSeriesList = class(TPersistent)
|
||||
@ -412,16 +414,26 @@ type
|
||||
end;
|
||||
|
||||
procedure Register;
|
||||
procedure RegisterSeriesClass(ASeriesClass: TSeriesClass; const ACaption: string);
|
||||
|
||||
var
|
||||
SeriesClassRegistry: TStringList;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
Clipbrd, Math;
|
||||
Clipbrd, LCLProc, Math;
|
||||
|
||||
const
|
||||
MinDouble = -1.7e308;
|
||||
MaxDouble = 1.7e308;
|
||||
|
||||
procedure RegisterSeriesClass(ASeriesClass: TSeriesClass; const ACaption: string);
|
||||
begin
|
||||
if SeriesClassRegistry.IndexOfObject(TObject(ASeriesClass)) < 0 then
|
||||
SeriesClassRegistry.AddObject(ACaption, TObject(ASeriesClass));
|
||||
end;
|
||||
|
||||
{ TChartPen }
|
||||
|
||||
procedure TChartPen.SetVisible(Value: Boolean);
|
||||
@ -1836,8 +1848,10 @@ end;
|
||||
procedure TBasicChartSeries.ReadState(Reader: TReader);
|
||||
begin
|
||||
inherited ReadState(Reader);
|
||||
if Reader.Parent is TChart then
|
||||
(AParent as TChart).AddSeries(Self);
|
||||
if Reader.Parent is TChart then begin
|
||||
(Reader.Parent as TChart).AddSeries(Self);
|
||||
//DebugLn('TAChart %s: %d series', [Reader.Parent.Name, (Reader.Parent as TChart).SeriesCount]);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TBasicChartSeries.SetParentComponent(AParent: TComponent);
|
||||
@ -1847,8 +1861,16 @@ begin
|
||||
end;
|
||||
|
||||
procedure Register;
|
||||
var
|
||||
i: Integer;
|
||||
sc: TSeriesClass;
|
||||
begin
|
||||
RegisterComponents('Additional', [TChart]);
|
||||
for i := 0 to SeriesClassRegistry.Count - 1 do begin
|
||||
sc := TSeriesClass(SeriesClassRegistry.Objects[i]);
|
||||
RegisterClass(sc);
|
||||
RegisterNoIcon([sc]);
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TChartSeriesList }
|
||||
@ -1884,10 +1906,14 @@ end;
|
||||
procedure TChartSeriesList.SetItem(
|
||||
AIndex: Integer; const AValue: TBasicChartSeries);
|
||||
begin
|
||||
FList.Items[AIndex] := AValue;
|
||||
GetItem(AIndex).Assign(AValue);
|
||||
end;
|
||||
|
||||
initialization
|
||||
{$I tagraph.lrs}
|
||||
SeriesClassRegistry := TStringList.Create;
|
||||
|
||||
finalization
|
||||
SeriesClassRegistry.Free;
|
||||
|
||||
end.
|
||||
|
@ -1644,4 +1644,11 @@ begin
|
||||
ACanvas.LineTo(ARect.Right, y);
|
||||
end;
|
||||
|
||||
initialization
|
||||
RegisterSeriesClass(TSerie, 'Line series');
|
||||
RegisterSeriesClass(TAreaSeries, 'Area series');
|
||||
RegisterSeriesClass(TBarSeries, 'Bar series');
|
||||
RegisterSeriesClass(TPieSeries, 'Pie series');
|
||||
RegisterSeriesClass(TLine, 'Line');
|
||||
|
||||
end.
|
||||
|
@ -15,6 +15,7 @@ object SeriesEditorForm: TSeriesEditorForm
|
||||
Width = 325
|
||||
Align = alClient
|
||||
MultiSelect = True
|
||||
OnClick = SeriesListBoxClick
|
||||
TabOrder = 0
|
||||
end
|
||||
object MainMenu1: TMainMenu
|
||||
@ -22,10 +23,10 @@ object SeriesEditorForm: TSeriesEditorForm
|
||||
top = 132
|
||||
object miAdd: TMenuItem
|
||||
Caption = 'Add'
|
||||
object miAddSeries: TMenuItem
|
||||
Caption = 'Series'
|
||||
OnClick = miAddSeriesClick
|
||||
end
|
||||
end
|
||||
object miDelete: TMenuItem
|
||||
Caption = 'Delete'
|
||||
OnClick = miDeleteClick
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -6,8 +6,8 @@ LazarusResources.Add('TSeriesEditorForm','FORMDATA',[
|
||||
+'ientHeight'#3'T'#1#11'ClientWidth'#3'E'#1#4'Menu'#7#9'MainMenu1'#7'OnClose'
|
||||
+#7#9'FormClose'#9'OnDestroy'#7#11'FormDestroy'#10'LCLVersion'#6#6'0.9.27'#0#8
|
||||
+'TListBox'#13'SeriesListBox'#6'Height'#3'T'#1#5'Width'#3'E'#1#5'Align'#7#8'a'
|
||||
+'lClient'#11'MultiSelect'#9#8'TabOrder'#2#0#0#0#9'TMainMenu'#9'MainMenu1'#4
|
||||
+'left'#2'<'#3'top'#3#132#0#0#9'TMenuItem'#5'miAdd'#7'Caption'#6#3'Add'#0#9'T'
|
||||
+'MenuItem'#11'miAddSeries'#7'Caption'#6#6'Series'#7'OnClick'#7#16'miAddSerie'
|
||||
+'sClick'#0#0#0#0#0
|
||||
+'lClient'#11'MultiSelect'#9#7'OnClick'#7#18'SeriesListBoxClick'#8'TabOrder'#2
|
||||
+#0#0#0#9'TMainMenu'#9'MainMenu1'#4'left'#2'<'#3'top'#3#132#0#0#9'TMenuItem'#5
|
||||
+'miAdd'#7'Caption'#6#3'Add'#0#0#9'TMenuItem'#8'miDelete'#7'Caption'#6#6'Dele'
|
||||
+'te'#7'OnClick'#7#13'miDeleteClick'#0#0#0#0
|
||||
]);
|
||||
|
@ -39,18 +39,30 @@ type
|
||||
|
||||
TSeriesEditorForm = class(TForm)
|
||||
MainMenu1: TMainMenu;
|
||||
miAddSeries: TMenuItem;
|
||||
miDelete: TMenuItem;
|
||||
miAdd: TMenuItem;
|
||||
SeriesListBox: TListBox;
|
||||
procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
|
||||
procedure FormDestroy(Sender: TObject);
|
||||
procedure miAddSeriesClick(Sender: TObject);
|
||||
procedure miDeleteClick(Sender: TObject);
|
||||
procedure SeriesListBoxClick(Sender: TObject);
|
||||
private
|
||||
FChart: TChart;
|
||||
FComponentEditor: TSeriesComponentEditor;
|
||||
FPropertyEditor: TSeriesPropertyEditor;
|
||||
FDesigner: TComponentEditorDesigner;
|
||||
procedure BuildCaption;
|
||||
procedure InitAddMenu;
|
||||
procedure RefreshSeriesList;
|
||||
procedure miAddSeriesClick(Sender: TObject);
|
||||
function FindSeries(ASeries: TObject; out AIndex: Integer): Boolean;
|
||||
|
||||
procedure SelectionChanged;
|
||||
procedure OnComponentRenamed(AComponent: TComponent);
|
||||
procedure OnPersistentDeleting(APersistent: TPersistent);
|
||||
procedure OnGetSelection(const ASelection: TPersistentSelectionList);
|
||||
procedure OnSetSelection(const ASelection: TPersistentSelectionList);
|
||||
procedure OnPersistentAdded(APersistent: TPersistent; ASelect: Boolean);
|
||||
public
|
||||
constructor Create(
|
||||
AOwner: TComponent; AChart: TChart; AComponentEditor: TComponentEditor;
|
||||
@ -141,6 +153,11 @@ end;
|
||||
|
||||
{ TSeriesEditorForm }
|
||||
|
||||
procedure TSeriesEditorForm.BuildCaption;
|
||||
begin
|
||||
Caption := sesSeriesEditorTitle + ' - ' + FChart.Name;
|
||||
end;
|
||||
|
||||
constructor TSeriesEditorForm.Create(
|
||||
AOwner: TComponent; AChart: TChart; AComponentEditor: TComponentEditor;
|
||||
APropertyEditor: TPropertyEditor);
|
||||
@ -153,8 +170,28 @@ begin
|
||||
FDesigner := FComponentEditor.Designer
|
||||
else
|
||||
FDesigner := FindRootDesigner(AChart) as TComponentEditorDesigner;
|
||||
Caption := sesSeriesEditorTitle + ' - ' + FChart.Name;
|
||||
BuildCaption;
|
||||
InitAddMenu;
|
||||
|
||||
RefreshSeriesList;
|
||||
|
||||
GlobalDesignHook.AddHandlerComponentRenamed(@OnComponentRenamed);
|
||||
GlobalDesignHook.AddHandlerPersistentDeleting(@OnPersistentDeleting);
|
||||
GlobalDesignHook.AddHandlerGetSelection(@OnGetSelection);
|
||||
GlobalDesignHook.AddHandlerSetSelection(@OnSetSelection);
|
||||
GlobalDesignHook.AddHandlerPersistentAdded(@OnPersistentAdded);
|
||||
|
||||
SelectionChanged;
|
||||
end;
|
||||
|
||||
function TSeriesEditorForm.FindSeries(
|
||||
ASeries: TObject; out AIndex: Integer): Boolean;
|
||||
begin
|
||||
if ASeries is TBasicChartSeries then
|
||||
AIndex := SeriesListBox.Items.IndexOfObject(ASeries)
|
||||
else
|
||||
AIndex := -1;
|
||||
Result := AIndex >= 0;
|
||||
end;
|
||||
|
||||
procedure TSeriesEditorForm.FormClose(Sender: TObject;
|
||||
@ -165,14 +202,127 @@ end;
|
||||
|
||||
procedure TSeriesEditorForm.FormDestroy(Sender: TObject);
|
||||
begin
|
||||
if FComponentEditor <> nil then
|
||||
if FComponentEditor <> nil then begin
|
||||
FComponentEditor.FEditorForm := nil;
|
||||
if
|
||||
(FChart <> nil) and (not (csDestroying in FChart.ComponentState)) and
|
||||
(SeriesListBox.SelCount > 0)
|
||||
then
|
||||
GlobalDesignHook.SelectOnlyThis(FChart);
|
||||
end;
|
||||
if FPropertyEditor <> nil then
|
||||
FPropertyEditor.FEditorForm := nil;
|
||||
if Assigned(GlobalDesignHook) then
|
||||
GlobalDesignHook.RemoveAllHandlersForObject(Self);
|
||||
end;
|
||||
|
||||
procedure TSeriesEditorForm.InitAddMenu;
|
||||
var
|
||||
i: Integer;
|
||||
mi: TMenuItem;
|
||||
begin
|
||||
for i := 0 to SeriesClassRegistry.Count - 1 do begin
|
||||
mi := TMenuItem.Create(Self);
|
||||
mi.OnClick := @miAddSeriesClick;
|
||||
mi.Caption := SeriesClassRegistry[i];
|
||||
mi.Tag := i;
|
||||
miAdd.Add(mi);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSeriesEditorForm.miAddSeriesClick(Sender: TObject);
|
||||
var
|
||||
s: TBasicChartSeries;
|
||||
c: TSeriesClass;
|
||||
n: String;
|
||||
begin
|
||||
c := TSeriesClass(SeriesClassRegistry.Objects[(Sender as TMenuItem).Tag]);
|
||||
n := Copy(c.ClassName, 2, Length(c.ClassName) - 1);
|
||||
s := c.Create(FChart.Owner);
|
||||
try
|
||||
s.Name := FDesigner.CreateUniqueComponentName(FChart.Name + n);
|
||||
FChart.AddSeries(s);
|
||||
FDesigner.PropertyEditorHook.PersistentAdded(s, true);
|
||||
FDesigner.Modified;
|
||||
RefreshSeriesList;
|
||||
except
|
||||
s.Free;
|
||||
raise;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSeriesEditorForm.miDeleteClick(Sender: TObject);
|
||||
var
|
||||
i: Integer;
|
||||
s: TBasicChartSeries;
|
||||
begin
|
||||
if SeriesListBox.SelCount = 0 then exit;
|
||||
for i := SeriesListBox.Items.Count - 1 downto 0 do
|
||||
if SeriesListBox.Selected[i] then begin
|
||||
s := TBasicChartSeries(SeriesListBox.Items.Objects[i]);
|
||||
SeriesListBox.Items.Delete(i);
|
||||
FDesigner.PropertyEditorHook.PersistentDeleting(s);
|
||||
s.Free;
|
||||
end;
|
||||
FDesigner.Modified;
|
||||
SelectionChanged;
|
||||
end;
|
||||
|
||||
procedure TSeriesEditorForm.OnComponentRenamed(AComponent: TComponent);
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
if AComponent = nil then exit;
|
||||
if FindSeries(AComponent, i) then
|
||||
SeriesListBox.Items[i] := AComponent.Name
|
||||
else if AComponent = FChart then
|
||||
BuildCaption;
|
||||
end;
|
||||
|
||||
procedure TSeriesEditorForm.OnGetSelection(
|
||||
const ASelection: TPersistentSelectionList);
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
if ASelection = nil then exit;
|
||||
ASelection.Clear;
|
||||
with SeriesListBox do
|
||||
for i := 0 to Items.Count - 1 do
|
||||
if Selected[i] then
|
||||
ASelection.Add(TPersistent(Items.Objects[i]));
|
||||
end;
|
||||
|
||||
procedure TSeriesEditorForm.OnPersistentAdded(
|
||||
APersistent: TPersistent; ASelect: Boolean);
|
||||
var
|
||||
i: Integer;
|
||||
s: TBasicChartSeries;
|
||||
begin
|
||||
if (APersistent = nil) or not (APersistent is TBasicChartSeries) then exit;
|
||||
s := APersistent as TBasicChartSeries;
|
||||
if s.ParentChart <> FChart then exit;
|
||||
i := SeriesListBox.Items.AddObject(s.Name, s);
|
||||
SeriesListBox.Selected[i] := ASelect;
|
||||
end;
|
||||
|
||||
procedure TSeriesEditorForm.OnPersistentDeleting(APersistent: TPersistent);
|
||||
var
|
||||
i: Integer;
|
||||
begin
|
||||
if FindSeries(APersistent, i) then
|
||||
SeriesListBox.Items.Delete(i);
|
||||
end;
|
||||
|
||||
procedure TSeriesEditorForm.OnSetSelection(
|
||||
const ASelection: TPersistentSelectionList);
|
||||
var
|
||||
i, j: Integer;
|
||||
begin
|
||||
if ASelection = nil then exit;
|
||||
SeriesListBox.ClearSelection;
|
||||
for i := 0 to ASelection.Count - 1 do
|
||||
if FindSeries(ASelection.Items[i], j) then
|
||||
SeriesListBox.Selected[j] := true;
|
||||
end;
|
||||
|
||||
procedure TSeriesEditorForm.RefreshSeriesList;
|
||||
@ -184,6 +334,29 @@ begin
|
||||
SeriesListBox.Items.AddObject(FChart.Series[i].Name, FChart.Series[i]);
|
||||
end;
|
||||
|
||||
procedure TSeriesEditorForm.SelectionChanged;
|
||||
var
|
||||
sel: TPersistentSelectionList;
|
||||
begin
|
||||
GlobalDesignHook.RemoveHandlerSetSelection(@OnSetSelection);
|
||||
try
|
||||
sel := TPersistentSelectionList.Create;
|
||||
try
|
||||
OnGetSelection(sel);
|
||||
FDesigner.PropertyEditorHook.SetSelection(sel) ;
|
||||
finally
|
||||
sel.Free;
|
||||
end;
|
||||
finally
|
||||
GlobalDesignHook.AddHandlerSetSelection(@OnSetSelection);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TSeriesEditorForm.SeriesListBoxClick(Sender: TObject);
|
||||
begin
|
||||
SelectionChanged;
|
||||
end;
|
||||
|
||||
initialization
|
||||
{$I taserieseditor.lrs}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user