Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

custom options during save in a document app

46 views
Skip to first unread message

Riccardo Mottola

unread,
Sep 28, 2012, 4:28:06 AM9/28/12
to discuss...@gnu.org
Hi,

I want to handle two different filetypes during save in a document based
application. For one of the type I need an option view in the panel to
set some parameters.

I did that in a "standard" application. There it is easy: I have a save
method which has the task to create and display the save panel, so it
can instantiate it, add the view, read the parameters and perform the
save by directly writing the file.

In my doc-based app however, I have a document and a window controller.
To save I have overidden "dataRepresentationOfType" (actual work) and
"saveDocumentAs" (to add the file extension, nothing more).

dataRepresentationOfType is fine for now: currently type is "TIFF".
Adding "JPEG" is trivial. I need however the compression rate, somehow
an additional parameter.

But where/how can I add my view to the panel and handle its parameter?
Can I override a method I do not see or do i need to throw-away part of
what document-based apps offer me?

Riccardo

Fred Kiefer

unread,
Sep 28, 2012, 5:11:53 AM9/28/12
to Riccardo Mottola, discuss...@gnu.org
You best options here is to override the method -prepareSavePanel in our
NSDocument subclass, which is the Apple recommended way of doing this.
You will also have to override shouldRunSavePanelWithAccessoryView to
return NO, otherwise the standard accessory view will still be displayed.

From there on down you will have to replace all the standard NSDocument
methods to handle your additional parameters. There is no way around that.




Riccardo Mottola

unread,
Oct 5, 2012, 5:06:48 AM10/5/12
to Fred Kiefer, discuss...@gnu.org
Hi Fred & Nikolaus,

thank you for your suggestions, they were mostly overlapping, so I was
confident it was the best way!

Fred Kiefer wrote:
> You best options here is to override the method -prepareSavePanel in
> our NSDocument subclass, which is the Apple recommended way of doing
> this. You will also have to override
> shouldRunSavePanelWithAccessoryView to return NO, otherwise the
> standard accessory view will still be displayed.
>
> From there on down you will have to replace all the standard
> NSDocument methods to handle your additional parameters. There is no
> way around that.
by searching on the web I found another important method to override:
- (NSString *)fileTypeFromLastRunSavePanel

which is very important if the new accessory view changes the filetype.
I found no other way to "set it", since setFileType doesn't work.

I have one problem though: the file extension.

Previously, i was running this in saveDocumentAs (thus "before")
filepath = [[filepath stringByDeletingPathExtension]
stringByAppendingString: @".tiff"];
[self setFileName:filepath];
[self setFileType: @"tiff"];

that's easy, since I only have one filetype, I could preset the
extension and normalize it before opening the panel. I may have many
extensions, because PRICE is "editor" of only TIFF files (or, in the
future JPEG and a few others) but "opens" all file types supported by GUI.

The best would be that on the change of the filetype popup (don't try
that on GNUstep yet or, if, substitute PRWindow.gorm file with
PRWindow.nib, there is a strange bug affecting only gorm).

How can I set the filename with the filepanel running? The filetype is
not a problem since it gets "set" later cleanly with the method
mentioned above.

Riccardo

Fred Kiefer

unread,
Oct 5, 2012, 6:02:16 AM10/5/12
to Riccardo Mottola, discuss...@gnu.org
I don't quite understand what you are asking here. Somewhere in your
code you run the actual save panel, with what ever extensions you need.
When this code returns you ask the save panel for the selected filename
and file type. This surely isn't the problem.
Do you want to change the filename that is displayed in the save panel
itself? This should be automatically adjusted when ever you select a
different file type. I just tested with Ink and there this mechanism
seems to work.
Most likely you are talking about a different problem that I fail to see.

Fred


Wolfgang Lux

unread,
Oct 5, 2012, 6:05:37 AM10/5/12
to Riccardo Mottola, Fred Kiefer, discuss...@gnu.org
Hi Riccardo,

