spiegel-keyman/developer/src/tike/project/Keyman.Developer.UI.Project.UfrmNewModelProjectParameters.pas

580 lines
15 KiB
ObjectPascal

unit Keyman.Developer.UI.Project.UfrmNewModelProjectParameters;
interface
uses
System.Classes,
System.SysUtils,
System.UITypes,
System.Variants,
Winapi.Messages,
Winapi.Windows,
Vcl.CheckLst,
Vcl.Controls,
Vcl.Dialogs,
Vcl.ExtCtrls,
Vcl.Forms,
Vcl.Graphics,
Vcl.Grids,
Vcl.StdCtrls,
Browse4Folder,
kpsfile,
PackageInfo,
UfrmTike,
utilfiletypes;
type
TfrmNewModelProjectParameters = class(TTikeForm)
lblFileName: TLabel;
lblPath: TLabel;
lblAuthorID: TLabel;
lblCoypright: TLabel;
lblVersion: TLabel;
lblAuthor: TLabel;
lblLanguages: TLabel;
editModelID: TEdit;
cmdBrowse: TButton;
editPath: TEdit;
editAuthorID: TEdit;
editCopyright: TEdit;
editVersion: TEdit;
editAuthor: TEdit;
cmdOK: TButton;
cmdCancel: TButton;
gridLanguages: TStringGrid;
cmdAddLanguage: TButton;
cmdEditLanguage: TButton;
cmdRemoveLanguage: TButton;
lblBCP47: TLabel;
lblUniq: TLabel;
editUniq: TEdit;
cbBCP47: TComboBox;
lblModelName: TLabel;
editModelName: TEdit;
Bevel1: TBevel;
lblProjectFilename: TLabel;
editProjectFilename: TEdit;
Label1: TLabel;
editFullCopyright: TEdit;
procedure cmdOKClick(Sender: TObject);
procedure editModelIDComponentChange(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure gridLanguagesClick(Sender: TObject);
procedure gridLanguagesDblClick(Sender: TObject);
procedure cmdAddLanguageClick(Sender: TObject);
procedure cmdEditLanguageClick(Sender: TObject);
procedure cmdRemoveLanguageClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure editCopyrightChange(Sender: TObject);
procedure editVersionChange(Sender: TObject);
procedure editAuthorChange(Sender: TObject);
procedure editPathChange(Sender: TObject);
procedure editModelIDChange(Sender: TObject);
procedure cmdBrowseClick(Sender: TObject);
procedure editModelNameChange(Sender: TObject);
procedure editFullCopyrightChange(Sender: TObject);
private
pack: TKPSFile;
FSetup: Integer;
dlgBrowse: TBrowse4Folder;
function GetAuthor: string;
function GetBasePath: string;
function GetCopyright: string;
function GetBCP47Tags: string;
function GetVersion: string;
function Validate: Boolean;
procedure EnableControls;
function SelectedLanguage: TPackageKeyboardLanguage;
procedure LanguageGrid_Fill;
procedure BCP47_Fill;
function SelectedLexicalModel: TPackageLexicalModel;
function GetModelID: string;
procedure UpdateAuthorIDFromAuthor;
procedure UpdateUniqFromModelName;
function GetModelName: string;
function GetAuthorID: string;
function GetPrimaryBCP47: string;
function GetUniq: string;
procedure UpdateModelIDFromComponents;
procedure UpdateProjectFilename;
function GetFullCopyright: string;
protected
function GetHelpTopic: string; override;
property AuthorID: string read GetAuthorID;
property PrimaryBCP47: string read GetPrimaryBCP47;
property Uniq: string read GetUniq;
public
property Copyright: string read GetCopyright;
property FullCopyright: string read GetFullCopyright;
property Version: string read GetVersion;
property Author: string read GetAuthor;
property ModelName: string read GetModelName;
property BCP47Tags: string read GetBCP47Tags;
property BasePath: string read GetBasePath;
property ModelID: string read GetModelID;
end;
function ShowNewModelProjectParameters(Owner: TComponent): Boolean;
implementation
uses
Keyman.System.LanguageCodeUtils,
Keyman.System.LexicalModelUtils,
BCP47Tag,
utilstr,
dmActionsMain,
KeymanDeveloperOptions,
Keyman.Developer.System.HelpTopics,
Keyman.Developer.System.Project.Project,
Keyman.Developer.System.Project.ProjectFile,
Keyman.Developer.System.ModelProjectTemplate,
Keyman.Developer.System.ProjectTemplate,
Keyman.Developer.UI.UfrmSelectBCP47Language;
{$R *.dfm}
function ShowNewModelProjectParameters(Owner: TComponent): Boolean;
var
f: TfrmNewModelProjectParameters;
pt: TProjectTemplate;
begin
f := TfrmNewModelProjectParameters.Create(Owner);
try
Result := f.ShowModal = mrOk;
if not Result then
Exit;
pt := TModelProjectTemplate.Create(f.BasePath, f.ModelID);
try
pt.Name := f.ModelName;
pt.Copyright := f.Copyright;
pt.FullCopyright := f.FullCopyright;
pt.Author := f.Author;
pt.Version := f.Version;
pt.BCP47Tags := f.BCP47Tags;
try
pt.Generate;
except
on E:EFOpenError do
begin
ShowMessage('Unable to create project: '+E.Message);
Exit(False);
end;
end;
modActionsMain.OpenProject(pt.ProjectFilename);
Result := True;
finally
pt.Free;
end;
finally
f.Free;
end;
end;
{ TfrmNewModelProjectParameters }
procedure TfrmNewModelProjectParameters.FormCreate(Sender: TObject);
begin
inherited;
editPath.Text := FKeymanDeveloperOptions.DefaultProjectPath;
dlgBrowse := TBrowse4Folder.Create(Self);
dlgBrowse.InitialDir := editPath.Text;
dlgBrowse.Options := [OnlySelectFileSysAncestors, ShowEditBox, UseNewDialogStyle];
dlgBrowse.Root := Desktop;
dlgBrowse.Title := 'Select folder to save project to';
pack := TKPSFile.Create;
pack.LexicalModels.Add(TPackageLexicalModel.Create(pack));
LanguageGrid_Fill;
EnableControls;
end;
procedure TfrmNewModelProjectParameters.FormDestroy(Sender: TObject);
begin
inherited;
FreeAndNil(pack);
end;
function TfrmNewModelProjectParameters.GetHelpTopic: string;
begin
Result := SHelpTopic_Context_NewModelProjectParameters;
end;
procedure TfrmNewModelProjectParameters.cmdBrowseClick(Sender: TObject);
begin
dlgBrowse.InitialDir := editPath.Text;
if dlgBrowse.Execute and (dlgBrowse.FileName <> '') then
editPath.Text := ExcludeTrailingPathDelimiter(dlgBrowse.FileName);
end;
procedure TfrmNewModelProjectParameters.cmdAddLanguageClick(
Sender: TObject);
var
lm: TPackageLexicalModel;
lang: TPackageKeyboardLanguage;
frm: TfrmSelectBCP47Language;
begin
lm := SelectedLexicalModel;
Assert(Assigned(lm));
frm := TfrmSelectBCP47Language.Create(Self);
try
if frm.ShowModal = mrOk then
begin
lang := TPackageKeyboardLanguage.Create(pack);
lang.ID := frm.LanguageID;
lang.Name := frm.LanguageName;
lm.Languages.Add(lang);
BCP47_Fill;
LanguageGrid_Fill;
gridLanguages.Row := gridLanguages.RowCount - 1;
gridLanguagesClick(gridLanguages);
EnableControls;
end;
finally
frm.Free;
end;
end;
procedure TfrmNewModelProjectParameters.cmdEditLanguageClick(
Sender: TObject);
var
lm: TPackageLexicalModel;
lang: TPackageKeyboardLanguage;
frm: TfrmSelectBCP47Language;
begin
lm := SelectedLexicalModel;
Assert(Assigned(lm));
lang := SelectedLanguage;
Assert(Assigned(lang));
frm := TfrmSelectBCP47Language.Create(Self);
try
frm.LanguageID := lang.ID;
frm.LanguageName := lang.Name;
if frm.ShowModal = mrOk then
begin
lang.ID := frm.LanguageID;
lang.Name := frm.LanguageName;
BCP47_Fill;
LanguageGrid_Fill;
EnableControls;
end;
finally
frm.Free;
end;
end;
procedure TfrmNewModelProjectParameters.cmdRemoveLanguageClick(
Sender: TObject);
var
lm: TPackageLexicalModel;
lang: TPackageKeyboardLanguage;
begin
lm := SelectedLexicalModel;
Assert(Assigned(lm));
lang := SelectedLanguage;
Assert(Assigned(lang));
lm.Languages.Remove(lang);
LanguageGrid_Fill;
BCP47_Fill;
EnableControls;
end;
procedure TfrmNewModelProjectParameters.cmdOKClick(Sender: TObject);
begin
if Validate then
ModalResult := mrOk;
end;
procedure TfrmNewModelProjectParameters.editAuthorChange(Sender: TObject);
begin
UpdateAuthorIDFromAuthor;
EnableControls;
end;
procedure TfrmNewModelProjectParameters.editModelNameChange(Sender: TObject);
begin
UpdateUniqFromModelName;
EnableControls;
end;
procedure TfrmNewModelProjectParameters.editCopyrightChange(Sender: TObject);
begin
EnableControls;
end;
procedure TfrmNewModelProjectParameters.editFullCopyrightChange(
Sender: TObject);
begin
EnableControls;
end;
procedure TfrmNewModelProjectParameters.editModelIDChange(Sender: TObject);
begin
UpdateProjectFilename;
EnableControls;
end;
procedure TfrmNewModelProjectParameters.editModelIDComponentChange(Sender: TObject);
begin
UpdateModelIDFromComponents;
EnableControls;
end;
procedure TfrmNewModelProjectParameters.editPathChange(Sender: TObject);
begin
UpdateProjectFilename;
EnableControls;
end;
procedure TfrmNewModelProjectParameters.editVersionChange(Sender: TObject);
begin
EnableControls;
end;
procedure TfrmNewModelProjectParameters.EnableControls;
var
e: Boolean;
begin
e :=
not Author.IsEmpty and
not ModelName.IsEmpty and
not AuthorID.IsEmpty and
not PrimaryBCP47.IsEmpty and
not Uniq.IsEmpty and
not Trim(editPath.Text).IsEmpty and
TLexicalModelUtils.DoesProjectFilenameFollowLexicalModelConventions(editModelID.Text + Ext_LexicalModelProject) and
(pack.LexicalModels[0].Languages.Count > 0);
cmdOK.Enabled := e;
e := gridLanguages.RowCount > 1;
gridLanguages.Enabled := e;
cmdRemoveLanguage.Enabled := e;
cmdEditLanguage.Enabled := e;
if e then
gridLanguages.FixedRows := 1;
end;
function TfrmNewModelProjectParameters.GetAuthor: string;
begin
Result := Trim(editAuthor.Text);
end;
function TfrmNewModelProjectParameters.GetAuthorID: string;
begin
Result := Trim(editAuthorID.Text);
end;
function TfrmNewModelProjectParameters.GetBasePath: string;
begin
Result := Trim(editPath.Text);
end;
function TfrmNewModelProjectParameters.GetCopyright: string;
begin
Result := Trim(editCopyright.Text);
end;
function TfrmNewModelProjectParameters.GetFullCopyright: string;
begin
Result := editFullCopyright.Text;
end;
function TfrmNewModelProjectParameters.GetModelID: string;
begin
Result := editModelID.Text;
end;
function TfrmNewModelProjectParameters.GetModelName: string;
begin
Result := Trim(editModelName.Text);
end;
function TfrmNewModelProjectParameters.GetPrimaryBCP47: string;
begin
Result := Trim(cbBCP47.Text);
end;
function TfrmNewModelProjectParameters.GetUniq: string;
begin
Result := Trim(editUniq.Text);
end;
function TfrmNewModelProjectParameters.GetBCP47Tags: string;
var
lang: TPackageKeyboardLanguage;
begin
Result := '';
for lang in pack.LexicalModels[0].Languages do
Result := Result + lang.ID + ' ';
Result := Result.Trim;
end;
function TfrmNewModelProjectParameters.GetVersion: string;
begin
Result := Trim(editVersion.Text);
end;
procedure TfrmNewModelProjectParameters.gridLanguagesClick(
Sender: TObject);
begin
EnableControls;
end;
procedure TfrmNewModelProjectParameters.gridLanguagesDblClick(
Sender: TObject);
begin
if SelectedLanguage <> nil then
cmdEditLanguage.Click;
end;
function TfrmNewModelProjectParameters.Validate: Boolean;
var
ProjectFolder: string;
begin
Result := TLexicalModelUtils.DoesProjectFilenameFollowLexicalModelConventions(editModelID.Text + Ext_LexicalModelProject);
if Result then
begin
if not DirectoryExists(editPath.Text) then
begin
if MessageDlg('The target folder '+editPath.Text+' does not exist. Create it now?', mtConfirmation, mbOkCancel, 0) = mrCancel then
Exit(False);
end;
ProjectFolder := IncludeTrailingPathDelimiter(editPath.Text) + editModelID.Text;
if DirectoryExists(ProjectFolder) then
begin
if MessageDlg('The project folder '+ProjectFolder+' already exists. Are you sure you want to overwrite it?', mtWarning,
mbOkCancel, 0) = mrCancel then
Exit(False);
end;
end;
end;
{ Dynamically update other fields based on filled details }
procedure TfrmNewModelProjectParameters.UpdateAuthorIDFromAuthor;
begin
editAuthorID.Text := TLexicalModelUtils.CleanLexicalModelIDComponent(Author);
editCopyright.Text := Char($00A9 {copyright})+' '+Author;
editFullCopyright.Text := Char($00A9 {copyright})+' '+FormatDateTime('yyyy', Now)+' '+Author;
end;
procedure TfrmNewModelProjectParameters.UpdateUniqFromModelName;
begin
editUniq.Text := TLexicalModelUtils.CleanLexicalModelIDComponent(ModelName);
end;
procedure TfrmNewModelProjectParameters.UpdateModelIDFromComponents;
begin
editModelID.Text := Format('%s.%s.%s', [AuthorID, PrimaryBCP47.ToLowerInvariant, Uniq]);
end;
procedure TfrmNewModelProjectParameters.UpdateProjectFilename;
begin
editProjectFilename.Text :=
IncludeTrailingPathDelimiter(BasePath) +
ModelID + PathDelim +
ModelID + Ext_LexicalModelProject;
// Scroll to the end of the control to show the filename
editProjectFilename.Perform(EM_SETSEL, Length(editProjectFilename.Text), Length(editProjectFilename.Text));
editProjectFilename.Perform(EM_SCROLLCARET, 0, 0);
end;
{ Languages Grid }
function TfrmNewModelProjectParameters.SelectedLexicalModel: TPackageLexicalModel;
begin
Result := pack.LexicalModels[0];
end;
function TfrmNewModelProjectParameters.SelectedLanguage: TPackageKeyboardLanguage;
var
lm: TPackageLexicalModel;
begin
lm := SelectedLexicalModel;
if not Assigned(lm) then
Exit(nil);
if gridLanguages.Row = 0 then
Exit(nil);
Result := gridLanguages.Objects[0, gridLanguages.Row] as TPackageKeyboardLanguage;
end;
procedure TfrmNewModelProjectParameters.LanguageGrid_Fill;
var
lm: TPackageLexicalModel;
i: Integer;
begin
Inc(FSetup);
try
gridLanguages.Cells[0, 0] := 'BCP 47 tag';
gridLanguages.Cells[1, 0] := 'Language name';
gridLanguages.ColWidths[0] := 120;
gridLanguages.ColWidths[1] := 10;
lm := SelectedLexicalModel;
if not Assigned(lm) then
begin
gridLanguages.RowCount := 1;
EnableControls;
Exit;
end;
gridLanguages.RowCount := lm.Languages.Count + 1;
gridLanguages.ColWidths[1] := gridLanguages.ClientWidth - 120 - 1;
for i := 0 to lm.Languages.Count - 1 do
begin
gridLanguages.Objects[0, i+1] := lm.Languages[i];
gridLanguages.Cells[0, i+1] := lm.Languages[i].ID;
gridLanguages.Cells[1, i+1] := lm.Languages[i].Name;
end;
EnableControls;
finally
Dec(FSetup);
end;
end;
procedure TfrmNewModelProjectParameters.BCP47_Fill;
var
lm: TPackageLexicalModel;
FLastBCP47: string;
lang: TPackageKeyboardLanguage;
begin
FLastBCP47 := cbBCP47.Text;
cbBCP47.Clear;
lm := SelectedLexicalModel;
if not Assigned(lm) then
Exit;
for lang in lm.Languages do
cbBCP47.Items.Add(lang.ID);
cbBCP47.ItemIndex := cbBCP47.Items.IndexOf(FLastBCP47);
if (cbBCP47.ItemIndex < 0) and (cbBCP47.Items.Count > 0) then
cbBCP47.ItemIndex := 0;
editModelIDComponentChange(cbBCP47);
end;
end.