mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-07-19 00:46:26 +02:00
384 lines
9.8 KiB
ObjectPascal
384 lines
9.8 KiB
ObjectPascal
{
|
|
*****************************************************************************
|
|
This file is part of the Printer4Lazarus package
|
|
|
|
See the file COPYING.modifiedLGPL.txt, included in this distribution,
|
|
for details about the license.
|
|
*****************************************************************************
|
|
}
|
|
unit framePageSetup;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils,
|
|
// LCL
|
|
LCLIntf, LCLProc, LResources, Controls, Graphics, Forms, ExtCtrls, StdCtrls,
|
|
Spin, Printers,
|
|
// Printers
|
|
OsPrinters, CupsLCL;
|
|
|
|
type
|
|
{ TframePageSetup }
|
|
|
|
TframePageSetup = class(TFrame)
|
|
cbPaper: TComboBox;
|
|
cbSource: TComboBox;
|
|
panMargins: TPanel;
|
|
boxShadow: TShape;
|
|
txtLeft: TFloatSpinEdit;
|
|
txtTop: TFloatSpinEdit;
|
|
txtRight: TFloatSpinEdit;
|
|
txtBottom: TFloatSpinEdit;
|
|
gpPaper: TGroupBox;
|
|
gpOrientation: TGroupBox;
|
|
gpMargins: TGroupBox;
|
|
lblSource: TLabel;
|
|
lblPaper: TLabel;
|
|
lblLeft: TLabel;
|
|
lblRight: TLabel;
|
|
lblTop: TLabel;
|
|
lblBottom: TLabel;
|
|
pbPreview: TPaintBox;
|
|
panSetup: TPanel;
|
|
panPreview: TPanel;
|
|
radLandscape: TRadioButton;
|
|
radPortrait: TRadioButton;
|
|
procedure cbPaperChange(Sender: TObject);
|
|
procedure panPreviewResize(Sender: TObject);
|
|
procedure pbPreviewMouseDown(Sender: TObject; Button: TMouseButton;
|
|
{%H-}Shift: TShiftState; {%H-}X, {%H-}Y: Integer);
|
|
procedure pbPreviewMouseWheelDown(Sender: TObject; {%H-}Shift: TShiftState;
|
|
{%H-}MousePos: TPoint; var Handled: Boolean);
|
|
procedure pbPreviewMouseWheelUp(Sender: TObject; {%H-}Shift: TShiftState;
|
|
{%H-}MousePos: TPoint; var Handled: Boolean);
|
|
procedure pbPreviewPaint(Sender: TObject);
|
|
procedure radPortraitClick(Sender: TObject);
|
|
procedure txtLeftChange(Sender: TObject);
|
|
private
|
|
FHeightTallest: Integer;
|
|
FFactorX, FFactorY, FZoom: Double;
|
|
function NToInches: double;
|
|
procedure RotateMargins(AOrder: boolean);
|
|
public
|
|
UnitInches: boolean;
|
|
EnablePreview: boolean;
|
|
EnableMargins: boolean;
|
|
EnablePapers: boolean;
|
|
EnableOrientation: boolean;
|
|
CurPageWidth: double;
|
|
CurPageHeight: double;
|
|
procedure Initialize(AEnablePreview, AEnableMargins, AEnablePapers,
|
|
AEnableOrientation: boolean);
|
|
procedure UpdatePageSize;
|
|
procedure UpdateMaxValues;
|
|
procedure SetDefaultMinMargins;
|
|
end;
|
|
|
|
implementation
|
|
|
|
{$R framepagesetup.lfm}
|
|
|
|
{ TframePageSetup }
|
|
|
|
function TframePageSetup.NToInches: double;
|
|
begin
|
|
if UnitInches then
|
|
Result:= 1
|
|
else
|
|
Result:= 1/25.4;
|
|
end;
|
|
|
|
procedure TframePageSetup.RotateMargins(AOrder: boolean);
|
|
var
|
|
m_l, m_t, m_r, m_b: double;
|
|
begin
|
|
m_l:= txtLeft.Value;
|
|
m_t:= txtTop.Value;
|
|
m_r:= txtRight.Value;
|
|
m_b:= txtBottom.Value;
|
|
|
|
if AOrder then
|
|
begin
|
|
txtLeft.Value:= m_b;
|
|
txtTop.Value:= m_l;
|
|
txtRight.Value:= m_t;
|
|
txtBottom.Value:= m_r;
|
|
end
|
|
else
|
|
begin
|
|
txtLeft.Value:= m_t;
|
|
txtTop.Value:= m_r;
|
|
txtRight.Value:= m_b;
|
|
txtBottom.Value:= m_l;
|
|
end;
|
|
|
|
// same way must change MinValues
|
|
m_l:= txtLeft.MinValue;
|
|
m_t:= txtTop.MinValue;
|
|
m_r:= txtRight.MinValue;
|
|
m_b:= txtBottom.MinValue;
|
|
|
|
if AOrder then
|
|
begin
|
|
txtLeft.MinValue:= m_b;
|
|
txtTop.MinValue:= m_l;
|
|
txtRight.MinValue:= m_t;
|
|
txtBottom.MinValue:= m_r;
|
|
end
|
|
else
|
|
begin
|
|
txtLeft.MinValue:= m_t;
|
|
txtTop.MinValue:= m_r;
|
|
txtRight.MinValue:= m_b;
|
|
txtBottom.MinValue:= m_l;
|
|
end;
|
|
end;
|
|
|
|
procedure TframePageSetup.pbPreviewPaint(Sender: TObject);
|
|
var
|
|
R: TRect;
|
|
NLeft, NTop, NRight, NBottom: integer;
|
|
begin
|
|
if not EnablePreview then
|
|
exit;
|
|
|
|
with pbPreview do
|
|
begin
|
|
Canvas.Pen.Style := psSolid;
|
|
Canvas.Pen.Color := clBlack;
|
|
Canvas.Brush.Color := clWhite;
|
|
Canvas.Rectangle(0, 0, Width, Height);
|
|
|
|
//if EnableMargins then // EnableMargins is for SpinEdits only
|
|
begin
|
|
NLeft := Round(txtLeft.Value * NToInches * Printer.XDPI * FFactorX * FZoom);
|
|
NTop := Round(txtTop.Value * NToInches * Printer.YDPI * FFactorY * FZoom);
|
|
NRight := Round(txtRight.Value * NToInches * Printer.XDPI * FFactorX * FZoom);
|
|
NBottom := Round(txtBottom.Value * NToInches * Printer.YDPI * FFactorY * FZoom);
|
|
|
|
R.Left := NLeft;
|
|
R.Top := NTop;
|
|
R.Right := Width-1-NRight;
|
|
R.Bottom := Height-1-NBottom;
|
|
|
|
Canvas.Pen.Color := clMedGray;
|
|
//Canvas.Pen.Style := psDash; // AT: setting line style don't work, line is solid
|
|
Canvas.Rectangle(R);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
procedure TframePageSetup.radPortraitClick(Sender: TObject);
|
|
begin
|
|
RotateMargins(radPortrait.Checked);
|
|
if radPortrait.Checked then
|
|
Printer.Orientation := poPortrait
|
|
else
|
|
Printer.Orientation := poLandsCape;
|
|
UpdatePageSize;
|
|
end;
|
|
|
|
procedure TframePageSetup.txtLeftChange(Sender: TObject);
|
|
begin
|
|
pbPreview.Update;
|
|
end;
|
|
|
|
procedure TframePageSetup.cbPaperChange(Sender: TObject);
|
|
begin
|
|
if Printer.PaperSize.DefaultPapers then
|
|
begin
|
|
if cbPaper.ItemIndex>=0 then
|
|
Printer.PaperSize.PaperName := cbPaper.Items[cbPaper.ItemIndex];
|
|
end else
|
|
Printer.PaperSize.PaperName := GetCupsComboKeyValue(cbPaper);
|
|
UpdatePageSize;
|
|
end;
|
|
|
|
procedure TframePageSetup.panPreviewResize(Sender: TObject);
|
|
var
|
|
TallH: Integer;
|
|
begin
|
|
if not EnablePreview then
|
|
exit;
|
|
|
|
TallH := Round(FheightTallest * FFactorY);
|
|
|
|
with PanPreview do
|
|
if (Height<>C_BOTHSPACES) and (TallH>(Height-C_BOTHSPACES)) then
|
|
FZoom := (Height-C_BOTHSPACES)/TallH
|
|
else
|
|
FZoom := 1.0;
|
|
end;
|
|
|
|
procedure TframePageSetup.pbPreviewMouseDown(Sender: TObject;
|
|
Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
|
|
begin
|
|
if Button=mbMiddle then
|
|
begin
|
|
FZoom := 1;
|
|
UpdatePageSize;
|
|
end;
|
|
end;
|
|
|
|
procedure TframePageSetup.pbPreviewMouseWheelDown(Sender: TObject;
|
|
Shift: TShiftState; MousePos: TPoint; var Handled: Boolean);
|
|
begin
|
|
FZoom := FZoom - 0.2;
|
|
if FZoom<0.5 then
|
|
FZoom := 0.5;
|
|
UpdatePageSize;
|
|
Handled := true;
|
|
end;
|
|
|
|
procedure TframePageSetup.pbPreviewMouseWheelUp(Sender: TObject;
|
|
Shift: TShiftState; MousePos: TPoint; var Handled: Boolean);
|
|
begin
|
|
FZoom := FZoom + 0.2;
|
|
UpdatePageSize;
|
|
Handled := true;
|
|
end;
|
|
|
|
procedure TframePageSetup.UpdatePageSize;
|
|
begin
|
|
if not EnablePreview then
|
|
exit;
|
|
|
|
with Printer.PaperSize.PaperRect.PhysicalRect do
|
|
begin
|
|
PbPreview.Width := Round(FFactorX * (Right - Left) * FZoom) + 2;
|
|
PbPreview.Height := Round(FFactorY * (Bottom - Top) * FZoom) + 2;
|
|
|
|
boxShadow.Width := pbPreview.Width;
|
|
boxShadow.Height := pbPreview.Height;
|
|
end;
|
|
|
|
with Printer.PaperSize.PaperRect do
|
|
begin
|
|
CurPageWidth := (PhysicalRect.Right-PhysicalRect.Left)/Printer.XDPI/NToInches;
|
|
CurPageHeight := (PhysicalRect.Bottom-PhysicalRect.Top)/Printer.YDPI/NToInches;
|
|
end;
|
|
|
|
UpdateMaxValues;
|
|
end;
|
|
|
|
procedure TframePageSetup.UpdateMaxValues;
|
|
|
|
procedure DoSetMax(Ctl: TFloatSpinEdit; Value: double);
|
|
begin
|
|
// because of TCustomFloatSpinEdit.GetLimitedValue
|
|
// we cannot set MinValue=MaxValue, all validation will break
|
|
if Ctl.MinValue > Value-0.2 then
|
|
Ctl.MinValue := Value-0.2;
|
|
Ctl.MaxValue := Value;
|
|
end;
|
|
|
|
const
|
|
cMul = 0.45; // max margin is almost 1/2 of page size
|
|
begin
|
|
DoSetMax(txtLeft, CurPageWidth * cMul);
|
|
DoSetMax(txtRight, CurPageWidth * cMul);
|
|
DoSetMax(txtTop, CurPageHeight * cMul);
|
|
DoSetMax(txtBottom, CurPageHeight * cMul);
|
|
end;
|
|
|
|
procedure TframePageSetup.Initialize(AEnablePreview, AEnableMargins, AEnablePapers,
|
|
AEnableOrientation: boolean);
|
|
var
|
|
i,j:Integer;
|
|
R: TPaperRect;
|
|
begin
|
|
EnablePreview:= AEnablePreview;
|
|
EnableMargins:= AEnableMargins;
|
|
EnablePapers:= AEnablePapers;
|
|
EnableOrientation:= AEnableOrientation;
|
|
|
|
cbPaper.Items.Clear;
|
|
cbSource.Items.Clear;
|
|
cbPaper.ItemIndex := -1;
|
|
cbSource.ItemIndex := -1;
|
|
|
|
if EnablePapers then
|
|
begin
|
|
SetupCupsCombo(cbSource, nil, 'InputSlot');
|
|
SetupCupsCombo(cbPaper, nil, 'PageSize');
|
|
if (cbPaper.Items.Count=0) then
|
|
begin
|
|
// no cups printer papers, use default ones
|
|
cbPaper.Items := Printer.PaperSize.SupportedPapers;
|
|
cbPaper.ItemIndex:= cbPaper.Items.IndexOf(Printer.PaperSize.PaperName);
|
|
end;
|
|
end;
|
|
|
|
cbPaper.Enabled := cbPaper.Items.Count>0;
|
|
cbSource.Enabled := cbSource.Items.Count>0;
|
|
|
|
//TODO: support reverse variants too?
|
|
gpOrientation.Enabled := EnableOrientation;
|
|
case Printer.Orientation of
|
|
poPortrait,poReversePortrait:
|
|
radPortrait.Checked := true;
|
|
poLandscape,poReverseLandscape:
|
|
radLandscape.Checked := true;
|
|
end;
|
|
|
|
gpMargins.Enabled := EnableMargins;
|
|
panPreview.Visible:= EnablePreview;
|
|
|
|
if EnablePreview then
|
|
begin
|
|
// assume 100 pix = 8.5 inch (IOW, letter size width = 100 pixels)
|
|
with ScreenInfo do
|
|
begin
|
|
FFactorX := (100/8.5)/Printer.XDPI;
|
|
FFactorY := (100/8.5)*(PixelsPerInchY/PixelsPerInchX)/Printer.YDPI;
|
|
end;
|
|
|
|
// find the tallest paper
|
|
FHeightTallest := 0;
|
|
j := -1;
|
|
if cbPaper.Enabled then
|
|
for i:=0 to cbPaper.Items.Count-1 do
|
|
begin
|
|
if Printer.PaperSize.DefaultPapers then
|
|
R := Printer.PaperSize.PaperRectOf[cbPaper.Items[i]]
|
|
else
|
|
R := Printer.PaperSize.PaperRectOf[GetCupsComboKeyValue(cbPaper, i)];
|
|
with R.PhysicalRect do
|
|
if FHeightTallest<(Bottom-Top) then
|
|
begin
|
|
FHeightTallest := (Bottom-Top);
|
|
j := i;
|
|
end;
|
|
end;
|
|
|
|
if j>=0 then
|
|
begin
|
|
{$IFDEF DebugCUPS}
|
|
DebugLn(' Tallest Paper is: %s Height=%d %.2f Inch',
|
|
[cbPaper.Items[j],FHeightTallest,FHeightTallest/Printer.YDPI]);
|
|
{$ENDIF}
|
|
end;
|
|
|
|
// zoom factor
|
|
FZoom := 1.0;
|
|
UpdatePageSize;
|
|
end;
|
|
end;
|
|
|
|
procedure TframePageSetup.SetDefaultMinMargins;
|
|
begin
|
|
with Printer.PaperSize.PaperRect do
|
|
begin
|
|
txtLeft.MinValue := (WorkRect.Left-PhysicalRect.Left)/Printer.XDPI/NToInches;
|
|
txtTop.MinValue := (WorkRect.Top-PhysicalRect.Top)/Printer.YDPI/NToInches;
|
|
txtRight.MinValue := (PhysicalRect.Right-WorkRect.Right)/Printer.XDPI/NToInches;
|
|
txtBottom.MinValue := (PhysicalRect.Bottom-WorkRect.Bottom)/Printer.YDPI/NToInches;
|
|
end;
|
|
end;
|
|
|
|
end.
|
|
|