> Hi Fred & Nikolaus,
>
> thank you for your suggestions, they were mostly overlapping, so I was confident it was the best way!
>
> Fred Kiefer wrote:
>> You best options here is to override the method -prepareSavePanel in our NSDocument subclass, which is the Apple recommended way of doing this. You will also have to override shouldRunSavePanelWithAccessoryView to return NO, otherwise the standard accessory view will still be displayed.
>>
>> From there on down you will have to replace all the standard NSDocument methods to handle your additional parameters. There is no way around that.
> by searching on the web I found another important method to override:
> - (NSString *)fileTypeFromLastRunSavePanel
>
> which is very important if the new accessory view changes the filetype. I found no other way to "set it", since setFileType doesn't work.
>
> I have one problem though: the file extension.
>
> Previously, i was running this in saveDocumentAs (thus "before")
> filepath = [[filepath stringByDeletingPathExtension] stringByAppendingString: @".tiff"];
> [self setFileName:filepath];
> [self setFileType: @"tiff"];
>
> that's easy, since I only have one filetype, I could preset the extension and normalize it before opening the panel. I may have many extensions, because PRICE is "editor" of only TIFF files (or, in the future JPEG and a few others) but "opens" all file types supported by GUI.
>
> The best would be that on the change of the filetype popup (don't try that on GNUstep yet or, if, substitute PRWindow.gorm file with PRWindow.nib, there is a strange bug affecting only gorm).
>
> How can I set the filename with the filepanel running? The filetype is not a problem since it gets "set" later cleanly with the method mentioned above.

I think you are on a completely wrong track here. If you want to add a JPEG file type to PRICE, you should declare that in the NSTypes (or CFBundleDocumentTypes) section of the Info.plist file as a separate type, but using the same NSDocumentClass as for TIFF files. Then, the NSDocument framework will automatically handle the file type and file extension for you and you shouldn't override saveDocumentAs: (it will not work in the way you'd expect on OS X anyway thanks to document modal sheets anyway).

To add options for the JPEG type you must add an accessory view to the save panel in -prepareSavePanel:, as Fred and Nikolaus suggested. Make sure you save the values selected by the user in attributes of your document class, so you have them available in -dataRepresentationOfType:

Wolfgang


Riccardo Mottola

unread,
Oct 5, 2012, 6:29:22 AM10/5/12
to Fred Kiefer, discuss...@gnu.org
Hi Fred,

Fred Kiefer wrote:
> I don't quite understand what you are asking here. Somewhere in your
> code you run the actual save panel, with what ever extensions you
> need. When this code returns you ask the save panel for the selected
> filename and file type. This surely isn't the problem.
> Do you want to change the filename that is displayed in the save panel
> itself? This should be automatically adjusted when ever you select a
> different file type. I just tested with Ink and there this mechanism
> seems to work.
> Most likely you are talking about a different problem that I fail to see.
I want to reproduce exactly that behaviour. But now the file type
selection is inside my accessory view becasue for JPEG I added some
options, so I need a way to handle that myself (or "attach" to the
existing tools the standard one uses).

I don't think I can leave the standard file type selection and enable
osme options only for certain types? that would mean two option views...

Riccardo


Riccardo Mottola

unread,
Oct 5, 2012, 8:37:33 AM10/5/12
to Wolfgang Lux, Fred Kiefer, discuss...@gnu.org
Hi Wolfgang,

Wolfgang Lux wrote:
> Hi Riccardo,
> I think you are on a completely wrong track here. If you want to add a JPEG file type to PRICE, you should declare that in the NSTypes (or CFBundleDocumentTypes) section of the Info.plist file as a separate type, but using the same NSDocumentClass as for TIFF files. Then, the NSDocument framework will automatically handle the file type and file extension for you and you shouldn't override saveDocumentAs: (it will not work in the way you'd expect on OS X anyway thanks to document modal sheets anyway).
>
> To add options for the JPEG type you must add an accessory view to the save panel in -prepareSavePanel:, as Fred and Nikolaus suggested. Make sure you save the values selected by the user in attributes of your document class, so you have them available in -dataRepresentationOfType:
>
Exactly, I added an accessory view, however as far as I understand, the
document types are now my burden. I do not want to override
saveDocumentAs anymore, at least not for this need. I can read back what
was selected with fileTypeFromLastRunSavePanel, however in the
"standard" view which these the type selection generated by the
NSDocumentClass are handled automatically. In the standard panel,
selection them does change the extension of the file directly (and
perhaps does other things too and I want to emulate this).

Your suggestion would be then to populate the popup dynamically by the
supported NSDocumentClass types? That would be a further plus that adds
some burden, since some have certain options other others, but could be
cool.

Riccardo

Dr. H. Nikolaus Schaller

unread,
Oct 5, 2012, 8:56:17 AM10/5/12
to Riccardo Mottola, Fred Kiefer, discuss...@gnu.org
Maybe you can try to give the SavePanel a delegate and implement the NSOpenSavePanelDelegate protocol?

So it should become possible to check the file extension as it is typed in. And you could then be possible to add or remove the accessory view dynamically.

Nikolaus


