Замечания и предложения

@Sun_Serega, Stopwatch можно использовать без указания пространств имен:

var sw1 := new Stopwatch;
sw1.Start;
    ...
sw1.Stop;
Writeln(sw1.Elapsed);

Мне не нравятся имена - Stopwatch и Elapsed. Я хотел бы сделать класс Performance на этом движке и несколько свойств с более понятным названием. И возможно чтобы сразу можно было запустить.

Как то так:?

begin
  var p1 := new Performance;
  
  p1.Measure(()->
  begin
    //ToDo какой то код
  end);
  
  p1.Measure(()->
  begin
    //ToDo какой то код
  end);
  
  p1.Println;
end.

Ну, по моему имя Stopwatch как раз больше отражает суть того, чем замеряют время. А вот Elapsed это уже заумное слово, но чем его лучше заменить - не уверен.

Как насчёт добавить возможность указывать режим маштабирования картинок в WPF модули? На куберфоруме человеку понадобилось.

Если что - вот перечисление, контролирующее этот режим.

1 лайк

Как насчет “убрать” все внутренние ключевые слова begin? Ну вот в записи, перед описанием полей, нет же слова begin, хотя вроде логично было бы его там использовать. В условных операторах это могло бы выглядеть так:

if a > 1 then
  ...
end
else
  ...
end;

Сразу видно к чему относится else. Или в циклах:

while b > 5 do
  ...
end;

И никогда не забудешь использовать операторные скобки, поскольку их и не будет как таковых, а будет всегда обязательное end. То есть на самом деле блоки в таких конструкциях будут обозначены между словами then end или else end или do end и так далее. И они будут всегда.

UPD: А операторыне скобки begin-end пусть останутся для потребности обозначения каких-либо других блоков где угодно в коде. Да и внутри функции для обозначения тела функции они наверное нужны.

UPD2: Можно не убирать begin-ы, а добавить еще и такую возможность, чтобы не переписывать весь паскаль =).

Лично я - категорически против. Сейчас количество begin совпадает с количеством end, как и должно быть, т.е. своеобразная парность “скобок” легко контролируется. Если убрать begin, но сделать обязательные end, ограничивающие элементы операторов, получится ерунда. Во-первых, полностью потеряется всякая совместимость с прежними версиями паскаля, допускающими запись без операторных скобок, например,

if a > 0 then
     Print('P')
else
    Print('N');
for i := 1 to n do
    a[i] := 2 * i - 1;

Во-вторых, все что Вы предлагаете - это в точности синтаксис языка Modula-2. Но причем тут Паскаль?

Хочется быть понятым правильно. Мне синтаксис управляющих конструкций в Modila-2 и Oberon нравится куда больше паскалевского. Но язык-то все же называется Pascal, пусть даже с приставкой АВС.NЕТ.

1 лайк

Вообще это я в Руби подсмотрел. А вся эта совместимость со старыми версиями паскалей-дельфи, как по мне, аки якорь для паскаля ABC. NET. Кому нужна эта каша-совместимость. Школьникам нужна? Да и паскаль ABC. NET уже и не паскаль вовсе.

Почему не Паскаль?

Возьмите любую программу, написанную на Паскале или Delphi и откомпилируйте. Она откомпилируется и запустится.

Вам не нужна - мы-то тут при чём? :slight_smile:

А если бы мы хотели бы написать руби, то написали бы руби.

И прошу вас - не подглядывайте в Хаскель.

А Вы в Руби случайно не подсмотрели, что популярность этого языка, так и не воспарив, начала снижаться?

Как-то попадалось несколько авторских вариантов операторных скобок, когда, например, написанное в одну строку автоматически считали блоком или же заменяли begin-end на фигурные скобки как в си, потому что “так короче и быстрее”, но после такого подхода сложно вернуться к традиционному.

Не не, вы не поняли. Не мне не нужна эта совместимость, хотя я этого и не писал вроде. Если кому-то нужна программа в стиле старого паскаля или дельфи они возьмут этот фри-паскаль или дельфи. Зачем им брать вашу среду? А вот вы лепите старое и новое в одну кучу и у вас получается синтаксический бардак.

Это мнение, пришедшее от нескольких активных пользователей с Киберфорума - мы его никоим образом не поддерживаем. Никакого синтаксического бардака нет - весь синтаксис заточен ровно под Паскаль.

В частности, совсем недавно появилась условная операция в стиле Паскаля:

var min := if x<y then x else y;

Кстати, и Free Pascal развивается - посмотрите на нововведения в его последней версии. В его диалекте тоже есть ряд интересных конструкций, в частности, шаблоны. Правда, не такие мощные, как у нас, - без автовывода типа, но Free Pascal славен другим - своей многоплатформенностью.

