Skip to content

Fix #15397 invisible delete area for internal CSL styles#15399

Open
Francis-Lee-210 wants to merge 6 commits intoJabRef:mainfrom
Francis-Lee-210:fix-15397-internal-csl-delete
Open

Fix #15397 invisible delete area for internal CSL styles#15399
Francis-Lee-210 wants to merge 6 commits intoJabRef:mainfrom
Francis-Lee-210:fix-15397-internal-csl-delete

Conversation

@Francis-Lee-210
Copy link
Copy Markdown

Related issues and pull requests

Closes #15397

PR Description

This fixes the invisible delete area shown for internal CSL styles in the OpenOffice/LibreOffice style selection dialog.

The delete cell is now explicitly cleared for empty rows and internal styles, so internal CSL styles no longer show a visible or invisible delete area. External CSL styles still show the delete button and remain deletable.

Steps to test

  1. Open JabRef and connect to an OpenOffice/LibreOffice document.
  2. Open the OpenOffice/LibreOffice panel and click Select style.
  3. In CSL Styles, verify that internal CSL styles no longer show a visible or invisible delete area.
  4. Import an external .csl style.
  5. Verify that the external style still shows the delete button and can still be deleted.

Comparison screenshots

  • Before:
Before
  • After - Internal CSL styles:
After-Internal
  • After - External CSL styles:
After-External

Library screenshot:

截屏2026-03-24 20 02 08

Checklist

  • I own the copyright of the code submitted and I license it under the MIT license
  • I manually tested my changes in running JabRef (always required)
  • [/] I added JUnit tests for changes (if applicable)
  • I added screenshots in the PR description (if change is visible to the user)
  • I added a screenshot in the PR description showing a library with a single entry with me as author and as title the issue number
  • I described the change in CHANGELOG.md in a way that can be understood by the average user (if change is visible to the user)
  • [/] I checked the user documentation for up to dateness and submitted a pull request to our user documentation repository

@github-actions
Copy link
Copy Markdown
Contributor

Hey @Francis-Lee-210! 👋

Thank you for contributing to JabRef!

We have automated checks in place, based on which you will soon get feedback if any of them are failing. We also use Qodo for review assistance. It will update your pull request description with a review help and offer suggestions to improve the pull request.

After all automated checks pass, a maintainer will also review your contribution. Once that happens, you can go through their comments in the "Files changed" tab and act on them, or reply to the conversation if you have further inputs. You can read about the whole pull request process in our contribution guide.

Please ensure that your pull request is in line with our AI Usage Policy and make necessary disclosures.

@qodo-free-for-open-source-projects
Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Fix invisible delete area for internal CSL styles

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Fix invisible delete button area for internal CSL styles
• Replace ValueTableCellFactory with custom TableCell implementation
• Explicitly clear cell content for internal and empty rows
• Preserve delete functionality for external CSL styles
Diagram
flowchart LR
  A["CSL Styles Table"] -->|"Custom TableCell"| B["Check if Internal Style"]
  B -->|"Internal or Empty"| C["Clear Cell Content"]
  B -->|"External Style"| D["Show Delete Button"]
  D --> E["User Can Delete"]
  C --> F["No Delete Area"]
Loading

Grey Divider

File Changes

1. jabgui/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogView.java 🐞 Bug fix +21/-10

Replace factory with custom TableCell for delete button

• Added imports for TableCell and Tooltip classes
• Replaced ValueTableCellFactory with custom TableCell implementation
• Implemented updateItem() method to conditionally render delete button
• Delete button only appears for external CSL styles, hidden for internal styles
• Explicitly clears cell graphics, text, tooltip and mouse handlers for empty/internal rows

jabgui/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogView.java


2. CHANGELOG.md 📝 Documentation +1/-0

Document CSL delete button fix

• Added entry documenting the fix for invisible delete button area
• References issue #15397 and clarifies external styles remain deletable

CHANGELOG.md


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects
Copy link
Copy Markdown
Contributor

qodo-free-for-open-source-projects bot commented Mar 24, 2026

Code Review by Qodo

