Qualtagh / JBroTable

JTable with a groupable header
The Unlicense
23 stars 4 forks source link

columnAtPoint() #3

Open ngdenco opened 6 years ago

ngdenco commented 6 years ago

Basically I am trying to find out what column I clicked.

I tried adding a mouse listener to the TableHeader, and use JTable.columnAtPoint() to get the index of the column, but columnAtPoint() does not work seem to work properly with the groups - as far as I can see it returns the lowest grouping correctly, as it appears to be only using the x part of the Point (since it is not an overridden method).

I have added the following which is working: JBroTable.java

    public String getIdentifierAtPoint(Point p) {
        int x = p.x;
        // Below inherited from {@link JTable#columnAtPoint(p)}
        if (!getComponentOrientation().isLeftToRight()) {
            x = getWidth() - x - 1;
        }
        return ((JBroTableColumnModel) getColumnModel()).getIdentifierAtPoint(new Point(x, p.y));
    }

JBroTableColumnModel.java

    public int getColumnIndexAtY(int y) {
        final int MAGIC_HEIGHT_NUMBER = 25;
        y += 1; // Results seem off by 1
        int correctLevel = 0;
        for (int i = 0; i < columns.size() && y > 0; i++) {
            y -= MAGIC_HEIGHT_NUMBER;
            if (y > 0)
                correctLevel++;
        }
        return correctLevel;
    }

    public String getIdentifierAtPoint(Point p) {
        TableColumnModel delegate = getDelegate(getColumnIndexAtY(p.y));
        if (delegate == null)
            return null;
        return (String) delegate.getColumn(delegate.getColumnIndexAtX(p.x)).getIdentifier();
    }

The obvious problem being that MAGIC_HEIGHT_NUMBER is just based off of my own use case. How can we get the row height properly so this returns correctly?

Qualtagh commented 6 years ago

Hi. Thank you for the interest to the project!

One of the lib methods was named incorrectly: getRowAtPoint. I've just committed a renamed version: https://github.com/Qualtagh/JBroTable/commit/b90862e115653ca2a089c215fb0c01a4adf419f3 Now it's rowAtPoint for consistency with columnAtPoint.

So, you can use the following methods: header.columnAtPoint, header.rowAtPoint, columnModel.getColumnAtAbsolutePosition. See sample snippet:

    final JBroTableHeader header = table.getTableHeader();
    header.addMouseListener( new MouseAdapter() {
      @Override
      public void mousePressed(MouseEvent e) {
        Point p = e.getPoint();
        int column = header.columnAtPoint( p );
        int row = header.rowAtPoint( p );
        System.out.println( column + ", " + row );
        System.out.println( header.getColumnModel().getColumnAtAbsolutePosition( column, row ) );
        System.out.println( header.getUI().getColumnAtPoint( p ) );
      }
    });

Also, header.getUI().getColumnAtPoint( p ) combines all these three and returns JBroTableColumn instance positioned at a given point. You can call getIdentifier() on this instance to get ID.

MAGIC_HEIGHT_NUMBER from your code corresponds to header.getRowHeight( level ). Height of each row is variable and can be customized, so a method call is needed.

ngdenco commented 6 years ago

Thanks for the quick reply, that makes sense. getUI().getColumnAtPoint() was what I was looking for, I was not aware of getUI().

I know this isn't the best place but since this is such a quiet issues board I don't want to spam a bunch of issues so I'll just send here. If you'd prefer me add a few issues I could do that. FWIW I was trying to make an "excel document preview" where you could have multiple headers, rearrange data, add columns, etc. At the end I would extract the layout and names that they have selected and output to a file in the same way. I was hoping for an addColumn(int idx) to add inbetween existing columns. Also I have the following issue:

I'm unsure if this is a problem with JTable or the implementation, but it seems if a Drag Column operation is interrupted in some way (such as by JDialog or PopupMenu) and the header doesn't get MouseReleased, things start getting wonky. For example take this code:

        JPopupMenu popupMenu = new JPopupMenu();
        JMenuItem insertLeft = new JMenuItem("Insert Left");
        insertLeft.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                JOptionPane.showInputDialog(null,"test","test",0,null,null,"test");
            }
        });
        popupMenu.add(insertLeft);
        table.getTableHeader().setComponentPopupMenu(popupMenu);

Now if you try to right click to bring up the menu, but accidentally drag a little first instead of a perfect click, the column header hangs in its position. Once this happens sometimes other issues happen (columns show wrong data until clicked, other outdated info).