Большое изменение в Dictionaries

1 to 2 - новый оператор в стиле Котлина для пары Ключ-Значение
Pair - синоним KV. KV - не запоминается
Теперь:
  d := Dict(1 to 2, 3 to 4)
   или
  d := Dict(Pair(1,2),Pair(3,4)

Кроме того
Новые конструкторы
  d := Dict(d1) - копия
  d := Dict(keys,values)
d.Update(d1)
d + d1
d += d1
d + pair
d - Seq(ключ)
d -= Seq(ключ)
This commit is contained in:
Mikhalkovich Stanislav 2024-07-15 13:50:11 +03:00
parent 97c29a4e1b
commit b8fec95599
24 changed files with 3143 additions and 2549 deletions

View file

@ -3522,6 +3522,12 @@ namespace CodeFormatters
add_space_before = true;
visit_node(lvex.ex);
}
public override void visit(to_expr to_ex)
{
visit_node(to_ex.key);
sb.Append(" ");
visit_node(to_ex.value);
}
#endregion
}

View file

@ -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 = "3503";
public const string Revision = "3506";
public const string MainVersion = Major + "." + Minor;
public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision;

View file

@ -1,4 +1,4 @@
%MINOR%=9
%REVISION%=3503
%COREVERSION%=0
%REVISION%=3506
%MINOR%=9
%MAJOR%=3

View file

@ -1,9 +1,9 @@
//
// This CSharp output file generated by Gardens Point LEX
// Version: 1.1.3.301
// Machine: DESKTOP-V3E9T2U
// DateTime: 11.07.2024 9:39:17
// UserName: alex
// Machine: DESKTOP-G8V08V4
// DateTime: 15.07.2024 13:28:05
// UserName: ?????????
// GPLEX input file <ABCPascal.lex>
// GPLEX frame file <embedded resource>
//

View file

@ -3327,6 +3327,8 @@ expr
{ $$ = $1; }
| format_expr
{ $$ = $1; }
| expr tkTo expr_l1
{ $$ = new to_expr($1, $3, @$); }
;
expr_l1

File diff suppressed because it is too large Load diff

View file

@ -381,6 +381,8 @@ script=

View file

@ -1 +1 @@
3.9.0.3503
3.9.0.3506

View file

@ -1 +1 @@
!define VERSION '3.9.0.3503'
!define VERSION '3.9.0.3506'

View file

@ -1317,6 +1317,11 @@ namespace PascalABCCompiler.SyntaxTree
{
DefaultVisit(_let_var_expr);
}
public virtual void visit(to_expr _to_expr)
{
DefaultVisit(_to_expr);
}
}

View file

@ -32,7 +32,6 @@ namespace PascalABCCompiler.SyntaxTree
upper.ReplaceDescendant(from, to);
}
public void ReplaceStatement(statement from, statement to)
{
to.Parent = from.Parent;

View file

@ -2101,6 +2101,14 @@ namespace PascalABCCompiler.SyntaxTree
{
}
public virtual void pre_do_visit(to_expr _to_expr)
{
}
public virtual void post_do_visit(to_expr _to_expr)
{
}
public override void visit(expression _expression)
{
DefaultVisit(_expression);
@ -4342,6 +4350,15 @@ namespace PascalABCCompiler.SyntaxTree
visit(let_var_expr.ex);
post_do_visit(_let_var_expr);
}
public override void visit(to_expr _to_expr)
{
DefaultVisit(_to_expr);
pre_do_visit(_to_expr);
visit(to_expr.key);
visit(to_expr.value);
post_do_visit(_to_expr);
}
}

View file

@ -544,6 +544,8 @@ namespace PascalABCCompiler.SyntaxTree
return new ref_var_def_statement();
case 261:
return new let_var_expr();
case 262:
return new to_expr();
}
return null;
}
@ -4569,6 +4571,19 @@ namespace PascalABCCompiler.SyntaxTree
_let_var_expr.ex = _read_node() as expression;
}
public void visit(to_expr _to_expr)
{
read_to_expr(_to_expr);
}
public void read_to_expr(to_expr _to_expr)
{
read_expression(_to_expr);
_to_expr.key = _read_node() as expression;
_to_expr.value = _read_node() as expression;
}
}

View file

@ -7181,6 +7181,36 @@ namespace PascalABCCompiler.SyntaxTree
}
}
public void visit(to_expr _to_expr)
{
bw.Write((Int16)262);
write_to_expr(_to_expr);
}
public void write_to_expr(to_expr _to_expr)
{
write_expression(_to_expr);
if (_to_expr.key == null)
{
bw.Write((byte)0);
}
else
{
bw.Write((byte)1);
_to_expr.key.visit(this);
}
if (_to_expr.value == null)
{
bw.Write((byte)0);
}
else
{
bw.Write((byte)1);
_to_expr.value.visit(this);
}
}
}

View file