🐞 Bugs (2) 📘 Rule violations (0) 📎 Requirement gaps (0) 📐 Spec deviations (0)

Grey Divider


Remediation recommended

1. Right-click triggers delete 🐞 Bug ✓ Correctness
Description
The CSL delete cell binds deletion to any mouse click (including secondary/middle clicks), which can
pop a delete confirmation unexpectedly and potentially delete a style on right-click. This is
particularly risky now that the handler deletes the row’s style directly rather than the
currently-selected style.
Code

jabgui/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogView.java[R160-164]

+                CSLStyleSelectViewModel style = getTableRow().getItem();
+                setGraphic(IconTheme.JabRefIcons.DELETE_ENTRY.getGraphicNode());
+                setTooltip(new Tooltip(Localization.lang("Remove style")));
+                setOnMouseClicked(_ -> viewModel.deleteCslStyle(style.getLayout().citationStyle()));
+            }
Evidence
The new cell factory assigns setOnMouseClicked without checking event.getButton(), so any mouse
click on the cell will call deleteCslStyle(...) and show a confirmation dialog. The new handler
targets getTableRow().getItem() (row-under-pointer), whereas the previous code used the selection
model; this makes accidental non-primary clicks act on the clicked row instead of a selected one.

jabgui/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogView.java[141-165]
jabgui/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogViewModel.java[237-243]
jabgui/src/main/java/org/jabref/gui/integrity/IntegrityCheckDialog.java[124-133]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The delete icon cell triggers deletion for any mouse button, which can open delete confirmation on right-click/middle-click.

### Issue context
The delete cell is implemented as a custom `TableCell` and uses `setOnMouseClicked` with an ignored event parameter.

### Fix focus areas
- Ensure delete triggers only on primary mouse button.
- (Optional) Trigger only on single-click to avoid odd multi-click behavior.

- jabgui/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogView.java[160-164]

### Suggested change (sketch)
Change the handler to accept the event and guard it:
```java
setOnMouseClicked(event -> {
   if (event.getButton() != MouseButton.PRIMARY) {
       return;
   }
   // optionally: if (event.getClickCount() != 1) return;
   viewModel.deleteCslStyle(style.getLayout().citationStyle());
   event.consume();
});
```

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Delete click bubbles to row 🐞 Bug ✓ Correctness
Description
The delete cell’s click handler does not consume the mouse event, so a double-click on the delete
column can also trigger the row’s double-click handler (which closes the dialog). This can cause
unexpected dialog closing while the user is interacting with the delete control.
Code

jabgui/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogView.java[R163-168]

