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