How to use a triple click with a ruby tool

The tool class has methods for onLButtonDown and onLButtonDoubleClick. But how can we implement a triple click?

My approach is to count the number of times the onLButtonDoubleClick method has been called. After the first call of onLButtonDown, the second call of onLButtonDoubleClick will be triple-click.

You must be using a Mac. When trapping the mouse-clicks in either Ruby (developing a SketchUp extension) or in C/C++ (developing a Windows app in MS Visual Studio), the sequence I always see when triple-clicking is:

β€˜onLButtonDown’, β€˜onLButtonDoubleClick’, β€˜onLButtonDown’

I never see a second β€˜Double-Click’ notification without a β€˜Button-Down’ (i.e. Single-click) first.

1 Like

For these sequences, do you do a kind of timing in which timeframe these events should happen to recognize this has a triple click instead of a normal or double click?

The following snippet will trap single, double and triple clicks on a Windows machine:

			def onLButtonDown(flags, x, y, view)
				if @doubleclick_filter
					puts "Saw Triple-Click:  #{@click_filter}  #{@doubleclick_filter}"
					@doubleclick_filter = false
				else
					puts "Saw First-Click:  #{@click_filter}  #{@doubleclick_filter}"
					@click_filter = true
				end
			end


			def onLButtonDoubleClick(flags, x, y, view)
				if @click_filter
					puts "Saw Double-Click:  #{@click_filter}  #{@doubleclick_filter}"
					@doubleclick_filter = true
					@click_filter = false
				else
					@doubleclick_filter = false
				end
			end			


			def onMouseMove(flags, x, y, view)
				@click_filter = false
				@doubleclick_filter = false
			end			

The booleans are reset in β€˜onMouseMove’ so that a long delay between the second and third clicks (or a double click and then a legitimate single click) is not always seen as a triple click.

1 Like

I have just checked on win, it is true!

So you can confirm that the Mac behaves differently? If so, this issue must be handled correctly to have an extension fully Mac AND Windows compatible…

As I recall, on Mac there were issues with onKeyDown (often would not fire) and we had to use onKeyUp instead to be cross platform. So platform tests should be done to see if the mouse button callbacks have any differences.

Also check for open issues in the API Issue Tracker.

and if so, logic to handle the functions β€˜onLButtonDown’ and β€˜onLButtonDoubleClick’ must be made dependant upon β€˜Sketchup.platform’…

My point was that if code instead uses onLButtonUp and it may be cross-platform without the need for the platform conditional.

But taking your point a bit further, Ruby allows conditional method definition. Ie …

class MyNamepsace::MyTool

  if Sketchup.platform == :platform_win
    def onLButtonDown(flags, x, y, view)
      # Windows specific implementation code
    end
    # ... other Win specific callback definitions ...
  else
    def onLButtonDown(flags, x, y, view)
      # Mac specific implementation code
    end
    # ... other Mac specific callback definitions ...
  end

end

This defines faster code as the methods do not need to constantly check what platform they are running on. The decision is done once at load time.

1 Like

Exactly. I currently define:

		@@gWindows = Sketchup.platform == :platform_win

then use β€˜@@gWindows’ in functions which are machine dependent. For example:

				if @@gWindows
					text << "  Ctrl - toggle Continuous"
				else
					text << "  Option - toggle Continuous"
				end

Based on how I (on Windows) have to setup to trap a triple-click, and how β€˜voquochai’ explains how he does it, is sounds like there is a difference in how they are implemented. The technique I use is consistent with what you experience when using the β€˜Mouse Properties’ dialog in Windows:
Triple-Clicking

So it appears I may need to duplicate my code in β€˜onKeyDown’ into β€˜onKeyUp’ as well, then block one or the other using my β€˜@@gWindows’ variable…

Good tip, thank you :slight_smile:

1 Like

NO, not exactly. You are doing the platform test within methods which is not necessary.
Secondly, you are using a module variable when a local constant would be better.

It is more efficient to define platform constants at the top of your module or tool class.
Also your tool class can set the text as local constants also in the same conditional if block, but in a subconditionals.

  if not defined? WIN
    WIN = Sketchup.platform == :platform_win
    MAC = !WIN
    SUFFIX = "  #{WIN ? "Ctrl" : "Option"} - toggle Continuous"
  end

No point in defining a variable (or calling Sketchup::platform all the time) as these things will not change once loaded on a given platform.

No, the first definition of β€˜@@gWindows’ is done in my class definition (highest level), not in any function call. This is why they were two separate β€˜Ruby’ code entries, and why I defined it as a class variable.

But of course you could not see my source file, and I was not clear about this. My bad.

1 Like

Oh good, but still, using a variable reference for something that will not change during runtime is really conventionally the role of a constant reference.

1 Like

Understood. Thanks :+1:

1 Like

Yep! On mac will be β€˜ onLButtonDown ’, β€˜ onLButtonDoubleClick ’ , β€˜ onLButtonDoubleClick ’ , β€˜ onLButtonDoubleClick ’…

Thank you for confirming. :+1:
This will definitely require machine dependent branching to trap a β€˜triple-click’…

1 Like