+                setOnMouseClicked(_ -> viewModel.deleteCslStyle(style.getLayout().citationStyle()));
+            }
+        });

        new ViewModelTableRowFactory<CSLStyleSelectViewModel>()
                .withOnMouseClickedEvent((item, event) -> {
Evidence
The delete cell installs an onMouseClicked handler but never consumes the event; the row factory
separately listens for clicks and closes the dialog on clickCount == 2. Without consuming in the
cell, the click can propagate/bubble to the row handler.

jabgui/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogView.java[163-176]
jabgui/src/main/java/org/jabref/gui/util/ViewModelTableRowFactory.java[137-143]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Click events on the delete cell can propagate to the table row handler. A double-click on the delete area can therefore trigger the row’s double-click behavior (select + close dialog).

### Issue context
The CSL styles table uses `ViewModelTableRowFactory.withOnMouseClickedEvent` to close the dialog on double-click, and the delete cell currently does not consume events.

### Fix focus areas
- Consume the mouse event in the delete cell handler to prevent bubbling to the row handler.
- Optionally ignore double-clicks for delete.

- jabgui/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogView.java[163-175]
- jabgui/src/main/java/org/jabref/gui/util/ViewModelTableRowFactory.java[137-143]

### Suggested change (sketch)
```java
setOnMouseClicked(event -> {
   if (event.getButton() != MouseButton.PRIMARY || event.getClickCount() != 1) {
       return;
   }
   viewModel.deleteCslStyle(style.getLayout().citationStyle());
   event.consume();
});
```

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@github-actions github-actions bot added good first issue An issue intended for project-newcomers. Varies in difficulty. component: libre-office status: changes-required Pull requests that are not yet complete labels Mar 24, 2026
@testlens-app

This comment has been minimized.

@testlens-app

This comment has been minimized.

@github-actions github-actions bot added status: no-bot-comments and removed status: changes-required Pull requests that are not yet complete labels Mar 24, 2026
Comment on lines +146 to +165
cslDeleteColumn.setCellFactory(_ -> new TableCell<>() {
@Override
protected void updateItem(Boolean internalStyle, boolean empty) {
super.updateItem(internalStyle, empty);

setText(null);
setGraphic(null);
setTooltip(null);
setOnMouseClicked(null);

if (empty || (internalStyle == null) || (getTableRow() == null) || (getTableRow().getItem() == null) || internalStyle) {
return;
}

new ValueTableCellFactory<CSLStyleSelectViewModel, Boolean>()
.withGraphic(internalStyle -> internalStyle ? null : IconTheme.JabRefIcons.DELETE_ENTRY.getGraphicNode())
.withOnMouseClickedEvent(_ -> _ -> {
CSLStyleSelectViewModel selectedStyle = cslStylesTable.getSelectionModel().getSelectedItem();
if (selectedStyle != null) {
viewModel.deleteCslStyle(selectedStyle.getLayout().citationStyle());
}
})
.withTooltip(_ -> Localization.lang("Remove style"))
.install(cslDeleteColumn);
CSLStyleSelectViewModel style = getTableRow().getItem();
setGraphic(IconTheme.JabRefIcons.DELETE_ENTRY.getGraphicNode());
setTooltip(new Tooltip(Localization.lang("Remove style")));
setOnMouseClicked(_ -> viewModel.deleteCslStyle(style.getLayout().citationStyle()));
}
});
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use our ValueTableCellFactory.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated the implementation to use ValueTableCellFactory, re-tested it locally, and pushed the change.

I also noticed that the Validate requirement coverage check keeps getting cancelled/timing out. Do I need to do anything on my side for that, or is it a CI/workflow issue?

@github-actions github-actions bot added status: changes-required Pull requests that are not yet complete and removed status: no-bot-comments labels Mar 24, 2026
@calixtus calixtus marked this pull request as draft March 25, 2026 07:27
@testlens-app

This comment has been minimized.

@github-actions github-actions bot added status: no-bot-comments status: changes-required Pull requests that are not yet complete and removed status: changes-required Pull requests that are not yet complete status: no-bot-comments labels Mar 25, 2026
@github-actions
Copy link
Copy Markdown
Contributor

Your pull request conflicts with the target branch.

Please merge with your code. For a step-by-step guide to resolve merge conflicts, see https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/addressing-merge-conflicts/resolving-a-merge-conflict-using-the-command-line.

@testlens-app

This comment has been minimized.

@github-actions github-actions bot added status: no-bot-comments and removed status: changes-required Pull requests that are not yet complete labels Mar 27, 2026
@testlens-app
Copy link
Copy Markdown

testlens-app bot commented Mar 27, 2026

✅ All tests passed ✅

🏷️ Commit: e5b1a59
▶️ Tests: 10203 executed
⚪️ Checks: 51/51 completed


Learn more about TestLens at testlens.app.

@subhramit subhramit marked this pull request as ready for review March 27, 2026 20:21
@qodo-free-for-open-source-projects
Copy link
Copy Markdown
Contributor

Review Summary by Qodo

Fix invisible delete area for internal CSL styles

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Fix invisible delete button area for internal CSL styles
• Prevent delete action execution on internal styles
• Maintain delete functionality for external CSL styles
• Update ValueTableCellFactory usage with correct parameter handling
Diagram
flowchart LR
  A["CSL Style Delete Cell"] --> B{"Is Internal Style?"}
  B -->|Yes| C["Hide Delete Button"]
  B -->|Yes| D["Disable Delete Action"]
  B -->|No| E["Show Delete Button"]
  B -->|No| F["Enable Delete Action"]
  C --> G["No Delete Area Visible"]
  D --> G
  E --> H["Delete Button Visible"]
  F --> H
Loading

Grey Divider

File Changes

1. jabgui/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogView.java 🐞 Bug fix +8/-6

Fix CSL delete button visibility and action handling

• Updated ValueTableCellFactory lambda expressions to accept both style and internal flag
 parameters
• Modified graphic factory to conditionally hide delete icon for internal styles
• Enhanced mouse click handler to return empty action for internal styles, preventing deletion
• Updated tooltip factory to hide tooltip text for internal styles

jabgui/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogView.java


2. CHANGELOG.md 📝 Documentation +1/-0

Document internal CSL delete button fix

• Added entry documenting the fix for invisible delete button area on internal CSL styles
• Clarified that external CSL styles remain deletable
• Referenced issue #15397

CHANGELOG.md


Grey Divider

Qodo Logo

@qodo-free-for-open-source-projects
Copy link
Copy Markdown
Contributor

qodo-free-for-open-source-projects bot commented Mar 27, 2026

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (0) 📎 Requirement gaps (0) 📐 Spec deviations (0)

Grey Divider


Remediation recommended

1. Stale tooltip not cleared 🐞 Bug ✓ Correctness ⭐ New
Description
Internal CSL style rows can still display the "Remove style" tooltip after scrolling because the
cell factory only sets a tooltip when the tooltip text is non-blank and never clears a previously
set tooltip when the new tooltip text is null/blank. This undermines the PR’s goal of removing the
(visible/invisible) delete affordance for internal styles.
Code

jabgui/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogView.java[155]

+                .withTooltip((_, internalStyle) -> internalStyle ? null : Localization.lang("Remove style"))
Evidence
The PR makes internal styles return a null tooltip; however, ValueTableCellFactory.updateItem() only
calls setTooltip(...) when the tooltip text is not blank and does not call setTooltip(null)
otherwise. Since JavaFX virtualizes/reuses TableCell instances, a cell previously used for an
external style (tooltip set) can be reused for an internal style and keep the old tooltip.

jabgui/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogView.java[145-156]
jabgui/src/main/java/org/jabref/gui/util/ValueTableCellFactory.java[108-138]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`StyleSelectDialogView` now returns `null` tooltip text for internal CSL styles, but `ValueTableCellFactory` does not clear an existing tooltip when the tooltip text is null/blank. Because JavaFX reuses cells, internal rows can incorrectly retain and show the previous row’s tooltip (e.g., “Remove style”).

### Issue Context
This PR intentionally removes delete affordances for internal CSL styles by setting tooltip to `null`.

### Fix Focus Areas
- jabgui/src/main/java/org/jabref/gui/util/ValueTableCellFactory.java[108-138]
- jabgui/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogView.java[145-156]

### Suggested fix
In `ValueTableCellFactory.updateItem`, when `toTooltip != null`, explicitly clear the tooltip when the computed tooltip text is blank/null, e.g.:
- compute `tooltipText`
- if blank: `setTooltip(null)`
- else: set the newly created Tooltip

This makes the new `internalStyle ? null : ...` behavior in `StyleSelectDialogView` work reliably under cell reuse.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Right-click triggers delete 🐞 Bug ✓ Correctness
Description
The CSL delete cell binds deletion to any mouse click (including secondary/middle clicks), which can
pop a delete confirmation unexpectedly and potentially delete a style on right-click. This is
particularly risky now that the handler deletes the row’s style directly rather than the
currently-selected style.
Code

jabgui/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogView.java[R160-164]

+                CSLStyleSelectViewModel style = getTableRow().getItem();
+                setGraphic(IconTheme.JabRefIcons.DELETE_ENTRY.getGraphicNode());
+                setTooltip(new Tooltip(Localization.lang("Remove style")));
+                setOnMouseClicked(_ -> viewModel.deleteCslStyle(style.getLayout().citationStyle()));
+            }
Evidence
The new cell factory assigns setOnMouseClicked without checking event.getButton(), so any mouse
click on the cell will call deleteCslStyle(...) and show a confirmation dialog. The new handler
targets getTableRow().getItem() (row-under-pointer), whereas the previous code used the selection
model; this makes accidental non-primary clicks act on the clicked row instead of a selected one.

jabgui/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogView.java[141-165]
jabgui/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogViewModel.java[237-243]
jabgui/src/main/java/org/jabref/gui/integrity/IntegrityCheckDialog.java[124-133]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The delete icon cell triggers deletion for any mouse button, which can open delete confirmation on right-click/middle-click.
### Issue context
The delete cell is implemented as a custom `TableCell` and uses `setOnMouseClicked` with an ignored event parameter.
### Fix focus areas
- Ensure delete triggers only on primary mouse button.
- (Optional) Trigger only on single-click to avoid odd multi-click behavior.
- jabgui/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogView.java[160-164]
### Suggested change (sketch)
Change the handler to accept the event and guard it:

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Delete click bubbles to row 🐞 Bug ✓ Correctness
Description
The delete cell’s click handler does not consume the mouse event, so a double-click on the delete
column can also trigger the row’s double-click handler (which closes the dialog). This can cause
unexpected dialog closing while the user is interacting with the delete control.
Code

jabgui/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogView.java[R163-168]

+                setOnMouseClicked(_ -> viewModel.deleteCslStyle(style.getLayout().citationStyle()));
+            }
+        });

       new ViewModelTableRowFactory<CSLStyleSelectViewModel>()
               .withOnMouseClickedEvent((item, event) -> {
Evidence
The delete cell installs an onMouseClicked handler but never consumes the event; the row factory
separately listens for clicks and closes the dialog on clickCount == 2. Without consuming in the
cell, the click can propagate/bubble to the row handler.

jabgui/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogView.java[163-176]
jabgui/src/main/java/org/jabref/gui/util/ViewModelTableRowFactory.java[137-143]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Click events on the delete cell can propagate to the table row handler. A double-click on the delete area can therefore trigger the row’s double-click behavior (select + close dialog).
### Issue context
The CSL styles table uses `ViewModelTableRowFactory.withOnMouseClickedEvent` to close the dialog on double-click, and the delete cell currently does not consume events.
### Fix focus areas
- Consume the mouse event in the delete cell handler to prevent bubbling to the row handler.
- Optionally ignore double-clicks for delete.
- jabgui/src/main/java/org/jabref/gui/openoffice/StyleSelectDialogView.java[163-175]
- jabgui/src/main/java/org/jabref/gui/util/ViewModelTableRowFactory.java[137-143]
### Suggested change (sketch)

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@subhramit
Copy link
Copy Markdown
Member

@Francis-Lee-210 please update the screenshots after your most recent change

@pluto-han
Copy link
Copy Markdown
Contributor

Just tried out this PR, found one problem:

  1. Add .csl file
  2. "Remove style" does not remove the file from the UI immediately, unless users reopen the dialog
PR.test.mp4

@pluto-han
Copy link
Copy Markdown
Contributor

Just tried out this PR, found one problem:

But the problem seems not related to this change.

@subhramit
Copy link
Copy Markdown
Member

Just tried out this PR, found one problem:

  1. Add .csl file
  2. "Remove style" does not remove the file from the UI immediately, unless users reopen the dialog

Is the problem there on the main branch as well? Or just this PR?

@pluto-han
Copy link
Copy Markdown
Contributor

pluto-han commented Mar 28, 2026

Is the problem there on the main branch as well? Or just this PR?

It exists in the main branch as well. An error shows up when removing the "removed" csl file again.
image

@subhramit
Copy link
Copy Markdown
Member

Is the problem there on the main branch as well? Or just this PR?

It exists in the main branch as well. An error shows up when removing the "removed" csl file again.

Good finding - create an issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component: libre-office first contrib good first issue An issue intended for project-newcomers. Varies in difficulty. status: no-bot-comments

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Remove invisible delete button for internal CSL styles

4 participants