Selection changed & double clicked

.
A have a table view “names” with 'selection changed" and “double clicked” connected. I need the ‘selection changed’ handler because it should change when the arrow keys are pressed.
The table contains the names of files and folders. If it is a folder, I would like to be able to double click the folder to go one level deeper to fill the table view with the contents of that folder.
After logging the two handlers It appears that in the middle of the ‘selection changed’ handler the ‘double-clicked’ handler becomes active when I double click on an item that is not selected yet. This result is a the window with data of two different items.

I may need some command that says to quit the ‘selection changed’ handler as soon it is double-clicked.

I tried everything, setting flags, even used the idle handler to restore wrong data.
The weird thing of this that it is not stable. Most of the times is goes OK but sometimes the two handlers conflict with each other and this results in a messed up window or an Applescript error.
Once it’s starting to give problems, it continues to make these mistakes even with an older version that worked properly in the past.
I am getting worried if appleScript Studio is reliable enough for long term projects where no one from IT is present.

I wonder if this combination could ever work properly or if I should just accept that this will never work and find an alternative for the Double-click.

So before I capitulate I would like to ask for some advice. I could have overlooked something.
Maybe some knows how to get it stable.

Thanks in advance,

John

:? Me, too. I have the same problem you’re having, but in an outline view… and it is quite frustrating. Applescript studio’s support for multiple table events is choppy at best, and I’m finding myself going to great lengths to solve this issue… only to come up with the ugliest and only marginally reliable solutions. I’m sure you’ve found, that you cannot connect a clicked AND double-clicked handler. In my current plugin project, I can’t even get the outline view to respond to my selection changed handler. I’d be tempted to call this a bug, as there are certainly times when you could want to reliably respond to multiple events without hacking together a workaround solution to a basic problem.

Considering all the testing I’ve done with outline views, I’d probably (however unappealing it may be) tell you to forget about it for now and find another way. You mentioned using a table view… does your interface allow for the use of an outline view instead? This may allow you to bypass modifying your data source on the fly, and help with some of the problems you’re having trying to rebuild and redraw when the table needs to update. Since the data source is built completely ahead of time, you would merely need to expand the items to expose their contents.

That’s about all the advice I have for you. I’ve redesigned my interface about a thousand times trying to come up with a functionality that is both appealling and reliable, because of this exact problem. I had hoped to capture the single click or selection changed event to enable/disable buttons dependent on which item was pressed, but have yet to find a good way that is solid and predictable. Now, in all of the buttons and menus I had hoped to disable/enable automatically depending on the table selection, I instead test for the selection in my clicked/choose menu item code and either carry on if the selection is OK, or return a beep or an error. Kind of ugly and not what I originally intended, but for now it beats trying to rewrite entirely in obj-c. For the project I’m on now… an Xcode plugin… the primary code MUST be in AS, because interacting with Xcode requires the scriptability of xcode, system events, etc… stuff that obj-c can’t handle.

Good luck…
j

Greetings John… and everyone else. 8)

I have come up with what I feel is a very good workaround to the problems with table views/outline views not registering both single and double clicks. I have found a way to use only the clicked handler to implement the functionality of both handlers… using some obj-c calls and some creative applescript.

Basically, when the user clicks the view, the code below will query the window for a reference to the current event. The window pretty much does all of the recording of events, registering them behind the scenes as single or double clicks. You can simply ask the window how many clicks are in the click count, and then respond to the event accordingly.

In this example, I ask the window for a reference to the last event, and set it to a variable. Using that reference to the event, we can use the built-in applescript studio commands (as with a mouse-down or mouse-up handler) to get information about the event. I ask it what the click count is… i.e single or double click… and then do an action accordingly.

I also added my code for displaying a psuedo-context menu for the item clicked. This requires you to set up one or more popup buttons to serve as your ‘context menus’. Make them pull-down buttons, and use the “send to back” option to place them behind the table/outline view. This will make them ‘invisible’ under normal circumstances, but because menu items have one of the highest window levels, they pop “through” the table view and seem to pop up from the clicked item. I test for the control key down using the ASS ‘control key down’ event property, and then use the location property of the event to find out where exactly we clicked. Do a little math to adjust where you want the menu to pop up in relation to your cursor when you click, and then call the appropriate popup button’s “performClick:” method to make it pop up at the cursor. Since it’s a real menu in the window, making it’s connections is easy, and you don’t run into any of the errors you find when trying to use the ‘official’ context menu protocol using connections between an object and a menu.

