[Openmcl-devel] NSSlider not responsive

Gary Byers gb at clozure.com
Fri Feb 1 23:53:44 PST 2008



On Sat, 2 Feb 2008, Osei Poku wrote:

> Hi,
>
> I have two objects on my window.
> (a) A custom view that I subclass as Model and successfully draw a
> rectangle inside.
> (b) A slider
>
> The simple idea is that the slider value controls the width of the
> rectangle.  This basically works fine however, I cannot drag the
> slider.  I can only click at the value I want it to be and the
> rectangle adjust accordingly.
>
> This is my code.  When the view redraws, the width of the rectangle
> becomes the VALUE slot inside model.  This value slot is set using the
> #/slide method at the bottom. The window controller class is contains
> the two objects in the window (model<my custom view> and slider ).
>
> (defclass model (ns:ns-view)
>   ((value :initform 10.0D0 :accessor model-value))
>   (:metaclass ns:+ns-object))
>
> (objc:defmethod (#/drawRect: :void) ((self model) (rect :<NSR>ect))
>   (ccl::with-autorelease-pool
>    (let ((r (ns:make-ns-rect 10 10 (model-value self) 100)))
>      (#/setFill (#/blueColor ns:ns-color))
>      (#/setStroke (#/redColor ns:ns-color))
>      (#_NSRectFill r)
>      (#/strokeRect: ns:ns-bezier-path r))))

Two comments:

1) if we haven't exported WITH-AUTORELASE-POOL, we should.
2) Each thread has its own private autorelease pool.  NSApplication's
#/run method runs on the main thread and does something like

  (with-autorelease-pool
     (let* ((event (get-next-event)))
       (#/sendEvent self event))) ; dispatch event to event responders

The method that I'm calling GET-NEXT-EVENT (because I'm too lazy to
look up the real name) obviously waits for low-level events from
the window server and creates NSEvent objects when it gets them;
while waiting, it may also detect cases where windows' views need
updating and call those views' #/updateRect: methods.

It doesn't (likely) hurt anything to have a nested autorelease pool
in your drawRect: method, but any code that runs in the event loop
already has one established in the #/run method.

>
> (defclass window-controller (ns:ns-object)
>   ((model :foreign-type :id :accessor model)
>    (slider :foreign-type :id :accessor slider))
>   (:metaclass ns:+ns-object))

There is a class - NSWindowController - that might be useful
to subclass here.

>
> (objc:defmethod #/slide: ((self window-controller) sender)
>   (let ((val (#/floatValue sender)))
>     (setf (model-value (model self)) val)
>     (#/setNeedsDisplay: (model self) t)))

I don't think that #/slide is sent by anything in Cocoa; sorry if there's
some missing IB stuff that arranges for that to happen.

If not: NSSlider is a subclass of NSControl, and an NSControl can have
an "action" method that's sent to some "target" object whenever it's
changed; there are #/setAction: and #/setTarget: methods that can set
these things up procedurally, and you can also set these things up in
IB.

If you intend for your window-controller class to be a subclass of
NSWindowController, you can arrange (in IB) that an instance of that
class will control the window and also arrange that it be the target
of the slider and receive #/slide from the slider (as the slider's
action message.)  It seems that this is likely to be what you want,
but I'm not really sure how that would happen if WINDOW-CONTROLLER
is just a sunclass of NS:NS-OBJECT (rather than being a subclass
of NS:NS-WINDOW-CONTROLLER).


>
> Additionally, any comments about possible memory leaks and in general
> bad openmcl/cocoa bridge/lisp programming are very welcome.
>
> Thanks,
>
> Osei
> _______________________________________________
> Openmcl-devel mailing list
> Openmcl-devel at clozure.com
> http://clozure.com/mailman/listinfo/openmcl-devel
>
>



More information about the Openmcl-devel mailing list