-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
Fix for issue: right click menu 6601 #9271
Merged
koppor
merged 10 commits into
JabRef:main
from
tomazari:fix-for-issue-right-click-menu-6601
Dec 5, 2022
Merged
Changes from 9 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
ac985e1
Created MainTableHeaderContextMenu.java. Can right-click to display a…
ethantr bc43dba
Adds functionality, when right-clicking on the header, displays a lis…
ethantr 3f7b9b9
Adds functionality, when right-clicking on the header, displays a lis…
ethantr 41ec51d
Saves MainTable within the MainTableHeaderContextMenu class, and now …
ethantr 6cebeb6
Modified MainTableColumnFactory and added createColumn() function to …
ethantr 1282223
Menu is now sorted from commonly used fields, followed by the remaind…
ethantr 572f92e
Separator item added to distinguish common and current items.
ethantr 3010384
Fixed bug on Linux machines, where user had to hold right click inste…
ethantr 54353df
Switched logic of Menu Item construction (first current columns, now …
ethantr c463838
Fixed checkstyle
calixtus File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
228 changes: 228 additions & 0 deletions
228
src/main/java/org/jabref/gui/maintable/MainTableHeaderContextMenu.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,228 @@ | ||
package org.jabref.gui.maintable; | ||
|
||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
import javafx.collections.ObservableList; | ||
import javafx.scene.control.ContextMenu; | ||
import javafx.scene.control.RadioMenuItem; | ||
import javafx.scene.control.SeparatorMenuItem; | ||
import javafx.scene.control.TableColumn; | ||
import javafx.scene.layout.StackPane; | ||
|
||
import org.jabref.gui.maintable.columns.MainTableColumn; | ||
|
||
public class MainTableHeaderContextMenu extends ContextMenu { | ||
|
||
private static final int OUT_OF_BOUNDS = -1; | ||
MainTable mainTable; | ||
MainTableColumnFactory factory; | ||
|
||
/** | ||
* Constructor for the right click menu | ||
* | ||
*/ | ||
public MainTableHeaderContextMenu(MainTable mainTable, MainTableColumnFactory factory) { | ||
super(); | ||
this.mainTable = mainTable; | ||
this.factory = factory; | ||
constructItems(mainTable); | ||
} | ||
|
||
/** | ||
* Handles showing the menu in the cursors position when right-clicked. | ||
*/ | ||
public void show(boolean show) { | ||
// TODO: 20/10/2022 unknown bug where issue does not show unless parameter is passed through this method. | ||
mainTable.setOnContextMenuRequested(event -> { | ||
// Display the menu if header is clicked, otherwise, remove from display. | ||
if (!(event.getTarget() instanceof StackPane) && show) { | ||
this.show(mainTable, event.getScreenX(), event.getScreenY()); | ||
} else if (this.isShowing()) { | ||
this.hide(); | ||
} | ||
event.consume(); | ||
}); | ||
} | ||
|
||
/** | ||
* Constructs the items for the list and places them in the menu. | ||
*/ | ||
private void constructItems(MainTable mainTable) { | ||
// Reset the right-click menu | ||
this.getItems().clear(); | ||
List<TableColumn<BibEntryTableViewModel, ?>> commonColumns = commonColumns(); | ||
|
||
// Populate the menu with currently used fields | ||
for (TableColumn<BibEntryTableViewModel, ?> column : mainTable.getColumns()) { | ||
// Append only if the column has not already been added (a common column) | ||
RightClickMenuItem itemToAdd = createMenuItem(column, true); | ||
this.getItems().add(itemToAdd); | ||
|
||
// Remove from remaining common columns pool | ||
MainTableColumn searchCol = (MainTableColumn<?>) column; | ||
if (isACommonColumn(searchCol)) { | ||
commonColumns.removeIf(tableCol -> ((MainTableColumn) tableCol).getModel().equals(searchCol.getModel())); | ||
} | ||
} | ||
|
||
SeparatorMenuItem separator = new SeparatorMenuItem(); | ||
this.getItems().add(separator); | ||
|
||
// Append to the menu the current remaining columns in the common columns. | ||
|
||
for (TableColumn<BibEntryTableViewModel, ?> tableColumn : commonColumns) { | ||
RightClickMenuItem itemToAdd = createMenuItem(tableColumn, false); | ||
this.getItems().add(itemToAdd); | ||
} | ||
} | ||
|
||
/** | ||
* Creates an item for the menu constructed with the name/visibility of the table column. | ||
* | ||
*/ | ||
@SuppressWarnings("rawtypes") | ||
private RightClickMenuItem createMenuItem(TableColumn<BibEntryTableViewModel, ?> column, boolean isDisplaying) { | ||
// Gets display name and constructs Radio Menu Item. | ||
MainTableColumn tableColumn = (MainTableColumn) column; | ||
String displayName = tableColumn.getDisplayName(); | ||
return new RightClickMenuItem(displayName, tableColumn, isDisplaying); | ||
} | ||
|
||
/** | ||
* Returns the current position of the inputted column in the table (index). | ||
* | ||
*/ | ||
private int obtainIndexOfColumn(MainTableColumn searchColumn) { | ||
ObservableList<TableColumn<BibEntryTableViewModel, ?>> columns = mainTable.getColumns(); | ||
for (int i = 0; i < columns.size(); i++) { | ||
TableColumn<BibEntryTableViewModel, ?> column = columns.get(i); | ||
MainTableColumnModel model = ((MainTableColumn) column).getModel(); | ||
if (model.equals(searchColumn.getModel())) { | ||
return i; | ||
} | ||
} | ||
return OUT_OF_BOUNDS; | ||
} | ||
|
||
/** | ||
* Adds the column into the MainTable for display. | ||
*/ | ||
@SuppressWarnings("rawtypes") | ||
private void addColumn(MainTableColumn tableColumn, int index) { | ||
if (index <= OUT_OF_BOUNDS || index >= mainTable.getColumns().size()) { | ||
mainTable.getColumns().add(tableColumn); | ||
} else { | ||
mainTable.getColumns().add(index, tableColumn); | ||
} | ||
} | ||
|
||
/** | ||
* Removes the column from the MainTable to remove visibility. | ||
*/ | ||
@SuppressWarnings("rawtypes") | ||
private void removeColumn(MainTableColumn tableColumn) { | ||
mainTable.getColumns().removeIf(tableCol -> ((MainTableColumn) tableCol).getModel().equals(tableColumn.getModel())); | ||
} | ||
|
||
/** | ||
* Checks if a column is one of the commonly used columns. | ||
*/ | ||
private boolean isACommonColumn(MainTableColumn tableColumn) { | ||
return isColumnInList(tableColumn, commonColumns()); | ||
} | ||
|
||
/** | ||
* Determines if a list of TableColumns contains the searched column. | ||
*/ | ||
private boolean isColumnInList(MainTableColumn searchColumn, List<TableColumn<BibEntryTableViewModel, ?>> tableColumns) { | ||
for (TableColumn<BibEntryTableViewModel, ?> column: | ||
tableColumns) { | ||
MainTableColumnModel model = ((MainTableColumn) column).getModel(); | ||
if (model.equals(searchColumn.getModel())) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
|
||
/** | ||
* Creates the list of the "commonly used" columns (currently based on the default preferences). | ||
*/ | ||
private List<TableColumn<BibEntryTableViewModel, ?>> commonColumns() { | ||
// Qualifier strings | ||
String entryTypeQualifier = "entrytype"; | ||
String authorEditQualifier = "author/editor"; | ||
String titleQualifier = "title"; | ||
String yearQualifier = "year"; | ||
String journalBookQualifier = "journal/booktitle"; | ||
String rankQualifier = "ranking"; | ||
String readStatusQualifier = "readstatus"; | ||
String priorityQualifier = "priority"; | ||
|
||
// Create the MainTableColumn Models from qualifiers + types. | ||
List<MainTableColumnModel> commonColumns = new ArrayList<>(); | ||
commonColumns.add(new MainTableColumnModel(MainTableColumnModel.Type.GROUPS)); | ||
commonColumns.add(new MainTableColumnModel(MainTableColumnModel.Type.FILES)); | ||
commonColumns.add(new MainTableColumnModel(MainTableColumnModel.Type.LINKED_IDENTIFIER)); | ||
commonColumns.add(new MainTableColumnModel(MainTableColumnModel.Type.NORMALFIELD, entryTypeQualifier)); | ||
commonColumns.add(new MainTableColumnModel(MainTableColumnModel.Type.NORMALFIELD, authorEditQualifier)); | ||
commonColumns.add(new MainTableColumnModel(MainTableColumnModel.Type.NORMALFIELD, titleQualifier)); | ||
commonColumns.add(new MainTableColumnModel(MainTableColumnModel.Type.NORMALFIELD, yearQualifier)); | ||
commonColumns.add(new MainTableColumnModel(MainTableColumnModel.Type.NORMALFIELD, journalBookQualifier)); | ||
commonColumns.add(new MainTableColumnModel(MainTableColumnModel.Type.SPECIALFIELD, rankQualifier)); | ||
commonColumns.add(new MainTableColumnModel(MainTableColumnModel.Type.SPECIALFIELD, readStatusQualifier)); | ||
commonColumns.add(new MainTableColumnModel(MainTableColumnModel.Type.SPECIALFIELD, priorityQualifier)); | ||
|
||
// Create the Table Columns from the models using factory methods. | ||
List<TableColumn<BibEntryTableViewModel, ?>> commonTableColumns = new ArrayList<>(); | ||
for (MainTableColumnModel columnModel: commonColumns | ||
) { | ||
calixtus marked this conversation as resolved.
Show resolved
Hide resolved
|
||
TableColumn<BibEntryTableViewModel, ?> tableColumn = factory.createColumn(columnModel); | ||
commonTableColumns.add(tableColumn); | ||
} | ||
return commonTableColumns; | ||
} | ||
|
||
/** | ||
* RightClickMenuItem: RadioMenuItem holding position in MainTable and its visibility. | ||
* | ||
*/ | ||
private class RightClickMenuItem extends RadioMenuItem { | ||
private int index; | ||
private boolean visibleInTable; | ||
|
||
RightClickMenuItem(String displayName, MainTableColumn column, boolean isVisible) { | ||
super(displayName); | ||
setVisibleInTable(isVisible); | ||
// Flag item as selected if the item is already in the main table. | ||
this.setSelected(isVisible); | ||
|
||
setIndex(OUT_OF_BOUNDS); | ||
|
||
// Set action to toggle visibility from main table when item is clicked | ||
this.setOnAction(event -> { | ||
if (isVisibleInTable()) { | ||
setIndex(obtainIndexOfColumn(column)); | ||
removeColumn(column); | ||
} else { | ||
addColumn(column, this.index); | ||
setIndex(obtainIndexOfColumn(column)); | ||
} | ||
setVisibleInTable(!this.visibleInTable); | ||
}); | ||
} | ||
|
||
public void setIndex(int index) { | ||
this.index = index; | ||
} | ||
|
||
public void setVisibleInTable(boolean visibleInTable) { | ||
this.visibleInTable = visibleInTable; | ||
} | ||
|
||
public boolean isVisibleInTable() { | ||
return visibleInTable; | ||
} | ||
} | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What happens if the user first removes a column, and then immediately readds it (e.g. he realizes removing it was a mistake). In this case, the column order should be the same as it was before. If I read the code correctly, then currently the column would be appended at the end instead of at its original position.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've made some more changes here with my current commit. When the user goes to click to remove the column, it obtains the current index in the MainTable and stores that number inside the Menu Item. If he wants to immediately place it back, it will be placed back in that exact position using that index.
If the items addjacent to it are removed, it will still be placed in the position of the given index - not sure if that will be confusing to the end user or not, whether it should be done in this way, or another. happy to hear your thoughts.