The only potential downfall to this method I’ve found so far, is that it may take a brief moment for the menu to reposition before it pops up. One major ADVANTAGE to this context menu method is that because you’re clicking the row, not the view itself, the item highlights before the menu pops up, so you can be assured that the menu is popping up for that row, not just at that point in the view. Those of you wishing to provide unique context menu’s for different items or levels in the view will appreciate this. Using the context menu connection in IB between a view and a menu does not implement this properly, where a control click on an item will bring up the menu, but will NOT highlight the item selected… making it impossible to pop up a specific menu customized for THAT ITEM.

on clicked theObject --> Connected to the table/outline view
	set theEvent to call method "currentEvent" of (window of theObject)
	if ((click count of theEvent) as string) = "2" then --> User double-clicked
		display dialog "Do Double-click action here"
	else --> User single-clicked
		if ((control key down of theEvent) as boolean) then --> User wants the context menu
			set {tmpH, tmpV} to location of theEvent
			tell popup button "popup" of (window of theObject)
				set position to {(tmpH - 2), (tmpV + 1)}
				call method "performClick:" of it
			end tell
		else --> Regular single-click
			display dialog "Do Single-click action here"
		end if
	end if
end clicked

It took me a while to come up with this, so I figured others could benefit from knowing about this technique. Have fun… :wink:

j

It works for me and is stabile , Thank you.
I only had to add a try block because of an applescript error.
However, Xcode still logs the error below and then continues:

*** Assertion failure in -[NSEvent clickCount], AppKit.subproj/NSEvent.m:520

This works:

on clicked theObject
	if name of theObject = "names" then
		try
			set theEvent to call method "currentEvent" of (window of theObject)
			if ((click count of theEvent) as string) = "2" then --> User double-clicked
				DOUBLE_CLICKED()
				return
			end if
		end try
		if ((control key down of theEvent) as boolean) then --> User wants more info
			SHOW_WINDOW()
		else --> Regular single-click 
			log "single Click"
		end if
		return
	end if
end clicked

Best Regards

John

This is a great little trick jobu - I never got anywhere with the context menu plugin. The only problem I’ve found is that the popup appears in the wrong place. If the main window is positioned in the bottom left corner of the screen, the popup turns up fine. As soon as the main window is moved away from that corner, the popup appears that distance further away from the point where the cursor is clicked…?

The only other minor niggle I have, is that it doesn’t appear till you release the mouse button. Is there any way to get the handler to be called when the button is pressed?

I don’t know why you’re having problems with the code, I don’t see the behavior you are reporting. Make sure that you use the code exactly as I posted it… or make certain that if you change it that you understand everything you change, especially the lines involving the position and location of the popup. If you can’t figure it out, send me a copy of the project, or at least a copy of the code you’re using, and I can take a look at what may be going wrong.

j

→ jobu10000(a)yahoo.com

This is the code I am using:

		try
			set theEvent to call method "currentEvent" of (window of theObject)
			if ((click count of theEvent) as string) = "2" then --> User double-clicked 
				doubleClick(theObject)
			else if ((control key down of theEvent) as boolean) then --> User wants the context menu 
				set {tmpH, tmpV} to location of theEvent
				tell popup button "context" of (window of theObject)
					set position to {(tmpH - 2), (tmpV + 1)}
					call method "performClick:" of it
				end tell
			end if
		end try

I removed the offset you originally added, to try to convince myself that there was no problem there…

It seems to be something going on in interface builder - I’ve just brought the popup back to the front, and moved it and saved again, and now it pop’s up in nearly the right place, just a bit to high up the screen…

Could it be anything to do with it’s positioning within the window?

It also seems to depend on which item is currently selected…

I don’t see any obvious problems with your code, so it’s likely a problem with some other code or unforeseen interaction we’re not catching.

When you get the event location and then set the position, both are references to locations within the window. So, unless you’re adjusting window size or position in other handlers simultaneously, this should not be the root of the problem.

I assume you mean objects OTHER than the one you’re popping up a context menu for? I tried setting up some other objects in my test window and still didn’t see the problem. It could be a conflict with handlers attached to other objects, but I’d have to see the interface to troubleshoot it.

Could you send me a copy of your project and I’ll take a look? It sounds like a small problem that there should be a simple solution for.

j

I think it’s sort of fixed itself after changing the size springs in interface builder. Very odd.

What I mean by item selected is the item in the popup - I haven’t fully fleshed out the code to handle selection of the items in the menu, so I guess once it’s processed, it would set the selected item in the popup back to the the top one. If the bottom item is selected, when it pops up, the cursor is just below the popup. I hope that makes sense?

