diff --git a/src/main/java/net/rptools/lib/FileUtil.java b/src/main/java/net/rptools/lib/FileUtil.java index c6901bf890..60f8d19386 100644 --- a/src/main/java/net/rptools/lib/FileUtil.java +++ b/src/main/java/net/rptools/lib/FileUtil.java @@ -26,7 +26,6 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; -import java.io.Reader; import java.net.MalformedURLException; import java.net.URISyntaxException; import java.net.URL; @@ -211,7 +210,7 @@ public static String getContentType(InputStream in) { String type = ""; try { type = URLConnection.guessContentTypeFromStream(in); - if (log.isDebugEnabled()) log.debug("result from guessContentTypeFromStream() is " + type); + log.debug("result from guessContentTypeFromStream() is {}", type); } catch (IOException e) { } return type; @@ -227,8 +226,7 @@ public static String getContentType(InputStream in) { public static String getContentType(URL url) { String type = ""; type = URLConnection.guessContentTypeFromName(url.getPath()); - if (log.isDebugEnabled()) - log.debug("result from guessContentTypeFromName(" + url.getPath() + ") is " + type); + log.debug("result from guessContentTypeFromName({}) is {}", url.getPath(), type); return type; } @@ -260,30 +258,6 @@ public static BufferedReader getFileAsReader(File file) throws IOException { new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8)); } - /** - * Given a URL this method determines the content type of the URL (if possible) and then returns a - * Reader with the appropriate character encoding. - * - * @param url the source of the data stream - * @return String representing the data - * @throws IOException in case of an I/O error - */ - public static Reader getURLAsReader(URL url) throws IOException { - InputStreamReader isr = null; - URLConnection conn = null; - // We're assuming character here, but it could be bytes. Perhaps we should - // check the MIME type returned by the network server? - conn = url.openConnection(); - if (log.isDebugEnabled()) { - String type = URLConnection.guessContentTypeFromName(url.getPath()); - log.debug("result from guessContentTypeFromName(" + url.getPath() + ") is " + type); - type = getContentType(conn.getInputStream()); - // Now make a guess and change 'encoding' to match the content type... - } - isr = new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8); - return isr; - } - public static InputStream getFileAsInputStream(File file) throws IOException { return getURLAsInputStream(file.toURI().toURL()); } diff --git a/src/main/java/net/rptools/lib/io/PackedFile.java b/src/main/java/net/rptools/lib/io/PackedFile.java index 2f54f7f446..12604252f1 100644 --- a/src/main/java/net/rptools/lib/io/PackedFile.java +++ b/src/main/java/net/rptools/lib/io/PackedFile.java @@ -52,6 +52,8 @@ import net.rptools.lib.CodeTimer; import net.rptools.lib.FileUtil; import net.rptools.lib.ModelVersionManager; +import net.rptools.maptool.client.AppState; +import net.rptools.maptool.client.MapTool; import net.rptools.maptool.model.Asset; import net.rptools.maptool.model.AssetManager; import net.rptools.maptool.model.GUID; @@ -290,7 +292,7 @@ public void save() throws IOException { return; } saveTimer = new CodeTimer("PackedFile.save"); - saveTimer.setEnabled(log.isDebugEnabled()); + saveTimer.setEnabled(AppState.isCollectProfilingData()); // Create the new file File newFile = new File(tmpDir, new GUID() + ".pak"); @@ -402,8 +404,9 @@ public void save() throws IOException { IOUtils.closeQuietly(zout); saveTimer.stop("cleanup"); - if (log.isDebugEnabled()) log.debug(saveTimer); - saveTimer = null; + if (saveTimer.isEnabled()) { + MapTool.getProfilingNoteFrame().addText(saveTimer.toString()); + } } } @@ -729,8 +732,7 @@ public InputStream getFileAsInputStream(String path) throws IOException { InputStream in = zipFile.getInputStream(entry); if (in == null) throw new FileNotFoundException(path); String type = FileUtil.getContentType(in); - if (log.isDebugEnabled() && type != null) - log.debug("FileUtil.getContentType() returned " + type); + log.debug("FileUtil.getContentType() returned {}", type); return in; } diff --git a/src/main/java/net/rptools/maptool/client/AppPreferences.java b/src/main/java/net/rptools/maptool/client/AppPreferences.java index 3404da5bf5..6f5f2dc64e 100644 --- a/src/main/java/net/rptools/maptool/client/AppPreferences.java +++ b/src/main/java/net/rptools/maptool/client/AppPreferences.java @@ -1231,9 +1231,7 @@ public static void setMruCampaigns(List mruCampaigns) { path = file.getCanonicalPath(); } catch (IOException e) { // Probably pretty rare, but we want to know about it - if (log.isInfoEnabled()) { - log.info("unexpected during file.getCanonicalPath()", e); // $NON-NLS-1$ - } + log.info("unexpected during file.getCanonicalPath()", e); // $NON-NLS-1$ path = file.getPath(); } // It's important that '%3A' is done last. Note that the pathSeparator may not be a colon on diff --git a/src/main/java/net/rptools/maptool/client/AppUtil.java b/src/main/java/net/rptools/maptool/client/AppUtil.java index 3cace9d1c2..1fcbd9b790 100644 --- a/src/main/java/net/rptools/maptool/client/AppUtil.java +++ b/src/main/java/net/rptools/maptool/client/AppUtil.java @@ -124,7 +124,7 @@ public static File getAppHome(String subdir) { RuntimeException re = new RuntimeException( I18N.getText("msg.error.unableToCreateDataDir", path.getAbsolutePath())); - if (log != null && log.isInfoEnabled()) { + if (log != null) { log.info("msg.error.unableToCreateDataDir", re); } throw re; diff --git a/src/main/java/net/rptools/maptool/client/AutoSaveManager.java b/src/main/java/net/rptools/maptool/client/AutoSaveManager.java index b93b7ed37f..42ecf17587 100644 --- a/src/main/java/net/rptools/maptool/client/AutoSaveManager.java +++ b/src/main/java/net/rptools/maptool/client/AutoSaveManager.java @@ -48,8 +48,7 @@ public void start() { if (autoSaveTimer == null) { autoSaveTimer = new Timer(1000, (Object) -> execute()); autoSaveTimer.setRepeats(false); - if (log.isDebugEnabled()) - log.debug("Logging level of 'DEBUG' sets timeout to seconds"); // $NON-NLS-1$ + log.debug("Logging level of 'DEBUG' sets timeout to seconds"); // $NON-NLS-1$ next(true); } } @@ -66,7 +65,9 @@ private void execute() { private boolean executeAndContinue() { int interval = - AppPreferences.getAutoSaveIncrement() * (log.isDebugEnabled() ? 1000 : 60 * 1000); + AppPreferences.getAutoSaveIncrement() + * 1000 + * (DeveloperOptions.Toggle.AutoSaveMeasuredInSeconds.isEnabled() ? 1 : 60); // auto-save is turned off with <= 0 if (interval <= 0) { diff --git a/src/main/java/net/rptools/maptool/client/ChatAutoSave.java b/src/main/java/net/rptools/maptool/client/ChatAutoSave.java index 60e632cd3f..fe40fe5d9b 100644 --- a/src/main/java/net/rptools/maptool/client/ChatAutoSave.java +++ b/src/main/java/net/rptools/maptool/client/ChatAutoSave.java @@ -49,8 +49,7 @@ private static TimerTask createTimer(final long timeout) { new TimerTask() { @Override public void run() { - if (log.isDebugEnabled()) - log.debug("Chat log autosave countdown complete from " + timeout); // $NON-NLS-1$ + log.debug("Chat log autosave countdown complete from {}", timeout); // $NON-NLS-1$ if (chatlog == null) { String filename = AppPreferences.getChatFilenameFormat(); // FJE Ugly kludge to replace older default entry with newer default @@ -63,8 +62,7 @@ public void run() { } File chatFile = new File(AppUtil.getAppHome("autosave").toString(), chatlog); // $NON-NLS-1$ - if (log.isInfoEnabled()) - log.info("Saving log to '" + chatFile + "'"); // $NON-NLS-1$ //$NON-NLS-2$ + log.info("Saving log to '{}'", chatFile); // $NON-NLS-1$ //$NON-NLS-2$ CommandPanel chat = MapTool.getFrame().getCommandPanel(); String old = MapTool.getFrame().getStatusMessage(); @@ -75,7 +73,7 @@ public void run() { try (FileWriter writer = new FileWriter(chatFile)) { writer.write(chat.getMessageHistory()); } - if (log.isInfoEnabled()) log.info("Log saved"); // $NON-NLS-1$ + log.info("Log saved"); // $NON-NLS-1$ } catch (IOException e) { // If this happens should we track it and turn off the autosave? Perhaps // after a certain number of consecutive failures? Or maybe just lengthen diff --git a/src/main/java/net/rptools/maptool/client/ClientMessageHandler.java b/src/main/java/net/rptools/maptool/client/ClientMessageHandler.java index 980633e624..360ad9631f 100644 --- a/src/main/java/net/rptools/maptool/client/ClientMessageHandler.java +++ b/src/main/java/net/rptools/maptool/client/ClientMessageHandler.java @@ -90,7 +90,7 @@ public void handleMessage(String id, byte[] message) { try { var msg = Message.parseFrom(message); var msgType = msg.getMessageTypeCase(); - log.info(id + " got: " + msgType); + log.debug(id + " got: " + msgType); switch (msgType) { case ADD_TOPOLOGY_MSG -> handle(msg.getAddTopologyMsg()); @@ -163,7 +163,7 @@ public void handleMessage(String id, byte[] message) { case UPDATE_PLAYER_STATUS_MSG -> handle(msg.getUpdatePlayerStatusMsg()); default -> log.warn(msgType + "not handled."); } - log.info(id + " handled: " + msgType); + log.debug(id + " handled: " + msgType); } catch (Exception e) { log.error(e); } @@ -1020,7 +1020,7 @@ private void handle(UpdatePlayerStatusMsg updatePlayerStatusMsg) { .orElse(null); if (player == null) { - log.info("UpdatePlayerStatusMsg failed. No player with name: '" + playerName + "'"); + log.warn("UpdatePlayerStatusMsg failed. No player with name: '" + playerName + "'"); return; } diff --git a/src/main/java/net/rptools/maptool/client/DeveloperOptions.java b/src/main/java/net/rptools/maptool/client/DeveloperOptions.java new file mode 100644 index 0000000000..ec695af7dc --- /dev/null +++ b/src/main/java/net/rptools/maptool/client/DeveloperOptions.java @@ -0,0 +1,79 @@ +/* + * This software Copyright by the RPTools.net development team, and + * licensed under the Affero GPL Version 3 or, at your option, any later + * version. + * + * MapTool Source Code is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public + * License * along with this source Code. If not, please visit + * and specifically the Affero license + * text at . + */ +package net.rptools.maptool.client; + +import java.util.Arrays; +import java.util.List; +import java.util.prefs.Preferences; +import net.rptools.maptool.language.I18N; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class DeveloperOptions { + private static final Logger log = LogManager.getLogger(DeveloperOptions.class); + private static final Preferences prefs = + Preferences.userRoot().node(AppConstants.APP_NAME + "/prefs"); + + public enum Toggle { + /** + * When enabled, make auto-save 60x more frequent by interpreting the user-provided value as + * seconds instead of minutes. + */ + AutoSaveMeasuredInSeconds("autoSaveMeasuredInSeconds"), + + /** When enabled, draw boundaries around each partition. */ + ShowPartitionDrawableBoundaries("showPartitionDrawableBoundaries"), + + /** + * When enabled, shows F, G, H scores for each cell encountered during pathfinding, as well as + * blocked moved. + */ + ShowAiDebugging("showAiDebugging"), + + /** When enabled, recalculates the grid shape each time it is needed. */ + IgnoreGridShapeCache("ignoreGridShapeCache"), + ; + + private final String key; + + Toggle(String key) { + this.key = key; + } + + public String getKey() { + return key; + } + + public boolean isEnabled() { + return prefs.getBoolean(key, true); + } + + public void setEnabled(boolean enabled) { + prefs.putBoolean(key, enabled); + } + + public String getLabel() { + return I18N.getText(String.format("Preferences.developer.%s.label", key)); + } + + public String getTooltip() { + return I18N.getText(String.format("Preferences.developer.%s.tooltip", key)); + } + } + + public static List getEnabledOptions() { + return Arrays.stream(Toggle.values()).filter(Toggle::isEnabled).toList(); + } +} diff --git a/src/main/java/net/rptools/maptool/client/MapTool.java b/src/main/java/net/rptools/maptool/client/MapTool.java index 7f963d1d3d..81668228d2 100644 --- a/src/main/java/net/rptools/maptool/client/MapTool.java +++ b/src/main/java/net/rptools/maptool/client/MapTool.java @@ -1376,6 +1376,29 @@ private static void postInitialize() { .getCurrentZoneRenderer() .getZone() .setTopologyTypes(AppPreferences.getTopologyTypes()); + + final var enabledDeveloperOptions = DeveloperOptions.getEnabledOptions(); + if (!enabledDeveloperOptions.isEmpty()) { + final var message = new StringBuilder(); + message + .append("

") + .append(I18N.getText("Preferences.developer.info.developerOptionsInUse")) + .append("

    "); + for (final var option : enabledDeveloperOptions) { + message.append("
  • ").append(option.getLabel()).append("
  • "); + } + message + .append("

") + .append( + I18N.getText( + "Preferences.developer.info.developerOptionsInUsePost", + I18N.getText("menu.edit"), + I18N.getText("action.preferences"), + I18N.getText("Preferences.tab.developer"))) + .append("

"); + + showWarning(message.toString()); + } } /** diff --git a/src/main/java/net/rptools/maptool/client/MapToolConnection.java b/src/main/java/net/rptools/maptool/client/MapToolConnection.java index 121f21c5da..2acc40f63e 100644 --- a/src/main/java/net/rptools/maptool/client/MapToolConnection.java +++ b/src/main/java/net/rptools/maptool/client/MapToolConnection.java @@ -14,8 +14,6 @@ */ package net.rptools.maptool.client; -import static net.rptools.maptool.server.proto.Message.MessageTypeCase.HEARTBEAT_MSG; - import java.io.IOException; import java.util.concurrent.ExecutionException; import net.rptools.clientserver.ConnectionFactory; @@ -102,13 +100,7 @@ public void close() throws IOException { } public void sendMessage(Message msg) { - var msgType = msg.getMessageTypeCase(); - var logText = player.getName() + " sent " + msg.getMessageTypeCase(); - if (msgType == HEARTBEAT_MSG) { - log.debug(logText); - } else { - log.info(logText); - } + log.debug(player.getName() + " sent " + msg.getMessageTypeCase()); connection.sendMessage(msg.toByteArray()); } } diff --git a/src/main/java/net/rptools/maptool/client/TransferableHelper.java b/src/main/java/net/rptools/maptool/client/TransferableHelper.java index 9def5c1867..67fc96d255 100644 --- a/src/main/java/net/rptools/maptool/client/TransferableHelper.java +++ b/src/main/java/net/rptools/maptool/client/TransferableHelper.java @@ -191,11 +191,11 @@ public static List getAsset(Transferable transferable) { // EXISTING ASSET if (transferable.isDataFlavorSupported(TransferableAsset.dataFlavor)) { - if (log.isInfoEnabled()) log.info("Selected: " + TransferableAsset.dataFlavor); + log.info("Selected: {}", TransferableAsset.dataFlavor); o = handleTransferableAsset(transferable); } if (o == null && transferable.isDataFlavorSupported(TransferableAssetReference.dataFlavor)) { - if (log.isInfoEnabled()) log.info("Selected: " + TransferableAssetReference.dataFlavor); + log.info("Selected: {}", TransferableAssetReference.dataFlavor); o = handleTransferableAssetReference(transferable); } @@ -227,7 +227,7 @@ public static List getAsset(Transferable transferable) { // "text/x-java-file-list", but // until it does... if (o == null && transferable.isDataFlavorSupported(URI_LIST_FLAVOR)) { - if (log.isInfoEnabled()) log.info("Selected: " + URI_LIST_FLAVOR); + log.info("Selected: {}", URI_LIST_FLAVOR); String data = (String) transferable.getTransferData(URI_LIST_FLAVOR); List list = textURIListToFileList(data); if (!list.isEmpty()) { @@ -240,7 +240,7 @@ public static List getAsset(Transferable transferable) { // Used by OSX (and Windows?) when files are dragged from the desktop: 'text/java-file-list; // java.util.List' if (o == null && transferable.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) { - if (log.isInfoEnabled()) log.info("Selected: " + DataFlavor.javaFileListFlavor); + log.info("Selected: {}", DataFlavor.javaFileListFlavor); List list = new FileTransferableHandler().getTransferObject(transferable); if (!list.isEmpty()) { List urls = handleURLList(list); @@ -251,7 +251,7 @@ public static List getAsset(Transferable transferable) { // DIRECT/BROWSER // Try 'image/x-java-image; java.awt.Image' to see if Java has recognized the image as such if (o == null && transferable.isDataFlavorSupported(X_JAVA_IMAGE)) { - if (log.isInfoEnabled()) log.info("Selected: " + X_JAVA_IMAGE); + log.info("Selected: {}", X_JAVA_IMAGE); BufferedImage image = (BufferedImage) new ImageTransferableHandler().getTransferObject(transferable); o = Asset.createImageAsset("unnamed", ImageUtil.imageToBytes(image)); @@ -260,7 +260,7 @@ public static List getAsset(Transferable transferable) { // DIRECT/BROWSER // Try 'application/x-java-url; java.net.URL' if (o == null && transferable.isDataFlavorSupported(URL_FLAVOR_URI)) { - if (log.isInfoEnabled()) log.info("Selected: " + URL_FLAVOR_URI); + log.info("Selected: {}", URL_FLAVOR_URI); URL url = (URL) transferable.getTransferData(URL_FLAVOR_URI); o = handleImage(url, "URL_FLAVOR_URI", transferable); } @@ -270,7 +270,7 @@ public static List getAsset(Transferable transferable) { // are better than // other file types... if (o == null && transferable.isDataFlavorSupported(URL_FLAVOR_PLAIN)) { - if (log.isInfoEnabled()) log.info("Selected: " + URL_FLAVOR_PLAIN); + log.info("Selected: {}", URL_FLAVOR_PLAIN); String text = (String) transferable.getTransferData(URL_FLAVOR_PLAIN); URL url = new URL(text); o = handleImage(url, "URL_FLAVOR_PLAIN", transferable); @@ -316,7 +316,7 @@ private static List textURIListToFileList(String data) { list.add(url); } catch (Exception e) { // There's no reason to trap the individual exceptions when a single catch suffices. - if (log.isInfoEnabled()) log.info(s, e); + log.info(s, e); // } catch (URISyntaxException e) { // Thrown by the URI constructor // e.printStackTrace(); // } catch (IllegalArgumentException e) { // Thrown by URI.toURL() @@ -333,16 +333,15 @@ private static Asset handleImage(URL url, String type, Transferable transferable BufferedImage image = null; Asset asset = null; try { - if (log.isDebugEnabled()) log.debug("Reading URL: " + url); // $NON-NLS-1$ + log.debug("Reading URL: {}", url); // $NON-NLS-1$ image = ImageIO.read(url); } catch (Exception e) { MapTool.showError("TransferableHelper.error.urlFlavor", e); // $NON-NLS-1$ } if (image == null) { - if (log.isDebugEnabled()) - log.debug( - type - + " didn't work; trying ImageTransferableHandler().getTransferObject()"); // $NON-NLS-1$ + log.debug( + "{} didn't work; trying ImageTransferableHandler().getTransferObject()", + type); // $NON-NLS-1$ image = (BufferedImage) new ImageTransferableHandler().getTransferObject(transferable); } if (image != null) { @@ -413,8 +412,8 @@ private static List handleURLList(List list) throws Exception { Asset temp = AssetManager.createAsset(url, Type.MTLIB); if (temp != null) { // `null' means no image available assets.add(temp); - } else if (log.isInfoEnabled()) { - log.info("Invalid MTLib for " + url); + } else { + log.info("Invalid MTLib for {}", url); } } else { // Get the MediaType so we can use it when creating the Asset later @@ -428,8 +427,8 @@ private static List handleURLList(List list) throws Exception { Asset temp = AssetManager.createAsset(url); if (temp != null) { // `null' means no image available assets.add(temp); - } else if (log.isInfoEnabled()) { - log.info("No image available for " + url); + } else { + log.info("No image available for {}", url); } } } @@ -549,6 +548,7 @@ public boolean canImport(JComponent comp, DataFlavor[] transferFlavors) { * @param t Transferable to check * @return a list of all DataFlavor objects that succeeded */ + // TODO The result is always ignored, this method is just used for informational logging now. private static List whichOnesWork(Transferable t) { List worked = new ArrayList(); @@ -565,9 +565,9 @@ private static List whichOnesWork(Transferable t) { try { result = t.getTransferData(flavor); } catch (UnsupportedFlavorException ufe) { - if (log.isDebugEnabled()) log.debug("Failed (UFE): " + flavor.toString()); // $NON-NLS-1$ + log.debug("Failed (UFE): {}", flavor.toString()); // $NON-NLS-1$ } catch (IOException ioe) { - if (log.isDebugEnabled()) log.debug("Failed (IOE): " + flavor.toString()); // $NON-NLS-1$ + log.debug("Failed (IOE): {}", flavor.toString()); // $NON-NLS-1$ } catch (Exception e) { // System.err.println(e); } @@ -575,8 +575,7 @@ private static List whichOnesWork(Transferable t) { for (Class type : validTypes) { if (type.equals(result.getClass())) { worked.add(flavor); - if (log.isInfoEnabled()) - log.info("Possible: " + flavor.toString() + " (" + result + ")"); // $NON-NLS-1$ + log.info("Possible: {} ({})", flavor, result); // $NON-NLS-1$ break; } } diff --git a/src/main/java/net/rptools/maptool/client/tool/PointerTool.java b/src/main/java/net/rptools/maptool/client/tool/PointerTool.java index c1d412e588..8c1481505b 100644 --- a/src/main/java/net/rptools/maptool/client/tool/PointerTool.java +++ b/src/main/java/net/rptools/maptool/client/tool/PointerTool.java @@ -1721,7 +1721,7 @@ public void paintOverlay(Graphics2D g) { LinkedList lineLayouts = new LinkedList(); if (AppPreferences.getShowStatSheet()) { CodeTimer timer = new CodeTimer("statSheet"); - timer.setEnabled(AppState.isCollectProfilingData() || log.isDebugEnabled()); + timer.setEnabled(AppState.isCollectProfilingData()); timer.setThreshold(5); timer.start("allProps"); for (TokenProperty property : @@ -1749,10 +1749,9 @@ public void paintOverlay(Graphics2D g) { } } timer.stop("allProps"); - if (AppState.isCollectProfilingData() || log.isDebugEnabled()) { + if (timer.isEnabled()) { String results = timer.toString(); MapTool.getProfilingNoteFrame().addText(results); - if (log.isDebugEnabled()) log.debug(results); } } if (tokenUnderMouse.getPortraitImage() != null || !propertyMap.isEmpty()) { diff --git a/src/main/java/net/rptools/maptool/client/tool/drawing/UndoPerZone.java b/src/main/java/net/rptools/maptool/client/tool/drawing/UndoPerZone.java index 7cf79db973..41c64f384e 100644 --- a/src/main/java/net/rptools/maptool/client/tool/drawing/UndoPerZone.java +++ b/src/main/java/net/rptools/maptool/client/tool/drawing/UndoPerZone.java @@ -73,7 +73,9 @@ protected UndoPerZone(UndoPerZone upz) throws IllegalArgumentException { } private void checkZone() { - if (zone == null && log.isDebugEnabled()) log.debug("zone == null (!)"); + if (zone == null) { + log.debug("zone == null (!)"); + } } /** @@ -84,8 +86,7 @@ private void checkZone() { */ public void addDrawable(Pen pen, Drawable drawable) { checkZone(); - if (log.isDebugEnabled()) - log.debug("drawable " + drawable + " being added to zone " + zone.getName()); + log.debug("drawable {} being added to zone {}", drawable, zone.getName()); manager.addEdit(new DrawableUndoableEdit(pen, drawable)); net.rptools.maptool.client.AppActions.UNDO_PER_MAP.isAvailable(); net.rptools.maptool.client.AppActions.REDO_PER_MAP.isAvailable(); @@ -103,10 +104,10 @@ public boolean canRedo() { public void undo() { checkZone(); if (!canUndo()) { - if (log.isDebugEnabled()) log.debug("Can't undo from zone " + zone.getName()); + log.debug("Can't undo from zone {}", zone.getName()); return; } - if (log.isDebugEnabled()) log.debug("Undoing last change on zone " + zone.getName()); + log.debug("Undoing last change on zone {}", zone.getName()); manager.undo(); } @@ -114,10 +115,10 @@ public void undo() { public void redo() { checkZone(); if (!canRedo()) { - if (log.isDebugEnabled()) log.debug("Can't redo from zone " + zone.getName()); + log.debug("Can't redo from zone {}", zone.getName()); return; } - if (log.isDebugEnabled()) log.debug("Redoing next change on zone " + zone.getName()); + log.debug("Redoing next change on zone {}", zone.getName()); manager.redo(); } diff --git a/src/main/java/net/rptools/maptool/client/ui/MapToolDockListener.java b/src/main/java/net/rptools/maptool/client/ui/MapToolDockListener.java index ecba6f49c0..86d18c4858 100644 --- a/src/main/java/net/rptools/maptool/client/ui/MapToolDockListener.java +++ b/src/main/java/net/rptools/maptool/client/ui/MapToolDockListener.java @@ -121,6 +121,6 @@ private void updatePanels(String panel) { * @param dfeId the DockableFrameEvent to record */ private void showEvent(String dfeId) { - if (log.isTraceEnabled()) log.trace(dfeId); + log.trace(dfeId); } } diff --git a/src/main/java/net/rptools/maptool/client/ui/MapToolFrame.java b/src/main/java/net/rptools/maptool/client/ui/MapToolFrame.java index f2bc9129ee..c1c61ffaf6 100644 --- a/src/main/java/net/rptools/maptool/client/ui/MapToolFrame.java +++ b/src/main/java/net/rptools/maptool/client/ui/MapToolFrame.java @@ -1968,11 +1968,9 @@ public void windowDeactivated(WindowEvent e) {} private void removeWindowsF10() { InputMap imap = menuBar.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); Object action = imap.get(KeyStroke.getKeyStroke("F10")); - if (log.isInfoEnabled()) - log.info( - "Removing the F10 key from the menuBar's InputMap; it did " - + (action == null ? "not" : "") - + " exist"); + log.info( + "Removing the F10 key from the menuBar's InputMap; it {} exist", + (action == null ? "did not" : "did")); ActionMap amap = menuBar.getActionMap(); amap.getParent().remove(action); } @@ -2028,8 +2026,7 @@ private void updateKeyStrokes(JComponent c) { // We're looking for MacroButton here, but we're adding AbstractActions below... Is this // right? XXX if (o instanceof MacroButton) { - if (log.isDebugEnabled()) - log.debug("Removing MacroButton " + ((MacroButton) o).getButtonText()); + log.debug("Removing MacroButton {}", ((MacroButton) o).getButtonText()); c.getActionMap().remove(o); } } diff --git a/src/main/java/net/rptools/maptool/client/ui/htmlframe/HTMLPane.java b/src/main/java/net/rptools/maptool/client/ui/htmlframe/HTMLPane.java index 91933481b1..525ce96886 100644 --- a/src/main/java/net/rptools/maptool/client/ui/htmlframe/HTMLPane.java +++ b/src/main/java/net/rptools/maptool/client/ui/htmlframe/HTMLPane.java @@ -67,13 +67,7 @@ public HTMLPane() { addHyperlinkListener( e -> { - if (log.isDebugEnabled()) { - log.debug( - "Responding to hyperlink event: " - + e.getEventType().toString() - + " " - + e.toString()); - } + log.debug("Responding to hyperlink event: {} {}", e.getEventType(), e); if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { if (e.getURL() != null) { MapTool.showDocument(e.getURL().toString()); @@ -149,10 +143,7 @@ public void flush() { */ public void doSubmit(String method, String action, String data) { if (actionListeners != null) { - if (log.isDebugEnabled()) { - log.debug( - "submit event: method='" + method + "' action='" + action + "' data='" + data + "'"); - } + log.debug("submit event: method='{}' action='{}' data='{}'", method, action, data); actionListeners.actionPerformed( new HTMLActionEvent.FormActionEvent(this, method, action, data)); } @@ -165,9 +156,7 @@ public void doSubmit(String method, String action, String data) { */ private void doChangeTitle(String title) { if (actionListeners != null) { - if (log.isDebugEnabled()) { - log.debug("changeTitle event: " + title); - } + log.debug("changeTitle event: {}", title); actionListeners.actionPerformed(new HTMLActionEvent.ChangeTitleActionEvent(this, title)); } } @@ -180,9 +169,7 @@ private void doChangeTitle(String title) { */ private void doRegisterMacro(String type, String link) { if (actionListeners != null) { - if (log.isDebugEnabled()) { - log.debug("registerMacro event: type='" + type + "' link='" + link + "'"); - } + log.debug("registerMacro event: type='{}' link='{}'", type, link); actionListeners.actionPerformed( new HTMLActionEvent.RegisterMacroActionEvent(this, type, link)); } @@ -196,9 +183,7 @@ private void doRegisterMacro(String type, String link) { */ private void handleMetaTag(String name, String content) { if (actionListeners != null) { - if (log.isDebugEnabled()) { - log.debug("metaTag found: name='" + name + "' content='" + content + "'"); - } + log.debug("metaTag found: name='{}' content='{}'", name, content); actionListeners.actionPerformed(new HTMLActionEvent.MetaTagActionEvent(this, name, content)); } } @@ -232,9 +217,7 @@ public void setText(String text) { } catch (IOException e) { // Do nothing, we should not get an io exception on string } - if (log.isDebugEnabled()) { - log.debug("setting text in HTMLPane: " + text); - } + log.debug("setting text in HTMLPane: {}", text); super.setText(HTMLPanelInterface.fixHTML(text)); } @@ -275,9 +258,7 @@ public void handleSimpleTag(HTML.Tag tag, MutableAttributeSet attributes, int po @Override public void handleError(String errorMsg, int pos) { - if (log.isTraceEnabled()) { - log.trace("handleError called in client.ui.htmlframe.HTMLPane.ParserCallBack: " + errorMsg); - } + log.trace("handleError called in client.ui.htmlframe.HTMLPane.ParserCallBack: {}", errorMsg); } /** diff --git a/src/main/java/net/rptools/maptool/client/ui/htmlframe/HTMLWebViewManager.java b/src/main/java/net/rptools/maptool/client/ui/htmlframe/HTMLWebViewManager.java index 182f5654cf..504eccc587 100644 --- a/src/main/java/net/rptools/maptool/client/ui/htmlframe/HTMLWebViewManager.java +++ b/src/main/java/net/rptools/maptool/client/ui/htmlframe/HTMLWebViewManager.java @@ -299,9 +299,7 @@ public void flush() { } public void updateContents(final String html, boolean scrollReset) { - if (log.isDebugEnabled()) { - log.debug("setting text in WebView: " + html); - } + log.debug("setting text in WebView: {}", html); this.scrollReset = scrollReset; // If the WebView has been flushed, the scrolling has already been stored if (!scrollReset && !isFlushed) { @@ -467,9 +465,7 @@ void handlePage() { */ private void doRegisterMacro(String type, String link) { if (actionListeners != null) { - if (log.isDebugEnabled()) { - log.debug("registerMacro event: type='" + type + "' link='" + link + "'"); - } + log.debug("registerMacro event: type='{}' link='{}'", type, link); actionListeners.actionPerformed( new HTMLActionEvent.RegisterMacroActionEvent(this, type, link)); } @@ -556,9 +552,7 @@ private boolean webViewHandledHref(String href) { * @param event the href event triggered */ private void fixHref(org.w3c.dom.events.Event event) { - if (log.isDebugEnabled()) { - log.debug("Responding to hyperlink event: " + event.getType() + " " + event.toString()); - } + log.debug("Responding to hyperlink event: {} {}", event.getType(), event); final String href = ((Element) event.getCurrentTarget()).getAttribute("href"); if (href != null && !href.equals("")) { @@ -586,9 +580,7 @@ private void fixHref(org.w3c.dom.events.Event event) { */ private void doChangeTitle(String title) { if (actionListeners != null) { - if (log.isDebugEnabled()) { - log.debug("changeTitle event: " + title); - } + log.debug("changeTitle event: {}", title); actionListeners.actionPerformed(new HTMLActionEvent.ChangeTitleActionEvent(this, title)); } } @@ -603,9 +595,7 @@ private void handleMetaTag(Element element) { String content = element.getAttribute("content"); if (actionListeners != null && name != null && content != null) { - if (log.isDebugEnabled()) { - log.debug("metaTag found: name='" + name + "' content='" + content + "'"); - } + log.debug("metaTag found: name='{}' content='{}'", name, content); actionListeners.actionPerformed(new HTMLActionEvent.MetaTagActionEvent(this, name, content)); } } @@ -790,10 +780,7 @@ private static void addToObject(JsonObject jObj, String name, String value) { */ private void doSubmit(String method, String action, String data) { if (actionListeners != null) { - if (log.isDebugEnabled()) { - log.debug( - "submit event: method='" + method + "' action='" + action + "' data='" + data + "'"); - } + log.debug("submit event: method='{}' action='{}' data='{}'", method, action, data); actionListeners.actionPerformed( new HTMLActionEvent.FormActionEvent(this, method, action, data)); } diff --git a/src/main/java/net/rptools/maptool/client/ui/macrobuttons/panels/SelectionPanel.java b/src/main/java/net/rptools/maptool/client/ui/macrobuttons/panels/SelectionPanel.java index de3f8d05dd..9a9d74e17a 100644 --- a/src/main/java/net/rptools/maptool/client/ui/macrobuttons/panels/SelectionPanel.java +++ b/src/main/java/net/rptools/maptool/client/ui/macrobuttons/panels/SelectionPanel.java @@ -79,7 +79,7 @@ public void init(List selectedTokenList) { } // Set up a code timer to get some performance data timer = new CodeTimer("selectionpanel"); - timer.setEnabled(AppState.isCollectProfilingData() || log.isDebugEnabled()); + timer.setEnabled(AppState.isCollectProfilingData()); timer.setThreshold(10); timer.start("painting"); @@ -108,10 +108,8 @@ public void init(List selectedTokenList) { } timer.stop("painting"); - if (AppState.isCollectProfilingData() || log.isDebugEnabled()) { - String results = timer.toString(); - MapTool.getProfilingNoteFrame().addText(results); - if (log.isDebugEnabled()) log.debug(results); + if (timer.isEnabled()) { + MapTool.getProfilingNoteFrame().addText(timer.toString()); } } diff --git a/src/main/java/net/rptools/maptool/client/ui/preferencesdialog/PreferencesDialog.java b/src/main/java/net/rptools/maptool/client/ui/preferencesdialog/PreferencesDialog.java index 6c1bfb63eb..89af3367b6 100644 --- a/src/main/java/net/rptools/maptool/client/ui/preferencesdialog/PreferencesDialog.java +++ b/src/main/java/net/rptools/maptool/client/ui/preferencesdialog/PreferencesDialog.java @@ -17,6 +17,8 @@ import static net.rptools.maptool.util.UserJvmOptions.getLanguages; import static net.rptools.maptool.util.UserJvmOptions.setJvmOption; +import java.awt.GridBagConstraints; +import java.awt.Insets; import java.awt.Toolkit; import java.awt.datatransfer.StringSelection; import java.awt.event.FocusAdapter; @@ -40,6 +42,7 @@ import net.rptools.maptool.client.AppPreferences; import net.rptools.maptool.client.AppPreferences.RenderQuality; import net.rptools.maptool.client.AppUtil; +import net.rptools.maptool.client.DeveloperOptions; import net.rptools.maptool.client.MapTool; import net.rptools.maptool.client.events.PreferencesChanged; import net.rptools.maptool.client.functions.MediaPlayerAdapter; @@ -420,6 +423,47 @@ public PreferencesDialog() { startupInfoLabel = panel.getLabel("startupInfoLabel"); + { + final var developerOptionToggles = (JPanel) panel.getComponent("developerOptionToggles"); + final var developerLayout = developerOptionToggles.getLayout(); + + final var labelConstraints = new GridBagConstraints(); + labelConstraints.insets = new Insets(6, 0, 6, 5); + labelConstraints.gridx = 0; + labelConstraints.gridy = 0; + labelConstraints.weightx = 0.; + labelConstraints.weighty = 1.; + labelConstraints.fill = GridBagConstraints.HORIZONTAL; + + final var checkboxConstraints = new GridBagConstraints(); + checkboxConstraints.insets = new Insets(6, 5, 6, 0); + checkboxConstraints.gridx = 1; + checkboxConstraints.gridy = 0; + checkboxConstraints.weightx = 0.; + checkboxConstraints.weighty = 1.; + checkboxConstraints.fill = GridBagConstraints.HORIZONTAL; + + for (final var option : DeveloperOptions.Toggle.values()) { + labelConstraints.gridy += 1; + checkboxConstraints.gridy += 1; + + final var label = new JLabel(option.getLabel()); + label.setToolTipText(option.getTooltip()); + label.setHorizontalAlignment(SwingConstants.LEADING); + label.setHorizontalTextPosition(SwingConstants.TRAILING); + + final var checkbox = new JCheckBox(); + checkbox.setName(option.getKey()); + checkbox.setModel(new DeveloperToggleModel(option)); + checkbox.addActionListener(e -> option.setEnabled(!checkbox.isSelected())); + + label.setLabelFor(checkbox); + + developerOptionToggles.add(label, labelConstraints); + developerOptionToggles.add(checkbox, checkboxConstraints); + } + } + File appCfgFile = AppUtil.getAppCfgFile(); String copyInfo = ""; if (appCfgFile != null) { // Don't try to display message if running from dev. @@ -1248,6 +1292,25 @@ private ComboBoxModel getLocalizedModel( return model; } + private static class DeveloperToggleModel extends DefaultButtonModel { + private final DeveloperOptions.Toggle option; + + public DeveloperToggleModel(DeveloperOptions.Toggle option) { + this.option = option; + } + + @Override + public boolean isSelected() { + return option.isEnabled(); + } + + @Override + public void setSelected(boolean b) { + option.setEnabled(b); + super.setEnabled(b); + } + } + /** * @author frank */ diff --git a/src/main/java/net/rptools/maptool/client/ui/preferencesdialog/PreferencesDialogView.form b/src/main/java/net/rptools/maptool/client/ui/preferencesdialog/PreferencesDialogView.form index f6a23c1e33..c31facaba3 100644 --- a/src/main/java/net/rptools/maptool/client/ui/preferencesdialog/PreferencesDialogView.form +++ b/src/main/java/net/rptools/maptool/client/ui/preferencesdialog/PreferencesDialogView.form @@ -2275,6 +2275,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/net/rptools/maptool/client/ui/preferencesdialog/PreferencesDialogView.java b/src/main/java/net/rptools/maptool/client/ui/preferencesdialog/PreferencesDialogView.java index 14091cee96..28c2246593 100644 --- a/src/main/java/net/rptools/maptool/client/ui/preferencesdialog/PreferencesDialogView.java +++ b/src/main/java/net/rptools/maptool/client/ui/preferencesdialog/PreferencesDialogView.java @@ -33,6 +33,9 @@ public class PreferencesDialogView { private JSpinner spinner1; private JCheckBox checkBox1; private JCheckBox checkBox2; + private JPanel developerOptionToggles; + private JPanel developerTab; + private JLabel developerTabWarning; /* spotless:off */ @@ -1039,8 +1042,37 @@ public class PreferencesDialogView { panel26.add(spacer15, new GridConstraints(4, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); final Spacer spacer16 = new Spacer(); panel26.add(spacer16, new GridConstraints(5, 2, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + developerTab = new JPanel(); + developerTab.setLayout(new GridLayoutManager(2, 1, new Insets(0, 0, 0, 0), -1, -1)); + tabbedPane1.addTab(this.$$$getMessageFromBundle$$$("net/rptools/maptool/language/i18n", "Preferences.tab.developer"), developerTab); final Spacer spacer17 = new Spacer(); - mainPanel.add(spacer17, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + developerTab.add(spacer17, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); + developerOptionToggles = new JPanel(); + developerOptionToggles.setLayout(new GridBagLayout()); + developerOptionToggles.setName("developerOptionToggles"); + developerTab.add(developerOptionToggles, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, 1, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 0, true)); + developerOptionToggles.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5), "", TitledBorder.DEFAULT_JUSTIFICATION, TitledBorder.DEFAULT_POSITION, this.$$$getFont$$$("Dialog", Font.BOLD, 12, developerOptionToggles.getFont()), new Color(-13538620))); + developerTabWarning = new JLabel(); + developerTabWarning.setForeground(new Color(-51200)); + this.$$$loadLabelText$$$(developerTabWarning, this.$$$getMessageFromBundle$$$("net/rptools/maptool/language/i18n", "Preferences.tab.developer.warning")); + developerTabWarning.setToolTipText(this.$$$getMessageFromBundle$$$("net/rptools/maptool/language/i18n", "Preferences.developer.autoSaveMeasuredInSeconds.tooltip")); + GridBagConstraints gbc; + gbc = new GridBagConstraints(); + gbc.gridx = 0; + gbc.gridy = 0; + gbc.gridwidth = 3; + gbc.anchor = GridBagConstraints.WEST; + gbc.insets = new Insets(6, 0, 6, 0); + developerOptionToggles.add(developerTabWarning, gbc); + final JPanel spacer18 = new JPanel(); + gbc = new GridBagConstraints(); + gbc.gridx = 2; + gbc.gridy = 1; + gbc.weightx = 1.0; + gbc.fill = GridBagConstraints.HORIZONTAL; + developerOptionToggles.add(spacer18, gbc); + final Spacer spacer19 = new Spacer(); + mainPanel.add(spacer19, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_VERTICAL, 1, GridConstraints.SIZEPOLICY_WANT_GROW, null, null, null, 0, false)); } /** diff --git a/src/main/java/net/rptools/maptool/client/ui/zone/PartitionedDrawableRenderer.java b/src/main/java/net/rptools/maptool/client/ui/zone/PartitionedDrawableRenderer.java index 0b25f43ce2..248d9fddba 100644 --- a/src/main/java/net/rptools/maptool/client/ui/zone/PartitionedDrawableRenderer.java +++ b/src/main/java/net/rptools/maptool/client/ui/zone/PartitionedDrawableRenderer.java @@ -28,6 +28,7 @@ import java.util.*; import net.rptools.lib.CodeTimer; import net.rptools.lib.image.ImageUtil; +import net.rptools.maptool.client.DeveloperOptions; import net.rptools.maptool.model.drawing.Drawable; import net.rptools.maptool.model.drawing.DrawablesGroup; import net.rptools.maptool.model.drawing.DrawnElement; @@ -152,8 +153,8 @@ public void renderDrawables( g.drawImage(chunk.image, x, y, null); timer.stop("render:DrawImage"); - // DEBUG: Partition boundaries - if (log.isDebugEnabled()) { // Show partition boundaries + // DEBUG: Show partition boundaries + if (DeveloperOptions.Toggle.ShowPartitionDrawableBoundaries.isEnabled()) { if (!messageLogged) { messageLogged = true; log.debug( diff --git a/src/main/java/net/rptools/maptool/client/ui/zone/ZoneRenderer.java b/src/main/java/net/rptools/maptool/client/ui/zone/ZoneRenderer.java index b1dc882dfc..9b10ae0deb 100644 --- a/src/main/java/net/rptools/maptool/client/ui/zone/ZoneRenderer.java +++ b/src/main/java/net/rptools/maptool/client/ui/zone/ZoneRenderer.java @@ -153,9 +153,6 @@ public class ZoneRenderer extends JComponent private boolean autoResizeStamp = false; - /** Show blocked grid lines during AStar moving, for debugging... */ - private boolean showAstarDebugging = false; - /** Store previous view to restore to, eg after GM shows ctrl+shift+space pointer */ private double previousScale; @@ -410,7 +407,7 @@ public void commitMoveSelectionSet(GUID keyTokenId) { // Lee: check only matters for snap-to-grid if (stg) { CodeTimer moveTimer = new CodeTimer("ZoneRenderer.commitMoveSelectionSet"); - moveTimer.setEnabled(AppState.isCollectProfilingData() || log.isDebugEnabled()); + moveTimer.setEnabled(AppState.isCollectProfilingData()); moveTimer.setThreshold(1); moveTimer.start("setup"); @@ -539,11 +536,7 @@ public void commitMoveSelectionSet(GUID keyTokenId) { moveTimer.stop("updateTokenTree"); if (moveTimer.isEnabled()) { - String results = moveTimer.toString(); - MapTool.getProfilingNoteFrame().addText(results); - if (log.isDebugEnabled()) { - log.debug(results); - } + MapTool.getProfilingNoteFrame().addText(moveTimer.toString()); moveTimer.clear(); } } else { @@ -797,7 +790,7 @@ public void paintComponent(Graphics g) { if (timer == null) { timer = new CodeTimer("ZoneRenderer.renderZone"); } - timer.setEnabled(AppState.isCollectProfilingData() || log.isDebugEnabled()); + timer.setEnabled(AppState.isCollectProfilingData()); timer.clear(); timer.setThreshold(10); timer.start("paintComponent"); @@ -842,11 +835,7 @@ public void paintComponent(Graphics g) { timer.stop("paintComponent"); if (timer.isEnabled()) { - String results = timer.toString(); - MapTool.getProfilingNoteFrame().addText(results); - if (log.isDebugEnabled()) { - log.debug(results); - } + MapTool.getProfilingNoteFrame().addText(timer.toString()); timer.clear(); } } @@ -1389,10 +1378,6 @@ private void renderRenderables(Graphics2D g) { } } - public CodeTimer getCodeTimer() { - return timer; - } - private enum LightOverlayClipStyle { CLIP_TO_VISIBLE_AREA, CLIP_TO_NOT_VISIBLE_AREA, @@ -2164,7 +2149,7 @@ protected void showBlockedMoves(Graphics2D g, PlayerView view, Set } // Show current Blocked Movement directions for A* - if (walker != null && (log.isDebugEnabled() || showAstarDebugging)) { + if (walker != null && DeveloperOptions.Toggle.ShowAiDebugging.isEnabled()) { Map> blockedMovesByTarget = walker.getBlockedMoves(); // Color currentColor = g.getColor(); for (var entry : blockedMovesByTarget.entrySet()) { @@ -2735,7 +2720,7 @@ public void addDistanceText( int textOffset = (int) (getScale() * 7 * fontScale); // 7 pixels at 100% zoom & grid size of 50 String distanceText = NumberFormat.getInstance().format(distance); - if (log.isDebugEnabled() || showAstarDebugging) { + if (DeveloperOptions.Toggle.ShowAiDebugging.isEnabled()) { distanceText += " (" + NumberFormat.getInstance().format(distanceWithoutTerrain) + ")"; fontSize = (int) (fontSize * 0.75); } diff --git a/src/main/java/net/rptools/maptool/client/walker/astar/AbstractAStarWalker.java b/src/main/java/net/rptools/maptool/client/walker/astar/AbstractAStarWalker.java index 66cdbf1ac0..65f51a6b61 100644 --- a/src/main/java/net/rptools/maptool/client/walker/astar/AbstractAStarWalker.java +++ b/src/main/java/net/rptools/maptool/client/walker/astar/AbstractAStarWalker.java @@ -34,9 +34,11 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; import net.rptools.lib.GeometryUtil; +import net.rptools.maptool.client.DeveloperOptions; import net.rptools.maptool.client.MapTool; import net.rptools.maptool.client.walker.AbstractZoneWalker; import net.rptools.maptool.model.CellPoint; +import net.rptools.maptool.model.GUID; import net.rptools.maptool.model.Label; import net.rptools.maptool.model.Token; import net.rptools.maptool.model.TokenFootprint; @@ -60,11 +62,11 @@ private static boolean isInteger(double d) { } private static final Logger log = LogManager.getLogger(AbstractAStarWalker.class); + // Manually set this in order to view H, G & F costs as rendered labels + private final GeometryFactory geometryFactory = new GeometryFactory(); - // private List debugLabels; protected int crossX = 0; protected int crossY = 0; - private boolean debugCosts = false; // Manually set this to view H, G & F costs as rendered labels private Area vbl = new Area(); private Area fowExposedArea = new Area(); private double cell_cost = zone.getUnitsPerCell(); @@ -80,6 +82,13 @@ private static boolean isInteger(double d) { private Map> fowBlockedMovesByGoal = new ConcurrentHashMap<>(); private final Map> terrainCells = new HashMap<>(); + /** + * The IDs of all debugging labels, so we can remove them again later. Only access this on the + * Swing thread _or else_. TODO Make this per-walker. Unfortunately we create new walkers all the + * time for each operation, so that isn't feasible right now. + */ + private static final List debugLabels = new ArrayList<>(); + public AbstractAStarWalker(Zone zone) { super(zone); @@ -287,14 +296,13 @@ protected List calculatePath(CellPoint start, CellPoint goal) { this.vblBlockedMovesByGoal.clear(); } - // Erase previous debug labels, this actually erases ALL labels! Use only when debugging! + // Erase previous debug labels. EventQueue.invokeLater( () -> { - if (!zone.getLabels().isEmpty() && debugCosts) { - for (Label label : zone.getLabels()) { - zone.removeLabel(label.getId()); - } + for (GUID labelId : debugLabels) { + zone.removeLabel(labelId); } + debugLabels.clear(); }); // Timeout quicker for GM cause reasons @@ -684,15 +692,13 @@ private boolean fowBlocksMovement(CellPoint start, CellPoint goal) { } protected void showDebugInfo(AStarCellPoint node) { - if (!log.isDebugEnabled() && !debugCosts) { + if (!DeveloperOptions.Toggle.ShowAiDebugging.isEnabled()) { return; } final int basis = zone.getGrid().getSize() / 10; final int xOffset = basis * (node.isOddStepOfOneTwoOneMovement ? 7 : 3); - // if (debugLabels == null) { debugLabels = new ArrayList<>(); } - Rectangle cellBounds = zone.getGrid().getBounds(node.position); DecimalFormat f = new DecimalFormat("##.00"); @@ -730,15 +736,13 @@ protected void showDebugInfo(AStarCellPoint node) { EventQueue.invokeLater( () -> { + // Track labels to delete later + debugLabels.addAll( + List.of(gScore.getId(), hScore.getId(), fScore.getId(), parent.getId())); zone.putLabel(gScore); zone.putLabel(hScore); zone.putLabel(fScore); zone.putLabel(parent); }); - - // Track labels to delete later - // debugLabels.add(gScore.getId()); - // debugLabels.add(hScore.getId()); - // debugLabels.add(fScore.getId()); } } diff --git a/src/main/java/net/rptools/maptool/model/AssetLoader.java b/src/main/java/net/rptools/maptool/model/AssetLoader.java index 82c1e602fd..c04872b96b 100644 --- a/src/main/java/net/rptools/maptool/model/AssetLoader.java +++ b/src/main/java/net/rptools/maptool/model/AssetLoader.java @@ -134,19 +134,13 @@ protected Map getIndexMap(String repository) { } indexMap = parseIndex(decode(index)); } catch (MalformedURLException e) { - if (log.isDebugEnabled()) { - log.error("Invalid repository URL: " + repository, e); - } + log.warn("Invalid repository URL: " + repository, e); status = RepoState.BAD_URL; } catch (IOException e) { - if (log.isDebugEnabled()) { - log.error("I/O error retrieving/saving index for '" + repository + "'", e); - } + log.error("I/O error retrieving/saving index for '" + repository + "'", e); status = RepoState.UNAVAILABLE; } catch (Throwable t) { - if (log.isDebugEnabled()) { - log.error("Could not retrieve index for '" + repository + "'", t); - } + log.error("Could not retrieve index for '" + repository + "'", t); status = RepoState.UNAVAILABLE; } repositoryStateMap.put(repository, status); diff --git a/src/main/java/net/rptools/maptool/model/Grid.java b/src/main/java/net/rptools/maptool/model/Grid.java index 20ead3bfad..e4c815925a 100644 --- a/src/main/java/net/rptools/maptool/model/Grid.java +++ b/src/main/java/net/rptools/maptool/model/Grid.java @@ -37,6 +37,7 @@ import javax.swing.KeyStroke; import net.rptools.lib.FileUtil; import net.rptools.maptool.client.AppPreferences; +import net.rptools.maptool.client.DeveloperOptions; import net.rptools.maptool.client.MapTool; import net.rptools.maptool.client.tool.PointerTool; import net.rptools.maptool.client.ui.zone.ZoneRenderer; @@ -663,12 +664,9 @@ public boolean checkCenterRegion(Rectangle regionToCheck, Area fog) { } } } - if (log.isInfoEnabled()) { - log.info( - "Center region of size " - + regionToCheck.getSize() - + " contains neither 4+ closed spaces nor 6+ open spaces?!"); - } + log.info( + "Center region of size {} contains neither 4+ closed spaces nor 6+ open spaces?!", + regionToCheck.getSize()); return openSpace >= closedSpace; } @@ -703,17 +701,11 @@ public boolean checkRegion(Rectangle regionToCheck, Area fog, int tolerance) { } } } - - if (log.isInfoEnabled()) { - log.info( - "Center region of size " - + regionToCheck.getSize() - + " contains neither " - + (9 - tolerance) - + "+ closed spaces nor " - + tolerance - + "+ open spaces?!"); - } + log.info( + "Center region of size {} contains neither {}+ closed spaces nor {}+ open spaces?!", + regionToCheck.getSize(), + 9 - tolerance, + tolerance); return openSpace >= closedSpace; } @@ -917,8 +909,9 @@ protected WalkerMetric getCurrentMetric() { */ protected Area getGridAreaFromCache(int gridRadius) { // If not already in cache, create and cache it - // Or if debug is enabled recreate cache - if (log.isDebugEnabled() || !getGridShapeCache().containsKey(gridRadius)) { + // Or if the flag is enabled, recreate cache + if (DeveloperOptions.Toggle.IgnoreGridShapeCache.isEnabled() + || !getGridShapeCache().containsKey(gridRadius)) { createGridArea(gridRadius); } diff --git a/src/main/java/net/rptools/maptool/model/MacroButtonProperties.java b/src/main/java/net/rptools/maptool/model/MacroButtonProperties.java index bbc70d37f1..8d60530ff9 100644 --- a/src/main/java/net/rptools/maptool/model/MacroButtonProperties.java +++ b/src/main/java/net/rptools/maptool/model/MacroButtonProperties.java @@ -762,11 +762,14 @@ public String getEvaluatedToolTip() { try { MapToolMacroContext context = new MapToolMacroContext("ToolTip", token != null ? token.getName() : "", false, index); - if (log.isDebugEnabled()) { + if (token == null) { log.debug( - "Evaluating toolTip: " - + (token != null ? "for token " + token.getName() + "(" + token.getId() + ")" : "") - + "----------------------------------------------------------------------------------"); + "Evaluating toolTip: ----------------------------------------------------------------------------------"); + } else { + log.debug( + "Evaluating toolTip: for token {} ({})----------------------------------------------------------------------------------", + token.getName(), + token.getId()); } return MapTool.getParser().parseLine(token, toolTip, context); } catch (ParserException pe) { diff --git a/src/main/java/net/rptools/maptool/model/Token.java b/src/main/java/net/rptools/maptool/model/Token.java index dcf26eebd5..f9df389d99 100644 --- a/src/main/java/net/rptools/maptool/model/Token.java +++ b/src/main/java/net/rptools/maptool/model/Token.java @@ -1846,16 +1846,11 @@ public Object getEvaluatedProperty(MapToolVariableResolver resolver, String key) } } try { - if (log.isDebugEnabled()) { - log.debug( - "Evaluating property: '" - + key - + "' for token " - + getName() - + "(" - + getId() - + ")----------------------------------------------------------------------------------"); - } + log.debug( + "Evaluating property: '{}' for token {} ({})----------------------------------------------------------------------------------", + key, + getName(), + getId()); val = MapTool.getParser().parseLine(resolver, this, val.toString()); } catch (ParserException pe) { log.debug("Ignoring Parse Exception, continuing to evaluate {}", key); @@ -1906,9 +1901,7 @@ private void loadOldMacros() { macroPropertiesMap.put(prop.getIndex(), prop); } macroMap = null; - if (log.isDebugEnabled()) { - log.debug("Token.loadOldMacros() set up " + macroPropertiesMap.size() + " new macros."); - } + log.debug("Token.loadOldMacros() set up {} new macros.", macroPropertiesMap.size()); } public int getMacroNextIndex() { diff --git a/src/main/java/net/rptools/maptool/server/ClientHandshake.java b/src/main/java/net/rptools/maptool/server/ClientHandshake.java index bacbcef0aa..bbddb65453 100644 --- a/src/main/java/net/rptools/maptool/server/ClientHandshake.java +++ b/src/main/java/net/rptools/maptool/server/ClientHandshake.java @@ -130,7 +130,7 @@ public void startHandshake() throws ExecutionException, InterruptedException { private void sendMessage(HandshakeMsg message) { var msgType = message.getMessageTypeCase(); - log.info(connection.getId() + " sent: " + msgType); + log.debug(connection.getId() + " sent: " + msgType); connection.sendMessage(message.toByteArray()); } @@ -140,7 +140,7 @@ public void handleMessage(String id, byte[] message) { var handshakeMsg = HandshakeMsg.parseFrom(message); var msgType = handshakeMsg.getMessageTypeCase(); - log.info(id + " got: " + msgType); + log.debug(id + " got: " + msgType); if (msgType == MessageTypeCase.HANDSHAKE_RESPONSE_CODE_MSG) { HandshakeResponseCodeMsg code = handshakeMsg.getHandshakeResponseCodeMsg(); diff --git a/src/main/java/net/rptools/maptool/server/MapToolServerConnection.java b/src/main/java/net/rptools/maptool/server/MapToolServerConnection.java index b1344d1d65..2fee48e50b 100644 --- a/src/main/java/net/rptools/maptool/server/MapToolServerConnection.java +++ b/src/main/java/net/rptools/maptool/server/MapToolServerConnection.java @@ -135,7 +135,7 @@ public void addMessageHandler(ServerMessageHandler handler) { } public void sendMessage(String id, Message message) { - log.info( + log.debug( server.getConfig().getServerName() + " sent to " + id @@ -145,7 +145,7 @@ public void sendMessage(String id, Message message) { } public void sendMessage(String id, Object channel, Message message) { - log.info( + log.debug( server.getConfig().getServerName() + " sent to " + id @@ -158,12 +158,12 @@ public void sendMessage(String id, Object channel, Message message) { } public void broadcastMessage(Message message) { - log.info(server.getConfig().getServerName() + " broadcast: " + message.getMessageTypeCase()); + log.debug(server.getConfig().getServerName() + " broadcast: " + message.getMessageTypeCase()); connection.broadcastMessage(message.toByteArray()); } public void broadcastMessage(String[] exclude, Message message) { - log.info( + log.debug( server.getConfig().getServerName() + " broadcast: " + message.getMessageTypeCase() diff --git a/src/main/java/net/rptools/maptool/server/ServerMessageHandler.java b/src/main/java/net/rptools/maptool/server/ServerMessageHandler.java index 625ca58c9d..3f2d320a83 100644 --- a/src/main/java/net/rptools/maptool/server/ServerMessageHandler.java +++ b/src/main/java/net/rptools/maptool/server/ServerMessageHandler.java @@ -70,16 +70,14 @@ public void handleMessage(String id, byte[] message) { var msg = Message.parseFrom(message); var msgType = msg.getMessageTypeCase(); - // we don't do anything with heartbeats they are only there to avoid routers dropping the - // connection. - // So just ignore then. + log.debug("from " + id + " got: " + msgType); + + // We don't do anything with heartbeats they are only there to avoid routers dropping the + // connection. So just ignore then. if (msgType == HEARTBEAT_MSG) { - log.debug("from " + id + " got: " + msgType); return; } - log.info("from " + id + " got: " + msgType); - switch (msgType) { case ADD_TOPOLOGY_MSG -> { handle(msg.getAddTopologyMsg()); @@ -260,9 +258,9 @@ public void handleMessage(String id, byte[] message) { sendToClients(id, msg); } - default -> log.warn(msgType + "not handled."); + default -> log.warn(msgType + " not handled."); } - log.info("from " + id + " handled: " + msgType); + log.debug("from " + id + " handled: " + msgType); } catch (Exception e) { log.error(ExceptionUtils.getStackTrace(e)); MapTool.showError(ExceptionUtils.getStackTrace(e)); diff --git a/src/main/java/net/rptools/maptool/util/PersistenceUtil.java b/src/main/java/net/rptools/maptool/util/PersistenceUtil.java index dbdcdb4de9..0236154cd5 100644 --- a/src/main/java/net/rptools/maptool/util/PersistenceUtil.java +++ b/src/main/java/net/rptools/maptool/util/PersistenceUtil.java @@ -44,6 +44,7 @@ import net.rptools.lib.io.PackedFile; import net.rptools.maptool.client.AppConstants; import net.rptools.maptool.client.AppPreferences; +import net.rptools.maptool.client.AppState; import net.rptools.maptool.client.AppUtil; import net.rptools.maptool.client.MapTool; import net.rptools.maptool.client.swing.SwingUtil; @@ -275,8 +276,8 @@ public static void saveCampaign(Campaign campaign, File campaignFile, String cam CodeTimer saveTimer; // FJE Previously this was 'private static' -- why? saveTimer = new CodeTimer("CampaignSave"); saveTimer.setThreshold(5); - saveTimer.setEnabled( - log.isDebugEnabled()); // Don't bother keeping track if it won't be displayed... + // Don't bother keeping track if it won't be displayed... + saveTimer.setEnabled(AppState.isCollectProfilingData()); // Strategy: save the file to a tmp location so that if there's a failure the original file // won't be touched. Then once we're finished, replace the old with the new. @@ -351,8 +352,8 @@ public static void saveCampaign(Campaign campaign, File campaignFile, String cam pakFile = null; tmpFile.delete(); // Delete the temporary file saveTimer.stop("OOM Close"); - if (log.isDebugEnabled()) { - log.debug(saveTimer); + if (saveTimer.isEnabled()) { + MapTool.getProfilingNoteFrame().addText(saveTimer.toString()); } MapTool.showError("msg.error.failedSaveCampaignOOM"); return; @@ -395,8 +396,8 @@ public static void saveCampaign(Campaign campaign, File campaignFile, String cam saveCampaignThumbnail(campaignFile.getName()); saveTimer.stop("Thumbnail"); - if (log.isDebugEnabled()) { - log.debug(saveTimer); + if (saveTimer.isEnabled()) { + MapTool.getProfilingNoteFrame().addText(saveTimer.toString()); } } diff --git a/src/main/java/net/rptools/maptool/util/UPnPUtil.java b/src/main/java/net/rptools/maptool/util/UPnPUtil.java index e4211c4180..c42da3b36c 100644 --- a/src/main/java/net/rptools/maptool/util/UPnPUtil.java +++ b/src/main/java/net/rptools/maptool/util/UPnPUtil.java @@ -87,7 +87,7 @@ public static boolean findIGDs() { if (ni.isUp() && !ni.isLoopback() && !ni.isVirtual()) { int found = 0; try { - if (log.isInfoEnabled()) log.info("UPnP: Trying interface " + ni.getDisplayName()); + log.info("UPnP: Trying interface {}", ni.getDisplayName()); InternetGatewayDevice[] thisNI; showMessage( ni.getDisplayName(), "Looking for gateway devices on " + ni.getDisplayName()); @@ -101,8 +101,7 @@ public static boolean findIGDs() { if (thisNI != null) { for (InternetGatewayDevice igd : thisNI) { found++; - if (log.isInfoEnabled()) - log.info("UPnP: Found IGD: " + igd.getIGDRootDevice().getModelName()); + log.info("UPnP: Found IGD: {}", igd.getIGDRootDevice().getModelName()); if (igds.put(igd, ni) != null) { // There was a previous mapping for this IGD! It's unlikely to have two NICs on // the @@ -112,8 +111,7 @@ public static boolean findIGDs() { // user a choice. // FIXME We SHOULD be using the "networking binding order" (Windows) // or "network service order" on OSX. - if (log.isInfoEnabled()) - log.info("UPnP: This was not the first time this IGD was found!"); + log.info("UPnP: This was not the first time this IGD was found!"); } } } @@ -122,8 +120,7 @@ public static boolean findIGDs() { // some IO Exception occurred during communication with device log.warn("While searching for internet gateway devices", ex); } - if (log.isInfoEnabled()) - log.info("Found " + found + " IGDs on interface " + ni.getDisplayName()); + log.info("Found {} IGDs on interface {}", found, ni.getDisplayName()); } } catch (SocketException se) { continue; @@ -160,8 +157,7 @@ public static boolean openPort(int port) { for (InterfaceAddress ifAddr : ni.getInterfaceAddresses()) { if (ifAddr.getAddress() instanceof Inet4Address) { localHostIP = ifAddr.getAddress().getHostAddress(); - if (log.isInfoEnabled()) - log.info("IP address " + localHostIP + " on interface " + ni.getDisplayName()); + log.info("IP address {} on interface {}", localHostIP, ni.getDisplayName()); } } break; @@ -169,14 +165,8 @@ public static boolean openPort(int port) { boolean mapped = gd.addPortMapping("MapTool", null, port, port, localHostIP, 0, "TCP"); if (mapped) { mappings.add(gd); - if (log.isInfoEnabled()) - log.info( - "UPnP: Port " - + port - + " mapped on " - + ni.getDisplayName() - + " at address " - + localHostIP); + log.info( + "UPnP: Port {} mapped on {} at address {}", port, ni.getDisplayName(), localHostIP); } } catch (UPNPResponseException respEx) { // oops the IGD did not like something !! @@ -219,12 +209,10 @@ public static boolean closePort(int port) { boolean unmapped = gd.deletePortMapping(null, port, "TCP"); if (unmapped) { count++; - if (log.isInfoEnabled()) - log.info("UPnP: Port unmapped from " + entry.getValue().getDisplayName()); + log.info("UPnP: Port unmapped from {}", entry.getValue().getDisplayName()); iter.remove(); } else { - if (log.isInfoEnabled()) - log.info("UPnP: Failed to unmap port from " + entry.getValue().getDisplayName()); + log.info("UPnP: Failed to unmap port from {}", entry.getValue().getDisplayName()); } } } catch (IOException e) { diff --git a/src/main/resources/net/rptools/maptool/language/i18n.properties b/src/main/resources/net/rptools/maptool/language/i18n.properties index a568771f57..595477071e 100644 --- a/src/main/resources/net/rptools/maptool/language/i18n.properties +++ b/src/main/resources/net/rptools/maptool/language/i18n.properties @@ -497,6 +497,18 @@ PersistenceUtil.warn.macroWrongFileType = File is not a MapTool macro fi PersistenceUtil.warn.macroSet = a Macro Set PersistenceUtil.warn.macrosetWrongFileType = File is not a MapTool macro set file. File is {0}. +Preferences.tab.developer = Developer +Preferences.tab.developer.warning = These options are not meant for normal use. If you aren't developing or debugging MapTool, don't enable them! +Preferences.developer.info.developerOptionsInUse = The following developer options are enabled: +Preferences.developer.autoSaveMeasuredInSeconds.label = Measure auto-save time in seconds +Preferences.developer.autoSaveMeasuredInSeconds.tooltip = When enabled, increases the frequency of auto-saves by reinterpreting the number as measuring seconds instead of minutes. +Preferences.developer.showPartitionDrawableBoundaries.label = Show spatial partitions when rendering drawings +Preferences.developer.showPartitionDrawableBoundaries.tooltip = When enabled, draws a boundary around each spatial partition that is used in drawing rendering. +Preferences.developer.showAiDebugging.label = Enable AI debugging +Preferences.developer.showAiDebugging.tooltip = When enabled, adds labels containing the f, g, and h costs calculated by A* during pathfinding, as well as the moves blocked by VBL. +Preferences.developer.ignoreGridShapeCache.label = Ignore grid shape cache +Preferences.developer.ignoreGridShapeCache.tooltip = When enabled, the grid's shape is recalculated every time it is needed. +Preferences.developer.info.developerOptionsInUsePost = If this is not intended, go to {0} > {1} > {2} tab and disable the options there. Preferences.tab.interactions = Interactions Preferences.label.maps.fow = New maps have Fog of War Preferences.label.maps.fow.tooltip = Fog of War can be enabled or disabled on individual maps.