3

I add some CTabItems with Images to a CTabFolder:

CTabFolder tabFolder = new CTabFolder(someSection, SWT.BORDER);
ImageDescriptor deleteImageDesc = sharedImages.getImageDescriptor(ISharedImages.IMG_ETOOL_DELETE);
Image deleteImage = deleteImageDesc.createImage();
CTabItem tabItem = new CTabItem(tabFolder, SWT.NONE);
tabItem.setImage(deleteImage);
// add more tabs...

tabItems

Then I want to create a ToolTip which appears if user moves mouse over a deleteImage.

ToolTip deleteToolTip = new ToolTip(getShell(), SWT.BALOON);
deleteToolTip.setMessage("Delete");
tabFolder.addMouseTrackListener(new MouseTrackAdapter()
{
    @Override
    public void mouseHover(MouseEvent e)
    {
        toolTip.setLocation(tabFolder.toDisplay(e.x, e.y));
        toolTip.setVisible(doesAnyOfTabImagesContainPoint(mousePosition));
    }
});

To implement method doesAnyOfTabImagesContainPoint I need to determine the position of every deleteImage. Since CTabItem isn't a Control I cannot use method toDisplay. I try to solve this by manually determining the position of deleteImage relative to tabFolder. It would help because the mouse position held by MouseEvent is also relative to tabFolder.

private boolean doesAnyOfTabImagesContainPoint(Point p)
{
    for (CTabItem tabItem : tabFolder.getItems())
    {
        Image i = tabItem.getImage();
        Rectangle tabItemBounds = tabItem.getBounds();
        Rectangle imageBounds = i.getBounds();
        imageBounds.x += tabItemBounds.x;
        imageBounds.y += tabItemBounds.y;
        if (imageBounds.contains(p))
            return true;
    }
    return false;
}

The requirement for working this properly is that Rectangle returned by i.getBounds() has correct location relative to tabItem. However it returns (0, 0, 16, 16) which cannot be right.

A dirty way to fix this would be to just add some constants:

imageBounds.x += bsTabBounds.x + 4;
imageBounds.y += bsTabBounds.y + 3;

But I am wondering if there's better way. I'm trying to investigate how CTabFolder positions images of the tabs but without success by now. Any help would be appreciated. Thanks in advance.

edit: for testing purposes here's the extracted image which i get from ISharedImages modified to see its border: delete.png

Danny Lo
  • 1,553
  • 4
  • 26
  • 48
  • Any feedback to my answer? – Baz May 09 '15 at 09:05
  • 1
    I am glad you are interested if your solution worked for me. Sorry for the delay, I've been on vacation this week. I tested your code at home and it looks like the problem doesn't appear for the simplified example. But I need to test this in real application to make the final decision if the problem is really solved. I'll do it on Monday as soon as I get to work. – Danny Lo May 09 '15 at 13:23

1 Answers1

1

Give the code below a shot. It's based on my answer here.

public static void main(String[] args)
{
    Display display = Display.getDefault();
    final Shell shell = new Shell(display);
    shell.setLayout(new FillLayout());

    final TabFolder folder = new TabFolder(shell, SWT.NONE);

    TabItem item = new TabItem(folder, SWT.NONE);
    item.setImage(display.getSystemImage(SWT.ICON_ERROR));
    item.setText("Text");

    folder.addListener(SWT.MouseMove, event -> {
        TabFolder curFolder = (TabFolder) event.widget;
        Point eventLocation = new Point(event.x, event.y);
        TabItem theItem = curFolder.getItem(eventLocation);

        if (theItem == null)
            return;

        Image image = theItem.getImage();

        if (eventLocation.x >= curFolder.getClientArea().x + theItem.getBounds().x + image.getBounds().x
                && eventLocation.x <= curFolder.getClientArea().x + theItem.getBounds().x + image.getBounds().x + image.getBounds().width
                && eventLocation.y >= theItem.getBounds().y + image.getBounds().y
                && eventLocation.y <= theItem.getBounds().y + image.getBounds().y + image.getBounds().height)
        {
            System.out.println("show tooltip");
        }
    });


    shell.pack();
    shell.open();
    while (!shell.isDisposed())
    {
        if (!display.readAndDispatch())
            display.sleep();
    }
}

I've tested it on Windows 7 and it seems to be working fine.

Community
  • 1
  • 1
Baz
  • 36,440
  • 11
  • 68
  • 94
  • 1
    I adjusted my application to use your piece of code, but unfortunately it doesn't work. I extracted the used image from org.eclilpse.ui and modified it to see borders. Here's a screenshot where you see that the tooltip appears where it shouldn't: http://i.imgur.com/ZT46ZHh.png – Danny Lo May 11 '15 at 08:35
  • @DannyLo That's interesting. Unfortunately, I can't really see why this is happening. – Baz May 11 '15 at 08:37
  • I just edited my question to provide that image with border, maybe you could test it on your system. – Danny Lo May 11 '15 at 08:38
  • 1
    @DannyLo I gave it a try and I just can't find a way to retrieve those magical 2 pixels that are missing. My guess is that it's the space to the "left" of the actual folder, but I'm not sure. – Baz May 11 '15 at 08:53
  • More curiosity: inside of my application the gap to the left is only 1 magical pixel. Vertical gap is the same: 4 pixels. – Danny Lo May 11 '15 at 09:10
  • Nope, the Vertical gap is also different: 3 and 4 pixels. – Danny Lo May 11 '15 at 09:16
  • @DannyLo I'm afraid you'll have to hard code those pixels in this case. Can't think of a cleaner solution I'm afraid. – Baz May 11 '15 at 09:20
  • I added the amount of "magical" pixels to `image.getBounds().x` and `y` and was able to observe correct behavior of the tooltip on the left and top borders. But then this happens: http://i.imgur.com/pxNWNLc.png 1 pixel too much on the bottom and right which forces me to adjust `width` and `height` of the `Rectangle` as well. – Danny Lo May 11 '15 at 09:21
  • @DannyLo Or replace the `<=`s with `<`s. – Baz May 11 '15 at 09:26
  • I afraid that this could look messy on MacOS or *nix. Need to test it. If the magical pixels are system-dependent, then I lose. – Danny Lo May 11 '15 at 09:30
  • @DannyLo Well, you can determine which OS you are running your code on and then set the pixels. – Baz May 11 '15 at 09:31
  • If you do this with `folder.setTabPosition(SWT.BOTTOM)` then the behavior is messed up again. I need this because I have second `tabFolder` with that style in my application which needs tooltips as well. – Danny Lo May 11 '15 at 10:11
  • @DannyLo I'm really sorry, but I can't seem to be able to help you with this. – Baz May 11 '15 at 10:14
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/77510/discussion-between-danny-lo-and-baz). – Danny Lo May 11 '15 at 11:13