Skip to content

Commit b7943ec

Browse files
committed
Add support to TCSS for margin & padding units
Modified all TCSS.PaddingProp and TCSS.MarginProp overloaded methods to add a new optional parameter to specify which length units to use. Previously only px was permitted. In order to permit fractional lengths to be specified for use with relative units, length parameters were changed to floating point from Integer. Non-Integer values are truncated to a maximum of 2 decimal places.
1 parent 2d6dff0 commit b7943ec

File tree

1 file changed

+133
-74
lines changed

1 file changed

+133
-74
lines changed

Src/UCSSUtils.pas

Lines changed: 133 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -200,28 +200,38 @@ TCSS = record
200200
/// <returns>string. Required length unit as text.</returns>
201201
class function LengthUnit(const LU: TCSSLengthUnit): string; static;
202202

203-
/// <summary>Builds a space separated list of lengths using specified
204-
/// units.</summary>
205-
/// <param name="List">array of Integer [in] List of lengths.</param>
206-
/// <param name="LU">TCSSLengthUnit [in] Specifies length unit to apply tp
207-
/// each length.</param>
208-
/// <returns>string. Required spaced separated list.</returns>
209-
class function LengthList(const List: array of Integer;
203+
/// <summary>Builds a space separated list of lengths using the specified
204+
/// unit.</summary>
205+
/// <param name="List"><c>array of Single</c> [in] List of lengths.</param>
206+
/// <param name="LU"><c>TCSSLengthUnit</c> [in] Specifies length unit to
207+
/// apply to each length.</param>
208+
/// <returns><c>string</c>. Required spaced separated list.</returns>
209+
/// <remarks>Note that lengths are rounded to a maximum of 2 decimal
210+
/// places.</remarks>
211+
class function LengthList(const List: array of Single;
210212
const LU: TCSSLengthUnit = cluPixels): string; static;
211213

212214
/// <summary>Creates a CSS "margin" property.</summary>
213-
/// <param name="Margin">array of Integer [in] Array of margin widths. Must
214-
/// contain either 1, 2 or 4 values.</param>
215-
/// <returns>string. Required CSS property.</returns>
216-
class function MarginProp(const Margin: array of Integer): string;
217-
overload; static;
215+
/// <param name="Margin"><c>array of Single</c> [in] Array of margin
216+
/// widths. Must contain either 1, 2 or 4 values.</param>
217+
/// <param name="LU"><c>TCSSLengthUnit</c> [in] Optional length unit to use
218+
/// for each margin width. Defaults to <c>cluPixels</c>.</param>
219+
/// <returns><c>string</c>. Required CSS property.</returns>
220+
/// <remarks>Note that margin values are rounded to a maximum of 2 decimal
221+
/// places.</remarks>
222+
class function MarginProp(const Margin: array of Single;
223+
const LU: TCSSLengthUnit = cluPixels): string; overload; static;
218224

219225
/// <summary>Creates a CSS "padding" property.</summary>
220-
/// <param name="Padding">array of Integer [in] Array of padding widths.
221-
/// Must contain either 1, 2 or 4 values.</param>
222-
/// <returns>string. Required CSS property.</returns>
223-
class function PaddingProp(const Padding: array of Integer): string;
224-
overload; static;
226+
/// <param name="Padding"><c>array of Single</c> [in] Array of padding
227+
/// widths. Must contain either 1, 2 or 4 values.</param>
228+
/// <param name="LU"><c>TCSSLengthUnit</c> [in] Optional length unit to use
229+
/// for each padding width. Defaults to <c>cluPixels</c>.</param>
230+
/// <returns><c>string</c>. Required CSS property.</returns>
231+
/// <remarks>Note that padding values are rounded to a maximum of 2 decimal
232+
/// places.</remarks>
233+
class function PaddingProp(const Padding: array of Single;
234+
const LU: TCSSLengthUnit = cluPixels): string; overload; static;
225235

226236
public
227237
/// <summary>Creates a CSS "color" property.</summary>
@@ -312,54 +322,77 @@ TCSS = record
312322

313323
/// <summary>Creates CSS "margin" property with same width on all edges.
314324
/// </summary>
315-
/// <param name="Margin">Integer [in] Margin width in pixels.</param>
316-
/// <returns>string. Required CSS property.</returns>
317-
class function MarginProp(const Margin: Integer): string; overload; static;
325+
/// <param name="Margin"><c>Single</c> [in] Margin width.</param>
326+
/// <param name="LU"><c>TCSSLengthUnit</c> [in] Optional length unit to use
327+
/// for the margin width. Defaults to <c>cluPixels</c>.</param>
328+
/// <returns><c>string</c>. Required CSS property.</returns>
329+
/// <remarks>Note that the margin value is rounded to a maximum of 2
330+
/// decimal places.</remarks>
331+
class function MarginProp(const Margin: Single;
332+
const LU: TCSSLengthUnit = cluPixels): string; overload; static;
318333

319334
/// <summary>Creates CSS "margin" property with potentially different
320335
/// margin widths on each side.</summary>
321-
/// <param name="Top">Integer [in] Top margin in pixels.</param>
322-
/// <param name="Right">Integer [in] Right margin in pixels.</param>
323-
/// <param name="Bottom">Integer [in] Bottom margin in pixels.</param>
324-
/// <param name="Left">Integer [in] Left margin in pixels.</param>
325-
/// <returns>string. Required CSS property.</returns>
326-
class function MarginProp(const Top, Right, Bottom, Left: Integer): string;
327-
overload; static;
336+
/// <param name="Top"><c>Single</c> [in] Top margin.</param>
337+
/// <param name="Right"><c>Single</c> [in] Right margin.</param>
338+
/// <param name="Bottom"><c>Single</c> [in] Bottom margin.</param>
339+
/// <param name="Left"><c>Single</c> [in] Left margin.</param>
340+
/// <param name="LU"><c>TCSSLengthUnit</c> [in] Optional length unit to use
341+
/// for each margin width. Defaults to <c>cluPixels</c>.</param>
342+
/// <returns><c>string</c>. Required CSS property.</returns>
343+
/// <remarks>Note that margin values are rounded to a maximum of 2 decimal
344+
/// places.</remarks>
345+
class function MarginProp(const Top, Right, Bottom, Left: Single;
346+
const LU: TCSSLengthUnit = cluPixels): string; overload; static;
328347

329348
/// <summary>Creates CSS "margin" or "margin-xxx" property (where "xxx" is
330349
/// a side).</summary>
331-
/// <param name="Side">TCSSSide [in] Specifies side(s) of element whose
332-
/// margin is to be set.</param>
333-
/// <param name="Margin">Integer [in] Width of margin in pixels.</param>
334-
/// <returns>string. Required CSS property.</returns>
335-
class function MarginProp(const Side: TCSSSide; const Margin: Integer):
336-
string; overload; static;
350+
/// <param name="Side"><c>TCSSSide</c> [in] Specifies the side(s) of the
351+
/// element whose margin is to be set.</param>
352+
/// <param name="Margin"><c>Single</c> [in] Width of margin in pixels.</param>
353+
/// <returns><c>string</c>. Required CSS property.</returns>
354+
/// <remarks>Note that the margin is rounded to a maximum of 2 decimal
355+
/// places.</remarks>
356+
class function MarginProp(const Side: TCSSSide; const Margin: Single;
357+
const LU: TCSSLengthUnit = cluPixels): string; overload; static;
337358

338359
/// <summary>Creates CSS "padding" property with same width on all sides.
339360
/// </summary>
340-
/// <param name="Padding">Integer [in] Padding width in pixels.</param>
341-
/// <returns>string. Required CSS property.</returns>
342-
class function PaddingProp(const Padding: Integer): string; overload;
343-
static;
361+
/// <param name="Padding"><c>Single</c> [in] Padding width.</param>
362+
/// <param name="LU"><c>TCSSLengthUnit</c> [in] Optional length unit to use
363+
/// for the padding width. Defaults to <c>cluPixels</c>.</param>
364+
/// <returns><c>string</c>. Required CSS property.</returns>
365+
/// <remarks>Note that the padding value is rounded to a maximum of 2
366+
/// decimal places.</remarks>
367+
class function PaddingProp(const Padding: Single;
368+
const LU: TCSSLengthUnit = cluPixels): string; overload; static;
344369

345370
/// <summary>Creates CSS "padding" property with potentially different
346371
/// padding widths on each side.</summary>
347-
/// <param name="Top">Integer [in] Top margin in pixels.</param>
348-
/// <param name="Right">Integer [in] Right margin in pixels.</param>
349-
/// <param name="Bottom">Integer [in] Bottom margin in pixels.</param>
350-
/// <param name="Left">Integer [in] Left margin in pixels.</param>
351-
/// <returns>string. Required CSS property.</returns>
352-
class function PaddingProp(const Top, Right, Bottom, Left: Integer):
353-
string; overload; static;
372+
/// <param name="Top"><c>Single</c> [in] Top margin.</param>
373+
/// <param name="Right"><c>Single</c> [in] Right margin.</param>
374+
/// <param name="Bottom"><c>Single</c> [in] Bottom margin.</param>
375+
/// <param name="Left"><c>Single</c> [in] Left margin.</param>
376+
/// <param name="LU"><c>TCSSLengthUnit</c> [in] Optional length unit to use
377+
/// for each padding width. Defaults to <c>cluPixels</c>.</param>
378+
/// <returns><c>string</c>. Required CSS property.</returns>
379+
/// <remarks>Note that padding values are rounded to a maximum of 2 decimal
380+
/// places.</remarks>
381+
class function PaddingProp(const Top, Right, Bottom, Left: Single;
382+
const LU: TCSSLengthUnit = cluPixels): string; overload; static;
354383

355384
/// <summary>Creates CSS "padding" or "padding-xxx" property (where "xxx"
356385
/// is a side).</summary>
357-
/// <param name="Side">TCSSSide [in] Specifies side(s) of element whose
358-
/// padding is to be set.</param>
359-
/// <param name="Padding">Integer [in] Width of padding in pixels.</param>
360-
/// <returns>string. Required CSS property.</returns>
361-
class function PaddingProp(const Side: TCSSSide; const Padding: Integer):
362-
string; overload; static;
386+
/// <param name="Side"><c>TCSSSide</c> [in] Specifies side(s) of element
387+
/// whose padding is to be set.</param>
388+
/// <param name="Padding"><c>Single</c> [in] Width of padding.</param>
389+
/// <param name="LU"><c>TCSSLengthUnit</c> [in] Optional length unit to use
390+
/// for the padding width. Defaults to <c>cluPixels</c>.</param>
391+
/// <returns><c>string</c>. Required CSS property.</returns>
392+
/// <remarks>Note that the padding value is rounded to a maximum of 2
393+
/// decimal places.</remarks>
394+
class function PaddingProp(const Side: TCSSSide; const Padding: Single;
395+
const LU: TCSSLengthUnit = cluPixels): string; overload; static;
363396

364397
/// <summary>Creates a CSS "text-decoration" property.</summary>
365398
/// <returns>string. Required CSS property.</returns>
@@ -477,7 +510,7 @@ implementation
477510

478511
uses
479512
// Delphi
480-
SysUtils, Windows,
513+
SysUtils, Windows, Math,
481514
// Project
482515
UIStringList, UStrUtils;
483516

@@ -519,7 +552,7 @@ class function TCSS.BorderProp(const Side: TCSSSide; const WidthPx: Cardinal;
519552
)
520553
else
521554
// Hiding border
522-
Result := Format('%s: %s;', [BorderSides[Side], LengthList([Cardinal(0)])]);
555+
Result := Format('%s: %s;', [BorderSides[Side], LengthList([0])]);
523556
end;
524557

525558
class function TCSS.ColorProp(const Color: TColor): string;
@@ -641,11 +674,32 @@ class function TCSS.InlineDisplayProp(const Show: Boolean): string;
641674
Result := DisplayProp(BlockDisplayStyles[Show]);
642675
end;
643676

644-
class function TCSS.LengthList(const List: array of Integer;
677+
class function TCSS.LengthList(const List: array of Single;
645678
const LU: TCSSLengthUnit): string;
679+
680+
function FmtLength(const L: Single): string;
681+
var
682+
NumX100: Int64;
683+
WholePart, DecPart: Int64;
684+
begin
685+
Assert(not (L < 0), 'TCSS.LengthList: Length < 0'); // avoiding using >=
686+
NumX100 := Round(Abs(L) * 100);
687+
WholePart := NumX100 div 100;
688+
DecPart := NumX100 mod 100;
689+
Result := IntToStr(WholePart);
690+
if DecPart <> 0 then
691+
begin
692+
Result := Result + '.'; // TODO: check CSS spec re localisation of '.'
693+
if DecPart mod 10 = 0 then
694+
Result := Result + IntToStr(DecPart div 10)
695+
else
696+
Result := Result + IntToStr(DecPart);
697+
end;
698+
end;
699+
646700
var
647701
Idx: Integer; // loops thru list of values
648-
ALength: Integer; // a length from list
702+
ALength: Single; // a length from list
649703
begin
650704
Assert((LU <> cluAuto) or (Length(List) = 1),
651705
'TCSS.LengthList: List size may only be 1 when length type is cltAuto');
@@ -659,7 +713,7 @@ class function TCSS.LengthList(const List: array of Integer;
659713
ALength := List[Idx];
660714
if Result <> '' then
661715
Result := Result + ' ';
662-
Result := Result + IntToStr(ALength);
716+
Result := Result + FmtLength(ALength);
663717
if ALength <> 0 then
664718
Result := Result + LengthUnit(LU); // only add unit if length not 0
665719
end;
@@ -701,32 +755,35 @@ class function TCSS.ListStyleTypeProp(const Value: TCSSListStyleType): string;
701755
Result := 'list-style-type: ' + Types[Value] + ';';
702756
end;
703757

704-
class function TCSS.MarginProp(const Margin: array of Integer): string;
758+
class function TCSS.MarginProp(const Margin: array of Single;
759+
const LU: TCSSLengthUnit): string;
705760
begin
706761
Assert(Length(Margin) in [1,2,4],
707762
'TCSS.MarginProp: Invalid margin parameters');
708-
Result := 'margin: ' + LengthList(Margin) + ';';
763+
Result := 'margin: ' + LengthList(Margin, LU) + ';';
709764
end;
710765

711-
class function TCSS.MarginProp(const Top, Right, Bottom, Left: Integer): string;
766+
class function TCSS.MarginProp(const Top, Right, Bottom, Left: Single;
767+
const LU: TCSSLengthUnit): string;
712768
begin
713-
Result := MarginProp([Top, Right, Bottom, Left]);
769+
Result := MarginProp([Top, Right, Bottom, Left], LU);
714770
end;
715771

716-
class function TCSS.MarginProp(const Margin: Integer): string;
772+
class function TCSS.MarginProp(const Margin: Single; const LU: TCSSLengthUnit):
773+
string;
717774
begin
718-
Result := MarginProp([Margin]);
775+
Result := MarginProp([Margin], LU);
719776
end;
720777

721-
class function TCSS.MarginProp(const Side: TCSSSide; const Margin: Integer):
722-
string;
778+
class function TCSS.MarginProp(const Side: TCSSSide; const Margin: Single;
779+
const LU: TCSSLengthUnit): string;
723780
const
724781
// Map of element sides to associated margin properties
725782
MarginSides: array[TCSSSide] of string = (
726783
'margin', 'margin-top', 'margin-left', 'margin-bottom', 'margin-right'
727784
);
728785
begin
729-
Result := Format('%s: %s;', [MarginSides[Side], LengthList([Margin])]);
786+
Result := Format('%s: %s;', [MarginSides[Side], LengthList([Margin], LU)]);
730787
end;
731788

732789
class function TCSS.MaxHeightProp(const HeightPx: Integer): string;
@@ -747,33 +804,35 @@ class function TCSS.OverflowProp(const Value: TCSSOverflowValue;
747804
Result := Format('%0:s: %1:s;', [Props[Direction], Values[Value]]);
748805
end;
749806

750-
class function TCSS.PaddingProp(const Padding: array of Integer): string;
807+
class function TCSS.PaddingProp(const Padding: array of Single;
808+
const LU: TCSSLengthUnit): string;
751809
begin
752810
Assert(Length(Padding) in [1,2,4],
753811
'TCSS.PaddingProp: Invalid padding parameters');
754-
Result := 'padding: ' + LengthList(Padding) + ';';
812+
Result := 'padding: ' + LengthList(Padding, LU) + ';';
755813
end;
756814

757-
class function TCSS.PaddingProp(const Top, Right, Bottom, Left: Integer):
758-
string;
815+
class function TCSS.PaddingProp(const Top, Right, Bottom, Left: Single;
816+
const LU: TCSSLengthUnit): string;
759817
begin
760-
Result := PaddingProp([Top, Right, Bottom, Left]);
818+
Result := PaddingProp([Top, Right, Bottom, Left], LU);
761819
end;
762820

763-
class function TCSS.PaddingProp(const Padding: Integer): string;
821+
class function TCSS.PaddingProp(const Padding: Single;
822+
const LU: TCSSLengthUnit): string;
764823
begin
765-
Result := PaddingProp([Padding]);
824+
Result := PaddingProp([Padding], LU);
766825
end;
767826

768-
class function TCSS.PaddingProp(const Side: TCSSSide;
769-
const Padding: Integer): string;
827+
class function TCSS.PaddingProp(const Side: TCSSSide; const Padding: Single;
828+
const LU: TCSSLengthUnit): string;
770829
const
771830
// Map of element sides to associated padding properties
772831
PaddingSides: array[TCSSSide] of string = (
773832
'padding', 'padding-top', 'padding-left', 'padding-bottom', 'padding-right'
774833
);
775834
begin
776-
Result := Format('%s: %s;', [PaddingSides[Side], LengthList([Padding])]);
835+
Result := Format('%s: %s;', [PaddingSides[Side], LengthList([Padding], LU)]);
777836
end;
778837

779838
class function TCSS.TextAlignProp(const TA: TCSSTextAlign): string;

0 commit comments

Comments
 (0)