I have a NSTokenField object with multilines (just resized the control vertically in interface builder). Unfortunately the NSTokenField object does not insert new line when pressing the return key. Any ideas how to make the control insterting a new line when pressing the return key?
Do I really have to go the complicated way through delegates like control:textView:doCommandBySelector: ?
Thank you.
By default, text fields (and by extension token fields) do not insert a new line when pressing the return key. This is the expected behavior.
A user who wishes to enter a return instead of tokenizing or committing the input may press Option-Return.
If you wish to disable this behavior programatically (be careful not to break the user's expectations) then the delegate is by far the easiest way to do so.
I am afraid there is no other simpler way.
But it is not too complicated anyway - here the swift code to use in the delegate, so that enter and tab presses actually insert new lines and tabs :
func control(_ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool
{
if (commandSelector == #selector(insertNewline))
{
textView.insertText("\n", replacementRange: textView.selectedRange)
return true
}
else if (commandSelector == #selector(insertTab))
{
textView.insertText("\t", replacementRange: textView.selectedRange)
return true
}
return false
}
Related
I develop a document-based Cocoa application allowed saving documents asynchronous. Namely, my NSDocument subclass returns ture on canAsynchronouslyWrite(to:typeOf:for:).
I want dynamically and silently delay (or cancel) regular auto-saving if the document content is editing. At first, I thought it's enough when I throw an error in checkAutosavingSafety(), but it displays an error message dialog for user.
I believe there is a standard way for such a standard demand. But I'm not sure either where in a NSDocument subclass I should prevent saving and to which method I should say "please wait".
Does someone have any idea for this?
For the reference, the content of document is text which is managed by NSTextView subclass.
I finally found that throwing an .userCalcelled error in a saving process with autosavingIsImplicitlyCancellable can cancel autosaving.
/// make autosaving cancellable
override var autosavingIsImplicitlyCancellable: Bool {
return true
}
/// save or autosave the document contents
override func save(to url: URL, ofType typeName: String, for saveOperation: NSDocument.SaveOperationType, completionHandler: #escaping (Error?) -> Void) {
// cancel if something is working
guard saveOperation != .autosaveInPlaceOperation || !self.isEditing else {
completionHandler(CocoaError(.userCancelled))
return
}
super.save(to: newUrl, ofType: typeName, for: saveOperation, completionHandler: completionHandler)
}
/// whether your document is currently being edited
var isEditing: Bool {
// check your document state
}
Im subclassing NSTextView and overriding keyDown. I want to detect command-key-combinations. Command-L, for example.
Apple's documentation indicates that you simply and the modifier flags (in the passed NSEvent) with NSEventModifierFlags.CommandKeyMask.
When I do so:
let ck = NSEventModifierFlags.CommandKeyMask
I receive an odd error:
Binary operator '&' cannot be applied to two 'NSEventModifierFlags' operands.
What's the deal? This is swift 2.0, xcode 7.
Thanks!
Apple's documentation indicates that you simply and the modifier flags
The documentation is still referring to C and Objective-C. Swift uses OptionSetType, which does not use bitwise operators for checking flags.
Instead, use the contains() method to check for one or more flags:
if theEvent.modifierFlags.contains(.CommandKeyMask) {
NSLog("command key down")
}
if theEvent.modifierFlags.contains(.AlternateKeyMask) {
NSLog("option key down")
}
if theEvent.modifierFlags.contains([.CommandKeyMask, .AlternateKeyMask]) {
NSLog("command and option keys down")
}
To check for a single key, use intersect to filter out any unwanted flags, then use == to check for a single flag:
let modifierkeys = theEvent.modifierFlags.intersect(.DeviceIndependentModifierFlagsMask)
if modifierkeys == .CommandKeyMask {
NSLog("Only command key down")
}
NSEventModifierFlags is an optionSet in Swift 2.0. You can use contain method to check it contains the command modifier key
override func keyDown(theEvent:NSEvent) {
if theEvent.characters == "l" && theEvent.modifierFlags.contains(.CommandKeyMask) {
print("command-L pressed")
}
}
I was going to put in a comment, but wasn't able to.
In case someone (like me) comes across this article in the future, Swift has changed a little since 2015.
Swift 4:
theEvent.modifierFlags.contains(.command)
theEvent.modifierFlags.contains(.option)
theEvent.modifierFlags.contains([.command, .option])
NSLog("command and option keys down")
also; (.control) is for CTRL.
This is my particular code:
override func viewDidLoad()
{
super.viewDidLoad()
NSEvent.addLocalMonitorForEvents(matching: NSEvent.EventTypeMask.keyDown, handler: myKeyDownEvent)
}
func myKeyDownEvent(event: NSEvent) -> NSEvent {
if (event.keyCode == 121) && event.modifierFlags.contains([.command, .option]) {
//Do what you want when PGDN + cmd + alt is pressed
}
return event
}
One can put an observer on the selectedIndex method of NSArrayController. This method has some drawbacks I think :
what will happen when the arrangedObjects is rearranged ? I admit this is not a very important problem
if we ask the observer to remember the old value of selectedIndex, it doesn't work. It is known but I cannot find again the link.
Why doesn't NSArrayController have a delegate ?
Is there another way to achieve what I want to do : launching some methods when the selection changes ?
Observe selection key of the NSArrayController (it is inherited from NSObjectController).
It will return either NSMultipleValuesMarker (when many objects are selected), NSNoSelectionMarker (when nothing is selected), or a proxy representing the selected object which can then be queried for the original object value through self key.
It will not change if rearranging objects did not actually change the selection.
You can also observe selectedObjects; in that case you won't need to deal with markers.
Providing hamstergene's excellent solution, in Swift 4.
In viewDidLoad, observe the key path.
arrayController.addObserver(self, forKeyPath: "selectedObjects", options: .new, context: nil)
In the view controller,
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
guard let keyPath = keyPath else { return }
switch keyPath {
case "selectedObjects":
// arrayController.selectedObjects has changed
default:
break
}
}
I've been developing with QT for around a week now and am pleased to say that I'm picking it up really fast. I'm an intermediate C++ programmer but picking up some parts of QT is proving to be challenging. I need to process key press events from the QPlainTextEdit when the user presses enter and I presume that the solution will involve sub classing the widget. Can any of you smart guys give me a potential implementable solution?
To really understand Qt and event handling there are two key areas of the documentation you should read. The first is the overview on The Event System and the second is a very important bit which is a cleverly hidden link on that page for QCoreApplication::notify. They should really move that to the main page of the Event System documentation as it really makes things quite clear (to me at least).
If you only need to handle some messages sent to the control - like the key-presses - there is no need to subclass it. You can alternatively use the event filtering mechanism. Here is a simple example:
Provide virtual eventFilter method in one of your QObject-based classes (e.g. the window form class).
bool MyWindow::eventFilter(QObject *watched, QEvent *event)
{
if(watched == ui->myTargetControl)
{
if(event->type() == QKeyEvent::KeyPress)
{
QKeyEvent * ke = static_cast<QKeyEvent*>(event);
if(ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter)
{
// [...]
return true; // do not process this event further
}
}
return false; // process this event further
}
else
{
// pass the event on to the parent class
return QMainWindow::eventFilter(watched, event);
}
}
Install your class as the event filter for the target control. Form constructor is usually a good place for this code. In the following snippet this refers to the instance of class in which you implemented the eventFilter method.
ui->myTargetControl->installEventFilter(this);
i would try subclassing QPlainTextEdit and reimplementing QWidget::keyPressEvent:
void YourTextEdit::keyPressEvent ( QKeyEvent * event )
{
if( event->key() == Qt::Key_Return )
{
// optional: if the QPlainTextEdit should do its normal action
// even when the return button is pressed, uncomment the following line
// QPlainTextEdit::keyPressEvent( event )
/* do your stuff here */
event->accept();
}
else
QPlainTextEdit::keyPressEvent( event )
}
please try :
if (event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter){
//do something
}
in your keyPressEvent() function.
I am using a basiceditfield to take input from the user to do some simple string search. But if i type a few letters and wish to go back without continuing the search, it automatically asks me whether to save the contents of the field. I don want this to happen. Can i in any way disable the "Changes made!-save-discard-cancel" option in basiceditfield(or any editfield for that matter)????please help!!!
Try adding this to your MainScreen class:
protected boolean onSavePrompt() {
return true;
}
Another way would be to override the dirty state logic on your Screen class like this:
public boolean isDirty() { return false; }
Of course you can also just override that same method on a subclass of your Field, and that too should probably work. (assuming you still want to do dirty-state-tracking of other fields on the screen.)
modify onClose method of Screen
public boolean onClose() {
this.close();
return true;
}