Parcourir la source

* 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
------------------------------------------------------------------------

michael il y a 4 ans
Parent
commit
81538babe2

+ 1 - 1
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

+ 1 - 1
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;
 

+ 30 - 30
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'; 

+ 20 - 13
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;

+ 105 - 21
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,42 +2981,74 @@ 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.RemoveClasses(el: TJSHTMLElement; const aClasses: String; Normalize : Boolean = false): String;
-
-begin
-  Result:=RemoveClasses(el.ClassName,aClasses,Normalize);
-  el.ClassName:=Result;
-end;
-
-class function TCustomWebWidget.AddClasses(const Source, aClasses: String; Normalize : Boolean = false): String;
-
+class function TCustomWebWidget.ReplaceClasses(const Source, aSearchClasses, aReplaceClasses : String; Normalize: Boolean): String;
 var
-  T : TJSStringDynArray;
+  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'),' ');
-  if AClasses='' then exit;
-  T:=TJSString(Result).split(' ');
-  For S in TJSString(aClasses).split(' ') do
+  Dest:=TJSString(Result).split(' ');
+  For sIdx:=0 to length(Srch)-1 do
+    begin
+    S:=Srch[sIdx];
     if (S<>'') then
       begin
-      if (TJSArray(T).indexOf(S)=-1) then
-        TJSArray(T).Push(S);
+      I:=TJSArray(Dest).indexOf(S);
+      if (I<>-1) then
+        begin
+        TJSArray(Dest).splice(i,1);
+        if sIdx<Length(Repl) then
+          begin
+          I:=TJSArray(Dest).indexOf(Repl[sIdx]);
+          if I=-1 then
+            TJSArray(Dest).Push(Repl[sIdx]);
+          end;
+        end;
       end;
-  Result:=TJSArray(T).Join(' ');
+    end;
+  Result:=TJSArray(Dest).join(' ');
+end;
+
+class function TCustomWebWidget.RemoveClasses(const Source, aClasses: String; Normalize : Boolean = false): String;
+
+begin
+  Result:=AddRemoveClasses(Source,'',aClasses,Normalize);
+end;
+
+class function TCustomWebWidget.RemoveClasses(el: TJSHTMLElement; const aClasses: String; Normalize : Boolean = false): String;
+
+begin
+  Result:=RemoveClasses(el.ClassName,aClasses,Normalize);
+  el.ClassName:=Result;
+end;
+
+class function TCustomWebWidget.AddClasses(const Source, aClasses: String; Normalize : Boolean = false): String;
+
+begin
+  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);