From 321020750e82a4f24761ad29cd9db9a043a0c2f9 Mon Sep 17 00:00:00 2001 From: Bart <9132501-flyingsheep@users.noreply.gitlab.com> Date: Wed, 9 Aug 2023 13:39:06 +0200 Subject: [PATCH] TaskDialog: TLCLTaskDialog: - trying to simplify laying out the controls. - use more meaningfull variable and constant names. - cut down on "magic numbers". - try to use the same left margins everywhere (ToDo: right margins). - simplify calculation the global margins: now only depends on tfEmulateClassicStyle, not on presence of an icon. - use a slightly smaller left margin for not tfEmulateClassicStyle (16 instead of 24), looks a bit better when compared to native Vista+ dialog. - more factoring out. - as a byproduct: resolves issue #40437. - less debug output. --- lcl/taskdlgemulation.pp | 342 +++++++++++++++++++++------------------- 1 file changed, 182 insertions(+), 160 deletions(-) diff --git a/lcl/taskdlgemulation.pp b/lcl/taskdlgemulation.pp index 5ba07d2bf7..0216e31323 100644 --- a/lcl/taskdlgemulation.pp +++ b/lcl/taskdlgemulation.pp @@ -21,6 +21,12 @@ type { TLCLTaskDialog } TLCLTaskDialog = class(TForm) + private + const + RadioIndent = 16; + ComboBoxHeight = 22; + LargeImageSize = 32; + SmallImageSize = 16; private /// the Task Dialog structure which created the form FDlg: TTaskDialog; @@ -50,17 +56,20 @@ type /// the Expand/Collaps button ExpandBtn: TButton; - - procedure AddIcon(out IconBorder,X,Y: Integer; AParent: TWinControl); + procedure GetDefaultButtons(out aButtonDef, aRadioDef: TModalResult); + procedure InitCaptions; + procedure InitGlobalDimensionsAndStyle(ACustomButtonsTextLength: Integer; out aWidth, aFontHeight: Integer); + function GetGlobalLeftMargin: Integer; + procedure AddIcon(out ALeft,ATop: Integer; AGlobalLeftMargin: Integer; AParent: TWinControl); procedure AddPanel; - procedure AddRadios(ARadioOffSet, AWidth, ARadioDef, AFontHeight: Integer; var X,Y: Integer; AParent: TWinControl); - procedure AddCommandLinkButtons(var X, Y: Integer; AWidth, AButtonDef, AFontHeight: Integer; AParent: TWinControl); - procedure AddButtons(var X,Y, XB: Integer; AWidth, AButtonDef: Integer; APArent: TWinControl); - procedure AddCheckBox(var X,Y, XB: Integer; AWidth, ALeftMargin: Integer; APArent: TWinControl); - procedure AddExpandButton(var X,Y, XB: Integer; AWidth, ALeftMargin: Integer; APArent: TWinControl); - procedure AddFooter(var X, Y, XB: Integer; AFontHeight, AWidth, AIconBorder: Integer; APArent: TWinControl); - function AddLabel(const AText: string; BigFont: boolean; var X, Y: Integer; AFontHeight, AWidth: Integer; APArent: TWinControl): TLabel; - procedure AddQueryCombo(var X,Y: Integer; AWidth: Integer; AParent: TWinControl); + procedure AddRadios(const ARadioOffSet, AWidth, ARadioDef, AFontHeight, ALeft: Integer; var ATop: Integer; AParent: TWinControl); + procedure AddCommandLinkButtons(const ALeft: Integer; var ATop: Integer; AWidth, AButtonDef, AFontHeight: Integer; AParent: TWinControl); + procedure AddButtons(const ALeft: Integer; var ATop, AButtonLeft: Integer; AWidth, AButtonDef: Integer; APArent: TWinControl); + procedure AddCheckBox(const ALeft: Integer; var ATop, XB: Integer; AWidth: Integer; APArent: TWinControl); + procedure AddExpandButton(const ALeft: Integer; var ATop, XB: Integer; AWidth: Integer; APArent: TWinControl); + procedure AddFooter(const ALeft: Integer; var ATop, XB: Integer; AFontHeight, AWidth, AGlobalLeftMargin: Integer; APArent: TWinControl); + function AddLabel(const AText: string; BigFont: Boolean; const ALeft: Integer; var ATop: Integer; AFontHeight, AWidth: Integer; APArent: TWinControl): TLabel; + procedure AddQueryCombo(const ALeft: Integer; var ATop: Integer; AWidth: Integer; AParent: TWinControl); procedure AddQueryEdit(var X,Y: Integer; AWidth: Integer; AParent: TWinControl); procedure SetupTimer; procedure ResetTimer; @@ -315,18 +324,88 @@ begin ARadioRes := i+TaskDialogFirstRadioButtonIndex; end; +procedure TLCLTaskDialog.GetDefaultButtons(out aButtonDef, aRadioDef: TModalResult); +begin + if FDlg.RadioButtons.DefaultButton<> nil then + aRadioDef := FDlg.RadioButtons.DefaultButton.Index + else + aRadioDef := 0; + if FDlg.Buttons.DefaultButton<>nil then + aButtonDef := FDlg.Buttons.DefaultButton.ModalResult + else + aButtonDef := TD_BTNMOD[FDlg.DefaultButton]; +end; +procedure TLCLTaskDialog.InitCaptions; +begin + DialogCaption := FDlg.Caption; + DlgTitle := FDlg.Title; + DlgText := FDlg.Text; + ExpandButtonCaption := FDlg.ExpandButtonCaption; + CollapsButtonCaption := FDlg.CollapsButtonCaption; + ExpandedText := FDlg.ExpandedText; + FooterText := FDlg.FooterText; + VerificationText := FDlg.VerificationText; + if (DialogCaption = '') then + if (Application.MainForm = nil) then + DialogCaption := Application.Title + else + DialogCaption := Application.MainForm.Caption; + if (DlgTitle = '') then + DlgTitle := IconMessage(TF_DIALOGICON(FDlg.MainIcon)); +end; -procedure TLCLTaskDialog.AddIcon(out IconBorder,X,Y: Integer; AParent: TWinControl); +procedure TLCLTaskDialog.InitGlobalDimensionsAndStyle(ACustomButtonsTextLength: Integer; out aWidth, aFontHeight: Integer); +begin + PixelsPerInch := 96; // we are using 96 PPI in the code, scale it automatically at ShowModal + Font.PixelsPerInch := 96; + BorderStyle := bsDialog; + if (tfAllowDialogCancellation in FDlg.Flags) then + BorderIcons := [biSystemMenu] + else + BorderIcons := []; + if (tfPositionRelativeToWindow in FDlg.Flags) then + Position := poOwnerFormCenter + else + Position := poScreenCenter; + + if not (tfEmulateClassicStyle in FDlg.Flags) then + Font := DefaultFont; + + aFontHeight := Font.Height; + if (aFontHeight = 0) then + aFontHeight := Screen.SystemFont.Height; + + aWidth := FDlg.Width; + if (aWidth <= 0) then + begin + aWidth := Canvas.TextWidth(DlgTitle); + if (aWidth > 300) or (Canvas.TextWidth(DlgText) > 300) or + (ACustomButtonsTextLength > 40) then + aWidth := 480 else + aWidth := 420; + end + else + if (aWidth < 120) then aWidth := 120; + ClientWidth := aWidth; + + Height := 200; + //debugln(['Font: Name=',Font.Name,', Size=',Font.Size,', Height=',Font.Height]); +end; + +function TLCLTaskDialog.GetGlobalLeftMargin: Integer; +begin + if (tfEmulateClassicStyle in FDlg.Flags) then + Result := 10 + else + Result := 16; +end; + +procedure TLCLTaskDialog.AddIcon(out ALeft,ATop: Integer; AGlobalLeftMargin: Integer; AParent: TWinControl); var aDialogIcon: TLCLTaskDialogIcon; begin - if (tfEmulateClassicStyle in FDlg.Flags) then - IconBorder := 10 - else - IconBorder := 24; - aDialogIcon := TF_DIALOGICON(FDlg.MainIcon); if (LCL_IMAGES[aDialogIcon]<>0) then begin @@ -334,23 +413,21 @@ begin Image.Parent := AParent; Image.Images := DialogGlyphs; Image.ImageIndex := DialogGlyphs.DialogIcon[LCL_IMAGES[aDialogIcon]]; - Image.SetBounds(IconBorder,IconBorder, 32, 32); + Image.SetBounds(AGlobalLeftMargin, AGlobalLeftMargin, LargeImageSize, LargeImageSize); Image.Stretch := True; Image.StretchOutEnabled := False; Image.Proportional := True; Image.Center := True; - X := Image.Width+IconBorder*2; - Y := Image.Top; + ALeft := Image.Width+AGlobalLeftMargin*2; + ATop := Image.Top; if (tfEmulateClassicStyle in FDlg.Flags) then - inc(Y, 8); + inc(ATop, 8); end else begin Image := nil; - if (not (tfEmulateClassicStyle in FDlg.Flags)) and (DlgTitle <> '') then - IconBorder := IconBorder*2; - X := IconBorder; - Y := IconBorder; + ALeft := AGlobalLeftMargin; + ATop := AGlobalLeftMargin; end; end; @@ -365,7 +442,7 @@ begin Panel.Color := clWindow; end; -procedure TLCLTaskDialog.AddRadios(ARadioOffSet, AWidth, ARadioDef, AFontHeight: Integer; var X,Y: Integer; AParent: TWinControl); +procedure TLCLTaskDialog.AddRadios(const ARadioOffSet, AWidth, ARadioDef, AFontHeight, ALeft: Integer; var ATop: Integer; AParent: TWinControl); var i: Integer; aHint: String; @@ -379,24 +456,24 @@ begin Parent := AParent; Tag := FDlg.RadioButtons[i].Index + TaskDialogFirstRadioButtonIndex; AutoSize := False; - SetBounds(X+16,Y,aWidth-32-X, (6-AFontHeight) + ARadioOffset); - Caption := FDlg.RadioButtons[i].Caption; //LCL RadioButton doesn't support multiline captions - inc(Y,Height + ARadioOffset); + SetBounds(ALeft+RadioIndent,ATop,aWidth-(2*RadioIndent)-ALeft, (6-AFontHeight) + ARadioOffset); + Caption := FDlg.RadioButtons[i].Caption; + inc(ATop,Height + ARadioOffset); if not (tfNoDefaultRadioButton in FDlg.Flags) and ((i=0) or (i=aRadioDef)) then Checked := True; OnClick := @OnRadioButtonClick; end; end; - inc(Y,24); + inc(ATop,24); end; -procedure TLCLTaskDialog.AddCommandLinkButtons(var X, Y: Integer; AWidth, AButtonDef, AFontHeight: Integer; AParent: TWinControl); +procedure TLCLTaskDialog.AddCommandLinkButtons(const ALeft: Integer; var ATop: Integer; AWidth, AButtonDef, AFontHeight: Integer; AParent: TWinControl); var i: Integer; CommandLink: TBitBtn; aHint: String; begin - inc(Y,8); + inc(ATop,8); for i := 0 to FDlg.Buttons.Count-1 do begin CommandLink := TBitBtn.Create(Self); @@ -405,15 +482,15 @@ begin Parent := AParent; Font.Height := AFontHeight-3; if (tfEmulateClassicStyle in FDlg.Flags) then - FCommandLinkButtonWidth := aWidth-10-X + FCommandLinkButtonWidth := aWidth-10-ALeft else - FCommandLinkButtonWidth := aWidth-16-X; - SetBounds(X,Y,FCommandLinkButtonWidth,40); + FCommandLinkButtonWidth := aWidth-16-ALeft; + SetBounds(ALeft,ATop,FCommandLinkButtonWidth,40); Caption := FDlg.Buttons[i].Caption; Hint := FDlg.Buttons[i].CommandLinkHint; if (Hint <> '') then ShowHint := True; - inc(Y,Height+2); + inc(ATop,Height+2); ModalResult := i+TaskDialogFirstButtonIndex; OnClick := @OnButtonClicked; if ModalResult=aButtonDef then @@ -440,10 +517,10 @@ begin end; end; end; - inc(Y,24); + inc(ATop,24); end; -procedure TLCLTaskDialog.AddButtons(var X, Y, XB: Integer; AWidth, AButtonDef: Integer; APArent: TWinControl); +procedure TLCLTaskDialog.AddButtons(const ALeft: Integer; var ATop, AButtonLeft: Integer; AWidth, AButtonDef: Integer; APArent: TWinControl); var CurrTabOrder, i: Integer; Btn: TTaskDialogCommonButton; @@ -453,18 +530,18 @@ var WB: integer; begin WB := Canvas.TextWidth(s)+52; - dec(XB,WB); - if XBnil) and (Ynil) and (ATop0 then AddBevel else - inc(Y,16); + inc(ATop,16); if (LCL_FOOTERIMAGES[TF_FOOTERICON(FDlg.FooterIcon)]<>0) then begin Image := TImage.Create(Self); @@ -607,22 +681,22 @@ begin Image.StretchOutEnabled := False; Image.Proportional := True; Image.Center := True; - Image.SetBounds(AIconBorder,Y,16,16); - X := 40+Image.Width; + Image.SetBounds(AGlobalLeftMargin,ATop,SmallImageSize,SmallImageSize); + ALabelLeft := AGlobalLeftMargin + Aleft + Image.Width; end else begin - X := 24; + ALabelLeft := ALeft;//24; end; - Element[tdeFooter] := AddLabel(FooterText, False, X, Y, AFontHeight, AWidth, AParent); + Element[tdeFooter] := AddLabel(FooterText, False, ALabelLeft, ATop, AFontHeight, AWidth, AParent); end; -function TLCLTaskDialog.AddLabel(const AText: string; BigFont: boolean; var X, Y: Integer; AFontHeight, AWidth: Integer; APArent: TWinControl): TLabel; +function TLCLTaskDialog.AddLabel(const AText: string; BigFont: Boolean; const ALeft: Integer; var ATop: Integer; AFontHeight, AWidth: Integer; APArent: TWinControl): TLabel; var R: TRect; W: integer; begin - //debugln(['TLCLTaskDialog.AddLabel A: AText=',AText,',X=',X,', AParent=',DbgSName(AParent),', AParent.Width=',AParent.Width,', Self.Width=',Self.Width]); + //debugln(['TLCLTaskDialog.AddLabel A: AText=',AText,',X=',ALeft,', AParent=',DbgSName(AParent),', AParent.Width=',AParent.Width,', Self.Width=',Self.Width]); if (AText = '') then Exit(nil); Result := TLabel.Create(Self); @@ -645,29 +719,27 @@ begin Result.AutoSize := False; R.Left := 0; R.Top := 0; - W := aWidth-X-8; + W := aWidth-ALeft-8; R.Right := W; R.Bottom := Result.Height; Result.Caption := AText; Result.Parent := AParent; LCLIntf.DrawText(Result.Canvas.Handle,PChar(AText),Length(AText),R,DT_CALCRECT or DT_WORDBREAK); - //debugln(['TLCLTaskDialog.AddLabel before Result.SetBounds(',X,',',Y,',',W,',',R.Bottom,')']); - Result.SetBounds(X,Y,W,R.Bottom); - //debugln(['TLCLTaskDialog.AddLabel after Result.SetBounds(',X,',',Y,',',W,',',R.Bottom,'), Result.BoundsRect=',DbgS(Result.BoundsRect)]); - inc(Y,R.Bottom+16); - //debugln(['TLCLTaskDialog.AddLabel End: X=',X,', Result.Left=',Result.Left]); + Result.SetBounds(ALeft,ATop,W,R.Bottom); + inc(ATop,R.Bottom+16); + //debugln(['TLCLTaskDialog.AddLabel End: X=',ALeft,', Result.Left=',Result.Left]); end; -procedure TLCLTaskDialog.AddQueryCombo(var X, Y: Integer; AWidth: Integer; AParent: TWinControl); +procedure TLCLTaskDialog.AddQueryCombo(const ALeft: Integer; var ATop: Integer; AWidth: Integer; AParent: TWinControl); begin QueryCombo := TComboBox.Create(Self); with QueryCombo do begin Items.Assign(FDlg.QueryChoices); if (FCommandLinkButtonWidth > 0) then - SetBounds(X,Y,FCommandLinkButtonWidth,22) //right align with the buttons + SetBounds(ALeft,ATop,FCommandLinkButtonWidth,ComboBoxHeight) //right align with the buttons else - SetBounds(X,Y,aWidth-32-X,22); + SetBounds(ALeft,ATop,aWidth-32-ALeft,ComboBoxHeight); if (tfQueryFixedChoices in FDlg.Flags) then Style := csDropDownList else @@ -683,7 +755,7 @@ begin end; Parent := AParent; end; - inc(Y,42); + inc(ATop,42); end; procedure TLCLTaskDialog.AddQueryEdit(var X, Y: Integer; AWidth: Integer; AParent: TWinControl); @@ -833,7 +905,7 @@ var aRadioDef, aButtonDef: TModalResult; B: TTaskDialogBaseButtonItem; ButtonID: Integer; - ARadioOffset, FontHeight, aWidth, IconBorder, X, Y, i, XB: integer; + ARadioOffset, FontHeight, aWidth, GlobalLeftMargin, ALeft, ATop, i, XB: integer; CurrParent: TWinControl; aDialogIcon: TLCLTaskDialogIcon; CommandLink: TBitBtn; @@ -844,32 +916,16 @@ var begin DisableAutoSizing; try - if FDlg.RadioButtons.DefaultButton<> nil then - aRadioDef := FDlg.RadioButtons.DefaultButton.Index - else - aRadioDef := 0; - if FDlg.Buttons.DefaultButton<>nil then - aButtonDef := FDlg.Buttons.DefaultButton.ModalResult - else - aButtonDef := TD_BTNMOD[FDlg.DefaultButton]; + GetDefaultButtons(aButtonDef, aRadioDef); CustomButtonsTextLength := 0; for B in FDlg.Buttons do CustomButtonsTextLength := CustomButtonsTextLength + Length(B.Caption); - - DialogCaption := FDlg.Caption; - DlgTitle := FDlg.Title; - DlgText := FDlg.Text; - ExpandButtonCaption := FDlg.ExpandButtonCaption; - CollapsButtonCaption := FDlg.CollapsButtonCaption; - ExpandedText := FDlg.ExpandedText; - FooterText := FDlg.FooterText; - VerificationText := FDlg.VerificationText; + InitCaptions; FVerifyChecked := (tfVerificationFlagChecked in FDlg.Flags); CommonButtons := FDlg.CommonButtons; - if (CommonButtons=[]) and (FDlg.Buttons.Count=0) then begin CommonButtons := [tcbOk]; @@ -877,48 +933,8 @@ begin aButtonDef := mrOk; end; - if (DialogCaption = '') then - if (Application.MainForm = nil) then - DialogCaption := Application.Title - else - DialogCaption := Application.MainForm.Caption; + InitGlobalDimensionsAndStyle(CustomButtonsTextLength, aWidth, FontHeight); - if (DlgTitle = '') then - DlgTitle := IconMessage(TF_DIALOGICON(FDlg.MainIcon)); - - PixelsPerInch := 96; // we are using 96 PPI in the code, scale it automatically at ShowModal - Font.PixelsPerInch := 96; - BorderStyle := bsDialog; - if (tfAllowDialogCancellation in FDlg.Flags) then - BorderIcons := [biSystemMenu] - else - BorderIcons := []; - if (tfPositionRelativeToWindow in FDlg.Flags) then - Position := poOwnerFormCenter - else - Position := poScreenCenter; - - if not (tfEmulateClassicStyle in FDlg.Flags) then - Font := DefaultFont; - - FontHeight := Font.Height; - if (FontHeight = 0) then - FontHeight := Screen.SystemFont.Height; - - aWidth := FDlg.Width; - if (aWidth <= 0) then - begin - aWidth := Canvas.TextWidth(DlgTitle); - if (aWidth > 300) or (Canvas.TextWidth(DlgText) > 300) or - (CustomButtonsTextLength > 40) then - aWidth := 480 else - aWidth := 420; - end - else - if (aWidth < 120) then aWidth := 120; - ClientWidth := aWidth; - - Height := TaskDialogFirstRadioButtonIndex; Caption := DialogCaption; // create a white panel for the main dialog part @@ -926,64 +942,70 @@ begin CurrParent := Panel; // handle main dialog icon - AddIcon(IconBorder, X, Y, CurrParent); + GlobalLeftMargin := GetGlobalLeftMargin; + AddIcon(ALeft, ATop, GlobalLeftMargin, CurrParent); + //debugln('SetupControls'); + //debugln([' GlobalLeftMargin=',GlobalLeftMargin]); + //debugln([' ALeft=',ALeft]); + //debugln([' ATop=',ATop]); // add main texts (DlgTitle, DlgText, Information) - Element[tdeMainInstruction] := AddLabel(DlgTitle, True, X, Y, FontHeight, aWidth, CurrParent); - Element[tdeContent] := AddLabel(DlgText, False, X, Y, FontHeight, aWidth, CurrParent); + Element[tdeMainInstruction] := AddLabel(DlgTitle, True, ALeft, ATop, FontHeight, aWidth, CurrParent); + Element[tdeContent] := AddLabel(DlgText, False, ALeft, ATop, FontHeight, aWidth, CurrParent); if (ExpandedText <> '') then // no information collapse/expand yet: it's always expanded - Element[tdeExpandedInfo] := AddLabel(ExpandedText, False, X, Y, FontHeight, aWidth, CurrParent); + Element[tdeExpandedInfo] := AddLabel(ExpandedText, False, ALeft, ATop, FontHeight, aWidth, CurrParent); // add radio CustomButtons if (FDlg.RadioButtons.Count > 0) then begin ARadioOffset := 1; - AddRadios(ARadioOffSet, aWidth, aRadioDef, FontHeight, X, Y, CurrParent); + AddRadios(ARadioOffSet, aWidth, aRadioDef, FontHeight, ALeft, ATop, CurrParent); end; // add command links CustomButtons if (tfUseCommandLinks in FDlg.Flags) and (FDlg.Buttons.Count<>0) then - AddCommandLinkButtons(X, Y, aWidth, aButtonDef, FontHeight, CurrParent); + AddCommandLinkButtons(ALeft, ATop, aWidth, aButtonDef, FontHeight, CurrParent); // add query combobox list or QueryEdit if (tfQuery in FDlg.Flags) and (FDlg.QueryChoices.Count > 0) then - AddQueryCombo(X, Y, aWidth, CurrParent) + AddQueryCombo(ALeft, ATop, aWidth, CurrParent) else begin if (tfSimpleQuery in FDlg.Flags) and (FDlg.SimpleQuery <> '') then - AddQueryEdit(X, Y, aWidth, CurrParent); + AddQueryEdit(ALeft, ATop, aWidth, CurrParent); end; // from now we won't add components to the white panel, but to the form - Panel.Height := Y; + Panel.Height := ATop; CurrParent := Self; XB := 0; + ALeft := GlobalLeftMargin; //Left most margin of the form // add CustomButtons and verification checkbox if (CommonButtons <> []) or ((FDlg.Buttons.Count<>0) and not (tfUseCommandLinks in FDlg.Flags)) then begin - AddButtons(X, Y, XB, aWidth, aButtonDef, CurrParent); + AddButtons(ALeft, ATop, XB, aWidth, aButtonDef, CurrParent); end; //Add Expand button if (ExpandedText <> '') then - AddExpandButton(X, Y, XB, aWidth, IconBorder, CurrParent); + AddExpandButton(ALeft, ATop, XB, aWidth, CurrParent); if (VerificationText <> '') then - AddCheckBox(X, Y, XB, aWidth, IconBorder, CurrParent); - inc(Y,36); + AddCheckBox(ALeft, ATop, XB, aWidth, CurrParent); + inc(ATop,36); // add FooterText text with optional icon if (FooterText <> '') then - AddFooter(X, Y, XB, FontHeight, aWidth, IconBorder, CurrParent); + AddFooter(ALeft, ATop, XB, FontHeight, aWidth, GlobalLeftMargin, CurrParent); - ClientHeight := Y; + ClientHeight := ATop; if (tfCallBackTimer in FDlg.Flags) then SetupTimer;