Wolfgang Lux

unread,
Oct 5, 2012, 9:17:14 AM10/5/12
to Riccardo Mottola, Fred Kiefer, discuss...@gnu.org
Riccardo Mottola wrote:

> Hi Wolfgang,
>
> Wolfgang Lux wrote:
>> Hi Riccardo,
>> I think you are on a completely wrong track here. If you want to add a JPEG file type to PRICE, you should declare that in the NSTypes (or CFBundleDocumentTypes) section of the Info.plist file as a separate type, but using the same NSDocumentClass as for TIFF files. Then, the NSDocument framework will automatically handle the file type and file extension for you and you shouldn't override saveDocumentAs: (it will not work in the way you'd expect on OS X anyway thanks to document modal sheets anyway).
>>
>> To add options for the JPEG type you must add an accessory view to the save panel in -prepareSavePanel:, as Fred and Nikolaus suggested. Make sure you save the values selected by the user in attributes of your document class, so you have them available in -dataRepresentationOfType:
>>
> Exactly, I added an accessory view, however as far as I understand, the document types are now my burden. I do not want to override saveDocumentAs anymore, at least not for this need. I can read back what was selected with fileTypeFromLastRunSavePanel, however in the "standard" view which these the type selection generated by the NSDocumentClass are handled automatically. In the standard panel, selection them does change the extension of the file directly (and perhaps does other things too and I want to emulate this).
>
> Your suggestion would be then to populate the popup dynamically by the supported NSDocumentClass types? That would be a further plus that adds some burden, since some have certain options other others, but could be cool.

