Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tooltips does not work on list elements #180

Closed
Sorceror opened this issue Sep 17, 2014 · 13 comments
Closed

Tooltips does not work on list elements #180

Sorceror opened this issue Sep 17, 2014 · 13 comments
Assignees
Projects

Comments

@Sorceror
Copy link
Contributor

If custom cell renderer is made for List component and tooltip is registered to cell element, tooltip is not shown (regular java basic setTooltip() method works).
Here is SSCCE

public class ListTooltip {
    public static void main(String[] args) {
        JFrame frame = new JFrame("List tooltip test");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

        WebList list = new WebList(new String[]{ "Editable element 1", "Editable element 2", "Editable element 3", "Editable element 4", "Editable element 5", "Editable element 6" });
        list.setCellRenderer(new CustomCellRenderer<String>());
        frame.getContentPane().add(list);

        frame.pack();
        frame.setVisible(true);
    }

    private static class CustomCellRenderer<E> implements ListCellRenderer<E> {
        public WebListCellRenderer cellRenderer;

        public CustomCellRenderer() {
            cellRenderer = new WebListCellRenderer();
        }

        @Override
        public Component getListCellRendererComponent(JList<? extends E> list, E value, int index, boolean isSelected, boolean cellHasFocus) {
            WebLabel lbl = (WebLabel) cellRenderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
            // this works but looks ugly
            // lbl.setToolTipText("Some tooltip test");

            // this does not work
            TooltipManager.addTooltip(lbl, "Some tooltip test");
            return lbl;
        }
    }
}
@mgarin
Copy link
Owner

mgarin commented Sep 17, 2014

