Command's tooltip and status bar text are not displaying

Hello there, i’m trying to implement a toolbar with multiple commands for my extension. I’ve tried using this simple example from the API documentation to create and add my commands to the toolbar:

toolbar = UI::Toolbar.new "Test"
cmd = UI::Command.new("Test") {
 UI.messagebox "Hello World"
}
cmd.small_icon = "ToolPencilSmall.png"
cmd.large_icon = "ToolPencilLarge.png"
cmd.tooltip = "Test Toolbars"
cmd.status_bar_text = "Testing the toolbars class"
cmd.menu_text = "Test"
toolbar = toolbar.add_item cmd
toolbar.show

What happens is that the toolbar and the commands are created but, neither the tooltip or the status bar text are displaying. I’ve tried getting this to work, and searched the forums for a similar problem, but did not find any. I was hoping someone could help me solve this problem.

This is what your code produces on Windows 10 & SketchUp 2018 …

image

This is how it works since the tooltips were changed for SketchUp 2013 and higher. With that release there were new icons and the tooltip boxes became this 2 line style where the bold title is the “tooltip()” and the description is the “status_bar_text()”.

Once the UI::Command object has been added to a toolbar object, the “tooltip()” property can no longer be changed. (Prior to this in v8 and earlier we could change the tooltip “on the fly”, but no longer from v2013 and higher.)

The “status_bar_text()” property still CAN be changed at any time to reflect a tool state, etc., if you wish.

Obviously the status_bar_text() also appears on the status bar, when the mouse is hovering over the toolbar button, AND when the tool is activated. So if the button activates a Ruby Tool, and you change the status text as the tool state changes, then do not forget to reset the status_bar_text() to the default inside the tool’s deactivate() callback method.


You are on Mac so I’ll see what Steve says about the differences in the interface. @slbaumgartner ?

Thanks for the reply Dan. It’s really weird, i’ve tried running my code snippet on the Ruby editor extension, and it worked. The code i was running was basically the same thing, but the command created a input box.
I started from scratch and got it running. I really don’t understand what was going on yet, now i have basically the same code as before, but with the tooltip working.

screenshot

Was your code running within a module namespace ?
When you paste code into the console it usually evaluates within Object, which means all references become global (since everything is a subclass of Object.)


Since you’ll be using multiple command objects, I’d suggest using either constant or module var references.

module Author
  module SomePlugin

   # At top of 1st file to load ...
    @@loaded = false unless defined?(@@loaded)

    # A bunch of code ... perhaps several files of code ...

    # At bottom of last file to load ...
    unless @@loaded

      CMD ||= {} # hash to hold command object references

      # Each command ...
      CMD[:some_tool]= UI::Command.new("Tool Name") {
        # Always implement command code in a separate method
        # so you can redfine the method as you tweak, reload and test
        tool_name_command_method()
      }.set_validation_proc {
        # Optional validation proc if you want button to gray or show checked state
        some_tool_boolean_method?() ? MF_ENABLED : MF_GRAYED
      }
      CMD[:some_tool].instance_eval %{
        self.small_icon = "ToolPencilSmall.png"
        self.large_icon = "ToolPencilLarge.png"
        self.tooltip = "Test Toolbars"
        self.status_bar_text = "Testing the toolbars class"
      }

      # ... more commands ...

      # Load your plugin submenu using the command objects here ...

      TOOLBAR ||= UI::Toolbar.new("SomeTools")

      CMD.each do |key,cmd|
        TOOLBAR.add_item( cmd )
      end
      TOOLBAR.show if TOOLBAR.get_last_state != TB_HIDDEN

      @@loaded = true
    end

  end
end

You might see quickly that a factory method for defining commands might make code a bit cleaner.

Hi Dan, thanks for the tip! Yeah i was running my code inside a module function, like this:

module Company
  module Plugin
    def self.create_commands
       #code that was creating the toolbar and the commands 
    end
    
    unless file_loaded?(__FILE__)
      self.create_commands
      file_loaded(__FILE__)
    end
  end
end

I gotta say, i’m having some difficulties organizing my plugin code, not only i’m new to Ruby, but i found the tutorials/examples on extension development to simple. Is there some resource on extension development that you can recommend me?
P.S. Again, thank you very much for all the help you are giving me.

I’ve not had time to look carefully at the specific issues in this code, and I’ll avoid questions about coding style, structure, factory methods, etc. But here is some info based on my understanding and what works in my extensions:

I always use full paths to the icon and cursor files. With bare filenames as in the example I am not sure where Ruby will look for the files. The result is possibly different on the Ruby Console than when an extension is loading as SketchUp starts. The strange icon with the sick face is the “file not found” one that SketchUp substitutes when it can’t find the file. I set up module-level constants for where the extension is loading (based on FILE in my base loader) and do a File.join to assemble paths to specific files as needed. That makes it easily relocatable.

