Provide print option from mac app - cocoa

I have a Mac app. In my Mac app one of my screen has a scrollView which contains a text field. On the same screen I have a button that needs to provide a print option. The text of the text field can be printed. Print button should call the Mac OS X print dialog box. I am able to open the print dialog box by connecting the button to the print option of the first responder through xib but when I preview I don't see any text except the print button. Please help.

check out the NSPrintOperation Class Reference.
NSPrintOperation Class Reference
you will probably need to compose the text to a NSView that is large enough to fit your scroll view contents... I haven't ever had to print from a scrollView, so i don't know.
look at
+ printOperationWithView:
you will probably have to override the print: action, remember that you will be sending that to the first responder... and should fall through to your NSDocument or NSApplication subclass, but I would probably try to grab it at NSDocument if document based, NSWindow (subclass or delegate) if not.

I got the answer for this.I am using the below code,
- (void)print:(id)sender {
// page settings for printing
[self setPrintInfo:[NSPrintInfo sharedPrintInfo]];
[printInfo setVerticalPagination:NSAutoPagination];
float horizontalMargin, verticalMargin;
horizontalMargin = 0;
verticalMargin = -100;
[printInfo setLeftMargin:horizontalMargin];
[printInfo setRightMargin:horizontalMargin];
[printInfo setHorizontallyCentered:YES];
[printInfo setTopMargin:-600];
[printInfo setBottomMargin:verticalMargin];
[[NSPrintOperation printOperationWithView:sampleText] runOperation];
}

Related

Why does NSTextView not always wrap text fluently while resizing?

