1/*
2
3PDF Writer printer driver.
4
5Version: 12.19.2000
6
7Copyright (c) 2001 OpenBeOS.
8
9Authors:
10	Philippe Houdoin
11	Simon Gauvin
12	Michael Pfeiffer
13
14Permission is hereby granted, free of charge, to any person obtaining a copy of
15this software and associated documentation files (the "Software"), to deal in
16the Software without restriction, including without limitation the rights to
17use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
18of the Software, and to permit persons to whom the Software is furnished to do
19so, subject to the following conditions:
20
21The above copyright notice and this permission notice shall be included in all
22copies or substantial portions of the Software.
23
24THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
30THE SOFTWARE.
31
32*/
33
34#include "PageSetupWindow.h"
35
36#include "AdvancedSettingsWindow.h"
37#include "Fonts.h"
38#include "FontsWindow.h"
39#include "BlockingWindow.h"
40#include "MarginView.h"
41#include "PrinterDriver.h"
42#include "pdflib.h"				// for pageFormat constants
43#include "PrintUtils.h"
44
45
46#include <Box.h>
47#include <Button.h>
48#include <GridView.h>
49#include <GroupLayout.h>
50#include <GroupLayoutBuilder.h>
51#include <MenuField.h>
52#include <Message.h>
53#include <PopUpMenu.h>
54#include <Screen.h>
55#include <TextControl.h>
56
57
58// static global variables
59static struct
60{
61	const char *label;
62	float width;
63	float height;
64} pageFormat[] =
65{
66	{ "Letter", letter_width, letter_height },
67	{ "Legal",  legal_width,  legal_height  },
68	{ "Ledger", ledger_width, ledger_height },
69	{ "p11x17", p11x17_width, p11x17_height },
70	{ "A0",     a0_width,     a0_height     },
71	{ "A1",     a1_width,     a1_height     },
72	{ "A2",     a2_width,     a2_height     },
73	{ "A3",     a3_width,     a3_height     },
74	{ "A4",     a4_width,     a4_height     },
75	{ "A5",     a5_width,     a5_height     },
76	{ "A6",     a6_width,     a6_height     },
77	{ "B5",     b5_width,     b5_height     },
78	{ NULL,     0.0,          0.0           }
79};
80
81
82static struct
83{
84	const char *label;
85	int32 orientation;
86} orientation[] =
87{
88	{ "Portrait", PrinterDriver::PORTRAIT_ORIENTATION },
89	{ "Landscape", PrinterDriver::LANDSCAPE_ORIENTATION },
90	{ NULL, 0 }
91};
92
93// PDFLib 5.x does not support PDF 1.2 anymore!
94static const char *pdf_compatibility[] = { "1.3", "1.4", NULL };
95
96
97PageSetupWindow::PageSetupWindow(BMessage *msg, const char *printerName)
98	: HWindow(BRect(0, 0, 200, 100), "Page setup", B_TITLED_WINDOW_LOOK,
99 		B_MODAL_APP_WINDOW_FEEL,
100 		B_NOT_RESIZABLE | B_NOT_MINIMIZABLE | B_NOT_ZOOMABLE
101			| B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE),
102	 fResult(B_ERROR),
103	 fSetupMsg(msg),
104	 fAdvancedSettings(*msg),
105	 fPrinterDirName(printerName)
106{
107	fExitSem = create_sem(0, "PageSetup");
108
109	if (printerName)
110		SetTitle(BString(printerName).Append(" page setup").String());
111
112	if (fSetupMsg->FindInt32("orientation", &fCurrentOrientation) != B_OK)
113		fCurrentOrientation = PrinterDriver::PORTRAIT_ORIENTATION;
114
115	BRect page;
116	float width = letter_width;
117	float height = letter_height;
118	if (fSetupMsg->FindRect("paper_rect", &page) == B_OK) {
119		width = page.Width();
120		height = page.Height();
121	} else {
122		page.Set(0, 0, width, height);
123	}
124
125	BString label;
126	if (fSetupMsg->FindString("pdf_paper_size", &label) != B_OK)
127		label = "Letter";
128
129	int32 compression;
130	fSetupMsg->FindInt32("pdf_compression", &compression);
131
132	int32 units;
133	if (fSetupMsg->FindInt32("units", &units) != B_OK)
134		units = kUnitInch;
135
136	// re-calculate the margin from the printable rect in points
137	BRect margin = page;
138	if (fSetupMsg->FindRect("printable_rect", &margin) == B_OK) {
139		margin.top -= page.top;
140		margin.left -= page.left;
141		margin.right = page.right - margin.right;
142		margin.bottom = page.bottom - margin.bottom;
143	} else {
144		margin.Set(28.34, 28.34, 28.34, 28.34);		// 28.34 dots = 1cm
145	}
146
147	BString setting_value;
148	if (fSetupMsg->FindString("pdf_compatibility", &setting_value) != B_OK)
149		setting_value = "1.3";
150
151	// Load font settings
152	fFonts = new Fonts();
153	fFonts->CollectFonts();
154	BMessage fonts;
155	if (fSetupMsg->FindMessage("fonts", &fonts) == B_OK)
156		fFonts->SetTo(&fonts);
157
158	fMarginView = new MarginView(int32(width), int32(height), margin,
159		MarginUnit(units));
160
161	BPopUpMenu* pageSize = new BPopUpMenu("Page size");
162	pageSize->SetRadioMode(true);
163
164	fPageSizeMenu = new BMenuField("page_size", "Page size:", pageSize);
165	fPageSizeMenu->Menu()->SetLabelFromMarked(true);
166
167	for (int32 i = 0; pageFormat[i].label != NULL; i++) {
168		BMessage* message = new BMessage(PAGE_SIZE_CHANGED);
169		message->AddFloat("width", pageFormat[i].width);
170		message->AddFloat("height", pageFormat[i].height);
171		BMenuItem* item = new BMenuItem(pageFormat[i].label, message);
172		pageSize->AddItem(item);
173
174		if (label.Compare(pageFormat[i].label) == 0)
175			item->SetMarked(true);
176	}
177
178	BPopUpMenu* orientationPopUpMenu = new BPopUpMenu("Orientation");
179	orientationPopUpMenu->SetRadioMode(true);
180
181	fOrientationMenu = new BMenuField("orientation", "Orientation:",
182		orientationPopUpMenu);
183	fOrientationMenu->Menu()->SetLabelFromMarked(true);
184
185	for (int32 i = 0; orientation[i].label != NULL; i++) {
186	 	BMessage* message = new BMessage(ORIENTATION_CHANGED);
187		message->AddInt32("orientation", orientation[i].orientation);
188		BMenuItem* item = new BMenuItem(orientation[i].label, message);
189		orientationPopUpMenu->AddItem(item);
190
191		if (fCurrentOrientation == orientation[i].orientation)
192			item->SetMarked(true);
193	}
194
195	BPopUpMenu* compatibility = new BPopUpMenu("PDF compatibility");
196	compatibility->SetRadioMode(true);
197
198	fPDFCompatibilityMenu = new BMenuField("pdf_compatibility",
199		"PDF compatibility:", compatibility);
200	fPDFCompatibilityMenu->Menu()->SetLabelFromMarked(true);
201
202	for (int32 i = 0; pdf_compatibility[i] != NULL; i++) {
203		BMenuItem* item = new BMenuItem(pdf_compatibility[i], NULL);
204		compatibility->AddItem(item);
205		if (setting_value == pdf_compatibility[i])
206			item->SetMarked(true);
207	}
208
209	fPDFCompressionSlider = new BSlider("pdf_compression",
210		"Compression:", NULL, 0, 9, B_HORIZONTAL);
211	fPDFCompressionSlider->SetLimitLabels("None", "Best");
212	fPDFCompressionSlider->SetHashMarks(B_HASH_MARKS_BOTTOM);
213	fPDFCompressionSlider->SetValue(compression);
214
215	BBox *separator = new BBox("separator");
216	separator->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 1));
217
218	BButton *cancel = new BButton("cancel", "Cancel", new BMessage(CANCEL_MSG));
219
220	BButton *ok = new BButton("ok", "OK", new BMessage(OK_MSG));
221	ok->MakeDefault(true);
222
223	BButton *fontsButton = new BButton("fonts", "Fonts" B_UTF8_ELLIPSIS,
224		new BMessage(FONTS_MSG));
225
226	BButton* advancedButton = new BButton("advanced",
227		"Advanced" B_UTF8_ELLIPSIS,
228		new BMessage(ADVANCED_MSG));
229
230	BGridView* settings = new BGridView();
231	BGridLayout* settingsLayout = settings->GridLayout();
232	settingsLayout->AddItem(fPageSizeMenu->CreateLabelLayoutItem(), 0, 0);
233	settingsLayout->AddItem(fPageSizeMenu->CreateMenuBarLayoutItem(), 1, 0);
234	settingsLayout->AddItem(fOrientationMenu->CreateLabelLayoutItem(), 0, 1);
235	settingsLayout->AddItem(fOrientationMenu->CreateMenuBarLayoutItem(), 1, 1);
236	settingsLayout->AddItem(fPDFCompatibilityMenu->CreateLabelLayoutItem(), 0, 2);
237	settingsLayout->AddItem(fPDFCompatibilityMenu->CreateMenuBarLayoutItem(), 1, 2);
238	settingsLayout->AddView(fPDFCompressionSlider, 0, 3, 2);
239	settingsLayout->SetSpacing(0, 0);
240
241	SetLayout(new BGroupLayout(B_VERTICAL));
242	AddChild(BGroupLayoutBuilder(B_VERTICAL, 0)
243		.AddGroup(B_HORIZONTAL, 5, 1)
244			.AddGroup(B_VERTICAL, 0, 1.0f)
245				.Add(fMarginView)
246				.AddGlue()
247			.End()
248			.AddGroup(B_VERTICAL, 0, 1.0f)
249				.Add(settings)
250				.AddGlue()
251			.End()
252		.End()
253		.Add(separator)
254		.AddGroup(B_HORIZONTAL, 10, 1.0f)
255			.Add(fontsButton)
256			.Add(advancedButton)
257			.AddGlue()
258			.Add(cancel)
259			.Add(ok)
260		.End()
261		.SetInsets(10, 10, 10, 10)
262	);
263
264	BRect winFrame(Frame());
265	BRect screenFrame(BScreen().Frame());
266	MoveTo((screenFrame.right - winFrame.right) / 2,
267		(screenFrame.bottom - winFrame.bottom) / 2);
268}
269
270
271PageSetupWindow::~PageSetupWindow()
272{
273	delete_sem(fExitSem);
274	delete fFonts;
275}
276
277
278void
279PageSetupWindow::MessageReceived(BMessage *msg)
280{
281	switch (msg->what) {
282		case OK_MSG: {
283			_UpdateSetupMessage();
284			fResult = B_OK;
285			release_sem(fExitSem);
286		}	break;
287
288		case CANCEL_MSG: {
289			fResult = B_ERROR;
290			release_sem(fExitSem);
291		}	break;
292
293		case PAGE_SIZE_CHANGED:	{
294			float w, h;
295			msg->FindFloat("width", &w);
296			msg->FindFloat("height", &h);
297			if (fCurrentOrientation == PrinterDriver::PORTRAIT_ORIENTATION) {
298				fMarginView->SetPageSize(w, h);
299			} else {
300				fMarginView->SetPageSize(h, w);
301			}
302			fMarginView->UpdateView(MARGIN_CHANGED);
303		}	break;
304
305		case ORIENTATION_CHANGED: {
306			int32 orientation;
307			msg->FindInt32("orientation", &orientation);
308
309			if (fCurrentOrientation != orientation) {
310				fCurrentOrientation = orientation;
311				BPoint p = fMarginView->PageSize();
312				fMarginView->SetPageSize(p.y, p.x);
313				fMarginView->UpdateView(MARGIN_CHANGED);
314			}
315		}	break;
316
317		case FONTS_MSG: {
318			(new FontsWindow(fFonts))->Show();
319		}	break;
320
321		case ADVANCED_MSG: {
322			(new AdvancedSettingsWindow(&fAdvancedSettings))->Show();
323		}	break;
324
325		default:
326			inherited::MessageReceived(msg);
327			break;
328	}
329}
330
331
332bool
333PageSetupWindow::QuitRequested()
334{
335	release_sem(fExitSem);
336	return true;
337}
338
339
340status_t
341PageSetupWindow::Go()
342{
343	MoveTo(300,300);
344	Show();
345
346	while (acquire_sem(fExitSem) == B_INTERRUPTED) {
347	}
348
349	// Have to cache the value since we delete ourself on Quit()
350	status_t result = fResult;
351	if (Lock())
352		Quit();
353
354	return result;
355}
356
357
358void
359PageSetupWindow::_UpdateSetupMessage()
360{
361	SetInt32(fSetupMsg, "orientation", fCurrentOrientation);
362
363	BMenuItem *item = fPDFCompatibilityMenu->Menu()->FindMarked();
364	if (item)
365		SetString(fSetupMsg, "pdf_compatibility", item->Label());
366
367	SetInt32(fSetupMsg, "pdf_compression", fPDFCompressionSlider->Value());
368
369	item = fPageSizeMenu->Menu()->FindMarked();
370	if (item) {
371		float w, h;
372		BMessage *msg = item->Message();
373		msg->FindFloat("width", &w);
374		msg->FindFloat("height", &h);
375		BRect r(0, 0, w, h);
376		if (fCurrentOrientation == PrinterDriver::LANDSCAPE_ORIENTATION)
377			r.Set(0, 0, h, w);
378
379		// Save the printable_rect
380		BRect margin = fMarginView->Margin();
381		if (fCurrentOrientation == PrinterDriver::PORTRAIT_ORIENTATION) {
382			margin.right = w - margin.right;
383			margin.bottom = h - margin.bottom;
384		} else {
385			margin.right = h - margin.right;
386			margin.bottom = w - margin.bottom;
387		}
388
389		SetRect(fSetupMsg, "paper_rect", r);
390		SetRect(fSetupMsg, "printable_rect", margin);
391		SetInt32(fSetupMsg, "units", fMarginView->Unit());
392		SetString(fSetupMsg, "pdf_paper_size", item->Label());
393	}
394
395	BMessage fonts;
396	if (fFonts->Archive(&fonts) == B_OK) {
397		fSetupMsg->RemoveName("fonts");
398		fSetupMsg->AddMessage("fonts", &fonts);
399	}
400
401	// advanced settings
402	BString value;
403	if (fAdvancedSettings.FindString("pdflib_license_key", &value) == B_OK)
404		SetString(fSetupMsg, "pdflib_license_key", value);
405
406	bool webLinks;
407	if (fAdvancedSettings.FindBool("create_web_links", &webLinks) == B_OK)
408		SetBool(fSetupMsg, "create_web_links", webLinks);
409
410	float linkBorder;
411	if (fAdvancedSettings.FindFloat("link_border_width", &linkBorder) == B_OK)
412		SetFloat(fSetupMsg, "link_border_width", linkBorder);
413
414	bool createBookmarks;
415	if (fAdvancedSettings.FindBool("create_bookmarks", &createBookmarks) == B_OK)
416		SetBool(fSetupMsg, "create_bookmarks", createBookmarks);
417
418	if (fAdvancedSettings.FindString("bookmark_definition_file", &value) == B_OK)
419		SetString(fSetupMsg, "bookmark_definition_file", value);
420
421	bool createXrefs;
422	if (fAdvancedSettings.FindBool("create_xrefs", &createXrefs) == B_OK)
423		SetBool(fSetupMsg, "create_xrefs", createXrefs);
424
425	if (fAdvancedSettings.FindString("xrefs_file", &value) == B_OK)
426		SetString(fSetupMsg, "xrefs_file", value.String());
427
428	int32 closeOption;
429	if (fAdvancedSettings.FindInt32("close_option", &closeOption) == B_OK)
430		SetInt32(fSetupMsg, "close_option", closeOption);
431}
432