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