@ -55897,6 +55897,196 @@ namespace PascalABCCompiler.SyntaxTree
}
///<summary>
///
///</summary>
[Serializable]
public partial class to_expr : expression
{
///<summary>
///Конструктор без параметров.
///</summary>
public to_expr()
{
}
///<summary>
///Конструктор с параметрами.
///</summary>
public to_expr(expression _key,expression _value)
{
this._key=_key;
this._value=_value;
FillParentsInDirectChilds();
}
///<summary>
///Конструктор с параметрами.
///</summary>
public to_expr(expression _key,expression _value,SourceContext sc)
{
this._key=_key;
this._value=_value;
source_context = sc;
FillParentsInDirectChilds();
}
protected expression _key;
protected expression _value;
///<summary>
///
///</summary>
public expression key
{
get
{
return _key;
}
set
{
_key=value;
if (_key != null)
_key.Parent = this;
}
}
///<summary>
///
///</summary>
public expression value
{
get
{
return _value;
}
set
{
_value=value;
if (_value != null)
_value.Parent = this;
}
}
/// <summary> Создает копию узла </summary>
public override syntax_tree_node Clone()
{
to_expr copy = new to_expr();
copy.Parent = this.Parent;
if (source_context != null)
copy.source_context = new SourceContext(source_context);
if (attributes != null)
{
copy.attributes = (attribute_list)attributes.Clone();
copy.attributes.Parent = copy;
}
if (key != null)
{
copy.key = (expression)key.Clone();
copy.key.Parent = copy;
}
if (value != null)
{
copy.value = (expression)value.Clone();
copy.value.Parent = copy;
}
return copy;
}
/// <summary> Получает копию данного узла корректного типа </summary>
public new to_expr TypedClone()
{
return Clone() as to_expr;
}
///<summary> Заполняет поля Parent в непосредственных дочерних узлах </summary>
public override void FillParentsInDirectChilds()
{
if (attributes != null)
attributes.Parent = this;
if (key != null)
key.Parent = this;
if (value != null)
value.Parent = this;
}
///<summary> Заполняет поля Parent во всем поддереве </summary>
public override void FillParentsInAllChilds()
{
FillParentsInDirectChilds();
attributes?.FillParentsInAllChilds();
key?.FillParentsInAllChilds();
value?.FillParentsInAllChilds();
}
///<summary>
///Свойство для получения количества всех подузлов без элементов поля типа List
///</summary>
public override Int32 subnodes_without_list_elements_count
{
get
{
return 2;
}
}
///<summary>
///Свойство для получения количества всех подузлов. Подузлом также считается каждый элемент поля типа List
///</summary>
public override Int32 subnodes_count
{
get
{
return 2;
}
}
///<summary>
///Индексатор для получения всех подузлов
///</summary>
public override syntax_tree_node this[Int32 ind]
{
get
{
if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1)
throw new IndexOutOfRangeException();
switch(ind)
{
case 0:
return key;
case 1:
return value;
}
return null;
}
set
{
if(subnodes_count == 0 || ind < 0 || ind > subnodes_count-1)
throw new IndexOutOfRangeException();
switch(ind)
{
case 0:
key = (expression)value;
break;
case 1:
value = (expression)value;
break;
}
}
}
///<summary>
///Метод для обхода дерева посетителем
///</summary>
///<param name="visitor">Объект-посетитель.</param>
///<returns>Return value is void</returns>
public override void visit(IVisitor visitor)
{
visitor.visit(this);
}
}
}

View file

@ -1576,6 +1576,12 @@ namespace PascalABCCompiler.SyntaxTree
///<param name="_let_var_expr">Node to visit</param>
///<returns> Return value is void </returns>
void visit(let_var_expr _let_var_expr);
///<summary>
///Method to visit to_expr.
///</summary>
///<param name="_to_expr">Node to visit</param>
///<returns> Return value is void </returns>
void visit(to_expr _to_expr);
}

View file

@ -3368,6 +3368,17 @@
<TagIndices />
</Tags>
</SyntaxNode>
<SyntaxNode Name="to_expr" BaseName="expression">
<Fields>
<SyntaxField Name="key" SyntaxType="expression" />
<SyntaxField Name="value" SyntaxType="expression" />
</Fields>
<Methods />
<Tags>
<CategoryIndices />
<TagIndices />
</Tags>
</SyntaxNode>
</SyntaxNodes>
<Settings>
<FileName>Tree.cs</FileName>
@ -3445,6 +3456,7 @@
<HelpData Key=".initial_value" Value="ссылка на addrvalue, которой интциализируется идентификатор" />
<HelpData Key=".inverted" Value="" />
<HelpData Key=".item_expression" Value="" />
<HelpData Key=".key" Value="" />
<HelpData Key=".left" Value="" />
<HelpData Key=".lists" Value="" />
<HelpData Key=".listunitsections" Value="" />
@ -4669,6 +4681,9 @@
<HelpData Key="template_type_reference." Value="" />
<HelpData Key="template_type_reference.name" Value="" />
<HelpData Key="template_type_reference.params_list" Value="" />
<HelpData Key="to_expr" Value="" />
<HelpData Key="to_expr.key" Value="" />
<HelpData Key="to_expr.value" Value="" />
<HelpData Key="token_info" Value="" />
<HelpData Key="token_info." Value="" />
<HelpData Key="token_info.override string ToString()" Value="" />

View file

@ -87,6 +87,8 @@ namespace Languages.Pascal.Frontend.Converters
CacheFunctionVisitor.New.ProcessNode(root);
ToExprVisitor.New.ProcessNode(root);
// При наличии файла lightpt.dat подключает модули LightPT и Tasks
root = TeacherControlConverter.New.Convert(root);

View file

@ -0,0 +1,51 @@
// Copyright (c) Ivan Bondarev, Stanislav Mikhalkovich (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using PascalABCCompiler.SyntaxTree;
namespace SyntaxVisitors.SugarVisitors
{
/// <summary>
/// А здесь не только замена кортежа - здесь оптимизация (a,b) := (1,2) и var (a,b) := (1,2)
/// </summary>
public class ToExprVisitor : BaseChangeVisitor
{
public static ToExprVisitor New
{
get { return new ToExprVisitor(); }
}
private int num = 0;
public string UniqueName()
{
num++;
return "#let_expr_vis"+num.ToString();
}
public override void visit(to_expr to_ex)
{
var pairMethod =
new method_call(
new dot_node(
new ident("PABCSystem", to_ex.source_context),
new ident("Pair", to_ex.source_context),
to_ex.source_context),
new expression_list(
new List<expression>()
{
to_ex.key,
to_ex.value
},
to_ex.source_context),
to_ex.source_context);
Replace(to_ex, pairMethod);
ProcessNode(to_ex.key);
ProcessNode(to_ex.value);
}
}
}

