• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag
 

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: How to imitiate mouse move programmatically? [NSApp postEvent:atStart:] does not work...
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: How to imitiate mouse move programmatically? [NSApp postEvent:atStart:] does not work...


  • Subject: Re: How to imitiate mouse move programmatically? [NSApp postEvent:atStart:] does not work...
  • From: Graham Cox <email@hidden>
  • Date: Wed, 4 Nov 2009 00:09:49 +1100


On 03/11/2009, at 11:15 PM, Oleg Krupnov wrote:

Maybe I'm not speaking clearly, but that's exactly what I'm trying to
do -- use a mouse event to cause a state change, but in this case the
mouse event would be fake. Mouse position is in no way part of the
view's state. I just want that at particular moment the view's state
becomes synchronized with the current mouse position, as if the mouse
did move.

But why? State is an independent variable. It is coupled to the mouse location in your case, but it's independent nevertheless. If you like, state is the part of the view's output (because it causes the visual appearance to change) whereas events are always input. Don't conflate them - views are designed to keep the input (events) and outputs (drawing) handled in two completely independent phases.


There are multiple items in the view, and the hovered one of the items
should be highlighted. When the mouse event arrives, the view performs
hit testing of its items and determines which of the items is hovered.
If I make a setState method as you suggest, I would have to specify
which item to highlight. This would break the view's encapsulation,
because I would have to perform item hit testing externally.

I don't really follow this. At some point any hit testing does have to be done externally, if you have multiple objects, either by you or by AppKit. Doing it yourself is easy, and I strongly recommend that approach as follows:


1. main view gets the localised mouse location.
2. it iterates over all of its sub-objects representing the items and asks each one to test itself against the mouse position which is passed to it.
3. The first item that returns yes is sent the appropriate -setState: to highlight it (and the main view also keeps track of this one as "the selected item").
4. the -setState: method invalidates the drawing area covered by the object.
5. drawing deals with the appearance change.


This is the classic, no-nonsense, normal everyday approach. Tracking to get each individual object to handle its own mouse tracking independently is not only going to be hard to get right, it's likely to have poor performance as well. All you're really doing is shunting the mouse position detection and hit-testing off onto multiple NSTrackingAreas - it still has to be done and it's unlikely to be faster than a simple approach that can take advantage of knowledge of how your sub-objects work.

(Side discussion: In fact, an improved design than the above where state is linked to the concept of selection is to maintain a separate list of the selected items. When the items are drawn, pass them the selected state on the fly by testing if they belong to the selection set or not. This avoids the maintenance of two state variables that need to be synchronised - one to mean 'this object is part of my selection' and another one within the object that indicates 'highlighted'. If you don't have to keep those two in synch they can never get out of synch, and management of the selection becomes independent of the objects that are selected themselves, which shouldn't really care, other than to draw differently accordingly).

Again, I could implement a custom "refresh" method in each view, which
would query the current mouse position and call the mouse moved event
handler, but in addition to the extra code, before calling this method
I would have to hit test the window to determine which view is
currently hovered, i.e. basically repeat what NSApp and NSWindow
normally do when dispatching mouse events. That's why I thought
simulating a mouse move event could be justified.

This sounds backwards. Instead, just pass the mouse position down to the sub-object as needed, usually to perform a hit-test. (It's good for each object to implement its own hit-test method because you can customise it for different classes if necessary). The main view that contains all these other objects should act as a controller, responding to mouse events and asking the relevant objects to change state.


If you find this repugnant for some reason (not sure why, it's what nearly all drawing apps actually do), another option is to make each sub-object a NSView subclass in its own right, so that the normal hit- testing and mouse dispatch is done for you. But this approach *is* discouraged by the docs for performance reasons - it's better to keep your sub-objects lightweight and let the main view do the work of grovelling over them. But even NSView has a -hitTest: method.

Also, beside this discussion of design, I'd appreciate to find out why
postEvent actually did not work, just to improve my understanding of
Cocoa, even if I decide against using this approach.

Well, I have successfully posted mouse-up events in the (rare) situation I described, but I filled in all the parameters, so maybe Dave's suggestion is right - you have to make sure the event is well- formed. Many of its parameters are esoteric, but can be obtained from the objects around you - the window, current graphics context, and so on.


If I haven't made my point yet however, don't pursue this - just do it correctlyâ„¢ instead. The above approach is what I use in DrawKit and it has never let me down ;-)

--Graham





_______________________________________________

Cocoa-dev mailing list (email@hidden)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden


  • Follow-Ups:
    • Re: How to imitiate mouse move programmatically? [NSApp postEvent:atStart:] does not work...
      • From: Oleg Krupnov <email@hidden>
References: 
 >How to imitiate mouse move programmatically? [NSApp postEvent:atStart:] does not work... (From: Oleg Krupnov <email@hidden>)
 >Re: How to imitiate mouse move programmatically? [NSApp postEvent:atStart:] does not work... (From: Graham Cox <email@hidden>)
 >Re: How to imitiate mouse move programmatically? [NSApp postEvent:atStart:] does not work... (From: Oleg Krupnov <email@hidden>)
 >Re: How to imitiate mouse move programmatically? [NSApp postEvent:atStart:] does not work... (From: Graham Cox <email@hidden>)
 >Re: How to imitiate mouse move programmatically? [NSApp postEvent:atStart:] does not work... (From: Oleg Krupnov <email@hidden>)
 >Re: How to imitiate mouse move programmatically? [NSApp postEvent:atStart:] does not work... (From: Graham Cox <email@hidden>)
 >Re: How to imitiate mouse move programmatically? [NSApp postEvent:atStart:] does not work... (From: Oleg Krupnov <email@hidden>)

  • Prev by Date: Re: How to imitiate mouse move programmatically? [NSApp postEvent:atStart:] does not work...
  • Next by Date: Re: Overriding -[UIViewController loadView], and loading from a nib
  • Previous by thread: Re: How to imitiate mouse move programmatically? [NSApp postEvent:atStart:] does not work...
  • Next by thread: Re: How to imitiate mouse move programmatically? [NSApp postEvent:atStart:] does not work...
  • Index(es):
    • Date
    • Thread