home *** CD-ROM | disk | FTP | other *** search
- //=============================================================================
- //
- // Copyright (C) 1996,1997,1998 by Paul S. McCarthy and Eric Sunshine.
- // Written by Paul S. McCarthy and Eric Sunshine.
- // All Rights Reserved.
- //
- // This notice may not be removed from this source code.
- //
- // This object is included in the MiscKit by permission from the authors
- // and its use is governed by the MiscKit license, found in the file
- // "License.rtf" in the MiscKit distribution. Please refer to that file
- // for a list of all applicable permissions and restrictions.
- //
- //=============================================================================
- //-----------------------------------------------------------------------------
- // MiscTableViewPrint.M
- //
- // Printing support for MiscTableScroll.
- //
- // FIXME: Move most of this junk up into table scroll.
- // FIXME: Separate computing the number of pages from doing all the
- // other work, so that hopefully, we can do all the other work
- // only if the user proceeds with a print operation.
- //-----------------------------------------------------------------------------
- //-----------------------------------------------------------------------------
- // $Id: MiscTableViewPrint.M,v 1.9 98/03/22 13:12:07 sunshine Exp $
- // $Log: MiscTableViewPrint.M,v $
- // Revision 1.9 98/03/22 13:12:07 sunshine
- // v133.1: Now prints corner view.
- //
- // Revision 1.8 97/11/24 01:48:34 sunshine
- // v131.1: Applied v131 NEXTSTEP 3.3 diffs to fix all printing problems.
- //
- // Revision 1.7 97/06/18 09:56:31 sunshine
- // v125.9: Worked around Objective-C++ compiler crash in OPENSTEP 4.2 for NT
- // when sending message to 'super' from within a category. Unified naming.
- //-----------------------------------------------------------------------------
- #import "MiscTableView.h"
- #import "MiscTableScrollPrivate.h"
- #import "MiscTableBorder.h"
- #import "MiscBorderView.h"
- #import "MiscGeometry.h"
-
- extern "Objective-C" {
- #import <AppKit/NSApplication.h>
- #import <AppKit/NSImage.h>
- #import <AppKit/NSPrintInfo.h>
- #import <AppKit/NSPrintOperation.h>
- #import <AppKit/NSPrintPanel.h>
- #import <AppKit/psops.h>
- }
-
- extern "C" {
- #import <math.h> // floor()
- }
-
- @implementation MiscTableView(Print)
-
- //-----------------------------------------------------------------------------
- // getPrintInfo
- //-----------------------------------------------------------------------------
- - (MiscTablePrintInfo const*)getPrintInfo
- {
- return (pages != 0) ? &(pages->info) : 0;
- }
-
-
- //-----------------------------------------------------------------------------
- // getHeight:
- //-----------------------------------------------------------------------------
- - (float)getHeight:(id)obj
- {
- if (obj != 0)
- {
- if ([obj respondsToSelector:@selector(frame)])
- return [obj frame].size.height;
- else if ([obj respondsToSelector:@selector(size)])
- return [obj size].height;
- }
- return 0;
- }
-
-
- //-----------------------------------------------------------------------------
- // getWidth:
- //-----------------------------------------------------------------------------
- - (float)getWidth:(id)obj
- {
- if (obj != 0)
- {
- if ([obj respondsToSelector:@selector(frame:)])
- return [obj frame].size.height;
- else if ([obj respondsToSelector:@selector(size:)])
- return [obj size].height;
- }
- return 0;
- }
-
-
- //-----------------------------------------------------------------------------
- // numPagesForBorder:pageSize:
- //-----------------------------------------------------------------------------
- - (int)numPagesForBorder:(MiscBorderType)bt pageSize:(float)scaled_page_size
- {
- int npages = 0;
-
- // FIXME: Borders with uniform size slots should be much simpler
- // than this.
-
- MiscPixels const page_size = (MiscPixels)floor(scaled_page_size);
-
- NSParameterAssert( page_size > 0 );
-
- MiscTableBorder* const border =
- (bt == MISC_COL_BORDER ? colBorder : rowBorder);
-
- MiscPixels sz_sum = 0;
- MiscCoord_V const numSlots = border->count();
- for (MiscCoord_V vslot = 0; vslot < numSlots; vslot++)
- {
- MiscPixels sz = border->effectiveSize(vslot);
- if (sz <= page_size)
- {
- sz_sum += sz;
- if (sz_sum > page_size)
- {
- sz_sum = sz;
- npages++;
- }
- }
- else
- {
- if (sz_sum > 0)
- npages++;
- npages += sz / page_size;
- sz_sum = sz % page_size;
- }
- }
-
- if (sz_sum >= 0)
- npages++;
-
- return npages;
- }
-
-
- //-----------------------------------------------------------------------------
- // append
- //-----------------------------------------------------------------------------
- static void append( MiscPixels w, MiscTSPageBreak& bk, MiscTSPageBreak bks[],
- int n, int num_breaks )
- {
- NSCParameterAssert( n < num_breaks );
- bk.size = w;
- bks[ n ] = bk;
- bk.offset += w;
- }
-
-
- //-----------------------------------------------------------------------------
- // border:pageSize:numPages:calcBreaks:
- //-----------------------------------------------------------------------------
- - (void)border:(MiscBorderType)bt
- pageSize:(float)pageSize
- numPages:(int)nPages
- clip:(BOOL)do_clip
- calcBreaks:(MiscTSPageBreak*)bks
- {
- MiscPixels const page_size = (MiscPixels)floor(pageSize);
-
- // FIXME: Borders with uniform size slots should be much simpler
- // than this.
-
- NSParameterAssert( page_size > 0 );
-
- MiscTableBorder* const border =
- (bt == MISC_COL_BORDER ? colBorder : rowBorder);
-
- MiscTSPageBreak bk;
- bk.offset = 0;
- bk.size = 0;
- bk.first = 0;
- bk.last = 0;
-
- int pg = 0;
- MiscPixels sz_sum = 0;
-
- MiscCoord_V const numSlots = border->count();
- for (MiscCoord_V vslot = 0; vslot < numSlots; vslot++)
- {
- MiscPixels sz = border->effectiveSize(vslot);
- if (sz <= page_size)
- {
- sz_sum += sz;
- if (sz_sum > page_size)
- {
- bk.last = (vslot - 1);
- append( sz_sum - sz, bk, bks, pg++, nPages );
- if (do_clip) goto clip_exit;
- bk.first = vslot;
- sz_sum = sz;
- }
- }
- else
- {
- if (sz_sum > 0)
- {
- bk.last = (vslot - 1);
- append( sz_sum, bk, bks, pg++, nPages );
- if (do_clip) goto clip_exit;
- }
- bk.first = vslot;
- bk.last = ~vslot;
- do {
- append( page_size, bk, bks, pg++, nPages );
- if (do_clip) goto clip_exit;
- bk.first = ~vslot;
- sz -= page_size;
- }
- while (sz > page_size);
- sz_sum = sz;
- }
- }
-
- if (sz_sum >= 0)
- {
- bk.last = numSlots - 1;
- append( sz_sum, bk, bks, pg++, nPages );
- }
-
- clip_exit:
-
- NSParameterAssert( pg == nPages );
- }
-
-
- //-----------------------------------------------------------------------------
- // - getImageForView:inRect:
- //-----------------------------------------------------------------------------
- - (NSImage*)getImageForView:(id)view inRect:(NSRect)rect
- {
- return [[[NSImage alloc] initWithData:
- [view dataWithEPSInsideRect:rect]] autorelease];
- }
-
-
- //-----------------------------------------------------------------------------
- // - getImageForView:
- //-----------------------------------------------------------------------------
- - (NSImage*)getImageForView:(id)view
- {
- return [self getImageForView:view inRect:[view bounds]];
- }
-
-
- //-----------------------------------------------------------------------------
- // getImages:info:
- //-----------------------------------------------------------------------------
- - (void)getImages:(MiscTSPageImages*)img
- info:(MiscTablePrintInfo const*)info
- {
- id delg;
- id const scroll = [self scroll];
-
- img->page_header = 0;
- img->page_footer = 0;
- img->col_titles = 0;
- img->row_titles = 0;
- img->corner_view = 0;
-
- if (pages->pageHeader != 0)
- {
- delg = [scroll responsibleDelegate:
- MiscDelegateFlags::DEL_PRINT_PAGE_HEADER];
- if (delg != 0)
- [delg tableScroll:scroll
- willPrintPageHeader:pages->pageHeader
- info:info];
- // FIXME: Need to shrink/grow/center/position.
- img->page_header = [[self getImageForView:pages->pageHeader] retain];
- }
-
- if (pages->pageFooter != 0)
- {
- delg = [scroll responsibleDelegate:
- MiscDelegateFlags::DEL_PRINT_PAGE_FOOTER];
- if (delg != 0)
- [delg tableScroll:scroll
- willPrintPageFooter:pages->pageFooter
- info:info];
- // FIXME: Need to shrink/grow/center/position.
- img->page_footer = [[self getImageForView:pages->pageFooter] retain];
- }
-
- if (pages->colTitles != 0)
- {
- NSRect r = info->print_rect;
- r.origin.y = 0;
- r.size.height = pages->col_titles_height;
- img->col_titles =
- [[self getImageForView:pages->colTitles inRect:r] retain];
- }
-
- if (pages->rowTitles != 0)
- {
- NSRect r = info->print_rect;
- r.origin.x = 0;
- r.size.width = pages->row_titles_width;
- img->row_titles =
- [[self getImageForView:pages->rowTitles inRect:r] retain];
- }
-
- if (pages->cornerView != 0)
- {
- NSRect r;
- r.origin.x = 0;
- r.origin.y = 0;
- r.size.width = pages->row_titles_width;
- r.size.height = pages->col_titles_height;
- img->corner_view =
- [[self getImageForView:pages->cornerView inRect:r] retain];
- }
- }
-
-
- //-----------------------------------------------------------------------------
- // calcPages
- //-----------------------------------------------------------------------------
- - (BOOL)calcPages
- {
- BOOL ok = YES; // FIXME: Deal with pages that are too small, etc.
- id const scroll = [self scroll];
-
- pages = new MiscTablePages;
-
- pages->pageHeader = [scroll getPageHeader];
- pages->pageFooter = [scroll getPageFooter];
- pages->page_header_height = [self getHeight:pages->pageHeader];
- pages->page_footer_height = [self getHeight:pages->pageFooter];
-
- pages->colTitles = [scroll colTitles];
- pages->rowTitles = [scroll rowTitles];
- if (pages->colTitles != 0 && pages->rowTitles != 0)
- pages->cornerView = [scroll cornerView];
- else
- pages->cornerView = 0;
- pages->col_titles_height = [scroll columnTitlesHeight];
- pages->row_titles_width = [scroll rowTitlesWidth ];
-
- float scroll_width = [scroll totalWidth];
- float scroll_height = [scroll totalHeight];
- float total_width = scroll_width + pages->row_titles_width;
- float total_height = scroll_height + pages->col_titles_height;
-
- NSPrintInfo* printInfo = [NSPrintInfo sharedPrintInfo];
- NSSize const paperSize = [printInfo paperSize];
-
- float page_width = paperSize.width -
- [printInfo leftMargin] - [printInfo rightMargin];
- float page_height = paperSize.height -
- [printInfo topMargin] - [printInfo bottomMargin] -
- pages->page_header_height -
- pages->page_footer_height;
-
- int const hPagination = [printInfo horizontalPagination];
- int const vPagination = [printInfo verticalPagination];
-
- BOOL hScaled = NO; double hScaler = 1.0;
- BOOL vScaled = NO; double vScaler = 1.0;
- BOOL isScaled = NO; double scaleFactor = 1.0;
-
- if (hPagination == NSFitPagination && total_width > page_width)
- {
- hScaled = YES;
- hScaler = double(page_width) / double(total_width);
- }
-
- if (vPagination == NSFitPagination && total_height > page_height)
- {
- vScaled = YES;
- vScaler = double(page_height) / double(total_height);
- }
-
- if (hScaled || vScaled)
- {
- isScaled = YES;
- if (vScaler < hScaler)
- scaleFactor = vScaler;
- else
- scaleFactor = hScaler;
- }
-
- float const EPSILON = 0.0001;
- float const pScaler = [[[printInfo dictionary]
- objectForKey:NSPrintScalingFactor] floatValue];
- if (pScaler < (1.0 - EPSILON) || (1.0 + EPSILON) < pScaler)
- {
- if (isScaled)
- scaleFactor *= pScaler;
- else
- {
- scaleFactor = pScaler;
- isScaled = YES;
- }
- }
-
- pages->info.is_scaled = isScaled;
- pages->info.scale_factor = scaleFactor;
-
- float scaled_page_width = page_width;
- float scaled_page_height = page_height;
-
- if (isScaled)
- {
- scaled_page_width = double(page_width) / scaleFactor;
- scaled_page_height = double(page_height) / scaleFactor;
- }
-
- scaled_page_width -= pages->row_titles_width;
- scaled_page_height -= pages->col_titles_height;
-
-
- //--- Calculate the number of rows/cols/pages -------------------------
-
- int ncols = 1;
- int nrows = 1;
-
- if (hPagination != NSClipPagination && scroll_width > scaled_page_width)
- ncols = [self numPagesForBorder:MISC_COL_BORDER
- pageSize:scaled_page_width];
-
- if (vPagination != NSClipPagination && scroll_height > scaled_page_height)
- nrows = [self numPagesForBorder:MISC_ROW_BORDER
- pageSize:scaled_page_height];
-
- NSParameterAssert( nrows > 0 ); NSParameterAssert( ncols > 0 );
-
- int const npages = nrows * ncols;
-
-
- //--- Allocate arrays -------------------------------------------------
-
- pages->col_breaks = (MiscTSPageBreak*)
- malloc( (ncols + nrows) * sizeof(MiscTSPageBreak) );
- pages->row_breaks = pages->col_breaks + ncols;
-
- MiscTSPageImages* images = (MiscTSPageImages*)
- malloc( npages * sizeof(*images) );
- pages->images = images;
-
-
- //--- Prepare print rectangles and border images ----------------------
-
- [self border:MISC_COL_BORDER
- pageSize:scaled_page_width
- numPages:ncols
- clip:(hPagination == NSClipPagination)
- calcBreaks:pages->col_breaks];
-
- [self border:MISC_ROW_BORDER
- pageSize:scaled_page_height
- numPages:nrows
- clip:(vPagination == NSClipPagination)
- calcBreaks:pages->row_breaks];
-
-
- MiscTablePrintInfo& info = pages->info;
- info.page_size = paperSize;
- info.num_print_pages = npages;
- info.num_print_rows = nrows;
- info.num_print_cols = ncols;
- info.scale_factor = scaleFactor;
- info.is_scaled = isScaled;
-
- int pg = 0;
- MiscTSPageImages* img = images;
- MiscTSPageBreak const* rbk = pages->row_breaks;
- for (int r = 0; r < nrows; r++,rbk++)
- {
- info.print_rect.origin.y = rbk->offset;
- info.print_rect.size.height = rbk->size;
- info.first_print_row = rbk->first;
- info.last_print_row = rbk->last;
-
- MiscTSPageBreak const* cbk = pages->col_breaks;
- for (int c = 0; c < ncols; c++,cbk++,img++)
- {
- info.print_rect.origin.x = cbk->offset;
- info.print_rect.size.width = cbk->size;
- info.first_print_col = cbk->first;
- info.last_print_col = cbk->last;
- info.print_page = ++pg;
-
- [self getImages:img info:&info];
- }
- }
-
- return ok;
- }
-
-
- //-----------------------------------------------------------------------------
- // freePages
- //-----------------------------------------------------------------------------
- - (void)freePages
- {
- if (pages->col_breaks != 0)
- {
- free( pages->col_breaks );
- pages->col_breaks = 0;
- }
- if (pages->images != 0)
- {
- for (int i = pages->info.num_print_pages; i-- > 0; )
- {
- MiscTSPageImages const& img = pages->images[i];
- if (img.page_header != 0) [img.page_header release];
- if (img.page_footer != 0) [img.page_footer release];
- if (img.col_titles != 0) [img.col_titles release];
- if (img.row_titles != 0) [img.row_titles release];
- if (img.corner_view != 0) [img.corner_view release];
- }
- free( pages->images );
- pages->images = 0;
- }
- delete pages;
- pages = 0;
- }
-
-
- //-----------------------------------------------------------------------------
- // print:
- //-----------------------------------------------------------------------------
- - (void)print:(id)sender
- {
- id const scroll = [self scroll];
- id del = [scroll responsibleDelegate:MiscDelegateFlags::DEL_WILL_PRINT];
- if (del != 0)
- [del tableScrollWillPrint:scroll];
-
- if ([self calcPages])
- {
- [self superPrint:sender];
- [self freePages];
- }
-
- del = [scroll responsibleDelegate:MiscDelegateFlags::DEL_DID_PRINT];
- if (del != 0)
- [del tableScrollDidPrint:scroll];
- }
-
-
- //-----------------------------------------------------------------------------
- // knowsPagesFirst:last:
- //-----------------------------------------------------------------------------
- - (BOOL)knowsPagesFirst:(int*)first last:(int*)last
- {
- if (pages != 0)
- {
- *first = 1;
- *last = pages->info.num_print_pages;
- return YES;
- }
- return NO;
- }
-
-
- //-----------------------------------------------------------------------------
- // rectForPage:
- //-----------------------------------------------------------------------------
- - (NSRect)rectForPage:(int)n
- {
- NSParameterAssert( pages != 0 );
- MiscTablePrintInfo const& info = pages->info;
- if (0 < n && n <= info.num_print_pages)
- {
- n--;
- int const r = (n / info.num_print_cols);
- int const c = (n % info.num_print_cols);
- MiscTSPageBreak const& cbk = pages->col_breaks[c];
- MiscTSPageBreak const& rbk = pages->row_breaks[r];
- return NSMakeRect( cbk.offset, rbk.offset, cbk.size, rbk.size );
- }
- return NSZeroRect;
- }
-
-
- //-----------------------------------------------------------------------------
- // locationOfPrintRect:
- //-----------------------------------------------------------------------------
- - (NSPoint)locationOfPrintRect:(NSRect)rect
- {
- NSPrintInfo* printInfo = [[NSPrintOperation currentOperation] printInfo];
- NSSize const paperSize = [printInfo paperSize];
- float ml = [printInfo leftMargin];
- float mr = [printInfo rightMargin];
- float mt = [printInfo topMargin];
- float mb = [printInfo bottomMargin];
-
- float x = 0;
- float y = 0;
- float h = paperSize.height;
- float w = paperSize.width;
- float rh = rect.size.height;
- float rw = rect.size.width;
- float tw = pages->row_titles_width;
- float th = pages->col_titles_height;
- float hh = pages->page_header_height;
-
- NSParameterAssert( pages != 0 );
-
- MiscTablePrintInfo const& info = pages->info;
- if (info.is_scaled)
- {
- float const k = info.scale_factor;
- x /= k;
- y /= k;
- h /= k;
- w /= k;
- ml /= k;
- mr /= k;
- mt /= k;
- mb /= k;
- }
-
- NSPoint pt = NSMakePoint( x + ml + tw, y + h - mt - rh - hh - th );
-
- if ([printInfo isHorizontallyCentered])
- {
- float dx = w - ml - mr - tw - rw;
- if (dx > 0)
- pt.x += dx / 2;
- }
-
- if ([printInfo isVerticallyCentered])
- {
- float dy = h - mt - mb - th - rh;
- if (dy > 0)
- pt.y -= dy / 2;
- }
-
- return pt;
- }
-
-
- //-----------------------------------------------------------------------------
- // drawImage:at:
- //-----------------------------------------------------------------------------
- - (void)drawImage:(NSImage*)img at:(NSPoint)pt
- {
- NSRect r;
- r.size = [img size];
- r.origin.x = pt.x;
- r.origin.y = pt.y - r.size.height;
- [img drawRepresentation:[[img representations] lastObject] inRect:r];
- }
-
-
- //-----------------------------------------------------------------------------
- // drawPageBorderWithSize:
- //-----------------------------------------------------------------------------
- - (void)drawPageBorderWithSize:(NSSize)borderSize
- {
- NSParameterAssert( pages != 0 );
- MiscTablePrintInfo const& info = pages->info;
-
- int n = [[NSPrintOperation currentOperation] currentPage] - 1;
- NSParameterAssert( 0 <= n );
- NSParameterAssert( n < info.num_print_pages );
- MiscTSPageImages const& img = pages->images[n];
-
- NSPrintInfo* printInfo = [[NSPrintOperation currentOperation] printInfo];
- float const ml = [printInfo leftMargin];
- float const mr = [printInfo rightMargin];
- float const mb = [printInfo bottomMargin];
- float const mt = [printInfo topMargin];
-
- NSPoint const page_origin = NSZeroPoint;
- NSSize const page_size = info.page_size;
- float bottom = page_origin.y + mb;
- float top = page_origin.y + page_size.height - mt;
- float left = page_origin.x + ml;
- float right = page_origin.x + page_size.width - mr;
-
- if (info.is_scaled)
- {
- float const k = info.scale_factor;
- PSscale( k, k );
- bottom /= k;
- top /= k;
- left /= k;
- right /= k;
- }
-
- if (img.page_header != 0)
- {
- [self drawImage:img.page_header at:NSMakePoint(top, left)];
- top -= pages->page_header_height;
- }
-
- if (img.page_footer != 0)
- {
- bottom += pages->page_footer_height;
- [self drawImage:img.page_footer at:NSMakePoint(left, bottom)];
- }
-
- float dx = 0;
- float dy = 0;
-
- if ([printInfo isHorizontallyCentered])
- {
- int const c = (n % info.num_print_cols);
- dx = right - left - pages->row_titles_width
- - pages->col_breaks[c].size;
- if (dx > 0)
- dx /= 2;
- else
- dx = 0;
- }
-
- if ([printInfo isVerticallyCentered])
- {
- int const r = (n / info.num_print_cols);
- dy = top - bottom - pages->col_titles_height
- - pages->row_breaks[r].size;
- if (dy > 0)
- dy /= 2;
- else
- dy = 0;
- }
-
- if (img.corner_view != 0)
- {
- NSPoint pt;
- pt.x = left + dx;
- pt.y = top - dy;
- [self drawImage:img.corner_view at:pt];
- }
-
- if (img.row_titles != 0)
- {
- NSPoint pt;
- pt.x = left + dx;
- pt.y = top - pages->col_titles_height - dy;
- [self drawImage:img.row_titles at:pt];
- }
-
- if (img.col_titles != 0)
- {
- NSPoint pt;
- pt.x = left + pages->row_titles_width + dx;
- pt.y = top - dy;
- [self drawImage:img.col_titles at:pt];
- }
- }
-
- @end
-