diff options
-rwxr-xr-x | vcl/aqua/inc/aquaprintview.h | 18 | ||||
-rw-r--r-- | vcl/aqua/inc/salprn.h | 18 | ||||
-rw-r--r-- | vcl/aqua/source/gdi/aquaprintaccessoryview.mm | 596 | ||||
-rwxr-xr-x | vcl/aqua/source/gdi/aquaprintview.mm | 10 | ||||
-rw-r--r-- | vcl/aqua/source/gdi/makefile.mk | 1 | ||||
-rw-r--r-- | vcl/aqua/source/gdi/salprn.cxx | 124 | ||||
-rw-r--r-- | vcl/inc/vcl/print.h | 13 | ||||
-rw-r--r-- | vcl/inc/vcl/print.hxx | 112 | ||||
-rw-r--r-- | vcl/inc/vcl/prndlg.hxx | 172 | ||||
-rw-r--r-- | vcl/inc/vcl/salprn.hxx | 6 | ||||
-rw-r--r-- | vcl/inc/vcl/svdata.hxx | 3 | ||||
-rw-r--r-- | vcl/inc/vcl/svids.hrc | 47 | ||||
-rw-r--r-- | vcl/prj/d.lst | 1 | ||||
-rw-r--r-- | vcl/source/app/salvtables.cxx | 2 | ||||
-rw-r--r-- | vcl/source/app/svdata.cxx | 11 | ||||
-rw-r--r-- | vcl/source/gdi/impprn.cxx | 2 | ||||
-rw-r--r-- | vcl/source/gdi/makefile.mk | 2 | ||||
-rw-r--r-- | vcl/source/gdi/print.cxx | 4 | ||||
-rw-r--r-- | vcl/source/gdi/print3.cxx | 672 | ||||
-rw-r--r-- | vcl/source/src/makefile.mk | 5 | ||||
-rw-r--r-- | vcl/source/src/print.src | 277 | ||||
-rw-r--r-- | vcl/source/src/stdtext.src | 7 | ||||
-rw-r--r-- | vcl/source/window/makefile.mk | 3 | ||||
-rw-r--r-- | vcl/source/window/printdlg.cxx | 1054 |
24 files changed, 3035 insertions, 125 deletions
diff --git a/vcl/aqua/inc/aquaprintview.h b/vcl/aqua/inc/aquaprintview.h index c5ce20c17425..294a6492869d 100755 --- a/vcl/aqua/inc/aquaprintview.h +++ b/vcl/aqua/inc/aquaprintview.h @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: aquaprintview.h,v $ - * $Revision: 1.3 $ + * $Revision: 1.3.114.1 $ * * This file is part of OpenOffice.org. * @@ -35,20 +35,28 @@ #include <Cocoa/Cocoa.h> #include "postmac.h" -class ImplQPrinter; +#include "vcl/print.hxx" + class AquaSalInfoPrinter; +namespace vcl { class PrinterListener; } @interface AquaPrintView : NSView { - ImplQPrinter* mpQPrinter; - AquaSalInfoPrinter* mpInfoPrinter; + vcl::PrinterListener* mpListener; + AquaSalInfoPrinter* mpInfoPrinter; } --(id)initWithQPrinter: (ImplQPrinter*)pPrinter withInfoPrinter: (AquaSalInfoPrinter*)pInfoPrinter; +-(id)initWithListener: (vcl::PrinterListener*)pListener withInfoPrinter: (AquaSalInfoPrinter*)pInfoPrinter; -(MacOSBOOL)knowsPageRange: (NSRangePointer)range; -(NSRect)rectForPage: (int)page; -(NSPoint)locationOfPrintRect: (NSRect)aRect; -(void)drawRect: (NSRect)rect; @end +@interface AquaPrintAccessoryView : NSObject +{ +} ++(NSObject*)setupPrinterPanel: (NSPrintOperation*)pOp withListener: (vcl::PrinterListener*)pListener; +@end + #endif diff --git a/vcl/aqua/inc/salprn.h b/vcl/aqua/inc/salprn.h index ec08261e8321..8bfa8ac98cae 100644 --- a/vcl/aqua/inc/salprn.h +++ b/vcl/aqua/inc/salprn.h @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: salprn.h,v $ - * $Revision: 1.12 $ + * $Revision: 1.12.56.1 $ * * This file is part of OpenOffice.org. * @@ -104,10 +104,10 @@ class AquaSalInfoPrinter : public SalInfoPrinter // so let's make AquaSalPrinter just a forwarder to AquaSalInfoPrinter // and concentrate the real work in one class // implement pull model print system - BOOL StartJob( const String* pFileName, - const String& rAppName, - ImplJobSetup* pSetupData, - ImplQPrinter* pQPrinter, + BOOL StartJob( const String* i_pFileName, + const String& i_rAppName, + ImplJobSetup* i_pSetupData, + vcl::PrinterListener& i_rListener, bool bIsQuickJob ); BOOL EndJob(); BOOL AbortJob(); @@ -142,10 +142,10 @@ class AquaSalPrinter : public SalPrinter ULONG i_nCopies, BOOL i_bCollate, ImplJobSetup* i_pSetupData ); // implement pull model print system - virtual BOOL StartJob( const String* pFileName, - const String& rAppName, - ImplJobSetup* pSetupData, - ImplQPrinter* pQPrinter ); + virtual BOOL StartJob( const String* i_pFileName, + const String& i_rAppName, + ImplJobSetup* i_pSetupData, + vcl::PrinterListener& i_rListener ); virtual BOOL EndJob(); virtual BOOL AbortJob(); diff --git a/vcl/aqua/source/gdi/aquaprintaccessoryview.mm b/vcl/aqua/source/gdi/aquaprintaccessoryview.mm new file mode 100644 index 000000000000..b7aa9f660dbd --- /dev/null +++ b/vcl/aqua/source/gdi/aquaprintaccessoryview.mm @@ -0,0 +1,596 @@ +/************************************************************************ + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: aquaprintview.mm,v $ + * $Revision: 1.5.56.1 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_vcl.hxx" + +#include "aquaprintview.h" +#include "salinst.h" +#include "vcl/print.hxx" + +#include <map> + +using namespace vcl; +using namespace com::sun::star; +using namespace com::sun::star::beans; +using namespace com::sun::star::uno; + +#if 0 +/* below is some dark magic to inherit an NSViewController if running + on MacOS 10.5. However this is futile since as long as our base line is 10.4 + can use the deprecated method NSPrintOperation:setAccessoryView anyway. + The problem here is that as long as we're linked for 10.4, the print panel + will never show a preview and our accessory view at the same time. This is awful, + but since it was dictated by Apple that IT MUST BE SO it cannot be bad + + Anyway the code below (the load method) is really ugly, so perhaps it's better this way. +*/ + +#import <objc/objc-class.h> + +APPKIT_EXTERN NSString *NSPrintPanelAccessorySummaryItemNameKey; +APPKIT_EXTERN NSString *NSPrintPanelAccessorySummaryItemDescriptionKey; + +#include "osl/module.h" + +@interface AquaPrintViewController : NSObject +{ + NSArray* pAry; +} ++(void)load; +-(id)init; +-(void)dealloc; +-(NSArray *)localizedSummaryItems; +-(NSSet*)keyPathsForValuesAffectingPreview; +@end + +@implementation AquaPrintViewController ++(void)load +{ + struct objc_class *pClass = (struct objc_class *)[self class]; + Class superclass = NSClassFromString(@"NSViewController"); + + if(superclass != NULL) + { + pClass->super_class = superclass; + pClass->instance_size += superclass->instance_size; + } +} + +-(id)init +{ + if( (self = [super performSelector: @selector(initWithNibName:bundle:) withObject: nil withObject: nil]) ) + { + NSObject* pKeys[] = { NSPrintPanelAccessorySummaryItemNameKey, NSPrintPanelAccessorySummaryItemDescriptionKey }; + NSObject* pVals[] = { @"the Name", @"the summary value" }; + NSDictionary* pDict = [NSDictionary dictionaryWithObjects: pVals forKeys: pKeys count: 2]; + pAry = [NSArray arrayWithObject: pDict]; + } + return self; +} + +-(void)dealloc +{ + [pAry release]; + [super dealloc]; +} + +-(NSArray *)localizedSummaryItems +{ + return pAry; +} +-(NSSet*)keyPathsForValuesAffectingPreview +{ + return [NSSet set]; +} +@end + +#endif + +class ListenerProperties +{ + vcl::PrinterListener* mpListener; + std::map< int, rtl::OUString > maTagToPropertyName; + std::map< int, rtl::OUString > maTagToValueName; + int mnNextTag; + public: + ListenerProperties( vcl::PrinterListener* i_pListener ) + : mpListener( i_pListener ), mnNextTag( 0 ) + {} + + void updatePrintJob() + { + // TODO: refresh page count etc from mpListener + } + + int addNameTag( const rtl::OUString& i_rPropertyName ) + { + int nNewTag = mnNextTag++; + maTagToPropertyName[ nNewTag ] = i_rPropertyName; + return nNewTag; + } + + int addNameAndValueTag( const rtl::OUString& i_rPropertyName, const rtl::OUString& i_rValue ) + { + int nNewTag = mnNextTag++; + maTagToPropertyName[ nNewTag ] = i_rPropertyName; + maTagToValueName[ nNewTag ] = i_rValue; + return nNewTag; + } + + void changePropertyWithNamedValue( int i_nTag ) + { + std::map< int, rtl::OUString >::const_iterator name_it = maTagToPropertyName.find( i_nTag ); + std::map< int, rtl::OUString >::const_iterator value_it = maTagToValueName.find( i_nTag ); + if( name_it != maTagToPropertyName.end() && value_it != maTagToValueName.end() ) + { + PropertyValue* pVal = mpListener->getValue( name_it->second ); + if( pVal ) + { + pVal->Value <<= value_it->second; + updatePrintJob(); + } + } + } + + void changePropertyWithBoolValue( int i_nTag, sal_Bool i_bValue ) + { + std::map< int, rtl::OUString >::const_iterator name_it = maTagToPropertyName.find( i_nTag ); + if( name_it != maTagToPropertyName.end() ) + { + PropertyValue* pVal = mpListener->getValue( name_it->second ); + if( pVal ) + { + pVal->Value <<= i_bValue; + updatePrintJob(); + } + } + } +}; + +@interface ControlTarget : NSObject +{ + ListenerProperties* mpListener; +} +-(id)initWithListenerMap: (ListenerProperties*)pListener; +-(void)triggered:(id)pSender; +-(void)dealloc; +@end + +@implementation ControlTarget +-(id)initWithListenerMap: (ListenerProperties*)pListener +{ + if( (self = [super init]) ) + { + mpListener = pListener; + } + return self; +} +-(void)triggered:(id)pSender; +{ + if( [pSender isMemberOfClass: [NSPopUpButton class]] ) + { + NSPopUpButton* pBtn = (NSPopUpButton*)pSender; + NSMenuItem* pSelected = [pBtn selectedItem]; + if( pSelected ) + { + int nTag = [pSelected tag]; + mpListener->changePropertyWithNamedValue( nTag ); + } + } + else if( [pSender isMemberOfClass: [NSButton class]] ) + { + NSButton* pBtn = (NSButton*)pSender; + int nTag = [pBtn tag]; + mpListener->changePropertyWithBoolValue( nTag, [pBtn state] == NSOnState ); + } + else if( [pSender isMemberOfClass: [NSMatrix class]] ) + { + NSObject* pObj = [(NSMatrix*)pSender selectedCell]; + if( [pObj isMemberOfClass: [NSButtonCell class]] ) + { + NSButtonCell* pCell = (NSButtonCell*)pObj; + int nTag = [pCell tag]; + mpListener->changePropertyWithNamedValue( nTag ); + } + } + else + { + DBG_ERROR( "unsupported class" ); + } +} +-(void)dealloc +{ + delete mpListener; + [super dealloc]; +} +@end + +static void adjustViewAndChildren( NSView* pView, NSSize& rMaxSize ) +{ + NSArray* pSubViews = [pView subviews]; + unsigned int nViews = [pSubViews count]; + NSRect aUnion = { { 0, 0 }, { 0, 0 } }; + + // get the combined frame of all subviews + for( unsigned int n = 0; n < nViews; n++ ) + { + aUnion = NSUnionRect( aUnion, [[pSubViews objectAtIndex: n] frame] ); + } + + // move everything so it will fit + for( unsigned int n = 0; n < nViews; n++ ) + { + NSView* pCurSubView = [pSubViews objectAtIndex: n]; + NSRect aFrame = [pCurSubView frame]; + aFrame.origin.x -= aUnion.origin.x - 5; + aFrame.origin.y -= aUnion.origin.y - 5; + [pCurSubView setFrame: aFrame]; + } + + // resize the view itself + aUnion.size.height += 10; + aUnion.size.width += 10; + [pView setFrameSize: aUnion.size]; + + if( aUnion.size.width > rMaxSize.width ) + rMaxSize.width = aUnion.size.width; + if( aUnion.size.height > rMaxSize.height ) + rMaxSize.height = aUnion.size.height; +} + +@implementation AquaPrintAccessoryView ++(NSObject*)setupPrinterPanel: (NSPrintOperation*)pOp withListener: (vcl::PrinterListener*)pListener; +{ + ListenerProperties* pListenerProperties = new ListenerProperties( pListener ); + ControlTarget* pCtrlTarget = [[ControlTarget alloc] initWithListenerMap: pListenerProperties]; + + NSView* pCurParent = 0; + long nCurY = 0; + long nCurX = 0; + NSRect aViewFrame = { { 0, 0 }, {400, 400 } }; + NSSize aMaxTabSize = { 0, 0 }; + NSTabView* pTabView = [[NSTabView alloc] initWithFrame: aViewFrame]; + + const Sequence< PropertyValue >& rOptions( pListener->getUIOptions() ); + for( int i = 0; i < rOptions.getLength(); i++ ) + { + Sequence< beans::PropertyValue > aOptProp; + rOptions[i].Value >>= aOptProp; + + // extract ui element + bool bEnabled = true; + rtl::OUString aCtrlType; + rtl::OUString aText; + rtl::OUString aPropertyName; + Sequence< rtl::OUString > aChoices; + + for( int n = 0; n < aOptProp.getLength(); n++ ) + { + const beans::PropertyValue& rEntry( aOptProp[ n ] ); + if( rEntry.Name.equalsAscii( "Text" ) ) + { + rEntry.Value >>= aText; + } + else if( rEntry.Name.equalsAscii( "ControlType" ) ) + { + rEntry.Value >>= aCtrlType; + } + else if( rEntry.Name.equalsAscii( "Choices" ) ) + { + rEntry.Value >>= aChoices; + } + else if( rEntry.Name.equalsAscii( "Property" ) ) + { + PropertyValue aVal; + rEntry.Value >>= aVal; + aPropertyName = aVal.Name; + } + else if( rEntry.Name.equalsAscii( "Enabled" ) ) + { + sal_Bool bValue = sal_True; + rEntry.Value >>= bValue; + bEnabled = bValue; + } + } + + if( aCtrlType.equalsAscii( "Group" ) || + aCtrlType.equalsAscii( "Subgroup" ) || + aCtrlType.equalsAscii( "Radio" ) || + aCtrlType.equalsAscii( "List" ) || + aCtrlType.equalsAscii( "Bool" ) ) + { + // since our build target is MacOSX 10.4 we can have only one accessory view + // so we have a single accessory view that is tabbed for grouping + if( aCtrlType.equalsAscii( "Group" ) || ! pCurParent ) + { + // set size of current parent + if( pCurParent ) + adjustViewAndChildren( pCurParent, aMaxTabSize ); + + // new tab item + if( ! aText.getLength() ) + aText = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OOo" ) ); + NSString* pLabel = CreateNSString( aText ); + NSTabViewItem* pItem = [[NSTabViewItem alloc] initWithIdentifier: pLabel ]; + [pItem setLabel: pLabel]; + [pTabView addTabViewItem: pItem]; + pCurParent = [[NSView alloc] initWithFrame: aViewFrame]; + [pItem setView: pCurParent]; + [pLabel release]; + + // reset indent + nCurX = 0; + } + + if( aCtrlType.equalsAscii( "Subgroup" ) && pCurParent ) + { + NSString* pText = CreateNSString( aText ); + NSRect aTextRect = { { 0, 0 }, { 300, 15 } }; + NSTextView* pTextView = [[NSTextView alloc] initWithFrame: aTextRect]; + [pTextView setEditable: NO]; + [pTextView setSelectable: NO]; + [pTextView setDrawsBackground: NO]; + [pTextView setString: pText]; + [pTextView sizeToFit]; // FIXME: this does nothing + [pCurParent addSubview: pTextView]; + + aTextRect = [pTextView frame]; + // move to nCurY + aTextRect.origin.y = nCurY - aTextRect.size.height; + [pTextView setFrame: aTextRect]; + + // update nCurY + nCurY = aTextRect.origin.y - 5; + + // set indent + nCurX = 20; + + // cleanup + [pText release]; + } + else if( aCtrlType.equalsAscii( "Bool" ) && pCurParent ) + { + NSString* pText = CreateNSString( aText ); + NSRect aCheckRect = { { nCurX, 0 }, { 0, 15 } }; + NSButton* pBtn = [[NSButton alloc] initWithFrame: aCheckRect]; + [pBtn setButtonType: NSSwitchButton]; + [pBtn setTitle: pText]; + sal_Bool bVal = sal_False; + PropertyValue* pVal = pListener->getValue( aPropertyName ); + if( pVal ) + pVal->Value >>= bVal; + [pBtn setState: bVal ? NSOnState : NSOffState]; + [pBtn setEnabled: (pListener->isUIOptionEnabled( aPropertyName ) && pVal != NULL) ? YES : NO]; + [pBtn sizeToFit]; + [pCurParent addSubview: pBtn]; + + // connect target + [pBtn setTarget: pCtrlTarget]; + [pBtn setAction: @selector(triggered:)]; + int nTag = pListenerProperties->addNameTag( aPropertyName ); + [pBtn setTag: nTag]; + + aCheckRect = [pBtn frame]; + + // move to nCurY + aCheckRect.origin.y = nCurY - aCheckRect.size.height; + [pBtn setFrame: aCheckRect]; + + // update nCurY + nCurY = aCheckRect.origin.y - 5; + + // cleanup + [pText release]; + } + else if( aCtrlType.equalsAscii( "Radio" ) && pCurParent ) + { + if( aText.getLength() ) + { + // add a label + NSString* pText = CreateNSString( aText ); + NSRect aTextRect = { { nCurX, 0 }, { 300, 15 } }; + NSTextView* pTextView = [[NSTextView alloc] initWithFrame: aTextRect]; + [pTextView setEditable: NO]; + [pTextView setSelectable: NO]; + [pTextView setDrawsBackground: NO]; + [pTextView setString: pText]; + [pTextView sizeToFit]; // FIXME: this does nothing + [pCurParent addSubview: pTextView]; + + // move to nCurY + aTextRect.origin.y = nCurY - aTextRect.size.height; + [pTextView setFrame: aTextRect]; + + // update nCurY + nCurY = aTextRect.origin.y - 5; + + // cleanup + [pText release]; + } + + // setup radio matrix + NSButtonCell* pProto = [[NSButtonCell alloc] init]; + + NSRect aRadioRect = { { nCurX + 20, 0 }, { 280 - nCurX, 5*aChoices.getLength() } }; + [pProto setTitle: @"RadioButtonGroup"]; + [pProto setButtonType: NSRadioButton]; + NSMatrix* pMatrix = [[NSMatrix alloc] initWithFrame: aRadioRect + mode: NSRadioModeMatrix + prototype: (NSCell*)pProto + numberOfRows: aChoices.getLength() + numberOfColumns: 1]; + // get currently selected value + rtl::OUString aSelectVal; + PropertyValue* pVal = pListener->getValue( aPropertyName ); + if( pVal && pVal->Value.hasValue() ) + pVal->Value >>= aSelectVal; + // set individual titles + NSArray* pCells = [pMatrix cells]; + for( sal_Int32 m = 0; m < aChoices.getLength(); m++ ) + { + NSCell* pCell = [pCells objectAtIndex: m]; + NSString* pTitle = CreateNSString( aChoices[m] ); + [pCell setTitle: pTitle]; + // connect target and action + [pCell setTarget: pCtrlTarget]; + [pCell setAction: @selector(triggered:)]; + int nTag = pListenerProperties->addNameAndValueTag( aPropertyName, aChoices[ m ] ); + [pCell setTag: nTag]; + [pTitle release]; + // set current selection + if( aSelectVal == aChoices[m] ) + [pMatrix selectCellAtRow: m column: 0]; + } + [pMatrix sizeToFit]; + aRadioRect = [pMatrix frame]; + + // move it down, so it comes to the correct position + aRadioRect.origin.y = nCurY - aRadioRect.size.height; + [pMatrix setFrame: aRadioRect]; + [pCurParent addSubview: pMatrix]; + + // update nCurY + nCurY = aRadioRect.origin.y - 5; + + + [pProto release]; + } + else if( aCtrlType.equalsAscii( "List" ) && pCurParent ) + { + NSString* pText = CreateNSString( aText ); + + // measure the text + NSFont* pFont = [NSFont labelFontOfSize: 0]; + NSDictionary* pDict = [NSDictionary dictionaryWithObject: pFont + forKey: NSFontAttributeName]; + + NSSize aTextSize = [pText sizeWithAttributes: pDict]; + // FIXME: the only thing reliable about sizeWithAttributes is + // that the size it outputs is way too small for our NSTextView + // that would not matter so much if NSTextView's fitToSize actually + // did something out of the box, alas it doesn't. This probably needs more + // fiddling with NSTextView's and NSTextContainer's parameters, however + // since this already almost cost me my sanity a Murphy factor of 1.5 + // will have to suffice for the time being. + aTextSize.width *= 1.5; + aTextSize.height += 3; + NSRect aTextRect = { { nCurX, 0 }, aTextSize }; + NSTextView* pTextView = [[NSTextView alloc] initWithFrame: aTextRect]; + [pTextView setEditable: NO]; + [pTextView setSelectable: NO]; + [pTextView setDrawsBackground: NO]; + [pTextView setString: pText]; + [pTextView setVerticallyResizable: NO]; + [pTextView setHorizontallyResizable: YES]; + [pTextView sizeToFit]; // FIXME: this actually does nothing + [pCurParent addSubview: pTextView]; + aTextRect = [pTextView frame]; + + + NSRect aBtnRect = { { nCurX + aTextRect.size.width, 0 }, { 0, 15 } }; + NSPopUpButton* pBtn = [[NSPopUpButton alloc] initWithFrame: aBtnRect pullsDown: NO]; + // iterate options + for( sal_Int32 m = 0; m < aChoices.getLength(); m++ ) + { + NSString* pItemText = CreateNSString( aChoices[m] ); + [pBtn addItemWithTitle: pItemText]; + NSMenuItem* pItem = [pBtn itemWithTitle: pItemText]; + int nTag = pListenerProperties->addNameAndValueTag( aPropertyName, aChoices[m] ); + [pItem setTag: nTag]; + [pItemText release]; + } + + PropertyValue* pVal = pListener->getValue( aPropertyName ); + rtl::OUString aSelectVal; + if( pVal && pVal->Value.hasValue() ) + pVal->Value >>= aSelectVal; + NSString* pSelectText = CreateNSString( aSelectVal ); + [pBtn setTitle: pSelectText]; + [pSelectText release]; + [pBtn setEnabled: (pListener->isUIOptionEnabled( aPropertyName ) && pVal != NULL) ? YES : NO]; + + [pBtn sizeToFit]; + [pCurParent addSubview: pBtn]; + + // connect target and action + [pBtn setTarget: pCtrlTarget]; + [pBtn setAction: @selector(triggered:)]; + + // move to nCurY + aBtnRect = [pBtn frame]; + aBtnRect.origin.y = nCurY - aBtnRect.size.height; + [pBtn setFrame: aBtnRect]; + + // align label + aTextRect.origin.y = aBtnRect.origin.y + (aBtnRect.size.height - aTextRect.size.height)/2; + [pTextView setFrame: aTextRect]; + + // update nCurY + nCurY = aBtnRect.origin.y - 5; + + // cleanup + [pText release]; + } + } + else + { + DBG_ERROR( "Unsupported UI option" ); + } + } + adjustViewAndChildren( pCurParent, aMaxTabSize ); + + // find the minimum needed tab size + NSSize aTabCtrlSize = [pTabView minimumSize]; + aTabCtrlSize.height += aMaxTabSize.height + 10; + if( aTabCtrlSize.width < aMaxTabSize.width + 10 ) + aTabCtrlSize.width = aMaxTabSize.width + 10; + [pTabView setFrameSize: aTabCtrlSize]; + + // set the accessory view + #if 0 + NSPrintPanel* pPanel = [pOp printPanel]; + if( [pPanel respondsToSelector: @selector(addAccessoryController:)] ) + { + // 10.5 and upward case + AquaPrintViewController* pCtrl = [[AquaPrintViewController alloc] init]; + [pCtrl performSelector: @selector(setView:) withObject: pTabView]; + [pCtrl performSelector: @selector(setTitle:) withObject: @"Test OOOOO"]; + [pPanel performSelector: @selector(addAccessoryController:) withObject: pCtrl]; + [pPanel performSelector: @selector(setOptions:) withObject: (id)(0x20001)]; + } + else + #endif + [pOp setAccessoryView: pTabView]; + + return pCtrlTarget; +} + +@end diff --git a/vcl/aqua/source/gdi/aquaprintview.mm b/vcl/aqua/source/gdi/aquaprintview.mm index 6099fbaed741..79efb9c80941 100755 --- a/vcl/aqua/source/gdi/aquaprintview.mm +++ b/vcl/aqua/source/gdi/aquaprintview.mm @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: aquaprintview.mm,v $ - * $Revision: 1.5 $ + * $Revision: 1.5.56.1 $ * * This file is part of OpenOffice.org. * @@ -33,15 +33,15 @@ #include "aquaprintview.h" #include "salprn.h" -#include "vcl/impprn.hxx" +#include "vcl/print.hxx" @implementation AquaPrintView --(id)initWithQPrinter: (ImplQPrinter*)pPrinter withInfoPrinter: (AquaSalInfoPrinter*)pInfoPrinter +-(id)initWithListener: (vcl::PrinterListener*)pListener withInfoPrinter: (AquaSalInfoPrinter*)pInfoPrinter { NSRect aRect = { { 0, 0 }, [pInfoPrinter->getPrintInfo() paperSize] }; if( (self = [super initWithFrame: aRect]) != nil ) { - mpQPrinter = pPrinter; + mpListener = pListener; mpInfoPrinter = pInfoPrinter; } return self; @@ -76,6 +76,6 @@ int nPage = (int)(aPaperSize.width * rect.origin.y + rect.origin.x); // page count is 1 based - mpQPrinter->PrintPage( nPage-1 + mpInfoPrinter->getCurPageRangeStart() ); + mpListener->printFilteredPage( nPage-1 ); } @end diff --git a/vcl/aqua/source/gdi/makefile.mk b/vcl/aqua/source/gdi/makefile.mk index deb6832a5525..90b5e55b82db 100644 --- a/vcl/aqua/source/gdi/makefile.mk +++ b/vcl/aqua/source/gdi/makefile.mk @@ -62,6 +62,7 @@ SLOFILES= $(SLO)$/salmathutils.obj \ $(SLO)$/salvd.obj \ $(SLO)$/salprn.obj \ $(SLO)$/aquaprintview.obj \ + $(SLO)$/aquaprintaccessoryview.obj \ $(SLO)$/salbmp.obj .IF "$(ENABLE_CAIRO)" == "TRUE" diff --git a/vcl/aqua/source/gdi/salprn.cxx b/vcl/aqua/source/gdi/salprn.cxx index ef6258829261..959d421ae978 100644 --- a/vcl/aqua/source/gdi/salprn.cxx +++ b/vcl/aqua/source/gdi/salprn.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: salprn.cxx,v $ - * $Revision: 1.16 $ + * $Revision: 1.16.56.2 $ * * This file is part of OpenOffice.org. * @@ -128,8 +128,8 @@ void AquaSalInfoPrinter::SetupPrinterGraphics( CGContextRef i_rContext ) const if( mePageOrientation == ORIENTATION_PORTRAIT ) { double dX = 0, dY = aPaperSize.height; - dX += aImageRect.origin.x; - dY -= aPaperSize.height - aImageRect.size.height - aImageRect.origin.y; + // dX += aImageRect.origin.x; + // dY -= aPaperSize.height - aImageRect.size.height - aImageRect.origin.y; CGContextTranslateCTM( i_rContext, dX + mnStartPageOffsetX, dY - mnStartPageOffsetY ); CGContextScaleCTM( i_rContext, 0.1, -0.1 ); } @@ -137,8 +137,8 @@ void AquaSalInfoPrinter::SetupPrinterGraphics( CGContextRef i_rContext ) const { CGContextRotateCTM( i_rContext, M_PI/2 ); double dX = aPaperSize.height, dY = -aPaperSize.width; - dY += aPaperSize.height - aImageRect.size.height - aImageRect.origin.y; - dX -= aImageRect.origin.x; + // dY += aPaperSize.height - aImageRect.size.height - aImageRect.origin.y; + // dX -= aImageRect.origin.x; CGContextTranslateCTM( i_rContext, dX + mnStartPageOffsetY, dY - mnStartPageOffsetX ); CGContextScaleCTM( i_rContext, -0.1, 0.1 ); @@ -459,77 +459,73 @@ void AquaSalInfoPrinter::GetPageInfo( const ImplJobSetup*, } } -BOOL AquaSalInfoPrinter::StartJob( const String* pFileName, - const String& rAppName, - ImplJobSetup* pSetupData, - ImplQPrinter* pQPrinter, +BOOL AquaSalInfoPrinter::StartJob( const String* i_pFileName, + const String& i_rAppName, + ImplJobSetup* i_pSetupData, + vcl::PrinterListener& i_rListener, bool bIsQuickJob ) { if( mbJob ) return FALSE; BOOL bSuccess = FALSE; - std::vector<ULONG> aPaperRanges; - if( ! pQPrinter->GetPaperRanges( aPaperRanges, true ) ) - return FALSE; - size_t nRanges = aPaperRanges.size(); + // FIXME: make paper ranges work again + mnCurPageRangeStart = 1; + mnCurPageRangeCount = i_rListener.getPageCount(); + AquaSalInstance* pInst = GetSalData()->mpFirstInstance; - for( ULONG nCurRange = 0; nCurRange < nRanges-1; nCurRange++ ) - { - mnStartPageOffsetX = mnStartPageOffsetY = 0; + mnStartPageOffsetX = mnStartPageOffsetY = 0; - // update job data - ImplJobSetup* pSetup = pQPrinter->GetPageSetup( aPaperRanges[ nCurRange ] ); - if( pSetup ) - SetData( ~0, pSetup ); - DBG_ASSERT( pSetup, "no job setup for range" ); + // update job data + if( i_pSetupData ) + SetData( ~0, i_pSetupData ); - mnCurPageRangeStart = aPaperRanges[nCurRange]; - mnCurPageRangeCount = aPaperRanges[nCurRange+1] - aPaperRanges[nCurRange]; - // create view - NSView* pPrintView = [[AquaPrintView alloc] initWithQPrinter: pQPrinter withInfoPrinter: this]; + // create view + NSView* pPrintView = [[AquaPrintView alloc] initWithListener: &i_rListener withInfoPrinter: this]; - NSMutableDictionary* pPrintDict = [mpPrintInfo dictionary]; + NSMutableDictionary* pPrintDict = [mpPrintInfo dictionary]; - // set filename - if( pFileName ) - { - [mpPrintInfo setJobDisposition: NSPrintSaveJob]; - NSString* pPath = CreateNSString( *pFileName ); - [pPrintDict setObject: pPath forKey: NSPrintSavePath]; - [pPath release]; - - // in this case we can only deliver the print job in one file - mnCurPageRangeStart = 0; - mnCurPageRangeCount = aPaperRanges.back(); - nCurRange = nRanges; - } + // set filename + if( i_pFileName ) + { + [mpPrintInfo setJobDisposition: NSPrintSaveJob]; + NSString* pPath = CreateNSString( *i_pFileName ); + [pPrintDict setObject: pPath forKey: NSPrintSavePath]; + [pPath release]; + } - [pPrintDict setObject: [[NSNumber numberWithInt: (int)pQPrinter->GetCopyCount()] autorelease] forKey: NSPrintCopies]; - [pPrintDict setObject: [[NSNumber numberWithBool: YES] autorelease] forKey: NSPrintDetailedErrorReporting]; - [pPrintDict setObject: [[NSNumber numberWithInt: 1] autorelease] forKey: NSPrintFirstPage]; - [pPrintDict setObject: [[NSNumber numberWithInt: (int)mnCurPageRangeCount] autorelease] forKey: NSPrintLastPage]; + // FIXME copies + // [pPrintDict setObject: [[NSNumber numberWithInt: (int)pQPrinter->GetCopyCount()] autorelease] forKey: NSPrintCopies]; + [pPrintDict setObject: [[NSNumber numberWithBool: YES] autorelease] forKey: NSPrintDetailedErrorReporting]; + [pPrintDict setObject: [[NSNumber numberWithInt: 1] autorelease] forKey: NSPrintFirstPage]; + [pPrintDict setObject: [[NSNumber numberWithInt: mnCurPageRangeCount] autorelease] forKey: NSPrintLastPage]; - // create print operation - NSPrintOperation* pPrintOperation = [NSPrintOperation printOperationWithView: pPrintView printInfo: mpPrintInfo]; + // create print operation + NSPrintOperation* pPrintOperation = [NSPrintOperation printOperationWithView: pPrintView printInfo: mpPrintInfo]; - if( pPrintOperation ) - { - bool bShowPanel = (! bIsQuickJob && getUseNativeDialog() ); - [pPrintOperation setShowsPrintPanel: bShowPanel ? YES : NO ]; - // [pPrintOperation setShowsProgressPanel: NO]; - bSuccess = TRUE; - mbJob = true; - pInst->startedPrintJob(); - [pPrintOperation runOperation]; - pInst->endedPrintJob(); - mbJob = false; - } + if( pPrintOperation ) + { + NSObject* pReleaseAfterUse = nil; + bool bShowPanel = (! bIsQuickJob && getUseNativeDialog() ); + [pPrintOperation setShowsPrintPanel: bShowPanel ? YES : NO ]; + [pPrintOperation setShowsProgressPanel: YES]; + if( bShowPanel ) + pReleaseAfterUse = [AquaPrintAccessoryView setupPrinterPanel: pPrintOperation withListener: &i_rListener]; + + bSuccess = TRUE; + mbJob = true; + pInst->startedPrintJob(); + [pPrintOperation runOperation]; + pInst->endedPrintJob(); + mbJob = false; + [pReleaseAfterUse release]; } + mnCurPageRangeStart = mnCurPageRangeCount = 0; + return bSuccess; } @@ -595,22 +591,22 @@ AquaSalPrinter::~AquaSalPrinter() // ----------------------------------------------------------------------- -BOOL AquaSalPrinter::StartJob( const String* pFileName, - const String& rAppName, - ImplJobSetup* pSetupData, - ImplQPrinter* pQPrinter ) +BOOL AquaSalPrinter::StartJob( const String* i_pFileName, + const String& i_rAppName, + ImplJobSetup* i_pSetupData, + vcl::PrinterListener& i_rListener ) { bool bIsQuickJob = false; std::hash_map< rtl::OUString, rtl::OUString, rtl::OUStringHash >::const_iterator quick_it = - pSetupData->maValueMap.find( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsQuickJob" ) ) ); + i_pSetupData->maValueMap.find( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsQuickJob" ) ) ); - if( quick_it != pSetupData->maValueMap.end() ) + if( quick_it != i_pSetupData->maValueMap.end() ) { if( quick_it->second.equalsIgnoreAsciiCaseAscii( "true" ) ) bIsQuickJob = true; } - return mpInfoPrinter->StartJob( pFileName, rAppName, pSetupData, pQPrinter, bIsQuickJob ); + return mpInfoPrinter->StartJob( i_pFileName, i_rAppName, i_pSetupData, i_rListener, bIsQuickJob ); } // ----------------------------------------------------------------------- diff --git a/vcl/inc/vcl/print.h b/vcl/inc/vcl/print.h index 51cbb5dee0cf..bc74b6441f28 100644 --- a/vcl/inc/vcl/print.h +++ b/vcl/inc/vcl/print.h @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: print.h,v $ - * $Revision: 1.4 $ + * $Revision: 1.4.114.2 $ * * This file is part of OpenOffice.org. * @@ -31,15 +31,18 @@ #ifndef _SV_PRINT_H #define _SV_PRINT_H -#include <tools/list.hxx> -#include <vcl/sv.h> -#include <vcl/dllapi.h> +#include "vcl/sv.h" +#include "vcl/dllapi.h" #include <vector> #include <hash_map> struct SalPrinterQueueInfo; class QueueInfo; +class JobSetup; + +namespace vcl +{ class PrinterListener; } // ------------------------ // - private printer data - @@ -87,5 +90,7 @@ public: // -------------- void ImplDeletePrnQueueList(); +void SAL_DLLPRIVATE ImplUpdateJobSetupPaper( JobSetup& rJobSetup ); + #endif // _SV_PRINT_H diff --git a/vcl/inc/vcl/print.hxx b/vcl/inc/vcl/print.hxx index fdc7f2ba9c69..cf491dc1b4f6 100644 --- a/vcl/inc/vcl/print.hxx +++ b/vcl/inc/vcl/print.hxx @@ -31,14 +31,19 @@ #ifndef _SV_PRINT_HXX #define _SV_PRINT_HXX -#include <tools/errcode.hxx> -#include <vcl/sv.h> -#include <vcl/dllapi.h> -#include <vcl/outdev.hxx> -#include <vcl/prntypes.hxx> -#include <vcl/jobset.hxx> -#include <vcl/gdimtf.hxx> -#include <tools/stream.hxx> +#include "tools/errcode.hxx" +#include "vcl/sv.h" +#include "vcl/dllapi.h" +#include "vcl/outdev.hxx" +#include "vcl/prntypes.hxx" +#include "vcl/jobset.hxx" +#include "vcl/gdimtf.hxx" +#include "tools/stream.hxx" +#include "tools/multisel.hxx" + +#include "com/sun/star/beans/PropertyValue.hpp" + +#include <boost/shared_ptr.hpp> struct SalPrinterInfoQueue; class SalInfoPrinter; @@ -49,9 +54,10 @@ class Window; class ImplQPrinter; struct ImplPrivatePrinterData; -namespace com { namespace sun { namespace star { namespace uno { - class Any; -} } } } +namespace vcl { + class PrinterListener; + class PrintDialog; +} // ----------------- // - Printer-Types - @@ -263,6 +269,11 @@ private: SAL_DLLPRIVATE void ImplUpdateFontList(); SAL_DLLPRIVATE void ImplFindPaperFormatForUserSize( JobSetup& ); DECL_DLLPRIVATE_LINK( ImplDestroyPrinterAsync, void* ); + + SAL_DLLPRIVATE bool StartJob( const XubString& rJobName, boost::shared_ptr<vcl::PrinterListener>& ); + + static SAL_DLLPRIVATE ULONG ImplSalPrinterErrorCodeToVCL( ULONG nError ); + public: SAL_DLLPRIVATE void ImplEndPrint(); SAL_DLLPRIVATE void ImplUpdateQuickStatus(); @@ -405,6 +416,85 @@ public: * if the printer list changed */ static void updatePrinters(); + + /** execute a print job + + starts a print job asynchronously (that is will return + + */ + static void PrintJob( const boost::shared_ptr<vcl::PrinterListener>& i_pListener, + const JobSetup& i_rInitSetup + ); + + // implementation detail of PrintJob being asynchronous + // not exported, not usable outside vcl + static void SAL_DLLPRIVATE ImplPrintJob( const boost::shared_ptr<vcl::PrinterListener>& i_pListener, + const JobSetup& i_rInitSetup + ); +}; + +namespace vcl +{ +class ImplPrinterListenerData; + +class VCL_DLLPUBLIC PrinterListener +{ + ImplPrinterListenerData* mpImplData; +public: + PrinterListener(); + virtual ~PrinterListener(); + + const boost::shared_ptr<Printer>& getPrinter() const; + const MultiSelection& getPageSelection() const; + + /* for implementations: get current job properties as changed by e.g. print dialog + this gets the current set of properties initially told to Printer::PrintJob + + For convenience a second sequence will be merged in to get a combined sequence. + In case of duplicate property names, the value of i_MergeList wins. + */ + com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue > + getJobProperties( const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& i_rMergeList ) const; + + /* get the PorpertyValue of a Property + */ + com::sun::star::beans::PropertyValue* getValue( const rtl::OUString& rPropertyName ); + const com::sun::star::beans::PropertyValue* getValue( const rtl::OUString& rPropertyName ) const; + + /* return the currently active UI options. These are the same passed to setUIOptions. + */ + const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& getUIOptions() const; + /* set possible UI options. should only be done once before passing the PrinterListener + to Printer::PrintJob + */ + void setUIOptions( const com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue >& ); + /* enable/disable an option; this can be used to implement dialog logic. + */ + void enableUIOption( const rtl::OUString& rPropName, bool bEnable ); + bool isUIOptionEnabled( const rtl::OUString& rPropName ) const; + + virtual int getPageCount() const = 0; // must be overloaded by the app + /* get the page parameters, namely the jobsetup that should be active for the page + (describing among others the physical page size) and the "page size". In writer + case this would probably be the same as the JobSetup since writer sets the page size + draw/impress for example print their page on the paper set on the printer, + possibly adjusting the page size to fit. That means the page size can be different from + the paper size. + */ + // must be overloaded by the app, return page size in 1/100th mm + virtual com::sun::star::uno::Sequence< com::sun::star::beans::PropertyValue > getPageParameters( int i_nPage ) const = 0; + virtual void printPage( int i_nPage ) const = 0; // must be overloaded by the app + virtual void jobFinished(); // optionally release resources bound to the job + + // implementation details, not usable outside vcl + void SAL_DLLPRIVATE printFilteredPage( int i_nPage ); + void SAL_DLLPRIVATE setPrinter( const boost::shared_ptr<Printer>& ); + void SAL_DLLPRIVATE setPageSelection( const MultiSelection& ); + void SAL_DLLPRIVATE setOptionChangeHdl( const Link& ); + void SAL_DLLPRIVATE createProgressDialog(); }; +} + + #endif // _SV_PRINT_HXX diff --git a/vcl/inc/vcl/prndlg.hxx b/vcl/inc/vcl/prndlg.hxx index 4fd6eaa999da..cba6b59e81f5 100644 --- a/vcl/inc/vcl/prndlg.hxx +++ b/vcl/inc/vcl/prndlg.hxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: prndlg.hxx,v $ - * $Revision: 1.3 $ + * $Revision: 1.3.114.5 $ * * This file is part of OpenOffice.org. * @@ -33,19 +33,167 @@ #include <vcl/dllapi.h> -#include <vcl/dialog.hxx> +#include "vcl/print.hxx" +#include "vcl/print.h" -class Printer; +#include "vcl/dialog.hxx" +#include "vcl/fixed.hxx" +#include "vcl/button.hxx" +#include "vcl/scrbar.hxx" +#include "vcl/gdimtf.hxx" +#include "vcl/lstbox.hxx" +#include "vcl/field.hxx" +#include "vcl/tabctrl.hxx" +#include "vcl/tabpage.hxx" -class VCL_DLLPUBLIC SystemDialog : public ModalDialog +#include "tools/multisel.hxx" + +#include <boost/shared_ptr.hpp> +#include <map> + +namespace vcl { -public: - SystemDialog( Window* pParent, WinBits nWinStyle ) : - ModalDialog( pParent, nWinStyle ) {} - SystemDialog( Window* pParent, const ResId& rResId ) : - ModalDialog( pParent, rResId ) {} - - virtual short Execute() { return 0; } -}; + class PrintDialog : public ModalDialog + { + class PrintPreviewWindow : public Window + { + GDIMetaFile maMtf; + public: + PrintPreviewWindow( Window* pParent, const ResId& ); + virtual ~PrintPreviewWindow(); + + virtual void Paint( const Rectangle& rRect ); + + void setPreview( const GDIMetaFile& ); + }; + + class PrinterTabPage : public TabPage + { + public: + ListBox maPrinters; + PushButton maSetupButton; + FixedText maType; + FixedText maTypeText; + FixedText maStatus; + FixedText maStatusText; + FixedText maLocation; + FixedText maLocText; + FixedText maComment; + FixedText maCommentText; + + PrinterTabPage( Window*, const ResId& ); + virtual ~PrinterTabPage(); + }; + + class JobTabPage : public TabPage + { + public: + ListBox maPrinters; + CheckBox maToFileBox; + FixedLine maPrintRange; + RadioButton maAllButton; + RadioButton maPagesButton; + RadioButton maSelectionButton; + Edit maPagesEdit; + + FixedLine maCopies; + FixedText maCopyCount; + NumericField maCopyCountField; + CheckBox maCollateBox; + FixedImage maCollateImage; + + Image maCollateImg; + Image maCollateHCImg; + Image maNoCollateImg; + Image maNoCollateHCImg; + + JobTabPage( Window*, const ResId& ); + virtual ~JobTabPage(); + }; + + OKButton maOKButton; + CancelButton maCancelButton; + PrintPreviewWindow maPreviewWindow; + FixedText maPageText; + ScrollBar maPageScrollbar; + + TabControl maTabCtrl; + PrinterTabPage maPrinterPage; + JobTabPage maJobPage; + + FixedLine maButtonLine; + + boost::shared_ptr< PrinterListener > maPListener; + + rtl::OUString maPageStr; + sal_Int32 mnCurPage; + sal_Int32 mnCachedPages; + Rectangle maPreviewSpace; + + std::list< Window* > maControls; + std::map< Window*, rtl::OUString > maControlToPropertyMap; + std::multimap< rtl::OUString, Window* > maPropertyToWindowMap; + std::map< Window*, sal_Int32 > maControlToNumValMap; + + void preparePreview(); + void setPreviewText( sal_Int32 ); + void updatePrinterText(); + void checkControlDependencies(); + void checkOptionalControlDependencies(); + void setupOptionalUI(); + com::sun::star::beans::PropertyValue* getValueForWindow( Window* ) const; + + virtual void Resize(); + + DECL_LINK( ScrollHdl, ScrollBar* ); + DECL_LINK( ScrollEndHdl, ScrollBar* ); + DECL_LINK( SelectHdl, ListBox* ); + DECL_LINK( ClickHdl, Button* ); + DECL_LINK( ModifyHdl, Edit* ); + DECL_LINK( UIOptionsChanged, void* ); + + DECL_LINK( UIOption_CheckHdl, CheckBox* ); + DECL_LINK( UIOption_RadioHdl, RadioButton* ); + DECL_LINK( UIOption_SelectHdl, ListBox* ); + DECL_LINK( UIOption_ModifyHdl, Edit* ); + + public: + PrintDialog( Window*, const boost::shared_ptr< PrinterListener >& ); + virtual ~PrintDialog(); + + bool isPrintToFile(); + MultiSelection getPageSelection(); + int getCopyCount(); + bool isCollate(); + }; + + class PrintProgressDialog : public ModelessDialog + { + String maStr; + FixedText maText; + CancelButton maButton; + + bool mbCanceled; + int mnCur; + int mnMax; + long mnProgressHeight; + Rectangle maProgressRect; + bool mbNativeProgress; + + DECL_LINK( ClickHdl, Button* ); + + void implCalcProgressRect(); + public: + PrintProgressDialog( Window* i_pParent, int i_nMax ); + ~PrintProgressDialog(); + + bool isCanceled() const { return mbCanceled; } + void setProgress( int i_nCurrent, int i_nMax = -1 ); + void tick(); + + virtual void Paint( const Rectangle& ); + }; +} + #endif // _SV_PRNDLG_HXX diff --git a/vcl/inc/vcl/salprn.hxx b/vcl/inc/vcl/salprn.hxx index a80c5873cbfb..d76040f8cb8b 100644 --- a/vcl/inc/vcl/salprn.hxx +++ b/vcl/inc/vcl/salprn.hxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: salprn.hxx,v $ - * $Revision: 1.5 $ + * $Revision: 1.5.114.1 $ * * This file is part of OpenOffice.org. * @@ -41,7 +41,7 @@ class SalGraphics; class SalFrame; struct ImplJobSetup; -class ImplQPrinter; +namespace vcl { class PrinterListener; } // ----------------------- // - SalPrinterQueueInfo - @@ -125,7 +125,7 @@ public: // public for Sal Implementation virtual BOOL StartJob( const String* pFileName, const String& rAppName, ImplJobSetup* pSetupData, - ImplQPrinter* pQPrinter ); + vcl::PrinterListener& rListener ); virtual BOOL EndJob() = 0; virtual BOOL AbortJob() = 0; diff --git a/vcl/inc/vcl/svdata.hxx b/vcl/inc/vcl/svdata.hxx index eabaa40be53e..e3072a4bc250 100644 --- a/vcl/inc/vcl/svdata.hxx +++ b/vcl/inc/vcl/svdata.hxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: svdata.hxx,v $ - * $Revision: 1.13 $ + * $Revision: 1.13.16.1 $ * * This file is part of OpenOffice.org. * @@ -354,6 +354,7 @@ void ImplDeInitSVData(); void ImplDestroySVData(); Window* ImplGetDefaultWindow(); VCL_DLLPUBLIC ResMgr* ImplGetResMgr(); +VCL_DLLPUBLIC ResId VclResId( sal_Int32 nId ); // throws std::bad_alloc if no res mgr DockingManager* ImplGetDockingManager(); void ImplWindowAutoMnemonic( Window* pWindow ); diff --git a/vcl/inc/vcl/svids.hrc b/vcl/inc/vcl/svids.hrc index 48297a04ea0e..ef4b021e1919 100644 --- a/vcl/inc/vcl/svids.hrc +++ b/vcl/inc/vcl/svids.hrc @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: svids.hrc,v $ - * $Revision: 1.8 $ + * $Revision: 1.8.84.3 $ * * This file is part of OpenOffice.org. * @@ -74,6 +74,48 @@ #define SV_MENU_MAC_SHOWALL 2005 #define SV_MENU_MAC_QUITAPP 2006 +#define SV_DLG_PRINT 2048 +#define SV_PRINT_OK 1 +#define SV_PRINT_CANCEL 2 +#define SV_PRINT_PAGE_TXT 3 +#define SV_PRINT_PAGE_PREVIEW 4 +#define SV_PRINT_PAGE_SCROLL 5 +#define SV_PRINT_TABCTRL 6 + +#define SV_PRINT_TAB_PRINTER 1 +#define SV_PRINT_PRINTERS 1 +#define SV_PRINT_PRT_TYPE 2 +#define SV_PRINT_PRT_TYPE_TXT 3 +#define SV_PRINT_PRT_STATUS 4 +#define SV_PRINT_PRT_STATUS_TXT 5 +#define SV_PRINT_PRT_LOCATION 6 +#define SV_PRINT_PRT_LOCATION_TXT 7 +#define SV_PRINT_PRT_COMMENT 8 +#define SV_PRINT_PRT_COMMENT_TXT 9 +#define SV_PRINT_PRT_TOFILE 10 +#define SV_PRINT_PRT_SETUP 11 + +#define SV_DLG_PRINT_PROGRESS 2048 +#define SV_PRINT_PROGRESS_CANCEL 1 +#define SV_PRINT_PROGRESS_TEXT 2 + +#define SV_PRINT_TAB_JOB 2 +#define SV_PRINT_RANGE 1 +#define SV_PRINT_ALL 2 +#define SV_PRINT_PAGERANGE 3 +#define SV_PRINT_SELECTION 4 +#define SV_PRINT_PAGERANGE_EDIT 5 +#define SV_PRINT_COPIES 6 +#define SV_PRINT_COPYCOUNT 7 +#define SV_PRINT_COPYCOUNT_FIELD 8 +#define SV_PRINT_COLLATE 9 +#define SV_PRINT_COLLATE_IMAGE 10 +#define SV_PRINT_BUTTONLINE 11 +#define SV_PRINT_COLLATE_IMG 12 +#define SV_PRINT_NOCOLLATE_IMG 13 +#define SV_PRINT_COLLATE_HC_IMG 14 +#define SV_PRINT_NOCOLLATE_HC_IMG 15 + #define SV_HELPTEXT_CLOSE 10000 #define SV_HELPTEXT_MINIMIZE 10001 #define SV_HELPTEXT_MAXIMIZE 10002 @@ -108,7 +150,8 @@ #define SV_STDTEXT_ABOUT 10204 #define SV_STDTEXT_PREFERENCES 10205 #define SV_MAC_SCREENNNAME 10206 -#define SV_STDTEXT_LAST SV_MAC_SCREENNNAME +#define SV_STDTEXT_ALLFILETYPES 10207 +#define SV_STDTEXT_LAST SV_STDTEXT_ALLFILETYPES #define SV_ACCESSERROR_FIRST SV_ACCESSERROR_WRONG_VERSION #define SV_ACCESSERROR_WRONG_VERSION 10500 diff --git a/vcl/prj/d.lst b/vcl/prj/d.lst index 0ddc61170547..c0b2675036b7 100644 --- a/vcl/prj/d.lst +++ b/vcl/prj/d.lst @@ -85,7 +85,6 @@ mkdir: %_DEST%\inc%_EXT%\vcl\plug\vcl ..\inc\vcl\outdev.hxx %_DEST%\inc%_EXT%\vcl\outdev.hxx ..\inc\vcl\pointr.hxx %_DEST%\inc%_EXT%\vcl\pointr.hxx ..\inc\vcl\print.hxx %_DEST%\inc%_EXT%\vcl\print.hxx -..\inc\vcl\prndlg.hxx %_DEST%\inc%_EXT%\vcl\prndlg.hxx ..\inc\vcl\prntypes.hxx %_DEST%\inc%_EXT%\vcl\prntypes.hxx ..\inc\vcl\ptrstyle.hxx %_DEST%\inc%_EXT%\vcl\ptrstyle.hxx ..\inc\vcl\regband.hxx %_DEST%\inc%_EXT%\vcl\regband.hxx diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx index 9d398aef10cd..fe1ef6e7b992 100644 --- a/vcl/source/app/salvtables.cxx +++ b/vcl/source/app/salvtables.cxx @@ -91,7 +91,7 @@ SalPrinter::~SalPrinter() } BOOL SalPrinter::StartJob( const String*, const String&, - ImplJobSetup*, ImplQPrinter* ) + ImplJobSetup*, vcl::PrinterListener& ) { return FALSE; } diff --git a/vcl/source/app/svdata.cxx b/vcl/source/app/svdata.cxx index edfd6a24bff9..56ba933e3931 100644 --- a/vcl/source/app/svdata.cxx +++ b/vcl/source/app/svdata.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: svdata.cxx,v $ - * $Revision: 1.56 $ + * $Revision: 1.56.114.1 $ * * This file is part of OpenOffice.org. * @@ -220,6 +220,15 @@ ResMgr* ImplGetResMgr() return pSVData->mpResMgr; } +ResId VclResId( sal_Int32 nId ) +{ + ResMgr* pMgr = ImplGetResMgr(); + if( ! pMgr ) + throw std::bad_alloc(); + + return ResId( nId, *pMgr ); +} + DockingManager* ImplGetDockingManager() { ImplSVData* pSVData = ImplGetSVData(); diff --git a/vcl/source/gdi/impprn.cxx b/vcl/source/gdi/impprn.cxx index 539c879c89ea..28d92a0b3832 100644 --- a/vcl/source/gdi/impprn.cxx +++ b/vcl/source/gdi/impprn.cxx @@ -478,10 +478,12 @@ void ImplQPrinter::EndQueuePrint() DBG_ASSERT( mpPrinter, "no SalPrinter in ImplQPrinter" ); if( mpPrinter ) { + #if 0 mpPrinter->StartJob( mbPrintFile ? &maPrintFile : NULL, Application::GetDisplayName(), maJobSetup.ImplGetConstData(), this ); + #endif EndJob(); mpParent->ImplEndPrint(); } diff --git a/vcl/source/gdi/makefile.mk b/vcl/source/gdi/makefile.mk index 977e5386fe97..57d5804a8afa 100644 --- a/vcl/source/gdi/makefile.mk +++ b/vcl/source/gdi/makefile.mk @@ -96,6 +96,7 @@ SLOFILES= $(SLO)$/salmisc.obj \ $(SLO)$/fontcvt.obj \ $(SLO)$/print.obj \ $(SLO)$/print2.obj \ + $(SLO)$/print3.obj \ $(SLO)$/regband.obj \ $(SLO)$/region.obj \ $(SLO)$/wall.obj \ @@ -120,6 +121,7 @@ EXCEPTIONSFILES= $(SLO)$/salmisc.obj \ $(SLO)$/gfxlink.obj \ $(SLO)$/print.obj \ $(SLO)$/print2.obj \ + $(SLO)$/print3.obj \ $(SLO)$/sallayout.obj \ $(SLO)$/image.obj \ $(SLO)$/impimage.obj \ diff --git a/vcl/source/gdi/print.cxx b/vcl/source/gdi/print.cxx index 0a5fbb189885..e8a1f5b32213 100644 --- a/vcl/source/gdi/print.cxx +++ b/vcl/source/gdi/print.cxx @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: print.cxx,v $ - * $Revision: 1.65 $ + * $Revision: 1.65.114.1 $ * * This file is part of OpenOffice.org. * @@ -1309,7 +1309,7 @@ void Printer::PrintPage() // ----------------------------------------------------------------------- -ULONG ImplSalPrinterErrorCodeToVCL( ULONG nError ) +ULONG Printer::ImplSalPrinterErrorCodeToVCL( ULONG nError ) { ULONG nVCLError; switch ( nError ) diff --git a/vcl/source/gdi/print3.cxx b/vcl/source/gdi/print3.cxx new file mode 100644 index 000000000000..887fa2ce39dd --- /dev/null +++ b/vcl/source/gdi/print3.cxx @@ -0,0 +1,672 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: print3.cxx,v $ + * $Revision: 1.1.2.11 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "precompiled_vcl.hxx" + +#include "vcl/print.hxx" +#include "vcl/prndlg.hxx" +#include "vcl/svapp.hxx" +#include "vcl/svdata.hxx" +#include "vcl/salinst.hxx" +#include "vcl/salprn.hxx" +#include "vcl/svids.hrc" + +#include "tools/urlobj.hxx" +#include "tools/multisel.hxx" + +#include "com/sun/star/ui/dialogs/XFilePicker.hpp" +#include "com/sun/star/ui/dialogs/XFilterManager.hpp" +#include "com/sun/star/ui/dialogs/TemplateDescription.hpp" +#include "com/sun/star/ui/dialogs/ExecutableDialogResults.hpp" +#include "com/sun/star/lang/XMultiServiceFactory.hpp" +#include "com/sun/star/awt/Size.hpp" +#include "comphelper/processfactory.hxx" + +#include <hash_map> +#include <hash_set> + +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::beans; +using namespace vcl; + +class vcl::ImplPrinterListenerData +{ +public: + struct ControlDependency + { + rtl::OUString maDependsOnName; + sal_Int32 mnDependsOnEntry; + + ControlDependency() : mnDependsOnEntry( -1 ) {} + }; + + typedef std::hash_map< rtl::OUString, size_t, rtl::OUStringHash > PropertyToIndexMap; + typedef std::hash_map< rtl::OUString, ControlDependency, rtl::OUStringHash > ControlDependencyMap; + + boost::shared_ptr<Printer> mpPrinter; + MultiSelection maSelection; + Sequence< PropertyValue > maUIOptions; + std::vector< PropertyValue > maUIProperties; + std::vector< bool > maUIPropertyEnabled; + PropertyToIndexMap maPropertyToIndex; + Link maOptionChangeHdl; + ControlDependencyMap maControlDependencies; + + vcl::PrintProgressDialog* mpProgress; + + ImplPrinterListenerData() : mpProgress( NULL ) {} + ~ImplPrinterListenerData() { delete mpProgress; } +}; + +PrinterListener::PrinterListener() + : mpImplData( new ImplPrinterListenerData ) +{ +} + +static rtl::OUString queryFile( Printer* pPrinter ) +{ + rtl::OUString aResult; + + uno::Reference< lang::XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory() ); + if( xFactory.is() ) + { + uno::Sequence< uno::Any > aTempl( 1 ); + aTempl.getArray()[0] <<= ui::dialogs::TemplateDescription::FILESAVE_AUTOEXTENSION; + uno::Reference< ui::dialogs::XFilePicker > xFilePicker( + xFactory->createInstanceWithArguments( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.ui.dialogs.FilePicker" ) ), + aTempl ), uno::UNO_QUERY ); + DBG_ASSERT( xFilePicker.is(), "could not get FilePicker service" ); + + uno::Reference< ui::dialogs::XFilterManager > xFilterMgr( xFilePicker, uno::UNO_QUERY ); + if( xFilePicker.is() && xFilterMgr.is() ) + { + try + { +#ifdef UNX + // add PostScript and PDF + bool bPS = true, bPDF = true; + if( pPrinter ) + { + if( pPrinter->GetCapabilities( PRINTER_CAPABILITIES_PDF ) ) + bPS = false; + else + bPDF = false; + } + if( bPS ) + xFilterMgr->appendFilter( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PostScript" ) ), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "*.ps" ) ) ); + if( bPDF ) + xFilterMgr->appendFilter( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Portable Document Format" ) ), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "*.pdf" ) ) ); +#elif defined WNT + (void)pPrinter; + xFilterMgr->appendFilter( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "*.PRN" ) ), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "*.prn" ) ) ); +#endif + // add arbitrary files + xFilterMgr->appendFilter( String( VclResId( SV_STDTEXT_ALLFILETYPES ) ), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "*.*" ) ) ); + } + catch( lang::IllegalArgumentException rExc ) + { + DBG_ERRORFILE( "caught IllegalArgumentException when registering filter\n" ); + } + + if( xFilePicker->execute() == ui::dialogs::ExecutableDialogResults::OK ) + { + uno::Sequence< ::rtl::OUString > aPathSeq( xFilePicker->getFiles() ); + INetURLObject aObj( aPathSeq[0] ); + aResult = aObj.PathToFileName(); + } + } + } + return aResult; +} + +struct PrintJobAsync +{ + boost::shared_ptr<PrinterListener> mpListener; + JobSetup maInitSetup; + + PrintJobAsync( const boost::shared_ptr<PrinterListener>& i_pListener, + const JobSetup& i_rInitSetup + ) + : mpListener( i_pListener ), maInitSetup( i_rInitSetup ) + {} + + DECL_LINK( ExecJob, void* ); +}; + +IMPL_LINK( PrintJobAsync, ExecJob, void*, EMPTYARG ) +{ + Printer::ImplPrintJob( mpListener, maInitSetup ); + + // clean up, do not access members after this + delete this; + + return 0; +} + +void Printer::PrintJob( const boost::shared_ptr<PrinterListener>& i_pListener, + const JobSetup& i_rInitSetup + ) +{ + PrintJobAsync* pAsync = new PrintJobAsync( i_pListener, i_rInitSetup ); + Application::PostUserEvent( LINK( pAsync, PrintJobAsync, ExecJob ) ); +} + +void Printer::ImplPrintJob( const boost::shared_ptr<PrinterListener>& i_pListener, + const JobSetup& i_rInitSetup + ) +{ + // setup printer + boost::shared_ptr<PrinterListener> pListener( i_pListener ); + boost::shared_ptr<Printer> pPrinter( new Printer( i_rInitSetup.GetPrinterName() ) ); + pListener->setPrinter( pPrinter ); + + // setup page range selection + MultiSelection aSel; + int nPages = i_pListener->getPageCount(); + aSel.SetTotalRange( Range( 1, nPages ) ); + aSel.SelectAll(); + + // check if the printer brings up its own dialog + // in that case leave the work to that dialog + if( ! pListener->getPrinter()->GetCapabilities( PRINTER_CAPABILITIES_EXTERNALDIALOG ) ) + { + try + { + PrintDialog aDlg( NULL, i_pListener ); + if( ! aDlg.Execute() ) + return; + if( aDlg.isPrintToFile() ) + { + rtl::OUString aFile = queryFile( pListener->getPrinter().get() ); + if( ! aFile.getLength() ) + return; + pListener->getPrinter()->EnablePrintFile( TRUE ); + pListener->getPrinter()->SetPrintFile( aFile ); + } + aSel = aDlg.getPageSelection(); + pListener->getPrinter()->SetCopyCount( static_cast<USHORT>(aDlg.getCopyCount()), aDlg.isCollate() ); + } + catch( std::bad_alloc& ) + { + } + } + + pListener->setPageSelection( aSel ); + pListener->getPrinter()->StartJob( String( RTL_CONSTASCII_USTRINGPARAM( "FIXME: no job name" ) ), + pListener ); + + pListener->jobFinished(); +} + +bool Printer::StartJob( const XubString& i_rJobName, boost::shared_ptr<vcl::PrinterListener>& i_pListener ) +{ + mnError = PRINTER_OK; + + if ( IsDisplayPrinter() ) + return FALSE; + + if ( IsJobActive() || IsPrinting() ) + return FALSE; + + if( mpPrinterData->mbNextJobIsQuick ) + { + String aKey( RTL_CONSTASCII_USTRINGPARAM( "IsQuickJob" ) ); + if( maJobSetup.GetValue( aKey ).Len() == 0 ) + maJobSetup.SetValue( aKey, String( RTL_CONSTASCII_USTRINGPARAM( "true" ) ) ); + } + + ULONG nCopies = mnCopyCount; + BOOL bCollateCopy = mbCollateCopy; + BOOL bUserCopy = FALSE; + + if ( nCopies > 1 ) + { + ULONG nDevCopy; + + if ( bCollateCopy ) + nDevCopy = GetCapabilities( PRINTER_CAPABILITIES_COLLATECOPIES ); + else + nDevCopy = GetCapabilities( PRINTER_CAPABILITIES_COPIES ); + + // Muessen Kopien selber gemacht werden? + if ( nCopies > nDevCopy ) + { + bUserCopy = TRUE; + nCopies = 1; + bCollateCopy = FALSE; + } + } + else + bCollateCopy = FALSE; + + + ImplSVData* pSVData = ImplGetSVData(); + mpPrinter = pSVData->mpDefInst->CreatePrinter( mpInfoPrinter ); + + if ( !mpPrinter ) + return FALSE; + + XubString* pPrintFile; + if ( mbPrintFile ) + pPrintFile = &maPrintFile; + else + pPrintFile = NULL; + + maJobName = i_rJobName; + mnCurPage = 1; + mnCurPrintPage = 1; + mbPrinting = TRUE; + if( ImplGetSVData()->maGDIData.mbPrinterPullModel ) + { + mbJobActive = TRUE; + // sallayer does all necesseary page printing + if( mpPrinter->StartJob( pPrintFile, + Application::GetDisplayName(), + maJobSetup.ImplGetConstData(), + *i_pListener ) ) + { + EndJob(); + } + else + { + mnError = ImplSalPrinterErrorCodeToVCL( mpPrinter->GetErrorCode() ); + if ( !mnError ) + mnError = PRINTER_GENERALERROR; + pSVData->mpDefInst->DestroyPrinter( mpPrinter ); + mnCurPage = 0; + mnCurPrintPage = 0; + mbPrinting = FALSE; + mpPrinter = NULL; + + return false; + } + } + else + { + if( mpPrinter->StartJob( pPrintFile, + i_rJobName, + Application::GetDisplayName(), + nCopies, bCollateCopy, + maJobSetup.ImplGetConstData() ) ) + { + mbJobActive = TRUE; + MultiSelection aSel( i_pListener->getPageSelection() ); + i_pListener->createProgressDialog(); + for( long nPage = aSel.FirstSelected(); nPage != long(SFX_ENDOFSELECTION); nPage = aSel.NextSelected() ) + { + // remember MultiSelection is 1 based (due to user input) + i_pListener->printFilteredPage( static_cast<int>(nPage-1) ); + } + EndJob(); + } + else + { + mnError = ImplSalPrinterErrorCodeToVCL( mpPrinter->GetErrorCode() ); + if ( !mnError ) + mnError = PRINTER_GENERALERROR; + pSVData->mpDefInst->DestroyPrinter( mpPrinter ); + mnCurPage = 0; + mnCurPrintPage = 0; + mbPrinting = FALSE; + mpPrinter = NULL; + + return false; + } + } + + return true; +} + +PrinterListener::~PrinterListener() +{ + delete mpImplData; +} + +const boost::shared_ptr<Printer>& PrinterListener::getPrinter() const +{ + return mpImplData->mpPrinter; +} + +const MultiSelection& PrinterListener::getPageSelection() const +{ + return mpImplData->maSelection; +} + +void PrinterListener::setPrinter( const boost::shared_ptr<Printer>& i_rPrinter ) +{ + mpImplData->mpPrinter = i_rPrinter; +} + +void PrinterListener::setPageSelection( const MultiSelection& i_rSel ) +{ + mpImplData->maSelection = i_rSel; +} + +static void modifyJobSetup( Printer* pPrinter, const Sequence< PropertyValue >& i_rProps ) +{ + for( sal_Int32 nProperty = 0, nPropertyCount = i_rProps.getLength(); nProperty < nPropertyCount; ++nProperty ) + { + if( i_rProps[ nProperty ].Name.equalsAscii( "PageSize" ) ) + { + Size aPageSize; + awt::Size aSize; + i_rProps[ nProperty].Value >>= aSize; + aPageSize.Width() = aSize.Width; + aPageSize.Height() = aSize.Height; + + Size aCurSize( pPrinter->GetPaperSize() ); + if( aPageSize != aCurSize ) + pPrinter->SetPaperSizeUser( aPageSize ); + } + } +} + +void PrinterListener::printFilteredPage( int i_nPage ) +{ + // update progress if necessary + if( mpImplData->mpProgress ) + { + // do nothing if printing is canceled + if( mpImplData->mpProgress->isCanceled() ) + return; + mpImplData->mpProgress->tick(); + Application::Reschedule( true ); + } + + // get page parameters + Sequence< PropertyValue > aPageParm( getPageParameters( i_nPage ) ); + const MapMode aMapMode( MAP_100TH_MM ); + + mpImplData->mpPrinter->Push(); + mpImplData->mpPrinter->SetMapMode( aMapMode ); + + // modify job setup if necessary + modifyJobSetup( mpImplData->mpPrinter.get(), aPageParm ); + + mpImplData->mpPrinter->EnableOutput( FALSE ); + + GDIMetaFile aPageFile; + aPageFile.Record( mpImplData->mpPrinter.get() ); + + printPage( i_nPage ); + + aPageFile.Stop(); + aPageFile.WindStart(); + mpImplData->mpPrinter->Pop(); + + ULONG nRestoreDrawMode = mpImplData->mpPrinter->GetDrawMode(); + sal_Int32 nMaxBmpDPIX = mpImplData->mpPrinter->ImplGetDPIX(); + sal_Int32 nMaxBmpDPIY = mpImplData->mpPrinter->ImplGetDPIY(); + + const PrinterOptions& rPrinterOptions = mpImplData->mpPrinter->GetPrinterOptions(); + + static const sal_Int32 OPTIMAL_BMP_RESOLUTION = 300; + static const sal_Int32 NORMAL_BMP_RESOLUTION = 200; + + + if( rPrinterOptions.IsReduceBitmaps() ) + { + // calculate maximum resolution for bitmap graphics + if( PRINTER_BITMAP_OPTIMAL == rPrinterOptions.GetReducedBitmapMode() ) + { + nMaxBmpDPIX = std::min( sal_Int32(OPTIMAL_BMP_RESOLUTION), nMaxBmpDPIX ); + nMaxBmpDPIY = std::min( sal_Int32(OPTIMAL_BMP_RESOLUTION), nMaxBmpDPIY ); + } + else if( PRINTER_BITMAP_NORMAL == rPrinterOptions.GetReducedBitmapMode() ) + { + nMaxBmpDPIX = std::min( sal_Int32(NORMAL_BMP_RESOLUTION), nMaxBmpDPIX ); + nMaxBmpDPIY = std::min( sal_Int32(NORMAL_BMP_RESOLUTION), nMaxBmpDPIY ); + } + else + { + nMaxBmpDPIX = std::min( sal_Int32(rPrinterOptions.GetReducedBitmapResolution()), nMaxBmpDPIX ); + nMaxBmpDPIY = std::min( sal_Int32(rPrinterOptions.GetReducedBitmapResolution()), nMaxBmpDPIY ); + } + } + + // convert to greysacles + if( rPrinterOptions.IsConvertToGreyscales() ) + { + mpImplData->mpPrinter->SetDrawMode( mpImplData->mpPrinter->GetDrawMode() | + ( DRAWMODE_GRAYLINE | DRAWMODE_GRAYFILL | DRAWMODE_GRAYTEXT | + DRAWMODE_GRAYBITMAP | DRAWMODE_GRAYGRADIENT ) ); + } + + // disable transparency output + if( rPrinterOptions.IsReduceTransparency() && ( PRINTER_TRANSPARENCY_NONE == rPrinterOptions.GetReducedTransparencyMode() ) ) + { + mpImplData->mpPrinter->SetDrawMode( mpImplData->mpPrinter->GetDrawMode() | DRAWMODE_NOTRANSPARENCY ); + } + + GDIMetaFile aCleanedFile; + mpImplData->mpPrinter->RemoveTransparenciesFromMetaFile( aPageFile, aCleanedFile, nMaxBmpDPIX, nMaxBmpDPIY, + rPrinterOptions.IsReduceTransparency(), + rPrinterOptions.GetReducedTransparencyMode() == PRINTER_TRANSPARENCY_AUTO, + rPrinterOptions.IsReduceBitmaps() && rPrinterOptions.IsReducedBitmapIncludesTransparency() + ); + + mpImplData->mpPrinter->EnableOutput( TRUE ); + + // actually print the page + mpImplData->mpPrinter->StartPage(); + + mpImplData->mpPrinter->Push(); + mpImplData->mpPrinter->SetMapMode( MAP_100TH_MM ); + aCleanedFile.WindStart(); + aCleanedFile.Play( mpImplData->mpPrinter.get() ); + mpImplData->mpPrinter->Pop(); + + mpImplData->mpPrinter->EndPage(); + + mpImplData->mpPrinter->SetDrawMode( nRestoreDrawMode ); +} + +void PrinterListener::jobFinished() +{ +} + +Sequence< PropertyValue > PrinterListener::getJobProperties( const Sequence< PropertyValue >& i_rMergeList ) const +{ + std::hash_set< rtl::OUString, rtl::OUStringHash > aMergeSet; + size_t nResultLen = size_t(i_rMergeList.getLength()) + mpImplData->maUIProperties.size(); + for( int i = 0; i < i_rMergeList.getLength(); i++ ) + aMergeSet.insert( i_rMergeList[i].Name ); + + Sequence< PropertyValue > aResult( nResultLen ); + for( int i = 0; i < i_rMergeList.getLength(); i++ ) + aResult[i] = i_rMergeList[i]; + int nCur = i_rMergeList.getLength(); + for( size_t i = 0; i < mpImplData->maUIProperties.size(); i++ ) + { + if( aMergeSet.find( mpImplData->maUIProperties[i].Name ) == aMergeSet.end() ) + aResult[nCur++] = mpImplData->maUIProperties[i]; + } + aResult.realloc( nCur ); + return aResult; +} + +const Sequence< beans::PropertyValue >& PrinterListener::getUIOptions() const +{ + return mpImplData->maUIOptions; +} + +com::sun::star::beans::PropertyValue* PrinterListener::getValue( const rtl::OUString& i_rProperty ) +{ + std::hash_map< rtl::OUString, size_t, rtl::OUStringHash >::const_iterator it = + mpImplData->maPropertyToIndex.find( i_rProperty ); + return it != mpImplData->maPropertyToIndex.end() ? &mpImplData->maUIProperties[it->second] : NULL; +} + +const com::sun::star::beans::PropertyValue* PrinterListener::getValue( const rtl::OUString& i_rProperty ) const +{ + std::hash_map< rtl::OUString, size_t, rtl::OUStringHash >::const_iterator it = + mpImplData->maPropertyToIndex.find( i_rProperty ); + return it != mpImplData->maPropertyToIndex.end() ? &mpImplData->maUIProperties[it->second] : NULL; +} + +void PrinterListener::setUIOptions( const Sequence< beans::PropertyValue >& i_rOptions ) +{ + DBG_ASSERT( mpImplData->maUIOptions.getLength() == 0, "setUIOptions called twice !" ); + + mpImplData->maUIOptions = i_rOptions; + mpImplData->maUIProperties.clear(); + mpImplData->maPropertyToIndex.clear(); + mpImplData->maUIPropertyEnabled.clear(); + + for( int i = 0; i < i_rOptions.getLength(); i++ ) + { + Sequence< beans::PropertyValue > aOptProp; + i_rOptions[i].Value >>= aOptProp; + bool bIsEnabled = true; + bool bHaveProperty = false; + vcl::ImplPrinterListenerData::ControlDependency aDep; + for( int n = 0; n < aOptProp.getLength(); n++ ) + { + const beans::PropertyValue& rEntry( aOptProp[ n ] ); + if( rEntry.Name.equalsAscii( "Property" ) ) + { + PropertyValue aVal; + rEntry.Value >>= aVal; + DBG_ASSERT( mpImplData->maPropertyToIndex.find( aVal.Name ) + == mpImplData->maPropertyToIndex.end(), "duplicate property entry" ); + mpImplData->maPropertyToIndex[ aVal.Name ] = mpImplData->maUIProperties.size(); + mpImplData->maUIProperties.push_back( aVal ); + bHaveProperty = true; + } + else if( rEntry.Name.equalsAscii( "Enabled" ) ) + { + sal_Bool bValue = sal_True; + rEntry.Value >>= bValue; + bIsEnabled = bValue; + } + else if( rEntry.Name.equalsAscii( "DependsOnName" ) ) + { + rEntry.Value >>= aDep.maDependsOnName; + } + else if( rEntry.Name.equalsAscii( "DependsOnEntry" ) ) + { + rEntry.Value >>= aDep.mnDependsOnEntry; + } + } + if( bHaveProperty ) + { + mpImplData->maUIPropertyEnabled.push_back( bIsEnabled ); + if( aDep.maDependsOnName.getLength() > 0 ) + mpImplData->maControlDependencies[ mpImplData->maUIProperties.back().Name ] = aDep; + } + } +} + +void PrinterListener::enableUIOption( const rtl::OUString& i_rProperty, bool i_bEnable ) +{ + std::hash_map< rtl::OUString, size_t, rtl::OUStringHash >::const_iterator it = + mpImplData->maPropertyToIndex.find( i_rProperty ); + if( it != mpImplData->maPropertyToIndex.end() ) + { + // call handler only for actual changes + if( ( mpImplData->maUIPropertyEnabled[ it->second ] && ! i_bEnable ) || + ( ! mpImplData->maUIPropertyEnabled[ it->second ] && i_bEnable ) ) + { + mpImplData->maUIPropertyEnabled[ it->second ] = i_bEnable; + rtl::OUString aPropName( i_rProperty ); + mpImplData->maOptionChangeHdl.Call( &aPropName ); + } + } +} + +bool PrinterListener::isUIOptionEnabled( const rtl::OUString& i_rProperty ) const +{ + bool bEnabled = false; + std::hash_map< rtl::OUString, size_t, rtl::OUStringHash >::const_iterator prop_it = + mpImplData->maPropertyToIndex.find( i_rProperty ); + if( prop_it != mpImplData->maPropertyToIndex.end() ) + { + bEnabled = mpImplData->maUIPropertyEnabled[prop_it->second]; + + if( bEnabled ) + { + // check control dependencies + vcl::ImplPrinterListenerData::ControlDependencyMap::const_iterator it = + mpImplData->maControlDependencies.find( i_rProperty ); + if( it != mpImplData->maControlDependencies.end() ) + { + // check if the dependency is enabled + // if the dependency is disabled, we are too + bEnabled = isUIOptionEnabled( it->second.maDependsOnName ); + + if( bEnabled ) + { + // does the dependency have the correct value ? + const com::sun::star::beans::PropertyValue* pVal = getValue( it->second.maDependsOnName ); + OSL_ENSURE( pVal, "unknown property in dependency" ); + if( pVal ) + { + sal_Int32 nDepVal; + sal_Bool bDepVal; + if( pVal->Value >>= nDepVal ) + { + bEnabled = (nDepVal == it->second.mnDependsOnEntry); + } + else if( pVal->Value >>= bDepVal ) + { + // could be a dependency on a checked boolean + // in this case the dependency is on a non zero for checked value + bEnabled = ( bDepVal && it->second.mnDependsOnEntry != 0) || + ( ! bDepVal && it->second.mnDependsOnEntry == 0); + } + else + { + // if the type does not match something is awry + OSL_ENSURE( 0, "strange type in control dependency" ); + bEnabled = false; + } + } + } + } + } + } + return bEnabled; +} + +void PrinterListener::setOptionChangeHdl( const Link& i_rHdl ) +{ + mpImplData->maOptionChangeHdl = i_rHdl; +} + +void PrinterListener::createProgressDialog() +{ + if( ! mpImplData->mpProgress ) + { + mpImplData->mpProgress = new PrintProgressDialog( NULL, mpImplData->maSelection.GetSelectCount() ); + mpImplData->mpProgress->Show(); + } +} diff --git a/vcl/source/src/makefile.mk b/vcl/source/src/makefile.mk index cf01c74b977d..7772af5a0978 100644 --- a/vcl/source/src/makefile.mk +++ b/vcl/source/src/makefile.mk @@ -8,7 +8,7 @@ # # $RCSfile: makefile.mk,v $ # -# $Revision: 1.8 $ +# $Revision: 1.8.114.1 $ # # This file is part of OpenOffice.org. # @@ -47,7 +47,8 @@ SRC1FILES= images.src \ stdtext.src \ helptext.src \ units.src \ - btntext.src + btntext.src \ + print.src RESLIB1NAME= $(RESTARGET) RESLIB1IMAGES= $(PRJ)$/source/src diff --git a/vcl/source/src/print.src b/vcl/source/src/print.src new file mode 100644 index 000000000000..e8543515d68c --- /dev/null +++ b/vcl/source/src/print.src @@ -0,0 +1,277 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: print.src,v $ + * $Revision: 1.1.2.4 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "vcl/svids.hrc" + +ModalDialog SV_DLG_PRINT +{ + Text [en-US] = "Printing"; + Closeable = TRUE; + Sizeable = TRUE; + Moveable = TRUE; + SVLook = TRUE; + + Size = MAP_APPFONT( 350, 195 ); + + OKButton SV_PRINT_OK + { + DefButton = TRUE; + Pos = MAP_APPFONT( 240, 175 ); + Size = MAP_APPFONT( 50, 15 ); + }; + CancelButton SV_PRINT_CANCEL + { + Pos = MAP_APPFONT( 295, 175 ); + Size = MAP_APPFONT( 50, 15 ); + }; + + Window SV_PRINT_PAGE_PREVIEW + { + Pos = MAP_APPFONT( 5, 5 ); + Size = MAP_APPFONT( 130, 130 ); + Border = TRUE; + }; + ScrollBar SV_PRINT_PAGE_SCROLL + { + Pos = MAP_APPFONT( 5, 140 ); + Size = MAP_APPFONT( 130, 10 ); + SVLook = TRUE; + HScroll = TRUE; + TabStop = TRUE; + }; + FixedText SV_PRINT_PAGE_TXT + { + Pos = MAP_APPFONT( 5,150 ); + Size = MAP_APPFONT( 130, 10 ); + Text [ en-US ] = "Page %p of %n"; + Center = TRUE; + }; + TabControl SV_PRINT_TABCTRL + { + Pos = MAP_APPFONT( 140, 5 ); + Size = MAP_APPFONT( 205, 155 ); + }; + FixedLine SV_PRINT_BUTTONLINE + { + Pos = MAP_APPFONT( 0, 165 ); + Size = MAP_APPFONT( 350, 8 ); + }; + + TabPage SV_PRINT_TAB_PRINTER + { + Text [en-US] = "Printer"; + Hide = TRUE; + + ListBox SV_PRINT_PRINTERS + { + Pos = MAP_APPFONT( 5, 5 ); + Size = MAP_APPFONT( 100, 200 ); + DropDown = TRUE; + }; + PushButton SV_PRINT_PRT_SETUP + { + Pos = MAP_APPFONT( 115, 5 ); + Size = MAP_APPFONT( 50, 15 ); + Text [en-US] = "Properties..."; + }; + FixedText SV_PRINT_PRT_TYPE + { + Pos = MAP_APPFONT( 5, 30 ); + Size = MAP_APPFONT( 40, 10 ); + Text [en-US] = "Type"; + }; + FixedText SV_PRINT_PRT_TYPE_TXT + { + Pos = MAP_APPFONT( 50, 30 ); + Size = MAP_APPFONT( 200, 10 ); + }; + FixedText SV_PRINT_PRT_STATUS + { + Pos = MAP_APPFONT( 5, 42 ); + Size = MAP_APPFONT( 40, 10 ); + Text [en-US] = "Status"; + }; + FixedText SV_PRINT_PRT_STATUS_TXT + { + Pos = MAP_APPFONT( 50, 42 ); + Size = MAP_APPFONT( 200, 10 ); + }; + FixedText SV_PRINT_PRT_LOCATION + { + Pos = MAP_APPFONT( 5, 54 ); + Size = MAP_APPFONT( 40, 10 ); + Text [en-US] = "Location"; + }; + FixedText SV_PRINT_PRT_LOCATION_TXT + { + Pos = MAP_APPFONT( 50, 54 ); + Size = MAP_APPFONT( 200, 10 ); + }; + FixedText SV_PRINT_PRT_COMMENT + { + Pos = MAP_APPFONT( 5, 66 ); + Size = MAP_APPFONT( 40, 10 ); + Text [en-US] = "Comment"; + }; + FixedText SV_PRINT_PRT_COMMENT_TXT + { + Pos = MAP_APPFONT( 50, 66 ); + Size = MAP_APPFONT( 200, 10 ); + }; + }; + + TabPage SV_PRINT_TAB_JOB + { + Text [en-US] = "Job Setup"; + Hide = TRUE; + + ListBox SV_PRINT_PRINTERS + { + Pos = MAP_APPFONT( 5, 5 ); + Size = MAP_APPFONT( 100, 200 ); + DropDown = TRUE; + }; + CheckBox SV_PRINT_PRT_TOFILE + { + Pos = MAP_APPFONT( 15, 20 ); + Size = MAP_APPFONT( 200, 12 ); + Text [en-US] = "Print to file"; + }; + FixedLine SV_PRINT_RANGE + { + Pos = MAP_APPFONT( 5, 30 ); + Size = MAP_APPFONT( 150, 10 ); + Text [en-US] = "Print range"; + }; + RadioButton SV_PRINT_ALL + { + Pos = MAP_APPFONT( 10, 40 ); + Size = MAP_APPFONT( 145, 15 ); + Text [en-US] = "All pages"; + Check = TRUE; + }; + RadioButton SV_PRINT_PAGERANGE + { + Pos = MAP_APPFONT( 10, 55 ); + Size = MAP_APPFONT( 60, 15 ); + Text [en-US] = "Pages"; + }; + Edit SV_PRINT_PAGERANGE_EDIT + { + Pos = MAP_APPFONT( 70, 55 ); + Size = MAP_APPFONT( 80, 15 ); + Border = TRUE; + }; + RadioButton SV_PRINT_SELECTION + { + Pos = MAP_APPFONT( 10, 70 ); + Size = MAP_APPFONT( 145, 15 ); + Text [en-US] = "Selection"; + }; + + FixedLine SV_PRINT_COPIES + { + Pos = MAP_APPFONT( 5, 90 ); + Size = MAP_APPFONT( 150, 10 ); + Text [en-US] = "Copies"; + }; + FixedText SV_PRINT_COPYCOUNT + { + Pos = MAP_APPFONT( 10, 100 ); + Size = MAP_APPFONT( 80, 10 ); + Text [en-US] = "Number of copies"; + }; + NumericField SV_PRINT_COPYCOUNT_FIELD + { + Pos = MAP_APPFONT( 90, 100 ); + Size = MAP_APPFONT( 40, 10 ); + Border = TRUE; + Spin = TRUE; + Minimum = 1; + Maximum = 16384; + Value = 1; + }; + FixedImage SV_PRINT_COLLATE_IMAGE + { + Pos = MAP_APPFONT( 10, 120 ); + Size = MAP_PIXEL( 80, 30 ); + }; + CheckBox SV_PRINT_COLLATE + { + Pos = MAP_APPFONT( 80, 120 ); + Size = MAP_APPFONT( 70, 10 ); + Text [en-US] = "Collate"; + }; + + Image SV_PRINT_COLLATE_IMG + { + ImageBitmap = Bitmap { File = "collate.png" ; }; + }; + + Image SV_PRINT_NOCOLLATE_IMG + { + ImageBitmap = Bitmap { File = "ncollate.png" ; }; + }; + + Image SV_PRINT_COLLATE_HC_IMG + { + ImageBitmap = Bitmap { File = "collate_h.png" ; }; + }; + + Image SV_PRINT_NOCOLLATE_HC_IMG + { + ImageBitmap = Bitmap { File = "ncollate_h.png" ; }; + }; + }; +}; + +ModelessDialog SV_DLG_PRINT_PROGRESS +{ + Text [en-US] = "Printing"; + Closeable = FALSE; + Sizeable = FALSE; + Moveable = TRUE; + SVLook = TRUE; + + Size = MAP_APPFONT( 120, 70 ); + + CancelButton SV_PRINT_PROGRESS_CANCEL + { + Pos = MAP_APPFONT( 35, 50 ); + Size = MAP_APPFONT( 50, 15 ); + }; + FixedText SV_PRINT_PROGRESS_TEXT + { + Pos = MAP_APPFONT( 5,10 ); + Size = MAP_APPFONT( 110, 10 ); + Text [ en-US ] = "Page %p of %n"; + Center = TRUE; + }; +}; diff --git a/vcl/source/src/stdtext.src b/vcl/source/src/stdtext.src index 5ad1cdceeb61..d4dca4915b6b 100644 --- a/vcl/source/src/stdtext.src +++ b/vcl/source/src/stdtext.src @@ -7,7 +7,7 @@ * OpenOffice.org - a multi-platform office productivity suite * * $RCSfile: stdtext.src,v $ - * $Revision: 1.53 $ + * $Revision: 1.53.84.1 $ * * This file is part of OpenOffice.org. * @@ -123,3 +123,8 @@ String SV_MAC_SCREENNNAME { Text [en-US] = "Screen %d"; }; + +String SV_STDTEXT_ALLFILETYPES +{ + Text [en-US] = "Any type"; +}; diff --git a/vcl/source/window/makefile.mk b/vcl/source/window/makefile.mk index cdd4aef73bb0..cadea48f6f7a 100644 --- a/vcl/source/window/makefile.mk +++ b/vcl/source/window/makefile.mk @@ -8,7 +8,7 @@ # # $RCSfile: makefile.mk,v $ # -# $Revision: 1.25 $ +# $Revision: 1.25.114.1 $ # # This file is part of OpenOffice.org. # @@ -70,6 +70,7 @@ SLOFILES= \ $(SLO)$/mnemonicengine.obj \ $(SLO)$/msgbox.obj \ $(SLO)$/scrwnd.obj \ + $(SLO)$/printdlg.obj \ $(SLO)$/seleng.obj \ $(SLO)$/split.obj \ $(SLO)$/splitwin.obj \ diff --git a/vcl/source/window/printdlg.cxx b/vcl/source/window/printdlg.cxx new file mode 100644 index 000000000000..739e9c036794 --- /dev/null +++ b/vcl/source/window/printdlg.cxx @@ -0,0 +1,1054 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: printdlg.cxx,v $ + * $Revision: 1.1.2.7 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#include "precompiled_vcl.hxx" + +#include "vcl/print.hxx" +#include "vcl/prndlg.hxx" +#include "vcl/dialog.hxx" +#include "vcl/button.hxx" +#include "vcl/svdata.hxx" +#include "vcl/svids.hrc" +#include "vcl/wall.hxx" +#include "vcl/jobset.h" +#include "vcl/status.hxx" +#include "vcl/decoview.hxx" + +#include "rtl/ustrbuf.hxx" + +#include "com/sun/star/awt/Size.hpp" + +using namespace vcl; +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::beans; + +PrintDialog::PrintPreviewWindow::PrintPreviewWindow( Window* i_pParent, const ResId& i_rId ) + : Window( i_pParent, i_rId ) +{ +} + +PrintDialog::PrintPreviewWindow::~PrintPreviewWindow() +{ +} + +void PrintDialog::PrintPreviewWindow::Paint( const Rectangle& i_rRect ) +{ + Window::Paint( i_rRect ); + + SetFillColor( Color( COL_WHITE ) ); + SetLineColor(); + DrawRect( Rectangle( Point( 0, 0 ), GetSizePixel() )); + Push(); + SetMapMode( MAP_100TH_MM ); + maMtf.WindStart(); + maMtf.Play( this, Point( 0, 0 ), PixelToLogic( GetSizePixel() ) ); + Pop(); +} + +void PrintDialog::PrintPreviewWindow::setPreview( const GDIMetaFile& i_rNewPreview ) +{ + maMtf = i_rNewPreview; + Invalidate(); +} + +PrintDialog::PrinterTabPage::PrinterTabPage( Window* i_pParent, const ResId& rResId ) + : TabPage( i_pParent, rResId ) + , maPrinters( this, VclResId( SV_PRINT_PRINTERS) ) + , maSetupButton( this, VclResId( SV_PRINT_PRT_SETUP ) ) + , maType( this, VclResId( SV_PRINT_PRT_TYPE ) ) + , maTypeText( this, VclResId( SV_PRINT_PRT_TYPE_TXT ) ) + , maStatus( this, VclResId( SV_PRINT_PRT_STATUS ) ) + , maStatusText(this, VclResId( SV_PRINT_PRT_STATUS_TXT ) ) + , maLocation( this, VclResId( SV_PRINT_PRT_LOCATION ) ) + , maLocText( this, VclResId( SV_PRINT_PRT_LOCATION_TXT ) ) + , maComment( this, VclResId( SV_PRINT_PRT_COMMENT ) ) + , maCommentText( this, VclResId( SV_PRINT_PRT_COMMENT_TXT ) ) +{ + FreeResource(); +} + +PrintDialog::PrinterTabPage::~PrinterTabPage() +{ +} + +PrintDialog::JobTabPage::JobTabPage( Window* i_pParent, const ResId& rResId ) + : TabPage( i_pParent, rResId ) + , maPrinters( this, VclResId( SV_PRINT_PRINTERS) ) + , maToFileBox( this, VclResId( SV_PRINT_PRT_TOFILE ) ) + , maPrintRange( this, VclResId( SV_PRINT_RANGE ) ) + , maAllButton( this, VclResId( SV_PRINT_ALL ) ) + , maPagesButton( this, VclResId( SV_PRINT_PAGERANGE ) ) + , maSelectionButton( this, VclResId( SV_PRINT_SELECTION ) ) + , maPagesEdit( this, VclResId( SV_PRINT_PAGERANGE_EDIT ) ) + , maCopies( this, VclResId( SV_PRINT_COPIES ) ) + , maCopyCount( this, VclResId( SV_PRINT_COPYCOUNT ) ) + , maCopyCountField( this, VclResId( SV_PRINT_COPYCOUNT_FIELD ) ) + , maCollateBox( this, VclResId( SV_PRINT_COLLATE ) ) + , maCollateImage( this, VclResId( SV_PRINT_COLLATE_IMAGE ) ) + , maCollateImg( VclResId( SV_PRINT_COLLATE_IMG ) ) + , maCollateHCImg( VclResId( SV_PRINT_COLLATE_HC_IMG ) ) + , maNoCollateImg( VclResId( SV_PRINT_NOCOLLATE_IMG ) ) + , maNoCollateHCImg( VclResId( SV_PRINT_NOCOLLATE_HC_IMG ) ) +{ + FreeResource(); +} + +PrintDialog::JobTabPage::~JobTabPage() +{ +} + +PrintDialog::PrintDialog( Window* i_pParent, const boost::shared_ptr<PrinterListener>& i_rListener ) + : ModalDialog( i_pParent, VclResId( SV_DLG_PRINT ) ) + , maOKButton( this, VclResId( SV_PRINT_OK ) ) + , maCancelButton( this, VclResId( SV_PRINT_CANCEL ) ) + , maPreviewWindow( this, VclResId( SV_PRINT_PAGE_PREVIEW ) ) + , maPageText( this, VclResId( SV_PRINT_PAGE_TXT ) ) + , maPageScrollbar( this, VclResId( SV_PRINT_PAGE_SCROLL ) ) + , maTabCtrl( this, VclResId( SV_PRINT_TABCTRL ) ) + , maPrinterPage( &maTabCtrl, VclResId( SV_PRINT_TAB_PRINTER ) ) + , maJobPage( &maTabCtrl, VclResId( SV_PRINT_TAB_JOB ) ) + , maButtonLine( this, VclResId( SV_PRINT_BUTTONLINE ) ) + , maPListener( i_rListener ) + , mnCurPage( 0 ) + , mnCachedPages( 0 ) +{ + FreeResource(); + + // insert the tab pages + maTabCtrl.InsertPage( SV_PRINT_TAB_JOB, maJobPage.GetText() ); + maTabCtrl.SetTabPage( SV_PRINT_TAB_JOB, &maJobPage ); + maTabCtrl.InsertPage( SV_PRINT_PAGE_PREVIEW, maPrinterPage.GetText() ); + maTabCtrl.SetTabPage( SV_PRINT_PAGE_PREVIEW, &maPrinterPage ); + + maPageStr = maPageText.GetText(); + // save space for the preview window + maPreviewSpace = Rectangle( maPreviewWindow.GetPosPixel(), maPreviewWindow.GetSizePixel() ); + // get the first page + preparePreview(); + + // set up the scrollbar for the preview pages + maPageScrollbar.SetScrollHdl( LINK( this, PrintDialog, ScrollHdl ) ); + maPageScrollbar.SetEndScrollHdl( LINK( this, PrintDialog, ScrollEndHdl ) ); + maPageScrollbar.EnableDrag( TRUE ); + + // fill printer listbox + const std::vector< rtl::OUString >& rQueues( Printer::GetPrinterQueues() ); + for( std::vector< rtl::OUString >::const_iterator it = rQueues.begin(); + it != rQueues.end(); ++it ) + { + maPrinterPage.maPrinters.InsertEntry( *it ); + maJobPage.maPrinters.InsertEntry( *it ); + } + // select current printer + if( maPrinterPage.maPrinters.GetEntryPos( maPListener->getPrinter()->GetName() ) != LISTBOX_ENTRY_NOTFOUND ) + { + maPrinterPage.maPrinters.SelectEntry( maPListener->getPrinter()->GetName() ); + maJobPage.maPrinters.SelectEntry( maPListener->getPrinter()->GetName() ); + } + else + { + // fall back to default printer + maPrinterPage.maPrinters.SelectEntry( Printer::GetDefaultPrinterName() ); + maJobPage.maPrinters.SelectEntry( Printer::GetDefaultPrinterName() ); + maPListener->setPrinter( boost::shared_ptr<Printer>( new Printer( Printer::GetDefaultPrinterName() ) ) ); + } + // update the text fields for the printer + updatePrinterText(); + + // set a select handler + maPrinterPage.maPrinters.SetSelectHdl( LINK( this, PrintDialog, SelectHdl ) ); + maJobPage.maPrinters.SetSelectHdl( LINK( this, PrintDialog, SelectHdl ) ); + + // setup page range edit + rtl::OUStringBuffer aBuf( 16 ); + aBuf.append( sal_Unicode('1') ); + if( mnCachedPages > 1 ) + { + aBuf.append( sal_Unicode('-') ); + aBuf.append( mnCachedPages ); + } + maJobPage.maPagesEdit.SetText( aBuf.makeStringAndClear() ); + + // setup click handler on the various buttons + maJobPage.maCollateBox.SetClickHdl( LINK( this, PrintDialog, ClickHdl ) ); + maJobPage.maAllButton.SetClickHdl( LINK( this, PrintDialog, ClickHdl ) ); + maJobPage.maSelectionButton.SetClickHdl( LINK( this, PrintDialog, ClickHdl ) ); + maJobPage.maPagesButton.SetClickHdl( LINK( this, PrintDialog, ClickHdl ) ); + maPrinterPage.maSetupButton.SetClickHdl( LINK( this, PrintDialog, ClickHdl ) ); + + // setup modify hdl + maJobPage.maCopyCountField.SetModifyHdl( LINK( this, PrintDialog, ModifyHdl ) ); + + // setup optional UI options set by application + setupOptionalUI(); + + // set change handler for UI options + maPListener->setOptionChangeHdl( LINK( this, PrintDialog, UIOptionsChanged ) ); + + // set min size pixel to current size + SetMinOutputSizePixel( GetOutputSizePixel() ); + + // setup dependencies + checkControlDependencies(); +} + +PrintDialog::~PrintDialog() +{ + while( ! maControls.empty() ) + { + delete maControls.front(); + maControls.pop_front(); + } +} + +bool PrintDialog::isPrintToFile() +{ + return maJobPage.maToFileBox.IsChecked(); +} + +int PrintDialog::getCopyCount() +{ + return static_cast<int>(maJobPage.maCopyCountField.GetValue()); +} + +bool PrintDialog::isCollate() +{ + return maJobPage.maCopyCountField.GetValue() > 1 ? maJobPage.maCollateBox.IsChecked() : FALSE; +} + +MultiSelection PrintDialog::getPageSelection() +{ + if( maJobPage.maPagesButton.IsChecked() ) + return MultiSelection( maJobPage.maPagesEdit.GetText() ); + else if( maJobPage.maAllButton.IsChecked() ) + { + MultiSelection aSel( Range( 1, maPListener->getPageCount() ) ); + aSel.SelectAll(); + return aSel; + } + DBG_ERROR( "NYI: Selection" ); + return MultiSelection(); +} + +void PrintDialog::setupOptionalUI() +{ + Window* pCurParent = 0; + long nCurY = 0, nXPos = 5; + USHORT nOptPageId = 9; + MapMode aFontMapMode( MAP_APPFONT ); + + Size aTabSize = maTabCtrl.GetSizePixel(); + const Sequence< PropertyValue >& rOptions( maPListener->getUIOptions() ); + for( int i = 0; i < rOptions.getLength(); i++ ) + { + Sequence< beans::PropertyValue > aOptProp; + rOptions[i].Value >>= aOptProp; + + // extract ui element + bool bEnabled = true; + rtl::OUString aCtrlType; + rtl::OUString aText; + rtl::OUString aPropertyName; + Sequence< rtl::OUString > aChoices; + sal_Int64 nMinValue = 0, nMaxValue = 0; + bool bDependency = false; + + for( int n = 0; n < aOptProp.getLength(); n++ ) + { + const beans::PropertyValue& rEntry( aOptProp[ n ] ); + if( rEntry.Name.equalsAscii( "Text" ) ) + { + rEntry.Value >>= aText; + } + else if( rEntry.Name.equalsAscii( "ControlType" ) ) + { + rEntry.Value >>= aCtrlType; + } + else if( rEntry.Name.equalsAscii( "Choices" ) ) + { + rEntry.Value >>= aChoices; + } + else if( rEntry.Name.equalsAscii( "Property" ) ) + { + PropertyValue aVal; + rEntry.Value >>= aVal; + aPropertyName = aVal.Name; + } + else if( rEntry.Name.equalsAscii( "Enabled" ) ) + { + sal_Bool bValue = sal_True; + rEntry.Value >>= bValue; + bEnabled = bValue; + } + else if( rEntry.Name.equalsAscii( "DependsOnName" ) ) + { + bDependency = true; + } + else if( rEntry.Name.equalsAscii( "MinValue" ) ) + { + rEntry.Value >>= nMinValue; + } + else if( rEntry.Name.equalsAscii( "MaxValue" ) ) + { + rEntry.Value >>= nMaxValue; + } + } + + if( aCtrlType.equalsAscii( "Group" ) || + aCtrlType.equalsAscii( "Subgroup" ) || + aCtrlType.equalsAscii( "Radio" ) || + aCtrlType.equalsAscii( "List" ) || + aCtrlType.equalsAscii( "Range" ) || + aCtrlType.equalsAscii( "Bool" ) ) + { + if( aCtrlType.equalsAscii( "Group" ) || ! pCurParent ) + { + // add new tab page + TabPage* pNewGroup = new TabPage( &maTabCtrl ); + maControls.push_front( pNewGroup ); + pCurParent = pNewGroup; + nCurY = 5; + nXPos = 5; + pNewGroup->SetText( aText ); + maTabCtrl.InsertPage( ++nOptPageId, aText ); + maTabCtrl.SetTabPage( nOptPageId, pNewGroup ); + } + + if( aCtrlType.equalsAscii( "Subgroup" ) && pCurParent ) + { + nXPos = 5; + FixedLine* pNewSub = new FixedLine( pCurParent ); + maControls.push_front( pNewSub ); + pNewSub->SetText( aText ); + nCurY += 4; + Size aPixelSize( aTabSize ); + aPixelSize.Width() /= 2; + aPixelSize.Height() = pCurParent->GetTextHeight() + 4; + pNewSub->SetPosSizePixel( pNewSub->LogicToPixel( Point( nXPos, nCurY ), aFontMapMode ), + aPixelSize ); + pNewSub->Show(); + nCurY += 12; + nXPos += 5; + } + else if( aCtrlType.equalsAscii( "Bool" ) && pCurParent ) + { + if( bDependency ) + nXPos += 5; + + // add a check box + CheckBox* pNewBox = new CheckBox( pCurParent ); + maControls.push_front( pNewBox ); + pNewBox->SetText( aText ); + + // FIXME: measure text + pNewBox->SetPosSizePixel( pNewBox->LogicToPixel( Point( nXPos, nCurY ), aFontMapMode ), + pNewBox->LogicToPixel( Size( 100, 10 ), aFontMapMode ) ); + nCurY += 12; + + pNewBox->Show(); + sal_Bool bVal = sal_False; + PropertyValue* pVal = maPListener->getValue( aPropertyName ); + if( pVal ) + pVal->Value >>= bVal; + pNewBox->Check( bVal ); + pNewBox->Enable( maPListener->isUIOptionEnabled( aPropertyName ) && pVal != NULL ); + pNewBox->SetToggleHdl( LINK( this, PrintDialog, UIOption_CheckHdl ) ); + + maPropertyToWindowMap.insert( std::pair< rtl::OUString, Window* >( aPropertyName, pNewBox ) ); + maControlToPropertyMap[pNewBox] = aPropertyName; + + if( bDependency ) + nXPos -= 5; + } + else if( aCtrlType.equalsAscii( "Radio" ) && pCurParent ) + { + long nOldXPos = nXPos; + if( aText.getLength() ) + { + // add a FixedText: + FixedText* pHeading = new FixedText( pCurParent ); + maControls.push_front( pHeading ); + pHeading->SetText( aText ); + Size aPixelSize( pHeading->LogicToPixel( Size( 10, 10 ), aFontMapMode ) ); + aPixelSize.Width() = aTabSize.Width() - aPixelSize.Width(); + pHeading->SetPosSizePixel( pHeading->LogicToPixel( Point( nXPos, nCurY ), aFontMapMode ), + aPixelSize ); + pHeading->Show(); + + nXPos += 10; + nCurY += 12; + } + + // iterate options + sal_Int32 nSelectVal = 0; + PropertyValue* pVal = maPListener->getValue( aPropertyName ); + if( pVal && pVal->Value.hasValue() ) + pVal->Value >>= nSelectVal; + for( sal_Int32 m = 0; m < aChoices.getLength(); m++ ) + { + RadioButton* pBtn = new RadioButton( pCurParent, m == 0 ? WB_GROUP : 0 ); + maControls.push_front( pBtn ); + pBtn->SetText( aChoices[m] ); + pBtn->Check( m == nSelectVal ); + Size aPixelSize( pBtn->LogicToPixel( Size( 10 + nXPos, 12 ), aFontMapMode ) ); + aPixelSize.Width() = aTabSize.Width() - aPixelSize.Width(); + pBtn->SetPosSizePixel( pBtn->LogicToPixel( Point( 15, nCurY ), aFontMapMode ), + aPixelSize ); + pBtn->Enable( maPListener->isUIOptionEnabled( aPropertyName ) ); + pBtn->SetToggleHdl( LINK( this, PrintDialog, UIOption_RadioHdl ) ); + pBtn->Show(); + maPropertyToWindowMap.insert( std::pair< rtl::OUString, Window* >( aPropertyName, pBtn ) ); + maControlToPropertyMap[pBtn] = aPropertyName; + maControlToNumValMap[pBtn] = m; + + nCurY += 12; + } + nXPos = nOldXPos; + } + else if( aCtrlType.equalsAscii( "List" ) && pCurParent ) + { + if( bDependency ) + nXPos += 5; + + // add a FixedText: + FixedText* pHeading = new FixedText( pCurParent ); + maControls.push_front( pHeading ); + pHeading->SetText( aText ); + Size aPixelSize( pHeading->LogicToPixel( Size( 10, 10 ), aFontMapMode ) ); + aPixelSize.Width() += pHeading->GetTextWidth( aText ); + pHeading->SetPosSizePixel( pHeading->LogicToPixel( Point( nXPos, nCurY ), aFontMapMode ), + aPixelSize ); + pHeading->Show(); + + ListBox* pList = new ListBox( pCurParent, WB_DROPDOWN | WB_BORDER ); + maControls.push_front( pList ); + + // iterate options + long nMaxTextWidth = 0; + for( sal_Int32 m = 0; m < aChoices.getLength(); m++ ) + { + pList->InsertEntry( aChoices[m] ); + long nEntryWidth = pList->GetTextWidth( aChoices[m] ); + if( nEntryWidth > nMaxTextWidth ) + nMaxTextWidth = nEntryWidth; + } + nMaxTextWidth += 30; + sal_Int32 nSelectVal = 0; + PropertyValue* pVal = maPListener->getValue( aPropertyName ); + if( pVal && pVal->Value.hasValue() ) + pVal->Value >>= nSelectVal; + pList->SelectEntryPos( static_cast<USHORT>(nSelectVal) ); + + aPixelSize = Size( pList->LogicToPixel( Size( 25, 12 ), aFontMapMode ) ); + aPixelSize.Width() = nMaxTextWidth; + aPixelSize.Height() *= aChoices.getLength() > 15 ? 15 : aChoices.getLength(); + + Point aListPos; + bool bDoAlign = false; + if( nMaxTextWidth + aPixelSize.Width() < aTabSize.Width() - 10 ) + { + aListPos = pHeading->GetPosPixel(); + aListPos.X() += pHeading->GetSizePixel().Width() + 5; + + // align heading and list box + bDoAlign = true; + } + else + { + nCurY += 12; + aListPos = pCurParent->LogicToPixel( Point( 15, nCurY ), aFontMapMode ); + } + + pList->SetPosSizePixel( aListPos, aPixelSize ); + pList->Enable( maPListener->isUIOptionEnabled( aPropertyName ) ); + pList->SetSelectHdl( LINK( this, PrintDialog, UIOption_SelectHdl ) ); + pList->Show(); + + maPropertyToWindowMap.insert( std::pair< rtl::OUString, Window* >( aPropertyName, pList ) ); + maControlToPropertyMap[pList] = aPropertyName; + nCurY += 16; + + if( bDoAlign ) + { + Point aPos = pHeading->GetPosPixel(); + Size aSize = pHeading->GetSizePixel(); + aPos.Y() += (pList->GetSizePixel().Height() - aSize.Height())/2; + pHeading->SetPosSizePixel( aPos, aSize ); + } + + if( bDependency ) + nXPos -= 5; + } + else if( aCtrlType.equalsAscii( "Range" ) && pCurParent ) + { + if( bDependency ) + nXPos += 5; + + // add a FixedText: + FixedText* pHeading = new FixedText( pCurParent ); + maControls.push_front( pHeading ); + pHeading->SetText( aText ); + Size aPixelSize( pHeading->LogicToPixel( Size( 10, 10 ), aFontMapMode ) ); + aPixelSize.Width() += pHeading->GetTextWidth( aText ); + pHeading->SetPosSizePixel( pHeading->LogicToPixel( Point( nXPos, nCurY ), aFontMapMode ), + aPixelSize ); + pHeading->Show(); + + NumericField* pField = new NumericField( pCurParent, WB_BORDER | WB_SPIN ); + maControls.push_front( pField ); + + // set min/max and current value + if( nMinValue != nMaxValue ) + { + pField->SetMin( nMinValue ); + pField->SetMax( nMaxValue ); + } + sal_Int64 nCurVal = 0; + PropertyValue* pVal = maPListener->getValue( aPropertyName ); + if( pVal && pVal->Value.hasValue() ) + pVal->Value >>= nCurVal; + pField->SetValue( nCurVal ); + + aPixelSize = Size( pField->LogicToPixel( Size( 80, 12 ), aFontMapMode ) ); + + Point aFieldPos; + bool bDoAlign = false; + if( aPixelSize.Width() < aTabSize.Width() - 10 ) + { + aFieldPos = pHeading->GetPosPixel(); + aFieldPos.X() += pHeading->GetSizePixel().Width() + 5; + + // align heading and list box + bDoAlign = true; + } + else + { + nCurY += 12; + aFieldPos = pCurParent->LogicToPixel( Point( 15, nCurY ), aFontMapMode ); + } + + pField->SetPosSizePixel( aFieldPos, aPixelSize ); + pField->Enable( maPListener->isUIOptionEnabled( aPropertyName ) ); + pField->SetModifyHdl( LINK( this, PrintDialog, UIOption_ModifyHdl ) ); + pField->Show(); + + maPropertyToWindowMap.insert( std::pair< rtl::OUString, Window* >( aPropertyName, pField ) ); + maControlToPropertyMap[pField] = aPropertyName; + nCurY += 16; + + if( bDoAlign ) + { + Point aPos = pHeading->GetPosPixel(); + Size aSize = pHeading->GetSizePixel(); + aPos.Y() += (pField->GetSizePixel().Height() - aSize.Height())/2; + pHeading->SetPosSizePixel( aPos, aSize ); + } + + if( bDependency ) + nXPos -= 5; + } + } + else + { + DBG_ERROR( "Unsupported UI option" ); + } + } +} + +void PrintDialog::checkControlDependencies() +{ + if( maJobPage.maCopyCountField.GetValue() > 1 ) + maJobPage.maCollateBox.Enable( TRUE ); + else + maJobPage.maCollateBox.Enable( FALSE ); + + maJobPage.maPagesEdit.Enable( maJobPage.maPagesButton.IsChecked() ); + Image aImg( maJobPage.maCollateBox.IsChecked() ? maJobPage.maCollateImg : maJobPage.maNoCollateImg ); + if( GetSettings().GetStyleSettings().GetFieldColor().IsDark() ) + aImg = maJobPage.maCollateBox.IsChecked() ? maJobPage.maCollateHCImg : maJobPage.maNoCollateHCImg; + + // adjust position and size of image + maJobPage.maCollateImage.SetSizePixel( aImg.GetSizePixel() ); + Point aPos( maJobPage.maCollateImage.GetPosPixel() ); + aPos.Y() = maJobPage.maCollateBox.GetPosPixel().Y(); + aPos.Y() -= (aImg.GetSizePixel().Height() - maJobPage.maCollateBox.GetSizePixel().Height())/2; + maJobPage.maCollateImage.SetPosPixel( aPos ); + maJobPage.maCollateImage.SetImage( aImg ); + + // enable setup button only for printers that can be setup + maPrinterPage.maSetupButton.Enable( maPListener->getPrinter()->HasSupport( SUPPORT_SETUPDIALOG ) ); +} + +void PrintDialog::checkOptionalControlDependencies() +{ + for( std::map< Window*, rtl::OUString >::iterator it = maControlToPropertyMap.begin(); + it != maControlToPropertyMap.end(); ++it ) + { + bool bShouldbeEnabled = maPListener->isUIOptionEnabled( it->second ); + bool bIsEnabled = it->first->IsEnabled(); + // Enable does not do a change check first, so can be less cheap than expected + if( bShouldbeEnabled != bIsEnabled ) + it->first->Enable( bShouldbeEnabled ); + } +} + +void PrintDialog::updatePrinterText() +{ + const QueueInfo* pInfo = Printer::GetQueueInfo( maPrinterPage.maPrinters.GetSelectEntry(), true ); + if( pInfo ) + { + maPrinterPage.maTypeText.SetText( pInfo->GetDriver() ); + // FIXME: status message + // maJobPage.maStatusText.SetText(); + maPrinterPage.maLocText.SetText( pInfo->GetLocation() ); + maPrinterPage.maCommentText.SetText( pInfo->GetComment() ); + } +} + +static rtl::OUString searchAndReplace( const rtl::OUString& i_rOrig, const char* i_pRepl, sal_Int32 i_nReplLen, sal_Int32 i_nReplacement ) +{ + sal_Int32 nPos = i_rOrig.indexOfAsciiL( i_pRepl, i_nReplLen ); + if( nPos != -1 ) + { + rtl::OUStringBuffer aBuf( i_rOrig.getLength() ); + aBuf.append( i_rOrig.getStr(), nPos ); + aBuf.append( i_nReplacement ); + if( nPos + i_nReplLen < i_rOrig.getLength() ) + aBuf.append( i_rOrig.getStr() + nPos + i_nReplLen ); + return aBuf.makeStringAndClear(); + } + return i_rOrig; +} + +void PrintDialog::setPreviewText( sal_Int32 nSetPage ) +{ + rtl::OUString aNewText( searchAndReplace( maPageStr, "%p", 2, nSetPage+1 ) ); + aNewText = searchAndReplace( aNewText, "%n", 2, mnCachedPages ); + maPageText.SetText( aNewText ); +} + +void PrintDialog::preparePreview() +{ + // page range may have changed depending on options + sal_Int32 nPages = maPListener->getPageCount(); + mnCachedPages = nPages; + + if( mnCurPage >= nPages ) + mnCurPage = nPages-1; + + setPreviewText( mnCurPage ); + + maPageScrollbar.SetRange( Range( 0, nPages-1 ) ); + maPageScrollbar.SetThumbPos( mnCurPage ); + + boost::shared_ptr<Printer> aPrt( maPListener->getPrinter() ); + + + const MapMode aMapMode( MAP_100TH_MM ); + aPrt->Push(); + aPrt->SetMapMode( aMapMode ); + + Size aPageSize( aPrt->GetPaperSize() ); + Sequence< PropertyValue > aPageParms( maPListener->getPageParameters( mnCurPage ) ); + for( sal_Int32 nProperty = 0, nPropertyCount = aPageParms.getLength(); nProperty < nPropertyCount; ++nProperty ) + { + if( aPageParms[ nProperty ].Name.equalsIgnoreAsciiCaseAscii( "PageSize" ) ) + { + awt::Size aSize; + aPageParms[ nProperty ].Value >>= aSize; + aPageSize.Width() = aSize.Width; + aPageSize.Height() = aSize.Height; + } + } + + aPrt->EnableOutput( FALSE ); + + GDIMetaFile aMtf; + aMtf.SetPrefSize( aPageSize ); + aMtf.SetPrefMapMode( aMapMode ); + aMtf.Record( &(*aPrt) ); + + maPListener->printPage( mnCurPage ); + + aMtf.Stop(); + aMtf.WindStart(); + aPrt->Pop(); + + Size aPreviewSize; + Point aPreviewPos = maPreviewSpace.TopLeft(); + const long nW = maPreviewSpace.GetSize().Width(); + const long nH = maPreviewSpace.GetSize().Height(); + if( aPageSize.Width() > aPageSize.Height() ) + { + aPreviewSize = Size( nW, nW * aPageSize.Height() / aPageSize.Width() ); + aPreviewPos.Y() += (maPreviewSpace.GetHeight() - aPreviewSize.Height())/2; + } + else + { + aPreviewSize = Size( nH * aPageSize.Width() / aPageSize.Height(), nH ); + aPreviewPos.X() += (maPreviewSpace.GetWidth() - aPreviewSize.Width())/2; + } + maPreviewWindow.SetPosSizePixel( aPreviewPos, aPreviewSize ); + const Size aLogicSize( maPreviewWindow.PixelToLogic( maPreviewWindow.GetSizePixel(), MapMode( MAP_100TH_MM ) ) ); + aMtf.Scale( double(aLogicSize.Width())/double(aPageSize.Width()), + double(aLogicSize.Height())/double(aPageSize.Height()) ); + maPreviewWindow.setPreview( aMtf ); +} + +IMPL_LINK( PrintDialog, ScrollHdl, ScrollBar*, pScrBar ) +{ + if( pScrBar == &maPageScrollbar ) + { + sal_Int32 nNewPage = static_cast<sal_Int32>( maPageScrollbar.GetThumbPos() ); + setPreviewText( nNewPage ); + } + return 0; +} + +IMPL_LINK( PrintDialog, ScrollEndHdl, ScrollBar*, pScrBar ) +{ + if( pScrBar == &maPageScrollbar ) + { + sal_Int32 nNewPage = static_cast<sal_Int32>( maPageScrollbar.GetThumbPos() ); + if( nNewPage != mnCurPage ) + { + mnCurPage = nNewPage; + preparePreview(); + } + } + return 0; +} + +IMPL_LINK( PrintDialog, SelectHdl, ListBox*, pBox ) +{ + if( pBox == &maPrinterPage.maPrinters || pBox == &maJobPage.maPrinters ) + { + String aNewPrinter( pBox->GetSelectEntry() ); + maJobPage.maPrinters.SelectEntry( aNewPrinter ); + maPrinterPage.maPrinters.SelectEntry( aNewPrinter ); + // set new printer + maPListener->setPrinter( boost::shared_ptr<Printer>( new Printer( aNewPrinter ) ) ); + // update text fields + updatePrinterText(); + } + return 0; +} + +IMPL_LINK( PrintDialog, ClickHdl, Button*, pButton ) +{ + if( pButton == &maPrinterPage.maSetupButton ) + { + maPListener->getPrinter()->Setup( this ); + } + checkControlDependencies(); + return 0; +} + +IMPL_LINK( PrintDialog, ModifyHdl, Edit*, EMPTYARG ) +{ + checkControlDependencies(); + return 0; +} + +IMPL_LINK( PrintDialog, UIOptionsChanged, void*, EMPTYARG ) +{ + checkOptionalControlDependencies(); + return 0; +} + +PropertyValue* PrintDialog::getValueForWindow( Window* i_pWindow ) const +{ + PropertyValue* pVal = NULL; + std::map< Window*, rtl::OUString >::const_iterator it = maControlToPropertyMap.find( i_pWindow ); + if( it != maControlToPropertyMap.end() ) + { + pVal = maPListener->getValue( it->second ); + DBG_ASSERT( pVal, "property value not found" ); + } + else + { + DBG_ERROR( "changed control not in property map" ); + } + return pVal; +} + +IMPL_LINK( PrintDialog, UIOption_CheckHdl, CheckBox*, i_pBox ) +{ + PropertyValue* pVal = getValueForWindow( i_pBox ); + if( pVal ) + { + sal_Bool bVal = i_pBox->IsChecked(); + pVal->Value <<= bVal; + + checkOptionalControlDependencies(); + + // update preview and page settings + preparePreview(); + } + return 0; +} + +IMPL_LINK( PrintDialog, UIOption_RadioHdl, RadioButton*, i_pBtn ) +{ + // this handler gets called for all radiobuttons that get unchecked, too + // however we only want one notificaction for the new value (that is for + // the button that gets checked) + if( i_pBtn->IsChecked() ) + { + PropertyValue* pVal = getValueForWindow( i_pBtn ); + std::map< Window*, sal_Int32 >::const_iterator it = maControlToNumValMap.find( i_pBtn ); + if( pVal && it != maControlToNumValMap.end() ) + { + + sal_Int32 nVal = it->second; + pVal->Value <<= nVal; + + checkOptionalControlDependencies(); + + // update preview and page settings + preparePreview(); + } + } + return 0; +} + +IMPL_LINK( PrintDialog, UIOption_SelectHdl, ListBox*, i_pBox ) +{ + PropertyValue* pVal = getValueForWindow( i_pBox ); + if( pVal ) + { + sal_Int32 nVal( i_pBox->GetSelectEntryPos() ); + pVal->Value <<= nVal; + + checkOptionalControlDependencies(); + + // update preview and page settings + preparePreview(); + } + return 0; +} + +IMPL_LINK( PrintDialog, UIOption_ModifyHdl, Edit*, i_pBox ) +{ + PropertyValue* pVal = getValueForWindow( i_pBox ); + if( pVal ) + { + NumericField* pNum = dynamic_cast<NumericField*>(i_pBox); + MetricField* pMetric = dynamic_cast<MetricField*>(i_pBox); + if( pNum ) + { + sal_Int64 nVal = pNum->GetValue(); + pVal->Value <<= nVal; + } + else if( pMetric ) + { + sal_Int64 nVal = pMetric->GetValue(); + pVal->Value <<= nVal; + } + else + { + rtl::OUString aVal( i_pBox->GetText() ); + pVal->Value <<= aVal; + } + + checkOptionalControlDependencies(); + + // update preview and page settings + preparePreview(); + } + return 0; +} + +void PrintDialog::Resize() +{ + Size aPixDiff( LogicToPixel( Size( 5, 5 ), MapMode( MAP_APPFONT ) ) ); + Size aWindowSize( GetOutputSizePixel() ); + + // position buttons from lower end, right to left + Size aBtnSize( maCancelButton.GetSizePixel() ); + Rectangle aBtnRect( Point( aWindowSize.Width() - aPixDiff.Width() - aBtnSize.Width(), + aWindowSize.Height() - aPixDiff.Height() - aBtnSize.Height() ), + aBtnSize ); + maCancelButton.SetPosSizePixel( aBtnRect.TopLeft(), aBtnRect.GetSize() ); + aBtnSize = maOKButton.GetSizePixel(); + aBtnRect = Rectangle( Point( aBtnRect.Left() - aPixDiff.Width() - aBtnSize.Width(), + aWindowSize.Height() - aPixDiff.Height() - aBtnSize.Height() ), + aBtnSize ); + maOKButton.SetPosSizePixel( aBtnRect.TopLeft(), aBtnRect.GetSize() ); + aBtnSize = maButtonLine.GetSizePixel(); + + // position fixed line above buttons + aBtnRect = Rectangle( Point( 0, aBtnRect.Top() - aPixDiff.Width() - aBtnSize.Height()/2 ), + Size( aWindowSize.Width(), aBtnSize.Height() ) ); + maButtonLine.SetPosSizePixel( aBtnRect.TopLeft(), aBtnRect.GetSize() ); + + // position tab control on upper right + aBtnSize = maTabCtrl.GetSizePixel(); + aBtnRect = Rectangle( Point( aWindowSize.Width() - aPixDiff.Width() - aBtnSize.Width(), + aPixDiff.Height() ), + Size( aBtnSize.Width(), maButtonLine.GetPosPixel().Y() - 2*aPixDiff.Height() ) ); + maTabCtrl.SetPosSizePixel( aBtnRect.TopLeft(), aBtnRect.GetSize() ); + + // set size for preview + long nMaxX = maTabCtrl.GetPosPixel().X() - 2*aPixDiff.Width(); + long nMaxY = maButtonLine.GetPosPixel().Y() + - 2 * aPixDiff.Height() + - maPageText.GetSizePixel().Height() + - maPageScrollbar.GetSizePixel().Height(); + long nPreviewLength = std::min( nMaxX, nMaxY ); + maPreviewSpace = Rectangle( Point( aPixDiff.Width(), aPixDiff.Height() ), + Size( nPreviewLength, nPreviewLength ) ); + + // position text and scrollbar below preview + aBtnRect = Rectangle( Point( aPixDiff.Width(), 2*aPixDiff.Height() + nPreviewLength ), + Size( nPreviewLength, maPageScrollbar.GetSizePixel().Height() ) ); + maPageScrollbar.SetPosSizePixel( aBtnRect.TopLeft(), aBtnRect.GetSize() ); + + aBtnRect.Top() = aBtnRect.Bottom() + aPixDiff.Height()/2; + aBtnRect.Bottom() = aBtnRect.Top() + maPageText.GetSizePixel().Height() - 1; + maPageText.SetPosSizePixel( aBtnRect.TopLeft(), aBtnRect.GetSize() ); + + // and do the preview + preparePreview(); +} + +// ----------------------------------------------------------------------------- +// +// PrintProgressDialog +// +// ----------------------------------------------------------------------------- + +PrintProgressDialog::PrintProgressDialog( Window* i_pParent, int i_nMax ) : + ModelessDialog( i_pParent, VclResId( SV_DLG_PRINT_PROGRESS ) ), + maText( this, VclResId( SV_PRINT_PROGRESS_TEXT ) ), + maButton( this, VclResId( SV_PRINT_PROGRESS_CANCEL ) ), + mbCanceled( false ), + mnCur( 0 ), + mnMax( i_nMax ), + mnProgressHeight( 15 ), + mbNativeProgress( false ) +{ + maStr = maText.GetText(); + + maButton.SetClickHdl( LINK( this, PrintProgressDialog, ClickHdl ) ); + +} + +PrintProgressDialog::~PrintProgressDialog() +{ +} + +IMPL_LINK( PrintProgressDialog, ClickHdl, Button*, pButton ) +{ + if( pButton == &maButton ) + mbCanceled = true; + + return 0; +} + +void PrintProgressDialog::implCalcProgressRect() +{ + if( IsNativeControlSupported( CTRL_PROGRESS, PART_ENTIRE_CONTROL ) ) + { + ImplControlValue aValue; + Region aControlRegion( Rectangle( Point(), Size( 100, mnProgressHeight ) ) ); + Region aNativeControlRegion, aNativeContentRegion; + if( GetNativeControlRegion( CTRL_PROGRESS, PART_ENTIRE_CONTROL, aControlRegion, + CTRL_STATE_ENABLED, aValue, rtl::OUString(), + aNativeControlRegion, aNativeContentRegion ) ) + { + mnProgressHeight = aNativeControlRegion.GetBoundRect().GetHeight(); + } + mbNativeProgress = true; + } + maProgressRect = Rectangle( Point( 10, maText.GetPosPixel().Y() + maText.GetSizePixel().Height() + 8 ), + Size( GetSizePixel().Width() - 20, mnProgressHeight ) ); +} + +void PrintProgressDialog::setProgress( int i_nCurrent, int i_nMax ) +{ + if( maProgressRect.IsEmpty() ) + implCalcProgressRect(); + + mnCur = i_nCurrent; + if( i_nMax != -1 ) + mnMax = i_nMax; + + rtl::OUString aNewText( searchAndReplace( maStr, "%p", 2, mnCur ) ); + aNewText = searchAndReplace( aNewText, "%n", 2, mnMax ); + maText.SetText( aNewText ); + + // update progress + Invalidate( maProgressRect, INVALIDATE_UPDATE ); +} + +void PrintProgressDialog::tick() +{ + if( mnCur < mnMax ) + setProgress( ++mnCur ); +} + +void PrintProgressDialog::Paint( const Rectangle& ) +{ + Push( PUSH_LINECOLOR | PUSH_FILLCOLOR ); + const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings(); + Color aPrgsColor = rStyleSettings.GetHighlightColor(); + if ( aPrgsColor == rStyleSettings.GetFaceColor() ) + aPrgsColor = rStyleSettings.GetDarkShadowColor(); + SetLineColor(); + SetFillColor( aPrgsColor ); + + const long nOffset = 3; + const long nWidth = 3*mnProgressHeight/2; + const long nFullWidth = nWidth + nOffset; + const long nMaxCount = maProgressRect.GetWidth() / nFullWidth; + DrawProgress( this, maProgressRect.TopLeft(), + nOffset, + nWidth, + mnProgressHeight, + static_cast<USHORT>(0), + static_cast<USHORT>(10000*mnCur/mnMax), + static_cast<USHORT>(10000/nMaxCount), + maProgressRect + ); + Pop(); + + if( ! mbNativeProgress ) + { + DecorationView aDecoView( this ); + Rectangle aFrameRect( maProgressRect ); + aFrameRect.Left() -= nOffset; + aFrameRect.Right() += nOffset; + aFrameRect.Top() -= nOffset; + aFrameRect.Bottom() += nOffset; + aDecoView.DrawFrame( aFrameRect ); + } +} |