Thread: [Pyobjc-dev] Subclassing NSTextField
Brought to you by:
ronaldoussoren
From: Steven D. A. <st...@ne...> - 2002-12-17 19:25:51
|
Hi, I may be having several misconceptions here, but I've looked at several sources without success, so I thought I'd ask. I want to examine the keys that are typed into an NSTextField, so I subclassed NSTextField in IB. In IB, I drew an NSTextField and set its custom class to my new class. Then in Main.py I defined the class as follows: class SearchTextField( AppKit.NSTextField ): #def init( self ): # print "initializing SearchTextField" # return self def keyDown_( self, the_event ): the_keys = the_event.characters() print "Received keys: ", the_keys It was my understanding that this should be sufficient; the new SearchTextField should use the class I defined. But I don't see my diagnostic message when I type. I also tried uncommenting the init function above, also with no effect (i.e. No diagnostic message when the app is starting up). I have it commented out because I assumed the standard init function the class inherits from NSTextField was good enough. On a related note, is there any mechanism to implement categories in pyobjc? I thought this question had been asked before, but I couldn't find it in my archive. steve -- |
From: <bb...@ma...> - 2002-12-17 20:08:14
|
On Tuesday, Dec 17, 2002, at 14:25 US/Eastern, Steven D. Arnold wrote: > Hi, > > I may be having several misconceptions here, but I've looked at several > sources without success, so I thought I'd ask. I want to examine the > keys > that are typed into an NSTextField, so I subclassed NSTextField in IB. > In > IB, I drew an NSTextField and set its custom class to my new class. > Then in > Main.py I defined the class as follows: > > class SearchTextField( AppKit.NSTextField ): > > #def init( self ): > # print "initializing SearchTextField" > # return self > > def keyDown_( self, the_event ): > the_keys = the_event.characters() > print "Received keys: ", the_keys > > It was my understanding that this should be sufficient; the new > SearchTextField should use the class I defined. But I don't see my > diagnostic message when I type. Editing of Text in the AppKit doesn't work quite like that. When a field becomes first responder & takes key, the window creates a field editor that is used to do the actual editing. The field editor more or less "floats above" the field. If you are looking for validation type behavior, you would want to create a custom Formatter. Given that your class is named 'SearchTextField', I'm guess you want to implement something like auto complettion and/or automatching as the user types? If that is the case, then have a look at the NSComboButton (or whatever it is called) as it support auto completion. If that doesn't address your needs, then you'll need to look at the text editing and control editing delegate protocols: @interface NSObject(NSControlSubclassDelegate) // These delegate and notification methods are sent from NSControl subclasses that allow text editing such as NSTextField and NSMatrix. The classes that need to send these have delegates. NSControl does not. - (BOOL)control:(NSControl *)control textShouldBeginEditing:(NSText *)fieldEditor; - (BOOL)control:(NSControl *)control textShouldEndEditing:(NSText *)fieldEditor; - (BOOL)control:(NSControl *)control didFailToFormatString:(NSString *)string errorDescription:(NSString *)error; - (void)control:(NSControl *)control didFailToValidatePartialString:(NSString *)string errorDescription:(NSString *)error; - (BOOL)control:(NSControl *)control isValidObject:(id)obj; - (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector; @end ...and.... @interface NSObject(NSTextDelegate) - (BOOL)textShouldBeginEditing:(NSText *)textObject; /* YES means do it */ - (BOOL)textShouldEndEditing:(NSText *)textObject; /* YES means do it */ - (void)textDidBeginEditing:(NSNotification *)notification; - (void)textDidEndEditing:(NSNotification *)notification; - (void)textDidChange:(NSNotification *)notification; /* Any keyDown or paste which changes the contents causes this */ The second only being applicable to NSText objects, I believe. In generaly, you wouldn't want to override -keyDown: on a NSTextField directly unless you really, really want to customize text entry behavior. > I also tried uncommenting the init function above, also with no effect > (i.e. > No diagnostic message when the app is starting up). I have it > commented out > because I assumed the standard init function the class inherits from > NSTextField was good enough. -init is not the designated initializer for NSView subclasses; generally, -initWithFrame: is. > On a related note, is there any mechanism to implement categories in > pyobjc? > I thought this question had been asked before, but I couldn't find it > in my > archive. Good question: Ronald? b.bum |
From: Ronald O. <ous...@ci...> - 2002-12-18 06:33:31
|
On Tuesday, Dec 17, 2002, at 21:08 Europe/Amsterdam, bb...@ma... wrote: > On Tuesday, Dec 17, 2002, at 14:25 US/Eastern, Steven D. Arnold wrote: > >> On a related note, is there any mechanism to implement categories in >> pyobjc? >> I thought this question had been asked before, but I couldn't find it >> in my >> archive. > > Good question: Ronald? Not really. You can of course implemenent methods from a category for your own subclasses (e.g. like the text* categories Bill mentioned in the previous message), but you cannot add new methods to existing Objective-C classes. You can add new methods to subclasses defined in Python. Some other useful things you cannot do at the moment (using the Internet as my Todo list :-) are: - Adding new methods to subclassses implemented in Python if those methods override/extend existing methods. You can do this, but your method won't be called if someone tries to access this method from Objective-C. - Removing methods from subclasses implemented in Python, if those methods override/extend existing methods. Again you can actually do this, but this doesn't have the right semantics. - Redefine an existing class. This is a feature: Because Objective-C has a flat namespace and python doesn't you might otherwise accidently replace and existing class. It is also not really possible to implement this without memory leaks. All of these would be usefull for incremental development and may be added in some future version (that includes support for categories). Ronald |
From: <bb...@ma...> - 2002-12-18 15:21:44
|
On Wednesday, Dec 18, 2002, at 01:32 US/Eastern, Ronald Oussoren wrote: > On Tuesday, Dec 17, 2002, at 21:08 Europe/Amsterdam, bb...@ma... > wrote: >> On Tuesday, Dec 17, 2002, at 14:25 US/Eastern, Steven D. Arnold wrote: >>> On a related note, is there any mechanism to implement categories in >>> pyobjc? >>> I thought this question had been asked before, but I couldn't find >>> it in my >>> archive. >> >> Good question: Ronald? > > Not really. You can of course implemenent methods from a category for > your own subclasses (e.g. like the text* categories Bill mentioned in > the previous message), but you cannot add new methods to existing > Objective-C classes. You can add new methods to subclasses defined in > Python. Some random notes... (more Internet as a todo list -- also a lot of this can be answered more specifically by looking at the darwin source -- i don't have net connectivity right now, though). How are categories found in bundles currently loaded into the runtime? Specifically, I see a declaration for a category structure in objc.h/objc-load.h/objc-class.h, but the only add methods API is this... OBJC_EXPORT void class_addMethods(Class, struct objc_method_list *); OBJC_EXPORT void class_removeMethods(Class, struct objc_method_list *); ... which is also interesting in that it appears that removing methods is naturally supported by ObjC? Didn't know that. > Some other useful things you cannot do at the moment (using the > Internet as my Todo list :-) are: > - Adding new methods to subclassses implemented in Python if those > methods override/extend existing methods. You can do this, but your > method won't be called if someone tries to access this method from > Objective-C. Is this a matter of invoking class_addMethods() with the appropriate objc_method_list? > - Removing methods from subclasses implemented in Python, if those > methods override/extend existing methods. Again you can actually do > this, but this doesn't have the right semantics. Not sure what you mean. It certainly isn't something that is commonly done in ObjC-- I don't think I have ever seen methods removed from classes in the 15 years I have been doing ObjC-- but the API appears to support this. This assumes that class_removeMethods() is more than a no-op. > - Redefine an existing class. This is a feature: Because Objective-C > has a flat namespace and python doesn't you might otherwise accidently > replace and existing class. It is also not really possible to > implement this without memory leaks. Right. In this case, enforcing the ObjC semantics of once-a-class-always-the-same-class is the way to go. > All of these would be usefull for incremental development and may be > added in some future version (that includes support for categories). It would be useful for more than incremental development. Categories-- as much as they can be horrendously abused-- are a fairly fundamental part of the ObjC development experience. If we can redefine existing methods on the fly-- swizzle methods-- then we can build some incredibly powerful introspection and debugging tools. Namely, we could potentially replace existing ObjC methods in a fashion where the existing functionality remains unchanged but some random method is invoked before and/or after the normal implementation. For debugging, this would be HUGE! b.bum |
From: Peter M. <zig...@po...> - 2002-12-18 15:44:29
|
I don't know if this is what you want but it may help: http://www.cocoadev.com/index.pl?MethodSwizzling Peter On Thursday, December 19, 2002, at 01:41 AM, bb...@ma... wrote: > On Wednesday, Dec 18, 2002, at 01:32 US/Eastern, Ronald Oussoren wrote: >> On Tuesday, Dec 17, 2002, at 21:08 Europe/Amsterdam, bb...@ma... >> wrote: >>> On Tuesday, Dec 17, 2002, at 14:25 US/Eastern, Steven D. Arnold >>> wrote: >>>> On a related note, is there any mechanism to implement categories >>>> in pyobjc? >>>> I thought this question had been asked before, but I couldn't find >>>> it in my >>>> archive. >>> >>> Good question: Ronald? >> >> Not really. You can of course implemenent methods from a category for >> your own subclasses (e.g. like the text* categories Bill mentioned in >> the previous message), but you cannot add new methods to existing >> Objective-C classes. You can add new methods to subclasses defined in >> Python. > > Some random notes... (more Internet as a todo list -- also a lot of > this can be answered more specifically by looking at the darwin source > -- i don't have net connectivity right now, though). > > How are categories found in bundles currently loaded into the runtime? > Specifically, I see a declaration for a category structure in > objc.h/objc-load.h/objc-class.h, but the only add methods API is > this... > > OBJC_EXPORT void class_addMethods(Class, struct objc_method_list *); > OBJC_EXPORT void class_removeMethods(Class, struct objc_method_list *); > > ... which is also interesting in that it appears that removing methods > is naturally supported by ObjC? Didn't know that. > >> Some other useful things you cannot do at the moment (using the >> Internet as my Todo list :-) are: >> - Adding new methods to subclassses implemented in Python if those >> methods override/extend existing methods. You can do this, but your >> method won't be called if someone tries to access this method from >> Objective-C. > > Is this a matter of invoking class_addMethods() with the appropriate > objc_method_list? > >> - Removing methods from subclasses implemented in Python, if those >> methods override/extend existing methods. Again you can actually do >> this, but this doesn't have the right semantics. > > Not sure what you mean. It certainly isn't something that is > commonly done in ObjC-- I don't think I have ever seen methods removed > from classes in the 15 years I have been doing ObjC-- but the API > appears to support this. This assumes that class_removeMethods() is > more than a no-op. > >> - Redefine an existing class. This is a feature: Because Objective-C >> has a flat namespace and python doesn't you might otherwise >> accidently replace and existing class. It is also not really possible >> to implement this without memory leaks. > > Right. In this case, enforcing the ObjC semantics of > once-a-class-always-the-same-class is the way to go. > >> All of these would be usefull for incremental development and may be >> added in some future version (that includes support for categories). > > It would be useful for more than incremental development. > > Categories-- as much as they can be horrendously abused-- are a fairly > fundamental part of the ObjC development experience. > > If we can redefine existing methods on the fly-- swizzle methods-- > then we can build some incredibly powerful introspection and debugging > tools. Namely, we could potentially replace existing ObjC methods in > a fashion where the existing functionality remains unchanged but some > random method is invoked before and/or after the normal > implementation. For debugging, this would be HUGE! > > b.bum > > > > ------------------------------------------------------- > This sf.net email is sponsored by: > With Great Power, Comes Great Responsibility Learn to use your power > at OSDN's High Performance Computing Channel > http://hpc.devchannel.org/ > _______________________________________________ > Pyobjc-dev mailing list > Pyo...@li... > https://lists.sourceforge.net/lists/listinfo/pyobjc-dev > |
From: <bb...@ma...> - 2002-12-18 15:51:27
|
On Wednesday, Dec 18, 2002, at 10:44 US/Eastern, Peter Montagner wrote: > I don't know if this is what you want but it may help: > > http://www.cocoadev.com/index.pl?MethodSwizzling Personally, I'm intimately familiar with method swizzling-- having used it many times to wreak havoc upon an application. :-) His example isn't very good -- he could have used Posing to achieve the same thing. The code is fairly clean, but has some issues. There is no need to swizzle the types-- the types should not change without serious risk of crashing. There is no need to actually declare a method. His alt method could easily have been declared as a C function: void alt_method(T *self, SEL _cmd) { ... } This allows one to define the method without knowing the class declaration in the first place-- which is where swizzling is most useful (i.e. editing classes for which you do not have a declaration that can be used to compile against). b.bum |
From: Peter M. <zig...@po...> - 2002-12-18 16:19:04
|
Yeah, I thought it looked a bit strange. I thought I'd send it to you anyway just in case. Peter On Thursday, December 19, 2002, at 02:51 AM, bb...@ma... wrote: > On Wednesday, Dec 18, 2002, at 10:44 US/Eastern, Peter Montagner wrote: >> I don't know if this is what you want but it may help: >> >> http://www.cocoadev.com/index.pl?MethodSwizzling > > Personally, I'm intimately familiar with method swizzling-- having > used it many times to wreak havoc upon an application. :-) > > His example isn't very good -- he could have used Posing to achieve > the same thing. > > The code is fairly clean, but has some issues. There is no need to > swizzle the types-- the types should not change without serious risk > of crashing. > > There is no need to actually declare a method. His alt method could > easily have been declared as a C function: > > void alt_method(T *self, SEL _cmd) { > ... > } > > This allows one to define the method without knowing the class > declaration in the first place-- which is where swizzling is most > useful (i.e. editing classes for which you do not have a declaration > that can be used to compile against). > > b.bum > > > > ------------------------------------------------------- > This SF.NET email is sponsored by: Order your Holiday Geek Presents > Now! > Green Lasers, Hip Geek T-Shirts, Remote Control Tanks, Caffeinated > Soap, > MP3 Players, XBox Games, Flying Saucers, WebCams, Smart Putty. > T H I N K G E E K . C O M http://www.thinkgeek.com/sf/ > _______________________________________________ > Pyobjc-dev mailing list > Pyo...@li... > https://lists.sourceforge.net/lists/listinfo/pyobjc-dev > |
From: Ronald O. <ous...@ci...> - 2002-12-18 18:48:55
|
On Wednesday, Dec 18, 2002, at 16:44 Europe/Amsterdam, Peter Montagner wrote: > I don't know if this is what you want but it may help: > > http://www.cocoadev.com/index.pl?MethodSwizzling Swapping methods? Hah, we can do better than that :-) Nice to see that it is not only us bridge-builders that poke around in the Objective-C runtime. > Peter > > On Thursday, December 19, 2002, at 01:41 AM, bb...@ma... wrote: > >> On Wednesday, Dec 18, 2002, at 01:32 US/Eastern, Ronald Oussoren >> wrote: >>> On Tuesday, Dec 17, 2002, at 21:08 Europe/Amsterdam, bb...@ma... >>> wrote: >>>> On Tuesday, Dec 17, 2002, at 14:25 US/Eastern, Steven D. Arnold >>>> wrote: >>>>> On a related note, is there any mechanism to implement categories >>>>> in pyobjc? >>>>> I thought this question had been asked before, but I couldn't find >>>>> it in my >>>>> archive. >>>> >>>> Good question: Ronald? >>> >>> Not really. You can of course implemenent methods from a category >>> for your own subclasses (e.g. like the text* categories Bill >>> mentioned in the previous message), but you cannot add new methods >>> to existing Objective-C classes. You can add new methods to >>> subclasses defined in Python. >> >> Some random notes... (more Internet as a todo list -- also a lot of >> this can be answered more specifically by looking at the darwin >> source -- i don't have net connectivity right now, though). >> >> How are categories found in bundles currently loaded into the >> runtime? Specifically, I see a declaration for a category structure >> in objc.h/objc-load.h/objc-class.h, but the only add methods API is >> this... >> >> OBJC_EXPORT void class_addMethods(Class, struct objc_method_list *); >> OBJC_EXPORT void class_removeMethods(Class, struct objc_method_list >> *); >> >> ... which is also interesting in that it appears that removing >> methods is naturally supported by ObjC? Didn't know that. The class_addMethods function is probably what is used to load categories. Categories are not really objects in the runtime. >> >>> Some other useful things you cannot do at the moment (using the >>> Internet as my Todo list :-) are: >>> - Adding new methods to subclassses implemented in Python if those >>> methods override/extend existing methods. You can do this, but your >>> method won't be called if someone tries to access this method from >>> Objective-C. >> >> Is this a matter of invoking class_addMethods() with the appropriate >> objc_method_list? Yes it is and that should be easy enough. With the current codebase this is only doable if you're adding to a python-defined class, when I get around to playing with libffi again we should be able to also add methods to pure Objective-C classes. >> >>> - Removing methods from subclasses implemented in Python, if those >>> methods override/extend existing methods. Again you can actually do >>> this, but this doesn't have the right semantics. >> >> Not sure what you mean. It certainly isn't something that is >> commonly done in ObjC-- I don't think I have ever seen methods >> removed from classes in the 15 years I have been doing ObjC-- but the >> API appears to support this. This assumes that class_removeMethods() >> is more than a no-op. When you're experimenting it might be usefull to just delete an existing method from a Python class (maybe because you just added it and found out this wasn't really what you wanted to do). If you remove a method you want that calls to that selector now go to the superclass. Say you have: class FooObject (NSObject): def hash(self): return 0xff obj = FooObject.alloc().init() After experimenting with this you decide that your implementation isn't very usefull and decide you can to without it: del FooObject.hash You'd expected that obj.hash() ends up calling NSObject.hash instead of causing an error because the Python class no longer implements hash. >> >>> - Redefine an existing class. This is a feature: Because Objective-C >>> has a flat namespace and python doesn't you might otherwise >>> accidently replace and existing class. It is also not really >>> possible to implement this without memory leaks. >> >> Right. In this case, enforcing the ObjC semantics of >> once-a-class-always-the-same-class is the way to go. During incremental development it might be usefull to replace existing classes, but that should not be the default behaviour. Just completely redefining an existing class by adding and removing methods might be just as usefull. In Python 2.3 it will also be possible to dynamicly change the class hierarchy for new-type classes. Supporting this in PyObjC might be neat. >> >>> All of these would be usefull for incremental development and may be >>> added in some future version (that includes support for categories). >> >> It would be useful for more than incremental development. >> >> Categories-- as much as they can be horrendously abused-- are a >> fairly fundamental part of the ObjC development experience. >> >> If we can redefine existing methods on the fly-- swizzle methods-- >> then we can build some incredibly powerful introspection and >> debugging tools. Namely, we could potentially replace existing ObjC >> methods in a fashion where the existing functionality remains >> unchanged but some random method is invoked before and/or after the >> normal implementation. For debugging, this would be HUGE! Doing that is not too hard. If you want to do this with 'pure' Objective-C classes things get a harder, but using libffi (or a simular library) this should still be doable. But you shouldn't trust my judgement on timing: I once said that getting PyObjC in a more usefull shape (w.r.t. using NIB files) should take about 2 weeks :-) Ronald |