I've stumbled upon a behavior in NSTextView that does not seem intended, or that I at least do not understand the reasoning behind.
When you have a large body of text in an NSTextView and you resize the control/window, the wrapping of words only happens fluently and immediately while resizing when the text is scrolled near the top. If you scroll far down in the text, it does not, and it doesn't seem to "commit" the wrapping until you release and finish resizing.
Is there some internal limitation, or is this a bug?
The issue seems to be reproducible:
macOS 10.15.4, Xcode 11.4.1
Create a new macOS App project
Put an NSTextView on the default generated view controller (doesn't matter which of the 3: rich, plain or default) and constrain it so that it resizes with the window (top, bottom, leading, trailing)
Run the application and paste a large body of text into the text view (for example: http://www.gutenberg.org/cache/epub/12281/pg12281.txt)
Scroll to the top of the NSTextView and observe how the text wraps while resizing the window
Scroll to the bottom and observe how it only wraps after resizing the window
Hoping there's any Cocoa detectives out there who can provide some enlightenment on this one.
EDIT:
As per the docs, it states that "the layout manager reserves the right to perform layout for larger ranges". I take it that this means it is indeed intended as a performance consideration.
Is there any way to determine what the limit is, though?
EDIT: You could try subclassing NSScrollView to render the text into multiple containers.
NSTextStorage *storage = [[NSTextStorage alloc] initWithString:string];
NSLayoutManager *manager = [[NSLayoutManager alloc] init];
[storage addLayoutManager:manager];
NSInteger i = 0;
while (YES) {
NSTextContainer *container = [[NSTextContainer alloc] initWithSize:CGSizeMake(width, height)];
[manager addTextContainer:container];
NSTextView *textView = [[NSTextView alloc] initWithFrame:CGRectMake(x, y, width, height) textContainer:container];
[self.contentView addSubview:textView];
i++;
NSRange range = [manager glyphRangeForTextContainer:container];
if ( range.length + range.location == string.length )
break;
}
Then, while resizing the window, you can call NSLayoutManager to ensure the layout only for visible containers.

NSTextView changing Insertion Point (Caret) Cursor size when there is no string

I am creating a NSTextView, and I want to change the size of the insertion point when the NSTextView is empty.
It appears that the caret cursor (I-Beam / IBeam cursor) size is based off of the current font size attribute on the attributedString property of the NSTextView.
The problem is that because the NSTextView has an empty attributedString, there can be no attributes on the string. This means that I can't apply a font size.
However, I can change the typingAttributes to have the fontSize be correct-- but the Insertion Point Cursor does not update size until I start typing
See these screenshots:
Notice here the textview on the right has a small insertion point cursor:
I start typing, and it updates in size:
So my question is, is there a property that I need to set on the NSTextView when I initialize it, in order to get the initial Insertion Point Cursor the correct Size? (I want it to match the typingAttributes font)
EDIT:
#Mark Bessey brought up a good question-- what is the order that I'm setting the typing attributes:
[_textEditor setTypingAttributes:typingAttributes];
[_textEditor setDelegate:self];
[view addSubview:_textEditor];
[self updateInsertionPointColor];
[[view window] makeFirstResponder:_textEditor];
[view setNeedsDisplay:YES];
I just ran into the same problem and – after not finding a good solution anywhere – managed to force the NSTextView to update its pointer by inserting a character and then replacing that character with an empty string in the same cycle.
I'm doing this in textView(_:shouldChangeTextIn:replacementString:), but I guess it works elsewhere just as fine.
let attributedString = NSAttributedString(string: " ", attributes: attributes)
let range = someRange
let insertLocation = range.location + range.length
textView.textStorage?.insert(attributedString, at: insertLocation)
textView.typingAttributes = attributes
textView.replaceCharacters(in: range, with: "")
Doing this works in a simple test app, in my applicationDidFinishLaunching method:
NSFont *font = [NSFont fontWithName:#"Marker Felt" size:24.0];
NSDictionary *attr = #{
NSFontAttributeName: font
};
[self.textView setTypingAttributes:attr];
I get the large I-beam cursor that I'd expect.
This is basically the same as what TextEdit does (sample code here), so it doesn't look like you're doing anything wrong, as far as setting the typingAttributes goes.
I wonder if perhaps you're setting the attributes at the wrong time. When do you set the typingAttributes? Is the view on-screen? Is it the first responder?
To changed the attributes when there is no text, using typingAttributes.
Typing attributes are reset automatically whenever the selection changes. However, if you add any user actions that change text attributes, the action should use this method to apply those attributes afterwards. User actions that change attributes should always set the typing attributes because there might not be a subsequent change in selection before the next typing.
#IBOutlet var targetTextView: NSTextView!{
didSet {
let attributes:[NSAttributedString.Key:Any] = [
.font:NSFont.userFont(ofSize: 16.0) ?? NSFont.systemFont(ofSize: 16.0),
.foregroundColor:NSColor(named: "targetColor")!
]
targetTextView.typingAttributes = attributes
}
}

How do I get "Page Attributes" option in Cocoa print dialog?

The program I'm writing runs under OS X 10.5 Leopard. My target has its Base SDK and Deployment Target both set to Mac OS X 10.5. When I initiate printing, my print dialog doesn't show the Page Attributes option in which the user can select page size and orientation.
Other programs running under Leopard do show this option:
Here's the code that initiates printing:
-(void)print {
NSPrintInfo *printInfo = [NSPrintInfo sharedPrintInfo];
TemperaturePressurePrintView *printView = [[TemperaturePressurePrintView alloc] initWithFrequencies:frequencies];
if (printView) {
[[NSPrintOperation printOperationWithView:printView printInfo:printInfo] runOperation];
[printView release];
}
}
What do I need to do to get Page Attributes to show up in my print dialog?
This was a tough thing to search for because the results were mostly about using the print panel, not programming one. I finally found a clue on Cocoabuilder where it mentions NSPrintPanelOptions and NSPrintPanel's -setOptions: method.
This code accomplishes what I need:
-(void)print {
NSPrintInfo *printInfo = [NSPrintInfo sharedPrintInfo];
TemperaturePressurePrintView *printView = [[TemperaturePressurePrintView alloc] initWithFrequencies:frequencies];
if (printView) {
NSPrintOperation *op = [NSPrintOperation printOperationWithView:printView printInfo:printInfo];
[[op printPanel] setOptions:[[op printPanel] options] | NSPrintPanelShowsPageSetupAccessory];
[op runOperation];
[printView release];
}
}
It's a few years after the original answer and macOS Sierra seems to have introduced a bug into the behaviour of panels that have the 'NSPrintPanelShowsPageSetupAccessory' option set. Invalid values, such as a ridiculously large scale, cause crashes instead of displaying an alert sheet.
Fortunately there is a workaround. Using
NSPrintPanelShowsPaperSize | NSPrintPanelShowsOrientation | NSPrintPanelShowsScaling
instead seems to result in a panel that works fine.

Automatically resize an NSButton to fit programmatically changed text (Xcode)

I have an NSButton (Push Button) with some temporary title text built in Interface Builder / Xcode. Elsewhere, the title text inside the button is changed programmatically to a string of unknown length (actually, many times to many different lengths).
I'd like the button to automatically be resized (with a fixed right position--so it grows out to the left) to fit whatever length of string is programmatically inserted as button text. But I can't figure it out. Any suggestions? Thanks in advance!
If you can't use Auto Layout as suggested by #jtbandes (it's only available in Lion), then you can call [button sizeToFit] after setting its string value, which will make the button resize to fit its string. You would then need to adjust its frame based on the new width.
You can't do this automatically, but it would be easy to do in a subclass of NSButton.
#implementation RKSizeToFitButton
- (void)setStringValue:(NSString*)aString
{
//get the current frame
NSRect frame = [self frame];
//button label
[super setStringValue:aString];
//resize to fit the new string
[self sizeToFit];
//calculate the difference between the two frame widths
NSSize newSize = self.frame.size;
CGFloat widthDelta = newSize.width - NSWidth(frame);
//set the frame origin
[self setFrameOrigin:NSMakePoint(NSMinX(self.frame) - widthDelta, NSMinY(self.frame))];
}
#end
This way you can just set your button's class to RKSizeToFitButton in Interface Builder and then calling setStringValue: on the button to change its label will "just work" with no additional code.
Sure! Just use Auto Layout! :)

