mbari-org / vars-annotation

Video Annotation Application for MBARI's Media Management (M3) software stack
https://docs.mbari.org/vars-annotation/
Apache License 2.0
16 stars 6 forks source link

Save the state of the hidden/shown columns in the new table view. #156

Open hohonuuli opened 1 year ago

hohonuuli commented 1 year ago

The swing table used in VARS doesn't not have built-in support for notifications or the state of the shown/hidden columns. Ideally we want to be able to save those to the users local preferences. When VARS restarts, it should read the preferences and show/hide the columns from their last session. (Request by @SarahRDBingo). This affects version 1.5.0

hohonuuli commented 1 year ago

I'm saving/loading the visible state of the columns. But when VARS is restarted when some columns are hidden, it breaks the table sorting. Swing is a little wierd, setting a column as visible = false actually removes it from the table's column model. I'm seeing this exception:

2023-02-17 00:43:25 [AWT-EventQueue-0                ] ERROR org.mbari.vars.ui.App                               Exception in thread [AWT-EventQueue-0]
java.lang.IndexOutOfBoundsException: column beyond range of TableModel
    at vars.annotation.merged.module@1.5.0/org.jdesktop.swingx.sort.DefaultSortController.checkColumn(DefaultSortController.java:177)
    at vars.annotation.merged.module@1.5.0/org.jdesktop.swingx.sort.DefaultSortController.toggleSortOrder(DefaultSortController.java:122)
    at java.desktop/javax.swing.plaf.basic.BasicTableHeaderUI$MouseInputHandler.mouseClicked(BasicTableHeaderUI.java:130)
    at java.desktop/java.awt.AWTEventMulticaster.mouseClicked(AWTEventMulticaster.java:278)
    at java.desktop/java.awt.AWTEventMulticaster.mouseClicked(AWTEventMulticaster.java:277)
    at java.desktop/java.awt.Component.processMouseEvent(Component.java:6623)
    at java.desktop/javax.swing.JComponent.processMouseEvent(JComponent.java:3398)
    at java.desktop/java.awt.Component.processEvent(Component.java:6385)
    at java.desktop/java.awt.Container.processEvent(Container.java:2266)
    at java.desktop/java.awt.Component.dispatchEventImpl(Component.java:4995)
    at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2324)
    at java.desktop/java.awt.Component.dispatchEvent(Component.java:4827)
    at java.desktop/java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4948)
    at java.desktop/java.awt.LightweightDispatcher.processMouseEvent(Container.java:4584)
    at java.desktop/java.awt.LightweightDispatcher.dispatchEvent(Container.java:4516)
    at java.desktop/java.awt.Container.dispatchEventImpl(Container.java:2310)
    at java.desktop/java.awt.Window.dispatchEventImpl(Window.java:2780)
    at java.desktop/java.awt.Component.dispatchEvent(Component.java:4827)
    at java.desktop/java.awt.EventQueue.dispatchEventImpl(EventQueue.java:775)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:720)
    at java.desktop/java.awt.EventQueue$4.run(EventQueue.java:714)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:97)
    at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:747)
    at java.desktop/java.awt.EventQueue$5.run(EventQueue.java:745)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
    at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
    at java.desktop/java.awt.EventQueue.dispatchEvent(EventQueue.java:744)
    at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:203)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:124)
    at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:113)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:109)
    at java.desktop/java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
    at java.desktop/java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
hohonuuli commented 1 year ago

Ack, this is a bug with the table sorting. When any column is hidden, all columns to the right of the hidden column will throw the above exception when sorting is tried.

hohonuuli commented 1 year ago

I tried switching to different sort controllers using things like table.setRowSorter(new TableSortController<>) but these have all thrown exceptions that prevent either the data or the whole table from being rendered 😡

hohonuuli commented 1 year ago

My latest workaround is to move the columns that are most likely to be hidden to the left. That way if they are hidden they won't mess with the sorting of the other columns. This is a total HACK.

MeaganPutts commented 1 year ago

@hohonuuli I have been using the 1.5.1 M1 release of VARS on my brand new iMac (got it Friday) and I haven't noticed it changing any records like before. I like the timeline feature and how it shows the density of records, making me feel accomplished as I work through really populated areas of the video.

However, it is extremely laggy when creating or changing records and sometimes does not make the changes that I have entered in the editing pane. Also, it is exhibiting odd behavior; often when I try to move backward through the video or skip to timecode the video will freeze for some time and when I click on a record with an image the image will not show. If I wait and/or click around on other records, things will be start working again.

hohonuuli commented 1 year ago

@MeaganPutts Thanks for the feedback! I'm tracking your lag in issue #165