NSPrintOperation NSprintInfo printer mac osx swift - macos

I am trying to print tickets on a thermal printer with my Mac. With that I have no problems. I use NSPrintOperation to perform the operation, assisted by NSPrinterInfo to the issue of margins and other settings.
The problem is that when I send the order to print the NSView always get the option to choose the printer, number of copies etc ...
I'd like to directly print the ticket without going through this intermediate state.
Can anyone help me do this?

From the documentation, you can choose to set the showsPrintPanel property as follows;
let printOperation = NSPrintOperation(view: someView)
printOperation.showsPrintPanel = false
printOperation.runOperation()

Related

How to deselect the contents of a TextField in swift

I have a simple desktop app where a TextField should be focused when the window loads. I have this working, but it's a little annoying that, having loaded the users content into the TextField, the entire contents of the field become selected automatically. The user may want to start editing the content, but they will rarely/never want to replace it all at once (imagine a text editor doing this, to see what I mean).
I see there is an Action for selectAll: but what I want is the opposite Action of selectNone:
I tried passing nil to the selectText method, but that doesn't work:
textField.selectText(nil)
I found a number of answers on StackOverflow that mention a selectedTextRange, but this appears to be outdated, because Xcode 6.3 doesn't recognize this as a valid property on TextField.
Can anyone explain how I do this?
It's been a while since I've dealt with NSTextFields to this level (I work mostly in iOS these days).
After doing a little digging I found this on the net:
NSText* textEditor = [window fieldEditor:YES forObject:textField];
NSRange range = {start, length};
[textEditor setSelectedRange:range];
window is the window containing your field, textField.
This requires the field editor to be managing your field, what can be done simply by previously selecting the whole text of the field using the selectText:sender method.
Here is the final swift code that I got working based on what Duncan C posted:
if let window = NSApplication.sharedApplication().mainWindow {
let textEditor = window.fieldEditor(true, forObject: textField)!
let range = NSRange(0..<0)
textEditor.selectedRange = range
}

Dynamically change paper size based on printer being displayed on NSPrintPanel

We are trying to modify the default selected paper size for a NSPrintPanel. Using NSNotification we are able to observe and implement changes on our accessoryViews in the NSPrintPanel. However when we try to implement setPaperSize (NSPrintInfo the instance method), nothing happens and the initial paper size (default) for the default printer is selected for all other printers (We have regular printers and receipt printers).
I know the new paper size being set is correct whenever the printer changes. We are programmatically obtaining the paper sizes from the Core Print. While trying to the set the right/desired paperSize, the app doesn't break or returns any stack. So it seems, it seems apple doesn't support changes to the paper size PrintPanel.
While researching the issue, we noticed that NSPrintPanel accessory view from apple titled "Paper Handling" seems to respond to the printer changes, based on the settings you provide to Page Setup (in the file menu, NSPageLayout). So our questions are:
Is there a way to access/set the Suggested Paper size displayed in this accessoryView programmatically?
I know this accessoryView reads from page setup (NSPageLayout), thus I'd like to know if to access set these values in the "Paper Handling" accessoryView is a good approach?
Notes:
- Mac doesn't seem to allow/provide a user friendly way to set default paper sizes for each printer installed.
Accessory View we are talking about:
We have reviewed apple documentation (of course) and posting from other people with similar issues with no avail. We'd greatly appreciate a push in the right direction. Thanks in advance.
It’s been a while since I’ve done this, but what happens when you set it on the NSPrintPanel’s printInfo? Any better? It might make its own temporary copy.

Setting printer-specific options on an NSPrintOperation without a panel

