123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197 |
- unit propertygridwidget;
- {$mode objfpc}
- interface
- uses
- Classes, SysUtils, types, web, webwidget, htmlwidgets, typinfo, contnrs;
- Type
- { TPropertyEditor }
- TSimplePropertyGridWidget = Class;
- TPropertyEditor = Class (TObject)
- private
- FGrid : TSimplePropertyGridWidget;
- FInfo : TTypeMemberProperty;
- FInstance : TObject;
- Level : Integer;
- SubList: TFPObjectList;
- ElRow : TJSHTMLElement;
- ElName : TJSHTMLElement;
- ElValue : TJSHTMLElement;
- OnValueChanged : TNotifyEvent;
- procedure SetInstance(AValue: TObject);
- public
- function CreateEditorElement (aTag : String; aID : String) : TJSHTMLElement; virtual;
- Constructor Create(aGrid : TSimplePropertyGridWidget;aInstance : TObject; aInfo: TTypeMemberProperty);
- Destructor destroy; override;
- Procedure ValueChanged(Event: TJSEvent);
- // Initialize editor
- Function InitEditor : TJSHTMLElement; virtual; abstract;
- // Apply editor value to property
- Procedure EditorToProperty; virtual; abstract;
- // Apply property value to editor
- Procedure PropertyToEditor; virtual; abstract;
- Property Info : TTypeMemberProperty Read FInfo;
- Property Instance : TObject Read FInstance Write SetInstance;
- Property Grid : TSimplePropertyGridWidget Read FGrid;
- end;
- TPropertyEditorClass = Class of TPropertyEditor;
- { TBooleanPropertyEditor }
- TBooleanPropertyEditor = Class(TPropertyEditor)
- procedure EditorToProperty; override;
- Function InitEditor: TJSHTMLElement; override;
- procedure PropertyToEditor; override;
- end;
- { TIntegerPropertyEditor }
- TIntegerPropertyEditor = Class(TPropertyEditor)
- procedure EditorToProperty; override;
- Function InitEditor: TJSHTMLElement; override;
- procedure PropertyToEditor; override;
- end;
- { TFloatPropertyEditor }
- TFloatPropertyEditor = Class(TPropertyEditor)
- procedure EditorToProperty; override;
- Function InitEditor: TJSHTMLElement; override;
- procedure PropertyToEditor; override;
- end;
- { TStringPropertyEditor }
- TStringPropertyEditor = Class(TPropertyEditor)
- procedure EditorToProperty; override;
- Function InitEditor: TJSHTMLElement; override;
- procedure PropertyToEditor; override;
- end;
- { TLabelPropertyEditor }
- TLabelPropertyEditor = Class(TPropertyEditor)
- procedure EditorToProperty; override;
- Function InitEditor: TJSHTMLElement; override;
- procedure PropertyToEditor; override;
- end;
- { TStringsPropertyEditor }
- TStringsPropertyEditor = Class(TPropertyEditor)
- procedure EditorToProperty; override;
- Function InitEditor: TJSHTMLElement; override;
- procedure PropertyToEditor; override;
- end;
- { TStringListPropertyEditor }
- TStringListPropertyEditor = Class(TPropertyEditor)
- // Values and texts to display.
- Procedure GetStrings(aTexts,aValues : TStrings); virtual; abstract;
- // Selected Option value
- Function GetSelectedValue : string;
- // Selected Option text
- Function GetSelectedText : string;
- Procedure SetSelectedValue(aValue : string);
- Function InitEditor: TJSHTMLElement; override;
- end;
- { TEnumerationPropertyEditor }
- TEnumerationPropertyEditor = Class(TStringListPropertyEditor)
- Procedure GetStrings(aTexts,aValues : TStrings); override;
- procedure EditorToProperty; override;
- procedure PropertyToEditor; override;
- end;
-
- { TComponentPropertyEditor }
- TComponentPropertyEditor = Class(TStringListPropertyEditor)
- Procedure GetStrings(aTexts,aValues : TStrings); override;
- procedure EditorToProperty; override;
- procedure PropertyToEditor; override;
- end;
- { TSetPropertyEditor }
- TSetPropertyEditor = Class(TPropertyEditor)
- Function InitEditor: TJSHTMLElement; override;
- procedure EditorToProperty; override;
- procedure PropertyToEditor; override;
- end;
- { TPersistentPropertyEditor }
- TPersistentPropertyEditor = Class(TPropertyEditor)
- labelEL,ButtoneL: TJSHTMLelement;
- procedure EditorToProperty; override;
- Function InitEditor: TJSHTMLElement; override;
- procedure PropertyToEditor; override;
- end;
- { TSimplePropertyGridWidget }
- // ObjectStack :
- // Collection: |PropName| -0 ClassName (N) |
- // Persistent: | > PropName| -0 ClassName (N) |
- // Top:
- // ObjectPath: < Instance1.PropName1[3].PropName2 |
- // + (N) [ XXX V] - ]
- TSimplePropertyGridWidget = class(TWebWidget)
- private
- FLookupRoot: TComponent;
- FMySubject: TObject;
- FProperties : TFPObjectList;
- procedure DoPropertyChanged(Sender: TObject);
- procedure SetSubject(AValue: TObject);
- procedure SetLookupRoot(AValue: TComponent);
- procedure UpdatePropertyFromEditor(aRow: TPropertyEditor);
- Protected
- function CreateEditorElement (aTag : String; aID : String) : TJSHTMLElement; virtual;
- function AllowProperty(M: TTypeMemberProperty): boolean; virtual;
- procedure CreatePropertyList(aInstance: TObject; aList: TFPObjectList); virtual;
- function CreatePropertyEditor(aInstance: TObject; aInfo: TTypeMemberProperty): TpropertyEditor; virtual;
- procedure CreatePropertyGrid(aTableElement, aRowElement: TJSHTMLElement; FMySubject: TObject; aProperties: TFPObjectList); virtual;
- function DoBooleanEditor(aEditor: TJSHTMLElement; aInfo: TPropertyEditor): TJSHTMLElement; virtual;
- function DoComponentEditor(aEditor: TJSHTMLElement; aInfo: TPropertyEditor): TJSHTMLElement; virtual;
- function DoEnumerationEditor(aEditor: TJSHTMLElement; aInfo: TPropertyEditor): TJSHTMLElement; virtual;
- function DoFloatEditor(aEditor: TJSHTMLElement; aInfo: TPropertyEditor): TJSHTMLElement; virtual;
- function DoIntegerEditor(aEditor: TJSHTMLElement; aInfo: TPropertyEditor): TJSHTMLElement; virtual;
- function DoLabelEditor(aEditor: TJSHTMLElement; aInfo: TPropertyEditor): TJSHTMLElement; virtual;
- function DoPersistentEditor(aEditor: TJSHTMLElement; aInfo: TPropertyEditor): TJSHTMLElement;virtual;
- function DoSetEditor(aEditor: TJSHTMLElement; aInfo: TPropertyEditor): TJSHTMLElement;virtual;
- function DoStringEditor(aEditor: TJSHTMLElement; aInfo: TPropertyEditor): TJSHTMLElement;virtual;
- function DoStringsEditor(aEditor: TJSHTMLElement; aInfo: TPropertyEditor): TJSHTMLElement;virtual;
- Public
- Constructor Create(aOwner : TComponent); override;
- Destructor Destroy; override;
- Function DoRenderHTML(aParent, aElement: TJSHTMLElement): TJSHTMLElement; override;
- Function HTMLTag : String; override;
- Published
- Property Subject : TObject Read FMySubject Write SetSubject;
- Property LookupRoot : TComponent Read FLookupRoot Write SetLookupRoot;
- end;
- implementation
- uses js;
- { TSetPropertyEditor }
- function TSetPropertyEditor.InitEditor: TJSHTMLElement;
- Var
- inp : TJSHTMLTableElement;
- cell : TJSHTMLTableDataCellElement;
- r : TJSHTMLTableRowElement;
- vals : TIntegerDynArray;
- eInfo : TTypeInfoEnum;
- I : Integer;
- selcb,CB : TJSHTMLInputElement;
- lbl : TJSHTMLLabelElement;
- begin
- Result:=CreateEditorElement('table','');
- eInfo:=TTypeInfoEnum(TTypeInfoSet(Info.TypeInfo).CompType);
- // Row with the property as a string.
- R:=TJSHTMLTableRowElement(CreateEditorElement('tr',''));
- Result.Append(R);
- cell:=TJSHTMLTableDatacellElement(CreateEditorElement('td',''));
- cell.InnerText:=GetSetProp(instance,Info);
- R.AppendChild(Cell);
- // For every element in the set, a checkbox row
- for I:=TTypeInfoEnum(Info.TypeInfo).MinValue to TTypeInfoEnum(Info.TypeInfo).MaxValue do
- begin
- // Row
- R:=TJSHTMLTableRowElement(CreateEditorElement('tr',''));
- Result.Append(R);
- // Cell
- cell:=TJSHTMLTableDatacellElement(CreateEditorElement('td',''));
- R.AppendChild(Cell);
- // Input
- CB:=TJSHTMLInputElement(CreateEditorElement('input',''));
- cb._type:='checkbox';
- cb.id:=Grid.GenerateID;
- cb.dataset['enumval']:=IntTostr(i);
- cell.AppendChild(cb);
- // label for input
- lbl:=TJSHTMLLabelElement(CreateEditorElement('label',''));
- lbl.For_:=cb.Id;
- lbl.InnerText:=TTypeInfoEnum(Info.TypeInfo).EnumType.IntToName[I];
- cell.AppendChild(lbl);
- end;
- end;
- procedure TSetPropertyEditor.EditorToProperty;
- Var
- vals : TIntegerDynArray;
- els: TJSNodeList;
- cb : TJSHTMLInputElement;
- I,V : Integer;
- begin
- vals:=[];
- els:=elValue.querySelectorAll('[data-enumval]');
- for I:=0 to els.length-1 do
- begin
- CB:=TJSHTMLInputElement(els[i]);
- if CB.checked then
- begin
- V:=StrToIntDef(String(CB.Dataset['enumval']),-1);
- if V>=0 then
- TJSArray(vals).push(V);
- end;
- end;
- SetSetPropArray(instance,Info,Vals)
- end;
- procedure TSetPropertyEditor.PropertyToEditor;
- Var
- vals : TIntegerDynArray;
- els: TJSNodeList;
- cb : TJSHTMLInputElement;
- I : Integer;
- begin
- vals:=GetSetPropArray(instance,Info);
- els:=elValue.querySelectorAll('[data-enumval]');
- for I:=0 to els.length-1 do
- begin
- CB:=TJSHTMLInputElement(els[i]);
- CB.checked:=TJSArray(vals).indexOf(StrToIntDef(String(CB.Dataset['enumval']),-1))>=0;
- end;
- end;
- { TFloatPropertyEditor }
- procedure TFloatPropertyEditor.EditorToProperty;
- Var
- S : String;
- F : Double;
- begin
- S:=TJSHTMLInputElement(ElValue).value;
- if TryStrToFloat(S,F) then
- SetFloatProp(Instance,Info,F)
- end;
- function TFloatPropertyEditor.InitEditor: TJSHTMLElement;
- begin
- Result:=CreateEditorElement('input','');
- TJSHTMLInputElement(Result)._type:='number';
- end;
- procedure TFloatPropertyEditor.PropertyToEditor;
- begin
- TJSHTMLInputElement(elValue).Value:=FloatToStr(GetFloatProp(Instance,Info));
- end;
- { TStringListPropertyEditor }
- function TStringListPropertyEditor.GetSelectedValue: string;
- Var
- Sel : TJSHTMLSelectElement;
- begin
- Sel:=TJSHTMLSelectElement(ElValue);
- if Sel.selectedIndex>=0 then
- Result:=TJSHTMLOptionElement(Sel.Options.Items[Sel.selectedIndex]).Value
- else
- Result:='';
- end;
- function TStringListPropertyEditor.GetSelectedText: string;
- Var
- Sel : TJSHTMLSelectElement;
- begin
- Sel:=TJSHTMLSelectElement(ElValue);
- if Sel.selectedIndex>=0 then
- Result:=TJSHTMLOptionElement(Sel.Options.Items[Sel.selectedIndex]).InnerText
- else
- Result:='';
- end;
- procedure TStringListPropertyEditor.SetSelectedValue(aValue: string);
- Var
- Inp:TJSHTMLSelectElement;
- I : integer;
- o : TJSHTMLOptionElement;
- begin
- Inp:=TJSHTMLSelectElement(elValue);
- O:=Nil;
- I:=0;
- While (O=Nil) and (I<inp.options.length) do
- begin
- if TJSHTMLOptionElement(inp.options.Items[i]).value=aValue then
- o:=TJSHTMLOptionElement(inp.options.Items[i]);
- Inc(I);
- end;
- if assigned(o) then
- o.selected:=True;
- end;
- function TStringListPropertyEditor.InitEditor: TJSHTMLElement;
- Var
- inp : TJSHTMLSelectElement;
- O,osel : TJSHTMLOptionElement;
- avalS : String;
- aVal,I : Integer;
- aTexts,aValues : TStrings;
- begin
- Result:=nil;
- aTexts:=Nil;
- aValues:=TstringList.Create;
- try
- aTexts:=TstringList.Create;
- GetStrings(aTexts,aValues);
- Result:=CreateEditorElement('select','');
- Inp:=TJSHTMLSelectElement(Result);
- inp.Multiple:=False;
- For I:=0 to aTexts.Count-1 do
- begin
- O:=TJSHTMLOptionElement(CreateEditorElement('option',''));
- O.InnerText:=aTexts[i];
- if (I<aValues.Count) then
- O.value:=aValues[i];
- Inp.appendChild(O)
- end
- finally
- aTexts.Free;
- aValues.Free;
- end;
- end;
- { TEnumerationPropertyEditor }
- procedure TEnumerationPropertyEditor.GetStrings(aTexts,aValues: TStrings);
- Var
- I : Integer;
- begin
- for I:=TTypeInfoEnum(Info.TypeInfo).MinValue to TTypeInfoEnum(Info.TypeInfo).MaxValue do
- begin
- aTexts.Add(TTypeInfoEnum(Info.TypeInfo).EnumType.IntToName[I]);
- aValues.Add(IntToStr(I));
- end;
- end;
- procedure TEnumerationPropertyEditor.EditorToProperty;
- Var
- Sel : TJSHTMLSelectElement;
- S : String;
- begin
- S:=GetSelectedValue;
- if S<>'' then
- SetOrdProp(Instance,Info,StrToInt(S));
- end;
- procedure TEnumerationPropertyEditor.PropertyToEditor;
- var
- aVal : Integer;
- begin
- AVal:=GetOrdProp(Instance,Info);
- SetSelectedValue(IntToStr(aVal));
- end;
- { TComponentPropertyEditor }
- procedure TComponentPropertyEditor.GetStrings(aTexts,aValues: TStrings);
- Var
- I : Integer;
- N : String;
- begin
- for I:=0 to Grid.LookupRoot.ComponentCount-1 do
- begin
- N:=Grid.LookupRoot.Components[i].Name;
- if N<>'' then
- aTexts.Add(N);
- end;
- end;
- procedure TComponentPropertyEditor.EditorToProperty;
- Var
- Sel : TJSHTMLSelectElement;
- S : String;
- C : TComponent;
-
- begin
- S:=GetSelectedValue;
- if S<>'' then
- begin
- C:=Grid.LookupRoot.FindComponent(S);
- SetObjectProp(Instance,Info,C);
- end
- else
- C:=Nil;
- SetObjectProp(Instance,Info,C);
- end;
- procedure TComponentPropertyEditor.PropertyToEditor;
- var
- aVal : TObject;
- begin
- AVal:=GetObjectProp(Instance,Info);
- if (AVal is TComponent) then
- SetSelectedValue(TComponent(aVal).Name)
- else
- SetSelectedValue('');
- end;
- { TLabelPropertyEditor }
- procedure TLabelPropertyEditor.EditorToProperty;
- Var
- S : String;
- begin
- S:=TJSHTMLLabelElement(ElValue).InnerText;
- SetStrProp(Instance,Info,S);
- end;
- function TLabelPropertyEditor.InitEditor: TJSHTMLElement;
- begin
- Result:=CreateEditorElement('label','');
- end;
- procedure TLabelPropertyEditor.PropertyToEditor;
- begin
- TJSHTMLLabelElement(elValue).InnerText:=GetStrProp(Instance,Info);
- end;
- { TPersistentPropertyEditor }
- procedure TPersistentPropertyEditor.EditorToProperty;
- var
- i : Integer;
- begin
- For I:=0 to SubList.Count-1 do
- TPersistentPropertyEditor(SubList[i]).EditorToProperty;
- end;
- function TPersistentPropertyEditor.InitEditor: TJSHTMLElement;
- Var
- O : TObject;
- I : Integer;
- SPE : TPropertyEditor;
- begin
- Result:=CreateEditorElement('div','');
- ButtonEl:=CreateEditorElement('i','');
- ButtonEl.ClassName:='fi fi-plus';
- Result.AppendChild(ButtonEl);
- Labelel:=CreateEditorElement('span','');
- Labelel.className:='persistentname';
- labelel.InnerText:='?';
- O:=GetObjectProp(Instance,Info);
- Writeln('Getting sublist for ',O.ClassName);
- SubList:=TFPObjectList.Create(True);
- Grid.CreatePropertyList(O,SubList);
- For I:=0 to SubList.Count-1 do
- begin
- SPE:=TPropertyEditor(SubList[i]);
- SPE.InitEditor;
- end;
- end;
- procedure TPersistentPropertyEditor.PropertyToEditor;
- Var
- I : Integer;
- SPE : TPropertyEditor;
- O : TObject;
- begin
- LabelEl.innertext:=GetObjectProp(Instance,Info).ClassName;
- O:=GetObjectProp(Self.Instance,Info);
- For I:=0 to SubList.Count-1 do
- begin
- SPE:=TPropertyEditor(SubList[i]);
- SPE.Instance:=O;
- if Assigned(SPE.Instance) then
- SPE.PropertyToEditor;
- end;
- end;
- { TStringPropertyEditor }
- procedure TStringPropertyEditor.EditorToProperty;
- Var
- S : String;
- begin
- S:=TJSHTMLInputElement(ElValue).value;
- SetStrProp(Instance,Info,S);
- end;
- function TStringPropertyEditor.InitEditor: TJSHTMLElement;
- begin
- Result:=CreateEditorElement('input','');
- TJSHTMLInputElement(Result)._type:='text';
- end;
- procedure TStringPropertyEditor.PropertyToEditor;
- begin
- TJSHTMLInputElement(elValue).Value:=GetStrProp(Instance,Info);
- end;
- { TStringsPropertyEditor }
- procedure TStringsPropertyEditor.EditorToProperty;
- Var
- L : TStrings;
- begin
- L:=TStringList.Create;
- try
- L.Text:=TJSHTMLTextAreaElement(ElValue).value;
- SetObjectProp(Instance,Info,L);
- finally
- l.free;
- end;
- end;
- function TStringsPropertyEditor.InitEditor: TJSHTMLElement;
- Var
- AVal : TObject;
- begin
- Result:=TJSHTMLTextAreaElement(CreateEditorElement('textarea',''));
- Result['rows']:='5';
- Result['columns']:='40';
- end;
- procedure TStringsPropertyEditor.PropertyToEditor;
- Var
- AVal : TObject;
- begin
- AVal:=GetObjectProp(Instance,Info);
- if Assigned(AVal) then
- TJSHTMLTextAreaElement(elValue).Value:=TStrings(aVal).Text
- else
- TJSHTMLTextAreaElement(elValue).Value:='';
- end;
- { TIntegerPropertyEditor }
- procedure TIntegerPropertyEditor.EditorToProperty;
- Var
- S : String;
- I : NativeInt;
- begin
- S:=TJSHTMLInputElement(ElValue).value;
- if TryStrToInt64(S,I) then
- SetOrdProp(Instance,Info,I)
- end;
- function TIntegerPropertyEditor.InitEditor: TJSHTMLElement;
- begin
- Result:=CreateEditorElement('input','');
- Result.Dataset['propname']:=Info.Name;
- TJSHTMLInputElement(Result)._type:='number';
- end;
- procedure TIntegerPropertyEditor.PropertyToEditor;
- begin
- TJSHTMLInputElement(ElValue).Value:=IntToStr(GetOrdProp(Instance,Info));
- end;
- { TBooleanPropertyEditor }
- procedure TBooleanPropertyEditor.EditorToProperty;
- Var
- B : Boolean;
- begin
- B:=TJSHTMLInputElement(ElValue).checked;
- SetBoolProp(Instance,Info,B);
- end;
- function TBooleanPropertyEditor.InitEditor: TJSHTMLElement;
- begin
- Result:=CreateEditorElement('input','');
- TJSHTMLInputElement(Result)._type:='checkbox';
- end;
- procedure TBooleanPropertyEditor.PropertyToEditor;
- begin
- TJSHTMLInputElement(elValue).Checked:=GetBoolProp(Instance,Info);
- end;
- { TPropertyEditor }
- procedure TPropertyEditor.ValueChanged(Event: TJSEvent);
- begin
- If Assigned(OnValueChanged) then
- OnValueChanged(Self);
- EditorToProperty;
- end;
- destructor TPropertyEditor.destroy;
- begin
- FreeAndNil(Sublist);
- inherited destroy;
- end;
- { TSimplePropertyGridWidget }
- procedure TSimplePropertyGridWidget.SetSubject(AValue: TObject);
- begin
- Writeln('Setting subject ', Assigned(aValue));
- if FMySubject=AValue then Exit;
- FMySubject:=AValue;
- if IsRendered then
- Refresh;
- end;
- function TSimplePropertyGridWidget.AllowProperty(M : TTypeMemberProperty) : boolean;
- begin
- Result:=M.TypeInfo.Kind in [tkInteger,tkChar,tkString,tkEnumeration,tkSet,tkDouble,tkBool,tkClass];
- end;
- procedure TSimplePropertyGridWidget.CreatePropertyList(aInstance : TObject; aList: TFPObjectList);
- Var
- R : TPropertyEditor;
- M: TTypeMemberProperty;
- begin
- aList.Clear;
- if Not Assigned(aInstance) then
- exit;
- for M in GetPropList(aInstance) do
- if AllowProperty(M) then
- begin
- // Writeln('Row for property ',M.Name);
- R:=CreatePropertyEditor(aInstance,M);
- if R<>Nil then
- aList.Add(R);
- end;
- end;
- constructor TSimplePropertyGridWidget.Create(aOwner: TComponent);
- begin
- inherited Create(aOwner);
- FProperties:=TFPObjectList.Create(True);
- end;
- destructor TSimplePropertyGridWidget.Destroy;
- begin
- FreeAndNil(FProperties);
- inherited Destroy;
- end;
- function TSimplePropertyGridWidget.DoRenderHTML(aParent, aElement: TJSHTMLElement) : TJSHTMLElement;
- begin
- // Writeln('Grid Render HTML',assigned(FMySubject));
- Result:=Inherited DoRenderHTML(aParent,aElement);
- CreatePropertyList(FMySubject,FProperties);
- aElement.className:='propGridTable table-bordered table-sm table-dark';
- CreatePropertyGrid(aElement,Nil,FMySubject,FProperties);
- end;
- procedure TSimplePropertyGridWidget.CreatePropertyGrid(aTableElement, aRowElement: TJSHTMLElement; FMySubject: TObject;
- aProperties: TFPObjectList);
- Var
- R : TPropertyEditor;
- TR,TD : TJSHTMLElement;
- I : integer;
- O : TObject;
- begin
- For I:=0 to aProperties.Count-1 do
- begin
- R:=TPropertyEditor(aProperties[i]);
- TR:=CreateEditorElement('tr','');
- TR.dataset['propertyName']:=R.Info.Name;
- TR.ClassName:='propGridRow';
- R.ElRow:=TR;
- aTableElement.AppendChild(TR);
- TD:=CreateEditorElement('td','');
- TD.className:='propGridNameCell';
- TR.AppendChild(TD);
- TD.InnerText:=R.Info.Name;
- R.ElName:=TD;
- TD:=CreateEditorElement('td','');
- TD.className:='propGridDataCell';
- TR.AppendChild(TD);
- R.ElValue:=R.InitEditor;
- if Assigned(R.ElValue) then
- begin
- R.PropertyToEditor;
- R.ElValue.Dataset['propname']:=R.Info.Name;
- R.ElValue.addEventListener('change',@R.ValueChanged);
- end;
- TD.AppendChild(R.ElValue);
- if Assigned(R.SubList) then
- begin
- O:=GetObjectProp(R.Instance,R.Info);
- if Assigned(O) then
- CreatePropertyGrid(aTableElement,TR,O,R.Sublist);
- end;
- end;
- end;
- function TSimplePropertyGridWidget.DoIntegerEditor(aEditor : TJSHTMLElement; aInfo: TPropertyEditor) : TJSHTMLElement;
- begin
- Result:=aEditor;
- if Result=Nil then
- begin
- Result:=CreateEditorElement('input','');
- Result.Dataset['propname']:=aInfo.Info.Name;
- TJSHTMLInputElement(Result)._type:='number';
- end;
- TJSHTMLInputElement(Result).Value:=IntToStr(GetOrdProp(aInfo.Instance,aInfo.Info));
- end;
- function TSimplePropertyGridWidget.DoFloatEditor(aEditor : TJSHTMLElement; aInfo: TPropertyEditor) : TJSHTMLElement;
- begin
- Result:=aEditor;
- if Result=Nil then
- begin
- Result:=CreateEditorElement('input','');
- Result.Dataset['propname']:=aInfo.Info.Name;
- TJSHTMLInputElement(Result)._type:='number';
- end;
- TJSHTMLInputElement(Result).Value:=FloatToStr(GetFloatProp(aInfo.Instance,aInfo.Info));
- end;
- function TSimplePropertyGridWidget.DoStringEditor(aEditor : TJSHTMLElement; aInfo: TPropertyEditor) : TJSHTMLElement;
- begin
- Result:=aEditor;
- if Result=Nil then
- begin
- Result:=CreateEditorElement('input','');
- TJSHTMLInputElement(Result)._type:='text';
- end;
- TJSHTMLInputElement(Result).Value:=GetStrProp(aInfo.Instance,aInfo.Info);
- end;
- function TSimplePropertyGridWidget.DoBooleanEditor(aEditor : TJSHTMLElement; aInfo: TPropertyEditor) : TJSHTMLElement;
- begin
- end;
- function TSimplePropertyGridWidget.DoEnumerationEditor(aEditor : TJSHTMLElement; aInfo: TPropertyEditor) : TJSHTMLElement;
- Var
- inp : TJSHTMLSelectElement;
- O,osel : TJSHTMLOptionElement;
- avalS : String;
- aVal,I : Integer;
- begin
- oSel:=nil;
- Result:=aEditor;
- AVal:=GetOrdProp(aInfo.Instance,aInfo.Info);
- aValS:=IntTostr(aVal);
- if Result=Nil then
- begin
- Result:=CreateEditorElement('select','');
- Inp:=TJSHTMLSelectElement(Result);
- inp.Multiple:=False;
- for I:=TTypeInfoEnum(aInfo.Info.TypeInfo).MinValue to TTypeInfoEnum(aInfo.Info.TypeInfo).MaxValue do
- begin
- O:=TJSHTMLOptionElement(CreateEditorElement('option',''));
- O.InnerText:=TTypeInfoEnum(aInfo.Info.TypeInfo).EnumType.IntToName[I];
- O.value:=IntToStr(I);
- if I=aVal then
- oSel:=o;
- Inp.appendChild(O)
- end;
- end
- else
- begin
- Inp:=TJSHTMLSelectElement(Result);
- for I:=0 to inp.options.length-1 do
- if TJSHTMLOptionElement(inp.options.Items[i]).value=aVals then
- oSel:=TJSHTMLOptionElement(inp.options.Items[i]);
- end;
- if assigned(oSel) then
- oSel.selected:=True;
- Inp.Value:=IntToStr(GetOrdProp(aInfo.Instance,aInfo.Info));
- end;
- function TSimplePropertyGridWidget.DoSetEditor(aEditor : TJSHTMLElement; aInfo: TPropertyEditor) : TJSHTMLElement;
- Var
- inp : TJSHTMLTableElement;
- cell : TJSHTMLTableDataCellElement;
- r : TJSHTMLTableRowElement;
- vals : TIntegerDynArray;
- eInfo : TTypeInfoEnum;
- I : Integer;
- selcb,CB : TJSHTMLInputElement;
- lbl : TJSHTMLLabelElement;
- begin
- result:=aEditor;
- eInfo:=TTypeInfoEnum(TTypeInfoSet(aInfo.Info.TypeInfo).CompType);
- vals:=GetSetPropArray(aInfo.instance,aInfo.Info);
- if Result=Nil then
- begin
- Result:=CreateEditorElement('table','');
- // Row with the property as a string.
- R:=TJSHTMLTableRowElement(CreateEditorElement('tr',''));
- Result.Append(R);
- cell:=TJSHTMLTableDatacellElement(CreateEditorElement('td',''));
- cell.InnerText:=GetSetProp(aInfo.instance,aInfo.Info);
- R.AppendChild(Cell);
- // For every element in the set, a checkbox row
- for I:=TTypeInfoEnum(aInfo.Info.TypeInfo).MinValue to TTypeInfoEnum(aInfo.Info.TypeInfo).MaxValue do
- begin
- // Row
- R:=TJSHTMLTableRowElement(CreateEditorElement('tr',''));
- Result.Append(R);
- // Cell
- cell:=TJSHTMLTableDatacellElement(CreateEditorElement('td',''));
- R.AppendChild(Cell);
- // Input
- CB:=TJSHTMLInputElement(CreateEditorElement('input',''));
- cb._type:='checkbox';
- cb.id:=GenerateID;
- cb.dataset['enumval']:=IntTostr(i);
- cell.AppendChild(cb);
- // label for input
- lbl:=TJSHTMLLabelElement(CreateEditorElement('label',''));
- lbl.For_:=cb.Id;
- lbl.InnerText:=TTypeInfoEnum(aInfo.Info.TypeInfo).EnumType.IntToName[I];
- cell.AppendChild(lbl);
- end;
- end;
- end;
- function TSimplePropertyGridWidget.DoComponentEditor(aEditor : TJSHTMLElement; aInfo: TPropertyEditor) : TJSHTMLElement;
- Var
- inp : TJSHTMLSelectElement;
- O,osel : TJSHTMLOptionElement;
- I : Integer;
- L,aVal : TObject;
- begin
- oSel:=nil;
- Result:=aEditor;
- AVal:=GetObjectProp(aInfo.Instance,aInfo.Info);
- if Result=Nil then
- begin
- Result:=CreateEditorElement('select','');
- Inp:=TJSHTMLSelectElement(Result);
- inp.Multiple:=False;
- if Assigned(LookupRoot) then
- begin
- For I:=0 to LookupRoot.ComponentCount-1 do
- begin
- O:=TJSHTMLOptionElement(CreateEditorElement('option',''));
- O.InnerText:=LookupRoot.Components[i].Name;
- O.value:=LookupRoot.Components[i].Name;
- if aVal=LookupRoot.Components[i] then
- oSel:=o;
- Inp.appendChild(O);
- end;
- end;
- end
- else
- begin
- Inp:=TJSHTMLSelectElement(Result);
- if Assigned(LookupRoot) then
- begin
- I:=0;
- While (oSeL=Nil) and (I<inp.options.length) do
- begin
- O:=TJSHTMLOptionElement(inp.options.Items[i]);
- L:=LookupRoot.FindComponent(O.Value);
- if L=aval then
- oSel:=O;
- inc(I);
- end;
- end;
- end;
- if assigned(oSel) then
- oSel.selected:=True;
- end;
- function TSimplePropertyGridWidget.DoLabelEditor(aEditor : TJSHTMLElement; aInfo: TPropertyEditor) : TJSHTMLElement;
- Var
- AVal : TObject;
- begin
- AVal:=GetObjectProp(aInfo.Instance,aInfo.Info);
- Result:=aEditor;
- if Result=Nil then
- Result:=TJSHTMLLabelElement(CreateEditorElement('label',''));
- Result.InnerText:=aVal.ClassName;
- end;
- function TSimplePropertyGridWidget.DoPersistentEditor(aEditor : TJSHTMLElement; aInfo: TPropertyEditor) : TJSHTMLElement;
- Var
- AVal : TObject;
- begin
- AVal:=GetObjectProp(aInfo.Instance,aInfo.Info);
- Result:=aEditor;
- if Result=Nil then
- Result:=TJSHTMLLabelElement(CreateEditorElement('label',''));
- Result.InnerText:=aVal.ClassName;
- end;
- function TSimplePropertyGridWidget.DoStringsEditor(aEditor : TJSHTMLElement; aInfo: TPropertyEditor) : TJSHTMLElement;
- Var
- AVal : TObject;
- begin
- AVal:=GetObjectProp(aInfo.Instance,aInfo.Info);
- Result:=aEditor;
- if Result=Nil then
- begin
- Result:=TJSHTMLTextAreaElement(CreateEditorElement('textarea',''));
- Result['rows']:='5';
- end;
- Result.InnerText:=aVal.ClassName;
- end;
- function TSimplePropertyGridWidget.CreatePropertyEditor (aInstance : TObject; aInfo: TTypeMemberProperty) : TpropertyEditor;
- Var
- EditorClass : TPropertyEditorClass;
- aEditor : TPropertyEditor;
- begin
- EditorClass:=nil;
- Result:=Nil;
- // Writeln('Creating property grid editor for ',aInfo.Info.Name);
- case aInfo.TypeInfo.Kind of
- tkInteger : EditorClass:=TIntegerPropertyEditor;
- tkChar : EditorClass:=TStringPropertyEditor;
- tkString : EditorClass:=TStringPropertyEditor;
- tkEnumeration : EditorClass:=TEnumerationPropertyEditor;
- tkSet : EditorClass:=TSetPropertyEditor;
- tkDouble : EditorClass:=TFloatPropertyEditor;
- tkBool : EditorClass:=TBooleanPropertyEditor;
- tkClass :
- begin
- If TTypeInfoClass(aInfo.TypeInfo).ClassType.InheritsFrom(TComponent) then
- EditorClass:=TComponentPropertyEditor
- else if TTypeInfoClass(aInfo.TypeInfo).ClassType.InheritsFrom(TStrings) then
- EditorClass:=TStringsPropertyEditor
- else if TTypeInfoClass(aInfo.TypeInfo).ClassType.InheritsFrom(TPersistent) then
- EditorClass:=TPersistentPropertyEditor
- else
- EditorClass:=TLabelPropertyEditor;
- end;
- end;
- if Assigned(EditorClass) then
- Result:= EditorClass.Create(self,aInstance,aInfo);
- end;
- procedure TSimplePropertyGridWidget.DoPropertyChanged(Sender: TObject);
- Var
- aRow : TPropertyEditor absolute sender;
- begin
- Writeln('Property ',aRow.Info.Name,' changed');
- end;
- (*
- procedure TSimplePropertyGridWidget.ApplyIntegerEditor(aRow : TPropertyEditor);
- Var
- S : String;
- I : NativeInt;
- begin
- S:=TJSHTMLInputElement(aRow.ElValue).value;
- if TryStrToInt64(S,I) then
- SetOrdProp(aRow.Instance,aRow.Info,I)
- end;
- procedure TSimplePropertyGridWidget.ApplyStringEditor(aRow : TPropertyEditor);
- Var
- S : String;
- begin
- S:=TJSHTMLInputElement(aRow.ElValue).value;
- SetStrProp(aRow.Instance,aRow.Info,S);
- end;
- procedure TSimplePropertyGridWidget.ApplyEnumEditor(aRow : TPropertyEditor);
- Var
- Sel : TJSHTMLSelectElement;
- begin
- Sel:=TJSHTMLSelectElement(aRow.ElValue);
- SetOrdProp(aRow.Instance,aRow.Info,StrToInt(TJSHTMLOptionElement(Sel.Options.Items[Sel.selectedIndex]).value));
- end;
- procedure TSimplePropertyGridWidget.ApplySetEditor(aRow : TPropertyEditor);
- begin
- end;
- procedure TSimplePropertyGridWidget.ApplyFloatEditor(aRow : TPropertyEditor);
- Var
- S : String;
- D : Double;
- Err : Integer;
- begin
- S:=TJSHTMLInputElement(aRow.ElValue).value;
- val(S,D,Err);
- if Err<>0 then
- if TryStrToFloat(S,D) then
- Err:=0;
- if Err=0 then
- SetFloatProp(aRow.Instance,aRow.Info,D);
- end;
- procedure TSimplePropertyGridWidget.ApplyBooleanEditor(aRow : TPropertyEditor);
- begin
- end;
- procedure TSimplePropertyGridWidget.ApplyComponentEditor(aRow : TPropertyEditor);
- begin
- end;
- procedure TSimplePropertyGridWidget.ApplyStringsEditor(aRow : TPropertyEditor);
- begin
- end;
- procedure TSimplePropertyGridWidget.ApplyPersistentEditor(aRow : TPropertyEditor);
- begin
- end;
- *)
- procedure TSimplePropertyGridWidget.UpdatePropertyFromEditor(aRow : TPropertyEditor);
- begin
- // Writeln('Creating property grid editor for ',aInfo.Info.Name);
- (*
- case Arow.Info.TypeInfo.Kind of
- tkInteger : ApplyIntegerEditor(aRow);
- tkChar : ApplyStringEditor(aRow);
- tkString : ApplyStringEditor(aRow);
- tkEnumeration : ApplyEnumEditor(aRow);
- tkSet : ApplySetEditor(aRow);
- tkDouble : ApplyFloatEditor(aRow);
- tkBool : ApplyBooleanEditor(aRow);
- tkClass :
- begin
- If TTypeInfoClass(aRow.Info.TypeInfo).ClassType.InheritsFrom(TComponent) then
- ApplyComponentEditor(aRow)
- else if TTypeInfoClass(aRow.Info.TypeInfo).ClassType.InheritsFrom(TStrings) then
- ApplyStringsEditor(aRow)
- else if TTypeInfoClass(aRow.Info.TypeInfo).ClassType.InheritsFrom(TPersistent) then
- ApplyPersistentEditor(aRow)
- end;
- end;
- *)
- // RefreshProperties(aRow);
- end;
- function TSimplePropertyGridWidget.CreateEditorElement(aTag: String; aID: String): TJSHTMLElement;
- begin
- Result:=CreateElement(aTag,aID);
- Case lowercase(aTag) of
- 'input',
- 'select' :
- Result.className:='form-control';
- end;
- end;
- procedure TSimplePropertyGridWidget.SetLookupRoot(AValue: TComponent);
- begin
- if FLookupRoot=AValue then Exit;
- FLookupRoot:=AValue;
- if IsRendered then
- Refresh;
- end;
- procedure TPropertyEditor.SetInstance(AValue: TObject);
- begin
- if FInstance=AValue then Exit;
- FInstance:=AValue;
- end;
- function TPropertyEditor.CreateEditorElement(aTag: String; aID: String): TJSHTMLElement;
- begin
- Result:=Grid.CreateEditorElement(aTag,aID);
- end;
- constructor TPropertyEditor.Create(aGrid: TSimplePropertyGridWidget; aInstance: TObject; aInfo: TTypeMemberProperty);
- begin
- FGrid:=aGrid;
- FInstance:=aInstance;
- FInfo:=aInfo;
- end;
- function TSimplePropertyGridWidget.HTMLTag: String;
- begin
- Result:='TABLE';
- end;
- end.
|