1 /* 2 * Copyright 2003-2009, Haiku, Inc. 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 * Dr. Hartmut Reh 10 * julun <host.haiku@gmx.de> 11 */ 12 13 #include "MarginView.h" 14 #include "PrinterDriver.h" 15 #include "PageSetupWindow.h" 16 #include "PrintUtils.h" 17 18 #include <stdlib.h> 19 20 21 #include <Box.h> 22 #include <Button.h> 23 #include <MenuField.h> 24 #include <Message.h> 25 #include <PopUpMenu.h> 26 #include <Screen.h> 27 #include <TextControl.h> 28 29 30 /* copied from PDFlib.h: */ 31 #define a0_width (float) 2380.0 32 #define a0_height (float) 3368.0 33 #define a1_width (float) 1684.0 34 #define a1_height (float) 2380.0 35 #define a2_width (float) 1190.0 36 #define a2_height (float) 1684.0 37 #define a3_width (float) 842.0 38 #define a3_height (float) 1190.0 39 #define a4_width (float) 595.0 40 #define a4_height (float) 842.0 41 #define a5_width (float) 421.0 42 #define a5_height (float) 595.0 43 #define a6_width (float) 297.0 44 #define a6_height (float) 421.0 45 #define b5_width (float) 501.0 46 #define b5_height (float) 709.0 47 #define letter_width (float) 612.0 48 #define letter_height (float) 792.0 49 #define legal_width (float) 612.0 50 #define legal_height (float) 1008.0 51 #define ledger_width (float) 1224.0 52 #define ledger_height (float) 792.0 53 #define p11x17_width (float) 792.0 54 #define p11x17_height (float) 1224.0 55 56 57 static struct 58 { 59 char *label; 60 float width; 61 float height; 62 } pageFormat[] = 63 { 64 {"Letter", letter_width, letter_height }, 65 {"Legal", legal_width, legal_height }, 66 {"Ledger", ledger_width, ledger_height }, 67 {"p11x17", p11x17_width, p11x17_height }, 68 {"A0", a0_width, a0_height }, 69 {"A1", a1_width, a1_height }, 70 {"A2", a2_width, a2_height }, 71 {"A3", a3_width, a3_height }, 72 {"A4", a4_width, a4_height }, 73 {"A5", a5_width, a5_height }, 74 {"A6", a6_width, a6_height }, 75 {"B5", b5_width, b5_height }, 76 {NULL, 0.0, 0.0 } 77 }; 78 79 80 static struct 81 { 82 char *label; 83 int32 orientation; 84 } orientation[] = 85 { 86 { "Portrait", PrinterDriver::PORTRAIT_ORIENTATION }, 87 { "Landscape", PrinterDriver::LANDSCAPE_ORIENTATION }, 88 { NULL, 0 } 89 }; 90 91 92 PageSetupWindow::PageSetupWindow(BMessage *msg, const char *printerName) 93 : BlockingWindow(BRect(0,0,400,220), "Page setup", B_TITLED_WINDOW_LOOK, 94 B_MODAL_APP_WINDOW_FEEL, B_NOT_RESIZABLE | B_NOT_MINIMIZABLE | 95 B_NOT_ZOOMABLE), 96 fSetupMsg(msg), 97 fPrinterDirName(printerName) 98 { 99 if (printerName) 100 SetTitle(BString(printerName).Append(" Page setup").String()); 101 102 // load orientation 103 if (fSetupMsg->FindInt32("orientation", &fCurrentOrientation) != B_OK) 104 fCurrentOrientation = PrinterDriver::PORTRAIT_ORIENTATION; 105 106 // load page rect 107 BRect page; 108 float width = letter_width; 109 float height = letter_height; 110 if (fSetupMsg->FindRect("preview:paper_rect", &page) == B_OK) { 111 width = page.Width(); 112 height = page.Height(); 113 } else { 114 page.Set(0, 0, width, height); 115 } 116 117 BString label; 118 if (fSetupMsg->FindString("preview:paper_size", &label) != B_OK) 119 label = "Letter"; 120 121 // Load units 122 int32 units; 123 if (fSetupMsg->FindInt32("units", &units) != B_OK) 124 units = kUnitInch; 125 126 // re-calculate the margin from the printable rect in points 127 BRect margin = page; 128 if (fSetupMsg->FindRect("preview:printable_rect", &margin) == B_OK) { 129 margin.top -= page.top; 130 margin.left -= page.left; 131 margin.right = page.right - margin.right; 132 margin.bottom = page.bottom - margin.bottom; 133 } else { 134 margin.Set(28.34, 28.34, 28.34, 28.34); // 28.34 dots = 1cm 135 } 136 137 BRect bounds(Bounds()); 138 BBox *panel = new BBox(bounds, "background", B_FOLLOW_ALL, 139 B_WILL_DRAW | B_FRAME_EVENTS | B_NAVIGABLE_JUMP, B_PLAIN_BORDER); 140 AddChild(panel); 141 142 bounds.InsetBy(10.0, 10.0); 143 bounds.right = 230.0; 144 bounds.bottom = 160.0; 145 fMarginView = new MarginView(bounds, int32(width), int32(height), margin, 146 MarginUnit(units)); 147 panel->AddChild(fMarginView); 148 fMarginView->SetResizingMode(B_FOLLOW_NONE); 149 150 BPopUpMenu* m = new BPopUpMenu("Page size"); 151 m->SetRadioMode(true); 152 153 bounds.OffsetBy(bounds.Width() + 10.0, 5.0); 154 float divider = be_plain_font->StringWidth("Orientation: "); 155 fPageSizeMenu = new BMenuField(bounds, "page_size", "Page size:", m); 156 panel->AddChild(fPageSizeMenu); 157 fPageSizeMenu->ResizeToPreferred(); 158 fPageSizeMenu->SetDivider(divider); 159 fPageSizeMenu->Menu()->SetLabelFromMarked(true); 160 161 for (int32 i = 0; pageFormat[i].label != NULL; i++) { 162 BMessage* message = new BMessage(PAGE_SIZE_CHANGED); 163 message->AddFloat("width", pageFormat[i].width); 164 message->AddFloat("height", pageFormat[i].height); 165 BMenuItem* item = new BMenuItem(pageFormat[i].label, message); 166 m->AddItem(item); 167 168 if (label.Compare(pageFormat[i].label) == 0) 169 item->SetMarked(true); 170 } 171 172 m = new BPopUpMenu("Orientation"); 173 m->SetRadioMode(true); 174 175 bounds.OffsetBy(0.0, fPageSizeMenu->Bounds().Height() + 10.0); 176 fOrientationMenu = new BMenuField(bounds, "orientation", "Orientation:", m); 177 panel->AddChild(fOrientationMenu); 178 fOrientationMenu->ResizeToPreferred(); 179 fOrientationMenu->SetDivider(divider); 180 fOrientationMenu->Menu()->SetLabelFromMarked(true); 181 182 for (int32 i = 0; orientation[i].label != NULL; i++) { 183 BMessage* message = new BMessage(ORIENTATION_CHANGED); 184 message->AddInt32("orientation", orientation[i].orientation); 185 BMenuItem* item = new BMenuItem(orientation[i].label, message); 186 m->AddItem(item); 187 188 if (fCurrentOrientation == orientation[i].orientation) 189 item->SetMarked(true); 190 } 191 192 float scale0; 193 BString scale; 194 if (fSetupMsg->FindFloat("scale", &scale0) == B_OK) 195 scale << (int)scale0; 196 else 197 scale = "100"; 198 199 bounds.OffsetBy(0.0, fOrientationMenu->Bounds().Height() + 10.0); 200 bounds.right -= 30.0; 201 fScaleControl = new BTextControl(bounds, "scale", "Scale [%]:", 202 scale.String(), NULL); 203 panel->AddChild(fScaleControl); 204 fScaleControl->ResizeToPreferred(); 205 fScaleControl->SetDivider(divider); 206 207 for (uint32 i = 0; i < '0'; i++) 208 fScaleControl->TextView()->DisallowChar(i); 209 210 for (uint32 i = '9' + 1; i < 255; i++) 211 fScaleControl->TextView()->DisallowChar(i); 212 213 fScaleControl->TextView()->SetMaxBytes(3); 214 215 bounds = Bounds(); 216 bounds.InsetBy(5.0, 0.0); 217 bounds.top = 218 MAX(fScaleControl->Frame().bottom, fMarginView->Frame().bottom) + 10.0; 219 BBox *line = new BBox(BRect(bounds.left, bounds.top, bounds.right, 220 bounds.top + 1.0), NULL, B_FOLLOW_LEFT_RIGHT); 221 panel->AddChild(line); 222 223 bounds.InsetBy(5.0, 0.0); 224 bounds.OffsetBy(0.0, 11.0); 225 BButton *cancel = new BButton(bounds, NULL, "Cancel", new BMessage(CANCEL_MSG)); 226 panel->AddChild(cancel); 227 cancel->ResizeToPreferred(); 228 229 BButton *ok = new BButton(bounds, NULL, "OK", new BMessage(OK_MSG)); 230 panel->AddChild(ok, cancel); 231 ok->ResizeToPreferred(); 232 233 bounds.right = fScaleControl->Frame().right; 234 ok->MoveTo(bounds.right - ok->Bounds().Width(), ok->Frame().top); 235 236 bounds = ok->Frame(); 237 cancel->MoveTo(bounds.left - cancel->Bounds().Width() - 10.0, bounds.top); 238 239 ok->MakeDefault(true); 240 ResizeTo(bounds.right + 10.0, bounds.bottom + 10.0); 241 242 BRect winFrame(Frame()); 243 BRect screenFrame(BScreen().Frame()); 244 MoveTo((screenFrame.right - winFrame.right) / 2, 245 (screenFrame.bottom - winFrame.bottom) / 2); 246 } 247 248 249 void 250 PageSetupWindow::UpdateSetupMessage() 251 { 252 SetInt32(fSetupMsg, "xres", 300); 253 SetInt32(fSetupMsg, "yres", 300); 254 SetInt32(fSetupMsg, "orientation", fCurrentOrientation); 255 256 // Save scaling factor 257 float scale = atoi(fScaleControl->Text()); 258 if (scale <= 0.0) scale = 100.0; 259 if (scale > 1000.0) scale = 1000.0; 260 SetFloat(fSetupMsg, "scale", scale); 261 262 float scaleR = 100.0 / scale; 263 BMenuItem *item = fPageSizeMenu->Menu()->FindMarked(); 264 if (item) { 265 float w, h; 266 BMessage *msg = item->Message(); 267 msg->FindFloat("width", &w); 268 msg->FindFloat("height", &h); 269 BRect r(0, 0, w, h); 270 if (fCurrentOrientation == PrinterDriver::LANDSCAPE_ORIENTATION) 271 r.Set(0, 0, h, w); 272 273 SetRect(fSetupMsg, "preview:paper_rect", r); 274 SetRect(fSetupMsg, "paper_rect", ScaleRect(r, scaleR)); 275 SetString(fSetupMsg, "preview:paper_size", item->Label()); 276 277 // Save the printable_rect 278 BRect margin = fMarginView->Margin(); 279 if (fCurrentOrientation == PrinterDriver::PORTRAIT_ORIENTATION) { 280 margin.right = w - margin.right; 281 margin.bottom = h - margin.bottom; 282 } else { 283 margin.right = h - margin.right; 284 margin.bottom = w - margin.bottom; 285 } 286 SetRect(fSetupMsg, "preview:printable_rect", margin); 287 SetRect(fSetupMsg, "printable_rect", ScaleRect(margin, scaleR)); 288 289 SetInt32(fSetupMsg, "units", fMarginView->Unit()); 290 } 291 } 292 293 294 void 295 PageSetupWindow::MessageReceived(BMessage *msg) 296 { 297 switch (msg->what) { 298 case OK_MSG: { 299 UpdateSetupMessage(); 300 Quit(B_OK); 301 } break; 302 303 case CANCEL_MSG: { 304 Quit(B_ERROR); 305 } break; 306 307 case PAGE_SIZE_CHANGED: { 308 float w, h; 309 msg->FindFloat("width", &w); 310 msg->FindFloat("height", &h); 311 if (fCurrentOrientation == PrinterDriver::PORTRAIT_ORIENTATION) { 312 fMarginView->SetPageSize(w, h); 313 } else { 314 fMarginView->SetPageSize(h, w); 315 } 316 fMarginView->UpdateView(MARGIN_CHANGED); 317 } break; 318 319 case ORIENTATION_CHANGED: { 320 int32 orientation; 321 msg->FindInt32("orientation", &orientation); 322 323 if (fCurrentOrientation != orientation) { 324 fCurrentOrientation = orientation; 325 BPoint p = fMarginView->PageSize(); 326 fMarginView->SetPageSize(p.y, p.x); 327 fMarginView->UpdateView(MARGIN_CHANGED); 328 } 329 } break; 330 331 default: 332 BlockingWindow::MessageReceived(msg); 333 break; 334 } 335 } 336