1 /*
2 * Copyright 2003-2009, Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * Philippe Houdoin
7 * Simon Gauvin
8 * Michael Pfeiffer
9 * Dr. Hartmut Reh
10 * julun <host.haiku@gmx.de>
11 */
12
13 #include "MarginView.h"
14 #include "PrinterDriver.h"
15 #include "PageSetupWindow.h"
16 #include "PrintUtils.h"
17
18 #include <stdlib.h>
19
20
21 #include <Box.h>
22 #include <Button.h>
23 #include <GridView.h>
24 #include <GroupLayout.h>
25 #include <GroupLayoutBuilder.h>
26 #include <MenuField.h>
27 #include <Message.h>
28 #include <PopUpMenu.h>
29 #include <Screen.h>
30 #include <TextControl.h>
31
32
33 /* copied from PDFlib.h: */
34 #define a0_width (float) 2380.0
35 #define a0_height (float) 3368.0
36 #define a1_width (float) 1684.0
37 #define a1_height (float) 2380.0
38 #define a2_width (float) 1190.0
39 #define a2_height (float) 1684.0
40 #define a3_width (float) 842.0
41 #define a3_height (float) 1190.0
42 #define a4_width (float) 595.0
43 #define a4_height (float) 842.0
44 #define a5_width (float) 421.0
45 #define a5_height (float) 595.0
46 #define a6_width (float) 297.0
47 #define a6_height (float) 421.0
48 #define b5_width (float) 501.0
49 #define b5_height (float) 709.0
50 #define letter_width (float) 612.0
51 #define letter_height (float) 792.0
52 #define legal_width (float) 612.0
53 #define legal_height (float) 1008.0
54 #define ledger_width (float) 1224.0
55 #define ledger_height (float) 792.0
56 #define p11x17_width (float) 792.0
57 #define p11x17_height (float) 1224.0
58
59
60 static struct
61 {
62 const char * label;
63 float width;
64 float height;
65 } pageFormat[] =
66 {
67 {"Letter", letter_width, letter_height },
68 {"Legal", legal_width, legal_height },
69 {"Ledger", ledger_width, ledger_height },
70 {"p11x17", p11x17_width, p11x17_height },
71 {"A0", a0_width, a0_height },
72 {"A1", a1_width, a1_height },
73 {"A2", a2_width, a2_height },
74 {"A3", a3_width, a3_height },
75 {"A4", a4_width, a4_height },
76 {"A5", a5_width, a5_height },
77 {"A6", a6_width, a6_height },
78 {"B5", b5_width, b5_height },
79 {NULL, 0.0, 0.0 }
80 };
81
82
83 static struct
84 {
85 const char * label;
86 int32 orientation;
87 } orientation[] =
88 {
89 { "Portrait", PrinterDriver::PORTRAIT_ORIENTATION },
90 { "Landscape", PrinterDriver::LANDSCAPE_ORIENTATION },
91 { NULL, 0 }
92 };
93
94
PageSetupWindow(BMessage * msg,const char * printerName)95 PageSetupWindow::PageSetupWindow(BMessage *msg, const char *printerName)
96 : BlockingWindow(BRect(0, 0, 100, 100), "Paper setup",
97 B_TITLED_WINDOW_LOOK,
98 B_MODAL_APP_WINDOW_FEEL,
99 B_NOT_RESIZABLE | B_NOT_MINIMIZABLE | B_NOT_ZOOMABLE
100 | B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE),
101 fSetupMsg(msg),
102 fPrinterDirName(printerName)
103 {
104 if (printerName)
105 SetTitle(BString(printerName).Append(" paper setup").String());
106
107 // load orientation
108 if (fSetupMsg->FindInt32("orientation", &fCurrentOrientation) != B_OK)
109 fCurrentOrientation = PrinterDriver::PORTRAIT_ORIENTATION;
110
111 // load page rect
112 BRect page;
113 float width = letter_width;
114 float height = letter_height;
115 if (fSetupMsg->FindRect("preview:paper_rect", &page) == B_OK) {
116 width = page.Width();
117 height = page.Height();
118 } else {
119 page.Set(0, 0, width, height);
120 }
121
122 BString label;
123 if (fSetupMsg->FindString("preview:paper_size", &label) != B_OK)
124 label = "Letter";
125
126 // Load units
127 int32 units;
128 if (fSetupMsg->FindInt32("units", &units) != B_OK)
129 units = kUnitInch;
130
131 // re-calculate the margin from the printable rect in points
132 BRect margin = page;
133 if (fSetupMsg->FindRect("preview:printable_rect", &margin) == B_OK) {
134 margin.top -= page.top;
135 margin.left -= page.left;
136 margin.right = page.right - margin.right;
137 margin.bottom = page.bottom - margin.bottom;
138 } else {
139 margin.Set(28.34, 28.34, 28.34, 28.34); // 28.34 dots = 1cm
140 }
141
142
143 fMarginView = new MarginView(int32(width), int32(height), margin,
144 MarginUnit(units));
145
146 BPopUpMenu* pageSizePopUpMenu = new BPopUpMenu("Page size");
147 pageSizePopUpMenu->SetRadioMode(true);
148
149 fPageSizeMenu = new BMenuField("page_size", "Page size:", pageSizePopUpMenu);
150 fPageSizeMenu->Menu()->SetLabelFromMarked(true);
151
152 for (int32 i = 0; pageFormat[i].label != NULL; i++) {
153 BMessage* message = new BMessage(PAGE_SIZE_CHANGED);
154 message->AddFloat("width", pageFormat[i].width);
155 message->AddFloat("height", pageFormat[i].height);
156 BMenuItem* item = new BMenuItem(pageFormat[i].label, message);
157 pageSizePopUpMenu->AddItem(item);
158
159 if (label.Compare(pageFormat[i].label) == 0)
160 item->SetMarked(true);
161 }
162
163 BPopUpMenu* orientationPopUpMenu = new BPopUpMenu("Orientation");
164 orientationPopUpMenu->SetRadioMode(true);
165
166 fOrientationMenu = new BMenuField("orientation", "Orientation:",
167 orientationPopUpMenu);
168 fOrientationMenu->Menu()->SetLabelFromMarked(true);
169
170 for (int32 i = 0; orientation[i].label != NULL; i++) {
171 BMessage* message = new BMessage(ORIENTATION_CHANGED);
172 message->AddInt32("orientation", orientation[i].orientation);
173 BMenuItem* item = new BMenuItem(orientation[i].label, message);
174 orientationPopUpMenu->AddItem(item);
175
176 if (fCurrentOrientation == orientation[i].orientation)
177 item->SetMarked(true);
178 }
179
180 float scale0;
181 BString scale;
182 if (fSetupMsg->FindFloat("scale", &scale0) == B_OK)
183 scale << (int)scale0;
184 else
185 scale = "100";
186
187 fScaleControl = new BTextControl("scale", "Scale [%]:",
188 scale.String(), NULL);
189
190 for (uint32 i = 0; i < '0'; i++)
191 fScaleControl->TextView()->DisallowChar(i);
192
193 for (uint32 i = '9' + 1; i < 255; i++)
194 fScaleControl->TextView()->DisallowChar(i);
195
196 fScaleControl->TextView()->SetMaxBytes(3);
197
198 BBox *separator = new BBox("separator");
199 separator->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 1));
200
201 BButton *cancel = new BButton("cancel", "Cancel", new BMessage(CANCEL_MSG));
202
203 BButton *ok = new BButton("ok", "OK", new BMessage(OK_MSG));
204 ok->MakeDefault(true);
205
206 BGridView* settings = new BGridView();
207 BGridLayout* settingsLayout = settings->GridLayout();
208 settingsLayout->AddItem(fPageSizeMenu->CreateLabelLayoutItem(), 0, 0);
209 settingsLayout->AddItem(fPageSizeMenu->CreateMenuBarLayoutItem(), 1, 0);
210 settingsLayout->AddItem(fOrientationMenu->CreateLabelLayoutItem(), 0, 1);
211 settingsLayout->AddItem(fOrientationMenu->CreateMenuBarLayoutItem(), 1, 1);
212 settingsLayout->AddItem(fScaleControl->CreateLabelLayoutItem(), 0, 2);
213 settingsLayout->AddItem(fScaleControl->CreateTextViewLayoutItem(), 1, 2);
214 settingsLayout->SetSpacing(0, 0);
215
216 SetLayout(new BGroupLayout(B_VERTICAL));
217 AddChild(BGroupLayoutBuilder(B_VERTICAL, 0)
218 .AddGroup(B_HORIZONTAL, 5, 1)
219 .AddGroup(B_VERTICAL, 0, 1.0f)
220 .Add(fMarginView)
221 .AddGlue()
222 .End()
223 .AddGroup(B_VERTICAL, 0, 1.0f)
224 .Add(settings)
225 .AddGlue()
226 .End()
227 .End()
228 .Add(separator)
229 .AddGroup(B_HORIZONTAL, 10, 1.0f)
230 .AddGlue()
231 .Add(cancel)
232 .Add(ok)
233 .End()
234 .SetInsets(10, 10, 10, 10)
235 );
236
237 BRect winFrame(Frame());
238 BRect screenFrame(BScreen().Frame());
239 MoveTo((screenFrame.right - winFrame.right) / 2,
240 (screenFrame.bottom - winFrame.bottom) / 2);
241 }
242
243
244 void
UpdateSetupMessage()245 PageSetupWindow::UpdateSetupMessage()
246 {
247 SetInt32(fSetupMsg, "xres", 300);
248 SetInt32(fSetupMsg, "yres", 300);
249 SetInt32(fSetupMsg, "orientation", fCurrentOrientation);
250
251 // Save scaling factor
252 float scale = atoi(fScaleControl->Text());
253 if (scale <= 0.0) scale = 100.0;
254 if (scale > 1000.0) scale = 1000.0;
255 SetFloat(fSetupMsg, "scale", scale);
256
257 float scaleR = 100.0 / scale;
258 BMenuItem *item = fPageSizeMenu->Menu()->FindMarked();
259 if (item) {
260 float w, h;
261 BMessage *msg = item->Message();
262 msg->FindFloat("width", &w);
263 msg->FindFloat("height", &h);
264 BRect r(0, 0, w, h);
265 if (fCurrentOrientation == PrinterDriver::LANDSCAPE_ORIENTATION)
266 r.Set(0, 0, h, w);
267
268 SetRect(fSetupMsg, "preview:paper_rect", r);
269 SetRect(fSetupMsg, "paper_rect", ScaleRect(r, scaleR));
270 SetString(fSetupMsg, "preview:paper_size", item->Label());
271
272 // Save the printable_rect
273 BRect margin = fMarginView->Margin();
274 if (fCurrentOrientation == PrinterDriver::PORTRAIT_ORIENTATION) {
275 margin.right = w - margin.right;
276 margin.bottom = h - margin.bottom;
277 } else {
278 margin.right = h - margin.right;
279 margin.bottom = w - margin.bottom;
280 }
281 SetRect(fSetupMsg, "preview:printable_rect", margin);
282 SetRect(fSetupMsg, "printable_rect", ScaleRect(margin, scaleR));
283
284 SetInt32(fSetupMsg, "units", fMarginView->Unit());
285 }
286 }
287
288
289 void
MessageReceived(BMessage * msg)290 PageSetupWindow::MessageReceived(BMessage *msg)
291 {
292 switch (msg->what) {
293 case OK_MSG: {
294 UpdateSetupMessage();
295 Quit(B_OK);
296 } break;
297
298 case CANCEL_MSG: {
299 Quit(B_ERROR);
300 } break;
301
302 case PAGE_SIZE_CHANGED: {
303 float w, h;
304 msg->FindFloat("width", &w);
305 msg->FindFloat("height", &h);
306 if (fCurrentOrientation == PrinterDriver::PORTRAIT_ORIENTATION) {
307 fMarginView->SetPageSize(w, h);
308 } else {
309 fMarginView->SetPageSize(h, w);
310 }
311 fMarginView->UpdateView(MARGIN_CHANGED);
312 } break;
313
314 case ORIENTATION_CHANGED: {
315 int32 orientation;
316 msg->FindInt32("orientation", &orientation);
317
318 if (fCurrentOrientation != orientation) {
319 fCurrentOrientation = orientation;
320 BPoint p = fMarginView->PageSize();
321 fMarginView->SetPageSize(p.y, p.x);
322 fMarginView->UpdateView(MARGIN_CHANGED);
323 }
324 } break;
325
326 default:
327 BlockingWindow::MessageReceived(msg);
328 break;
329 }
330 }
331