If I experience the positioning problem again, I’ll send you a copy if that is OK.

One other thing - is there a way of removing the ‘tick’ next to the selected item? That would make it even more menu like…

:smiley: Ahh… now I get it.

First, add a new menu item to your popup button at the top of it’s current menu items. Then, select your popup button, and check “Pull Down” instead of “Pop Up”. This will make it act like a normal context menu. The extra menu item becomes the title item, and it’s attributes (like title and name) are not really relavent. The pulldown menu style needs an extra item to serve as the menu title, and it always pops down from that top menu item, like a main menu.

Hope that does it.
j

Yup - that sorts it out nicely. Thanks!

Only thing left now is popping up straight away instead of waiting for the button release? :smiley:

Now that’s what I call a clever solution for the single/double click problem in AS , jobu !

Although this thread startet a year ago, it seems that Apple hasn’t fixed the click problem yet.

@ John den Heyer:

You can avoid the *** Assertion failure in -[NSEvent clickCount], AppKit.subproj/NSEvent.m:520 error by preserving the count of click at the beginning of the handler and use it later on in the handler:

on clicked theObject
set theEvent to call method “currentEvent” of (window of theObject)
set clickcount to ((click count of theEvent) as string) --preserve the count of clicks
if name of theObject is “buttonOne” then
–do something
else if name of theObject is “outlineOne” then
if clickcount = “2” then – User double-clicked
–double click routine
else – User single-clicked
–single click routine
end if
end if
end clicked

I gave up on using “selection changed” in combination with “double clicked” because it messed too many things up. So I found this method a great possibility, with just a connected clicked handler. The problem is so far I’m getting NSInternalScript Error (8) when I click on the table.

Just to make sure I’m doing it right:

  1. I have the table on a tab view
  2. only “clicked” is connected to the table view (not the scroll view) in IB (along with column clicked in data view section) and a few others in Table View section (drops/# of rows).
  3. no other explicit connections have been made.
  4. I’m not using the context menu part so I took that out.

I’m wondering whether “window of the object” is appropriate for a table on a tab view, so I tried “tab view of theObject” instead to no avail.

Thanks.

EDIT:

NEVER MIND. Got it to work. I had to move this check all the way to the TOP of the On clicked handler. At the bottom (maybe waiting too long??) it was getting errors but at the top it works.

For the record in case anyone else is having this problem, these are the errors I was getting when it was at the bottom of the on clicked handler:

Still not able to resolve this. I tried breaking it up to see where the problem is, and despite the try blocks below I get a “the variable cclicks is not defined” error dialog in addition to this log.


set these_clicks to call method "currentEvent" of (window of theObject)
                        try
                        log these_clicks
			on error myerr
				log "could not log these_clicks " & myerr
			end try
			
			try
				set cclicks to (click count of these_clicks) as string
			on error myerr
				log "could not get click count " & myerr
			end try
			
			if cclicks = "2" then --> User double-clicked
				--display dialog "Do Double-click action here"
				log "double"
			else --> User single-clicked
				log "single"
			end if

Here’s the log:

this trick apparently no longer works in snow leopard. :frowning:

just get a simple “AppleEvent failed” message.

Not sure whether any call methods are now supported with all the changes, which would be sad.

What now?

the call method command is definitely supported in Snow Leopard, otherwise approximately 60% of all ASS apps would break

well that’s a huge relief… Hoping for some guide to a) making necessary changes to existing projects and b) transitioning to the new system, either written by apple or by some of you all pros around here.

in the meantime expect a lot of posts here from me!

now back to the topic at hand, any way to achieve this double-click test that works in snow leopard?

Still trying on this one.

What I was able to find out so far, to the extent I could get the debugger to work at all with an ASS project and XCode 3.2, was this

This line works:

set these_clicks to call method "currentEvent" of (window of theObject)

It returns a value of “event 1”.

Any attempt to get anything out of “event 1” errors with "AppleEvent failed. Some I tried:


set eventprops to properties of these_clicks
set propertyitems to every item of eventprops
log (these_clicks) as string
set cclicks to (click count of these_clicks) --as string

One thing I did notice is that “click count” when compiled color-codes as a property would, however the actual event property is clickCount. Why is that? however if I tried clickCount instead it color-codes as local variable.

I know, I know, gonna have to learn the new environment eventually but for now I’m just trying to make an existing project work as before.

thanks.

PS, console log: