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