Кроме того, у них отсутствует нормальная оболочка, которую можно было бы использовать в обучении. Lazarus - он явно заточен на проектирование оконных интерфейсов.

А обобщения, кортежи и лямбды появляются сейчас во всех языках, и синтаксически они затачиваются именно на этот язык. Язык, который не развивается, - мёртв

Предлагаю добавить самописный модуль в папку стандартных модулей паскаля - WPFButton, или же в WPFObjects добавить как отдельный класс.

Думаю “Кнопки” понадобятся многим,кто пишет программы,связанные с WPF на данном языке.

unit WPFButton;

interface

uses SIRObjectsWPF;

type
  ButtonWPF = class(RectangleWPF)
    private clb: boolean;
    public event Click: procedure;
  
  private
    procedure MouseDown(x, y: real; mb: integer);
    begin
      if (ObjectUnderPoint(x, y) = self) and (mb = 1)
      then begin
        self.AnimMoveTo(self.Left + 2, self.Top + 2, 0.1);
        clb := true;
      end;
    end;
    
    procedure MouseUp(x, y: real; mb: integer);
    begin
      if (ObjectUnderPoint(x, y) = self)
        then 
        if Click <> nil
          then Click;
      
      if clb
      then begin
        self.AnimMoveTo(self.Left - 2, self.Top - 2, 0.1);
        clb := false;
      end;
    end;
    
    public constructor Create(x, y, w, h: real; cl: Gcolor; s: string);
    begin
      inherited Create(x, y, w, h, cl);
      self.Text := s;
      OnMouseDown += MouseDown;
      OnMouseUp += MouseUp;
    end;
    
    public constructor Create(x, y, w, h, bw: real; cl: Gcolor; bcl: GColor; s: string);
    begin
      inherited Create(x, y, w, h, cl, bw, bcl);
      self.Text := s;
      OnMouseDown += MouseDown;
      OnMouseUp += MouseUp;
    end;
    
    procedure Dispose;
    begin
      OnMouseDown -= MouseDown;
      OnMouseUp -= MouseUp;
    end;
  
  end;


implementation

begin

end. 
1 лайк

А убирать как? Наверное деструктор надо…

Т.к. я унаследовал от класса RectangleWPF, то процедура с именем “Destroy” уже есть.Может назвать Dispose?

Все,добавил.

Рассмотрите такой код:

uses GraphWPF,Controls;

begin
  Window.Title := 'Цвета';
  Font.Size := 40;
  AddLeftPanel(150);

  var rb := IntegerBlock('Красный:',12,255);
  var r := Slider(0,255,255);
  EmptyBlock;
  var gb := IntegerBlock('Зеленый:',12,255);
  var g := Slider(0,255,255);
  EmptyBlock;
  var bb := IntegerBlock('Синий:',12,255);
  var b := Slider(0,255,255);
  
  EmptyBlock;
  var bt := Button('Выход');
  bt.Click := procedure -> Window.Close;
  

  r.Frequency := 16;
  g.Frequency := 16;
  b.Frequency := 16;
  
  var p: procedure := ()-> begin
    Window.Clear(RGB(r.Value.Round,g.Value.Round,b.Value.Round));
    rb.Value := r.Value.Round;
    gb.Value := g.Value.Round;
    bb.Value := b.Value.Round;
    DrawText(GraphWindow.ClientRect,$'R={rb.Value}, G={gb.Value}, B={bb.Value}');
  end;
  r.ValueChanged := p;
  g.ValueChanged := p;
  b.ValueChanged := p;
  p;
end.

Так же хочу предложить изменения в класс “PictureWPF”. В модуле WPFObjects я не нашел возможности отобразить картинку из Ресурсов программы. По этому добавил в PictureWPF несколько методов,и конструкторы,для возможности отобразить картинку из Ресурсов.

Если изменить этот класс в модуле,тоон не работает.При запуске программы вылетает ошибка компилятора “Чтения за концом потока” .Но если скопировать код из модуля WPFObjects изменить название модуля,и изменить класс,то работает,но при таком подходе нужно модуль всегда рядом с программой носить.