View file

@ -61,6 +61,7 @@
<Compile Include="SugarVisitors\AssignTuplesDesugarVisitor\desugarAlgoritm\SymbolNode.cs" />
<Compile Include="SugarVisitors\AssignTuplesDesugarVisitor\NewAssignTuplesDesugarVisitor.cs" />
<Compile Include="SugarVisitors\CacheFunctionVisitor.cs" />
<Compile Include="SugarVisitors\ToExprVisitor.cs" />
<Compile Include="SugarVisitors\LetExprVisitor.cs" />
<Compile Include="SugarVisitors\TestAssignIsDefVisitor.cs" />
<Compile Include="SugarVisitors\UnpackLambdaParametersVisitor.cs" />

View file

@ -2483,10 +2483,16 @@ function SSetStr(params a: array of string): SortedSet<string>;
function Dict<TKey, TVal>(params pairs: array of KeyValuePair<TKey, TVal>): Dictionary<TKey, TVal>;
/// Возвращает словарь пар элементов (ключ, значение)
function Dict<TKey, TVal>(params pairs: array of (TKey, TVal)): Dictionary<TKey, TVal>;
/// Возвращает словарь пар элементов (ключ, значение), построенный на значениях последовательности
/// Возвращает словарь пар элементов (ключ, значение), построенный по последовательности пар
function Dict<TKey, TVal>(pairs: sequence of KeyValuePair<TKey, TVal>): Dictionary<TKey, TVal>;
/// Возвращает словарь пар элементов (ключ, значение), построенный по последовательности пар
function Dict<TKey, TVal>(pairs: sequence of (TKey, TVal)): Dictionary<TKey, TVal>;
/// Возвращает словарь пар элементов (ключ, значение), построенный по последовательностям ключей и значений
function Dict<TKey, TVal>(keys: sequence of TKey; values: sequence of TVal): Dictionary<TKey, TVal>;
/// Возвращает пару элементов (ключ, значение)
function KV<TKey, TVal>(key: TKey; value: TVal): KeyValuePair<TKey, TVal>;
/// Возвращает пару элементов (ключ, значение)
function Pair<TKey, TVal>(key: TKey; value: TVal): KeyValuePair<TKey, TVal>;
/// Возвращает словарь пар элементов (строка, строка)
function DictStr(params pairs: array of (string, string)): Dictionary<string, string>;
/// Возвращает словарь пар элементов (строка, целое)
@ -5710,13 +5716,21 @@ begin
Result.Add(pairs[i][0], pairs[i][1]);
end;
function Dict<TKey, TVal>(pairs: sequence of (TKey, TVal)): Dictionary<TKey, TVal>
:= Dict(pairs.ToArray); // внутренняя ошибка компилятора
function Dict<TKey, TVal>(pairs: sequence of KeyValuePair<TKey, TVal>): Dictionary<TKey, TVal>
:= Dict(pairs.ToArray);
function KV<TKey, TVal>(key: TKey; value: TVal): KeyValuePair<TKey, TVal>;
begin
Result := new KeyValuePair<TKey, TVal>(key, value);
end;
function Dict<TKey, TVal>(pairs: sequence of (TKey, TVal)): Dictionary<TKey, TVal>
:= Dict(pairs.ToArray);
function Dict<TKey, TVal>(keys: sequence of TKey; values: sequence of TVal): Dictionary<TKey, TVal>
:= Dict(keys.Zip(values, (k,v) -> KV(k,v)));
function KV<TKey, TVal>(key: TKey; value: TVal): KeyValuePair<TKey, TVal>
:= new KeyValuePair<TKey, TVal>(key, value);
function Pair<TKey, TVal>(key: TKey; value: TVal): KeyValuePair<TKey, TVal>
:= new KeyValuePair<TKey, TVal>(key, value);
function DictStr(params pairs: array of (string, string)): Dictionary<string, string>
:= Dict&<string, string>(pairs);
@ -14125,12 +14139,58 @@ begin
Result := Self.GroupBy(x->x).ToDictionary(g -> g.Key, g -> proj(g.Key));
end;
/// Операция удаления из словаря пары с указанным значением ключа
/// Обновляет данные в словаре данными из другого словаря
procedure Update<TKey, TVal>(Self: Dictionary<TKey, TVal>; update: Dictionary<TKey, TVal>); extensionmethod;
begin
foreach var kv in update do
Self[kv.Key] := kv.Value;
end;
/// Обновляет данные в словаре данными из другого словаря
procedure operator+=<TKey, TVal>(Self: Dictionary<TKey, TVal>; update: Dictionary<TKey, TVal>); extensionmethod;
begin
foreach var kv in update do
Self[kv.Key] := kv.Value;
end;
/// Объединяет данные в двух словарях. Если в обоих имеются одинаковые ключи, то с ключом связывается значение из второго словаря
function operator+<TKey, TVal>(Self: Dictionary<TKey, TVal>; dict: Dictionary<TKey, TVal>): Dictionary<TKey, TVal>; extensionmethod;
begin
var d := PABCSystem.Dict(Self);
d += dict;
Result := d;
end;
/// Удаляет из словаря пары с указанным значением ключа
procedure operator-=<Key,Value>(Self: IDictionary<Key,Value>; k: Key); extensionmethod;
begin
Self.Remove(k);
end;
/// Удаляет из словаря пары с указанными значениями ключа
procedure operator-=<Key,Value>(Self: IDictionary<Key,Value>; keys: sequence of Key); extensionmethod;
begin
foreach var k in keys do
Self.Remove(k);
end;
/// Возвращает словарь, в котором из исходного словаря удален элемент с данным ключом
function operator-<TKey, TVal>(Self: Dictionary<TKey, TVal>; key: TKey): Dictionary<TKey, TVal>; extensionmethod;
begin
var d := Dict(Self);
d -= key;
Result := d;
end;
/// Возвращает словарь, в котором из исходного словаря удалены все элементы с ключами, задаваемыми вторым операндом
function operator-<TKey, TVal>(Self: Dictionary<TKey, TVal>; keys: sequence of TKey): Dictionary<TKey, TVal>; extensionmethod;
begin
var d := Dict(Self);
d -= keys;
Result := d;
end;
// --------------------------------------------
//>> Методы расширения типа Tuple # Extension methods for Tuple
// -------------------------------------------

