/components/printers/unix/framepagesetup.pas

http://github.com/graemeg/lazarus · Pascal · 320 lines · 262 code · 41 blank · 17 comment · 22 complexity · 2729cb1c7fa75c1361ca1c3b8ae3ade3 MD5 · raw file

  1. unit framePageSetup;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, Graphics, FileUtil, LResources, Forms, ExtCtrls, StdCtrls,
  6. Printers, OsPrinters, LCLIntf, LCLProc, Controls, CupsLCL;
  7. type
  8. TPageSetupMode = (psmFull, psmPapers, psmMargins);
  9. TPageSetupOption = (
  10. psoMargins, // margins and preview are visible
  11. psoPapers, // papers group visible
  12. psoOrientation // orientation group visible
  13. );
  14. TPageSetupOptions = set of TPageSetupOption;
  15. { TframePageSetup }
  16. TframePageSetup = class(TFrame)
  17. cbPaper: TComboBox;
  18. cbSource: TComboBox;
  19. panMargins: TPanel;
  20. txtLeft: TEdit;
  21. txtRight: TEdit;
  22. txtTop: TEdit;
  23. txtBottom: TEdit;
  24. gpPaper: TGroupBox;
  25. gpOrientation: TGroupBox;
  26. gpMargins: TGroupBox;
  27. lblSource: TLabel;
  28. lblPaper: TLabel;
  29. lblLeft: TLabel;
  30. lblRight: TLabel;
  31. lblTop: TLabel;
  32. lblBottom: TLabel;
  33. pbPreview: TPaintBox;
  34. panSetup: TPanel;
  35. panPreview: TPanel;
  36. radLandscape: TRadioButton;
  37. radPortrait: TRadioButton;
  38. procedure cbPaperChange(Sender: TObject);
  39. procedure panPreviewResize(Sender: TObject);
  40. procedure pbPreviewMouseDown(Sender: TObject; Button: TMouseButton;
  41. {%H-}Shift: TShiftState; {%H-}X, {%H-}Y: Integer);
  42. procedure pbPreviewMouseWheelDown(Sender: TObject; {%H-}Shift: TShiftState;
  43. {%H-}MousePos: TPoint; var Handled: Boolean);
  44. procedure pbPreviewMouseWheelUp(Sender: TObject; {%H-}Shift: TShiftState;
  45. {%H-}MousePos: TPoint; var Handled: Boolean);
  46. procedure pbPreviewPaint(Sender: TObject);
  47. procedure radPortraitClick(Sender: TObject);
  48. private
  49. { private declarations }
  50. FHeightTallest: Integer;
  51. FHardMargins: TRect;
  52. FKw,FKh,FZoom: Double;
  53. FOptions: TPageSetupOptions;
  54. public
  55. { public declarations }
  56. procedure Initialize(AMode: TPageSetupMode);
  57. procedure UpdatePageSize;
  58. end;
  59. implementation
  60. {$R framepagesetup.lfm}
  61. { TframePageSetup }
  62. procedure TframePageSetup.pbPreviewPaint(Sender: TObject);
  63. var
  64. R: TRect;
  65. procedure DrawMargin(AIndex: Integer; ASize: Integer);
  66. begin
  67. with pbPreview do
  68. case AIndex of
  69. 0: // Left
  70. begin
  71. Canvas.MoveTo(ASize, 1);
  72. Canvas.LineTo(ASize, Height-1);
  73. end;
  74. 1: //Top
  75. begin
  76. Canvas.MoveTo(1,ASize);
  77. Canvas.LineTo(Width-1, ASize);
  78. end;
  79. 2: // Right
  80. begin
  81. Canvas.MoveTo(Width-1-ASize, 1);
  82. Canvas.LineTo(Width-1-ASize,Height-1);
  83. end;
  84. 3: // Bottom
  85. begin
  86. Canvas.MoveTo(1,Height-1-Asize);
  87. Canvas.LineTo(Width-1, Height-1-ASize);
  88. end;
  89. end;
  90. end;
  91. begin
  92. if Sender=nil then ;
  93. if not (psoMargins in FOptions) then
  94. exit;
  95. with pbPreview do
  96. begin
  97. // page frame
  98. R := Rect(0,0,Width,Height);
  99. Canvas.Pen.Color := clBlack;
  100. Canvas.Brush.Color:=clWhite;
  101. Canvas.Rectangle(R);
  102. // hard margins
  103. Canvas.Pen.Color := RGBToColor(255,204,204);
  104. DrawMargin(0, FHardMargins.Left );
  105. DrawMargin(1, FHardMargins.Top );
  106. DrawMargin(2, FHardMargins.Right );
  107. DrawMargin(3, FHardMargins.Bottom);
  108. end;
  109. end;
  110. procedure TframePageSetup.radPortraitClick(Sender: TObject);
  111. begin
  112. if sender=nil then ;
  113. if radPortrait.Checked then
  114. Printer.Orientation := poPortrait
  115. else
  116. Printer.Orientation := poLandsCape;
  117. UpdatePageSize;
  118. end;
  119. procedure TframePageSetup.cbPaperChange(Sender: TObject);
  120. begin
  121. if Printer.PaperSize.DefaultPapers then
  122. begin
  123. if cbPaper.ItemIndex>=0 then
  124. Printer.PaperSize.PaperName := cbPaper.Items[cbPaper.ItemIndex];
  125. end else
  126. Printer.PaperSize.PaperName := GetCupsComboKeyValue(cbPaper);
  127. UpdatePageSize;
  128. end;
  129. procedure TframePageSetup.panPreviewResize(Sender: TObject);
  130. var
  131. TallH: Integer;
  132. begin
  133. if not (psoMargins in FOptions) then
  134. exit;
  135. TallH := Round(FheightTallest * FKh);
  136. with PanPreview do
  137. if (Height<>C_BOTHSPACES) and (TallH>(Height-C_BOTHSPACES)) then
  138. FZoom := (Height-C_BOTHSPACES)/TallH
  139. else
  140. FZoom := 1.0;
  141. end;
  142. procedure TframePageSetup.pbPreviewMouseDown(Sender: TObject;
  143. Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
  144. begin
  145. if Button=mbMiddle then
  146. begin
  147. FZoom := 1;
  148. UpdatePageSize;
  149. end;
  150. end;
  151. procedure TframePageSetup.pbPreviewMouseWheelDown(Sender: TObject;
  152. Shift: TShiftState; MousePos: TPoint; var Handled: Boolean);
  153. begin
  154. FZoom := FZoom - 0.2;
  155. if FZoom<0.5 then
  156. FZoom := 0.5;
  157. UpdatePageSize;
  158. Handled := true;
  159. end;
  160. procedure TframePageSetup.pbPreviewMouseWheelUp(Sender: TObject;
  161. Shift: TShiftState; MousePos: TPoint; var Handled: Boolean);
  162. begin
  163. FZoom := FZoom + 0.2;
  164. UpdatePageSize;
  165. Handled := true;
  166. end;
  167. procedure TframePageSetup.UpdatePageSize;
  168. begin
  169. if not (psoMargins in FOptions) then
  170. exit;
  171. with Printer.PaperSize.PaperRect.PhysicalRect do
  172. begin
  173. PbPreview.Width := Round(Fkw * (Right - Left) * FZoom) + 2;
  174. PbPreview.Height := Round(FKh * (Bottom - Top) * FZoom) + 2;
  175. end;
  176. with Printer.PaperSize.PaperRect do
  177. begin
  178. FHardMargins.Left := Round(Fkw * (WorkRect.Left-PhysicalRect.Left) * FZoom);
  179. FHardMargins.Right := Round(Fkw * (Physicalrect.Right-WorkRect.Right) * FZoom);
  180. FHardMargins.Top := Round(FkH * (WorkRect.Top-PhysicalRect.Top) * FZoom);
  181. FHardMargins.Bottom := Round(FkH * (PhysicalRect.Bottom-WorkRect.Bottom) * FZoom);
  182. end;
  183. {$IFDEF DebugCUPS}
  184. with FHardMargins do
  185. begin
  186. DebugLn(' Kh=%.2f Kw=%.2f',[FKh,FKw]);
  187. DebugLn(' BoxLimits L=0 T=0 R=%d B=%d',[PbPreview.Width-1,PbPreview.Height-1]);
  188. DebugLn('OrgMargins L=%d T=%d R=%d B=%d',[Left,Top,Right,Bottom]);
  189. end;
  190. {$ENDIF}
  191. end;
  192. procedure TframePageSetup.Initialize(AMode: TPageSetupMode);
  193. var
  194. i,j:Integer;
  195. R: TPaperRect;
  196. begin
  197. case AMode of
  198. psmMargins:
  199. FOptions := [psoMargins];
  200. psmPapers:
  201. FOptions := [psoPapers,psoOrientation];
  202. else
  203. FOptions := [psoMargins,psoPapers,psoOrientation];
  204. end;
  205. if [psoMargins,psoPapers]*FOptions<>[] then
  206. begin
  207. SetupCupsCombo(cbPaper, nil, 'PageSize');
  208. if (cbPaper.Items.Count=0) then
  209. begin
  210. // no cups printer papers, use default ones
  211. cbPaper.Items := Printer.PaperSize.SupportedPapers;
  212. cbPaper.ItemIndex:= cbPaper.Items.IndexOf(Printer.PaperSize.PaperName);
  213. cbPaper.Enabled:=true;
  214. end;
  215. end;
  216. if psoPapers in FOptions then
  217. SetupCupsCOmbo(cbSource, nil, 'InputSlot')
  218. else
  219. gpPaper.Visible := false;
  220. //TODO: support reverse variants too?
  221. gpOrientation.Visible := (psoOrientation in FOptions);
  222. case Printer.Orientation of
  223. poPortrait,poReversePortrait:
  224. radPortrait.Checked := true;
  225. poLandscape,poReverseLandscape:
  226. radLandscape.Checked := true;
  227. end;
  228. if psoMargins in FOptions then
  229. begin
  230. // assume 100 pix = 8.5 inch (IOW, letter size width = 100 pixels)
  231. with ScreenInfo do
  232. begin
  233. FKw := (100/8.5)/Printer.XDPI;
  234. FKh := (100/8.5)*(PixelsPerInchY/PixelsPerInchX)/Printer.YDPI;
  235. end;
  236. // find the tallest paper
  237. FHeightTallest := 0;
  238. j := -1;
  239. if cbPaper.Enabled then
  240. for i:=0 to cbPaper.Items.Count-1 do
  241. begin
  242. if Printer.PaperSize.DefaultPapers then
  243. R := Printer.PaperSize.PaperRectOf[cbPaper.Items[i]]
  244. else
  245. R := Printer.PaperSize.PaperRectOf[GetCupsComboKeyValue(cbPaper, i)];
  246. with R.PhysicalRect do
  247. if FHeightTallest<(Bottom-Top) then
  248. begin
  249. FHeightTallest := (Bottom-Top);
  250. j := i;
  251. end;
  252. end;
  253. if j>=0 then
  254. begin
  255. {$IFDEF DebugCUPS}
  256. DebugLn(' Tallest Paper is: %s Height=%d %.2f Inch',
  257. [cbPaper.Items[j],FHeightTallest,FHeightTallest/Printer.YDPI]);
  258. {$ENDIF}
  259. end;
  260. // zoom factor
  261. FZoom := 1.0;
  262. UpdatePageSize;
  263. end else
  264. begin
  265. panPreview.Visible:=false;
  266. gpMargins.Visible:=false;
  267. end;
  268. if AMode=psmPapers then
  269. begin
  270. gpOrientation.Anchors:=[akTop,akRight,akBottom];
  271. gpOrientation.Align:=alRight;
  272. gpPaper.Anchors:=[akTop,akLeft];
  273. gpPaper.Align:=alClient;
  274. PanSetup.Align:=alClient;
  275. end else
  276. if AMode=psmMargins then
  277. PanSetup.Height:=gpMargins.Height+C_BOTHSPACES;
  278. end;
  279. end.