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