From 81538babe26dedf63d7b867c2a5a2c16ff0df5f4 Mon Sep 17 00:00:00 2001 From: michael Date: Fri, 27 Nov 2020 16:34:51 +0000 Subject: [PATCH] * Merging revisions 941,942,950,951,952,953 from trunk: ------------------------------------------------------------------------ r941 | svenbarth | 2020-11-13 16:02:27 +0100 (Fri, 13 Nov 2020) | 1 line * TStack<>.TrimExcess should override TCustomList<>.TrimExcess ------------------------------------------------------------------------ r942 | svenbarth | 2020-11-15 12:26:08 +0100 (Sun, 15 Nov 2020) | 1 line * fix compilation of Tetris demo ------------------------------------------------------------------------ r950 | michael | 2020-11-24 15:59:49 +0100 (Tue, 24 Nov 2020) | 1 line * Added rendercolumn, so columns can be disabled ------------------------------------------------------------------------ r951 | michael | 2020-11-25 12:15:19 +0100 (Wed, 25 Nov 2020) | 1 line * Add Focus and ReplaceClasses/AddRemoveClasses ------------------------------------------------------------------------ r952 | michael | 2020-11-27 09:41:43 +0100 (Fri, 27 Nov 2020) | 1 line * Make creation of data-tags optional ------------------------------------------------------------------------ r953 | michael | 2020-11-27 17:12:43 +0100 (Fri, 27 Nov 2020) | 1 line * Correct options objects ------------------------------------------------------------------------ --- demo/tetris/utetris.pp | 2 +- packages/rtl/generics.collections.pas | 2 +- packages/rtl/webaudio.pas | 60 ++++++------ packages/webwidget/htmlwidgets.pp | 33 ++++--- packages/webwidget/webwidget.pas | 126 +++++++++++++++++++++----- 5 files changed, 157 insertions(+), 66 deletions(-) diff --git a/demo/tetris/utetris.pp b/demo/tetris/utetris.pp index 6ee39ab..b62fd16 100644 --- a/demo/tetris/utetris.pp +++ b/demo/tetris/utetris.pp @@ -627,7 +627,7 @@ Var S : String; begin Result:=true; - S:=aEvent.currentTarget.ID; + S:=aEvent.currentTargetElement.ID; aEvent.preventDefault; if Copy(S,1,Length(SControl))=SControl then begin diff --git a/packages/rtl/generics.collections.pas b/packages/rtl/generics.collections.pas index 1250588..60dc29b 100644 --- a/packages/rtl/generics.collections.pas +++ b/packages/rtl/generics.collections.pas @@ -326,7 +326,7 @@ type function Pop: T; function Peek: T; function Extract: T; - procedure TrimExcess; + procedure TrimExcess; override; property Count: SizeInt read GetCount; end; diff --git a/packages/rtl/webaudio.pas b/packages/rtl/webaudio.pas index 941c953..05ffc8b 100644 --- a/packages/rtl/webaudio.pas +++ b/packages/rtl/webaudio.pas @@ -131,7 +131,7 @@ Type TJSAudioContextOptions --------------------------------------------------------------------} - TJSAudioContextOptions = class(TJSObject) + TJSAudioContextOptions = class external name 'Object' (TJSObject) latencyHint : JSValue; sampleRate : Double; end; @@ -140,7 +140,7 @@ Type TJSAudioTimestamp --------------------------------------------------------------------} - TJSAudioTimestamp = class(TJSObject) + TJSAudioTimestamp = class external name 'Object' (TJSObject) contextTime : Double; performanceTime : TJSDOMHighResTimeStamp; end; @@ -149,7 +149,7 @@ Type TJSOfflineAudioContextOptions --------------------------------------------------------------------} - TJSOfflineAudioContextOptions = class(TJSObject) + TJSOfflineAudioContextOptions = class external name 'Object' (TJSObject) numberOfChannels : NativeInt; length_ : NativeInt;external name 'length'; sampleRate : Double; @@ -159,7 +159,7 @@ Type TJSOfflineAudioCompletionEventInit --------------------------------------------------------------------} - TJSOfflineAudioCompletionEventInit = class(TJSObject) + TJSOfflineAudioCompletionEventInit = class external name 'Object' (TJSObject) renderedBuffer : TJSAudioBuffer; end; @@ -167,7 +167,7 @@ Type TJSAudioBufferOptions --------------------------------------------------------------------} - TJSAudioBufferOptions = class(TJSObject) + TJSAudioBufferOptions = class external name 'Object' (TJSObject) numberOfChannels : NativeInt; length_ : NativeInt;external name 'length'; sampleRate : Double; @@ -177,7 +177,7 @@ Type TJSAudioNodeOptions --------------------------------------------------------------------} - TJSAudioNodeOptions = class(TJSObject) + TJSAudioNodeOptions = class external name 'Object' (TJSObject) channelCount : NativeInt; _channelCountMode : ChannelCountMode;external name 'channelCountMode'; _channelInterpretation : ChannelInterpretation;external name 'channelInterpretation'; @@ -187,7 +187,7 @@ Type TJSAnalyserOptions --------------------------------------------------------------------} - TJSAnalyserOptions = class(TJSObject) + TJSAnalyserOptions = class external name 'Object' (TJSObject) fftSize : NativeInt; maxDecibels : Double; minDecibels : Double; @@ -198,7 +198,7 @@ Type TJSAudioBufferSourceOptions --------------------------------------------------------------------} - TJSAudioBufferSourceOptions = class(TJSObject) + TJSAudioBufferSourceOptions = class external name 'Object' (TJSObject) buffer : TJSAudioBuffer; detune : Double; loop : boolean; @@ -211,7 +211,7 @@ Type TJSAudioProcessingEventInit --------------------------------------------------------------------} - TJSAudioProcessingEventInit = class(TJSObject) + TJSAudioProcessingEventInit = class external name 'Object' (TJSObject) playbackTime : Double; inputBuffer : TJSAudioBuffer; outputBuffer : TJSAudioBuffer; @@ -221,7 +221,7 @@ Type TJSBiquadFilterOptions --------------------------------------------------------------------} - TJSBiquadFilterOptions = class(TJSObject) + TJSBiquadFilterOptions = class external name 'Object' (TJSObject) type_ : BiquadFilterType;external name 'type'; Q : Double; detune : Double; @@ -233,7 +233,7 @@ Type TJSChannelMergerOptions --------------------------------------------------------------------} - TJSChannelMergerOptions = class(TJSObject) + TJSChannelMergerOptions = class external name 'Object' (TJSObject) numberOfInputs : NativeInt; end; @@ -241,7 +241,7 @@ Type TJSChannelSplitterOptions --------------------------------------------------------------------} - TJSChannelSplitterOptions = class(TJSObject) + TJSChannelSplitterOptions = class external name 'Object' (TJSObject) numberOfOutputs : NativeInt; end; @@ -249,7 +249,7 @@ Type TJSConstantSourceOptions --------------------------------------------------------------------} - TJSConstantSourceOptions = class(TJSObject) + TJSConstantSourceOptions = class external name 'Object' (TJSObject) offset : Double; end; @@ -257,7 +257,7 @@ Type TJSConvolverOptions --------------------------------------------------------------------} - TJSConvolverOptions = class(TJSObject) + TJSConvolverOptions = class external name 'Object' (TJSObject) buffer : TJSAudioBuffer; disableNormalization : boolean; end; @@ -266,7 +266,7 @@ Type TJSDelayOptions --------------------------------------------------------------------} - TJSDelayOptions = class(TJSObject) + TJSDelayOptions = class external name 'Object' (TJSObject) maxDelayTime : Double; delayTime : Double; end; @@ -275,7 +275,7 @@ Type TJSDynamicsCompressorOptions --------------------------------------------------------------------} - TJSDynamicsCompressorOptions = class(TJSObject) + TJSDynamicsCompressorOptions = class external name 'Object' (TJSObject) attack : Double; knee : Double; ratio : Double; @@ -287,7 +287,7 @@ Type TJSGainOptions --------------------------------------------------------------------} - TJSGainOptions = class(TJSObject) + TJSGainOptions = class external name 'Object' (TJSObject) gain : Double; end; @@ -295,7 +295,7 @@ Type TJSIIRFilterOptions --------------------------------------------------------------------} - TJSIIRFilterOptions = class(TJSObject) + TJSIIRFilterOptions = class external name 'Object' (TJSObject) feedforward : TDoubleDynArray; feedback : TDoubleDynArray; end; @@ -304,7 +304,7 @@ Type TJSMediaElementAudioSourceOptions --------------------------------------------------------------------} - TJSMediaElementAudioSourceOptions = class(TJSObject) + TJSMediaElementAudioSourceOptions = class external name 'Object' (TJSObject) mediaElement : TJSElement; end; @@ -312,7 +312,7 @@ Type TJSMediaStreamAudioSourceOptions --------------------------------------------------------------------} - TJSMediaStreamAudioSourceOptions = class(TJSObject) + TJSMediaStreamAudioSourceOptions = class external name 'Object' (TJSObject) mediaStream : JSValue; end; @@ -320,7 +320,7 @@ Type TJSMediaStreamTrackAudioSourceOptions --------------------------------------------------------------------} - TJSMediaStreamTrackAudioSourceOptions = class(TJSObject) + TJSMediaStreamTrackAudioSourceOptions = class external name 'Object' (TJSObject) mediaStreamTrack : JSValue; end; @@ -328,7 +328,7 @@ Type TJSOscillatorOptions --------------------------------------------------------------------} - TJSOscillatorOptions = class(TJSObject) + TJSOscillatorOptions = class external name 'Object' (TJSObject) type_ : OscillatorType;external name 'type'; frequency : Double; detune : Double; @@ -339,7 +339,7 @@ Type TJSPannerOptions --------------------------------------------------------------------} - TJSPannerOptions = class(TJSObject) + TJSPannerOptions = class external name 'Object' (TJSObject) panningModel : PanningModelType; distanceModel : DistanceModelType; positionX : Double; @@ -360,7 +360,7 @@ Type TJSPeriodicWaveConstraints --------------------------------------------------------------------} - TJSPeriodicWaveConstraints = class(TJSObject) + TJSPeriodicWaveConstraints = class external name 'Object' (TJSObject) disableNormalization : boolean; end; @@ -368,7 +368,7 @@ Type TJSPeriodicWaveOptions --------------------------------------------------------------------} - TJSPeriodicWaveOptions = class(TJSObject) + TJSPeriodicWaveOptions = class external name 'Object' (TJSObject) real : TDoubleDynArray; imag : TDoubleDynArray; end; @@ -377,7 +377,7 @@ Type TJSStereoPannerOptions --------------------------------------------------------------------} - TJSStereoPannerOptions = class(TJSObject) + TJSStereoPannerOptions = class external name 'Object' (TJSObject) pan : Double; end; @@ -385,7 +385,7 @@ Type TJSWaveShaperOptions --------------------------------------------------------------------} - TJSWaveShaperOptions = class(TJSObject) + TJSWaveShaperOptions = class external name 'Object' (TJSObject) curve : TDoubleDynArray; oversample : OverSampleType; end; @@ -394,7 +394,7 @@ Type TJSAudioWorkletNodeOptions --------------------------------------------------------------------} - TJSAudioWorkletNodeOptions = class(TJSObject) + TJSAudioWorkletNodeOptions = class external name 'Object' (TJSObject) numberOfInputs : NativeInt; numberOfOutputs : NativeInt; outputChannelCount : TNativeIntDynArray; @@ -406,7 +406,7 @@ Type TJSAudioParamDescriptor --------------------------------------------------------------------} - TJSAudioParamDescriptor = class(TJSObject) + TJSAudioParamDescriptor = class external name 'Object' (TJSObject) name : String; defaultValue : Double; minValue : Double; @@ -539,7 +539,7 @@ Type TJSAudioNode --------------------------------------------------------------------} - TJSAudioNode = class external name 'AudioNode' (TJSEventTarget) +TJSAudioNode = class external name 'AudioNode' (TJSEventTarget) Private Fcontext : TJSBaseAudioContext; external name 'context'; FnumberOfInputs : NativeInt; external name 'numberOfInputs'; diff --git a/packages/webwidget/htmlwidgets.pp b/packages/webwidget/htmlwidgets.pp index 8615d4d..8544817 100644 --- a/packages/webwidget/htmlwidgets.pp +++ b/packages/webwidget/htmlwidgets.pp @@ -627,6 +627,7 @@ Type procedure SetCaption(AValue: String); procedure SetClassNames(AValue: String); Protected + Function RenderColumn : Boolean; virtual; Function GetDisplayName: string; override; function GetCaption: String; virtual; Public @@ -1543,19 +1544,20 @@ Var begin For I:=0 to CustomColumns.Count-1 do - begin - aCell.Reset; - aCell.FColumn:=CustomColumns[i]; - aCell.SetRowColKind(-1,I,aKind); -// Writeln(CellKinds[aKind],' cell before : ',aCell.Tag,' data : ',aCell.Text); - aEnum.GetCellData(aCell); -// Writeln(CellKinds[aKind],' cell after : ',aCell.Tag,' data : ',aCell.Text); - if aCell.Tag='' then - ACell.Tag:=CellTags[aKind]; - if Assigned(FOnGetCellData) then - FOnGetCellData(Self,aEnum,aCell); - aParent.appendChild(RenderCell(aCell)); - end; + if CustomColumns[i].RenderColumn then + begin + aCell.Reset; + aCell.FColumn:=CustomColumns[i]; + aCell.SetRowColKind(-1,I,aKind); + // Writeln(CellKinds[aKind],' cell before : ',aCell.Tag,' data : ',aCell.Text); + aEnum.GetCellData(aCell); + // Writeln(CellKinds[aKind],' cell after : ',aCell.Tag,' data : ',aCell.Text); + if aCell.Tag='' then + ACell.Tag:=CellTags[aKind]; + if Assigned(FOnGetCellData) then + FOnGetCellData(Self,aEnum,aCell); + aParent.appendChild(RenderCell(aCell)); + end; end; procedure TCustomTableWidget.RenderRows(aParent: TJSHTMLElement; aKind: TRowKind; aCell: TTableWidgetCellData); @@ -1760,6 +1762,11 @@ begin FClassNames:=AValue; end; +function TCustomTableColumn.RenderColumn: Boolean; +begin + Result:=True; +end; + function TCustomTableColumn.GetDisplayName: string; begin Result:=Caption; diff --git a/packages/webwidget/webwidget.pas b/packages/webwidget/webwidget.pas index 00316f6..e3e2324 100644 --- a/packages/webwidget/webwidget.pas +++ b/packages/webwidget/webwidget.pas @@ -447,16 +447,24 @@ Type Property HaveReferences : Boolean Read GetHaveReferences; // Property attrs Property StoredAttrs : TJSObject Read FAttrs; + Public + Class var CreateDataTags : Boolean; Public Constructor Create(aOwner : TComponent); override; Destructor Destroy; override; // Does this element allow childern ? Class Function AllowChildren : Boolean; virtual; // Manipulate Classes + Class Function AddRemoveClasses(const Source, aAddClasses, aRemoveClasses : String; Normalize : Boolean = false) : String; + // Number of classes in search and replace must match. + Class Function ReplaceClasses(const Source, aSearchClasses, aReplaceClasses : String; Normalize : Boolean = false) : String; Class Function RemoveClasses(const Source, aClasses : String; Normalize : Boolean = false) : String; Class Function RemoveClasses(el : TJSHTMLElement; const aClasses : String; Normalize : Boolean = false) : String; Class Function AddClasses(const Source, aClasses : String; Normalize : Boolean = false) : String; Class Function AddClasses(el : TJSHTMLElement; const aClasses : String; Normalize : Boolean = false) : String; + Class Function AddRemoveClasses(el : TJSHTMLElement; const aAddClasses, aRemoveClasses : String; Normalize : Boolean = false) : String; + // Number of classes in search and replace must match. + Class Function ReplaceClasses(el : TJSHTMLElement; const aSearchClasses, aReplaceClasses : String; Normalize : Boolean = false) : String; // Manipulate styles function EnsureStyle(const aName: String): TStyleItem; function AddStyle(const aName,aValue: String): TStyleItem; @@ -469,7 +477,11 @@ Type Procedure Refresh; // Unrender Procedure Unrender; overload; + // Focus widget. Will render if it was not yet rendered. + Procedure Focus; // These work on the classes property, and on the current element if rendered. Returns the new value of classes. + Function AddRemoveClasses(const aAddClasses, aRemoveClasses : String; Normalize : Boolean = false) : String; + Function ReplaceClasses(const aSearchClasses, aReplaceClasses : String; Normalize : Boolean = false) : String; Function RemoveClasses(const aClasses : String; Normalize : Boolean = false) : String; Function AddClasses(const aClasses : String; Normalize : Boolean = false) : String; // Finding widgets @@ -2755,6 +2767,14 @@ begin UnRender(P); end; +procedure TCustomWebWidget.Focus; +begin + if not IsRendered then + ReFresh; + Element.Focus; +end; + + procedure TCustomWebWidget.ApplyWidgetSettings(aElement: TJSHTMLElement); // Normally, this should be called BEFORE FElement is set. @@ -2801,13 +2821,13 @@ Var Procedure MaybeSet(El : TJSHTMLElement; AName : String); begin - if Assigned(el) then + if Assigned(el) and CreateDataTags then el.Dataset[aName]:=AID; end; begin AID:=ElementID; - if assigned(Element) then + if assigned(Element) and Not CreateDataTags then Element.dataset[SElementClass]:=ClassName; MaybeSet(Element,SElementData); MaybeSet(TopElement,STopElementData); @@ -2950,8 +2970,8 @@ begin Result:=True; end; -class function TCustomWebWidget.RemoveClasses(const Source, aClasses: String; Normalize : Boolean = false): String; - +class function TCustomWebWidget.AddRemoveClasses(const Source, aAddClasses, + aRemoveClasses: String; Normalize: Boolean): String; var T : TJSStringDynArray; i : integer; @@ -2961,16 +2981,63 @@ begin if Normalize then Result:=TJSString(Result).replace(TJSRegexp.New('\s\s+','g'),' '); T:=TJSString(Result).split(' '); - For S in TJSString(aClasses).split(' ') do + For S in TJSString(aRemoveClasses).split(' ') do if (S<>'') then begin I:=TJSArray(T).indexOf(S); if (I<>-1) then TJSArray(T).splice(i,1); end; + For S in TJSString(aAddClasses).split(' ') do + if (S<>'') then + begin + I:=TJSArray(T).indexOf(S); + if (I=-1) then + TJSArray(T).Push(S); + end; Result:=TJSArray(T).join(' '); end; +class function TCustomWebWidget.ReplaceClasses(const Source, aSearchClasses, aReplaceClasses : String; Normalize: Boolean): String; +var + Dest,Srch,Repl : TJSStringDynArray; + sIdx,I : integer; + S : String; + +begin + Srch:=TJSString(aSearchClasses).split(' '); + Repl:=TJSString(aReplaceClasses).split(' '); + Result:=Source; + if Normalize then + Result:=TJSString(Result).replace(TJSRegexp.New('\s\s+','g'),' '); + Dest:=TJSString(Result).split(' '); + For sIdx:=0 to length(Srch)-1 do + begin + S:=Srch[sIdx]; + if (S<>'') then + begin + I:=TJSArray(Dest).indexOf(S); + if (I<>-1) then + begin + TJSArray(Dest).splice(i,1); + if sIdx'') then - begin - if (TJSArray(T).indexOf(S)=-1) then - TJSArray(T).Push(S); - end; - Result:=TJSArray(T).Join(' '); + Result:=AddRemoveClasses(Source,aClasses,'',Normalize); end; class function TCustomWebWidget.AddClasses(el: TJSHTMLElement; const aClasses: String; Normalize : Boolean = false): String; @@ -3006,6 +3058,38 @@ begin el.ClassName:=Trim(Result); end; +class function TCustomWebWidget.AddRemoveClasses(el: TJSHTMLElement; + const aAddClasses, aRemoveClasses: String; Normalize: Boolean): String; +begin + Result:=AddRemoveClasses(el.ClassName,aAddClasses,aRemoveClasses,Normalize); + el.ClassName:=Trim(Result); +end; + +class function TCustomWebWidget.ReplaceClasses(el: TJSHTMLElement; + const aSearchClasses, aReplaceClasses: String; Normalize: Boolean): String; +begin + Result:=ReplaceClasses(el.ClassName,aSearchClasses, aReplaceClasses,Normalize); + el.ClassName:=Trim(Result); +end; + +function TCustomWebWidget.AddRemoveClasses(const aAddClasses, + aRemoveClasses: String; Normalize: Boolean): String; +begin + FClasses:=AddRemoveClasses(FClasses,aAddClasses,aRemoveClasses,Normalize); + Result:=FClasses; + if IsRendered then + Result:=AddRemoveClasses(FElement,aAddClasses,aRemoveClasses,Normalize) +end; + +function TCustomWebWidget.ReplaceClasses(const aSearchClasses, + aReplaceClasses: String; Normalize: Boolean): String; +begin + FClasses:=ReplaceClasses(FClasses,aSearchClasses,aReplaceClasses,Normalize); + Result:=FClasses; + if IsRendered then + Result:=ReplaceClasses(FElement,aSearchClasses,aReplaceClasses,Normalize) +end; + function TCustomWebWidget.RemoveClasses(const aClasses: String; Normalize : Boolean = false): String; begin FClasses:=RemoveClasses(FClasses,aClasses,Normalize);