What I meant (and I guess I wasn't clear about that) is that you should not try to reimplement any functionality provided by NSDocument. NSDocument has already created the pop up with the document types at the time -prepareSavePanel: is called. So in your implementation of that method just ask the save panel for its current accessory view and add your own elements to that view (you may eventually need to resize the existing view for that). Or make the existing accessory view a subview of your own accessory view. If you want to dynamically change the save panel options depending on the document type currently chosen by the user, you can do so by overriding the (undocumented) NSDocument method -changeSaveType:. However, if you do so, be sure to call the super class implementation in your own method.

Wolfgang


Riccardo Mottola

unread,
Oct 5, 2012, 9:56:13 AM10/5/12
to Wolfgang Lux, discuss...@gnu.org
Hi,

Wolfgang Lux wrote:
> Riccardo Mottola wrote:
> What I meant (and I guess I wasn't clear about that) is that you should not try to reimplement any functionality provided by NSDocument. NSDocument has already created the pop up with the document types at the time -prepareSavePanel: is called. So in your implementation of that method just ask the save panel for its current accessory view and add your own elements to that view (you may eventually need to resize the existing view for that). Or make the existing accessory view a subview of your own accessory view. If you want to dynamically change the save panel options depending on the document type currently chosen by the user, you can do so by overriding the (undocumented) NSDocument method -changeSaveType:. However, if you do so, be sure to call the super class implementation in your own method.
>
Aha, so you say I should just try to extend the existing view. That
sounds the best way of course.
I precisely want to that. Currently TIFF has no options, JPEG has a
compression slider. Theoretically also TIFF has compression or not, but
just boolean. If, in the future, I'll support something else, it might
need for example Transparency for GIF and PNG...

Perhaps the best way would be to have N different small "options only"
accessory views, like TIFFOptionsView, JPEGOptionsView and add them as a
subview of the existing accessory view, but I don't know well how to
mess with it.

is changeSaveType, undocumented, available on both Mac and GS? or is it
some kind of extension? That would be the place probably where to add
the view-swizzling code.

Riccardo

Wolfgang Lux

unread,
Oct 5, 2012, 10:10:27 AM10/5/12
to Riccardo Mottola, discuss...@gnu.org
Riccardo Mottola wrote:

> is changeSaveType, undocumented, available on both Mac and GS? or is it some kind of extension? That would be the place probably where to add the view-swizzling code.

It is available on both Cocoa and GNUstep (otherwise, I wouldn't have suggested using it :-)

Wolfgang


Fred Kiefer

unread,
Oct 5, 2012, 10:11:01 AM10/5/12
to discuss...@gnu.org
On 05.10.2012 15:56, Riccardo Mottola wrote:
>
> is changeSaveType, undocumented, available on both Mac and GS? or is it
> some kind of extension? That would be the place probably where to add
> the view-swizzling code.

According to this post it is available on Apple as well:

http://lists.apple.com/archives/cocoa-dev/2004/Jan/msg00778.html

Riccardo Mottola

unread,
Oct 6, 2012, 7:21:44 AM10/6/12
to Wolfgang Lux, discuss...@gnu.org
Hi,

Wolfgang Lux wrote:
> Riccardo Mottola wrote:
>
>> is changeSaveType, undocumented, available on both Mac and GS? or is it some kind of extension? That would be the place probably where to add the view-swizzling code.
> It is available on both Cocoa and GNUstep (otherwise, I wouldn't have suggested using it :-)
>
Indeed, it exists and works. I just get a warning when I call [super
changeSaveType:sender] but it works as advertised (well from you, Apple
keeps it hidden!).
Perhaps the best thing would be to add/remove from the accessoryView the
options for each file tye and make it totally dynamic.

Now some further questions:
how do I get the current accessory view to modify it with my stuff? I
could call "superview" on the sender which is the popupbutton, but it
seems dirty. [savePanel accessoryView] ? I tried getting the
accessoryView and making it larger, but it doesn't work, it is a NSBox,
which makes sense under Mac. Perhaps the default one is not saved in
accessoryView?

Second, in the changeSaveType method I need to know which filetype was
selected. The document has not yet an updated fileType (hence the need
of fileTYpeFromLastRunSavePanel of course).
A way would be to read directly the contents of the popupbutton, but
perhaps there is a cleaner way. It appears to have the document name.

It looks like I have a clear idea of what to do, but getting list in the
implementation details, I hate this!

Riccardo

Wolfgang Lux

unread,
Oct 6, 2012, 8:40:30 AM10/6/12
to Riccardo Mottola, discuss...@gnu.org
Riccardo Mottola wrote:

> Hi,
>
> Wolfgang Lux wrote:
>> Riccardo Mottola wrote:
>>
>>> is changeSaveType, undocumented, available on both Mac and GS? or is it some kind of extension? That would be the place probably where to add the view-swizzling code.
>> It is available on both Cocoa and GNUstep (otherwise, I wouldn't have suggested using it :-)
>>
> Indeed, it exists and works. I just get a warning when I call [super changeSaveType:sender] but it works as advertised (well from you, Apple keeps it hidden!).

You might add a declaration
@interface NSDocument(Hidden)
- (void)changeSaveType: (NSString *)fileType;
@end
to get rid of the warning.

> Perhaps the best thing would be to add/remove from the accessoryView the options for each file tye and make it totally dynamic.
>
> Now some further questions:
> how do I get the current accessory view to modify it with my stuff? I could call "superview" on the sender which is the popupbutton, but it seems dirty. [savePanel accessoryView] ? I tried getting the accessoryView and making it larger, but it doesn't work, it is a NSBox, which makes sense under Mac. Perhaps the default one is not saved in accessoryView?

If changing the size of the accessory view doesn't work, create your own view and make the view returned from -accessoryView a subview of your own view. On the other hand, if the accessory view is a NSBox on Cocoa, you may want to create your own NSBox for the accessory view and only add the content view of the NSBox to your view.

> Second, in the changeSaveType method I need to know which filetype was selected. The document has not yet an updated fileType (hence the need of fileTYpeFromLastRunSavePanel of course).

The new file type is passed as argument to the -changeSaveType: method.

Wolfgang

Riccardo Mottola

unread,
Oct 6, 2012, 4:33:43 PM10/6/12
to Wolfgang Lux, discuss...@gnu.org
Hi,

thanks Wolfgang, I have some dirty, but almost working code. I shuffle
the view on panel creation, I was unablle to dynamically
> Riccardo Mottola wrote:
>
>
> You might add a declaration
> @interface NSDocument(Hidden)
> - (void)changeSaveType: (NSString *)fileType;
> @end
> to get rid of the warning.
apparently it is of type (id)sender. Read below.
> The new file type is passed as argument to the -changeSaveType: method.
It appears instead that the sender is passed: NSPopUpButton, I printed
out the sender.

I made a hack now to use pos.1 and pos2.. just to test (it is bad of
course, since the order and generally the filetypes might change). It
shows the concept can work, I will commit it so you can see it and i can
test it on gnustep too.

Besides the file-type hack, other two things need a solution:
- on load, I don't know how to "initialize" the values. In my old code,
I issued a message to simulate a "click" on the popupbutton, which thus
syncronized all the values. Here I don't have a reference to the
popupbutton to click! Also I can't assume that the default filetype is
TIFF or JPEG for example
- the document "remembers" how it was last saved! so once it has a
filetype, the next time you do saveAs it removes the accessory view!.
Also TextEdit doesn't behave this way, so I fear it is something I do.
Perhaps the accessoryView doesn't get regenerated? I don't know, the
documentation says it gets released, thus I suppose it is logically
recreated the next time.


Riccardo


Wolfgang Lux

unread,
Oct 7, 2012, 3:33:33 AM10/7/12
to Riccardo Mottola, discuss...@gnu.org
Riccardo Mottola wrote:

> thanks Wolfgang, I have some dirty, but almost working code. I shuffle the view on panel creation, I was unablle to dynamically
>> Riccardo Mottola wrote:
>>
>>
>> You might add a declaration
>> @interface NSDocument(Hidden)
>> - (void)changeSaveType: (NSString *)fileType;
>> @end
>> to get rid of the warning.
> apparently it is of type (id)sender. Read below.
>> The new file type is passed as argument to the -changeSaveType: method.
> It appears instead that the sender is passed: NSPopUpButton, I printed out the sender.

Ummm, sorry, you are of course right. I got confused at some point.

> I made a hack now to use pos.1 and pos2.. just to test (it is bad of course, since the order and generally the filetypes might change). It shows the concept can work, I will commit it so you can see it and i can test it on gnustep too.

No need to use hacks. The proper way to find out the selected file type is [[sender selectedItem] representedObject].

> Besides the file-type hack, other two things need a solution:
> - on load, I don't know how to "initialize" the values. In my old code, I issued a message to simulate a "click" on the popupbutton, which thus syncronized all the values. Here I don't have a reference to the popupbutton to click! Also I can't assume that the default filetype is TIFF or JPEG for example

Not sure what your problem is here. There is nothing you need to initialize. NSDocument automatically selects the current document type (as returned by the -fileType method) for you.

> - the document "remembers" how it was last saved! so once it has a filetype, the next time you do saveAs it removes the accessory view!. Also TextEdit doesn't behave this way, so I fear it is something I do. Perhaps the accessoryView doesn't get regenerated? I don't know, the documentation says it gets released, thus I suppose it is logically recreated the next time.

At least under GNUstep the pop up button is created just once and retained by the NSDocument class. The next time you use the save panel the pop up button will be reused and set as accessory view of the save panel before -prepareSavePanel is called. If that doesn't work for you, you seem to have a major bug in your code.

Wolfgang


Riccardo Mottola

unread,
Oct 7, 2012, 5:46:07 AM10/7/12
to Wolfgang Lux, discuss...@gnu.org
Hi Wolfgang,

On 2012-10-07 09:33:33 +0200 Wolfgang Lux <wolfga...@gmail.com>
wrote:

>> I made a hack now to use pos.1 and pos2.. just to test (it is bad of
>> course, since the order and generally the filetypes might change).
>> It shows
>> the concept can work, I will commit it so you can see it and i can
>> test it
>> on gnustep too.
>
> No need to use hacks. The proper way to find out the selected file
> type is
> [[sender selectedItem] representedObject].

Perfect. The represented object is a NSString and contains directly
the filetype. I cleaned up the code, it works fine and commited it.

> Not sure what your problem is here. There is nothing you need to
> initialize.
> NSDocument automatically selects the current document type (as
> returned by
> the -fileType method) for you.
I need to initialize my option controls, specifically I send an action
to the compression ration slider, so it reads its value and sends it
to the text field. I do this if" "JPEG" is selected, but not if "TIFF"
since it is not needed.

At startup, the document type gets selected automatically, but it does
not "perform" the action. So if it selects TIFF it is fine, but if it
is already JPEG, the fields are uninitialized.
Perhaps I should check duing the file panel creation, but there I
don't have the "sener", that is the popupbutton, to explicitely check
for the type.


> At least under GNUstep the pop up button is created just once and
> retained by
> the NSDocument class. The next time you use the save panel the pop up
> button
> will be reused and set as accessory view of the save panel before
> -prepareSavePanel is called. If that doesn't work for you, you seem
> to have a
> major bug in your code.
I don't doubt there are bugs lurking around.

On mac, if I do "save as" and "save as again" I get twice this log:

2012-10-07 11:13:37.651 PRICE[1316] prepareSavePanel, original
accessory view class: NSBox
2012-10-07 11:13:37.666 PRICE[1316] original content view: <NSView:
0x4692f0>
2012-10-07 11:13:37.669 PRICE[1316] new options view: <NSBox: 0x4d6840>

<...>

2012-10-07 11:13:48.188 PRICE[1316] prepareSavePanel, original
accessory view class: NSBox
2012-10-07 11:13:48.188 PRICE[1316] original content view: <NSView:
0x5828d70>
2012-10-07 11:13:48.188 PRICE[1316] new options view: <NSBox: 0x4d6840>

this means that the options view loaded from the nib is the same, but
he view of the savepanel is different.

On GNUstep I ca't get anything to work at the moment, I expect I need
some slight different reparent code, because the accessory view is not
a Box, however right now I get "null" for the original content view.
Does it work for you?

Rccardo


Wolfgang Lux

unread,
Oct 7, 2012, 8:02:37 AM10/7/12
to Riccardo Mottola, discuss...@gnu.org
Riccardo Mottola wrote:

>> Not sure what your problem is here. There is nothing you need to initialize. NSDocument automatically selects the current document type (as returned by the -fileType method) for you.
> I need to initialize my option controls, specifically I send an action to the compression ration slider, so it reads its value and sends it to the text field. I do this if" "JPEG" is selected, but not if "TIFF" since it is not needed.
>
> At startup, the document type gets selected automatically, but it does not "perform" the action. So if it selects TIFF it is fine, but if it is already JPEG, the fields are uninitialized.
> Perhaps I should check duing the file panel creation, but there I don't have the "sener", that is the popupbutton, to explicitely check for the type.

You don't need the pop up button. I told you above that the pop up button is set to the current type of the document and this is what NSDocument's -fileType method returns!

>> At least under GNUstep the pop up button is created just once and retained by the NSDocument class. The next time you use the save panel the pop up button will be reused and set as accessory view of the save panel before -prepareSavePanel is called. If that doesn't work for you, you seem to have a major bug in your code.
> I don't doubt there are bugs lurking around.
>
> On mac, if I do "save as" and "save as again" I get twice this log:
>
> 2012-10-07 11:13:37.651 PRICE[1316] prepareSavePanel, original accessory view class: NSBox
> 2012-10-07 11:13:37.666 PRICE[1316] original content view: <NSView: 0x4692f0>
> 2012-10-07 11:13:37.669 PRICE[1316] new options view: <NSBox: 0x4d6840>
>
> <...>
>
> 2012-10-07 11:13:48.188 PRICE[1316] prepareSavePanel, original accessory view class: NSBox
> 2012-10-07 11:13:48.188 PRICE[1316] original content view: <NSView: 0x5828d70>
> 2012-10-07 11:13:48.188 PRICE[1316] new options view: <NSBox: 0x4d6840>
>
> this means that the options view loaded from the nib is the same, but he view of the savepanel is different.

Which doesn't surprise me much, as the save panel on OS X on the second call should be different as well :-)
Contrary to what the documentation says, you get a new panel for each call of NSSavePanel -savePanel. But then, this shouldn't matter much for your code.

> On GNUstep I ca't get anything to work at the moment, I expect I need some slight different reparent code, because the accessory view is not a Box, however right now I get "null" for the original content view. Does it work for you?

Just checked and it indeed doesn't work on GNUstep. Turns out this is because GNUstep is still using a long deprecated API (-runModalSavePanel:withAccessoryView:) to present the save panel. However, this gives you a different option to modify the accessory: Override that NSDocument method and change the accessoryView passed to that method before calling the super class implementation.

Wolfgang


Riccardo Mottola

unread,
Oct 7, 2012, 4:52:53 PM10/7/12
to Wolfgang Lux, discuss...@gnu.org
Hi,

On 2012-10-07 14:02:37 +0200 Wolfgang Lux <wolfga...@gmail.com>
wrote:

>
> You don't need the pop up button. I told you above that the pop up
> button is
> set to the current type of the document and this is what
> NSDocument's
> -fileType method returns!
yes, got that, I use that on startup to know which type is presented
and I shuffeld the code to initialize the status each time, easy.
Works like a charme now. (on the first run, that is)

> Which doesn't surprise me much, as the save panel on OS X on the
> second call
> should be different as well :-)
> Contrary to what the documentation says, you get a new panel for each
> call of
> NSSavePanel -savePanel. But then, this shouldn't matter much for your
> code.
exactly, I don't care if I get each time a new one. I retain my
original view coming from the NIB file.

What coiuld be is that the the panel's view which I add to my own view
gets released and that this causes toruble? I dont' see why, I add one
next time. Perhaps it should bre cleanly "removed" from th superview
instead of just being released? that would become tricky. I in fact
get this exception now, on Mac:

2012-10-07 19:17:12.077 PRICE[1495] *** -[NSCFString setEnabled:]:
selector not recognized [self = 0x4ffbe0]
2012-10-07 19:17:12.082 PRICE[1495] *** -[NSCFString setEnabled:]:
selector not recognized [self = 0x4ffbe0]
this is bgous, this is actually, according to gdb, there the
compression slider gets enabled! not a string.

Another run got me:
2012-10-07 22:15:15.282 PRICE[1561] *** -[_NSViewAuxiliary
setEnabled:]: selector not recognized [self = 0x4d1640]
2012-10-07 22:15:15.307 PRICE[1561] *** -[_NSViewAuxiliary
setEnabled:]: selector not recognized [self = 0x4d1640]

This shows that it is "random stuff", just some kind of memory
corruption I guess,

>> On GNUstep I ca't get anything to work at the moment, I expect I
>> need some
>> slight different reparent code, because the accessory view is not a
>> Box,
>> however right now I get "null" for the original content view. Does
>> it work
>> for you?
>
> Just checked and it indeed doesn't work on GNUstep. Turns out this is
> because
> GNUstep is still using a long deprecated API
> (-runModalSavePanel:withAccessoryView:) to present the save panel.
> However,
> this gives you a different option to modify the accessory: Override
> that
> NSDocument method and change the accessoryView passed to that method
> before
> calling the super class implementation.

Why does it matter? the calling sequence is different? I see my
methods called, but the values are still null. So th calls look
compatible, but something is perhaps not initialised?

I tried overriding it in MyDocument.m and it never gets called :(

Riccardo


Wolfgang Lux

unread,
Oct 8, 2012, 8:42:58 AM10/8/12
to Riccardo Mottola, discuss...@gnu.org
Riccardo Mottola wrote:

>>> On GNUstep I ca't get anything to work at the moment, I expect I need some slight different reparent code, because the accessory view is not a Box, however right now I get "null" for the original content view. Does it work for you?
>> Just checked and it indeed doesn't work on GNUstep. Turns out this is because GNUstep is still using a long deprecated API (-runModalSavePanel:withAccessoryView:) to present the save panel. However, this gives you a different option to modify the accessory: Override that NSDocument method and change the accessoryView passed to that method before calling the super class implementation.
>
> Why does it matter? the calling sequence is different? I see my methods called, but the values are still null. So th calls look compatible, but something is perhaps not initialised?

Okay, looks like I have to explain myself once again.
When GNUstep presents a save panel (from the saveDocument, saveDocumentAs, and saveDocumentTo actions), it ultimately presents an application modal save panel going through the -runModalSavePanel:withAccessoryView: method. This gets the default accessory view of the AppKit passed in and allows subclasses to modify that accessory view or create a different view before calling the super class implementation in NSDocument, which actually displays the panel.
Apple has switched to using document modals panels (aka sheets) for NSDocument in MacOS X Public Beta and now calls -runModalSavePanelForSaveOperation:delegate:didSaveSelector:contextInfo: instead of -runModalSavePanel:withAccessoryView:. To allow customization of the save panel, the new method calls -prepareSavePanel:. You can find this information in Apple's older AppKit release notes.
Now GNUstep implements a strange mixture by calling the new method (and hence -prepareSavePanel:) when a document save panel is to be presented and then calling the old method from there.

So, my idea (not spelled out explicitly) is that you override -runModalSavePanel:withAccessoryView: to customize the accessory view under GNUstep and to use -prepareSavePanel: to customize it under Cocoa when -accessoryView returns a non-nil view.


> I tried overriding it in MyDocument.m and it never gets called :(

It is called for me, i.e. on GNUstep not on Cocoa.

Wolfgang


Riccardo Mottola

unread,
Oct 8, 2012, 9:48:41 AM10/8/12
to Wolfgang Lux, discuss...@gnu.org
Hi Wolfgang,

thanks for your patience. I still don't have it working, but I least
understand things a bit better.

Wolfgang Lux wrote:
> Riccardo Mottola wrote:
>
> Okay, looks like I have to explain myself once again.
> When GNUstep presents a save panel (from the saveDocument, saveDocumentAs, and saveDocumentTo actions), it ultimately presents an application modal save panel going through the -runModalSavePanel:withAccessoryView: method. This gets the default accessory view of the AppKit passed in and allows subclasses to modify that accessory view or create a different view before calling the super class implementation in NSDocument, which actually displays the panel.
> Apple has switched to using document modals panels (aka sheets) for NSDocument in MacOS X Public Beta and now calls -runModalSavePanelForSaveOperation:delegate:didSaveSelector:contextInfo: instead of -runModalSavePanel:withAccessoryView:. To allow customization of the save panel, the new method calls -prepareSavePanel:. You can find this information in Apple's older AppKit release notes.
> Now GNUstep implements a strange mixture by calling the new method (and hence -prepareSavePanel:) when a document save panel is to be presented and then calling the old method from there.
Thanks for the explanation. GS tries to be compatible with both, but
since the order is different, when it comes up to prepareSavePanel, the
view is not initialized?
>
> So, my idea (not spelled out explicitly) is that you override -runModalSavePanel:withAccessoryView: to customize the accessory view under GNUstep and to use -prepareSavePanel: to customize it under Cocoa when -accessoryView returns a non-nil view.
>
>
>> I tried overriding it in MyDocument.m and it never gets called :(
> It is called for me, i.e. on GNUstep not on Cocoa.
I attach my little patch for GS, code is easier than words sometimes.
My goal is to override in MyDocument and call the same method in the
WindowController. In case, i can make one or the other override
conditioned by an #ifdef if necessary.

I did not get a call into runModalSavePanel before because I got an
exception in the controller.

The output I get (with my patch) is:
2012-10-08 13:44:20.989 PRICE[2448] prepareSavePanel
2012-10-08 13:44:20.989 PRICE[2448] prepareSavePanel, original accessory
view class: (null)
2012-10-08 13:44:20.990 PRICE[2448] original content view: (null)
2012-10-08 13:44:20.990 PRICE[2448] new options view: h=-&- v=-&-
<NSView: 0x2b34a3c4> f={x = 1; y = 9; width = 348; height = 86} b={x =
0; y = 0; width = 348; height = 86}
2012-10-08 13:44:20.990 PRICE[2448] runModalSavePanel:
withAccessoryView. We should see this only on GS
2012-10-08 13:44:20.990 PRICE[2448] prepareSavePanel, original accessory
view class: NSView
2012-10-08 13:44:20.990 PRICE[2448] original content view: h=-&- v=--&
<NSView: 0x2b34a3c4> f={x = 0; y = 40; width = 348; height = 86} b={x =
0; y = 0; width = 348; height = 86}
2012-10-08 13:44:20.990 PRICE[2448] new options view: h=-&- v=--&
<NSView: 0x2b34a3c4> f={x = 0; y = 40; width = 348; height = 86} b={x =
0; y = 0; width = 348; height = 86}
2012-10-08 13:44:20.991 PRICE[2448] reported exception - <NSException:
0x2b33e144> NAME:NSInvalidArgumentException
REASON:addSubview:positioned:relativeTo: creates a loop in the views
tree! INFO:(null)


I am trying to take in account the differences between GS and Cocoa
recarding views and boxes, but something is still wrong there. Shouldn't
we in the long run just adopt Cocoa's behaviour?

In any case, i still have the problem that on Cocoa it doesn't work on
the second run for me, so anything is still a bit flaky.

Riccardo
GS-accessoryView.patch

Riccardo Mottola

unread,
Oct 8, 2012, 2:32:26 PM10/8/12
to Wolfgang Lux, discuss...@gnu.org
Hi,

On 2012-10-08 14:42:58 +0200 Wolfgang Lux <wolfga...@gmail.com>
wrote:

> So, my idea (not spelled out explicitly) is that you override
> -runModalSavePanel:withAccessoryView: to customize the accessory view
> under
> GNUstep and to use -prepareSavePanel: to customize it under Cocoa
> when
> -accessoryView returns a non-nil view.

If I run the patch which I attached in my other mail on mac 10.4, I
get:

2012-10-08 20:21:24.278 PRICE[327] *** WARNING: Method
fileNameFromRunningSavePanelForSaveOperation: in class MyDocument is
obsolete and will be removed in release GM ***
2012-10-08 20:21:24.541 PRICE[327] runModalSavePanel:
withAccessoryView. We should see this only on GS
2012-10-08 20:21:24.542 PRICE[327] set type to Jpeg
2012-10-08 20:21:24.560 PRICE[327] prepareSavePanel, original
accessory view class: NSBox
2012-10-08 20:21:24.561 PRICE[327] original content view: <NSView:
0x4155f0>
2012-10-08 20:21:24.561 PRICE[327] new options view: <NSBox: 0x4d4bf0>


and it even works.. it is interesting that prepareSavePaenl is in that
case NOT called, the output is different than on GS.
10.4 is old, but quite newer than GM :) I think I still have GM
around...

reopening the panel obviously doesn't work, I wouldn't expect that.

Riccardo


0 new messages