Re: [Pyobjc-dev] pyobjc on 2.2.1 & non-framework builds
Brought to you by:
ronaldoussoren
From: Bill B. <bb...@co...> - 2002-10-27 22:44:29
|
On Friday, October 25, 2002, at 09:31 AM, Jack Jansen wrote: > Bill, > a couple of questions on your architectural remarks. > On Friday, Oct 25, 2002, at 02:40 Europe/Amsterdam, Bill Bumgarner > wrote: >> Bugs & Architecture: >> >> - there should be a way in the GUI to open a file into the >> settings -- i.e. the Open... command should be "Run script..." and >> "Open..." should truly open the script as a document. [...] >> >> - the 'run in terminal' button doesn't update the field contents >> and, as such, the contents can get out of sync... >> >> - If the multi-doc architecture is going to be used, there should >> be something to save! [...] >> Finally, the app really isn't a multiple-document type app. [...] > > All these hinge on the fact that PythonLauncher looks like a > multidocument application, but really isn't. Is that a problem? I > modeled the semantics more-or-less after Stuffit Expander: > PythonLauncher can operate in 2 modes, one where it's already running > (and opening a document always goes into interactive mode) and another > one where the application is started for a single document, which is > launched (optionally after allowing interaction to set the options) > after which PythonLauncher quits without further ado. Ahh... OK -- that clarifies things a bit and I'll modify my comments accordingly. I could see use for a multi-doc app if one were to want to save per-script configuration information but, as you indicate, there isn't a whole heck of a lot of value in that. A console might be nice, though, and that would open the need to leave the app running. >> - If I use the new menu item, it doesn't seem possible to set the >> script to be executed by the document. > > That's because I haven't been able to disable the New command, which > is what I really would want to do. Can you tell me how to do this? > (Or, better, tell me where I should have found the information) In a multiple document architecture app, the 'new' menu item is bound to newDocument: on the First Responder. If it should always be disabled, why not just delete the menu item? In any case, you can use Cocoa's automatic menu validation to disable the menu item. Implement the following method on the application's delegate: - (BOOL)validateMenuItem:(NSMenuItem *)aCell { SEL action = [aCell action]; if (action == @selector(newDocument:)) return NO; return YES; } -validateMenuItem: can be implemented on any object in the responder chain. Whenever a menu is popped down, the method is called for each cell in the menu -- the invocation of methods follows the same pattern as the responder chain. I.e. first responder view -> superview -> superview -> ...etc... -> window -> window's delegate -> app -> app's delegate. If you don't have any documents/windows on the screen, then the responder chain is just app -> app's delegate and, in this case, means you want to return NO for the newDocument: item from the app's delegate's implementation. >> - Since both the preferences window and the documents have the >> same interior UI, the NIB file for that UI should be split out and >> the preferences and document window should share that single NIB. >> The preferences window should likely move to a tabbed view with the >> different file types in the tabs -- that seems to be the HIG way >> these days. > > Again, I wanted to do this but I haven't been able to come up with a > way to do it. Please enlighten me. There's actually two things that I > haven't been able to find out: > 1. How can I share the interior contents of two windows? First, create a new nib file that contains a Custom View in it (a Custom View is just a container for other views, in this instance -- kind of like a window in a regular nib file). Stick the shared UI into this NIB file. The trick is that the file's owner doesn't have to be the same class as it is in the runtime-- it just needs to be the instance of some class that defines the same set of actions and outlets as are used in IB. An alternative would be to make the Settings class control the UI elements -- if the outlets are non-nil, it keeps the UI up to date and monitors user interaction with the UI. An instance of settings could then be passed as the owner. Then, when you load either the preferences panel or a script window's NIB, load this second NIB as well. Now that you have all the UI elements loaded, the trick is to shove 'em into the window. This is mostly a case of moving the various views around to make room for the new chunk of content. Very likely, the easiest solution is to simply dump a custom view into the window. Resize it to be in the position and of the same size as the chunk of UI you are going to be sharing between the two windows. Add an outlet to the PreferencesWindowController and MyDocument classes that connect to the view to be replaced. Then, in awakeFromNib:, do something like: [[viewToBeReplacedWithRealContents superview] replaceSubview: viewToBeReplacedWithRealContents with: customViewThatContainsTheSharedContentsInThatOtherNibFile] More sane variable names would likely be preferable... (For the preferences controller, there is no need to do the view swap thing as the TabView already has a view in it that can be used to swap the UI elements in as necessary. > 2. How do I get a tabbed view without actually having something > different on every tab (I want the same controls on each tab, really, > and I don't want to duplicate either the code or the controls)? Good question. I don't... didn't... know. I gave it a try and it boils down to a one liner (I love Cocoa that way :-). Set your window controller (document, whatever) to be the delegate of the Tab View. Then, implement something like: - (void)tabView:(NSTabView *)aTabView didSelectTabViewItem:(NSTabViewItem *)tabViewItem; { // share the shared UI elements across all tabs. Use -identifier to figure out which tab was selected if you want to do so passively. Alternatively, use [[tabView selectedTabViewItem] ...] or create three outlets to the tab view items and simply do == when updating / reading from the UI. NSLog(@"Did select tab %@ (%@)", [tabViewItem identifier], [tabViewItem label]); [[[tabView selectedTabViewItem] view] addSubview: sharedUIElements]; } To make sure *something* is displayed when the nib is loaded, do the following in, say, -awakeFromNib: [[[tabView selectedTabViewItem] view] addSubview: sharedUIElements]; You can grab the example from the following URL -- it is bogus save for the tab view manipulation. It also shows how to programmatically create tabs -- may be necessary if you want to support a dynamic list of configurations or something similar. http://www.friday.com/software/examples/tabtest.tgz >> - NSTask would be a better candidate than system() to subshell >> out the command. It would allow the app to monitor the output and >> display a console. > [...] >> The first step in moving to a true multi-doc style app is for the app >> to give the user control over when documents are closed -- that is, >> if a user opens a python script [as opposed to Running... a script >> without opening a visible document at all], the associated window >> should remain open until the user tells it to go away. The document >> should have a notion of 'currently running, do you want to launch >> another instance of the same thing?' and 'abort/stop current run'. > > These are things I specifically don't want to do (i.e. convince me > otherwise if you think it's worthwhile). The intention of > PythonLauncher is to be like Java AppletLauncher (or the above > mentioned Stuffit Expander): it should "fire and forget" the script. > Remember, the reason this was written in the first place is because > CFBundleTypeRole=Shell doesn't work (which is what it's trying to > emulate, with the options dialog thrown in so that we no longer have > to provide that in pythonw, and have the functionality for console > scripts too). Ideally a naive user shouldn't even be aware of the fact > that this thing exists. I'm all for keeping it as simple as possible. If someone really wants to have more control over the execution of a script, then they can use the IDE or command line directly. Given the clarification as to the design goals provided above, these requested features are pretty much out the window-- but they would be nice to have in other contexts... b.bum |