diff --git a/Configuration/GlobalAssemblyInfo.cs b/Configuration/GlobalAssemblyInfo.cs index e24dd3f30..aff56f085 100644 --- a/Configuration/GlobalAssemblyInfo.cs +++ b/Configuration/GlobalAssemblyInfo.cs @@ -15,7 +15,7 @@ internal static class RevisionClass public const string Major = "3"; public const string Minor = "9"; public const string Build = "0"; - public const string Revision = "3467"; + public const string Revision = "3473"; public const string MainVersion = Major + "." + Minor; public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision; diff --git a/Configuration/Version.defs b/Configuration/Version.defs index 72e9cb7bc..14b94ce30 100644 --- a/Configuration/Version.defs +++ b/Configuration/Version.defs @@ -1,4 +1,4 @@ %MINOR%=9 -%REVISION%=3467 +%REVISION%=3473 %COREVERSION%=0 %MAJOR%=3 diff --git a/Localization/DefaultLang.resources b/Localization/DefaultLang.resources index d2c271dce..bce1542d9 100644 Binary files a/Localization/DefaultLang.resources and b/Localization/DefaultLang.resources differ diff --git a/Parsers/PascalABCParserNewSaushkin/ABCPascal.cs b/Parsers/PascalABCParserNewSaushkin/ABCPascal.cs index 1fc6f8b8b..8e1734dce 100644 --- a/Parsers/PascalABCParserNewSaushkin/ABCPascal.cs +++ b/Parsers/PascalABCParserNewSaushkin/ABCPascal.cs @@ -1,9 +1,9 @@ // // This CSharp output file generated by Gardens Point LEX // Version: 1.1.3.301 -// Machine: DESKTOP-V3E9T2U -// DateTime: 27.04.2024 19:33:37 -// UserName: alex +// Machine: DESKTOP-G8V08V4 +// DateTime: 05.05.2024 20:08:13 +// UserName: ????????? // GPLEX input file // GPLEX frame file // diff --git a/Parsers/PascalABCParserNewSaushkin/ABCPascalYacc.cs b/Parsers/PascalABCParserNewSaushkin/ABCPascalYacc.cs index f48b09194..d0cb14138 100644 --- a/Parsers/PascalABCParserNewSaushkin/ABCPascalYacc.cs +++ b/Parsers/PascalABCParserNewSaushkin/ABCPascalYacc.cs @@ -1,10 +1,10 @@ // (see accompanying GPPGcopyright.rtf) // GPPG version 1.3.6 -// Machine: DESKTOP-V3E9T2U -// DateTime: 23.04.2024 22:43:23 -// UserName: alex -// Input file +// Machine: DESKTOP-G8V08V4 +// DateTime: 05.05.2024 20:08:14 +// UserName: ????????? +// Input file // options: no-lines gplex @@ -60,7 +60,7 @@ public abstract class ScanBase : AbstractScanner { - // Verbatim content from ABCPascal.y + // Verbatim content from D:\PABC_Git\Parsers\PascalABCParserNewSaushkin\ABCPascal.y // Э�?и об�?явления добавля�?�?ся в класс GPPGParser, п�?едс�?авля�?�?ий собой па�?се�?, гене�?и�?�?ем�?й сис�?емой gppg public syntax_tree_node root; // �?о�?невой �?зел син�?акси�?еского де�?ева @@ -72,7 +72,7 @@ public partial class GPPGParser: ShiftReduceParser scanner) : base(scanner) { } - // End verbatim content from ABCPascal.y + // End verbatim content from D:\PABC_Git\Parsers\PascalABCParserNewSaushkin\ABCPascal.y #pragma warning disable 649 private static Dictionary aliasses; diff --git a/Parsers/PascalABCParserNewSaushkin/PABC.ymc b/Parsers/PascalABCParserNewSaushkin/PABC.ymc index 6bac188a0..6b557701c 100644 --- a/Parsers/PascalABCParserNewSaushkin/PABC.ymc +++ b/Parsers/PascalABCParserNewSaushkin/PABC.ymc @@ -376,5 +376,6 @@ script= + diff --git a/Release/pabcversion.txt b/Release/pabcversion.txt index 63fb2005c..23c564eda 100644 --- a/Release/pabcversion.txt +++ b/Release/pabcversion.txt @@ -1 +1 @@ -3.9.0.3467 +3.9.0.3473 diff --git a/ReleaseGenerators/PascalABCNET_version.nsh b/ReleaseGenerators/PascalABCNET_version.nsh index f4636dad1..4df1ed09c 100644 --- a/ReleaseGenerators/PascalABCNET_version.nsh +++ b/ReleaseGenerators/PascalABCNET_version.nsh @@ -1 +1 @@ -!define VERSION '3.9.0.3467' +!define VERSION '3.9.0.3473' diff --git a/TestSuite/CompilationSamples/LightPT.pas b/TestSuite/CompilationSamples/LightPT.pas index d319fbd2e..c5eb01202 100644 --- a/TestSuite/CompilationSamples/LightPT.pas +++ b/TestSuite/CompilationSamples/LightPT.pas @@ -571,6 +571,11 @@ var GenerateTestData: integer -> () := nil; TestMode: TestModeType := tmNone; TestNumber: integer; + +/// Включить дополнительные сообщения о записи в удаленную базу данных +procedure SetMessagesOn; +/// Выключить дополнительные сообщения о записи в удаленную базу данных +procedure SetMessageOff; implementation @@ -612,6 +617,9 @@ var TaskNamesMap := new Dictionary; ServerAddr := 'https://air.mmcs.sfedu.ru/pascalabc'; + + // Дополнительные сообщения о записи в удаленную базу данных + additionalMessages := False; {=========================================================} { Типы, связанные с сетью } @@ -2807,11 +2815,19 @@ end; { Процедуры для записи в базы данных } {=========================================================} +procedure AdditionalMessage(message: string); +begin + if additionalMessages then + ColoredMessage(message, MsgColorMagenta); +end; + procedure WriteInfoToRemoteDatabase(auth: string; LessonName, TaskName, TaskPlatform, TaskResult, text, AdditionalInfo: string); begin + AdditionalMessage($'WriteInfoToRemoteDatabase начало. Урок {LessonName}, задание {TaskName}, результат {TaskResult}'); // Считать логин пароль из auth var data := System.IO.File.ReadAllBytes(auth); var arr := Decrypt(data).Split(#10); + AdditionalMessage($'Логин и пароль расшифрованы'); var login,pass: string; if arr.Length >= 2 then begin @@ -2819,8 +2835,10 @@ begin pass := arr[1]; // Теперь как-то записать в БД информацию var User := new ServerAccessProvider(ServerAddr); + AdditionalMessage($'Непосредственно перед SendPostRequest'); var t2 := User.SendPostRequest(login, pass, LessonName, TaskName, TaskPlatform, TaskResult, text, AdditionalInfo); var v := t2.Result; + AdditionalMessage($'После SendPostRequest - результат: {v}'); v := v; if v <> 'Success' then ColoredMessage('Ошибка сервера: '+v, MsgColorGray); @@ -2840,6 +2858,12 @@ begin try var auth := FindAuthDat(); // файл авторизации ищется либо в текущей папке либо в папке на уровень выше var args := System.Environment.GetCommandLineArgs; + if auth = '' then + AdditionalMessage('Файл auth.dat не найден') + else if (args.Length < 3) then + AdditionalMessage('args.Length < 3') + else if args[2].ToLower <> 'true' then + AdditionalMessage('args[2].ToLower <> true'); if (auth <> '') and (args.Length >= 3) and (args[2].ToLower = 'true') then begin var text := ''; @@ -2851,6 +2875,7 @@ begin except on e: System.AggregateException do begin + ColoredMessage('->>',MsgColorGray); foreach var x in e.InnerExceptions do if x is HTTPRequestException then begin @@ -2861,10 +2886,20 @@ begin else ColoredMessage('Ошибка сервера: '+x.Message,MsgColorGray); end; on e: Exception do - ColoredMessage(e.Message,MsgColorGray); + ColoredMessage('Исключение в WriteInfoToDatabases: '+e.Message,MsgColorGray); end; end; +procedure SetMessagesOn; +begin + additionalMessages := True; +end; + +procedure SetMessageOff; +begin + additionalMessages := False; +end; + {===========================================================} { Переопределенные подсистемы ввода и вывода } {===========================================================} diff --git a/TestSuite/CompilationSamples/PABCSystem.pas b/TestSuite/CompilationSamples/PABCSystem.pas index 34ed51fd4..86781eaeb 100644 --- a/TestSuite/CompilationSamples/PABCSystem.pas +++ b/TestSuite/CompilationSamples/PABCSystem.pas @@ -1506,17 +1506,18 @@ function EnumerateDirectories(path: string): sequence of string; /// Возвращает последовательность имен каталогов по заданному пути, включая подкаталоги function EnumerateAllDirectories(path: string): sequence of string; -/// Для типа System.Type возвращает имя типа объекта +/// Возвращает имя отражённого типа "t" function TypeToTypeName(t: System.Type): string; -/// Для типа System.Type записывает в res имя типа объекта +/// Добавляет в res имя отражённого типа "t" procedure TypeToTypeName(t: System.Type; res: StringBuilder); -/// Для типа System.Type записывает в res имя типа объекта +/// Записывает в res имя отражённого типа "t" procedure TypeToTypeName(t: System.Type; res: TextWriter); -/// Возвращает имя типа объекта + +/// Возвращает имя типа объекта "o" function TypeName(o: object): string; -/// Записывает в res имя типа объекта +/// Добавляет в res имя типа объекта "o" procedure TypeName(o: object; res: StringBuilder); -/// Записывает в res имя типа объекта +/// Записывает в res имя типа объекта "o" procedure TypeName(o: object; res: TextWriter); ///-procedure New(var p: ^T); @@ -2674,11 +2675,11 @@ function RuntimeInitialize(kind: byte; variable: object): object; ///Вычисление размера типа на этапе выполнения function GetRuntimeSize: integer; -/// Возвращает строку для вывода в write +/// Возвращает строку для вывода подобного Write function _ObjectToString(o: object): string; -/// Записывает в res строку для вывода в write +/// Добавляет в res строку для вывода подобного Write procedure _ObjectToString(o: object; res: StringBuilder); -/// Записывает в res строку для вывода в write +/// Записывает в res строку для вывода подобного Write procedure _ObjectToString(o: object; res: TextWriter); function IsUnix: boolean; @@ -4387,9 +4388,8 @@ type if a.Length=0 then begin // Алгоритм ниже не расчитан на пустые массив - // Правда для "new byte[1,0]" таким образом - // выведет "[]" вместо "[[]]" - res.Write('[]'); + loop a.Rank do res.Write('['); + loop a.Rank do res.Write(']'); exit; end; @@ -4477,7 +4477,7 @@ type if not enmr_has_next then break; end; - res.Write( if is_set then ']' else ']' ); + res.Write( if is_set then '}' else ']' ); exit; end; @@ -4550,15 +4550,15 @@ begin exit; end; - if t.GetInterfaces.Contains(typeof(System.Collections.IEnumerable)) then + if t.GetInterfaces.Append(t).Contains(typeof(System.Collections.IEnumerable)) then begin - var typed := t.GetInterfaces.FirstOrDefault(intr->intr.IsGenericType and (intr.GetGenericTypeDefinition=typeof(IEnumerable<>))); - if (typed<>nil) and ( + var typed := t.GetInterfaces.Append(t).FirstOrDefault(intr->intr.IsGenericType and (intr.GetGenericTypeDefinition=typeof(IEnumerable<>))); + if (t=typed) or (typed<>nil) and ( // Выводим как sequence только классы, созданные yield функцией // "clyield#" это yield класс паскаля t.Name.StartsWith('clyield#') or // А все yield классы C# являются вложенными и скрытыми - (t.DeclaringType<>nil) and not t.IsPublic + t.IsNestedPrivate ) then begin res.Write('sequence of '); @@ -4567,39 +4567,94 @@ begin end; end; + var gen_args := t.GetGenericArguments; + + //TODO t.IsClass, чтобы ValueTuple пока что не ловило + if t.GetInterfaces.Contains(typeof(System.Runtime.CompilerServices.ITuple)) and t.IsClass then + begin + res.Write('('); + var any_gen_arg := false; + foreach var arg in gen_args do + begin + if any_gen_arg then + res.Write(', ') else + any_gen_arg := true; + TypeToTypeName(arg, res); + end; + res.Write(')'); + exit; + end; + var name := t.Name; if t.IsSubclassOf(typeof(Delegate)) then begin var mi := t.GetMethod('Invoke'); - if mi=nil then raise new NotImplementedException; - ObjectToStringUtils.MethodToString(mi, false, res); - exit; + // nil for System.MulticastDelegate + if mi<>nil then + begin + ObjectToStringUtils.MethodToString(mi, false, res); + exit; + end; end; - // typeof(t1) или typeof(t1<>) - // typeof(t1<>) можно проверить отдельно с .IsGenericTypeDefinition - // Но в данном случае это не нужно - if t.IsGenericType then + // "Lst(0).GetEnumerator.GetType.DeclaringType" возвращает List, а не List + // При чём этот T.IsNested возвращает true, хотя это параметр а не вложенный тип + if t.IsNested and not t.IsGenericParameter then begin - res.Write( name.Remove(name.IndexOf('`')) ); - res.Write('<'); - var any_gen_par := false; - foreach var gen_par in t.GetGenericArguments do + var parent_def := t.DeclaringType; + var parent := parent_def; + if parent.IsGenericType then begin - if any_gen_par then + // Во вложенный тип копирует все типы шаблона из внешнего класса + // class Parent { class Nested } + // На практике вложенный тип будет Parent`1+Nested`1 + // Но тут писать в res будем только + + var t_def_args := t.GetGenericTypeDefinition.GetGenericArguments; + var parent_def_args := parent_def.GetGenericArguments; + for var i := 0 to parent_def_args.Length-1 do + if t_def_args[i].Name <> parent_def_args[i].Name then + // Ожидается что всегда будет перед в примере выше + raise new NotImplementedException; + + var parent_args := new System.Type[parent_def_args.Length]; + &Array.ConstrainedCopy(gen_args,0, parent_args,0, parent_args.Length); + parent := parent_def.MakeGenericType(parent_args); + + var own_args := new System.Type[gen_args.Length-parent_def_args.Length]; + &Array.ConstrainedCopy(gen_args,parent_args.Length, own_args,0, own_args.Length); + gen_args := own_args; + + end; + TypeToTypeName(parent, res); + res.Write('+'); + end; + + if gen_args.Count<>0 then + begin + res.Write(name.Remove(name.LastIndexOf('`'))); + res.Write('<'); + var any_gen_arg := false; + foreach var arg in gen_args do + begin + if any_gen_arg then res.Write(', ') else - any_gen_par := true; - TypeToTypeName(gen_par, res); + any_gen_arg := true; + TypeToTypeName(arg, res); end; res.Write('>'); exit; end; + if t.IsGenericParameter then + res.Write('['); res.Write(name); + if t.IsGenericParameter then + res.Write(']'); end; procedure TypeToTypeName(t: System.Type; res: StringBuilder) := -TypeToTypeName(t, new StringWriter(res)); + TypeToTypeName(t, new StringWriter(res)); procedure TypeName(o: object; res: TextWriter); begin @@ -4624,7 +4679,7 @@ begin TypeToTypeName(t, res); end; procedure TypeName(o: object; res: StringBuilder) := -TypeName(o, new StringWriter(res)); + TypeName(o, new StringWriter(res)); function TypeToTypeName(t: System.Type): string; begin @@ -4641,9 +4696,9 @@ begin end; procedure _ObjectToString(o: object; res: TextWriter) := -ObjectToStringUtils.Append(o, new Stack, res); + ObjectToStringUtils.Append(o, new Stack, res); procedure _ObjectToString(o: object; res: StringBuilder) := -_ObjectToString(o, new StringWriter(res)); + _ObjectToString(o, new StringWriter(res)); function _ObjectToString(o: object): string; begin var res := new StringBuilder; diff --git a/TestSuite/CompilationSamples/WPF.pas b/TestSuite/CompilationSamples/WPF.pas index b77de4236..97181f036 100644 --- a/TestSuite/CompilationSamples/WPF.pas +++ b/TestSuite/CompilationSamples/WPF.pas @@ -19,7 +19,7 @@ type Panel = Panel; Grid = Grid; - Canvas = Canvas; + Canvas = System.Windows.Controls.Canvas; StackPanel = StackPanel; DockPanel = DockPanel; WrapPanel = WrapPanel; @@ -45,7 +45,7 @@ type DrawingVisual = DrawingVisual; - Thickness = Thickness; + Thickness = System.Windows.Thickness; TThickness = Thickness; FontStyle = FontStyle; FontStyles = FontStyles; @@ -212,8 +212,8 @@ begin Result := Self; end; -function &With(Self: StackPanel; Background: Brush := nil; - Color: TColor := Colors.White): StackPanel; extensionmethod; +function &With(Self: T; Background: Brush := nil; + Color: TColor := Colors.White): T; extensionmethod; where T: Panel; begin if Background <> nil then Self.Background := Background @@ -221,14 +221,14 @@ begin Result := Self; end; -function &With(Self: Canvas; Background: Brush := nil; +{function &With(Self: Canvas; Background: Brush := nil; Color: TColor := Colors.White): Canvas; extensionmethod; begin if Background <> nil then Self.Background := Background else Self.Background := GBrush(color); Result := Self; -end; +end;} function AsMainContent(Self: T): T; extensionmethod; where T: FrameworkElement; begin @@ -264,28 +264,37 @@ begin DockPanel.SetDock(c,dock); end; -procedure StackPanel.Add(c: FrameworkElement); +{procedure StackPanel.Add(c: FrameworkElement); begin Self.Children.Add(c); -end; +end;} -procedure StackPanel.AddElements(params aa: array of FrameworkElement); +procedure Panel.AddElements(params aa: array of FrameworkElement); begin foreach var c in aa do Self.Children.Add(c); end; -function ArrControls(params cc: array of Control) := cc; +function ControlsList(params cc: array of Control) := Lst(cc); -procedure StackPanel.AddControls(controls: sequence of Control; - Width: real := real.NaN; Height: real := real.NaN; Padding: Thickness := 0; Margin: Thickness := 0); +function ControlsList(cc: sequence of Control) := Lst(cc); + +procedure Panel.AddControls(controls: sequence of Control; + Width: real := real.NaN; Height: real := real.NaN; Padding: Thickness := -1; Margin: Thickness := -1; + FontSize: real := real.NaN); begin foreach var b in controls do begin - b.Margin := Margin; - b.Padding := Padding; - b.Width := Width; - b.Height := Height; + if Margin <> -1 then + b.Margin := Margin; + if Padding <> -1 then + b.Padding := Padding; + if not real.IsNaN(Width) then + b.Width := Width; + if not real.IsNaN(Height) then + b.Height := Height; + if not real.IsNaN(FontSize) then + b.FontSize := FontSize; Self.Add(b); end; end; @@ -305,7 +314,8 @@ function Init(Self: FrameworkElement; Width: real := real.NaN; Height: real := r Margin: Thickness := 0): FrameworkElement; extensionmethod; begin Self.Width := Width; - Self.Height := Height; + if not real.IsNaN(Height) then + Self.Height := Height; Self.Margin := Margin; Result := Self; end; diff --git a/TestSuite/GetAvaiter.pas b/TestSuite/GetAvaiter.pas new file mode 100644 index 000000000..914820498 --- /dev/null +++ b/TestSuite/GetAvaiter.pas @@ -0,0 +1,6 @@ +uses System.Threading.Tasks; + +begin + var tt := new Task(()->1); + var q := tt.GetAwaiter +end. \ No newline at end of file diff --git a/bin/Lib/LightPT.pas b/bin/Lib/LightPT.pas index d319fbd2e..c5eb01202 100644 --- a/bin/Lib/LightPT.pas +++ b/bin/Lib/LightPT.pas @@ -571,6 +571,11 @@ var GenerateTestData: integer -> () := nil; TestMode: TestModeType := tmNone; TestNumber: integer; + +/// Включить дополнительные сообщения о записи в удаленную базу данных +procedure SetMessagesOn; +/// Выключить дополнительные сообщения о записи в удаленную базу данных +procedure SetMessageOff; implementation @@ -612,6 +617,9 @@ var TaskNamesMap := new Dictionary; ServerAddr := 'https://air.mmcs.sfedu.ru/pascalabc'; + + // Дополнительные сообщения о записи в удаленную базу данных + additionalMessages := False; {=========================================================} { Типы, связанные с сетью } @@ -2807,11 +2815,19 @@ end; { Процедуры для записи в базы данных } {=========================================================} +procedure AdditionalMessage(message: string); +begin + if additionalMessages then + ColoredMessage(message, MsgColorMagenta); +end; + procedure WriteInfoToRemoteDatabase(auth: string; LessonName, TaskName, TaskPlatform, TaskResult, text, AdditionalInfo: string); begin + AdditionalMessage($'WriteInfoToRemoteDatabase начало. Урок {LessonName}, задание {TaskName}, результат {TaskResult}'); // Считать логин пароль из auth var data := System.IO.File.ReadAllBytes(auth); var arr := Decrypt(data).Split(#10); + AdditionalMessage($'Логин и пароль расшифрованы'); var login,pass: string; if arr.Length >= 2 then begin @@ -2819,8 +2835,10 @@ begin pass := arr[1]; // Теперь как-то записать в БД информацию var User := new ServerAccessProvider(ServerAddr); + AdditionalMessage($'Непосредственно перед SendPostRequest'); var t2 := User.SendPostRequest(login, pass, LessonName, TaskName, TaskPlatform, TaskResult, text, AdditionalInfo); var v := t2.Result; + AdditionalMessage($'После SendPostRequest - результат: {v}'); v := v; if v <> 'Success' then ColoredMessage('Ошибка сервера: '+v, MsgColorGray); @@ -2840,6 +2858,12 @@ begin try var auth := FindAuthDat(); // файл авторизации ищется либо в текущей папке либо в папке на уровень выше var args := System.Environment.GetCommandLineArgs; + if auth = '' then + AdditionalMessage('Файл auth.dat не найден') + else if (args.Length < 3) then + AdditionalMessage('args.Length < 3') + else if args[2].ToLower <> 'true' then + AdditionalMessage('args[2].ToLower <> true'); if (auth <> '') and (args.Length >= 3) and (args[2].ToLower = 'true') then begin var text := ''; @@ -2851,6 +2875,7 @@ begin except on e: System.AggregateException do begin + ColoredMessage('->>',MsgColorGray); foreach var x in e.InnerExceptions do if x is HTTPRequestException then begin @@ -2861,10 +2886,20 @@ begin else ColoredMessage('Ошибка сервера: '+x.Message,MsgColorGray); end; on e: Exception do - ColoredMessage(e.Message,MsgColorGray); + ColoredMessage('Исключение в WriteInfoToDatabases: '+e.Message,MsgColorGray); end; end; +procedure SetMessagesOn; +begin + additionalMessages := True; +end; + +procedure SetMessageOff; +begin + additionalMessages := False; +end; + {===========================================================} { Переопределенные подсистемы ввода и вывода } {===========================================================} diff --git a/bin/Lib/PABCSystem.xml b/bin/Lib/PABCSystem.xml index 1e2c97443..90b2518e6 100644 --- a/bin/Lib/PABCSystem.xml +++ b/bin/Lib/PABCSystem.xml @@ -1141,19 +1141,19 @@ -- - + -- - + -- - + -- - + -- - + -- diff --git a/bin/Lib/WPF.pas b/bin/Lib/WPF.pas index b77de4236..97181f036 100644 --- a/bin/Lib/WPF.pas +++ b/bin/Lib/WPF.pas @@ -19,7 +19,7 @@ type Panel = Panel; Grid = Grid; - Canvas = Canvas; + Canvas = System.Windows.Controls.Canvas; StackPanel = StackPanel; DockPanel = DockPanel; WrapPanel = WrapPanel; @@ -45,7 +45,7 @@ type DrawingVisual = DrawingVisual; - Thickness = Thickness; + Thickness = System.Windows.Thickness; TThickness = Thickness; FontStyle = FontStyle; FontStyles = FontStyles; @@ -212,8 +212,8 @@ begin Result := Self; end; -function &With(Self: StackPanel; Background: Brush := nil; - Color: TColor := Colors.White): StackPanel; extensionmethod; +function &With(Self: T; Background: Brush := nil; + Color: TColor := Colors.White): T; extensionmethod; where T: Panel; begin if Background <> nil then Self.Background := Background @@ -221,14 +221,14 @@ begin Result := Self; end; -function &With(Self: Canvas; Background: Brush := nil; +{function &With(Self: Canvas; Background: Brush := nil; Color: TColor := Colors.White): Canvas; extensionmethod; begin if Background <> nil then Self.Background := Background else Self.Background := GBrush(color); Result := Self; -end; +end;} function AsMainContent(Self: T): T; extensionmethod; where T: FrameworkElement; begin @@ -264,28 +264,37 @@ begin DockPanel.SetDock(c,dock); end; -procedure StackPanel.Add(c: FrameworkElement); +{procedure StackPanel.Add(c: FrameworkElement); begin Self.Children.Add(c); -end; +end;} -procedure StackPanel.AddElements(params aa: array of FrameworkElement); +procedure Panel.AddElements(params aa: array of FrameworkElement); begin foreach var c in aa do Self.Children.Add(c); end; -function ArrControls(params cc: array of Control) := cc; +function ControlsList(params cc: array of Control) := Lst(cc); -procedure StackPanel.AddControls(controls: sequence of Control; - Width: real := real.NaN; Height: real := real.NaN; Padding: Thickness := 0; Margin: Thickness := 0); +function ControlsList(cc: sequence of Control) := Lst(cc); + +procedure Panel.AddControls(controls: sequence of Control; + Width: real := real.NaN; Height: real := real.NaN; Padding: Thickness := -1; Margin: Thickness := -1; + FontSize: real := real.NaN); begin foreach var b in controls do begin - b.Margin := Margin; - b.Padding := Padding; - b.Width := Width; - b.Height := Height; + if Margin <> -1 then + b.Margin := Margin; + if Padding <> -1 then + b.Padding := Padding; + if not real.IsNaN(Width) then + b.Width := Width; + if not real.IsNaN(Height) then + b.Height := Height; + if not real.IsNaN(FontSize) then + b.FontSize := FontSize; Self.Add(b); end; end; @@ -305,7 +314,8 @@ function Init(Self: FrameworkElement; Width: real := real.NaN; Height: real := r Margin: Thickness := 0): FrameworkElement; extensionmethod; begin Self.Width := Width; - Self.Height := Height; + if not real.IsNaN(Height) then + Self.Height := Height; Self.Margin := Margin; Result := Self; end;