NSDocument isDocumentEdited and undo - objective-c

In a document-based application, for every user action I add an entry in the UndoManager, including selection, meaning that an 'undo' will restore the previous selection.
Some times a user will open a document, view some items by selecting them and then close the document, but even if the user didn't 'alter' anything, the user is asked to save changes, this is annoying and can be misleading to the user.
It seems that the document's dirty flag (isDocumentEdited) is automatically set when registering undo actions, but is there a way I can prevent this for some particualr undoable actions, such as selection change?
Thanks!

You should be able to call -setActionIsDiscardable:YES on the undoManager when you register actions that don’t need to be saved.

Related

Need To Revert Multiple Controls Back To Previous Values

I have the following situation where I have multiple controls on a form. The user can select an Edit mode which allows them to modify the contents of the controls (textboxes, checkboxes, comboboxes, etc.) After editing has been made, the user can either select the Save or Cancel button.
Obviously clicking on save will save all changes to the database, however, if the user clicks on cancel, I want to 'somehow' revert all controls back to their previous state.
Currently, when the user clicks on cancel, the form turns off edit mode, but the controls remain with all the changes made until they reload the form.
Is there an easy way around this, or do I need to reload the entire form content from the database each time the user clicks on cancel?
Thanks in advance.
I'm just going to outline a possible solution here.
You could have a dictionary in your form in which you store the content of your controls whenever a user first modifies them, indexing them by the control name.
When the user starts modifying a control, you check if the control already exists in the dictionary. If it doesn't you add a new entry to the dictionary with the current value of teh control.
If the user cancels the editing process, you can loop through the dictionary, find each control in your form by its name (Form.Controls(ControlName) or something like that I think), set its value back to what it was and remove the entry from the dictionary.
It's not the most elegant solution as it will involve linking up all your controls to the TextChanged event or equivalent to capture their value when they are modified...
To avoid that, you could fill the dictionary right at the start when you load your form, after populating the values from the DB and then only set those controls' value back which have a different value when the user cancels.

NSUndoManager: disable "redo" for destructive action

I'd like to add undo/redo functionality to my Mac app. The app works with notes and I'd like to add an "undo" action for when the user deletes a note.
This works just fine, the "Undo Delete Note" menu becomes active after the user deleted a note, but after using the "Undo Delete Note" command, there is a "Redo Delete Note" menu that becomes active.
Currently nothing happens when I click "Redo Delete Note", because I didn't register an action. I don't want the user to be able to delete a note accidentally through the undo/redo stack.
Is it possible to add an "undo" action without a "redo" action?
Not in the common case. And to do so would be to violate the implicit contract of the platform-standard undo/redo mechanism. You want the things you register to be symmetric. If a user deletes a note, then the available undo action should bring the note back. If the user elects to undo, then the redo action would be to "delete the note" again. It shouldn't matter if a user "accidentally" deletes a note by virtue of undo or redo, because they should always be able to get it back by doing the inverse action, right?
Don't overthink this.

Capturing undo and redo edit text groups in NSTextView

I'm writing a plugin for an existing app and I need to capture the modified text and range affected by the undo and redo action. I am able to access the NSUndoManager and NSTextView the app has created and I am able to register for notifications. Is there a way to leverage these elements to grab the group of text that is undone/redone?
I haven't done this, so I'm only going by the docs/knowledge.
Because you have access to the textview you can become a textview delegate. You'll then receive useful messages...
Before the text changes:
textView:shouldChangeTextInRange:replacementString:
textView:shouldChangeTextInRanges:replacementStrings:
textView:shouldChangeTypingAttributes:toAttributes:
After the text changes:
textViewDidChangeTypingAttributes:
I don't know if you'll receive these changes (does UndoManager bypass this stuff?), but you may. In any event you can query selection settings while handling the previous messages.
Before the selection changes:
textView:willChangeSelectionFromCharacterRange:toCharacterRange:
textView:willChangeSelectionFromCharacterRanges:toCharacterRanges:
After:
textViewDidChangeSelection:
UndoManager should tell you that it is in the process of performing an Undo, which mean that you can differentiate ordinary changes from undo-based changes.
This seems like enough to go on, I hope it helps.

