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