From: Joe J. <dar...@gm...> - 2006-11-11 07:15:07
|
First, understand that I am a complete newbie to Haskell and HOC so please forgive me if this seems rather basic. I have checked the users archive and was unable to find an answer to this. I am trying to create a custom NSView subclass that, specifically one that overrides drawRect. What I am having a problem with is understanding how to override this function and how to actually get some custom drawing done. Actually, I;m not even sure if my class is being instantiated. I slapped a view into the ExpressionParser window, gave it a custom class with the same name as my class (which would normally be all I would need to do in Cocoa). Here is what I have for my view so far: {-# OPTIONS -fglasgow-exts -fth #-} module EPView where import Cocoa $(declareClass "EPView" "NSView") $(exportClass "EPView" "ev_" [ {- Outlet "expressionEntry" [t| NSTextField () |] , Outlet "evaluation" [t| NSTextField () |] ,-} InstanceMethod 'drawRect ] ) obj #. var = obj # getIVar var ev_drawRect rect self = do putStrLn "Hello World" The putStrLn is there just to get something into that method. I think it is doing something (as I see traces of Hell World in the console log, though not consistent). What I am trying to do is to get something to draw (right now nothing more complex then filling in the rect that is passed in with a blackColor from NSColor. Can anyone provide some pointers (or some code) for this problem? Thanx, joe |
From: David C. <dw...@dw...> - 2006-11-11 12:30:35
Attachments:
View.hs
|
Joe wrote: > I am trying to create a custom NSView subclass that, specifically one > that overrides drawRect. What I am having a problem with is > understanding how to override this function and how to actually get > some custom drawing done. Actually, I;m not even sure if my class is > being instantiated. I slapped a view into the ExpressionParser window, > gave it a custom class with the same name as my class (which would > normally be all I would need to do in Cocoa). Joe, Here's the source for a more complex view that I wrote in Haskell. I can't remember if this compiles/works correctly (it was working at one point, but I started tinkering more), but it should give you something to go on as far as showing how to declare the draw_rect function appropriately. Of particular note, I believe that I had to export the info_drawRect in the $(exportClass) directive in order for the Cocoa system to be able to call the haskellized replacement function. (Also a style note, I was experimenting with some utility functions which use unsafePerformIO; said usage is not recommended... :-D) Additional disclaimer: this code was written about a year ago, so I'm sure there are general improvements which could be made in general. I might make the following changes to your view, just to see if it gives you what you are expecting: --- {-# OPTIONS -fglasgow-exts -fth #-} module EPView where import Cocoa import AppKit.NSView as NSView hiding (print) $(declareClass "EPView" "NSView") $(exportClass "EPView" "ev_" [ InstanceMethod info_drawRect ] ) obj #. var = obj # getIVar var ev_drawRect rect self = do r <- self # NSView.bounds -- proper instance selection. _NSColor # blackColor >>= set -- class selector nsRectFill r return () --- Regards, David Christensen |
From: Joe J. <dar...@gm...> - 2006-11-12 00:39:27
|
Cool, I'll give that a shot. I didn't know about the AppKit import so I'll add that as well. A few questions: 1) (Serious newbie q) What does the # stand for? I haven't seen that yet in what I have read. 2) For the general audience: Is there any way to make the getIvar code (obj #. var = obj # getIVar var) disappear? This appears in every class and seems like something that could be part of a base class, or part of the template definition (note that I have no idea how the template stuff works so...). 3) In general are all of the NSXxxx functions in Cocoa/Foundation/AppKit prefaced with nsXxxx in Haskell? Thanx, joe On 11/11/06, David Christensen <dw...@dw...> wrote: > Joe wrote: > > > I am trying to create a custom NSView subclass that, specifically one > > that overrides drawRect. What I am having a problem with is > > understanding how to override this function and how to actually get > > some custom drawing done. Actually, I;m not even sure if my class is > > being instantiated. I slapped a view into the ExpressionParser window, > > gave it a custom class with the same name as my class (which would > > normally be all I would need to do in Cocoa). > > Joe, > > Here's the source for a more complex view that I wrote in Haskell. I > can't remember if this compiles/works correctly (it was working at > one point, but I started tinkering more), but it should give you > something to go on as far as showing how to declare the draw_rect > function appropriately. > > Of particular note, I believe that I had to export the info_drawRect > in the $(exportClass) directive in order for the Cocoa system to be > able to call the haskellized replacement function. > > (Also a style note, I was experimenting with some utility functions > which use unsafePerformIO; said usage is not recommended... :-D) > Additional disclaimer: this code was written about a year ago, so I'm > sure there are general improvements which could be made in general. > > I might make the following changes to your view, just to see if it > gives you what you are expecting: > > --- > {-# OPTIONS -fglasgow-exts -fth #-} > > module EPView where > > import Cocoa > import AppKit.NSView as NSView hiding (print) > > $(declareClass "EPView" "NSView") > > $(exportClass "EPView" "ev_" > [ > InstanceMethod info_drawRect > ] > ) > > obj #. var = obj # getIVar var > > ev_drawRect rect self = do > r <- self # NSView.bounds -- proper instance selection. > _NSColor # blackColor >>= set -- class selector > nsRectFill r > return () > --- > > Regards, > > David Christensen > > > > |
From: Wolfgang T. <wol...@gm...> - 2006-11-12 21:58:25
|
On 11/11/06, David Christensen <dw...@dw...> wrote: > Of particular note, I believe that I had to export the info_drawRect > in the $(exportClass) directive in order for the Cocoa system to be > able to call the haskellized replacement function. That used to be the case, now you need to use 'drawRect instead of info_drawRect. On 12-Nov-06, at 1:39 AM, Joe Jones wrote: > 1) (Serious newbie q) What does the # stand for? I haven't seen that > yet in what I have read. The # operator is defined by HOC as follows: object # message = message object A selector in HOC is just a function that takes the target object as its *last* argument, and # is just a way to make things look more object-oriented. > 2) For the general audience: Is there any way to make the getIvar code > (obj #. var = obj # getIVar var) disappear? This appears in every > class and seems like something that could be part of a base class, or > part of the template definition (note that I have no idea how the > template stuff works so...). David already answered this; a related question: should this convenience function be included in the HOC library itself? Currently, the "official" HOC way to access instance variables are the getIVar and setIVar functions. The #. operator is shorter, but breaks the symmetry between getIVar and setIVar. > 3) In general are all of the NSXxxx functions in > Cocoa/Foundation/AppKit prefaced with nsXxxx in Haskell? In general, yes. It is always possible that the HOC interface generator failed to parse a function declaration in Apple's header files and therefore left it out altogeter. Should that have happened to a function that you need, give me a shout on the mailing list. On 12-Nov-06, at 3:09 AM, Joe Jones wrote: > OK, I had to remove the NSView. prefix from the bounds call to get > that line to compile. However, the next line tells me that : > > EPView.hs:20:30: Not in scope: `set' Again, David already answered this, but this is what you get when I start writing an answer, then go do something else before finishing it. I would hate to have to throw it away, though: First, as a newcomer to Haskell, make sure you understand about Haskell's module system. Read up on import, import qualified, import qualified A as B etc. There are many methods by the name "set" in Cocoa. Not all of them have the same type signature, so they cannot be represented by just one function definition in HOC. When there are several different selectors by the same name, none of the selectors is exported by the top-level module Cocoa. We have to use the module system to disambiguate between the different "meanings" of the word "set" in Cocoa. For example, Cocoa defines: + (id) set; in class NSSet, and: - (void) set; in class NSColor. So, the word "set" could refer to either of those selectors, with a different type signature. To use them, we have to do something like this: > import Cocoa > import qualified Foundation.NSSet as NSSet > import qualified AppKit.NSColor as NSColor > > ... > > foo myColor = do > mySet <- _NSSet # NSSet.set -- objective C: mySet = [NSSet set]; > myColor # NSColor.set -- objective C: [myColor set]; > return mySet Note that HOC's module names follow Cocoa's header file names, not Cocoa's class names. Cheers, Wolfgang |
From: Joe J. <dar...@gm...> - 2006-11-12 02:09:35
|
OK, I had to remove the NSView. prefix from the bounds call to get that line to compile. However, the next line tells me that : EPView.hs:20:30: Not in scope: `set' And I'm not sure why it's not in scope because set IS a method of AppKit.NSColor. On 11/11/06, David Christensen <dw...@dw...> wrote: > Joe wrote: > > > I am trying to create a custom NSView subclass that, specifically one > > that overrides drawRect. What I am having a problem with is > > understanding how to override this function and how to actually get > > some custom drawing done. Actually, I;m not even sure if my class is > > being instantiated. I slapped a view into the ExpressionParser window, > > gave it a custom class with the same name as my class (which would > > normally be all I would need to do in Cocoa). > > Joe, > > Here's the source for a more complex view that I wrote in Haskell. I > can't remember if this compiles/works correctly (it was working at > one point, but I started tinkering more), but it should give you > something to go on as far as showing how to declare the draw_rect > function appropriately. > > Of particular note, I believe that I had to export the info_drawRect > in the $(exportClass) directive in order for the Cocoa system to be > able to call the haskellized replacement function. > > (Also a style note, I was experimenting with some utility functions > which use unsafePerformIO; said usage is not recommended... :-D) > Additional disclaimer: this code was written about a year ago, so I'm > sure there are general improvements which could be made in general. > > I might make the following changes to your view, just to see if it > gives you what you are expecting: > > --- > {-# OPTIONS -fglasgow-exts -fth #-} > > module EPView where > > import Cocoa > import AppKit.NSView as NSView hiding (print) > > $(declareClass "EPView" "NSView") > > $(exportClass "EPView" "ev_" > [ > InstanceMethod info_drawRect > ] > ) > > obj #. var = obj # getIVar var > > ev_drawRect rect self = do > r <- self # NSView.bounds -- proper instance selection. > _NSColor # blackColor >>= set -- class selector > nsRectFill r > return () > --- > > Regards, > > David Christensen > > > > |
From: David C. <dw...@dw...> - 2006-11-12 18:16:22
|
> 1) (Serious newbie q) What does the # stand for? I haven't seen that > yet in what I have read. # is the "call this selector" function. These are equivalents: // Objective-C [someObject someSelector] // Haskell someObject # someSelector More complicated equivalents: // Objective-C [someObject someSelector:foo withArgs:bar] // Haskell someObject # someSelectorWithArgs foo bar And of course: // Objective-C [[someObject fooSelector] barSelector] // Haskell someObject # fooSelector >>= barSelector >>= serves as the "nested selectors" equivalent; the way that > 2) For the general audience: Is there any way to make the getIvar code > (obj #. var = obj # getIVar var) disappear? This appears in every > class and seems like something that could be part of a base class, or > part of the template definition (note that I have no idea how the > template stuff works so...). If you are not using it, you do not need to define it. It is just a convenience function for accessing the instance variables of an object. > 3) In general are all of the NSXxxx functions in > Cocoa/Foundation/AppKit prefaced with nsXxxx in Haskell? In general, yes. It should be noted that not all functions are imported; it depends on how smart the ifgen script is (which, as I understand it, basically parses the header files for Cocoa and automates the wrapper generation for the ffi in Haskell). I've thought that a tool like unto "perldoc" would be in order for some of the Haskell packages (I also haven't looked to see if Haddock docs are a generation option with hoc; it may be). > Thanx, > joe David Christensen |
From: Joe J. <dar...@gm...> - 2006-11-12 21:32:59
|
Thanks for the info. This was very enlightening and will help a lot. :-) On 11/12/06, David Christensen <dw...@dw...> wrote: > > 1) (Serious newbie q) What does the # stand for? I haven't seen that > > yet in what I have read. > > # is the "call this selector" function. These are equivalents: > > // Objective-C > [someObject someSelector] > > // Haskell > someObject # someSelector > > More complicated equivalents: > > // Objective-C > [someObject someSelector:foo withArgs:bar] > > // Haskell > someObject # someSelectorWithArgs foo bar > > And of course: > > // Objective-C > [[someObject fooSelector] barSelector] > > // Haskell > someObject # fooSelector >>= barSelector > > >>= serves as the "nested selectors" equivalent; the way that > > > 2) For the general audience: Is there any way to make the getIvar code > > (obj #. var = obj # getIVar var) disappear? This appears in every > > class and seems like something that could be part of a base class, or > > part of the template definition (note that I have no idea how the > > template stuff works so...). > > If you are not using it, you do not need to define it. It is just a > convenience function for accessing the instance variables of an object. > > > 3) In general are all of the NSXxxx functions in > > Cocoa/Foundation/AppKit prefaced with nsXxxx in Haskell? > > In general, yes. It should be noted that not all functions are > imported; it depends on how smart the ifgen script is (which, as I > understand it, basically parses the header files for Cocoa and > automates the wrapper generation for the ffi in Haskell). I've > thought that a tool like unto "perldoc" would be in order for some of > the Haskell packages (I also haven't looked to see if Haddock docs > are a generation option with hoc; it may be). > > > Thanx, > > joe > > David Christensen > > > |
From: David C. <dw...@dw...> - 2006-11-12 18:21:42
|
> OK, I had to remove the NSView. prefix from the bounds call to get > that line to compile. Did you include the import statement for NSView explicitly? This may also be due to me forgetting to specify the import as qualified... :-) > However, the next line tells me that : > EPView.hs:20:30: Not in scope: `set' > And I'm not sure why it's not in scope because set IS a method of > AppKit.NSColor. This is an exporting issue due to the fact that there are multiple classes in the Cocoa hierarchy which define a "set" selector. In HOC, all selectors are of the same type; for these duplicate selectors there is no way to distinguish which selector you meant by name and type alone, so by default these are not exported. You can either import the module explicitly or import qualified to provide a different namespace for that selector to live: Either: > import AppKit > import qualified AppKit.NSColor as NSColor > ... > blackColor # NSColor.set Or: > import AppKit > import AppKit.NSColor (set) > ... > blackColor # set ---- David Christensen |
From: Joe J. <dar...@gm...> - 2006-11-12 21:33:40
|
The import worked beautifully. Thanks. Now, on to greater drawing goodness! On 11/12/06, David Christensen <dw...@dw...> wrote: > > OK, I had to remove the NSView. prefix from the bounds call to get > > that line to compile. > > Did you include the import statement for NSView explicitly? This may > also be due to me forgetting to specify the import as qualified... :-) > > > However, the next line tells me that : > > EPView.hs:20:30: Not in scope: `set' > > And I'm not sure why it's not in scope because set IS a method of > > AppKit.NSColor. > > This is an exporting issue due to the fact that there are multiple > classes in the Cocoa hierarchy which define a "set" selector. In > HOC, all selectors are of the same type; for these duplicate > selectors there is no way to distinguish which selector you meant by > name and type alone, so by default these are not exported. > > You can either import the module explicitly or import qualified to > provide a different namespace for that selector to live: > > Either: > > > import AppKit > > import qualified AppKit.NSColor as NSColor > > ... > > blackColor # NSColor.set > > Or: > > > import AppKit > > import AppKit.NSColor (set) > > ... > > blackColor # set > > ---- > David Christensen > |