this question has bothered me on and off for about a year, and I thought perhaps someone else would have experience with a similar situation.
Goal: on Mac OS X 10.6-7, to print multiple NSViews to EPSON Stylus Pro 4880 printers using a defined resolution and 'high speed' setting, without showing a print panel.
Current situation: I can create successful NSPrintOperations for each NSView, but if I do not show a print panel, it appears the printer's default resolution is used, which is far too high, and slow, for my needs.
Best solution I have so far: I have tried showing the print panel and defining a Mac OS 'preset' which has the correct print resolution and high speed settings already enabled. The downside here is that the Mac preset overrides the number of copies I have set via NSCopies, which is a problem. The other difficulty of course is having someone always around to press the 'OK' button a few thousand times a day.
Where I'm up to
When the NSPrintOperation runs its panel, it has to set the EPSON-specific printer settings somewhere, but I cannot find where it is saved. They don't appear to be set in [NSPrintInfo printSettings].
I have looked at the PPD for the printer, but I can't find the high speed setting anywhere, and the default resolution defined in the PPD is not actually used as the default when printing. It appears EPSON has their own driver settings which are not taken from the PPD I have, and I am not sure how to set them manually.
Basically, running the NSPrintOperation with a print panel and preset overrides all the settings, including the ones I don't want to override. Running it without the print panel leaves all the settings as default, which is not what I want. Can anyone point me in the right direction to find a solution in between those two?
After the NSPrintOperation's runOperation runs with the dialog, look in PMPrintSettings, the printer-specific parameters may be there. I suppose you could persist PMPrintSettings for the future somehow and load the via updateFromPMPrintSettings.
This is unfortunately the best solution I have found so far though I hate to call it 'best', or even a 'solution'. It comes back to this: run an operation with a panel, and then programmatically 'click' the Print button.
[op runOperationModalForWindow: self.window delegate: self didRunSelector: nil contextInfo: nil];
NSPanel *panel = (NSPanel*)self.window.attachedSheet;
for (NSView *view in ((NSView*)panel.contentView).subviews)
{
if (view.class == [NSButton class])
{
NSButton *button = (NSButton*)view;
if ([button.title isEqualToString: #"Print"])
[button performClick: self];
}
}
or
op.runOperationModalForWindow(window, delegate: nil, didRunSelector: nil, contextInfo: nil)
(window.attachedSheet?.contentView.subviews.filter({ $0 is NSButton }) as [NSButton]).filter({ $0.title == "Print" }).first?.performClick(self)
The downside obviously is a window is needed, while I was hoping to run this as a headless server application. I have tried working with Core Printing and PMPrinter/PMPrintSettings and so forth to no avail. The only thing I have not yet tried is talking to CUPS directly. Maybe I'll save that for a rainy day!

Setting value of AXTextField programmatically (OS X Cocoa Accessibility API)

I'm using the Cocoa Accessibility API to try and modify the value of a text field (AXTextField) in another application, but I've run into a problem: my code correctly identifies and modifies the contents of the text field in question, and the text of the field visibly changes, but the changes aren't registered by the program I'm trying to control. Is there a way to do this in with the API without having to generate keyboard events?
Sample code:
AXUIElementCopyElementAtPosition(appRef,
clickPoint.x,
clickPoint.y,
&boxRef);
NSString *valueToSet = [NSString stringWithFormat:#"%f",amount];
AXUIElementSetAttributeValue(boxRef,kAXValueAttribute,valueToSet);
And the text field changes to the value specified in "amount" but the other program doesn't recognize the change - I have to go type the number in myself to get it to pick up the change (I can tell the difference, because the program responds when a new value is typed in the box). Can anyone point me in the right direction?
For posterity: Informed sources tell me that this is actually a bug in the application I'm trying to control. You can tell the difference by using UI Browser (http://prefabsoftware.com/uibrowser/) to try and set the value of the textfield; if UI Browser can't make the change stick, then the matter is out of your control.
Try telling the text field:
perform action "AXConfirm"
This is Applescript, but whatever the Cocoa equivalent is, it may make the change stick even if UI Browser can not (I've used it before).

Printing without Page Setup - reacting to paper size and orientation changes?

The AppKit release notes for Leopard say:
In many applications it is not
appropriate to present page setup
panels to the user, or even include a
Page Setup... item in the File menu,
but there has been no other easy way
to let the user specify page setup
parameters to be used when printing.
(New UI advice: if your application
doesn't persistently store page setup
parameters on a per-document basis, or
have some mechanism to associate them
with whatever other kind of
large-scale objects your application
may deal with, it probably shouldn't
have a page setup panel at all.)
I have fairly simple printing needs and would like to eliminate the “Page Setup...” command from my application.
My previous recipe for printing text was to create an offscreen text view of an appropriate size for the current paper size and orientation, then start a print operation for that view.
However, if allow the user to change the paper size and orientation in the print panel, I need to react to that change and reconfigure my printing text view.
What is the correct way to handle this situation?
My current hacked up sample app does this by subclassing NSTextView and reconfiguring for the new page parameters in -[MyTextView knowsPageRange:].
One approach that's slightly hacky but works really well is to run two NSPrintOperations.
We use this in our app's printing code, to detect if the user selected a regular printer or a receipt printer in the print panel. The app prints an entirely different document for each kind of printer.
So in PyObjC, untested code:
def smartlyPrintView_(self, theViewToPrint):
# set up and run an initial NSPrintOperation to get printInfo
fakePrintOperation = NSPrintOperation.printOperationWithView_(theViewToPrint)
NSPrintOperation.setCurrentOperation_(fakePrintOperation)
if NSPrintPanel.printPanel().runModal() == True:
# get the printInfo so we can do stuff with it
printInfo = fakePrintOperation.printInfo()
# get rid of our fakePrintOperation
NSPrintOperation.currentOperation().cleanUpOperation()
# do stuff
# run a real NSPrintOperation without a printPanel
realPrintOperation = NSPrintOperation.printOperationWithView_printInfo_(theViewToPrint, printInfo)
realPrintOperation.setShowsPrintPanel_(False)
realPrintOperation.runOperation()
else:
NSPrintOperation.currentOperation().cleanUpOperation()
Recipe to translate this to Obj-C:
Add some variable declarations, replace the underscores with colons, and interleave the arguments with the method's clauses. Mix in half a cup of flour and a handful of semi-colons. Simmer at low heat for thirthy minutes and serve hot. Good luck :)

Resources