* Copyright 2003-2009, Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Philippe Houdoin
* Simon Gauvin
* Michael Pfeiffer
* Dr. Hartmut Reh
* julun <host.haiku@gmx.de>
*/
#include "MarginView.h"
#include "PrinterDriver.h"
#include "PageSetupWindow.h"
#include "PrintUtils.h"
#include <stdlib.h>
#include <Box.h>
#include <Button.h>
#include <GridView.h>
#include <GroupLayout.h>
#include <GroupLayoutBuilder.h>
#include <MenuField.h>
#include <Message.h>
#include <PopUpMenu.h>
#include <Screen.h>
#include <TextControl.h>
#define a0_width (float) 2380.0
#define a0_height (float) 3368.0
#define a1_width (float) 1684.0
#define a1_height (float) 2380.0
#define a2_width (float) 1190.0
#define a2_height (float) 1684.0
#define a3_width (float) 842.0
#define a3_height (float) 1190.0
#define a4_width (float) 595.0
#define a4_height (float) 842.0
#define a5_width (float) 421.0
#define a5_height (float) 595.0
#define a6_width (float) 297.0
#define a6_height (float) 421.0
#define b5_width (float) 501.0
#define b5_height (float) 709.0
#define letter_width (float) 612.0
#define letter_height (float) 792.0
#define legal_width (float) 612.0
#define legal_height (float) 1008.0
#define ledger_width (float) 1224.0
#define ledger_height (float) 792.0
#define p11x17_width (float) 792.0
#define p11x17_height (float) 1224.0
static struct
{
const char * label;
float width;
float height;
} pageFormat[] =
{
{"Letter", letter_width, letter_height },
{"Legal", legal_width, legal_height },
{"Ledger", ledger_width, ledger_height },
{"p11x17", p11x17_width, p11x17_height },
{"A0", a0_width, a0_height },
{"A1", a1_width, a1_height },
{"A2", a2_width, a2_height },
{"A3", a3_width, a3_height },
{"A4", a4_width, a4_height },
{"A5", a5_width, a5_height },
{"A6", a6_width, a6_height },
{"B5", b5_width, b5_height },
{NULL, 0.0, 0.0 }
};
static struct
{
const char * label;
int32 orientation;
} orientation[] =
{
{ "Portrait", PrinterDriver::PORTRAIT_ORIENTATION },
{ "Landscape", PrinterDriver::LANDSCAPE_ORIENTATION },
{ NULL, 0 }
};
PageSetupWindow::PageSetupWindow(BMessage *msg, const char *printerName)
: BlockingWindow(BRect(0, 0, 100, 100), "Paper setup",
B_TITLED_WINDOW_LOOK,
B_MODAL_APP_WINDOW_FEEL,
B_NOT_RESIZABLE | B_NOT_MINIMIZABLE | B_NOT_ZOOMABLE
| B_AUTO_UPDATE_SIZE_LIMITS | B_CLOSE_ON_ESCAPE),
fSetupMsg(msg),
fPrinterDirName(printerName)
{
if (printerName)
SetTitle(BString(printerName).Append(" paper setup").String());
if (fSetupMsg->FindInt32("orientation", &fCurrentOrientation) != B_OK)
fCurrentOrientation = PrinterDriver::PORTRAIT_ORIENTATION;
BRect page;
float width = letter_width;
float height = letter_height;
if (fSetupMsg->FindRect("preview:paper_rect", &page) == B_OK) {
width = page.Width();
height = page.Height();
} else {
page.Set(0, 0, width, height);
}
BString label;
if (fSetupMsg->FindString("preview:paper_size", &label) != B_OK)
label = "Letter";
int32 units;
if (fSetupMsg->FindInt32("units", &units) != B_OK)
units = kUnitInch;
BRect margin = page;
if (fSetupMsg->FindRect("preview:printable_rect", &margin) == B_OK) {
margin.top -= page.top;
margin.left -= page.left;
margin.right = page.right - margin.right;
margin.bottom = page.bottom - margin.bottom;
} else {
margin.Set(28.34, 28.34, 28.34, 28.34);
}
fMarginView = new MarginView(int32(width), int32(height), margin,
MarginUnit(units));
BPopUpMenu* pageSizePopUpMenu = new BPopUpMenu("Page size");
pageSizePopUpMenu->SetRadioMode(true);
fPageSizeMenu = new BMenuField("page_size", "Page size:", pageSizePopUpMenu);
fPageSizeMenu->Menu()->SetLabelFromMarked(true);
for (int32 i = 0; pageFormat[i].label != NULL; i++) {
BMessage* message = new BMessage(PAGE_SIZE_CHANGED);
message->AddFloat("width", pageFormat[i].width);
message->AddFloat("height", pageFormat[i].height);
BMenuItem* item = new BMenuItem(pageFormat[i].label, message);
pageSizePopUpMenu->AddItem(item);
if (label.Compare(pageFormat[i].label) == 0)
item->SetMarked(true);
}
BPopUpMenu* orientationPopUpMenu = new BPopUpMenu("Orientation");
orientationPopUpMenu->SetRadioMode(true);
fOrientationMenu = new BMenuField("orientation", "Orientation:",
orientationPopUpMenu);
fOrientationMenu->Menu()->SetLabelFromMarked(true);
for (int32 i = 0; orientation[i].label != NULL; i++) {
BMessage* message = new BMessage(ORIENTATION_CHANGED);
message->AddInt32("orientation", orientation[i].orientation);
BMenuItem* item = new BMenuItem(orientation[i].label, message);
orientationPopUpMenu->AddItem(item);
if (fCurrentOrientation == orientation[i].orientation)
item->SetMarked(true);
}
float scale0;
BString scale;
if (fSetupMsg->FindFloat("scale", &scale0) == B_OK)
scale << (int)scale0;
else
scale = "100";
fScaleControl = new BTextControl("scale", "Scale [%]:",
scale.String(), NULL);
for (uint32 i = 0; i < '0'; i++)
fScaleControl->TextView()->DisallowChar(i);
for (uint32 i = '9' + 1; i < 255; i++)
fScaleControl->TextView()->DisallowChar(i);
fScaleControl->TextView()->SetMaxBytes(3);
BBox *separator = new BBox("separator");
separator->SetExplicitMaxSize(BSize(B_SIZE_UNLIMITED, 1));
BButton *cancel = new BButton("cancel", "Cancel", new BMessage(CANCEL_MSG));
BButton *ok = new BButton("ok", "OK", new BMessage(OK_MSG));
ok->MakeDefault(true);
BGridView* settings = new BGridView();
BGridLayout* settingsLayout = settings->GridLayout();
settingsLayout->AddItem(fPageSizeMenu->CreateLabelLayoutItem(), 0, 0);
settingsLayout->AddItem(fPageSizeMenu->CreateMenuBarLayoutItem(), 1, 0);
settingsLayout->AddItem(fOrientationMenu->CreateLabelLayoutItem(), 0, 1);
settingsLayout->AddItem(fOrientationMenu->CreateMenuBarLayoutItem(), 1, 1);
settingsLayout->AddItem(fScaleControl->CreateLabelLayoutItem(), 0, 2);
settingsLayout->AddItem(fScaleControl->CreateTextViewLayoutItem(), 1, 2);
settingsLayout->SetSpacing(0, 0);
SetLayout(new BGroupLayout(B_VERTICAL));
AddChild(BGroupLayoutBuilder(B_VERTICAL, 0)
.AddGroup(B_HORIZONTAL, 5, 1)
.AddGroup(B_VERTICAL, 0, 1.0f)
.Add(fMarginView)
.AddGlue()
.End()
.AddGroup(B_VERTICAL, 0, 1.0f)
.Add(settings)
.AddGlue()
.End()
.End()
.Add(separator)
.AddGroup(B_HORIZONTAL, 10, 1.0f)
.AddGlue()
.Add(cancel)
.Add(ok)
.End()
.SetInsets(10, 10, 10, 10)
);
BRect winFrame(Frame());
BRect screenFrame(BScreen().Frame());
MoveTo((screenFrame.right - winFrame.right) / 2,
(screenFrame.bottom - winFrame.bottom) / 2);
}
void
PageSetupWindow::UpdateSetupMessage()
{
SetInt32(fSetupMsg, "xres", 300);
SetInt32(fSetupMsg, "yres", 300);
SetInt32(fSetupMsg, "orientation", fCurrentOrientation);
float scale = atoi(fScaleControl->Text());
if (scale <= 0.0) scale = 100.0;
if (scale > 1000.0) scale = 1000.0;
SetFloat(fSetupMsg, "scale", scale);
float scaleR = 100.0 / scale;
BMenuItem *item = fPageSizeMenu->Menu()->FindMarked();
if (item) {
float w, h;
BMessage *msg = item->Message();
msg->FindFloat("width", &w);
msg->FindFloat("height", &h);
BRect r(0, 0, w, h);
if (fCurrentOrientation == PrinterDriver::LANDSCAPE_ORIENTATION)
r.Set(0, 0, h, w);
SetRect(fSetupMsg, "preview:paper_rect", r);
SetRect(fSetupMsg, "paper_rect", ScaleRect(r, scaleR));
SetString(fSetupMsg, "preview:paper_size", item->Label());
BRect margin = fMarginView->Margin();
if (fCurrentOrientation == PrinterDriver::PORTRAIT_ORIENTATION) {
margin.right = w - margin.right;
margin.bottom = h - margin.bottom;
} else {
margin.right = h - margin.right;
margin.bottom = w - margin.bottom;
}
SetRect(fSetupMsg, "preview:printable_rect", margin);
SetRect(fSetupMsg, "printable_rect", ScaleRect(margin, scaleR));
SetInt32(fSetupMsg, "units", fMarginView->Unit());
}
}
void
PageSetupWindow::MessageReceived(BMessage *msg)
{
switch (msg->what) {
case OK_MSG: {
UpdateSetupMessage();
Quit(B_OK);
} break;
case CANCEL_MSG: {
Quit(B_ERROR);
} break;
case PAGE_SIZE_CHANGED: {
float w, h;
msg->FindFloat("width", &w);
msg->FindFloat("height", &h);
if (fCurrentOrientation == PrinterDriver::PORTRAIT_ORIENTATION) {
fMarginView->SetPageSize(w, h);
} else {
fMarginView->SetPageSize(h, w);
}
fMarginView->UpdateView(MARGIN_CHANGED);
} break;
case ORIENTATION_CHANGED: {
int32 orientation;
msg->FindInt32("orientation", &orientation);
if (fCurrentOrientation != orientation) {
fCurrentOrientation = orientation;
BPoint p = fMarginView->PageSize();
fMarginView->SetPageSize(p.y, p.x);
fMarginView->UpdateView(MARGIN_CHANGED);
}
} break;
default:
BlockingWindow::MessageReceived(msg);
break;
}
}