How can I make a button not fire its action on click-through?

The Apple Human Interface Guidelines state that:
An item that provides click-through is one that a user can activate on an inactive window with one click, instead of clicking first to make the window active and then clicking the item. Click-through provides greater efficiency in performing such tasks as closing or resizing inactive windows, and copying or moving files. In many cases, however, click-through could confuse a user who clicks an item unintentionally.
and
Don’t provide click-through for an item or action that:
Is potentially harmful and does not allow the user to cancel it (for example, the Delete button in Mail)
Is difficult or impossible to cancel (such as the Send button in Mail)
Dismisses a dialog without telling the user what action was taken (for example, the Save button in a Save dialog that overwrites an existing file and automatically dismisses the dialog)
Removes the user from the current context (for example, selecting a new item in a Finder column can change the target of the Finder window)
What I want to do is that if the user clicks a specific button it will not send its message unless the window is active (for example, the delete message button in Mail). How can I achieve this? If I need to subclass NSButton that's fine.
Look at the NSView Documentation:
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ApplicationKit/Classes/NSView_Class/Reference/NSView.html#//apple_ref/occ/instm/NSView/acceptsFirstMouse:
You need to override acceptsFirstMouse to return TRUE to enable click through.
The default behaviour is not click-through:
The default implementation ignores theEvent and returns NO.
It's possible you have already overridden this method in your code, or in code you have based your code on. Try removing the implementation of acceptsFirstMouse in your code.

ASP.NET Keep fileupload after postback

I'm writing an intranet ASP.NET page using VB.NET. I've run into a particularly nasty problem dealing with handling file uploads. I'll do my best to explain the problem, and perhaps someone can help.
My problem is almost a duplicate of this one, or this one, except (other than the filename) I don't care about sending the file to the server until the other data has been reviewed.
Here's the situation:
Joe Q. Dataentry inputs some data into several fields. The first 3 are drop down, and when he changes the selection, a postback event is fired that queries a database for valid entries for the other drop down selections. After selecting the values, he inputs some other data, chooses a file to accompany the data and clicks the "Update" button. When he hits the button, it fires a postback event that sends the current data to the server to be validated. The data will create a change in the database, so he is presented with a view of the current state, and what it will look like when his changes are made. He can now either confirm or cancel the operation for whatever reason.
Part of the data he will see involves the extension of the file which may be a PDF, or could also be some image file or other document.
Now here's where my problem is - on each postback event, the fileupload dialog is cleared. I was getting around it by creating a temporary file on the first postback and then renaming if he clicks OK or deleting on Cancel... but I need to do a variety of things, based on the previous state of data and the filename. I've tried to keep some session variables to retain the filename, and that works OK for just renaming the file, but for what I need to do it gets unwieldy.
What I want to do is be able to have the postback event to present the changes, and then when the user clicks "OK", submit the file. Is there any possible way to do that?
One of my thoughts was to do some of the validation client-side (I'm already re-validating server side so I'm not too worried about data security there), but I don't know how I could get the information from the database query.
Thanks for any help, and reading my slightly convoluted story/situation!
EDIT:
It appears that what I want to do is prevent a certain button from firing a full postback. Is there any way to do that?
EDIT II:
I have an update panel on the page already - is there any way for the button to only post what's in the update panel?
What you might want to do is place your drop-downs inside of an ASP.NET AJAX UpdatePanel, and keep your file upload control out of that.
Your update panel will do the post backs and allow your validation logic to happen without submitting the file, then when you hit your final "Save" button (which is also outside of your UpdatePanel) the entire form will be submitted back and you can work with your file then.