From f8af3a6ca7c8e8afab36591a39609d684e32457f Mon Sep 17 00:00:00 2001 From: Baaaaaz <131240480+Baaaaaz@users.noreply.github.com> Date: Thu, 13 Aug 2026 20:38:50 +0100 Subject: [PATCH 1/5] table groups --- .../main/proto/data_transfer_objects.proto | 1 + .../client/functions/LookupTableFunction.java | 60 ++++++++++++++++++- .../ui/lookuptable/EditLookupTablePanel.java | 3 + .../lookuptable/EditLookupTablePanelView.form | 44 +++++++++----- .../lookuptable/EditLookupTablePanelView.java | 5 ++ .../LookupTableDetailsTablePanelModel.java | 19 +++++- .../rptools/maptool/model/LookupTable.java | 17 ++++++ .../rptools/maptool/language/i18n.properties | 1 + 8 files changed, 132 insertions(+), 18 deletions(-) diff --git a/messages/src/main/proto/data_transfer_objects.proto b/messages/src/main/proto/data_transfer_objects.proto index b2d8bcc0d1..cc045bdeec 100644 --- a/messages/src/main/proto/data_transfer_objects.proto +++ b/messages/src/main/proto/data_transfer_objects.proto @@ -57,6 +57,7 @@ message LookupTableDto { bool visible = 5; bool allow_lookup = 6; bool pick_once = 7; + google.protobuf.StringValue group = 8; } message LookupEntryDto { diff --git a/src/main/java/net/rptools/maptool/client/functions/LookupTableFunction.java b/src/main/java/net/rptools/maptool/client/functions/LookupTableFunction.java index 3d67edd2b3..953c99c37e 100644 --- a/src/main/java/net/rptools/maptool/client/functions/LookupTableFunction.java +++ b/src/main/java/net/rptools/maptool/client/functions/LookupTableFunction.java @@ -21,6 +21,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; +import java.util.stream.Collectors; import java.util.stream.Stream; import net.rptools.lib.MD5Key; import net.rptools.maptool.client.MapTool; @@ -67,7 +68,10 @@ public LookupTableFunction() { "resetTablePicks", "getTablePickOnce", "setTablePickOnce", - "getTablePicksLeft"); + "getTablePicksLeft", + "getTableGroup", + "setTableGroup", + "getTableGroups"); } /** The singleton instance. */ @@ -101,6 +105,20 @@ public Object childEvaluate( } return StringUtils.join(getTableList(MapTool.getPlayer().isGM()), delim); + } else if ("getTableGroups".equalsIgnoreCase(function)) { + + FunctionUtil.checkNumberParam("getTableGroups", params, 0, 1); + String delim = ","; + if (params.size() > 0) { + delim = params.get(0).toString(); + } + if ("json".equalsIgnoreCase(delim)) { + JsonArray jsonArray = new JsonArray(); + getTableGroupList(MapTool.getPlayer().isGM()).forEach(jsonArray::add); + return jsonArray; + } + return StringUtils.join(getTableGroupList(MapTool.getPlayer().isGM()), delim); + } else if ("getTableVisible".equalsIgnoreCase(function)) { checkTrusted(function); @@ -468,6 +486,25 @@ public Object childEvaluate( LookupTable lookupTable = getMaptoolTable(name, function); return lookupTable.getPicksLeft(); + } else if ("getTableGroup".equalsIgnoreCase(function)) { + + checkTrusted(function); + FunctionUtil.checkNumberParam("getTableGroup", params, 1, 1); + String name = params.get(0).toString(); + LookupTable lookupTable = getMaptoolTable(name, function); + return lookupTable.getGroup(); + + } else if ("setTableGroup".equalsIgnoreCase(function)) { + + checkTrusted(function); + FunctionUtil.checkNumberParam("setTableGroup", params, 2, 2); + String name = params.get(0).toString(); + String group = params.get(1).toString(); + LookupTable lookupTable = getMaptoolTable(name, function); + lookupTable.setGroup(group); + processMutatedLookupTable(lookupTable, true); + return ""; + } else { // if tbl, table, tblImage or tableImage FunctionUtil.checkNumberParam(function, params, 1, 3); String name = params.get(0).toString(); @@ -585,6 +622,27 @@ private List getTableList(boolean isGm) { return tables; } + /** + * If GM return all table groups otherwise only return groups for visible tables + * + * @param isGm does the calling function has GM privileges + * @return a list of table groups + */ + private List getTableGroupList(boolean isGm) { + return MapTool.getCampaign().getLookupTableMap().values().stream() + // If not GM, only keep visible tables + .filter(lt -> isGm || lt.getVisible()) + // Get the group name from the table + .map(LookupTable::getGroup) + // Remove any null groups + .filter(Objects::nonNull) + // Remove duplicate groups + .distinct() + // Sort groups + .sorted() + .collect(Collectors.toList()); + } + /** * Function to return a MapTool table. * diff --git a/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanel.java b/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanel.java index ff9fe32e45..247c2764a6 100644 --- a/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanel.java +++ b/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanel.java @@ -193,6 +193,7 @@ public void bind(LookupTable lookupTable) { super.bind(lookupTable); view.getTableName().setText(lookupTable.getName()); + view.getTableGroup().setText(lookupTable.getGroup()); view.getDefaultTableRoll() .setText(lookupTable.getPickOnce() ? "" : lookupTable.calculateRoll()); tableImageAssetPanel.setImageId(lookupTable.getTableImage()); @@ -240,6 +241,7 @@ public boolean commit() { return false; } var isPickOnce = view.getPickOnce().isSelected(); + String group = view.getTableGroup().getText().trim(); // Before modifying the table, parse and validate all the entries to avoid partial modification // in case of error. @@ -284,6 +286,7 @@ public boolean commit() { // save existing name for later removal from LookupTableMap String origname = lookupTable.getName(); lookupTable.setName(name); + lookupTable.setGroup(group); lookupTable.setPickOnce(isPickOnce); lookupTable.setRoll(isPickOnce ? null : view.getDefaultTableRoll().getText()); lookupTable.setTableImage(tableImageAssetPanel.getImageId()); diff --git a/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanelView.form b/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanelView.form index 2512356cdf..6111f52d42 100644 --- a/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanelView.form +++ b/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanelView.form @@ -3,7 +3,7 @@ - + @@ -26,7 +26,7 @@ - + @@ -44,7 +44,7 @@ - + @@ -52,7 +52,7 @@ - + @@ -61,7 +61,7 @@ - + @@ -71,7 +71,7 @@ - + @@ -81,17 +81,17 @@ - + - + - + @@ -102,7 +102,7 @@ - + @@ -119,7 +119,7 @@ - + @@ -137,7 +137,7 @@ - + @@ -145,7 +145,7 @@ - + @@ -154,7 +154,7 @@ - + @@ -163,7 +163,7 @@ - + @@ -171,6 +171,20 @@ + + + + + + + + + + + + + + diff --git a/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanelView.java b/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanelView.java index 7802961c5c..8342bf5dba 100644 --- a/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanelView.java +++ b/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanelView.java @@ -20,6 +20,7 @@ public class EditLookupTablePanelView { private JPanel mainPanel; private JTextField tableName; + private JTextField tableGroup; private JTextField defaultTableRoll; private JCheckBox isVisible; private JCheckBox allowLookup; @@ -39,6 +40,10 @@ public JTextField getTableName() { return tableName; } + public JTextField getTableGroup() { + return tableGroup; + } + public JTextField getDefaultTableRoll() { return defaultTableRoll; } diff --git a/src/main/java/net/rptools/maptool/client/ui/lookuptable/LookupTableDetailsTablePanelModel.java b/src/main/java/net/rptools/maptool/client/ui/lookuptable/LookupTableDetailsTablePanelModel.java index f5fe608cf1..90efcef5ff 100644 --- a/src/main/java/net/rptools/maptool/client/ui/lookuptable/LookupTableDetailsTablePanelModel.java +++ b/src/main/java/net/rptools/maptool/client/ui/lookuptable/LookupTableDetailsTablePanelModel.java @@ -35,6 +35,7 @@ public class LookupTableDetailsTablePanelModel extends AbstractTableModel { List.of( DetailsTableColumn.IMAGE, DetailsTableColumn.NAME, + DetailsTableColumn.GROUP, DetailsTableColumn.PLAYER_VISIBLE, DetailsTableColumn.ALLOW_LOOKUP, DetailsTableColumn.PICK_ONCE, @@ -45,7 +46,7 @@ public class LookupTableDetailsTablePanelModel extends AbstractTableModel { /** Defines the details view columns visible for non-GMs and their sequence */ private static final List PLAYER_COLUMNS = - List.of(DetailsTableColumn.IMAGE, DetailsTableColumn.NAME); + List.of(DetailsTableColumn.IMAGE, DetailsTableColumn.NAME, DetailsTableColumn.GROUP); /** * Retries the set list of details view columns based on GM role or not @@ -88,7 +89,7 @@ Object getValue(LookupTable table) { String.class, SwingConstants.LEFT, 200, - Icons.WINDOW_TABLES, + null, null, null) { @Override @@ -96,6 +97,20 @@ Object getValue(LookupTable table) { return table.getName(); } }, + GROUP( + I18N.getText("Label.group"), + null, + String.class, + SwingConstants.LEFT, + 100, + null, + null, + null) { + @Override + Object getValue(LookupTable table) { + return table.getGroup(); + } + }, PLAYER_VISIBLE( null, I18N.getText("EditLookupTablePanel.showplayer"), diff --git a/src/main/java/net/rptools/maptool/model/LookupTable.java b/src/main/java/net/rptools/maptool/model/LookupTable.java index 5bb5ebe271..d8bfd89d9b 100644 --- a/src/main/java/net/rptools/maptool/model/LookupTable.java +++ b/src/main/java/net/rptools/maptool/model/LookupTable.java @@ -34,6 +34,7 @@ public class LookupTable { private @Nonnull List entryList = new ArrayList<>(); private @Nullable String name; + private @Nullable String group; private @Nullable String defaultRoll; private @Nullable MD5Key tableImage; private @Nonnull Boolean visible = true; @@ -48,6 +49,7 @@ public LookupTable() {} public LookupTable(LookupTable table) { name = table.name; + group = table.group; defaultRoll = table.defaultRoll; tableImage = table.tableImage; pickOnce = table.pickOnce; @@ -94,6 +96,14 @@ public String getName() { return name; } + public void setGroup(String group) { + this.group = group; + } + + public String getGroup() { + return group; + } + /** * Finds the first entry that matches a given roll result. * @@ -500,6 +510,9 @@ private Object readResolve() { if (entryList == null) { entryList = new ArrayList<>(); } + if (group == null) { + group = ""; + } return this; } @@ -535,6 +548,7 @@ public long getEntryValueCount() { public static LookupTable fromDto(LookupTableDto dto) { var table = new LookupTable(); table.name = dto.hasName() ? dto.getName().getValue() : null; + table.group = dto.hasGroup() ? dto.getGroup().getValue() : null; table.entryList = dto.getEntriesList().stream().map(e -> LookupEntry.fromDto(e)).collect(Collectors.toList()); table.defaultRoll = dto.hasDefaultRoll() ? dto.getDefaultRoll().getValue() : null; @@ -551,6 +565,9 @@ public LookupTableDto toDto() { if (name != null) { dto.setName(StringValue.of(name)); } + if (group != null) { + dto.setGroup(StringValue.of(group)); + } if (defaultRoll != null) { dto.setDefaultRoll(StringValue.of(defaultRoll)); } diff --git a/src/main/resources/net/rptools/maptool/language/i18n.properties b/src/main/resources/net/rptools/maptool/language/i18n.properties index 7ca803a223..7238536f94 100644 --- a/src/main/resources/net/rptools/maptool/language/i18n.properties +++ b/src/main/resources/net/rptools/maptool/language/i18n.properties @@ -260,6 +260,7 @@ Label.lights = Vision Label.type = Type Label.name = Name Label.gmname = GM Name +Label.group = Group Label.speechName = Speech Bubble Name Label.optional = Optional Label.options = Options From d6d6f7f10abd1985af39aaee19eca5c9520ef6a7 Mon Sep 17 00:00:00 2001 From: Baaaaaz <131240480+Baaaaaz@users.noreply.github.com> Date: Thu, 13 Aug 2026 21:00:51 +0100 Subject: [PATCH 2/5] cache edit panel dialog instance to persist resizing and relocating --- .../ui/lookuptable/LookupTablePanel.java | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/rptools/maptool/client/ui/lookuptable/LookupTablePanel.java b/src/main/java/net/rptools/maptool/client/ui/lookuptable/LookupTablePanel.java index c8491e5527..7c4e56c1b6 100644 --- a/src/main/java/net/rptools/maptool/client/ui/lookuptable/LookupTablePanel.java +++ b/src/main/java/net/rptools/maptool/client/ui/lookuptable/LookupTablePanel.java @@ -47,6 +47,9 @@ public class LookupTablePanel extends AbeillePanel { /** a tabular view of {@link LookupTable}s' details */ private LookupTableDetailsTablePanel detailsTablePanel; + /** cache edit panel instance so position and dimensions are retained within the session */ + private EditLookupTablePanel editLookupTablePanel; + /** manages the different views and so only one is visible as a time */ private CardLayout viewLayout; @@ -55,6 +58,13 @@ public LookupTablePanel() { panelInit(); } + private EditLookupTablePanel getEditLookupTablePanel() { + if (editLookupTablePanel == null) { + editLookupTablePanel = new EditLookupTablePanel(); + } + return editLookupTablePanel; + } + /** the view options */ private enum ViewMode { /** a view of {@code LookupTable} images and their names as labels. */ @@ -134,7 +144,7 @@ public void mouseClicked(MouseEvent e) { if (detailsTable.columnAtPoint(e.getPoint()) == 0) { lookupTableRoll(lookupTable); } else { - new EditLookupTablePanel().showDialog(lookupTable, false); + getEditLookupTablePanel().showDialog(lookupTable, false); } } else { lookupTableRoll(lookupTable); @@ -219,7 +229,7 @@ public void initDuplicateButton() { } LookupTable lookupTable = new LookupTable(selected); lookupTable.setName("Copy of " + lookupTable.getName()); - new EditLookupTablePanel().showDialog(lookupTable, true); + getEditLookupTablePanel().showDialog(lookupTable, true); imagePanel.clearSelection(); refreshStructure(); @@ -236,7 +246,7 @@ public void initEditTableButton() { if (lookupTable == null) { return; } - new EditLookupTablePanel().showDialog(lookupTable, false); + getEditLookupTablePanel().showDialog(lookupTable, false); refreshData(); }); } @@ -247,7 +257,7 @@ public void initNewTableButton() { getNewButton() .addActionListener( e -> { - new EditLookupTablePanel().showDialog(new LookupTable(), true); + getEditLookupTablePanel().showDialog(new LookupTable(), true); imagePanel.clearSelection(); refreshStructure(); }); From 5a6844dd3ede990836eb3406cd47b9f8d5dfd9ab Mon Sep 17 00:00:00 2001 From: Baaaaaz <131240480+Baaaaaz@users.noreply.github.com> Date: Fri, 14 Aug 2026 06:52:04 +0100 Subject: [PATCH 3/5] add table metadata and change group to JComboBox --- .../main/proto/data_transfer_objects.proto | 1 + .../client/functions/LookupTableFunction.java | 35 +++++- .../ui/lookuptable/EditLookupTablePanel.java | 71 +++++++++++- .../lookuptable/EditLookupTablePanelView.form | 101 ++++++++++++++---- .../lookuptable/EditLookupTablePanelView.java | 16 ++- .../LookupTableDetailsTablePanelModel.java | 17 ++- .../rptools/maptool/model/LookupTable.java | 30 +++++- .../rptools/maptool/language/i18n.properties | 2 + 8 files changed, 241 insertions(+), 32 deletions(-) diff --git a/messages/src/main/proto/data_transfer_objects.proto b/messages/src/main/proto/data_transfer_objects.proto index cc045bdeec..01330393a7 100644 --- a/messages/src/main/proto/data_transfer_objects.proto +++ b/messages/src/main/proto/data_transfer_objects.proto @@ -58,6 +58,7 @@ message LookupTableDto { bool allow_lookup = 6; bool pick_once = 7; google.protobuf.StringValue group = 8; + google.protobuf.StringValue metadata = 9; } message LookupEntryDto { diff --git a/src/main/java/net/rptools/maptool/client/functions/LookupTableFunction.java b/src/main/java/net/rptools/maptool/client/functions/LookupTableFunction.java index 953c99c37e..53f20e5155 100644 --- a/src/main/java/net/rptools/maptool/client/functions/LookupTableFunction.java +++ b/src/main/java/net/rptools/maptool/client/functions/LookupTableFunction.java @@ -71,7 +71,9 @@ public LookupTableFunction() { "getTablePicksLeft", "getTableGroup", "setTableGroup", - "getTableGroups"); + "getTableGroups", + "getTableMetadata", + "setTableMetadata"); } /** The singleton instance. */ @@ -487,7 +489,9 @@ public Object childEvaluate( return lookupTable.getPicksLeft(); } else if ("getTableGroup".equalsIgnoreCase(function)) { - + /* + * getTableGroup(tblName) - get the named table's group + */ checkTrusted(function); FunctionUtil.checkNumberParam("getTableGroup", params, 1, 1); String name = params.get(0).toString(); @@ -495,7 +499,9 @@ public Object childEvaluate( return lookupTable.getGroup(); } else if ("setTableGroup".equalsIgnoreCase(function)) { - + /* + * getTableGroup(tblName, group) - set the named table's group + */ checkTrusted(function); FunctionUtil.checkNumberParam("setTableGroup", params, 2, 2); String name = params.get(0).toString(); @@ -505,6 +511,29 @@ public Object childEvaluate( processMutatedLookupTable(lookupTable, true); return ""; + } else if ("getTableMetadata".equalsIgnoreCase(function)) { + /* + * getTableMetadata(tblName) - get the named table's metadata + */ + checkTrusted(function); + FunctionUtil.checkNumberParam("getTableMetadata", params, 1, 1); + String name = params.get(0).toString(); + LookupTable lookupTable = getMaptoolTable(name, function); + return lookupTable.getMetadata(); + + } else if ("setTableMetadata".equalsIgnoreCase(function)) { + /* + * setTableMetadata(tblName, metadata) - set the named table's metadata + */ + checkTrusted(function); + FunctionUtil.checkNumberParam("setTableMetadata", params, 2, 2); + String name = params.get(0).toString(); + String metadata = params.get(1).toString(); + LookupTable lookupTable = getMaptoolTable(name, function); + lookupTable.setMetadata(metadata); + processMutatedLookupTable(lookupTable, true); + return ""; + } else { // if tbl, table, tblImage or tableImage FunctionUtil.checkNumberParam(function, params, 1, 3); String name = params.get(0).toString(); diff --git a/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanel.java b/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanel.java index 247c2764a6..8a1dfd9dd2 100644 --- a/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanel.java +++ b/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanel.java @@ -22,6 +22,10 @@ import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Objects; @@ -34,6 +38,8 @@ import javax.swing.table.AbstractTableModel; import javax.swing.table.TableCellRenderer; import net.rptools.lib.MD5Key; +import net.rptools.maptool.client.AppConstants; +import net.rptools.maptool.client.AppPreferences; import net.rptools.maptool.client.MapTool; import net.rptools.maptool.client.MapToolUtil; import net.rptools.maptool.client.swing.AbeillePanel; @@ -48,6 +54,10 @@ import net.rptools.maptool.model.AssetManager; import net.rptools.maptool.model.LookupTable; import net.rptools.maptool.model.LookupTable.LookupEntry; +import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; +import org.fife.ui.rsyntaxtextarea.SyntaxConstants; +import org.fife.ui.rsyntaxtextarea.Theme; +import org.fife.ui.rtextarea.RTextScrollPane; public class EditLookupTablePanel extends AbeillePanel { private static final int PICKED_COLUMN_INDEX = 0; @@ -99,6 +109,7 @@ public void showDialog(@Nullable LookupTable lookupTable, boolean isNew) { .setIcon(RessourceManager.getSmallIcon(Icons.TABLEPANEL_TABLE_PLAYER_LOOKUP)); view.getPickOnceIcon().setIcon(RessourceManager.getSmallIcon(Icons.TABLEPANEL_TABLE_PICK_ONCE)); + loadTableGroups(); bind(lookupTable); dialogFactory.display(); @@ -188,12 +199,60 @@ public void initTableImage() { replaceComponent(view.getTableImagePlaceholder(), tableImageAssetPanel); } + public void initMetadataSyntaxArea() { + + // configure the syntax text area + RSyntaxTextArea rsta = view.getTableMetadata(); + rsta.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JSON); + rsta.setCodeFoldingEnabled(true); + rsta.setEditable(true); + rsta.setInsertPairedCharacters(false); + rsta.setLineWrap(true); + rsta.setTabSize(4); + rsta.setWrapStyleWord(true); + rsta.setUseFocusableTips(false); + + RTextScrollPane rtsp = view.getTableMetadataScrollPane(); + rtsp.setLineNumbersEnabled(true); + + // theme the syntax text area + Path themePath = + AppConstants.THEMES_DIR + .toPath() + .resolve(AppPreferences.defaultMacroEditorTheme.get() + ".xml"); + try (InputStream in = Files.newInputStream(themePath)) { + Theme.load(in).apply(rsta); + } catch (IOException e) { + System.err.println("Unable to load theme: " + themePath + " " + e); + } + } + + /** + * Populate the Table Groups ComboBox with groups already used. Should be outside an {@code init*} + * method as needs to respond to group changes. + */ + public void loadTableGroups() { + view.getTableGroup().removeAllItems(); + + MapTool.getCampaign().getLookupTableMap().values().stream() + // Get the group name from the table + .map(LookupTable::getGroup) + // Remove any null groups + .filter(Objects::nonNull) + // Remove duplicate groups + .distinct() + // Sort groups + .sorted() + // Add to the ComboBox + .forEach(group -> view.getTableGroup().addItem(group)); + } + @Override public void bind(LookupTable lookupTable) { super.bind(lookupTable); view.getTableName().setText(lookupTable.getName()); - view.getTableGroup().setText(lookupTable.getGroup()); + view.getTableGroup().setSelectedItem(lookupTable.getGroup()); view.getDefaultTableRoll() .setText(lookupTable.getPickOnce() ? "" : lookupTable.calculateRoll()); tableImageAssetPanel.setImageId(lookupTable.getTableImage()); @@ -204,6 +263,8 @@ public void bind(LookupTable lookupTable) { view.getDefaultTableRoll().setEnabled(!lookupTable.getPickOnce()); view.getResetPicks().setEnabled(lookupTable.getPickOnce()); + view.getTableMetadata().setText(lookupTable.getMetadata()); + view.getTableName().requestFocusInWindow(); var model = new LookupTableTableModel(); @@ -241,7 +302,12 @@ public boolean commit() { return false; } var isPickOnce = view.getPickOnce().isSelected(); - String group = view.getTableGroup().getText().trim(); + + // Get the selected or entered table group from the combo box + Object selectedTableGroup = view.getTableGroup().getSelectedItem(); + String group = selectedTableGroup == null ? "" : selectedTableGroup.toString(); + + String metadata = view.getTableMetadata().getText().trim(); // Before modifying the table, parse and validate all the entries to avoid partial modification // in case of error. @@ -292,6 +358,7 @@ public boolean commit() { lookupTable.setTableImage(tableImageAssetPanel.getImageId()); lookupTable.setVisible(view.getIsVisible().isSelected()); lookupTable.setAllowLookup(view.getAllowLookup().isSelected()); + lookupTable.setMetadata(metadata); lookupTable.clearEntries(); for (var entry : entries) { diff --git a/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanelView.form b/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanelView.form index 6111f52d42..a4b9e53c5b 100644 --- a/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanelView.form +++ b/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanelView.form @@ -1,31 +1,15 @@
- + - + - - - - - - - - - - - - - - - - @@ -179,19 +163,92 @@ - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + +
diff --git a/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanelView.java b/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanelView.java index 8342bf5dba..2d8f451731 100644 --- a/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanelView.java +++ b/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanelView.java @@ -15,12 +15,14 @@ package net.rptools.maptool.client.ui.lookuptable; import javax.swing.*; +import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; +import org.fife.ui.rtextarea.RTextScrollPane; public class EditLookupTablePanelView { private JPanel mainPanel; private JTextField tableName; - private JTextField tableGroup; + private JComboBox tableGroup; private JTextField defaultTableRoll; private JCheckBox isVisible; private JCheckBox allowLookup; @@ -31,6 +33,8 @@ public class EditLookupTablePanelView { private JLabel isVisibleIcon; private JLabel allowLookupIcon; private JLabel pickOnceIcon; + private RSyntaxTextArea tableMetadata; + private RTextScrollPane tableMetadataScrollPane; public JComponent getRootComponent() { return mainPanel; @@ -40,7 +44,7 @@ public JTextField getTableName() { return tableName; } - public JTextField getTableGroup() { + public JComboBox getTableGroup() { return tableGroup; } @@ -83,4 +87,12 @@ public JLabel getAllowLookupIcon() { public JLabel getPickOnceIcon() { return pickOnceIcon; } + + public RSyntaxTextArea getTableMetadata() { + return tableMetadata; + } + + public RTextScrollPane getTableMetadataScrollPane() { + return tableMetadataScrollPane; + } } diff --git a/src/main/java/net/rptools/maptool/client/ui/lookuptable/LookupTableDetailsTablePanelModel.java b/src/main/java/net/rptools/maptool/client/ui/lookuptable/LookupTableDetailsTablePanelModel.java index 90efcef5ff..3db35ace30 100644 --- a/src/main/java/net/rptools/maptool/client/ui/lookuptable/LookupTableDetailsTablePanelModel.java +++ b/src/main/java/net/rptools/maptool/client/ui/lookuptable/LookupTableDetailsTablePanelModel.java @@ -42,7 +42,8 @@ public class LookupTableDetailsTablePanelModel extends AbstractTableModel { DetailsTableColumn.ROLL, DetailsTableColumn.COUNT_ENTRIES, DetailsTableColumn.COUNT_VALUES, - DetailsTableColumn.COUNT_IMAGES); + DetailsTableColumn.COUNT_IMAGES, + DetailsTableColumn.METADATA); /** Defines the details view columns visible for non-GMs and their sequence */ private static final List PLAYER_COLUMNS = @@ -208,6 +209,20 @@ Object getValue(LookupTable table) { Object getValue(LookupTable table) { return table.getEntryImageCount(); } + }, + METADATA( + I18N.getText("EditLookupTablePanel.tab.metadata"), + null, + Boolean.class, + SwingConstants.CENTER, + 80, + null, + Icons.WINDOW_TABLES, + null) { + @Override + Object getValue(LookupTable table) { + return table.hasMetadata(); + } }; private final String title; diff --git a/src/main/java/net/rptools/maptool/model/LookupTable.java b/src/main/java/net/rptools/maptool/model/LookupTable.java index d8bfd89d9b..d14e86febe 100644 --- a/src/main/java/net/rptools/maptool/model/LookupTable.java +++ b/src/main/java/net/rptools/maptool/model/LookupTable.java @@ -34,7 +34,7 @@ public class LookupTable { private @Nonnull List entryList = new ArrayList<>(); private @Nullable String name; - private @Nullable String group; + private @Nonnull String group = ""; private @Nullable String defaultRoll; private @Nullable MD5Key tableImage; private @Nonnull Boolean visible = true; @@ -42,6 +42,7 @@ public class LookupTable { // Flags a table as Pick Once, i.e. each entry can only be chosen once before the // table must be reset(). private @Nonnull Boolean pickOnce = false; + private @Nonnull String metadata = ""; public static final String NO_PICKS_LEFT = "NO_PICKS_LEFT"; @@ -56,6 +57,7 @@ public LookupTable(LookupTable table) { visible = table.visible; allowLookup = table.allowLookup; entryList.addAll(table.entryList); + metadata = table.metadata; } public String getRoll() { @@ -100,10 +102,18 @@ public void setGroup(String group) { this.group = group; } - public String getGroup() { + public @Nonnull String getGroup() { return group; } + public void setMetadata(String metadata) { + this.metadata = metadata; + } + + public @Nonnull String getMetadata() { + return metadata; + } + /** * Finds the first entry that matches a given roll result. * @@ -513,6 +523,9 @@ private Object readResolve() { if (group == null) { group = ""; } + if (metadata == null) { + metadata = ""; + } return this; } @@ -545,6 +558,15 @@ public long getEntryValueCount() { .count(); } + /** + * Returns if the table has any metadata or not. + * + * @return true/false + */ + public boolean hasMetadata() { + return metadata != null && !metadata.isBlank(); + } + public static LookupTable fromDto(LookupTableDto dto) { var table = new LookupTable(); table.name = dto.hasName() ? dto.getName().getValue() : null; @@ -556,6 +578,7 @@ public static LookupTable fromDto(LookupTableDto dto) { table.setVisible(dto.getVisible()); table.setAllowLookup(dto.getAllowLookup()); table.setPickOnce(dto.getPickOnce()); + table.metadata = dto.hasMetadata() ? dto.getMetadata().getValue() : null; return table; } @@ -577,6 +600,9 @@ public LookupTableDto toDto() { dto.setVisible(visible); dto.setAllowLookup(allowLookup); dto.setPickOnce(pickOnce); + if (metadata != null) { + dto.setName(StringValue.of(metadata)); + } return dto.build(); } } diff --git a/src/main/resources/net/rptools/maptool/language/i18n.properties b/src/main/resources/net/rptools/maptool/language/i18n.properties index 7238536f94..b423fead7a 100644 --- a/src/main/resources/net/rptools/maptool/language/i18n.properties +++ b/src/main/resources/net/rptools/maptool/language/i18n.properties @@ -439,6 +439,8 @@ EditLookupTablePanel.showplayer = Show Table to Players EditLookupTablePanel.lookup = Allow Lookup by Players EditLookupTablePanel.pickOnce = Pick Once Table EditLookupTablePanel.resetPicks = Reset Picks +EditLookupTablePanel.tab.entries = Entries +EditLookupTablePanel.tab.metadata = Metadata EditTokenDialog.label.label = Label EditTokenDialog.menu.notes.sendChat = Send to Chat From 3f34cce4c0bf9da7ce9fa57a44a463c5a48c7e6c Mon Sep 17 00:00:00 2001 From: Baaaaaz <131240480+Baaaaaz@users.noreply.github.com> Date: Sat, 15 Aug 2026 11:39:20 +0100 Subject: [PATCH 4/5] add table metadata type --- .../main/proto/data_transfer_objects.proto | 1 + .../ui/lookuptable/EditLookupTablePanel.java | 28 +++++++++++--- .../lookuptable/EditLookupTablePanelView.form | 23 +++++++++++- .../lookuptable/EditLookupTablePanelView.java | 5 +++ .../LookupTableDetailsTablePanelModel.java | 12 +++--- .../rptools/maptool/model/LookupTable.java | 37 +++++++++++++++---- .../rptools/maptool/language/i18n.properties | 2 + 7 files changed, 86 insertions(+), 22 deletions(-) diff --git a/messages/src/main/proto/data_transfer_objects.proto b/messages/src/main/proto/data_transfer_objects.proto index 01330393a7..6d47b9572a 100644 --- a/messages/src/main/proto/data_transfer_objects.proto +++ b/messages/src/main/proto/data_transfer_objects.proto @@ -59,6 +59,7 @@ message LookupTableDto { bool pick_once = 7; google.protobuf.StringValue group = 8; google.protobuf.StringValue metadata = 9; + google.protobuf.StringValue metadata_type = 10; } message LookupEntryDto { diff --git a/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanel.java b/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanel.java index 8a1dfd9dd2..bfe27deecf 100644 --- a/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanel.java +++ b/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanel.java @@ -30,11 +30,7 @@ import java.util.List; import java.util.Objects; import javax.annotation.Nullable; -import javax.swing.BorderFactory; -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JTable; -import javax.swing.WindowConstants; +import javax.swing.*; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableCellRenderer; import net.rptools.lib.MD5Key; @@ -203,7 +199,7 @@ public void initMetadataSyntaxArea() { // configure the syntax text area RSyntaxTextArea rsta = view.getTableMetadata(); - rsta.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JSON); + rsta.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_NONE); rsta.setCodeFoldingEnabled(true); rsta.setEditable(true); rsta.setInsertPairedCharacters(false); @@ -225,6 +221,19 @@ public void initMetadataSyntaxArea() { } catch (IOException e) { System.err.println("Unable to load theme: " + themePath + " " + e); } + + JComboBox syntaxStyle = view.getTableMetadataType(); + syntaxStyle.addItem(SyntaxConstants.SYNTAX_STYLE_NONE); + syntaxStyle.addItem(SyntaxConstants.SYNTAX_STYLE_CSV); + syntaxStyle.addItem(SyntaxConstants.SYNTAX_STYLE_HTML); + syntaxStyle.addItem(SyntaxConstants.SYNTAX_STYLE_JSON); + syntaxStyle.addItem(SyntaxConstants.SYNTAX_STYLE_MARKDOWN); + syntaxStyle.addItem(SyntaxConstants.SYNTAX_STYLE_XML); + + syntaxStyle.addActionListener( + e -> { + rsta.setSyntaxEditingStyle((String) syntaxStyle.getSelectedItem()); + }); } /** @@ -264,6 +273,10 @@ public void bind(LookupTable lookupTable) { view.getResetPicks().setEnabled(lookupTable.getPickOnce()); view.getTableMetadata().setText(lookupTable.getMetadata()); + view.getTableMetadataType().setSelectedItem(lookupTable.getMetadataType()); + if (view.getTableMetadataType().getSelectedItem() == null) { + view.getTableMetadataType().setSelectedItem(SyntaxConstants.SYNTAX_STYLE_NONE); + } view.getTableName().requestFocusInWindow(); @@ -308,6 +321,8 @@ public boolean commit() { String group = selectedTableGroup == null ? "" : selectedTableGroup.toString(); String metadata = view.getTableMetadata().getText().trim(); + String metadataType = + Objects.requireNonNull(view.getTableMetadataType().getSelectedItem()).toString(); // Before modifying the table, parse and validate all the entries to avoid partial modification // in case of error. @@ -359,6 +374,7 @@ public boolean commit() { lookupTable.setVisible(view.getIsVisible().isSelected()); lookupTable.setAllowLookup(view.getAllowLookup().isSelected()); lookupTable.setMetadata(metadata); + lookupTable.setMetadataType(metadataType); lookupTable.clearEntries(); for (var entry : entries) { diff --git a/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanelView.form b/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanelView.form index a4b9e53c5b..8e9a8cd65a 100644 --- a/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanelView.form +++ b/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanelView.form @@ -211,7 +211,7 @@
- + @@ -221,7 +221,7 @@ - + @@ -234,6 +234,25 @@ + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanelView.java b/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanelView.java index 2d8f451731..674de5da74 100644 --- a/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanelView.java +++ b/src/main/java/net/rptools/maptool/client/ui/lookuptable/EditLookupTablePanelView.java @@ -35,6 +35,7 @@ public class EditLookupTablePanelView { private JLabel pickOnceIcon; private RSyntaxTextArea tableMetadata; private RTextScrollPane tableMetadataScrollPane; + private JComboBox tableMetadataType; public JComponent getRootComponent() { return mainPanel; @@ -95,4 +96,8 @@ public RSyntaxTextArea getTableMetadata() { public RTextScrollPane getTableMetadataScrollPane() { return tableMetadataScrollPane; } + + public JComboBox getTableMetadataType() { + return tableMetadataType; + } } diff --git a/src/main/java/net/rptools/maptool/client/ui/lookuptable/LookupTableDetailsTablePanelModel.java b/src/main/java/net/rptools/maptool/client/ui/lookuptable/LookupTableDetailsTablePanelModel.java index 3db35ace30..537eb0475f 100644 --- a/src/main/java/net/rptools/maptool/client/ui/lookuptable/LookupTableDetailsTablePanelModel.java +++ b/src/main/java/net/rptools/maptool/client/ui/lookuptable/LookupTableDetailsTablePanelModel.java @@ -100,7 +100,7 @@ Object getValue(LookupTable table) { }, GROUP( I18N.getText("Label.group"), - null, + I18N.getText("LookupTablePanel.group.tooltip"), String.class, SwingConstants.LEFT, 100, @@ -212,16 +212,16 @@ Object getValue(LookupTable table) { }, METADATA( I18N.getText("EditLookupTablePanel.tab.metadata"), + I18N.getText("LookupTablePanel.metadata.tooltip"), + String.class, + SwingConstants.LEFT, + 100, null, - Boolean.class, - SwingConstants.CENTER, - 80, null, - Icons.WINDOW_TABLES, null) { @Override Object getValue(LookupTable table) { - return table.hasMetadata(); + return table.hasMetadata() ? table.getMetadataType() : ""; } }; diff --git a/src/main/java/net/rptools/maptool/model/LookupTable.java b/src/main/java/net/rptools/maptool/model/LookupTable.java index d14e86febe..d97db7f1ba 100644 --- a/src/main/java/net/rptools/maptool/model/LookupTable.java +++ b/src/main/java/net/rptools/maptool/model/LookupTable.java @@ -27,6 +27,7 @@ import net.rptools.maptool.server.proto.LookupTableDto; import net.rptools.maptool.util.ExpressionParserFactory; import net.rptools.parser.ParserException; +import org.fife.ui.rsyntaxtextarea.SyntaxConstants; public class LookupTable { @@ -34,7 +35,7 @@ public class LookupTable { private @Nonnull List entryList = new ArrayList<>(); private @Nullable String name; - private @Nonnull String group = ""; + private @Nullable String group; private @Nullable String defaultRoll; private @Nullable MD5Key tableImage; private @Nonnull Boolean visible = true; @@ -42,7 +43,8 @@ public class LookupTable { // Flags a table as Pick Once, i.e. each entry can only be chosen once before the // table must be reset(). private @Nonnull Boolean pickOnce = false; - private @Nonnull String metadata = ""; + private @Nullable String metadata; + private @Nullable String metadataType; public static final String NO_PICKS_LEFT = "NO_PICKS_LEFT"; @@ -58,6 +60,7 @@ public LookupTable(LookupTable table) { allowLookup = table.allowLookup; entryList.addAll(table.entryList); metadata = table.metadata; + metadataType = table.metadataType; } public String getRoll() { @@ -98,20 +101,28 @@ public String getName() { return name; } - public void setGroup(String group) { + public void setGroup(@Nullable String group) { this.group = group; } - public @Nonnull String getGroup() { - return group; + public String getGroup() { + return group == null ? "" : group; } - public void setMetadata(String metadata) { + public void setMetadata(@Nullable String metadata) { this.metadata = metadata; } - public @Nonnull String getMetadata() { - return metadata; + public String getMetadata() { + return metadata == null ? "" : metadata; + } + + public void setMetadataType(@Nullable String metadataType) { + this.metadataType = metadataType; + } + + public @Nullable String getMetadataType() { + return metadataType == null ? SyntaxConstants.SYNTAX_STYLE_NONE : metadataType; } /** @@ -520,12 +531,18 @@ private Object readResolve() { if (entryList == null) { entryList = new ArrayList<>(); } + /* TODO B if (group == null) { group = ""; } if (metadata == null) { metadata = ""; } + if (metadata == null) { + metadata = SyntaxConstants.SYNTAX_STYLE_NONE; + } + */ + return this; } @@ -579,6 +596,7 @@ public static LookupTable fromDto(LookupTableDto dto) { table.setAllowLookup(dto.getAllowLookup()); table.setPickOnce(dto.getPickOnce()); table.metadata = dto.hasMetadata() ? dto.getMetadata().getValue() : null; + table.metadataType = dto.hasMetadataType() ? dto.getMetadataType().getValue() : null; return table; } @@ -603,6 +621,9 @@ public LookupTableDto toDto() { if (metadata != null) { dto.setName(StringValue.of(metadata)); } + if (metadataType != null) { + dto.setName(StringValue.of(metadataType)); + } return dto.build(); } } diff --git a/src/main/resources/net/rptools/maptool/language/i18n.properties b/src/main/resources/net/rptools/maptool/language/i18n.properties index b423fead7a..dd40e8753d 100644 --- a/src/main/resources/net/rptools/maptool/language/i18n.properties +++ b/src/main/resources/net/rptools/maptool/language/i18n.properties @@ -681,12 +681,14 @@ LookupTablePanel.error.saveFailed = Could not save table "{0}". LookupTablePanel.info.saved = Table saved as "{0}". LookupTablePanel.msg.titleEdit = Edit Table LookupTablePanel.msg.titleNew = New Table +LookupTablePanel.group.tooltip = Table group (optional). LookupTablePanel.countEntries = Entries LookupTablePanel.countEntries.tooltip = A count of the number of table entries. LookupTablePanel.countValues = Values LookupTablePanel.countValues.tooltip = A count of the number of table entries with values. LookupTablePanel.countImages = Images LookupTablePanel.countImages.tooltip = A count of the number of table entries with images. +LookupTablePanel.metadata.tooltip = The metadata type if the table has metadata. LookupTablePanel.viewIcons = Icons LookupTablePanel.viewDetails = Details LookupTablePanel.viewIcons.tooltip = Show an icon view of table images and name labels. From fc5c4c7e8dbad828efcda169c47ce4b4817236c1 Mon Sep 17 00:00:00 2001 From: Baaaaaz <131240480+Baaaaaz@users.noreply.github.com> Date: Sat, 15 Aug 2026 11:39:48 +0100 Subject: [PATCH 5/5] alter getTableNames to allow optional group filtering --- .../client/functions/LookupTableFunction.java | 40 ++++++++++++------- .../rptools/maptool/model/LookupTable.java | 12 ------ 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/main/java/net/rptools/maptool/client/functions/LookupTableFunction.java b/src/main/java/net/rptools/maptool/client/functions/LookupTableFunction.java index 53f20e5155..1b05480e7e 100644 --- a/src/main/java/net/rptools/maptool/client/functions/LookupTableFunction.java +++ b/src/main/java/net/rptools/maptool/client/functions/LookupTableFunction.java @@ -46,6 +46,7 @@ public LookupTableFunction() { "tblImage", "tableImage", "getTableNames", + "getTableGroups", "getTableRoll", "setTableRoll", "clearTable", @@ -71,7 +72,6 @@ public LookupTableFunction() { "getTablePicksLeft", "getTableGroup", "setTableGroup", - "getTableGroups", "getTableMetadata", "setTableMetadata"); } @@ -94,18 +94,25 @@ public Object childEvaluate( throws ParserException { if ("getTableNames".equalsIgnoreCase(function)) { - - FunctionUtil.checkNumberParam("getTableNames", params, 0, 1); + /* + getTableNames(delim) - get all/visible table names + getTableNames(delim, group) - get all/visible table names in a named group + */ + FunctionUtil.checkNumberParam("getTableNames", params, 0, 2); String delim = ","; + String group = null; if (params.size() > 0) { delim = params.get(0).toString(); } + if (params.size() > 1) { + group = params.get(1).toString(); + } if ("json".equalsIgnoreCase(delim)) { JsonArray jsonArray = new JsonArray(); - getTableList(MapTool.getPlayer().isGM()).forEach(jsonArray::add); + getTableList(MapTool.getPlayer().isGM(), group).forEach(jsonArray::add); return jsonArray; } - return StringUtils.join(getTableList(MapTool.getPlayer().isGM()), delim); + return StringUtils.join(getTableList(MapTool.getPlayer().isGM(), group), delim); } else if ("getTableGroups".equalsIgnoreCase(function)) { @@ -500,7 +507,7 @@ public Object childEvaluate( } else if ("setTableGroup".equalsIgnoreCase(function)) { /* - * getTableGroup(tblName, group) - set the named table's group + * setTableGroup(tblName, group) - set the named table's group */ checkTrusted(function); FunctionUtil.checkNumberParam("setTableGroup", params, 2, 2); @@ -636,18 +643,23 @@ private void processMutatedLookupTable(LookupTable lookupTable, boolean dataOnly } /** - * * If GM return all tables Otherwise only return visible tables + * * If GM return all tables otherwise only return visible tables, optionally filtered by table + * group * - * @param isGm boolean Does the calling function has GM privileges + * @param isGm boolean Does the calling function has GM privilege + * @param group String Only return tables in the group * @return a list of table names */ - private List getTableList(boolean isGm) { + private List getTableList(boolean isGm, String group) { List tables = new ArrayList<>(); - if (isGm) tables.addAll(MapTool.getCampaign().getLookupTableMap().keySet()); - else - MapTool.getCampaign().getLookupTableMap().values().stream() - .filter(LookupTable::getVisible) - .forEachOrdered((lt) -> tables.add(lt.getName())); + var stream = MapTool.getCampaign().getLookupTableMap().values().stream(); + if (!isGm) { + stream = stream.filter(LookupTable::getVisible); + } + if (group != null) { + stream = stream.filter(lt -> lt.getGroup().equals(group)); + } + stream.forEachOrdered((lt) -> tables.add(lt.getName())); return tables; } diff --git a/src/main/java/net/rptools/maptool/model/LookupTable.java b/src/main/java/net/rptools/maptool/model/LookupTable.java index d97db7f1ba..942835c908 100644 --- a/src/main/java/net/rptools/maptool/model/LookupTable.java +++ b/src/main/java/net/rptools/maptool/model/LookupTable.java @@ -531,18 +531,6 @@ private Object readResolve() { if (entryList == null) { entryList = new ArrayList<>(); } - /* TODO B - if (group == null) { - group = ""; - } - if (metadata == null) { - metadata = ""; - } - if (metadata == null) { - metadata = SyntaxConstants.SYNTAX_STYLE_NONE; - } - */ - return this; }