xref: /haiku/src/add-ons/print/drivers/preview/PageSetupWindow.cpp (revision 0c93c0a807b27096abbfad677436afb7d1712d4a)
1 /*
2  * Copyright 2003-2007, Haiku. 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  *		Hartmut Reh
10  */
11 
12 #include <stdlib.h>
13 
14 #include <InterfaceKit.h>
15 #include <SupportKit.h>
16 #include "PrinterDriver.h"
17 #include "PageSetupWindow.h"
18 
19 #include "BeUtils.h"
20 #include "MarginView.h"
21 
22 // static global variables
23 static struct
24 {
25 	char  *label;
26 	float width;
27 	float height;
28 } pageFormat[] =
29 {
30 	{"Letter", letter_width, letter_height },
31 	{"Legal",  legal_width,  legal_height  },
32 	{"Ledger", ledger_width, ledger_height  },
33 	{"p11x17", p11x17_width, p11x17_height  },
34 	{"A0",     a0_width,     a0_height     },
35 	{"A1",     a1_width,     a1_height     },
36 	{"A2",     a2_width,     a2_height     },
37 	{"A3",     a3_width,     a3_height     },
38 	{"A4",     a4_width,     a4_height     },
39 	{"A5",     a5_width,     a5_height     },
40 	{"A6",     a6_width,     a6_height     },
41 	{"B5",     b5_width,     b5_height     },
42 	{NULL,     0.0,          0.0           }
43 };
44 
45 
46 static struct
47 {
48 	char  *label;
49 	int32 orientation;
50 } orientation[] =
51 {
52 	{"Portrait",  PrinterDriver::PORTRAIT_ORIENTATION},
53 	{"Landscape", PrinterDriver::LANDSCAPE_ORIENTATION},
54 	{NULL, 0}
55 };
56 
57 
58 /**
59  * Constuctor
60  *
61  * @param
62  * @return
63  */
64 PageSetupWindow::PageSetupWindow(BMessage *msg, const char *printerName)
65 	:	BlockingWindow(BRect(0,0,400,220), "Page Setup", B_TITLED_WINDOW_LOOK,
66  			B_MODAL_APP_WINDOW_FEEL, B_NOT_RESIZABLE | B_NOT_MINIMIZABLE |
67  			B_NOT_ZOOMABLE)
68 {
69 	MoveTo(300, 300);
70 
71 	fSetupMsg	= msg;
72 
73 	if ( printerName ) {
74 		BString	title;
75 
76 		title << printerName << " Page Setup";
77 		SetTitle( title.String() );
78 
79 		// save the printer name
80 		fPrinterDirName = printerName;
81 	}
82 
83 	// ---- Ok, build a default page setup user interface
84 	BRect		r(0, 0, letter_width, letter_height);
85 	BBox		*panel;
86 	BButton		*button;
87 	float		x, y, w, h;
88 	int         i;
89 	BMenuItem	*item;
90 	float       width, height;
91 	int32       orient;
92 	BRect		page;
93 	BRect		margin(0, 0, 0, 0);
94 	MarginUnit	units = kUnitInch;
95 	BString 	setting_value;
96 
97 	// load orientation
98 	fSetupMsg->FindInt32("orientation", &orient);
99 
100 	// load page rect
101 	if (fSetupMsg->FindRect("preview:paper_rect", &r) == B_OK) {
102 		width = r.Width();
103 		height = r.Height();
104 		page = r;
105 	} else {
106 		width = letter_width;
107 		height = letter_height;
108 		page.Set(0, 0, width, height);
109 	}
110 
111 	// Load units
112 	int32 unitsValue;
113 	if (fSetupMsg->FindInt32("units", &unitsValue) == B_OK) {
114 		units = (MarginUnit)unitsValue;
115 	}
116 
117 	// add a *dialog* background
118 	r = Bounds();
119 	panel = new BBox(r, "top_panel", B_FOLLOW_ALL,
120 					B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE_JUMP,
121 					B_PLAIN_BORDER);
122 
123 	////////////// Create the margin view //////////////////////
124 
125 	// re-calculate the margin from the printable rect in points
126 	margin = page;
127 	if (fSetupMsg->FindRect("preview:printable_rect", &margin) == B_OK) {
128 		margin.top -= page.top;
129 		margin.left -= page.left;
130 		margin.right = page.right - margin.right;
131 		margin.bottom = page.bottom - margin.bottom;
132 	} else {
133 		margin.Set(28.34, 28.34, 28.34, 28.34);		// 28.34 dots = 1cm
134 	}
135 
136 	fMarginView = new MarginView(BRect(20,20,200,160), (int32)width, (int32)height,
137 			margin, units);
138 	panel->AddChild(fMarginView);
139 
140 	// add page format menu
141 	// Simon Changed to OFFSET popups
142 	x = r.left + kMargin * 2 + kOffset; y = r.top + kMargin * 2;
143 
144 	BPopUpMenu* m = new BPopUpMenu("page_size");
145 	m->SetRadioMode(true);
146 
147 	// Simon changed width 200->140
148 	BMenuField *mf = new BMenuField(BRect(x, y, x + 140, y + 20), "page_size",
149 		"Page Size:", m);
150 	fPageSizeMenu = mf;
151 	mf->ResizeToPreferred();
152 	mf->GetPreferredSize(&w, &h);
153 
154 	// Simon added: SetDivider
155 	mf->SetDivider(be_plain_font->StringWidth("Page Size#"));
156 
157 	panel->AddChild(mf);
158 
159 	item = NULL;
160 	for (i = 0; pageFormat[i].label != NULL; i++)
161 	{
162 		BMessage* msg = new BMessage('pgsz');
163 		msg->AddFloat("width", pageFormat[i].width);
164 		msg->AddFloat("height", pageFormat[i].height);
165 		BMenuItem* mi = new BMenuItem(pageFormat[i].label, msg);
166 		m->AddItem(mi);
167 
168 		if (width == pageFormat[i].width && height == pageFormat[i].height) {
169 			item = mi;
170 		}
171 		if (height == pageFormat[i].width && width == pageFormat[i].height) {
172 			item = mi;
173 		}
174 	}
175 	mf->Menu()->SetLabelFromMarked(true);
176 	if (!item) {
177 		item = m->ItemAt(0);
178 	}
179 	item->SetMarked(true);
180 	mf->MenuItem()->SetLabel(item->Label());
181 
182 	// add orientation menu
183 	y += h + kMargin;
184 	m = new BPopUpMenu("orientation");
185 	m->SetRadioMode(true);
186 
187 	// Simon changed 200->140
188 	mf = new BMenuField(BRect(x, y, x + 140, y + 20), "orientation", "Orientation:", m);
189 
190 	// Simon added: SetDivider
191 	mf->SetDivider(be_plain_font->StringWidth("Orientation#"));
192 
193 	fOrientationMenu = mf;
194 	mf->ResizeToPreferred();
195 	panel->AddChild(mf);
196 	r.top += h;
197 	item = NULL;
198 	for (int i = 0; orientation[i].label != NULL; i++)
199 	{
200 	 	BMessage* msg = new BMessage('ornt');
201 		msg->AddInt32("orientation", orientation[i].orientation);
202 		BMenuItem* mi = new BMenuItem(orientation[i].label, msg);
203 		m->AddItem(mi);
204 
205 		if (orient == orientation[i].orientation) {
206 			item = mi;
207 		}
208 	}
209 	mf->Menu()->SetLabelFromMarked(true);
210 // SHOULD BE REMOVED
211 	if (!item) {
212 		item = m->ItemAt(0);
213 	}
214 ///////////////////
215 	item->SetMarked(true);
216 	mf->MenuItem()->SetLabel(item->Label());
217 
218 	// add scale text control
219 	y += h + kMargin;
220 	BString scale;
221 	float scale0;
222 	if (fSetupMsg->FindFloat("scale", &scale0) == B_OK) {
223 		scale << (int)scale0;
224 	} else {
225 		scale = "100";
226 	}
227 	fScaleControl = new BTextControl(BRect(x, y, x + 100, y + 20), "scale", "Scale [%]:",
228 									scale.String(),
229 	                                NULL, B_FOLLOW_RIGHT);
230 	int num;
231 	for (num = 0; num <= 255; num++) {
232 		fScaleControl->TextView()->DisallowChar(num);
233 	}
234 	for (num = 0; num <= 9; num++) {
235 		fScaleControl->TextView()->AllowChar('0' + num);
236 	}
237 	fScaleControl->TextView()->SetMaxBytes(3);
238 
239 	panel->AddChild(fScaleControl);
240 
241 	// add a "OK" button, and make it default
242 	button 	= new BButton(r, NULL, "OK", new BMessage(OK_MSG),
243 		B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
244 	button->ResizeToPreferred();
245 	button->GetPreferredSize(&w, &h);
246 	x = r.right - w - 8;
247 	y = r.bottom - h - 8;
248 	button->MoveTo(x, y);
249 	panel->AddChild(button);
250 	button->MakeDefault(true);
251 
252 	// add a "Cancel button
253 	button 	= new BButton(r, NULL, "Cancel", new BMessage(CANCEL_MSG),
254 		B_FOLLOW_RIGHT | B_FOLLOW_BOTTOM);
255 	button->GetPreferredSize(&w, &h);
256 	button->ResizeToPreferred();
257 	button->MoveTo(x - w - 8, y);
258 	panel->AddChild(button);
259 
260 	// add a separator line...
261 	BBox * line = new BBox(BRect(r.left, y - 9, r.right, y - 8), NULL,
262 		B_FOLLOW_LEFT_RIGHT | B_FOLLOW_BOTTOM );
263 	panel->AddChild(line);
264 
265 	// Finally, add our panel to window
266 	AddChild(panel);
267 }
268 
269 
270 // --------------------------------------------------
271 void
272 PageSetupWindow::UpdateSetupMessage()
273 {
274 	BMenuItem *item;
275 	int32 orientation = 0;
276 
277 	item = fOrientationMenu->Menu()->FindMarked();
278 	if (item) {
279 		BMessage *msg = item->Message();
280 		msg->FindInt32("orientation", &orientation);
281 		SetInt32(fSetupMsg, "orientation", orientation);
282 	}
283 
284 	// Save scaling factor
285 	float scale = atoi(fScaleControl->Text());
286 	if (scale <= 0.0) { // sanity check
287 		scale = 100.0;
288 	}
289 	if (scale > 1000.0) {
290 		scale = 1000.0;
291 	}
292 	SetFloat(fSetupMsg, "scale", scale);
293 
294 	float scaleR = 100.0 / scale;
295 
296 	item = fPageSizeMenu->Menu()->FindMarked();
297 	if (item) {
298 		float w, h;
299 		BMessage *msg = item->Message();
300 		msg->FindFloat("width", &w);
301 		msg->FindFloat("height", &h);
302 		BRect r;
303 		if (orientation == 0) {
304 			r.Set(0, 0, w, h);
305 		} else {
306 			r.Set(0, 0, h, w);
307 		}
308 		SetRect(fSetupMsg, "preview:paper_rect", r);
309 		SetRect(fSetupMsg, "paper_rect", ScaleRect(r, scaleR));
310 
311 		// Save the printable_rect
312 		BRect margin = fMarginView->GetMargin();
313 		if (orientation == 0) {
314 			margin.right = w - margin.right;
315 			margin.bottom = h - margin.bottom;
316 		} else {
317 			margin.right = h - margin.right;
318 			margin.bottom = w - margin.bottom;
319 		}
320 		SetRect(fSetupMsg, "preview:printable_rect", margin);
321 		SetRect(fSetupMsg, "printable_rect", ScaleRect(margin, scaleR));
322 
323 		// save the units used
324 		int32 units = fMarginView->GetMarginUnit();
325 		SetInt32(fSetupMsg, "units", units);
326 	}
327 }
328 
329 
330 // --------------------------------------------------
331 void
332 PageSetupWindow::MessageReceived(BMessage *msg)
333 {
334 	switch (msg->what){
335 		case OK_MSG:
336 			UpdateSetupMessage();
337 			Quit(B_OK);
338 			break;
339 
340 		case CANCEL_MSG:
341 			Quit(B_ERROR);
342 			break;
343 
344 		// Simon added
345 		case 'pgsz':
346 			{
347 				float w, h;
348 				msg->FindFloat("width", &w);
349 				msg->FindFloat("height", &h);
350 				BMenuItem *item = fOrientationMenu->Menu()->FindMarked();
351 				if (item) {
352 					int32 orientation = 0;
353 					BMessage *m = item->Message();
354 					m->FindInt32("orientation", &orientation);
355 					if (orientation == PrinterDriver::PORTRAIT_ORIENTATION) {
356 						fMarginView->SetPageSize(w, h);
357 					} else {
358 						fMarginView->SetPageSize(h, w);
359 					}
360 					fMarginView->UpdateView(MARGIN_CHANGED);
361 				}
362 			}
363 			break;
364 
365 		// Simon added
366 		case 'ornt':
367 			{
368 				BPoint p = fMarginView->GetPageSize();
369 				int32 orientation;
370 				msg->FindInt32("orientation", &orientation);
371 				if (orientation == PrinterDriver::LANDSCAPE_ORIENTATION
372 					&& p.y > p.x) {
373 					fMarginView->SetPageSize(p.y, p.x);
374 					fMarginView->UpdateView(MARGIN_CHANGED);
375 				}
376 				if (orientation == PrinterDriver::PORTRAIT_ORIENTATION
377 					&& p.x > p.y) {
378 					fMarginView->SetPageSize(p.y, p.x);
379 					fMarginView->UpdateView(MARGIN_CHANGED);
380 				}
381 			}
382 			break;
383 
384 		default:
385 			inherited::MessageReceived(msg);
386 			break;
387 	}
388 }
389 
390 
391 
392