Added ability to set a page margin (re-uses MarginView from PDF writer).

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@10948 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Michael Pfeiffer
2005-01-22 14:26:52 +00:00
parent ba6aff63d0
commit fdb0d9ef11
11 changed files with 1294 additions and 119 deletions
+13
View File
@@ -11,6 +11,7 @@
#include <Rect.h>
#include "Halftone.h"
#include "MarginView.h" // for MarginUnit
class BMessage;
class PrinterCap;
@@ -229,6 +230,8 @@ private:
BRect fScaledPaperRect;
BRect fPrintableRect;
BRect fScaledPrintableRect;
BRect fPhysicalRect;
BRect fScaledPhysicalRect;
int32 fNup;
int32 fFirstPage;
int32 fLastPage;
@@ -246,6 +249,7 @@ private:
Color fColor;
Halftone::DitherType fDitherType;
PageSelection fPageSelection;
MarginUnit fMarginUnit;
public:
JobData(BMessage *msg, const PrinterCap *cap, Settings settings);
@@ -284,6 +288,12 @@ public:
const BRect &getScaledPrintableRect() const { return fScaledPrintableRect; }
void setScaledPrintableRect(const BRect &printable_rect) { fScaledPrintableRect = printable_rect; }
const BRect &getPhysicalRect() const { return fPhysicalRect; }
void setPhysicalRect(const BRect &Physical_rect) { fPhysicalRect = Physical_rect; }
const BRect &getScaledPhysicalRect() const { return fScaledPhysicalRect; }
void setScaledPhysicalRect(const BRect &Physical_rect) { fScaledPhysicalRect = Physical_rect; }
int32 getNup() const { return fNup; }
void setNup(int32 nup) { fNup = nup; }
@@ -331,6 +341,9 @@ public:
PageSelection getPageSelection() const { return fPageSelection; }
void setPageSelection(PageSelection pageSelection) { fPageSelection = pageSelection; }
MarginUnit getMarginUnit() const { return fMarginUnit; }
void setMarginUnit(MarginUnit marginUnit) { fMarginUnit = marginUnit; }
};
#endif /* __JOBDATA_H */
+225
View File
@@ -0,0 +1,225 @@
/*
MarginView.h
Copyright (c) 2002 OpenBeOS.
Authors:
Philippe Houdoin
Simon Gauvin
Michael Pfeiffer
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Documentation:
The MarginView is designed to be a self contained component that manages
the display of a BBox control that shows a graphic of a page and its'
margings. The component also includes text fields that are used to mofify
the margin values and a popup to change the units used for the margins.
There are two interfaces for the MarginView component:
1) Set methods:
- page size
- orientation
Get methods to retrieve:
- margins
- page size
The method interface is available for the parent Component to call on
the MarginView in response to the Window receiveing messages from
other BControls that it contains, such as a Page Size popup. The
Get methods are used to extract the page size and margins so that
the printer driver may put these values into a BMessage for printing.
2) 'Optional' Message interface:
- Set Page Size
- Flip Orientation
The message interface is available for GUI Controls, BPopupMenu to send
messages to the MarginView if the parent Window is not used to handle
the messages.
General Use of MarginView component:
1) Simply construct a new MarginView object with the margins
you want as defaults and add this view to the parent view
of the dialog.
MarginView *mv;
mv = new MarginView(viewSizeRect, pageWidth, pageHeight);
parentView->AddChild(mv);
* you can also set the margins in the constructor, and the units:
mv = new MarginView(viewSizeRect, pageWidth, pageHeight
marginRect, kUnitPointS);
! but remeber to have the marginRect values match the UNITS :-)
2) Set Page Size with methods:
mv-SetPageSize( pageWidth, pageHeight );
mv->UpdateView();
3) Set Page Size with BMessage:
BMessage* msg = new BMessage(CHANGE_PAGE_SIZE);
msg->AddFloat("width", pageWidth);
msg->AddFloat("height", pageHeight);
mv->PostMessage(msg);
4) Flip Page with methods:
mv-SetPageSize( pageHeight, pageWidth );
mv->UpdateView();
5) Flip Page with BMessage:
BMessage* msg = new BMessage(FLIP_PAGE);
mv->Looper()->PostMessage(msg);
Note: the MarginView DOES NOT keep track of the orientation. This
should be done by the code for the Page setup dialog.
6) Get Page Size
BPoint pageSize = mv->GetPageSize();
7) Get Margins
BRect margins = mv->GetMargins();
8) Get Units
uint32 units = mv->GetUnits();
where units is one of:
kUnitInch, 72 points/in
kUnitCM, 28.346 points/cm
kUnitPoint, 1 point/point
*/
#ifndef MARGIN_VIEW_H
#define MARGIN_VIEW_H
#include <InterfaceKit.h>
#include <Looper.h>
class MarginManager;
// Messages that the MarginManager accepts
const uint32 TOP_MARGIN_CHANGED = 'tchg';
const uint32 RIGHT_MARGIN_CHANGED = 'rchg';
const uint32 LEFT_MARGIN_CHANGED = 'lchg';
const uint32 BOTTOM_MARGIN_CHANGED = 'bchg';
const uint32 MARGIN_CHANGED = 'mchg';
const uint32 CHANGE_PAGE_SIZE = 'chps';
const uint32 FLIP_PAGE = 'flip';
const uint32 MARGIN_UNIT_CHANGED = 'mucg';
enum MarginUnit {
kUnitInch = 0,
kUnitCM,
kUnitPoint
};
/**
* Class MarginView
*/
class MarginView : public BBox
{
friend MarginManager;
private:
// GUI components
BTextControl *fTop, *fBottom, *fLeft, *fRight;
// rect that holds the margins for the page as a set of point offsets
BRect fMargins;
// the maximum size of the page view calculated from the view size
float fMaxPageWidth;
float fMaxPageHeight;
// the actual size of the page in points
float fPageHeight;
float fPageWidth;
// the units used to calculate the page size
MarginUnit fMarginUnit;
float fUnitValue;
// the size of the drawing area we have to draw the view in pixels
float fViewHeight;
float fViewWidth;
// Calculate the view size for the margins
void CalculateViewSize(uint32 msg);
// performed internally using the supplied popup
void SetMarginUnit(MarginUnit unit);
// performed internally using text fields
void SetMargin(BRect margin);
// utility method
void AllowOnlyNumbers(BTextControl *textControl, int maxNum);
public:
MarginView(BRect rect,
int32 pageWidth = 0,
int32 pageHeight = 0,
BRect margins = BRect(1, 1, 1, 1), // default to 1 inch
MarginUnit unit = kUnitInch);
~MarginView();
/// all the GUI construction code
void ConstructGUI();
// page size
void SetPageSize(float pageWidth, float pageHeight);
// point.x = width, point.y = height
BPoint GetPageSize(void);
// margin
BRect GetMargin(void);
// orientation
// None, this state should be saved elsewhere in the page setup code
// and not here. See the FLIP_PAGE message to perform this function.
// units
MarginUnit GetMarginUnit(void);
// will cause a recalc and redraw
void UpdateView(uint32 msg);
// BeOS Hook methods
virtual void AttachedToWindow(void);
void Draw(BRect rect);
void FrameResized(float width, float height);
void MessageReceived(BMessage *msg);
};
#endif //MARGIN_VIEW_H
+10 -1
View File
@@ -8,12 +8,15 @@
#include <View.h>
#include "DialogWindow.h"
#include "JobData.h"
class BRadioButton;
class BPopUpMenu;
class JobData;
class PaperCap;
class PrinterData;
class PrinterCap;
class MarginView;
class PageSetupView : public BView {
public:
@@ -21,15 +24,21 @@ public:
~PageSetupView();
virtual void AttachedToWindow();
bool UpdateJobData();
void MessageReceived(BMessage *msg);
private:
void AddOrientationItem(const char *name, JobData::Orientation orientation);
JobData::Orientation GetOrientation();
PaperCap *GetPaperCap();
JobData *fJobData;
PrinterData *fPrinterData;
const PrinterCap *fPrinterCap;
BRadioButton *fPortrait;
BPopUpMenu *fPaper;
BPopUpMenu *fOrientation;
BPopUpMenu *fResolution;
BTextControl *fScaling;
MarginView *fMarginView;
};
class PageSetupDlg : public DialogWindow {
+3 -3
View File
@@ -29,9 +29,9 @@ struct BaseCap {
struct PaperCap : public BaseCap {
JobData::Paper paper;
BRect paper_rect;
BRect printable_rect;
BRect physical_rect;
PaperCap(const string &n, bool d, JobData::Paper p, const BRect &r1, const BRect &r2)
: BaseCap(n, d), paper(p), paper_rect(r1), printable_rect(r2) {}
: BaseCap(n, d), paper(p), paper_rect(r1), physical_rect(r2) {}
};
struct PaperSourceCap : public BaseCap {
@@ -91,7 +91,7 @@ public:
kColor,
// Static boolean settings follow.
// For them isSupport() has to be implemented only.
kCopyCommand // supports printer page copy command?
kCopyCommand, // supports printer page copy command?
};
virtual int countCap(CapID) const = 0;
@@ -53,7 +53,15 @@ GraphicsDriver::~GraphicsDriver()
{
}
void GraphicsDriver::setupData(BFile *spool_file, long page_count)
static BRect RotateRect(BRect rect)
{
BRect rotated(rect.top, rect.left, rect.bottom, rect.right);
return rotated;
}
void
GraphicsDriver::setupData(BFile *spool_file, long page_count)
{
BMessage *msg = new BMessage();
msg->Unflatten(spool_file);
@@ -62,18 +70,16 @@ void GraphicsDriver::setupData(BFile *spool_file, long page_count)
delete msg;
fRealJobData = new JobData(*fOrgJobData);
BRect rc;
switch (fOrgJobData->getNup()) {
case 2:
case 8:
case 32:
case 128:
rc.left = fOrgJobData->getPrintableRect().top;
rc.top = fOrgJobData->getPrintableRect().left;
rc.right = fOrgJobData->getPrintableRect().bottom;
rc.bottom = fOrgJobData->getPrintableRect().right;
fRealJobData->setPrintableRect(rc);
fRealJobData->setPrintableRect(RotateRect(fOrgJobData->getPrintableRect()));
fRealJobData->setScaledPrintableRect(RotateRect(fOrgJobData->getScaledPrintableRect()));
fRealJobData->setPhysicalRect(RotateRect(fOrgJobData->getPhysicalRect()));
fRealJobData->setScaledPhysicalRect(RotateRect(fOrgJobData->getScaledPhysicalRect()));
if (JobData::kPortrait == fOrgJobData->getOrientation())
fRealJobData->setOrientation(JobData::kLandscape);
else
@@ -91,7 +97,8 @@ void GraphicsDriver::setupData(BFile *spool_file, long page_count)
fSpoolMetaData = new SpoolMetaData(spool_file);
}
void GraphicsDriver::cleanupData()
void
GraphicsDriver::cleanupData()
{
delete fRealJobData;
delete fOrgJobData;
@@ -101,15 +108,19 @@ void GraphicsDriver::cleanupData()
fSpoolMetaData = NULL;
}
void GraphicsDriver::setupBitmap()
void
GraphicsDriver::setupBitmap()
{
fPixelDepth = color_space2pixel_depth(fOrgJobData->getSurfaceType());
fPageWidth = (fRealJobData->getPrintableRect().IntegerWidth() * fOrgJobData->getXres() + 71) / 72;
fPageHeight = (fRealJobData->getPrintableRect().IntegerHeight() * fOrgJobData->getYres() + 71) / 72;
fPageWidth = (fRealJobData->getPhysicalRect().IntegerWidth() * fOrgJobData->getXres() + 71) / 72;
fPageHeight = (fRealJobData->getPhysicalRect().IntegerHeight() * fOrgJobData->getYres() + 71) / 72;
int widthByte = (fPageWidth * fPixelDepth + 7) / 8;
int size = widthByte * fPageHeight;
#ifdef USE_PREVIEW_FOR_DEBUG
size = 0;
#endif
if (size < kMaxMemorySize) {
fBandCount = 0;
@@ -140,14 +151,16 @@ void GraphicsDriver::setupBitmap()
fBitmap->AddChild(fView);
}
void GraphicsDriver::cleanupBitmap()
void
GraphicsDriver::cleanupBitmap()
{
delete fBitmap;
fBitmap = NULL;
fView = NULL;
}
static BPoint get_scale(JobData *org_job_data)
static
BPoint get_scale(JobData *org_job_data)
{
float width;
float height;
@@ -160,8 +173,8 @@ static BPoint get_scale(JobData *org_job_data)
scale.x = scale.y = 1.0f;
break;
case 2: /* 1x2 or 2x1 */
width = org_job_data->getPrintableRect().Width();
height = org_job_data->getPrintableRect().Height();
width = org_job_data->getPhysicalRect().Width();
height = org_job_data->getPhysicalRect().Height();
if (width < height) { // portrait
scale.x = height / 2.0f / width;
scale.y = width / height;
@@ -171,8 +184,8 @@ static BPoint get_scale(JobData *org_job_data)
}
break;
case 8: /* 2x4 or 4x2 */
width = org_job_data->getPrintableRect().Width();
height = org_job_data->getPrintableRect().Height();
width = org_job_data->getPhysicalRect().Width();
height = org_job_data->getPhysicalRect().Height();
if (width < height) {
scale.x = height / 4.0f / width;
scale.y = width / height / 2.0f;
@@ -182,8 +195,8 @@ static BPoint get_scale(JobData *org_job_data)
}
break;
case 32: /* 4x8 or 8x4 */
width = org_job_data->getPrintableRect().Width();
height = org_job_data->getPrintableRect().Height();
width = org_job_data->getPhysicalRect().Width();
height = org_job_data->getPhysicalRect().Height();
if (width < height) {
scale.x = height / 8.0f / width;
scale.y = width / height / 4.0f;
@@ -231,7 +244,8 @@ static BPoint get_scale(JobData *org_job_data)
return scale;
}
static BPoint get_offset(
static BPoint
get_offset(
int index,
const BPoint *scale,
JobData *org_job_data)
@@ -240,8 +254,8 @@ static BPoint get_offset(
offset.x = 0;
offset.y = 0;
float width = org_job_data->getScaledPrintableRect().Width();
float height = org_job_data->getScaledPrintableRect().Height();
float width = org_job_data->getScaledPhysicalRect().Width();
float height = org_job_data->getScaledPhysicalRect().Height();
switch (org_job_data->getNup()) {
case 1:
@@ -315,6 +329,12 @@ static BPoint get_offset(
break;
}
// adjust margin
offset.x += org_job_data->getScaledPrintableRect().left -
org_job_data->getPhysicalRect().left;
offset.y += org_job_data->getScaledPrintableRect().top -
org_job_data->getPhysicalRect().top;
float real_scale = min(scale->x, scale->y);
if (real_scale != scale->x)
offset.x *= scale->x / real_scale;
@@ -325,7 +345,8 @@ static BPoint get_offset(
}
// print the specified pages on a physical page
bool GraphicsDriver::printPage(PageDataList *pages)
bool
GraphicsDriver::printPage(PageDataList *pages)
{
#ifndef USE_PREVIEW_FOR_DEBUG
BPoint offset;
@@ -377,8 +398,6 @@ bool GraphicsDriver::printPage(PageDataList *pages)
return false;
}
} while (offset.x >= 0.0f && offset.y >= 0.0f);
return true;
#else // !USE_PREVIEW_FOR_DEBUG
fView->SetScale(1.0);
fView->SetHighColor(255, 255, 255);
@@ -393,7 +412,7 @@ bool GraphicsDriver::printPage(PageDataList *pages)
for (it = pages->begin() ; it != pages->end() ; it++) {
BPoint left_top(get_offset(page_index, &scale, fOrgJobData));
BRect clip(fOrgJobData->getPrintableRect());
BRect clip(fOrgJobData->getScaledPrintableRect());
clip.OffsetTo(left_top);
BRegion *region = new BRegion();
region->Set(clip);
@@ -413,14 +432,17 @@ bool GraphicsDriver::printPage(PageDataList *pages)
page_index++;
}
BRect rc(fRealJobData->getPrintableRect());
BRect rc(fRealJobData->getPhysicalRect());
rc.OffsetTo(30.0, 30.0);
PreviewWindow *preview = new PreviewWindow(rc, "Preview", fBitmap);
preview->Go();
#endif // USE_PREVIEW_FOR_DEBUG
return true;
}
bool GraphicsDriver::collectPages(SpoolData *spool_data, PageDataList *pages)
bool
GraphicsDriver::collectPages(SpoolData *spool_data, PageDataList *pages)
{
// collect the pages to be printed on the physical page
PageData *page_data;
@@ -436,12 +458,14 @@ bool GraphicsDriver::collectPages(SpoolData *spool_data, PageDataList *pages)
return more;
}
bool GraphicsDriver::skipPages(SpoolData *spool_data)
bool
GraphicsDriver::skipPages(SpoolData *spool_data)
{
return collectPages(spool_data, NULL);
}
bool GraphicsDriver::printDocument(SpoolData *spool_data)
bool
GraphicsDriver::printDocument(SpoolData *spool_data)
{
bool more;
bool success;
@@ -525,7 +549,8 @@ bool GraphicsDriver::printDocument(SpoolData *spool_data)
return success;
}
bool GraphicsDriver::printJob(BFile *spool_file)
bool
GraphicsDriver::printJob(BFile *spool_file)
{
bool success = true;
print_file_header pfh;
@@ -579,7 +604,8 @@ bool GraphicsDriver::printJob(BFile *spool_file)
return success;
}
BMessage *GraphicsDriver::takeJob(BFile* spool_file, uint32 flags)
BMessage *
GraphicsDriver::takeJob(BFile* spool_file, uint32 flags)
{
fFlags = flags;
BMessage *msg;
@@ -591,39 +617,46 @@ BMessage *GraphicsDriver::takeJob(BFile* spool_file, uint32 flags)
return msg;
}
bool GraphicsDriver::startDoc()
bool
GraphicsDriver::startDoc()
{
return true;
}
bool GraphicsDriver::startPage(int)
bool
GraphicsDriver::startPage(int)
{
return true;
}
bool GraphicsDriver::nextBand(BBitmap *, BPoint *)
bool
GraphicsDriver::nextBand(BBitmap *, BPoint *)
{
return true;
}
bool GraphicsDriver::endPage(int)
bool
GraphicsDriver::endPage(int)
{
return true;
}
bool GraphicsDriver::endDoc(bool)
bool
GraphicsDriver::endDoc(bool)
{
return true;
}
void GraphicsDriver::writeSpoolData(const void *buffer, size_t size) throw(TransportException)
void
GraphicsDriver::writeSpoolData(const void *buffer, size_t size) throw(TransportException)
{
if (fTransport) {
fTransport->write(buffer, size);
}
}
void GraphicsDriver::writeSpoolString(const char *format, ...) throw(TransportException)
void
GraphicsDriver::writeSpoolString(const char *format, ...) throw(TransportException)
{
if (fTransport) {
char buffer[256];
@@ -635,7 +668,8 @@ void GraphicsDriver::writeSpoolString(const char *format, ...) throw(TransportEx
}
}
void GraphicsDriver::writeSpoolChar(char c) throw(TransportException)
void
GraphicsDriver::writeSpoolChar(char c) throw(TransportException)
{
if (fTransport) {
fTransport->write(&c, 1);
@@ -643,7 +677,8 @@ void GraphicsDriver::writeSpoolChar(char c) throw(TransportException)
}
void GraphicsDriver::rgb32_to_rgb24(void* src, void* dst, int width) {
void
GraphicsDriver::rgb32_to_rgb24(void* src, void* dst, int width) {
uint8* d = (uint8*)dst;
rgb_color* s = (rgb_color*)src;
for (int i = width; i > 0; i --) {
@@ -654,7 +689,8 @@ void GraphicsDriver::rgb32_to_rgb24(void* src, void* dst, int width) {
}
}
void GraphicsDriver::cmap8_to_rgb24(void* src, void* dst, int width) {
void
GraphicsDriver::cmap8_to_rgb24(void* src, void* dst, int width) {
uint8* d = (uint8*)dst;
uint8* s = (uint8*)src;
const color_map* cmap = system_colors();
@@ -667,7 +703,8 @@ void GraphicsDriver::cmap8_to_rgb24(void* src, void* dst, int width) {
}
}
void GraphicsDriver::convert_to_rgb24(void* src, void* dst, int width, color_space cs) {
void
GraphicsDriver::convert_to_rgb24(void* src, void* dst, int width, color_space cs) {
if (cs == B_RGB32) rgb32_to_rgb24(src, dst, width);
else if (cs == B_CMAP8) cmap8_to_rgb24(src, dst, width);
else {
@@ -675,7 +712,8 @@ void GraphicsDriver::convert_to_rgb24(void* src, void* dst, int width, color_spa
}
}
uint8 GraphicsDriver::gray(uint8 r, uint8 g, uint8 b) {
uint8
GraphicsDriver::gray(uint8 r, uint8 g, uint8 b) {
if (r == g && g == b) {
return r;
} else {
@@ -684,7 +722,8 @@ uint8 GraphicsDriver::gray(uint8 r, uint8 g, uint8 b) {
}
void GraphicsDriver::rgb32_to_gray(void* src, void* dst, int width) {
void
GraphicsDriver::rgb32_to_gray(void* src, void* dst, int width) {
uint8* d = (uint8*)dst;
rgb_color* s = (rgb_color*)src;
for (int i = width; i > 0; i --) {
@@ -693,7 +732,8 @@ void GraphicsDriver::rgb32_to_gray(void* src, void* dst, int width) {
}
}
void GraphicsDriver::cmap8_to_gray(void* src, void* dst, int width) {
void
GraphicsDriver::cmap8_to_gray(void* src, void* dst, int width) {
uint8* d = (uint8*)dst;
uint8* s = (uint8*)src;
const color_map* cmap = system_colors();
@@ -704,7 +744,8 @@ void GraphicsDriver::cmap8_to_gray(void* src, void* dst, int width) {
}
}
void GraphicsDriver::convert_to_gray(void* src, void* dst, int width, color_space cs) {
void
GraphicsDriver::convert_to_gray(void* src, void* dst, int width, color_space cs) {
if (cs == B_RGB32) rgb32_to_gray(src, dst, width);
else if (cs == B_CMAP8) cmap8_to_gray(src, dst, width);
else {
@@ -15,6 +15,7 @@ StaticLibrary print :
JSDSlider.cpp
JobData.cpp
JobSetupDlg.cpp
MarginView.cpp
PackBits.cpp
PageSetupDlg.cpp
PagesView.cpp
@@ -34,6 +34,9 @@ static const char *kJDDitherType = "JJJJ_dither_type";
static const char *kJDPaperRect = "JJJJ_paper_rect";
static const char* kJDPrintableRect = "JJJJ_printable_rect";
static const char* kJDPageSelection = "JJJJ_page_selection";
static const char* kJDMarginUnit = "JJJJ_margin_unit";
static const char* kJDPhysicalRect = "JJJJ_physical_rect";
static const char* kJDScaledPhysicalRect = "JJJJ_scaled_physical_rect";
JobData::JobData(BMessage *msg, const PrinterCap *cap, Settings settings)
{
@@ -72,6 +75,9 @@ JobData::JobData(const JobData &job_data)
fColor = job_data.fColor;
fDitherType = job_data.fDitherType;
fPageSelection = job_data.fPageSelection;
fMarginUnit = job_data.fMarginUnit;
fPhysicalRect = job_data.fPhysicalRect;
fScaledPhysicalRect = job_data.fScaledPhysicalRect;
}
JobData &JobData::operator = (const JobData &job_data)
@@ -102,6 +108,9 @@ JobData &JobData::operator = (const JobData &job_data)
fColor = job_data.fColor;
fDitherType = job_data.fDitherType;
fPageSelection = job_data.fPageSelection;
fMarginUnit = job_data.fMarginUnit;
fPhysicalRect = job_data.fPhysicalRect;
fScaledPhysicalRect = job_data.fScaledPhysicalRect;
return *this;
}
@@ -165,6 +174,14 @@ void JobData::load(BMessage *msg, const PrinterCap *cap, Settings settings)
fScaledPrintableRect = msg->FindRect(kJDScaledPrintableRect);
}
if (msg->HasRect(kJDPhysicalRect)) {
fPhysicalRect = msg->FindRect(kJDPhysicalRect);
}
if (msg->HasRect(kJDScaledPhysicalRect)) {
fScaledPhysicalRect = msg->FindRect(kJDScaledPhysicalRect);
}
if (msg->HasInt32(kJDFirstPage))
fFirstPage = msg->FindInt32(kJDFirstPage);
else
@@ -245,6 +262,11 @@ void JobData::load(BMessage *msg, const PrinterCap *cap, Settings settings)
fPageSelection = (PageSelection)msg->FindInt32(kJDPageSelection);
else
fPageSelection = kAllPages;
if (msg->HasInt32(kJDMarginUnit))
fMarginUnit = (MarginUnit)msg->FindInt32(kJDMarginUnit);
else
fMarginUnit = kUnitInch;
}
void JobData::save(BMessage *msg)
@@ -299,6 +321,21 @@ void JobData::save(BMessage *msg)
else
msg->AddRect(kJDScaledPrintableRect, fScaledPrintableRect);
if (msg->HasRect(kJDPhysicalRect))
msg->ReplaceRect(kJDPhysicalRect, fPhysicalRect);
else
msg->AddRect(kJDPhysicalRect, fPhysicalRect);
if (msg->HasRect(kJDScaledPhysicalRect))
msg->ReplaceRect(kJDScaledPhysicalRect, fScaledPhysicalRect);
else
msg->AddRect(kJDScaledPhysicalRect, fScaledPhysicalRect);
if (msg->HasInt32(kJDMarginUnit))
msg->ReplaceInt32(kJDMarginUnit, fMarginUnit);
else
msg->AddInt32(kJDMarginUnit, fMarginUnit);
// page settings end here; don't store job settings in message
if (fSettings == kPageSettings) return;
@@ -649,6 +649,8 @@ JobSetupView::AttachedToWindow()
fDuplex->SetValue(B_CONTROL_ON);
}
fDuplex->SetTarget(this);
} else {
fDuplex = NULL;
}
/* copies */
@@ -717,7 +719,8 @@ JobSetupView::UpdateButtonEnabledState()
fFromPage->SetEnabled(pageRangeEnabled);
fToPage->SetEnabled(pageRangeEnabled);
bool pageSelectionEnabled = fDuplex->Value() != B_CONTROL_ON;
bool pageSelectionEnabled = fDuplex == NULL ||
fDuplex->Value() != B_CONTROL_ON;
fAllPages->SetEnabled(pageSelectionEnabled);
fOddNumberedPages->SetEnabled(pageSelectionEnabled);
fEvenNumberedPages->SetEnabled(pageSelectionEnabled);
@@ -0,0 +1,728 @@
/*
MarginView.cpp
Copyright (c) 2002 OpenBeOS.
Authors:
Philippe Houdoin
Simon Gauvin
Michael Pfeiffer
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Todo:
2 Make Strings constants or UI resources
*/
#ifndef MARGIN_VIEW_H
#include "MarginView.h"
#endif
#include <AppKit.h>
#include <SupportKit.h>
#include <stdio.h>
#include <stdlib.h>
/*----------------- MarginView Private Constants --------------------*/
const int kOffsetY = 20;
const int kOffsetX = 10;
const int kStringSize = 50;
const int kWidth = 50;
const int kNumCount = 10;
const static float kPointUnits = 1; // 1 point = 1 point
const static float kInchUnits = 72; // 1" = 72 points
const static float kCMUnits = 28.346; // 72/2.54 1cm = 28.346 points
const static float kMinFieldWidth = 100; // pixels
const static float kMinUnitHeight = 30; // pixels
const static float kUnitFormat[] = { kInchUnits, kCMUnits, kPointUnits };
const static char *kUnitNames[] = { "Inch", "cm", "Points", NULL };
const static MarginUnit kUnitMsg[] = { kUnitInch,
kUnitCM,
kUnitPoint };
const pattern kDots = {{ 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 }};
const rgb_color kBlack = { 0,0,0,0 };
const rgb_color kRed = { 255,0,0,0 };
const rgb_color kWhite = { 255,255,255,0 };
const rgb_color kGray = { 220,220,220,0 };
/*----------------- MarginView Public Methods --------------------*/
/**
* Constructor
*
* @param frame, BRect that is the size of the view passed to the superclase
* @param pageWidth, float that is the points value of the page width
* @param pageHeight, float that is the points value of the page height
* @param margins, BRect values of margins
* @param units, unit32 enum for units used in view
* @return void
*/
MarginView::MarginView(BRect frame,
int32 pageWidth,
int32 pageHeight,
BRect margins,
MarginUnit units)
:BBox(frame, NULL, B_FOLLOW_ALL)
{
fMarginUnit = units;
fUnitValue = kUnitFormat[units];
SetLabel("Margins");
fMaxPageHeight = frame.Height() - kMinUnitHeight - kOffsetY;
fMaxPageWidth = frame.Width() - kMinFieldWidth - kOffsetX;
fMargins = margins;
fPageWidth = pageWidth;
fPageHeight = pageHeight;
}
/**
* Destructor
*
* @param none
* @return void
*/
MarginView::~MarginView() {
}
/*----------------- MarginView Public BeOS Hook Methods --------------------*/
/**
* Draw
*
* @param BRect, the draw bounds
* @return void
*/
void
MarginView::Draw(BRect rect)
{
BBox::Draw(rect);
float y_offset = (float)kOffsetY;
float x_offset = (float)kOffsetX;
BRect r;
// Calculate offsets depending on orientation
if (fPageWidth < fPageHeight) { // Portrait
x_offset = (fMaxPageWidth/2 + kOffsetX) - fViewWidth/2;
} else { // landscape
y_offset = (fMaxPageHeight/2 + kOffsetY) - fViewHeight/2;
}
// draw the page
SetHighColor(kWhite);
r = BRect(0, 0, fViewWidth, fViewHeight);
r.OffsetBy(x_offset, y_offset);
FillRect(r);
SetHighColor(kBlack);
StrokeRect(r);
// draw margin
SetHighColor(kRed);
SetLowColor(kWhite);
r.top += fMargins.top;
r.right -= fMargins.right;
r.bottom -= fMargins.bottom;
r.left += fMargins.left;
StrokeRect(r, kDots);
// draw the page size label
SetHighColor(kBlack);
SetLowColor(kGray);
char str[kStringSize];
sprintf(str, "%2.1f x %2.1f", fPageWidth/fUnitValue, fPageHeight/fUnitValue);
SetFontSize(10);
DrawString((const char *)str, BPoint(x_offset, fMaxPageHeight + 40));
}
/**
* BeOS Hook Function, change the size of the margin display
*
* @param width of the page
* @param height the page
* @return void
*/
void
MarginView::FrameResized(float width, float height)
{
fMaxPageHeight = height - kMinUnitHeight - kOffsetX;
fMaxPageWidth = width - kMinFieldWidth - kOffsetY;
CalculateViewSize(MARGIN_CHANGED);
Invalidate();
}
/**
* AttachToWindow
*
* @param none
* @return void
*/
void
MarginView::AttachedToWindow()
{
if (Parent()) {
SetViewColor(Parent()->ViewColor());
}
ConstructGUI();
}
/*----------------- MarginView Public Methods --------------------*/
/**
* GetUnits
*
* @param none
* @return uint32 enum, units in inches, cm, points
*/
MarginUnit
MarginView::GetMarginUnit(void) {
return fMarginUnit;
}
/**
* UpdateView, recalculate and redraw the view
*
* @param msg is a message to the calculate size to tell which field caused
* the update to occur, or it is a general update.
* @return void
*/
void
MarginView::UpdateView(uint32 msg)
{
Window()->Lock();
CalculateViewSize(msg); // nur Preview in Margins BBox!
Invalidate();
Window()->Unlock();
}
/**
* SetPageSize
*
* @param pageWidth, float that is the unit value of the page width
* @param pageHeight, float that is the unit value of the page height
* @return void
*/
void
MarginView::SetPageSize(float pageWidth, float pageHeight)
{
fPageWidth = pageWidth;
fPageHeight = pageHeight;
}
/**
* GetPageSize
*
* @param none
* @return BPoint, contains actual point values of page in x, y of point
*/
BPoint
MarginView::GetPageSize(void) {
return BPoint(fPageWidth, fPageHeight);
}
/**
* GetMargin
*
* @param none
* @return rect, return margin values always in points
*/
BRect
MarginView::GetMargin(void)
{
BRect margin;
// convert the field text to values
float ftop = atof(fTop->Text());
float fright = atof(fRight->Text());
float fleft = atof(fLeft->Text());
float fbottom = atof(fBottom->Text());
// convert to units to points
switch (fMarginUnit)
{
case kUnitInch:
// convert to points
ftop *= kInchUnits;
fright *= kInchUnits;
fleft *= kInchUnits;
fbottom *= kInchUnits;
break;
case kUnitCM:
// convert to points
ftop *= kCMUnits;
fright *= kCMUnits;
fleft *= kCMUnits;
fbottom *= kCMUnits;
break;
case kUnitPoint:
break;
}
margin.Set(fleft, ftop, fright, fbottom);
return margin;
}
/**
* MesssageReceived()
*
* Receive messages for the view
*
* @param BMessage* , the message being received
* @return void
*/
void
MarginView::MessageReceived(BMessage *msg)
{
switch (msg->what)
{
case CHANGE_PAGE_SIZE: {
float w;
float h;
msg->FindFloat("width", &w);
msg->FindFloat("height", &h);
SetPageSize(w, h);
UpdateView(MARGIN_CHANGED);
}
break;
case FLIP_PAGE: {
BPoint p;
p = GetPageSize();
SetPageSize(p.y, p.x);
UpdateView(MARGIN_CHANGED);
}
break;
case MARGIN_CHANGED:
UpdateView(MARGIN_CHANGED);
break;
case TOP_MARGIN_CHANGED:
UpdateView(TOP_MARGIN_CHANGED);
break;
case LEFT_MARGIN_CHANGED:
UpdateView(LEFT_MARGIN_CHANGED);
break;
case RIGHT_MARGIN_CHANGED:
UpdateView(RIGHT_MARGIN_CHANGED);
break;
case BOTTOM_MARGIN_CHANGED:
UpdateView(BOTTOM_MARGIN_CHANGED);
break;
case MARGIN_UNIT_CHANGED:
{
int32 marginUnit;
if (msg->FindInt32("marginUnit", &marginUnit) == B_OK) {
SetMarginUnit((MarginUnit)marginUnit);
}
}
break;
default:
BView::MessageReceived(msg);
break;
}
}
/*----------------- MarginView Private Methods --------------------*/
/**
* ConstructGUI()
*
* Creates the GUI for the View. MUST be called AFTER the View is attached to
* the Window, or will crash and/or create strange behaviour
*
* @param none
* @return void
*/
void
MarginView::ConstructGUI()
{
BMessage *msg;
BString str;
BMenuItem *item;
BMenuField *mf;
BPopUpMenu *menu;
// Create text fields
msg = new BMessage(MARGIN_CHANGED);
BRect r(Frame().Width() - be_plain_font->StringWidth("Top#") - kWidth,
kOffsetY, Frame().Width() - kOffsetX, kWidth);
// top
str << fMargins.top/fUnitValue;
fTop = new BTextControl( r, "top", "Top:", str.String(), NULL,
B_FOLLOW_RIGHT);
fTop->SetModificationMessage(new BMessage(TOP_MARGIN_CHANGED));
fTop->SetDivider(be_plain_font->StringWidth("Top#"));
fTop->SetTarget(this);
AllowOnlyNumbers(fTop, kNumCount);
AddChild(fTop);
//left
r.OffsetBy(0, kOffsetY);
r.left = Frame().Width() - be_plain_font->StringWidth("Left#") - kWidth;
str = "";
str << fMargins.left/fUnitValue;
fLeft = new BTextControl( r, "left", "Left:", str.String(), NULL,
B_FOLLOW_RIGHT);
fLeft->SetModificationMessage(new BMessage(LEFT_MARGIN_CHANGED));
fLeft->SetDivider(be_plain_font->StringWidth("Left#"));
fLeft->SetTarget(this);
AllowOnlyNumbers(fLeft, kNumCount);
AddChild(fLeft);
//bottom
r.OffsetBy(0, kOffsetY);
r.left = Frame().Width() - be_plain_font->StringWidth("Bottom#") - kWidth;
str = "";
str << fMargins.bottom/fUnitValue;
fBottom = new BTextControl( r, "bottom", "Bottom:", str.String(), NULL,
B_FOLLOW_RIGHT);
fBottom->SetModificationMessage(new BMessage(BOTTOM_MARGIN_CHANGED));
fBottom->SetDivider(be_plain_font->StringWidth("Bottom#"));
fBottom->SetTarget(this);
AllowOnlyNumbers(fBottom, kNumCount);
AddChild(fBottom);
//right
r.OffsetBy(0, kOffsetY);
r.left = Frame().Width() - be_plain_font->StringWidth("Right#") - kWidth;
str = "";
str << fMargins.right/fUnitValue;
fRight = new BTextControl( r, "right", "Right:", str.String(), NULL,
B_FOLLOW_RIGHT);
fRight->SetModificationMessage(new BMessage(RIGHT_MARGIN_CHANGED));
fRight->SetDivider(be_plain_font->StringWidth("Right#"));
fRight->SetTarget(this);
AllowOnlyNumbers(fRight, kNumCount);
AddChild(fRight);
// Create Units popup
r.OffsetBy(-kOffsetX, kOffsetY);
r.right += kOffsetY;
menu = new BPopUpMenu("units");
mf = new BMenuField(r, "units", "Units", menu,
B_FOLLOW_BOTTOM|B_FOLLOW_RIGHT|B_WILL_DRAW);
mf->ResizeToPreferred();
mf->SetDivider(be_plain_font->StringWidth("Units#"));
// Construct menu items
for (int i=0; kUnitNames[i] != NULL; i++ )
{
msg = new BMessage(MARGIN_UNIT_CHANGED);
msg->AddInt32("marginUnit", kUnitMsg[i]);
menu->AddItem(item = new BMenuItem(kUnitNames[i], msg));
item->SetTarget(this);
if (fMarginUnit == kUnitMsg[i]) {
item->SetMarked(true);
}
}
AddChild(mf);
// calculate the sizes for drawing page view
CalculateViewSize(MARGIN_CHANGED);
}
/**
* AllowOnlyNumbers()
*
* @param BTextControl, the control we want to only allow numbers
* @param maxNum, the maximun number of characters allowed
* @return void
*/
void
MarginView::AllowOnlyNumbers(BTextControl *textControl, int maxNum)
{
BTextView *tv = textControl->TextView();
for (long i = 0; i < 256; i++) {
tv->DisallowChar(i);
}
for (long i = '0'; i <= '9'; i++) {
tv->AllowChar(i);
}
tv->AllowChar(B_BACKSPACE);
tv->AllowChar('.');
tv->SetMaxBytes(maxNum);
}
/**
* SetMargin
*
* @param brect, margin values in rect
* @return void
*/
void
MarginView::SetMargin(BRect margin) {
fMargins = margin;
}
/**
* SetUnits, called by the MarginMgr when the units popup is selected
*
* @param uint32, the enum that identifies the units requested to change to.
* @return void
*/
void
MarginView::SetMarginUnit(MarginUnit unit)
{
// do nothing if the current units are the same as requested
if (unit == fMarginUnit) {
return;
}
// set the units Format
fUnitValue = kUnitFormat[unit];
// convert the field text to values
float ftop = atof(fTop->Text());
float fright = atof(fRight->Text());
float fleft = atof(fLeft->Text());
float fbottom = atof(fBottom->Text());
// convert to target units
switch (fMarginUnit)
{
case kUnitInch:
// convert to points
ftop *= kInchUnits;
fright *= kInchUnits;
fleft *= kInchUnits;
fbottom *= kInchUnits;
// check for target unit is cm
if (unit == kUnitCM) {
ftop /= kCMUnits;
fright /= kCMUnits;
fleft /= kCMUnits;
fbottom /= kCMUnits;
}
break;
case kUnitCM:
// convert to points
ftop *= kCMUnits;
fright *= kCMUnits;
fleft *= kCMUnits;
fbottom *= kCMUnits;
// check for target unit is inches
if (unit == kUnitInch) {
ftop /= kInchUnits;
fright /= kInchUnits;
fleft /= kInchUnits;
fbottom /= kInchUnits;
}
break;
case kUnitPoint:
// check for target unit is cm
if (unit == kUnitCM) {
ftop /= kCMUnits;
fright /= kCMUnits;
fleft /= kCMUnits;
fbottom /= kCMUnits;
}
// check for target unit is inches
if (unit == kUnitInch) {
ftop /= kInchUnits;
fright /= kInchUnits;
fleft /= kInchUnits;
fbottom /= kInchUnits;
}
break;
}
fMarginUnit = unit;
// lock Window since these changes are from another thread
Window()->Lock();
// set the fields to new units
BString str;
str << ftop;
fTop->SetText(str.String());
str = "";
str << fleft;
fLeft->SetText(str.String());
str = "";
str << fright;
fRight->SetText(str.String());
str = "";
str << fbottom;
fBottom->SetText(str.String());
// update UI
CalculateViewSize(MARGIN_CHANGED);
Invalidate();
Window()->Unlock();
}
/**
* CalculateViewSize
*
* calculate the size of the view that is used
* to show the page inside the margin box. This is dependent
* on the size of the box and the room we have to show it and
* the units that we are using and the orientation of the page.
*
* @param msg, the message for which field changed to check value bounds
* @return void
*/
void
MarginView::CalculateViewSize(uint32 msg)
{
// determine page orientation
if (fPageHeight < fPageWidth) { // LANDSCAPE
fViewWidth = fMaxPageWidth;
fViewHeight = fPageHeight * (fViewWidth/fPageWidth);
float hdiff = fViewHeight - fMaxPageHeight;
if (hdiff > 0) {
fViewHeight -= hdiff;
fViewWidth -= hdiff;
}
} else { // PORTRAIT
fViewHeight = fMaxPageHeight;
fViewWidth = fPageWidth * (fViewHeight/fPageHeight);
float wdiff = fViewWidth - fMaxPageWidth;
if (wdiff > 0) {
fViewHeight -= wdiff;
fViewWidth -= wdiff;
}
}
// calculate margins based on view size
// find the length of 1 pixel in points
// ex: 80px/800pt = 0.1px/pt
float pixelLength = fViewHeight/fPageHeight;
// convert the margins to points
// The text field will have a number that us in the current unit
// ex 0.2" * 72pt = 14.4pts
float ftop = atof(fTop->Text()) * fUnitValue;
float fright = atof(fRight->Text()) * fUnitValue;
float fbottom = atof(fBottom->Text()) * fUnitValue;
float fleft = atof(fLeft->Text()) * fUnitValue;
// Check that the margins don't overlap each other...
float ph = fPageHeight;
float pw = fPageWidth;
BString str;
// Bounds calculation rules:
if (msg == TOP_MARGIN_CHANGED)
{
// top must be <= bottom
if (ftop > (ph - fbottom)) {
ftop = ph - fbottom;
str = "";
str << ftop / fUnitValue;
Window()->Lock();
fTop->SetText(str.String());
Window()->Unlock();
}
}
if (msg == BOTTOM_MARGIN_CHANGED)
{
// bottom must be <= pageHeight
if (fbottom > (ph - ftop)) {
fbottom = ph - ftop;
str = "";
str << fbottom / fUnitValue;
Window()->Lock();
fBottom->SetText(str.String());
Window()->Unlock();
}
}
if (msg == LEFT_MARGIN_CHANGED)
{
// left must be <= right
if (fleft > (pw - fright)) {
fleft = pw - fright;
str = "";
str << fleft / fUnitValue;
Window()->Lock();
fLeft->SetText(str.String());
Window()->Unlock();
}
}
if (msg == RIGHT_MARGIN_CHANGED)
{
// right must be <= fPageWidth
if (fright > (pw - fleft)) {
fright = pw - fleft;
str = "";
str << fright / fUnitValue;
Window()->Lock();
fRight->SetText(str.String());
Window()->Unlock();
}
}
// convert the unit value to pixels
// ex: 14.4pt * 0.1px/pt = 1.44px
fMargins.top = ftop * pixelLength;
fMargins.right = fright * pixelLength;
fMargins.bottom = fbottom * pixelLength;
fMargins.left = fleft * pixelLength;
}
@@ -14,6 +14,7 @@
#include <Bitmap.h>
#include <Box.h>
#include <Button.h>
#include <Font.h>
#include <Looper.h>
#include <MessageFilter.h>
#include <MenuField.h>
@@ -25,15 +26,17 @@
#include <RadioButton.h>
#include <Rect.h>
#include <String.h>
#include <SupportDefs.h>
#include <TextControl.h>
#include <View.h>
#include "PageSetupDlg.h"
#include "BeUtils.h"
#include "DbgMsg.h"
#include "JobData.h"
#include "MarginView.h"
#include "PageSetupDlg.h"
#include "PrinterData.h"
#include "PrinterCap.h"
#include "DbgMsg.h"
#include "BeUtils.h"
#if (!__MWERKS__ || defined(MSIPL_USING_NAMESPACE))
using namespace std;
@@ -41,30 +44,37 @@ using namespace std;
#define std
#endif
#define PAGESETUP_WIDTH 350
#define PAGESETUP_HEIGHT 135
#define MENU_HEIGHT 16
#define MENU_WIDTH 200
#define BUTTON_WIDTH 70
#define BUTTON_HEIGHT 20
#define TEXT_HEIGHT 16
#define ORIENT_H 10
#define ORIENT_V 10
#define ORIENT_WIDTH 100
#define ORIENT_HEIGHT 60
#define PORT_TEXT "Portrait"
#define RAND_TEXT "Landscape"
#define MARGIN_H 10
#define MARGIN_V 10
#define MARGIN_WIDTH 180
#define MARGIN_HEIGHT 140
#define PAPER_H ORIENT_H + ORIENT_WIDTH + 15
#define PAPER_V 20
#define PAPER_WIDTH 200
#define PAGESETUP_WIDTH MARGIN_H + MARGIN_WIDTH + 15 + MENU_WIDTH + 10
#define PAGESETUP_HEIGHT MARGIN_V + MARGIN_HEIGHT + BUTTON_HEIGHT + 20
#define PAPER_H MARGIN_H + MARGIN_WIDTH + 15
#define PAPER_V 10
#define PAPER_WIDTH MENU_WIDTH
#define PAPER_HEIGHT MENU_HEIGHT
#define PAPER_TEXT "Paper Size:"
#define ORIENT_H PAPER_H
#define ORIENT_V PAPER_V + 24
#define ORIENT_WIDTH MENU_WIDTH
#define ORIENT_HEIGHT MENU_HEIGHT
#define ORIENTATION_TEXT "Orientation:"
#define PORTRAIT_TEXT "Portrait"
#define LANDSCAPE_TEXT "Landscape"
#define RES_H PAPER_H
#define RES_V PAPER_V + 24
#define RES_WIDTH 150
#define RES_V ORIENT_V + 24
#define RES_WIDTH MENU_WIDTH
#define RES_HEIGHT MENU_HEIGHT
#define RES_TEXT "Resolution:"
@@ -84,15 +94,18 @@ using namespace std;
#define PRINT_LINE_V (PAGESETUP_HEIGHT - BUTTON_HEIGHT - 23)
const BRect ORIENTAION_RECT(
const BRect MARGIN_RECT(
MARGIN_H,
MARGIN_V,
MARGIN_H + MARGIN_WIDTH,
MARGIN_V + MARGIN_HEIGHT);
const BRect ORIENTATION_RECT(
ORIENT_H,
ORIENT_V,
ORIENT_H + ORIENT_WIDTH,
ORIENT_V + ORIENT_HEIGHT);
const BRect PORT_RECT(10, 15, 80, 14);
const BRect LAND_RECT(10, 35, 80, 14);
const BRect PAPER_RECT(
PAPER_H,
PAPER_V,
@@ -125,7 +138,9 @@ const BRect CANCEL_RECT(
enum MSGS {
kMsgCancel = 1,
kMsgOK
kMsgOK,
kMsgOrientationChanged,
kMsgPaperChanged,
};
PageSetupView::PageSetupView(BRect frame, JobData *job_data, PrinterData *printer_data, const PrinterCap *printer_cap)
@@ -138,30 +153,47 @@ PageSetupView::~PageSetupView()
{
}
void PageSetupView::AttachedToWindow()
void
PageSetupView::AddOrientationItem(const char* name, JobData::Orientation orientation)
{
BMessage *msg = new BMessage(kMsgOrientationChanged);
msg->AddInt32("orientation", orientation);
BMenuItem *item = new BMenuItem(name, msg);
fOrientation->AddItem(item);
item->SetTarget(this);
if (fJobData->getOrientation() == orientation) {
item->SetMarked(true);
} else if (fOrientation->CountItems() == 1) {
item->SetMarked(true);
}
}
void
PageSetupView::AttachedToWindow()
{
BMenuItem *item = NULL;
BMenuField *menufield;
BMenuField *menuField;
BButton *button;
bool marked;
int count;
/* orientaion */
/* margin */
MarginUnit units = fJobData->getMarginUnit();
BRect paper = fJobData->getPaperRect();
BRect margin = fJobData->getPrintableRect();
BBox *box = new BBox(ORIENTAION_RECT);
AddChild(box);
box->SetLabel("Orientation");
// re-calculate the margin from the printable rect in points
margin.top -= paper.top;
margin.left -= paper.left;
margin.right = paper.right - margin.right;
margin.bottom = paper.bottom - margin.bottom;
fPortrait = new BRadioButton(PORT_RECT, "", PORT_TEXT, NULL);
box->AddChild(fPortrait);
BRadioButton *landscape = new BRadioButton(LAND_RECT, "", RAND_TEXT, NULL);
box->AddChild(landscape);
if (JobData::kPortrait == fJobData->getOrientation())
fPortrait->SetValue(B_CONTROL_ON);
else
landscape->SetValue(B_CONTROL_ON);
fMarginView = new MarginView(MARGIN_RECT,
paper.IntegerWidth(),
paper.IntegerHeight(),
margin, units);
AddChild(fMarginView);
/* paper selection */
@@ -171,7 +203,9 @@ void PageSetupView::AttachedToWindow()
count = fPrinterCap->countCap(PrinterCap::kPaper);
PaperCap **paper_cap = (PaperCap **)fPrinterCap->enumCap(PrinterCap::kPaper);
while (count--) {
item = new BMenuItem((*paper_cap)->label.c_str(), NULL);
BMessage *msg = new BMessage(kMsgPaperChanged);
msg->AddPointer("paperCap", *paper_cap);
item = new BMenuItem((*paper_cap)->label.c_str(), msg);
fPaper->AddItem(item);
item->SetTarget(this);
if ((*paper_cap)->paper == fJobData->getPaper()) {
@@ -182,10 +216,32 @@ void PageSetupView::AttachedToWindow()
}
if (!marked)
item->SetMarked(true);
menufield = new BMenuField(PAPER_RECT, "", PAPER_TEXT, fPaper);
AddChild(menufield);
menuField = new BMenuField(PAPER_RECT, "", PAPER_TEXT, fPaper);
AddChild(menuField);
float width = StringWidth(PAPER_TEXT) + 7;
menufield->SetDivider(width);
menuField->SetDivider(width);
/* orientaion */
fOrientation = new BPopUpMenu("orientation");
fOrientation->SetRadioMode(true);
menuField = new BMenuField(ORIENTATION_RECT, "orientation", ORIENTATION_TEXT, fOrientation);
menuField->SetDivider(width);
count = fPrinterCap->countCap(PrinterCap::kOrientation);
if (count == 0) {
AddOrientationItem(PORTRAIT_TEXT, JobData::kPortrait);
AddOrientationItem(LANDSCAPE_TEXT, JobData::kLandscape);
} else {
OrientationCap **orientation_cap = (OrientationCap **)fPrinterCap->enumCap(PrinterCap::kOrientation);
while (count--) {
AddOrientationItem((*orientation_cap)->label.c_str(),
(*orientation_cap)->orientation);
orientation_cap++;
}
}
AddChild(menuField);
/* resolution */
@@ -206,9 +262,9 @@ void PageSetupView::AttachedToWindow()
}
if (!marked)
item->SetMarked(true);
menufield = new BMenuField(RESOLUTION_RECT, "", RES_TEXT, fResolution);
AddChild(menufield);
menufield->SetDivider(width);
menuField = new BMenuField(RESOLUTION_RECT, "", RES_TEXT, fResolution);
AddChild(menuField);
menuField->SetDivider(width);
/* scale */
BString scale;
@@ -240,39 +296,51 @@ void PageSetupView::AttachedToWindow()
button->MakeDefault(true);
}
inline void swap(float *e1, float *e2)
inline void
swap(float *e1, float *e2)
{
float e = *e1;
*e1 = *e2;
*e2 = e;
}
bool PageSetupView::UpdateJobData()
JobData::Orientation
PageSetupView::GetOrientation()
{
if (B_CONTROL_ON == fPortrait->Value()) {
fJobData->setOrientation(JobData::kPortrait);
BMenuItem *item = fOrientation->FindMarked();
int32 orientation;
if (item != NULL &&
item->Message()->FindInt32("orientation", &orientation) == B_OK) {
return (JobData::Orientation)orientation;
} else {
fJobData->setOrientation(JobData::kLandscape);
return JobData::kPortrait;
}
}
BRect paper_rect;
BRect printable_rect;
PaperCap *
PageSetupView::GetPaperCap()
{
BMenuItem *item = fPaper->FindMarked();
void *pointer;
if (item != NULL &&
item->Message()->FindPointer("paperCap", &pointer) == B_OK) {
return (PaperCap*)pointer;
} else {
return (PaperCap*)fPrinterCap->getDefaultCap(PrinterCap::kPaper);
}
}
bool
PageSetupView::UpdateJobData()
{
fJobData->setOrientation(GetOrientation());
PaperCap *paperCap = GetPaperCap();
BRect paper_rect = paperCap->paper_rect;
BRect physical_rect = paperCap->physical_rect;
int count;
count = fPrinterCap->countCap(PrinterCap::kPaper);
PaperCap **paper_cap = (PaperCap **)fPrinterCap->enumCap(PrinterCap::kPaper);
const char *paper_label = fPaper->FindMarked()->Label();
while (count--) {
if (!strcmp((*paper_cap)->label.c_str(), paper_label)) {
fJobData->setPaper((*paper_cap)->paper);
paper_rect = (*paper_cap)->paper_rect;
printable_rect = (*paper_cap)->printable_rect;
break;
}
paper_cap++;
}
count = fPrinterCap->countCap(PrinterCap::kResolution);
ResolutionCap **resolution_cap = (ResolutionCap **)fPrinterCap->enumCap(PrinterCap::kResolution);
const char *resolution_label = fResolution->FindMarked()->Label();
@@ -285,11 +353,26 @@ bool PageSetupView::UpdateJobData()
resolution_cap++;
}
// adjust printable rect by margin
fJobData->setMarginUnit(fMarginView->GetMarginUnit());
BRect margin = fMarginView->GetMargin();
BRect printable_rect = margin;
printable_rect.right = paper_rect.right - margin.right;
printable_rect.bottom = paper_rect.bottom - margin.bottom;
printable_rect.left = max_c(printable_rect.left, physical_rect.left);
printable_rect.top = max_c(printable_rect.top, physical_rect.top);
printable_rect.right = min_c(printable_rect.right, physical_rect.right);
printable_rect.bottom = min_c(printable_rect.bottom, physical_rect.bottom);
if (JobData::kLandscape == fJobData->getOrientation()) {
swap(&paper_rect.left, &paper_rect.top);
swap(&paper_rect.right, &paper_rect.bottom);
swap(&printable_rect.left, &printable_rect.top);
swap(&printable_rect.right, &printable_rect.bottom);
swap(&physical_rect.left, &physical_rect.top);
swap(&physical_rect.right, &physical_rect.bottom);
}
float scaling = atoi(fScaling->Text());
@@ -307,11 +390,35 @@ bool PageSetupView::UpdateJobData()
fJobData->setScaledPaperRect(ScaleRect(paper_rect, scalingR));
fJobData->setPrintableRect(printable_rect);
fJobData->setScaledPrintableRect(ScaleRect(printable_rect, scalingR));
fJobData->setPhysicalRect(physical_rect);
fJobData->setScaledPhysicalRect(ScaleRect(physical_rect, scalingR));
fJobData->save();
return true;
}
void
PageSetupView::MessageReceived(BMessage *msg)
{
switch (msg->what) {
case kMsgPaperChanged:
case kMsgOrientationChanged:
{
JobData::Orientation orientation = GetOrientation();
PaperCap *paperCap = GetPaperCap();
float width = paperCap->paper_rect.Width();
float height = paperCap->paper_rect.Height();
if (orientation != JobData::kPortrait) {
swap(&width, &height);
}
fMarginView->SetPageSize(width, height);
fMarginView->UpdateView(MARGIN_CHANGED);
}
break;
}
}
//====================================================================
PageSetupDlg::PageSetupDlg(JobData *job_data, PrinterData *printer_data, const PrinterCap *printer_cap)
@@ -331,7 +438,8 @@ PageSetupDlg::PageSetupDlg(JobData *job_data, PrinterData *printer_data, const P
SetResult(B_ERROR);
}
void PageSetupDlg::MessageReceived(BMessage *msg)
void
PageSetupDlg::MessageReceived(BMessage *msg)
{
switch (msg->what) {
case kMsgOK:
@@ -195,7 +195,17 @@ PrinterDriverInstance::~PrinterDriverInstance()
char *add_printer(char *printerName)
{
PrinterDriverInstance instance;
BPath path;
BNode folder;
BNode* spoolFolder = NULL;
// get spool folder
if (find_directory(B_USER_PRINTERS_DIRECTORY, &path) == B_OK &&
path.Append(printerName) == B_OK &&
folder.SetTo(path.Path()) == B_OK) {
spoolFolder = &folder;
}
PrinterDriverInstance instance(spoolFolder);
return instance.GetPrinterDriver()->AddPrinter(printerName);
}