View file

@ -17,55 +17,61 @@ uses System.Windows.Markup;
type
TControl = Control;
Panel = System.Windows.Controls.Panel;
Panel = System.Windows.Controls.Panel; // Это для других модулей
Grid = System.Windows.Controls.Grid;
Canvas = System.Windows.Controls.Canvas;
StackPanel = System.Windows.Controls.StackPanel;
DockPanel = System.Windows.Controls.DockPanel;
WrapPanel = System.Windows.Controls.WrapPanel;
TPanel = Panel;
TGrid = Grid;
TStackPanel = StackPanel;
TDockPanel = DockPanel;
TCanvas = Canvas;
//TPanel = Panel; // Это для себя
//TGrid = Grid;
//TCanvas = Canvas;
//TStackPanel = StackPanel;
//TDockPanel = DockPanel;
//TWrapPanel = WrapPanel;
// Типы элементов управления
Button = Button;
TButton = Button;
&Label = &Label;
TLabel = &Label;
CheckBox = CheckBox;
TextBox = TextBox;
Slider = Slider;
ComboBox = ComboBox;
Button = System.Windows.Controls.Button;
&Label = System.Windows.Controls.Label;
TextBlock = System.Windows.Controls.TextBlock;
TextBox = System.Windows.Controls.TextBox;
CheckBox = System.Windows.Controls.CheckBox;
Slider = System.Windows.Controls.Slider;
ComboBox = System.Windows.Controls.ComboBox;
Border = System.Windows.Controls.Border;
Rectangle = Rectangle;
Rectangle = System.Windows.Shapes.Rectangle;
RadioButton = System.Windows.Controls.RadioButton;
//TButton = Button;
TLabel = &Label;
//TTextBlock = TextBlock;
//TTextBox = TextBox;
//TCheckBox = CheckBox;
//TSlider = Slider;
//TComboBox = ComboBox;
DrawingVisual = DrawingVisual;
Thickness = System.Windows.Thickness;
TThickness = Thickness;
//TThickness = Thickness;
FontStyle = FontStyle;
FontStyles = FontStyles;
GridLength = GridLength;
GridUnitType = GridUnitType;
Brushes = Brushes;
Brush = Brush;
Brush = System.Windows.Media.Brush;
Pen = Pen;
Point = Point;
Colors = Colors;
SolidColorBrush = SolidColorBrush;
Orientation = Orientation;
TOrientation = Orientation;
VerticalAlignment = VerticalAlignment;
HorizontalAlignment = HorizontalAlignment;
//TOrientation = Orientation;
VerticalAlignment = System.Windows.VerticalAlignment;
HorizontalAlignment = System.Windows.HorizontalAlignment;
HA = HorizontalAlignment;
VA = VerticalAlignment;
Dock = Dock;
Color = Color;
TColor = Color;
//TColor = Color;
TickPlacement = TickPlacement;
Binding = Binding;
PropertyPath = PropertyPath;
@ -165,14 +171,14 @@ begin
Grid.SetColumn(c,col);
end;
function AddToCell<T>(Self: T; gr: TGrid; row,col: integer): T; extensionmethod; where T: FrameworkElement;
function AddToCell<T>(Self: T; gr: Grid; row,col: integer): T; extensionmethod; where T: FrameworkElement;
begin
Result := Self;
if gr<>nil then
gr.Add(Result,row,col);
end;
function AddTo<T>(Self: T; gr: TPanel): T; extensionmethod; where T: FrameworkElement;
function AddTo<T>(Self: T; gr: Panel): T; extensionmethod; where T: FrameworkElement;
begin
Result := Self;
if gr<>nil then
@ -196,7 +202,7 @@ var CurrentPen := GPen(Colors.Black,1);
var CurrentBrush := GBrush(Colors.White);
// Декораторы
function &With(Self: TGrid; ShowGridLines: boolean := True): TGrid; extensionmethod;
function &With(Self: Grid; ShowGridLines: boolean := True): Grid; extensionmethod;
begin
Self.ShowGridLines := ShowGridLines;
Result := Self;
@ -214,7 +220,7 @@ begin
end;
function &With<T>(Self: T; Background: Brush := nil;
Color: TColor := Colors.White): T; extensionmethod; where T: Panel;
Color: Color := Colors.White): T; extensionmethod; where T: Panel;
begin
if Background <> nil then
Self.Background := Background
@ -276,31 +282,33 @@ begin
Self.Children.Add(c);
end;
function ControlsList(params cc: array of Control) := Lst(cc);
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);
procedure Panel.AddElements(elements: sequence of FrameworkElement;
Width: real := real.NaN; Height: real := real.NaN;
Padding: Thickness := -1; Margin: Thickness := -1);
begin
foreach var b in controls do
foreach var b in elements do
begin
if Margin <> -1 then
b.Margin := Margin;
if Padding <> -1 then
b.Padding := Padding;
begin
var prop := b.GetType.GetProperty('Padding');
if prop <> nil then
prop.SetValue(b,Padding);
end;
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;
function Text(Self: TButton): string; extensionmethod := Self.Content as string;
function Elements(params cc: array of FrameworkElement) := Lst(cc);
function Elements(cc: sequence of FrameworkElement) := Lst(cc);
function Text(Self: Button): string; extensionmethod := Self.Content as string;
function Text(Self: &Label): string; extensionmethod := Self.Content as string;
function Text(Self: CheckBox): string; extensionmethod := Self.Content as string;
@ -312,12 +320,14 @@ begin
end;
function Init(Self: FrameworkElement; Width: real := real.NaN; Height: real := real.NaN;
Margin: Thickness := 0): FrameworkElement; extensionmethod;
Margin: Thickness := -1): FrameworkElement; extensionmethod;
begin
Self.Width := Width;
if not real.IsNaN(Width) then
Self.Width := Width;
if not real.IsNaN(Height) then
Self.Height := Height;
Self.Margin := Margin;
if Margin <> -1 then
Self.Margin := Margin;
Result := Self;
end;
@ -335,64 +345,75 @@ begin
Result := ParseXaml(s);
end;
// Функции создания элементов управления
//-----------------------------------------------------------------------//
// Функции создания элементов управления
//-----------------------------------------------------------------------//
function CreateButton(Text: string; Width: real := real.NaN; Height: real := real.NaN;
Margin: Thickness := 0; Padding: Thickness := 0): Button;
function CreateElement<T>(Width: real := real.NaN; Height: real := real.NaN; Margin: Thickness := -1): T;
where T: FrameworkElement, constructor;
begin
Result := Button.Create;
Result := new T;
Result.Init(Width,Height,Margin);
Result.Content := Text;
Result.Padding := Padding;
end;
/// Элемент управления Кнопка. Основное событие - Click
function CreateButton(Text: string; Width: real := real.NaN; Height: real := real.NaN;
Margin: Thickness := -1; Padding: Thickness := -1): Button;
begin
Result := CreateElement&<Button>(Width,Height,Margin);
Result.Content := Text;
if Padding <> -1 then
Result.Padding := Padding;
end;
// Создает массив элементов управления Кнопка
function CreateButtons(Texts: array of string; Width: real := real.NaN; Height: real := real.NaN;
Margin: Thickness := 0; Padding: Thickness := 0): array of Button;
Margin: Thickness := -1; Padding: Thickness := -1): array of Button;
begin
Result := new Button[Texts.Length];
for var i:=0 to Result.Length - 1 do
Result[i] := CreateButton(Texts[i], Width, Height, Margin, Padding);
end;
/// Элемент управления для редактирования текста
function CreateTextBox(Text: string; Width: real := real.NaN; Height: real := real.NaN;
Margin: Thickness := 0): TextBox;
Margin: Thickness := -1): TextBox;
begin
Result := TextBox.Create;
Result.Init(Width,Height,Margin);
Result := CreateElement&<TextBox>(Width,Height,Margin);
Result.Text := Text;
end;
function CreateLabel(Text: string; Width: real := real.NaN; Height: real := real.NaN;
Margin: Thickness := 0): &Label;
/// Элемент управления для отображения текста
function CreateTextBlock(Text: string := ''; Width: real := real.NaN; Height: real := real.NaN;
Margin: Thickness := -1): TextBlock;
begin
Result := &Label.Create;
Result.Init(Width,Height,Margin);
Result := CreateElement&<TextBlock>(Width,Height,Margin);
Result.Text := Text;
end;
/// Текстовая подпись для элемента управления
function CreateLabel(Text: string; Width: real := real.NaN; Height: real := real.NaN;
Margin: Thickness := -1): &Label;
begin
Result := CreateElement&<&Label>(Width,Height,Margin);
Result.Content := Text;
end;
function CreateTextBlock(Text: string := ''; Width: real := real.NaN; Height: real := real.NaN;
Margin: Thickness := 0): TextBlock;
begin
Result := TextBlock.Create;
Result.Init(Width,Height,Margin);
Result.Text := Text;
end;
/// Элемент управления Флажок
function CreateCheckBox(Text: string; Width: real := real.NaN; Height: real := real.NaN;
Margin: Thickness := 0; IsChecked: boolean := False): CheckBox;
Margin: Thickness := -1; IsChecked: boolean := False): CheckBox;
begin
Result := CheckBox.Create;
Result.Init(Width,Height,Margin);
Result := CreateElement&<CheckBox>(Width,Height,Margin);
Result.Content := Text;
Result.IsChecked := IsChecked;
end;
/// Элемент управления Слайдер
function CreateSlider(Min: real := 0; Max: real := 10; Step: real := 1; TickFrequency: real := 1;
Width: real := real.NaN; Height: real := real.NaN; Margin: Thickness := 0;
Width: real := real.NaN; Height: real := real.NaN; Margin: Thickness := -1;
Value: real := real.NaN): Slider;
begin
Result := Slider.Create;
Result.Init(Width,Height,Margin);
Result := CreateElement&<Slider>(Width,Height,Margin);
Result.Minimum := Min;
Result.Maximum := Max;
Result.SmallChange := Step;
@ -403,19 +424,70 @@ begin
Result.Value := Value
end;
//-- Создание панелей
/// Элемент управления для выбора с раскрывающимся списком
function CreateComboBox(Items: array of string := nil; Width: real := real.NaN; Height: real := real.NaN;
Margin: Thickness := 0): ComboBox;
Margin: Thickness := -1): ComboBox;
begin
Result := ComboBox.Create;
Result.Init(Width,Height,Margin);
Result := CreateElement&<ComboBox>(Width,Height,Margin);
if items <> nil then
foreach var item in items do
Result.Items.Add(item);
Result.SelectedIndex := 0;
end;
/// Элемент Прямоугольник
function CreateRectangle(Width: real := real.NaN; Height: real := real.NaN; Margin: Thickness := -1): Rectangle;
begin
Result := CreateElement&<Rectangle>(Width,Height,Margin);
end;
/// Отображает границу и фон вокруг дочернего элемента. Основное свойство - Child
function CreateBorder(Width: real := real.NaN; Height: real := real.NaN;
Margin: Thickness := -1; Background: Brush := nil; BorderBrush: Brush := nil;
BorderThickness: Thickness := -1; Child: UIElement := nil): Border;
begin
Result := CreateElement&<Border>(Width,Height,Margin);
if Background<>nil then
Result.Background := Background;
if BorderBrush<>nil then
Result.BorderBrush := BorderBrush;
if BorderThickness<>-1 then
Result.BorderThickness := BorderThickness;
if Child <> nil then
Result.Child := Child;
end;
/// Элемент управления Радиокнопка. Радиокнопки могут быть сгруппированы по GroupName. Основное событие - Checked
function CreateRadioButton(Width: real := real.NaN; Height: real := real.NaN; Margin: Thickness := -1;
Text: string := ''; GroupName: string := nil; IsChecked: boolean := False): RadioButton;
begin
Result := CreateElement&<Radiobutton>(Width,Height,Margin);
Result.Content := Text;
if GroupName<>nil then
Result.GroupName := GroupName;
Result.IsChecked := IsChecked;
end;
// Создает массив элементов управления Радиокнопка
function CreateRadioButtons(Texts: array of string; Width: real := real.NaN; Height: real := real.NaN;
Margin: Thickness := -1; GroupName: string := nil): array of WPF.RadioButton;
begin
Result := new WPF.RadioButton[Texts.Length];
for var i:=0 to Result.Length - 1 do
Result[i] := CreateRadioButton(Width, Height, Margin, Texts[i], GroupName);
end;
function Bordered(Self: UIElement; BorderThickness: Thickness := -1; BorderBrush: Brush := nil; Margin:
Thickness := -1): WPF.Border; extensionmethod;
begin
Result := CreateBorder(BorderBrush := BorderBrush, BorderThickness := BorderThickness, Margin := Margin, Child := Self);
end;
//-----------------------------------------------------------------------//
// Функции создания панелей
//-----------------------------------------------------------------------//
/// Панель, состоящая из строк и столбцов переменного размера
function CreateGrid(rows: integer := 1; cols: integer := 1; ColumnWidths: array of real := nil;
RowHeights: array of real := nil): Grid;
begin
@ -434,55 +506,104 @@ begin
Result := gr;
end;
function CreateDockPanel(Margin: Thickness := 0): DockPanel;
/// Панель, в которой можно пристыковывать элементы управления к краям, используя DockPanel.SetDock
function CreateDockPanel(Margin: Thickness := -1): DockPanel;
begin
Result := new DockPanel;
Result.Margin := Margin;
if Margin <> -1 then
Result.Margin := Margin;
end;
function CreateCanvas(Margin: Thickness := 0): Canvas;
/// Определяет область, в которой можно располагать элементы управления с помощью координат
function CreateCanvas(Margin: Thickness := -1): Canvas;
begin
Result := new Canvas;
Result.Margin := Margin;
if Margin <> -1 then
Result.Margin := Margin;
end;
/// Панель, располагающая элементы управления вертикально или горизонтально
function CreateStackPanel(Width: real := real.NaN; Height: real := real.NaN;
Margin: Thickness := 0; Horizontal: boolean := False): StackPanel;
Margin: Thickness := -1; Horizontal: boolean := False;
HAlign: HorizontalAlignment := HA.Left; VAlign: VerticalAlignment := VA.Top): StackPanel;
begin
Result := new StackPanel;
Result.Init(Width,Height,Margin);
if Horizontal then
Result.Orientation := Orientation.Horizontal;
end;
function CreateRectangle(Width: real := real.NaN; Height: real := real.NaN;
Margin: Thickness := 0): Rectangle;
begin
Result := new Rectangle;
Result.Init(Width,Height,Margin);
Result.HorizontalAlignment := HAlign;
Result.VerticalAlignment := VAlign;
end;
type
///!#
Controls = static class
static function Button(Text: string; Left: real := real.NaN; Top: real := real.NaN;
Width: real := real.NaN; Height: real := real.NaN; Margin: Thickness := 0;
Padding: Thickness := 0): TButton
:= WPF.CreateButton(Text,Width,Height,Margin,Padding);
static function Drawing: WPF.Drawing
:= CreateDrawing;
static function DrawingVisual: WPF.DrawingVisual
:= new WPF.DrawingVisual;
public
/// Элемент управления Кнопка. Основное событие - Click
static function Button(Text: string; Width: real := real.NaN; Height: real := real.NaN;
Margin: Thickness := -1; Padding: Thickness := -1): WPF.Button := WPF.CreateButton(Text,Width,Height,Margin,Padding);
/// Создает массив элементов управления Кнопка
static function Buttons(Texts: array of string; Width: real := real.NaN; Height: real := real.NaN;
Margin: Thickness := -1; Padding: Thickness := -1): array of WPF.Button
:= WPF.CreateButtons(Texts,Width,Height,Margin,Padding);
/// Элемент управления для редактирования текста
static function TextBox(Text: string; Width: real := real.NaN; Height: real := real.NaN;
Margin: Thickness := -1): WPF.TextBox := WPF.CreateTextBox(Text, Width, Height, Margin);
/// Элемент управления для редактирования текста
static function TextBlock(Text: string := ''; Width: real := real.NaN; Height: real := real.NaN;
Margin: Thickness := -1) := WPF.CreateTextBlock(Text, Width, Height, Margin);
/// Текстовая подпись для элемента управления
static function &Label(Text: string; Width: real := real.NaN; Height: real := real.NaN;
Margin: Thickness := -1): WPF.Label := WPF.CreateLabel(Text, Width, Height, Margin);
/// Элемент управления Флажок
static function CheckBox(Text: string; Width: real := real.NaN; Height: real := real.NaN;
Margin: Thickness := -1; IsChecked: boolean := False): WPF.CheckBox
:= WPF.CreateCheckBox(Text, Width, Height, Margin, IsChecked);
/// Элемент управления Слайдер
static function Slider(Min: real := 0; Max: real := 10; Step: real := 1; TickFrequency: real := 1;
Width: real := real.NaN; Height: real := real.NaN; Margin: Thickness := -1; Value: real := real.NaN): WPF.Slider
:= WPF.CreateSlider(Min, Max, Step, TickFrequency, Width, Height, Margin, Value);
/// Элемент управления для выбора с раскрывающимся списком
static function ComboBox(Items: array of string := nil; Width: real := real.NaN; Height: real := real.NaN;
Margin: Thickness := -1): WPF.ComboBox := CreateComboBox(Items, Width, Height, Margin);
/// Элемент Прямоугольник
static function Rectangle(Width: real := real.NaN; Height: real := real.NaN;
Margin: Thickness := -1): WPF.Rectangle
:= CreateRectangle(Width, Height, Margin);
/// Отображает границу и фон вокруг дочернего элемента. Основное свойство - Child
static function Border(Width: real := real.NaN; Height: real := real.NaN;
Margin: Thickness := -1; Background: Brush := nil;
BorderBrush: Brush := nil; BorderThickness: Thickness := -1; Child: UIElement := nil): WPF.Border
:= CreateBorder(Width,Height,Margin,Background,BorderBrush,BorderThickness,Child);
/// Элемент управления Радиокнопка. Радиокнопки могут быть сгруппированы по GroupName. Основное событие - Checked
static function RadioButton(Width: real := real.NaN; Height: real := real.NaN; Margin: Thickness := -1;
Text: string := ''; GroupName: string := nil; IsChecked: boolean := False): WPF.RadioButton
:= CreateRadioButton(Width,Height,Margin,Text,GroupName,IsChecked);
// Создает массив элементов управления Радиокнопка
static function RadioButtons(Texts: array of string; Width: real := real.NaN; Height: real := real.NaN;
Margin: Thickness := -1; GroupName: string := nil): array of WPF.RadioButton
:= CreateRadioButtons(Texts, Width, Height, Margin, GroupName);
static function Drawing: WPF.Drawing := CreateDrawing;
/// Визуальный объект для отрисовки
static function DrawingVisual: WPF.DrawingVisual := new WPF.DrawingVisual;
end;
Panels = static class
static function Grid(rows: integer := 1; cols: integer := 1; ColumnWidths: array of real := nil; RowHeights: array of real := nil): TGrid
/// Панель, состоящая из строк и столбцов переменного размера
static function Grid(rows: integer := 1; cols: integer := 1; ColumnWidths: array of real := nil; RowHeights: array of real := nil): WPF.Grid
:= CreateGrid(rows,cols,ColumnWidths,RowHeights);
/// Панель, располагающая элементы управления вертикально или горизонтально
static function StackPanel(Width: real := real.NaN; Height: real := real.NaN;
Margin: Thickness := 0; Horizontal: boolean := False): TStackPanel
:= CreateStackPanel(Width,Height,Margin,Horizontal);
static function DockPanel(Margin: Thickness := 0): TDockPanel := CreateDockPanel(Margin);
Margin: Thickness := -1; Horizontal: boolean := False;
HAlign: HorizontalAlignment := HA.Left; VAlign: VerticalAlignment := VA.Top): WPF.StackPanel
:= CreateStackPanel(Width,Height,Margin,Horizontal,HAlign,VAlign);
/// Панель, в которой можно пристыковывать элементы управления к краям, используя DockPanel.SetDock
static function DockPanel(Margin: Thickness := -1): WPF.DockPanel := CreateDockPanel(Margin);
/// Определяет область, в которой можно располагать элементы управления с помощью координат
static function Canvas(Margin: Thickness := -1): WPF.Canvas := CreateCanvas(Margin);
end;
initialization
MainWindow := new Window;
@ -495,7 +616,7 @@ initialization
MainWindow.Left := w/2;
MainWindow.Top := h/2;
MainWindow.Content := new WrapPanel;
MainWindow.Content := new Grid; // как в стандартном WPF-приложении
CurrentParent := MainWindow;
finalization
Application.Run(MainWindow);

