Skip to content

Commit 003587c

Browse files
CSL4LibreOffice - A [GSoC '24] (#11477)
* Finish CSL Style selection Tab * Preview Section (To Diagnose) * Rename preview boxes * Fixed CSL Style Preview as per suggestions * Resize CSL Prveiw box height, Comply with Checkstyle * IntelliJ refactoring & Add back filter functionality * Draft Commit: Establish Basic Framework * Draft Commit: Establish Basic Framework * Connect UI with CSL Logic (Phase 1), Improve HTML Formatter (Phase 2), Cleanup * Add logging of Cited Style Name for Testing * Add preliminary test support for in-text citations * Refine Implementation: Refactoring [1] * Improve Logging * Major CSL Formatting improvements * Fix test, OpenRewrite * Remove in-text citation test * Fix architecture test: Move business logic from model to logic directory * Fix order of imports * Extend CSL Citation feature to manually selected library entries * Don't assume Databasecontext * Major bug fix: Using Filter Seelcted entries from start (Use name instead of index, basis for preferences) * Implement extensible selection of Style categories, Reconnect JStyle pipeline * Proper notification of selected style * Separation of bibliographic and in-text citation handling * Log instead of throwing exceptions while citing * Handle the case of margins (gap between citation number and text) * Refactoring, Localization * Changelog * RewriteRun * Add ADR for Style Type Selection Problem * Remove unused localization * Fix markdown error * Remove comment * remove csl submodules * Resolve submodules * gitmodules * Recover gitmodules * recover gitmodules * Recovery attempt * fix submodules * Add double click to select CSL style functionality * Add double-click to select CSL style feature * Adjust changelog * Optimize transformHtml * Add parameterized logging * Remove thrown exception, replace by logger * Add a return statement (enforced) * Remove unused fields * openRewrite * Remove boilerplate comment --------- Co-authored-by: Siedlerchr <siedlerkiller@gmail.com>
1 parent ee46fe7 commit 003587c

17 files changed

+407
-100
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv
1111

1212
### Added
1313

14+
- We added support for selecting and using CSL Styles in JabRef's OpenOffice/LibreOffice integration for inserting bibliographic and in-text citations into a document.
15+
1416
### Changed
1517

1618
### Fixed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
nav_order: 31
3+
parent: Decision Records
4+
---
5+
# Use currently active Style tab in Select Style Dialog to decide which style to activate
6+
7+
## Context and Problem Statement
8+
9+
In the Select Style Dialog window of the OpenOffice Panel, in case a style is selected in both the CSL Styles Tab and JStyles Tab, how to decide which of the two will be activated for use?
10+
11+
## Considered Options
12+
13+
* Use toggle in Select Style GUI
14+
* Use toggle in Preferences
15+
* Use Buttons in Select Style GUI
16+
* Use Toggle in Main GUI
17+
* Use currently active Tab in Select Style GUI and add a notification
18+
19+
## Decision Outcome
20+
21+
Chosen option: "Use currently active Tab in Select Style GUI and add a notification", because we already had two tabs indicating a clear separation of choices to the user. It was the most convenient way without adding extra steps to make the user choose "which style type to use" before selecting the style, which would be the case in the other options if chosen. The option is quite intuitive, extensible for working with multiple tabs and make only three to four clicks are necessary to select a style. Furthermore, the notification makes it clear to the user which style type as well as which style is selected.

src/main/java/org/jabref/gui/openoffice/OOBibBase.java

+31-17
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.jabref.gui.openoffice;
22

3+
import java.io.IOException;
34
import java.nio.file.Path;
45
import java.util.ArrayList;
56
import java.util.Arrays;
@@ -21,8 +22,10 @@
2122
import org.jabref.logic.openoffice.action.Update;
2223
import org.jabref.logic.openoffice.frontend.OOFrontend;
2324
import org.jabref.logic.openoffice.frontend.RangeForOverlapCheck;
25+
import org.jabref.logic.openoffice.oocsltext.CSLCitationOOAdapter;
2426
import org.jabref.logic.openoffice.style.OOBibStyle;
2527
import org.jabref.model.database.BibDatabase;
28+
import org.jabref.model.database.BibDatabaseContext;
2629
import org.jabref.model.entry.BibEntry;
2730
import org.jabref.model.openoffice.CitationEntry;
2831
import org.jabref.model.openoffice.rangesort.FunctionalTextViewCursor;
@@ -509,7 +512,7 @@ public void guiActionApplyCitationEntries(List<CitationEntry> citationEntries) {
509512
* Note: Undo does not remove or reestablish custom properties.
510513
*
511514
* @param entries The entries to cite.
512-
* @param database The database the entries belong to (all of them). Used when creating the citation mark.
515+
* @param bibDatabaseContext The database the entries belong to (all of them). Used when creating the citation mark.
513516
* <p>
514517
* Consistency: for each entry in {@code entries}: looking it up in {@code syncOptions.get().databases} (if present) should yield {@code database}.
515518
* @param style The bibliography style we are using.
@@ -518,11 +521,11 @@ public void guiActionApplyCitationEntries(List<CitationEntry> citationEntries) {
518521
* @param syncOptions Indicates whether in-text citations should be refreshed in the document. Optional.empty() indicates no refresh. Otherwise provides options for refreshing the reference list.
519522
*/
520523
public void guiActionInsertEntry(List<BibEntry> entries,
521-
BibDatabase database,
524+
BibDatabaseContext bibDatabaseContext,
522525
OOBibStyle style,
523526
CitationType citationType,
524527
String pageInfo,
525-
Optional<Update.SyncOptions> syncOptions) {
528+
Optional<Update.SyncOptions> syncOptions, StyleSelectDialogViewModel.StyleType selectedStyleType) {
526529

527530
final String errorTitle = "Could not insert citation";
528531

@@ -579,15 +582,24 @@ public void guiActionInsertEntry(List<BibEntry> entries,
579582

580583
try {
581584
UnoUndo.enterUndoContext(doc, "Insert citation");
582-
583-
EditInsert.insertCitationGroup(doc,
584-
frontend.get(),
585-
cursor.get(),
586-
entries,
587-
database,
588-
style,
589-
citationType,
590-
pageInfo);
585+
if (selectedStyleType == StyleSelectDialogViewModel.StyleType.CSL) {
586+
// Handle CSL Styles
587+
if (citationType == CitationType.AUTHORYEAR_INTEXT) {
588+
CSLCitationOOAdapter.insertInText(doc, cursor.get(), entries, bibDatabaseContext);
589+
} else {
590+
CSLCitationOOAdapter.insertBibliography(doc, cursor.get(), entries, bibDatabaseContext);
591+
}
592+
} else {
593+
// Handle JStyles
594+
EditInsert.insertCitationGroup(doc,
595+
frontend.get(),
596+
cursor.get(),
597+
entries,
598+
bibDatabaseContext.getDatabase(),
599+
style,
600+
citationType,
601+
pageInfo);
602+
}
591603

592604
if (syncOptions.isPresent()) {
593605
Update.resyncDocument(doc, style, fcursor.get(), syncOptions.get());
@@ -596,11 +608,13 @@ public void guiActionInsertEntry(List<BibEntry> entries,
596608
OOError.from(ex).setTitle(errorTitle).showErrorDialog(dialogService);
597609
} catch (DisposedException ex) {
598610
OOError.from(ex).setTitle(errorTitle).showErrorDialog(dialogService);
599-
} catch (CreationException
600-
| IllegalTypeException
601-
| NotRemoveableException
602-
| PropertyVetoException
603-
| WrappedTargetException ex) {
611+
} catch (
612+
CreationException |
613+
WrappedTargetException |
614+
IOException |
615+
PropertyVetoException |
616+
IllegalTypeException |
617+
NotRemoveableException ex) {
604618
LOGGER.warn("Could not insert entry", ex);
605619
OOError.fromMisc(ex).setTitle(errorTitle).showErrorDialog(dialogService);
606620
} finally {

src/main/java/org/jabref/gui/openoffice/OpenOfficePanel.java

+37-25
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,14 @@
4242
import org.jabref.gui.util.TaskExecutor;
4343
import org.jabref.logic.citationkeypattern.CitationKeyGenerator;
4444
import org.jabref.logic.citationkeypattern.CitationKeyPatternPreferences;
45+
import org.jabref.logic.citationstyle.CitationStyle;
4546
import org.jabref.logic.help.HelpFile;
4647
import org.jabref.logic.journals.JournalAbbreviationRepository;
4748
import org.jabref.logic.l10n.Localization;
4849
import org.jabref.logic.openoffice.OpenOfficeFileSearch;
4950
import org.jabref.logic.openoffice.OpenOfficePreferences;
5051
import org.jabref.logic.openoffice.action.Update;
52+
import org.jabref.logic.openoffice.oocsltext.CSLCitationOOAdapter;
5153
import org.jabref.logic.openoffice.style.OOBibStyle;
5254
import org.jabref.logic.openoffice.style.StyleLoader;
5355
import org.jabref.model.database.BibDatabase;
@@ -98,7 +100,8 @@ public class OpenOfficePanel {
98100
private final FileUpdateMonitor fileUpdateMonitor;
99101
private final BibEntryTypesManager entryTypesManager;
100102
private OOBibBase ooBase;
101-
private OOBibStyle style;
103+
private OOBibStyle jStyle;
104+
private StyleSelectDialogViewModel.StyleType currentStyleType;
102105

103106
public OpenOfficePanel(LibraryTabContainer tabContainer,
104107
PreferencesService preferencesService,
@@ -165,15 +168,15 @@ private boolean getOrUpdateTheStyle(String title) {
165168
final boolean FAIL = true;
166169
final boolean PASS = false;
167170

168-
if (style == null) {
169-
style = loader.getUsedStyle();
171+
if (jStyle == null) {
172+
jStyle = loader.getUsedStyle();
170173
} else {
171174
try {
172-
style.ensureUpToDate();
175+
jStyle.ensureUpToDate();
173176
} catch (IOException ex) {
174-
LOGGER.warn("Unable to reload style file '" + style.getPath() + "'", ex);
177+
LOGGER.warn("Unable to reload style file '{}'", jStyle.getPath(), ex);
175178
String msg = Localization.lang("Unable to reload style file")
176-
+ "'" + style.getPath() + "'"
179+
+ "'" + jStyle.getPath() + "'"
177180
+ "\n" + ex.getMessage();
178181
new OOError(title, msg, ex).showErrorDialog(dialogService);
179182
return FAIL;
@@ -190,17 +193,25 @@ private void initPanel() {
190193
selectDocument.setOnAction(e -> ooBase.guiActionSelectDocument(false));
191194

192195
setStyleFile.setMaxWidth(Double.MAX_VALUE);
193-
setStyleFile.setOnAction(event ->
194-
dialogService.showCustomDialogAndWait(new StyleSelectDialogView(loader))
195-
.ifPresent(selectedStyle -> {
196-
style = selectedStyle;
197-
try {
198-
style.ensureUpToDate();
199-
} catch (IOException e) {
200-
LOGGER.warn("Unable to reload style file '" + style.getPath() + "'", e);
201-
}
202-
dialogService.notify(Localization.lang("Current style is '%0'", style.getName()));
203-
}));
196+
setStyleFile.setOnAction(event -> {
197+
StyleSelectDialogView styleDialog = new StyleSelectDialogView(loader);
198+
dialogService.showCustomDialogAndWait(styleDialog)
199+
.ifPresent(selectedStyle -> {
200+
jStyle = selectedStyle;
201+
currentStyleType = styleDialog.getSelectedStyleType();
202+
try {
203+
jStyle.ensureUpToDate();
204+
} catch (IOException e) {
205+
LOGGER.warn("Unable to reload style file '{}'", jStyle.getPath(), e);
206+
}
207+
if (currentStyleType == StyleSelectDialogViewModel.StyleType.JSTYLE) {
208+
dialogService.notify(Localization.lang("Currently selected JStyle: '%0'", jStyle.getName()));
209+
} else {
210+
CitationStyle cslStyle = CSLCitationOOAdapter.getSelectedStyle();
211+
dialogService.notify(Localization.lang("Currently selected CSL Style: '%0'", cslStyle.getTitle()));
212+
}
213+
});
214+
});
204215

205216
pushEntries.setTooltip(new Tooltip(Localization.lang("Cite selected entries between parenthesis")));
206217
pushEntries.setOnAction(e -> pushEntries(CitationType.AUTHORYEAR_PAR, false));
@@ -223,16 +234,16 @@ private void initPanel() {
223234
return;
224235
}
225236
List<BibDatabase> databases = getBaseList();
226-
ooBase.guiActionUpdateDocument(databases, style);
237+
ooBase.guiActionUpdateDocument(databases, jStyle);
227238
});
228239

229240
merge.setMaxWidth(Double.MAX_VALUE);
230241
merge.setTooltip(new Tooltip(Localization.lang("Combine pairs of citations that are separated by spaces only")));
231-
merge.setOnAction(e -> ooBase.guiActionMergeCitationGroups(getBaseList(), style));
242+
merge.setOnAction(e -> ooBase.guiActionMergeCitationGroups(getBaseList(), jStyle));
232243

233244
unmerge.setMaxWidth(Double.MAX_VALUE);
234245
unmerge.setTooltip(new Tooltip(Localization.lang("Separate merged citations")));
235-
unmerge.setOnAction(e -> ooBase.guiActionSeparateCitations(getBaseList(), style));
246+
unmerge.setOnAction(e -> ooBase.guiActionSeparateCitations(getBaseList(), jStyle));
236247

237248
ContextMenu settingsMenu = createSettingsPopup();
238249
settingsB.setMaxWidth(Double.MAX_VALUE);
@@ -462,8 +473,8 @@ private void pushEntries(CitationType citationType, boolean addPageInfo) {
462473
return;
463474
}
464475

465-
final BibDatabase database = stateManager.getActiveDatabase().get().getDatabase();
466-
if (database == null) {
476+
final BibDatabaseContext bibDatabaseContext = stateManager.getActiveDatabase().get();
477+
if (bibDatabaseContext == null) {
467478
OOError.noDataBaseIsOpenForCiting()
468479
.setTitle(errorDialogTitle)
469480
.showErrorDialog(dialogService);
@@ -510,11 +521,12 @@ private void pushEntries(CitationType citationType, boolean addPageInfo) {
510521
: Optional.empty();
511522

512523
ooBase.guiActionInsertEntry(entries,
513-
database,
514-
style,
524+
bibDatabaseContext,
525+
jStyle,
515526
citationType,
516527
pageInfo,
517-
syncOptions);
528+
syncOptions,
529+
currentStyleType);
518530
}
519531

520532
/**

src/main/java/org/jabref/gui/openoffice/StyleSelectDialog.fxml

+56-24
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,70 @@
11
<?xml version="1.0" encoding="UTF-8"?>
22

3+
<?import javafx.geometry.Insets?>
34
<?import javafx.scene.control.Button?>
45
<?import javafx.scene.control.ButtonType?>
56
<?import javafx.scene.control.DialogPane?>
7+
<?import javafx.scene.control.Label?>
8+
<?import javafx.scene.control.ListView?>
9+
<?import javafx.scene.control.Tab?>
610
<?import javafx.scene.control.TableColumn?>
711
<?import javafx.scene.control.TableView?>
12+
<?import javafx.scene.control.TabPane?>
813
<?import javafx.scene.layout.BorderPane?>
914
<?import javafx.scene.layout.VBox?>
10-
<DialogPane xmlns:fx="http://javafx.com/fxml/1" minHeight="-Infinity" minWidth="-Infinity" prefHeight="470.0"
11-
prefWidth="701.0" xmlns="http://javafx.com/javafx/8.0.171"
15+
<?import org.controlsfx.control.textfield.CustomTextField?>
16+
<DialogPane xmlns:fx="http://javafx.com/fxml/1" minHeight="-Infinity" minWidth="-Infinity" prefHeight="500.0"
17+
prefWidth="800.0" xmlns="http://javafx.com/javafx/8.0.171"
1218
fx:controller="org.jabref.gui.openoffice.StyleSelectDialogView">
1319
<content>
14-
<BorderPane>
15-
<top>
16-
<TableView fx:id="tvStyles" prefHeight="208.0" prefWidth="662.0" BorderPane.alignment="CENTER">
17-
<columns>
18-
<TableColumn fx:id="colName" minWidth="100.0" prefWidth="-1.0" text="%Name"/>
19-
<TableColumn fx:id="colJournals" minWidth="100.0" prefWidth="75.0" text="%Journals"/>
20-
<TableColumn fx:id="colFile" minWidth="100.0" prefWidth="-1.0" text="%File"/>
21-
<TableColumn fx:id="colDeleteIcon" minWidth="100.0" prefWidth="-1.0"/>
22-
</columns>
23-
<columnResizePolicy>
24-
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY"/>
25-
</columnResizePolicy>
26-
</TableView>
27-
</top>
28-
<right>
29-
<Button fx:id="add" alignment="TOP_RIGHT" mnemonicParsing="false" onAction="#addStyleFile"
30-
text="%Add style file" BorderPane.alignment="CENTER"/>
31-
</right>
32-
<bottom>
33-
<VBox fx:id="vbox" prefHeight="84.0" prefWidth="665.0" BorderPane.alignment="CENTER"/>
34-
</bottom>
35-
</BorderPane>
20+
<TabPane fx:id="tabPane" tabClosingPolicy="UNAVAILABLE">
21+
<tabs>
22+
<Tab text="CSL Styles">
23+
<content>
24+
<VBox spacing="10.0" VBox.vgrow="ALWAYS">
25+
<padding>
26+
<Insets top="10.0" right="10.0" bottom="10.0" left="10.0"/>
27+
</padding>
28+
<VBox spacing="4.0" VBox.vgrow="ALWAYS">
29+
<Label text="%Available" styleClass="sectionHeader"/>
30+
<CustomTextField fx:id="searchBox" promptText="%Filter" prefHeight="20.0"/>
31+
<ListView fx:id="availableListView" VBox.vgrow="ALWAYS"/>
32+
</VBox>
33+
<VBox spacing="4.0">
34+
<Label text="%Preview" styleClass="sectionHeader"/>
35+
<VBox fx:id="cslPreviewBox" prefHeight="300.0" spacing="4.0"/>
36+
</VBox>
37+
</VBox>
38+
</content>
39+
</Tab>
40+
<Tab text="JStyles">
41+
<content>
42+
<BorderPane>
43+
<top>
44+
<TableView fx:id="tvStyles" prefHeight="208.0" prefWidth="662.0" BorderPane.alignment="CENTER">
45+
<columns>
46+
<TableColumn fx:id="colName" minWidth="100.0" prefWidth="-1.0" text="%Name"/>
47+
<TableColumn fx:id="colJournals" minWidth="100.0" prefWidth="75.0" text="%Journals"/>
48+
<TableColumn fx:id="colFile" minWidth="100.0" prefWidth="-1.0" text="%File"/>
49+
<TableColumn fx:id="colDeleteIcon" minWidth="100.0" prefWidth="-1.0"/>
50+
</columns>
51+
<columnResizePolicy>
52+
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY"/>
53+
</columnResizePolicy>
54+
</TableView>
55+
</top>
56+
<right>
57+
<Button fx:id="add" alignment="TOP_RIGHT" mnemonicParsing="false" onAction="#addStyleFile"
58+
text="%Add style file" BorderPane.alignment="CENTER"/>
59+
</right>
60+
<bottom>
61+
<VBox fx:id="jstylePreviewBox" prefHeight="84.0" prefWidth="665.0" BorderPane.alignment="CENTER"/>
62+
</bottom>
63+
</BorderPane>
64+
</content>
65+
</Tab>
66+
</tabs>
67+
</TabPane>
3668
</content>
3769
<buttonTypes>
3870
<ButtonType fx:constant="CANCEL"/>

0 commit comments

Comments
 (0)