nlve/src/uAboutForm.pas
4aiman 4c422ef57d Курсор прилипает к границам клипов
Курсор воспроизведения по щелчку вставал ровно туда, куда попала мышь.
В стык двух кусков так не попасть: на общем плане одна точка экрана —
это секунды материала, а ставят курсор чаще всего именно на стык.

Теперь он притягивается к границам клипов на любой дорожке и к началу
монтажа. Работает и при щелчке по клипу, и по линейке, и по пустому
месту, и при протяжке. Shift меняет решение на противоположное — как у
прилипания клипов.

Переключатель свой, со значком клея, рядом с магнитом: клипы липнут при
перетаскивании, курсор — при щелчке, это разные привычки, и одно бывает
нужно без другого. Состояние переживает перезапуск.

Расчёт открыт наружу и проверяется числами: семь проверок в lfmcheck,
от «стык рядом — притянуло» до «выключено — не притягивает».
2026-08-31 00:32:44 +03:00

235 lines
10 KiB
ObjectPascal
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
uAboutForm — окно «О программе».
Две вкладки. «Ресурсы» — на чём программа держится и чьи значки
использует: бесплатная лицензия Icons8 требует ссылку на каждый значок.
«Возможности» — что программа умеет.
Вкладки свои, а не TPageControl: системные под Windows остались бы
светлой полосой поверх тёмного окна.
Текст показывает uArticleView: он сам переносит строки по ширине окна и
делает ссылки нажимаемыми.
}
unit uAboutForm;
{$mode objfpc}{$H+}
interface
uses
Classes, SysUtils, Controls, Forms, Graphics, StdCtrls, Dialogs,
uTheme, uArticleView;
procedure ShowAboutForm;
implementation
type
{ Обработчики живут в объекте: событиям нужны методы. }
TAboutDialog = class(TComponent)
public
Form: TForm;
BtnResources: TThemedButton;
BtnFeatures: TThemedButton;
ViewResources: TArticleView;
ViewFeatures: TArticleView;
procedure ShowResources(Sender: TObject);
procedure ShowFeatures(Sender: TObject);
procedure Select(AResources: Boolean);
end;
procedure TAboutDialog.Select(AResources: Boolean);
begin
BtnResources.Down := AResources;
BtnFeatures.Down := not AResources;
ViewResources.Visible := AResources;
ViewFeatures.Visible := not AResources;
end;
procedure TAboutDialog.ShowResources(Sender: TObject);
begin
Select(True);
end;
procedure TAboutDialog.ShowFeatures(Sender: TObject);
begin
Select(False);
end;
{ Списки под Windows и под Linux разные: там сборки скачивает сама
программа, здесь их ставит пакетный менеджер. }
function ResourcesText: string;
begin
Result :=
'# nlve' + LineEnding +
'Монтаж без перекодирования: куски вырезаются и склеиваются ' +
'копированием потока.' + LineEnding +
'Автор: 4aiman' + LineEnding +
LineEnding +
'# Значки' + LineEnding +
'Icons8. Нужна ссылка на каждый значок.' + LineEnding +
'Прилипание — Magnet' + LineEnding +
' https://icons8.com/icon/79942/magnet' + LineEnding +
'Схлопывание — Merge Vertical' + LineEnding +
' https://icons8.com/icon/2EQegp8tbR6Q/merge-vertical' + LineEnding +
'Журнал — Property' + LineEnding +
' https://icons8.com/icon/79872/property' + LineEnding +
'Прилипание курсора — Клей' + LineEnding +
' https://icons8.com/icon/111296/glue' + LineEnding +
'Значок программы — Showing Video Frames' + LineEnding +
' https://icons8.com/icon/69093/showing-video-frames' + LineEnding +
'Сам Icons8' + LineEnding +
' https://icons8.com' + LineEnding +
LineEnding +
'# Видео и звук' + LineEnding +
{$IFDEF WINDOWS}
'ffmpeg — нарезка, склейка, перекодирование. Сборка BtbN, GPL.' +
LineEnding +
' https://github.com/BtbN/FFmpeg-Builds' + LineEnding +
' https://ffmpeg.org' + LineEnding +
'libmpv — предпросмотр. Сборка shinchiro, GPL.' + LineEnding +
' https://github.com/shinchiro/mpv-winbuild-cmake' + LineEnding +
' https://mpv.io' + LineEnding +
'7-Zip — распаковка сборок libmpv. LGPL-2.1.' + LineEnding +
' https://www.7-zip.org' + LineEnding +
{$ELSE}
'ffmpeg — нарезка, склейка, перекодирование. GPL-2 и новее.' +
LineEnding +
' sudo apt install ffmpeg' + LineEnding +
' https://ffmpeg.org' + LineEnding +
'libmpv — предпросмотр. GPL-3 и новее.' + LineEnding +
' sudo apt install mpv' + LineEnding +
' https://mpv.io' + LineEnding +
{$ENDIF}
LineEnding +
'# Инструменты' + LineEnding +
'Free Pascal' + LineEnding +
' https://www.freepascal.org' + LineEnding +
'Lazarus LCL' + LineEnding +
' https://www.lazarus-ide.org' + LineEnding +
LineEnding +
'ffmpeg и libmpv в состав программы не входят: ffmpeg запускается ' +
'отдельной программой, libmpv ставится отдельно.';
end;
function FeaturesText: string;
begin
Result :=
'# Монтаж' + LineEnding +
'Дорожки для картинки и для звука.' + LineEnding +
'При перекрытии картинку даёт верхняя дорожка, звук всех дорожек ' +
'смешивается.' + LineEnding +
'Перенос, растягивание за края, рез по курсору (S), удаление.' +
LineEnding +
'Прилипание к соседям и к курсору. Shift отменяет его.' + LineEnding +
'Связки: видео и его звук ходят вместе. Ctrl+G связывает и ' +
'развязывает.' + LineEnding +
'Схлопывание дыр: Ctrl+Shift+R или само при перетаскивании.' +
LineEnding +
'Отмена и повтор: Ctrl+Z, Ctrl+Y.' + LineEnding +
LineEnding +
'# На дорожках' + LineEnding +
'Форма звука. Shift со стрелками усиливает её на тихих записях.' +
LineEnding +
'Громкость и прозрачность — ручкой на клипе.' + LineEnding +
'Появление и уход — за верхние углы клипа.' + LineEnding +
'Перекрытие на одной дорожке помечено крестом: там переход.' +
LineEnding +
'Цвет краёв показывает, потребует ли рез перекодирования.' + LineEnding +
LineEnding +
'# Предпросмотр' + LineEnding +
'Играет монтаж целиком, не собирая файлов.' + LineEnding +
'Показывает кадр проекта, а не кадр исходника.' + LineEnding +
'Прозрачность и переходы видны.' + LineEnding +
LineEnding +
'# Кадрирование' + LineEnding +
'Вписать, заполнить или растянуть. Увеличение, смещение, поворот, ' +
'отражение.' + LineEnding +
'Рамку можно тянуть мышью.' + LineEnding +
'У каждого клипа своё.' + LineEnding +
LineEnding +
'# Сборка' + LineEnding +
'Обычная — копированием потоков, за время копирования файла.' +
LineEnding +
'Заранее сказано, сколько секунд придётся пересобрать и почему.' +
LineEnding +
'Точный рез перекодирует только огрызок до опорного кадра.' +
LineEnding +
'С перекодированием: от 720p до 4K, свой поток, HEVC или H.264, ' +
'на видеокарте.' + LineEnding +
'Перепаковка в другой контейнер без пересчёта.' + LineEnding +
LineEnding +
'# Прочее' + LineEnding +
'Индекс опорных кадров читается из заголовка: 20 мс вместо 12 секунд.' +
LineEnding +
'Фоновая работа видна полоской внизу и штриховкой на монтаже.' +
LineEnding +
'Свои цвета во всех окнах.' + LineEnding +
'Настройки и недавние проекты переживают перезапуск.';
end;
procedure ShowAboutForm;
var
Dlg: TAboutDialog;
BtnClose: TThemedButton;
begin
Dlg := TAboutDialog.Create(nil);
try
Dlg.Form := TForm.CreateNew(nil);
Dlg.Form.Caption := 'О программе';
Dlg.Form.Position := poScreenCenter;
Dlg.Form.ClientWidth := 720;
Dlg.Form.ClientHeight := 560;
Dlg.Form.Constraints.MinWidth := 420;
Dlg.Form.Constraints.MinHeight := 300;
Dlg.BtnResources := TThemedButton.Create(Dlg.Form);
Dlg.BtnResources.Parent := Dlg.Form;
Dlg.BtnResources.SetBounds(12, 12, 140, 28);
Dlg.BtnResources.Caption := 'Ресурсы';
Dlg.BtnResources.TabStop := False;
Dlg.BtnResources.OnClick := @Dlg.ShowResources;
Dlg.BtnFeatures := TThemedButton.Create(Dlg.Form);
Dlg.BtnFeatures.Parent := Dlg.Form;
Dlg.BtnFeatures.SetBounds(158, 12, 140, 28);
Dlg.BtnFeatures.Caption := 'Возможности';
Dlg.BtnFeatures.TabStop := False;
Dlg.BtnFeatures.OnClick := @Dlg.ShowFeatures;
Dlg.ViewResources := TArticleView.Create(Dlg.Form);
Dlg.ViewResources.Parent := Dlg.Form;
Dlg.ViewResources.SetBounds(12, 48, 696, 460);
Dlg.ViewResources.Anchors := [akTop, akLeft, akRight, akBottom];
Dlg.ViewFeatures := TArticleView.Create(Dlg.Form);
Dlg.ViewFeatures.Parent := Dlg.Form;
Dlg.ViewFeatures.SetBounds(12, 48, 696, 460);
Dlg.ViewFeatures.Anchors := [akTop, akLeft, akRight, akBottom];
BtnClose := TThemedButton.Create(Dlg.Form);
BtnClose.Parent := Dlg.Form;
BtnClose.SetBounds(608, 520, 100, 28);
BtnClose.Anchors := [akRight, akBottom];
BtnClose.Caption := 'Закрыть';
BtnClose.ModalResult := mrOk;
BtnClose.Default := True;
BtnClose.Cancel := True;
ApplyDarkTheme(Dlg.Form);
{ Текст задаётся после раскраски: раскладка считается по тому шрифту,
которым он будет нарисован. }
Dlg.ViewResources.SetText(ResourcesText);
Dlg.ViewFeatures.SetText(FeaturesText);
Dlg.Select(True);
Dlg.Form.ShowModal;
finally
Dlg.Form.Free;
Dlg.Free;
end;
end;
end.