Dynamic Results and Covering Data

Today I have a question that sprouted off of this one: Database Results in Cocoa. It's regarding using the data that was returned by a database to create a certain number of questions. I am using a form of the following code (this was posted in the question).
NSMutableDictionary * interfaceElements = [[NSMutableDictionary alloc] init];
for (NSInteger i = 0; i < numberOfTextFields; ++i) {
//this is just to make a frame that's indented 10px
//and has 10px between it and the previous NSTextField (or window edge)
NSRect frame = NSMakeRect(10, (i*22 + (i+1)*10), 100, 22);
NSTextField * newField = [[NSTextField alloc] initWithFrame:frame];
//configure newField appropriately
[[myWindow contentView] addSubview:newField];
[interfaceElements setObject:newField forKey:#"someUniqueIdentifier"];
[newField release];
}
However, now when I attempt to use IFVerticallyExpandingTextfield (from http://www.cocoadev.com/index.pl?IFVerticallyExpandingTextField), or create any large amount of text, it simply goes over the other drawn content. I looked into using setAutosizingMask: on the object, but it has not worked so far.
Thanks for any help.
EDIT: What I want the effect to look like is called "Correct TextField" and what happens is called "StackOverflow Sample" - http://www.mediafire.com/?sharekey=bd476ea483deded875a4fc82078ae6c8e04e75f6e8ebb871.
EDIT 2: And if no one knows how to use this IFVerticallyExpandingTextfield class, would anyone know if there is another way to accomplish the effect?
Do you mean this?
http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaDrawingGuide/GraphicsContexts/GraphicsContexts.html
Your question is not very clear to me but this might help ^^^.
Look at 'Modifying the Current Graphics State' on that page.
What about just exactly copying the code from the 'Correct textfield' example and use it in your application? Or start your application from the 'Correct texfield' example.
Also
A comment on http://www.cocoadev.com/index.pl?IFVerticallyExpandingTextField says:
Give it a try! You should be able to
throw this into a project, read the
files in Interface Builder, and use
the custom class pane to make an
NSTextField into an
IFVerticallyExpandingTextField. You'll
need to set the layout and
linebreaking attributes for word
wrapping for this to work.
Although expansion should work
properly when the textfield is
embedded in a subview, I'm having some
trouble dealing with NSScrollViews.
The field expands into the
scrollview's content view, but none of
the controls on the scrollbar appear.
Some help here would be appreciated.

Resources