As you know, SketchUp 2016 added support for scalable icons and cursors (pdf on Mac, svg on Windows). I haven’t checked whether png images will even work on these versions, but certainly the icons and cursor won’t scale properly on your display. I think they just get embedded as tiny things in a larger box?

I’ve had no problems with Command#tooltip working. I’ve never used Command#status_bar_text (don’t really see the need for it anyway) so I can’t comment on how it works on Mac.

Yes this wasn’t really about the icon. It is about the toolitip, so I didn’t bother having any icons load.

Re, the icon. Absolute paths are always good. At one time there was a “path rule”,… perhaps the paths were relative to the ruby file being loaded, but I never remember (and always have the feeling that it differed by platform,) … so like you, I started just using absolute paths.

Did you ever get this working completely on macOS? I’m also finding that it only partially works. I can’t get both cmd.tooltip and cmd.status_bar_text to show up—only one or the other. cmd.status_bar_text only displays if there is no cmd.tooltip; otherwise, only cmd.tooltip displays.

On Windows, both show up just fine, with the horizontal line separator between them. But on macOS, I don’t see any toolbar items for any extension that seem to show more than one field.

(Testing this in SU 2016-SU 2018)

I just re-read this topic based on seeing @fleawig’s post and it struck me that maybe in the older posts there is confusion about what cmd.status_bar_text is supposed to do. The Ruby API docs say

The text that will appear on the status bar when the cursor is over the command’s menu item.

They do not say it will appear when you hover over a toolbar item (they say that for the tooltip). None of the code samples earlier involve a menu item, only toolbars. I don’t think I’ve ever seen a status text appear when hovering over a menu item, so it may be that this feature is broken. But I’ve also never seen a second line appear in the tooltip on MacOS X. Based on the API docs I’d think it was a bug if it did.

My post is based on different behavior between macOS and Windows, in a plugin that uses the same code and values for both platforms. It’s just like the difference you see between @DanRathbun’s result (An icon floated left, a title, a horizontal rule, and then a text field) and @mateusgondimlima’s result (just the tooltip string, with nothing else.) You’ll notice they’re quite different.

Now that I look at this in more detail, though, it looks as if, on macOS, the status_bar_text attribute only works for tools that can be selected, not for toolbar items that trigger an alert or open a dialog. It seems that perhaps this was just implemented differently between the two platforms.

…and it does appear that on macOS, the status_bar_text attribute does nothing at all for the example case given in the API. On Windows it works perfectly fine—the example string appears in the status bar when the cursor is over the toolbar button—but on macOS, nothing appears in the status bar.

And, in our plugin, hovering over the command’s menu item in macOS doesn’t produce any result in the status bar either.

Yup. Always provide full path.

Are you referring this these examples?

What kind of examples would you like to see? How to manage your extension’s files,modules,classes as it grows?

Anything related to UI might yield different results between the platforms. It could be differences in the platform itself of inconsistencies. I’m not that familiar with how the statusbar update code works to say anything of the top of my head on this one.
But I do know that validation procs in Mac’s toolbars isn’t working properly. (I’ve ended up disabling them in my own extensions - leaving the validation procs in for Windows only.) We have an open issue on that one. (Though if I recall it was a non-trivial issue to address.)

Tooltips and icons should work on both platform though. If anyone sees anything different I’d encourage to post a complete example that reproduce. (Would be good to post that in the issue tracker actually: GitHub - SketchUp/api-issue-tracker: Public issue tracker for the SketchUp and LayOut's APIs)

if you want the second line on a mac you need to add a \n in the. tooltip or in the .status text…

but it will not show in the document Status Bar…

cmd.tooltip = "Test Toolbars \n Testing the toolbars class"

john

Thanks for the replies. The behavior is definitely quite different between the two platforms, so I’ll open an issue about this.

That’s a good idea. I’ll have to make a platform-aware solution, so that it puts in the newline on macOS but not Windows.

Another note on this—I found the same thing, that it only half-works. I attempted to add a UI.refresh call to my proc, since this did produce the desired behavior when I did it manually, but this UI call makes SketchUp immediately crash.

Here’s the code I tried:

cmd_browse.set_validation_proc do
    if Core.asset_dialog && Core.asset_dialog.visible?
        MF_DISABLED
        # This causes an immediate crash
        UI.refresh_toolbars
    else
        MF_ENABLED
    end
end
  1. The reason for the crash is that this in a infinite loop. The UI refresh routine will call the validation procs on all the toolbar buttons, and yours starts another UI refresh in the midst of one in progress.

  2. Every validation proc should return one of the MF constant integer values. Your example may not as the UI.refresh_toolbars() method returns nil, not one of the integers that the OS is expecting. … that is if it doesn’t crash.

3 Likes

That’s helpful to know, thanks @DanRathbun!

1 Like

Even worse, it’s a recursive infinite loop which will eventually (in this case quickly) use up all stack space and cause a crash.

1 Like

Yea, likely a stack overflow or some kind of memory fault. But not being familiar with how Mac’s work I decided not to say specifics.