PictureWPF = class(ObjectWPF)
private
  PName: string;
  function CreateBitmapImage(fname: string) := new BitmapImage(new System.Uri(fname, System.UriKind.Relative)); 
  procedure Rest(x, y, w, h: real; b: BitmapImage);
  begin
    var im := new System.Windows.Controls.Image();
    im.Source := b;
    im.Width := w;
    im.Height := h;
    
    InitOb(x, y, w, h, im);
  end;
  
  function GetString(self: string; oi, ni: integer): string;
  begin
    for var i := oi to ni do 
      result += self[i];
  end;
  
  procedure InitOb5(x, y, w, h: real; name: string);
  begin
    PName := GetString(name, 1, name.LastIndexOf('.'));
    var bmi := new System.Windows.Media.Imaging.BitmapImage();
    bmi.BeginInit();
    bmi.StreamSource := GetResourceStream(name);
    bmi.EndInit();
    Rest(x, y, w, h, bmi);
  end;
  
  procedure InitOb4(x, y: real; name: string);
  begin
    PName := GetString(name, 1, name.LastIndexOf('.'));
    var bmi := new System.Windows.Media.Imaging.BitmapImage();
    bmi.BeginInit();
    bmi.StreamSource := GetResourceStream(name);
    bmi.EndInit();
    Rest(x, y, bmi.PixelWidth, bmi.PixelHeight, bmi);
  end;
  
  procedure InitOb3(x, y, w, h: real; fname: string);
  begin
    var b := CreateBitmapImage(fname);
    Rest(x, y, w, h, b);
  end;
  
  procedure InitOb2(x, y: real; fname: string);
  begin
    var b := CreateBitmapImage(fname);
    Rest(x, y, b.PixelWidth, b.PixelHeight, b);
  end;
  
  function GetInternalGeometry: Geometry; override;
  begin
    var r := Rect(0, 0, Width, Height);
    Result := new RectangleGeometry(r);
  end;

public
  function Element := ob as System.Windows.Controls.Image;
    /// Создает рисунок из файла fname с координатами левого верхнего угла (x,y)
  constructor(x, y: real; fname: string):= Invoke(InitOb2, x, y, fname);
    /// Создает рисунок из файла fname с координатами левого верхнего угла (x,y) и размерами (w,h)
constructor(x, y, w, h: real; fname: string):= Invoke(InitOb3, x, y, w, h, fname);
    /// Создает рисунок из файла fname с координатой левого верхнего угла, заданной точкой p
constructor(p: Point; fname: string):= Invoke(InitOb2, p.x, p.y, fname);
    /// Создает рисунок из файла fname  с координатой левого верхнего угла, заданной точкой p, и размерами (w,h)
constructor(p: Point; w, h: real; fname: string):= Invoke(InitOb3, p.x, p.y, w, h, fname);
    ///Создает рисунок из потока
constructor(x, y: real; name: string;b:boolean:=false):=Invoke(InitOb4, x, y, name);
    ///Создает рисунок из потока с шириной w и высотой h
constructor(x, y, w, h: real; name: string;b:boolean:=false):=Invoke(InitOb5, x, y, w, h, name);
    /// Декоратор текста объекта
function SetText(txt: string; size: real := 16; fontname: string := 'Arial'; c: GColor := Colors.Black): PictureWPF  
:= inherited SetText(txt, size, fontname, c) as PictureWPF;
    /// Декоратор поворота объекта
  function SetRotate(da: real): PictureWPF := inherited SetRotate(da) as PictureWPF;
  
  property Name: string read PName write PName := value;
end;

Не работает. “Program1.pas(31) : ClientRect не объявлен в типе GraphWindowType” У меня стоит не последняя версия, т.к. последнее обновление сломало что-то,не помню что именно,нет времени искать минимальный код,поставил версию до последнего обновления

Немного изменил ваш код,теперь работает:

uses GraphWPF, Controls;

begin
  Window.Title := 'Цвета';
  Font.Size := 40;
  AddLeftPanel(150);
  
  var rb := IntegerBlock('Красный:', 12, 255);
  var r := Slider(0, 255, 255);
  EmptyBlock;
  var gb := IntegerBlock('Зеленый:', 12, 255);
  var g := Slider(0, 255, 255);
  EmptyBlock;
  var bb := IntegerBlock('Синий:', 12, 255);
  var b := Slider(0, 255, 255);
  
  EmptyBlock;
  var bt := Button('Выход');
  bt.Click := procedure -> Window.Close;
  
  
  r.Frequency := 16;
  g.Frequency := 16;
  b.Frequency := 16;
  
  var p: procedure := () -> begin
    Window.Clear(RGB(r.Value.Round, g.Value.Round, b.Value.Round));
    rb.Value := r.Value.Round;
    gb.Value := g.Value.Round;
    bb.Value := b.Value.Round;
    DrawText(Window.ClientRect, $'R={rb.Value}, G={gb.Value}, B={bb.Value}');
  end;
  r.ValueChanged += p;
  g.ValueChanged += p;
  b.ValueChanged += p;
  p;
end.

Лучше тогда принимать System.IO.Stream а не string.