View file

@ -2483,10 +2483,16 @@ function SSetStr(params a: array of string): SortedSet<string>;
function Dict<TKey, TVal>(params pairs: array of KeyValuePair<TKey, TVal>): Dictionary<TKey, TVal>;
/// Возвращает словарь пар элементов (ключ, значение)
function Dict<TKey, TVal>(params pairs: array of (TKey, TVal)): Dictionary<TKey, TVal>;
/// Возвращает словарь пар элементов (ключ, значение), построенный на значениях последовательности
/// Возвращает словарь пар элементов (ключ, значение), построенный по последовательности пар
function Dict<TKey, TVal>(pairs: sequence of KeyValuePair<TKey, TVal>): Dictionary<TKey, TVal>;
/// Возвращает словарь пар элементов (ключ, значение), построенный по последовательности пар
function Dict<TKey, TVal>(pairs: sequence of (TKey, TVal)): Dictionary<TKey, TVal>;
/// Возвращает словарь пар элементов (ключ, значение), построенный по последовательностям ключей и значений
function Dict<TKey, TVal>(keys: sequence of TKey; values: sequence of TVal): Dictionary<TKey, TVal>;
/// Возвращает пару элементов (ключ, значение)
function KV<TKey, TVal>(key: TKey; value: TVal): KeyValuePair<TKey, TVal>;
/// Возвращает пару элементов (ключ, значение)
function Pair<TKey, TVal>(key: TKey; value: TVal): KeyValuePair<TKey, TVal>;
/// Возвращает словарь пар элементов (строка, строка)
function DictStr(params pairs: array of (string, string)): Dictionary<string, string>;
/// Возвращает словарь пар элементов (строка, целое)
@ -5710,13 +5716,21 @@ begin
Result.Add(pairs[i][0], pairs[i][1]);
end;
function Dict<TKey, TVal>(pairs: sequence of (TKey, TVal)): Dictionary<TKey, TVal>
:= Dict(pairs.ToArray); // внутренняя ошибка компилятора
function Dict<TKey, TVal>(pairs: sequence of KeyValuePair<TKey, TVal>): Dictionary<TKey, TVal>
:= Dict(pairs.ToArray);
function KV<TKey, TVal>(key: TKey; value: TVal): KeyValuePair<TKey, TVal>;
begin
Result := new KeyValuePair<TKey, TVal>(key, value);
end;
function Dict<TKey, TVal>(pairs: sequence of (TKey, TVal)): Dictionary<TKey, TVal>
:= Dict(pairs.ToArray);
function Dict<TKey, TVal>(keys: sequence of TKey; values: sequence of TVal): Dictionary<TKey, TVal>
:= Dict(keys.Zip(values, (k,v) -> KV(k,v)));
function KV<TKey, TVal>(key: TKey; value: TVal): KeyValuePair<TKey, TVal>
:= new KeyValuePair<TKey, TVal>(key, value);
function Pair<TKey, TVal>(key: TKey; value: TVal): KeyValuePair<TKey, TVal>
:= new KeyValuePair<TKey, TVal>(key, value);
function DictStr(params pairs: array of (string, string)): Dictionary<string, string>
:= Dict&<string, string>(pairs);
@ -14125,12 +14139,58 @@ begin
Result := Self.GroupBy(x->x).ToDictionary(g -> g.Key, g -> proj(g.Key));
end;
/// Операция удаления из словаря пары с указанным значением ключа
/// Обновляет данные в словаре данными из другого словаря
procedure Update<TKey, TVal>(Self: Dictionary<TKey, TVal>; update: Dictionary<TKey, TVal>); extensionmethod;
begin
foreach var kv in update do
Self[kv.Key] := kv.Value;
end;
/// Обновляет данные в словаре данными из другого словаря
procedure operator+=<TKey, TVal>(Self: Dictionary<TKey, TVal>; update: Dictionary<TKey, TVal>); extensionmethod;
begin
foreach var kv in update do
Self[kv.Key] := kv.Value;
end;
/// Объединяет данные в двух словарях. Если в обоих имеются одинаковые ключи, то с ключом связывается значение из второго словаря
function operator+<TKey, TVal>(Self: Dictionary<TKey, TVal>; dict: Dictionary<TKey, TVal>): Dictionary<TKey, TVal>; extensionmethod;
begin
var d := PABCSystem.Dict(Self);
d += dict;
Result := d;
end;
/// Удаляет из словаря пары с указанным значением ключа
procedure operator-=<Key,Value>(Self: IDictionary<Key,Value>; k: Key); extensionmethod;
begin
Self.Remove(k);
end;
/// Удаляет из словаря пары с указанными значениями ключа
procedure operator-=<Key,Value>(Self: IDictionary<Key,Value>; keys: sequence of Key); extensionmethod;
begin
foreach var k in keys do
Self.Remove(k);
end;
/// Возвращает словарь, в котором из исходного словаря удален элемент с данным ключом
function operator-<TKey, TVal>(Self: Dictionary<TKey, TVal>; key: TKey): Dictionary<TKey, TVal>; extensionmethod;
begin
var d := Dict(Self);
d -= key;
Result := d;
end;
/// Возвращает словарь, в котором из исходного словаря удалены все элементы с ключами, задаваемыми вторым операндом
function operator-<TKey, TVal>(Self: Dictionary<TKey, TVal>; keys: sequence of TKey): Dictionary<TKey, TVal>; extensionmethod;
begin
var d := Dict(Self);
d -= keys;
Result := d;
end;
// --------------------------------------------
//>> Методы расширения типа Tuple # Extension methods for Tuple
// -------------------------------------------

View file

@ -477,6 +477,12 @@ begin
Result[i] := CreateRadioButton(Width, Height, Margin, Texts[i], GroupName);
end;
function Bordered(Self: UIElement; BorderThickness: Thickness := -1; BorderBrush: Brush := nil; Margin:
Thickness := -1): WPF.Border; extensionmethod;
begin
Result := CreateBorder(BorderBrush := BorderBrush, BorderThickness := BorderThickness, Margin := Margin, Child := Self);
end;
//-----------------------------------------------------------------------//
// Функции создания панелей
//-----------------------------------------------------------------------//