diff --git a/headers/private/print/libprint/JobData.h b/headers/private/print/libprint/JobData.h index 4798268c7c..236a7b212e 100644 --- a/headers/private/print/libprint/JobData.h +++ b/headers/private/print/libprint/JobData.h @@ -11,6 +11,7 @@ #include #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 */ diff --git a/headers/private/print/libprint/MarginView.h b/headers/private/print/libprint/MarginView.h new file mode 100644 index 0000000000..88db6a055e --- /dev/null +++ b/headers/private/print/libprint/MarginView.h @@ -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 +#include + +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 diff --git a/headers/private/print/libprint/PageSetupDlg.h b/headers/private/print/libprint/PageSetupDlg.h index 0c3576098d..659098cf61 100644 --- a/headers/private/print/libprint/PageSetupDlg.h +++ b/headers/private/print/libprint/PageSetupDlg.h @@ -8,12 +8,15 @@ #include #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 { diff --git a/headers/private/print/libprint/PrinterCap.h b/headers/private/print/libprint/PrinterCap.h index b2ca00b11c..f47d27a345 100644 --- a/headers/private/print/libprint/PrinterCap.h +++ b/headers/private/print/libprint/PrinterCap.h @@ -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; diff --git a/src/add-ons/print/drivers/shared/libprint/GraphicsDriver.cpp b/src/add-ons/print/drivers/shared/libprint/GraphicsDriver.cpp index e28d91b7d5..aa3a3ae130 100644 --- a/src/add-ons/print/drivers/shared/libprint/GraphicsDriver.cpp +++ b/src/add-ons/print/drivers/shared/libprint/GraphicsDriver.cpp @@ -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 { diff --git a/src/add-ons/print/drivers/shared/libprint/Jamfile b/src/add-ons/print/drivers/shared/libprint/Jamfile index 404398deec..eb866a548c 100644 --- a/src/add-ons/print/drivers/shared/libprint/Jamfile +++ b/src/add-ons/print/drivers/shared/libprint/Jamfile @@ -15,6 +15,7 @@ StaticLibrary print : JSDSlider.cpp JobData.cpp JobSetupDlg.cpp + MarginView.cpp PackBits.cpp PageSetupDlg.cpp PagesView.cpp diff --git a/src/add-ons/print/drivers/shared/libprint/JobData.cpp b/src/add-ons/print/drivers/shared/libprint/JobData.cpp index 204f7fdf78..0e421a5275 100644 --- a/src/add-ons/print/drivers/shared/libprint/JobData.cpp +++ b/src/add-ons/print/drivers/shared/libprint/JobData.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; diff --git a/src/add-ons/print/drivers/shared/libprint/JobSetupDlg.cpp b/src/add-ons/print/drivers/shared/libprint/JobSetupDlg.cpp index d1dc3e11f3..64c563fafc 100644 --- a/src/add-ons/print/drivers/shared/libprint/JobSetupDlg.cpp +++ b/src/add-ons/print/drivers/shared/libprint/JobSetupDlg.cpp @@ -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); diff --git a/src/add-ons/print/drivers/shared/libprint/MarginView.cpp b/src/add-ons/print/drivers/shared/libprint/MarginView.cpp new file mode 100644 index 0000000000..e15940d3f8 --- /dev/null +++ b/src/add-ons/print/drivers/shared/libprint/MarginView.cpp @@ -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 +#include + +#include +#include + +/*----------------- 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; +} + + diff --git a/src/add-ons/print/drivers/shared/libprint/PageSetupDlg.cpp b/src/add-ons/print/drivers/shared/libprint/PageSetupDlg.cpp index 1fb04c6d3c..1a63c12ac8 100644 --- a/src/add-ons/print/drivers/shared/libprint/PageSetupDlg.cpp +++ b/src/add-ons/print/drivers/shared/libprint/PageSetupDlg.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -25,15 +26,17 @@ #include #include #include +#include #include #include -#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: diff --git a/src/add-ons/print/drivers/shared/libprint/PrinterDriver.cpp b/src/add-ons/print/drivers/shared/libprint/PrinterDriver.cpp index 069e6b7854..9fdda350dd 100644 --- a/src/add-ons/print/drivers/shared/libprint/PrinterDriver.cpp +++ b/src/add-ons/print/drivers/shared/libprint/PrinterDriver.cpp @@ -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); }