Unfortunately WebLaF custom tooltips doen't work the same way Swing tooltips work - they have different underlying behavior and won't appear for renderer components (doesn't matter whether its tree, table or list renderer).

WebLaF custom tooltips are bound to components and displayed according to their positions. Swing tooltips do the same in most cases but they use a tricky workaround for the renderers case since each renderer is basically just one component updated multiply times in a row to display all cells. Registering WebLaF tooltips like you did in the example in the renderer call will only attach that tooltip to the renderer component but it will never be displayed, because renderer components aren't actually displayed but manually painted onto renderer pane of the list.

With later updates there will be an additional settings for WebList, WebTree and WebTable to provide something like tooltip provider where you will be able to pass your custom tooltip for each cell in a similar way you do in Swing cell renderers.

@mgarin mgarin added this to the Enhancements milestone Sep 17, 2014
@mgarin mgarin self-assigned this Sep 17, 2014
@mgarin
Copy link
Owner

mgarin commented Sep 17, 2014

I might be able to include that improvement into v1.29 update.

@Sorceror
Copy link
Contributor Author

Ok, thanks a lot for clarifying. It's quite important feature for our project, I would appreciate it a lot.

@mgarin mgarin removed this from the Enhancements milestone Sep 30, 2014
@Sorceror Sorceror removed this from the Enhancements milestone Sep 30, 2014
@mgarin mgarin added this to the v1.29 milestone Sep 30, 2014
mgarin added a commit that referenced this issue Oct 30, 2014
…ooltips [ #180 ]

Simplified "setPreferredSize" method is now available for most of Web-components
mgarin added a commit that referenced this issue Mar 15, 2015
#180 ]

Minor improvements for WebTree and WebList rollover behavior
@mgarin mgarin added the solved label Mar 15, 2015
@mgarin
Copy link
Owner

mgarin commented Mar 15, 2015

Complete implementation of this feature for list, tree and table is now available in source code.
A bit later today or tomorrow I will also release updated pre-release artifacts.

All three components (WebList, WebTree and WebTable) are using ToolTipProvider interface to provide customized WebLaF tooltips for their cells. There are also three separate abstract implementations for each of those components to simplify interface usage: ListToolTipProvider, TreeToolTipProvider and TableToolTipProvider.

Here are some test examples for this new feature:

public class WebListTooltip
{
    public static void main ( final String[] args )
    {
        WebLookAndFeel.install ();

        final WebList list = new WebList ( new String[]{ "Item 1", "Item 2", "Item 3", "Item 4" } );
        list.setVisibleRowCount ( 4 );
        list.setToolTipProvider ( new ListToolTipProvider ()
        {
            @Override
            public String getToolTipText ( final WebList component, final Object value, final int index, final int column,
                                           final boolean isSelected )
            {
                return "Cell value: " + value;
            }
        } );

        TestFrame.show ( new WebScrollPane ( list ), 150 );
    }
}
public class WebTreeTooltip
{
    public static void main ( final String[] args )
    {
        WebLookAndFeel.install ();

        final WebTree tree = new WebTree ();
        tree.setToolTipProvider ( new TreeToolTipProvider<UniqueNode> ()
        {
            @Override
            public String getToolTipText ( final WebTree<UniqueNode> tree, final UniqueNode node, final int row, final boolean isSelected )
            {
                return "Node: " + node;
            }
        } );

        TestFrame.show ( new WebScrollPane ( tree ), 150 );
    }
}
public class WebTableTooltip
{
    public static void main ( final String[] args )
    {
        WebLookAndFeel.install ();

        final Object[][] data = { { "1", "2", "3" }, { "d1", "d2", "d3" } };
        final WebTable table = new WebTable ( data, new Object[]{ "c1", "c2", "c3" } );
        table.setToolTipProvider ( new TableToolTipProvider ()
        {
            @Override
            public String getToolTipText ( final WebTable component, final Object value, final int index, final int column,
                                           final boolean isSelected )
            {
                return "Cell value: " + value;
            }
        } );

        TestFrame.show ( new WebScrollPane ( table ), 150 );
    }
}

@mgarin mgarin closed this as completed Mar 15, 2015
@Sorceror
Copy link
Contributor Author

Perfect. Thanks a lot!

@mgarin
Copy link
Owner

mgarin commented Mar 16, 2015

I will also be adding more features and settings for those with time, so feel free to ask for any settings you might want to have there as those implementation are just basic ones and can be easily improved.

@Sorceror
Copy link
Contributor Author

It's way OT, but one thing that bothers me with JList a lot is the way how are list items treated when they're layout in row wrap, e.g.

+---+---+---+
| 1 | 2 | 3 |
+---+---+---+
| 4 | 5 | 6 |
+---+---+---+

I would appreciate if there could be some setting which will allow to set how many list items in one row should be visible (there is only setting for how many rows in one column should be visible) with item size recalculation whenever size of list change.

@mgarin
Copy link
Owner

mgarin commented Mar 16, 2015

Not sure if I understood you right.

Basically this is what happens when you set some >0 value into setVisibleRowCount:
image
As you can see - list forces data to fill exactly 4 rows in any case. Even if there is space for more than 4 rows. Even if there is not enough space for 4 rows. Code of this example:

    public static void main ( final String[] args )
    {
        WebLookAndFeel.install ();
        final String[] d = new String[]{ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15" };
        final WebList list = new WebList ( d );
        list.setVisibleRowCount ( 4 );
        list.setLayoutOrientation ( JList.VERTICAL_WRAP );
        list.setCellRenderer ( new WebListCellRenderer ()
        {
            @Override
            public Component getListCellRendererComponent ( final JList list, final Object value, final int index, final boolean isSelected,
                                                            final boolean cellHasFocus )
            {
                final Component r = super.getListCellRendererComponent ( list, value, index, isSelected, cellHasFocus );
                setMargin ( 15 );
                setHorizontalAlignment ( CENTER );
                return r;
            }
        } );
        TestFrame.show ( list );
    }

So you want exactly the same but for columns?
My point here is that this feature is simply useless as it won't scale if something happens with list size.

But if you really want that feature - you can easily achieve it by using the same setting and updating its value based on list elements amount. Here is how it can be done:

    public static void main ( final String[] args )
    {
        WebLookAndFeel.install ();
        final String[] d = new String[]{ "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15" };
        final WebListModel<String> listModel = new WebListModel<String> ( d );
        final WebList list = new WebList ( listModel );
        list.setLayoutOrientation ( JList.HORIZONTAL_WRAP );
        list.setVisibleRowCount ( 4 );
        list.setCellRenderer ( new WebListCellRenderer ()
        {
            @Override
            public Component getListCellRendererComponent ( final JList list, final Object value, final int index, final boolean isSelected,
                                                            final boolean cellHasFocus )
            {
                final Component r = super.getListCellRendererComponent ( list, value, index, isSelected, cellHasFocus );
                setMargin ( 15 );
                setHorizontalAlignment ( CENTER );
                return r;
            }
        } );
        listModel.addListDataListener ( new ListDataListener ()
        {
            @Override
            public void intervalAdded ( final ListDataEvent e )
            {
                updateColumnsCount ();
            }

            @Override
            public void intervalRemoved ( final ListDataEvent e )
            {
                updateColumnsCount ();
            }

            @Override
            public void contentsChanged ( final ListDataEvent e )
            {
                updateColumnsCount ();
            }

            private void updateColumnsCount ()
            {
                final int desiredColumnsCount = 4;
                final int size = listModel.getSize ();
                list.setVisibleRowCount ( size % desiredColumnsCount == 0 ? size / desiredColumnsCount : size / desiredColumnsCount + 1 );
            }
        } );
        TestFrame.show ( new GroupPanel ( GroupingType.fillFirst, false, list, new WebButton ( "Add element", new ActionListener ()
        {
            @Override
            public void actionPerformed ( final ActionEvent e )
            {
                listModel.add ( "" + ( list.getModelSize () + 1 ) );
            }
        } ) ) );
    }

Just a simple hack :)

In case you want to make list more agile and keep the wrap - you can simply disable row limitation:

list.setVisibleRowCount ( 0 );

@mgarin
Copy link
Owner

mgarin commented Mar 16, 2015

Btw, here are results of the hack above:
image image

@mgarin
Copy link
Owner

mgarin commented Mar 16, 2015

Recalculation of the items size is an issue there indeed and can't be solved that easily.
I would actually love to have it as well in some cases.
I have added a separate enhancement issue for this stuff: #241

@Sorceror
Copy link
Contributor Author

That hack with addListDataListener() is great, that will help me a lot!

For the resize problem approach I use changeListener invocation item size re-calculation on scrollpane viewport which wraps all my lists. Whenever stateChange is called, I check if viewport size has changed and if does, I calculate new size of item in list and force it by setFixedCellWidth method. Sometimes it happens, that item size is some particular value, which force scrollbar to be visible, it cause that size of viewport is changed again and new item size has to be calculated. That cause scrollbar to not be visible again. It cause another item size recalculation and it goes on and on a on :-/.
So I hope if the resizing could be done from inside the component this problem might disappear.

@mgarin
Copy link
Owner

mgarin commented Mar 16, 2015

Will see what can be done with the next update :)

@mgarin
Copy link
Owner

mgarin commented Mar 17, 2015

Updated pre-release artifacts are now available here:
http://weblookandfeel.com/downloads/prerelease/

@mgarin mgarin added this to Completed in v1.2.9 Nov 27, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
v1.2.9
Completed
Development

No branches or pull requests

2 participants