diff --git a/bin/jmeter.properties b/bin/jmeter.properties index bac04e85bc9..a5446b45d05 100644 --- a/bin/jmeter.properties +++ b/bin/jmeter.properties @@ -1182,11 +1182,14 @@ cookies=cookies #jsyntaxtextarea.wrapstyleword=true #jsyntaxtextarea.linewrap=true #jsyntaxtextarea.codefolding=true +#jsyntaxtextarea.highlight=true # Set 0 to disable undo feature in JSyntaxTextArea #jsyntaxtextarea.maxundos=50 # Change the font on the (JSyntax) Text Areas. (Useful for HiDPI screens) #jsyntaxtextarea.font.family=Hack #jsyntaxtextarea.font.size=14 +#jsyntaxtextarea.theme.default=themes/default.xml +#jsyntaxtextarea.theme.dark=themes/dark.xml # Set this to false to disable the use of JSyntaxTextArea for the Console Logger panel #loggerpanel.usejsyntaxtext=true diff --git a/src/bom-thirdparty/build.gradle.kts b/src/bom-thirdparty/build.gradle.kts index 6d54246c2b1..f4976b91f75 100644 --- a/src/bom-thirdparty/build.gradle.kts +++ b/src/bom-thirdparty/build.gradle.kts @@ -45,7 +45,7 @@ dependencies { api("com.fasterxml.jackson.core:jackson-annotations:2.16.1") api("com.fasterxml.jackson.core:jackson-core:2.16.1") api("com.fasterxml.jackson.core:jackson-databind:2.16.1") - api("com.fifesoft:rsyntaxtextarea:3.3.4") + api("com.fifesoft:rsyntaxtextarea:3.6.0") api("com.formdev:svgSalamander:1.1.4") api("com.github.ben-manes.caffeine:caffeine:2.9.3") api("com.github.weisj:darklaf-core:2.7.3") @@ -143,5 +143,17 @@ dependencies { api("xerces:xercesImpl:2.12.2") api("xml-apis:xml-apis:1.4.01") api("xmlpull:xmlpull:1.1.3.1") + //FlatLaf: https://www.formdev.com/flatlaf/native-libraries/#gradle + val flatlafVersion = "3.6.2" + api("com.formdev:flatlaf:${flatlafVersion}" ) + api("com.formdev:flatlaf:${flatlafVersion}:linux-x86_64@so") + api("com.formdev:flatlaf:${flatlafVersion}:macos-x86_64@dylib") + api("com.formdev:flatlaf:${flatlafVersion}:windows-x86_64@dll") + api("com.formdev:flatlaf-intellij-themes:${flatlafVersion}") + api("com.formdev:flatlaf-extras:${flatlafVersion}") + api("com.formdev:flatlaf-fonts-inter:4.1") + api("com.formdev:flatlaf-fonts-jetbrains-mono:2.304") + api("com.formdev:flatlaf-fonts-roboto:2.137") + api("com.formdev:flatlaf-fonts-roboto-mono:3.000") } } diff --git a/src/core/build.gradle.kts b/src/core/build.gradle.kts index 98160b953a5..c8ad78b4197 100644 --- a/src/core/build.gradle.kts +++ b/src/core/build.gradle.kts @@ -132,6 +132,9 @@ dependencies { testFixturesApi(testFixtures(projects.src.jorphan)) testFixturesImplementation(projects.src.testkit) testFixturesImplementation("org.junit.jupiter:junit-jupiter") + + implementation( "com.formdev:flatlaf" ) + implementation( "com.formdev:flatlaf-intellij-themes" ) } val generatedVersionDir = layout.buildDirectory.dir("generated/sources/version") diff --git a/src/core/src/main/java/org/apache/jmeter/SplashScreen.java b/src/core/src/main/java/org/apache/jmeter/SplashScreen.java index b3326bb221b..ff5851ee0e9 100644 --- a/src/core/src/main/java/org/apache/jmeter/SplashScreen.java +++ b/src/core/src/main/java/org/apache/jmeter/SplashScreen.java @@ -30,6 +30,7 @@ import javax.swing.SwingUtilities; import javax.swing.border.EmptyBorder; +import org.apache.jmeter.gui.action.LookAndFeelCommand; import org.apache.jmeter.util.JMeterUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -74,7 +75,7 @@ public static JComponent loadLogo() { log.warn("Unable to find logo {}", svgResourcePath, e); } - if (svgUri != null) { + if (svgUri != null && LookAndFeelCommand.isDarklafTheme()) { Icon icon = new ThemedSVGIcon(svgUri, 521, 177); logo.setIcon(icon); } else { diff --git a/src/core/src/main/java/org/apache/jmeter/gui/LoggerPanel.java b/src/core/src/main/java/org/apache/jmeter/gui/LoggerPanel.java index 6e380a7f8ce..1017ba5a754 100644 --- a/src/core/src/main/java/org/apache/jmeter/gui/LoggerPanel.java +++ b/src/core/src/main/java/org/apache/jmeter/gui/LoggerPanel.java @@ -83,7 +83,7 @@ private JTextArea init() { // WARNING: called from ctor so must not be overridde JSyntaxTextArea jSyntaxTextArea = JSyntaxTextArea.getInstance(15, 80, true); jSyntaxTextArea.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_NONE); jSyntaxTextArea.setCodeFoldingEnabled(false); - jSyntaxTextArea.setAntiAliasingEnabled(false); + jSyntaxTextArea.setAntiAliasingEnabled(true); jSyntaxTextArea.setEditable(false); jSyntaxTextArea.setLineWrap(false); jSyntaxTextArea.setLanguage("text"); diff --git a/src/core/src/main/java/org/apache/jmeter/gui/MainFrame.java b/src/core/src/main/java/org/apache/jmeter/gui/MainFrame.java index 969bed78c3b..42c5ddc8d03 100644 --- a/src/core/src/main/java/org/apache/jmeter/gui/MainFrame.java +++ b/src/core/src/main/java/org/apache/jmeter/gui/MainFrame.java @@ -247,7 +247,7 @@ public MainFrame(TreeModel treeModel, JMeterTreeListener treeListener) { // Shift down means "horizontal scrolling" on macOS, and we need only vertical one if ((e.getModifiersEx() & (ctrlAltMask | InputEvent.SHIFT_DOWN_MASK)) == ctrlAltMask) { e.consume(); - final float scale = 1.1f; + final float scale = JMeterUtils.getPropDefault("zoom_scale", 1.1f); int rotation = e.getWheelRotation(); if (rotation > 0) { // DOWN JMeterUtils.applyScaleOnFonts(1.0f / scale); @@ -642,7 +642,7 @@ private static JScrollPane createMainPanel() { private static LoggerPanel createLoggerPanel() { LoggerPanel loggerPanel = new LoggerPanel(); loggerPanel.setMinimumSize(new Dimension(0, 100)); - loggerPanel.setPreferredSize(new Dimension(0, 150)); + loggerPanel.setPreferredSize(new Dimension(0, 100)); GuiPackage guiInstance = GuiPackage.getInstance(); guiInstance.setLoggerPanel(loggerPanel); guiInstance.getMenuItemLoggerPanel().getModel().setSelected(DISPLAY_LOGGER_PANEL); diff --git a/src/core/src/main/java/org/apache/jmeter/gui/action/LookAndFeelCommand.java b/src/core/src/main/java/org/apache/jmeter/gui/action/LookAndFeelCommand.java index 0821b8a05d3..d6ff93abe6c 100644 --- a/src/core/src/main/java/org/apache/jmeter/gui/action/LookAndFeelCommand.java +++ b/src/core/src/main/java/org/apache/jmeter/gui/action/LookAndFeelCommand.java @@ -36,9 +36,12 @@ import org.apache.jmeter.gui.util.JMeterMenuBar; import org.apache.jmeter.util.JMeterUtils; import org.apache.jorphan.gui.JFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import com.formdev.flatlaf.FlatLaf; +import com.formdev.flatlaf.intellijthemes.FlatAllIJThemes; import com.github.weisj.darklaf.LafManager; -import com.github.weisj.darklaf.theme.DarculaTheme; import com.github.weisj.darklaf.theme.Theme; import com.google.auto.service.AutoService; @@ -47,6 +50,7 @@ */ @AutoService(Command.class) public class LookAndFeelCommand extends AbstractAction { + private static final Logger log = LoggerFactory.getLogger(LookAndFeelCommand.class); private static final String JMETER_LAF = "jmeter.laf"; // $NON-NLS-1$ private static final Map items = new LinkedHashMap<>(); @@ -106,11 +110,29 @@ private static MenuItem ofDarklafTheme(Theme theme) { if (System.getProperty("darklaf.treeRowPopup") == null) { System.setProperty("darklaf.treeRowPopup", "false"); } - UIManager.installLookAndFeel(JMeterMenuBar.DARCULA_LAF, JMeterMenuBar.DARCULA_LAF_CLASS); + + //Add FlatLAF Themes + for (String flatLaf : new String[]{"FlatLightLaf", "FlatDarkLaf", "FlatIntelliJLaf", "FlatDarculaLaf"}) { + try { + UIManager.installLookAndFeel(flatLaf, "com.formdev.flatlaf." + flatLaf); + } catch( Exception ex ) { + log.warn("Failed to load FlatLAF theme: {}", flatLaf, ex); + } + } + for (String flatLaf : new String[]{"FlatMacDarkLaf", "FlatMacLightLaf"}) { + try { + UIManager.installLookAndFeel(flatLaf, "com.formdev.flatlaf.themes" + flatLaf); + } catch( Exception ex ) { + log.warn("Failed to load FlatLAF theme: {}", flatLaf, ex); + } + } + for (UIManager.LookAndFeelInfo lafInfo : FlatAllIJThemes.INFOS) { + UIManager.installLookAndFeel(lafInfo.getName(), lafInfo.getClassName()); + } List items = new ArrayList<>(); for (UIManager.LookAndFeelInfo laf : JMeterMenuBar.getAllLAFs()) { - if (!laf.getClassName().equals(JMeterMenuBar.DARCULA_LAF_CLASS)) { + if (!laf.getClassName().equals(JMeterMenuBar.DARKLAF_LAF_CLASS)) { items.add(MenuItem.of(laf.getName(), laf.getClassName())); } else { for (Theme theme : LafManager.getRegisteredThemes()) { @@ -143,15 +165,10 @@ public static Collection getMenuItems() { */ @Deprecated public static String getJMeterLaf(){ - String laf = PREFS.get(USER_PREFS_KEY, null); - if (laf != null) { - return checkLafName(laf); - } - String osName = System.getProperty("os.name") // $NON-NLS-1$ .toLowerCase(Locale.ENGLISH); // Spaces are not allowed in property names read from files - laf = JMeterUtils.getProperty(JMETER_LAF+"."+osName.replace(' ', '_')); + String laf = JMeterUtils.getProperty(JMETER_LAF+"."+osName.replace(' ', '_')); if (laf != null) { return checkLafName(laf); } @@ -160,10 +177,7 @@ public static String getJMeterLaf(){ if (laf != null) { return checkLafName(laf); } - laf = JMeterUtils.getPropDefault(JMETER_LAF, JMeterMenuBar.DARCULA_LAF_CLASS); - if (laf != null) { - return checkLafName(laf); - } + return UIManager.getCrossPlatformLookAndFeelClassName(); } @@ -174,16 +188,16 @@ public static String getJMeterLaf(){ public static String getPreferredLafCommand() { String laf = PREFS.get(USER_PREFS_KEY, null); if (laf != null) { - return laf; + MenuItem item = items.get(laf); + if (item == null) { + log.warn("LookAndFeel command '{}' not found in available items, falling back to default LAFs", laf); + } else { + return item.command; + } } String jMeterLaf = getJMeterLaf(); - if (jMeterLaf.equals(JMeterMenuBar.DARCULA_LAF_CLASS)) { - // Convert old Darcula to new Darklaf-Darcula LaF - return MenuItem.ofDarklafTheme(new DarculaTheme()).command; - } - - return MenuItem.of("default", jMeterLaf).command; // $NON-NLS-1$ + return MenuItem.of("default", jMeterLaf).command; // $NON-NLS-1$ } // Check if LAF is a built-in one @@ -205,8 +219,12 @@ public static boolean isDarklafTheme() { return "Darklaf".equalsIgnoreCase(UIManager.getLookAndFeel().getID()); // $NON-NLS-1$ } + public static boolean isFlatlafTheme() { + return UIManager.getLookAndFeel() instanceof FlatLaf; + } + public static boolean isDark() { - return isDarklafTheme() && Theme.isDark(LafManager.getTheme()); + return (isDarklafTheme() && Theme.isDark(LafManager.getTheme())) || (isFlatlafTheme() && ((FlatLaf)UIManager.getLookAndFeel()).isDark()); } public static void activateLookAndFeel(String command) { diff --git a/src/core/src/main/java/org/apache/jmeter/gui/util/JMeterMenuBar.java b/src/core/src/main/java/org/apache/jmeter/gui/util/JMeterMenuBar.java index 4f829e9d2ea..3ec22f2e9ba 100644 --- a/src/core/src/main/java/org/apache/jmeter/gui/util/JMeterMenuBar.java +++ b/src/core/src/main/java/org/apache/jmeter/gui/util/JMeterMenuBar.java @@ -53,6 +53,7 @@ import org.apache.jmeter.util.LocaleChangeEvent; import org.apache.jmeter.util.LocaleChangeListener; import org.apache.jmeter.util.SSLManager; +import org.apache.jorphan.gui.GuiUtils; import org.apache.jorphan.reflect.LogAndIgnoreServiceLoadExceptionHandler; import org.apache.jorphan.util.JOrphanUtils; import org.apache.logging.log4j.Level; @@ -101,10 +102,10 @@ public class JMeterMenuBar extends JMenuBar implements LocaleChangeListener { public static final String SYSTEM_LAF = "System"; // $NON-NLS-1$ public static final String CROSS_PLATFORM_LAF = "CrossPlatform"; // $NON-NLS-1$ - public static final String DARCULA_LAF = "Darcula"; // $NON-NLS-1$ public static final String DARKLAF_LAF = "Darklaf"; // $NON-NLS-1$ - public static final String DARCULA_LAF_CLASS = "com.bulenkov.darcula.DarculaLaf"; // $NON-NLS-1$ + public static final String FLAT_LAF = "FlatLaf"; // $NON-NLS-1$ public static final String DARKLAF_LAF_CLASS = "com.github.weisj.darklaf.DarkLaf"; // $NON-NLS-1$ + public static final String FLATLAF_LAF_CLASS = "com.formdev.flatlaf.FlatLightLaf"; // $NON-NLS-1$ public JMeterMenuBar() { // List for recent files menu items @@ -317,6 +318,7 @@ private void makeOptionsMenu() { private static JMenu createLaFMenu() { JMenu lafMenu = makeMenuRes("appearance", 'L'); + JMenu flatLafSubMenu = new JMenu("FlatLaf Themes"); ButtonGroup lafGroup = new ButtonGroup(); String currentLafCommand = LookAndFeelCommand.getPreferredLafCommand(); for (LookAndFeelCommand.MenuItem item : LookAndFeelCommand.getMenuItems()) { @@ -326,9 +328,16 @@ private static JMenu createLaFMenu() { if (item.getCommand().equals(currentLafCommand)) { menuItem.setSelected(true); } + if (item.getCommand().startsWith("laf:com.formdev.flatlaf")) { + flatLafSubMenu.add(menuItem); + } else { + lafMenu.add(menuItem); + } lafGroup.add(menuItem); - lafMenu.add(menuItem); } + GuiUtils.makeScrollableMenu(flatLafSubMenu); + lafMenu.addSeparator(); + lafMenu.add(flatLafSubMenu); return lafMenu; } diff --git a/src/core/src/main/java/org/apache/jmeter/gui/util/JSyntaxTextArea.java b/src/core/src/main/java/org/apache/jmeter/gui/util/JSyntaxTextArea.java index 6625fa75777..ba1196ed2e5 100644 --- a/src/core/src/main/java/org/apache/jmeter/gui/util/JSyntaxTextArea.java +++ b/src/core/src/main/java/org/apache/jmeter/gui/util/JSyntaxTextArea.java @@ -29,13 +29,16 @@ import javax.swing.SwingUtilities; import javax.swing.UIManager; +import org.apache.commons.lang3.StringUtils; import org.apache.jmeter.gui.action.LookAndFeelCommand; import org.apache.jmeter.util.JMeterUtils; import org.apache.jorphan.gui.JFactory; import org.apache.jorphan.gui.JMeterUIDefaults; import org.apache.jorphan.gui.ui.TextComponentUI; import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea; +import org.fife.ui.rsyntaxtextarea.Style; import org.fife.ui.rsyntaxtextarea.SyntaxConstants; +import org.fife.ui.rsyntaxtextarea.SyntaxScheme; import org.fife.ui.rsyntaxtextarea.Theme; import org.fife.ui.rtextarea.RUndoManager; import org.slf4j.Logger; @@ -53,7 +56,8 @@ public class JSyntaxTextArea extends RSyntaxTextArea { private static final long serialVersionUID = 211L; private static final Logger log = LoggerFactory.getLogger(JSyntaxTextArea.class); - private static final Theme DEFAULT_THEME = loadTheme(Theme.class, "themes/default.xml"); + private static final Theme DEFAULT_THEME = loadTheme(Theme.class, JMeterUtils.getPropDefault("jsyntaxtextarea.theme.default", "themes/default.xml")); + private static final Theme DEFAULT_DARK_THEME = loadTheme(Theme.class, JMeterUtils.getPropDefault("jsyntaxtextarea.theme.dark", "themes/dark.xml")); private final Properties languageProperties = JMeterUtils.loadProperties("org/apache/jmeter/gui/util/textarea.properties"); //$NON-NLS-1$ @@ -64,6 +68,7 @@ public class JSyntaxTextArea extends RSyntaxTextArea { private static final int MAX_UNDOS = JMeterUtils.getPropDefault("jsyntaxtextarea.maxundos", 50); private static final String USER_FONT_FAMILY = JMeterUtils.getPropDefault("jsyntaxtextarea.font.family", null); private static final int USER_FONT_SIZE = JMeterUtils.getPropDefault("jsyntaxtextarea.font.size", -1); + private static final boolean HIGHLIGHT_OCCURRENCES = JMeterUtils.getPropDefault("jsyntaxtextarea.highlight", true); private static final HierarchyListener GUTTER_THEME_PATCHER = e -> { if ((e.getChangeFlags() & HierarchyEvent.PARENT_CHANGED) != 0 @@ -93,6 +98,7 @@ public class JSyntaxTextArea extends RSyntaxTextArea { public static JSyntaxTextArea getInstance(int rows, int cols, boolean disableUndo) { try { JSyntaxTextArea jSyntaxTextArea = new JSyntaxTextArea(rows, cols, disableUndo); + jSyntaxTextArea.createPopupMenu(); JFactory.withDynamic(jSyntaxTextArea, JSyntaxTextArea::applyTheme); // Gutter styling is only applied if the text area is contained in a scroll pane. jSyntaxTextArea.addHierarchyListener(GUTTER_THEME_PATCHER); @@ -143,16 +149,53 @@ public String getText() { */ private static void applyTheme(JSyntaxTextArea jSyntaxTextArea) { final boolean isDarklafTheme = LookAndFeelCommand.isDarklafTheme(); - final Theme theme = isDarklafTheme ? new DarklafRSyntaxTheme(jSyntaxTextArea) : DEFAULT_THEME; + final boolean isFlatlafTheme = LookAndFeelCommand.isFlatlafTheme(); + final Theme theme = isDarklafTheme ? new DarklafRSyntaxTheme(jSyntaxTextArea) : (LookAndFeelCommand.isDark() ? DEFAULT_DARK_THEME : DEFAULT_THEME); + + // Calculate scaled font size + float scale = JMeterUIDefaults.INSTANCE.getScale(); + Font baseFont; + if (USER_FONT_FAMILY != null) { + baseFont = JMeterUIDefaults.createFont(USER_FONT_FAMILY, Font.PLAIN, USER_FONT_SIZE > 0 ? USER_FONT_SIZE : 12); + } else { + baseFont = jSyntaxTextArea.getFont(); + } + if (Math.abs(scale - 1.0f) > 0.01) { + baseFont = baseFont.deriveFont(baseFont.getSize2D() * scale); + } + + // Apply theme first if (theme != null) { theme.apply(jSyntaxTextArea); - Font font = jSyntaxTextArea.getFont(); - float scale = JMeterUIDefaults.INSTANCE.getScale(); - if (Math.abs(scale - 1.0f) > 0.01) { - font = font.deriveFont(font.getSize2D() * scale); - jSyntaxTextArea.setFont(font); + } + + // Apply scaled font to all token types + SyntaxScheme scheme = jSyntaxTextArea.getSyntaxScheme(); + for (int i = 0; i < scheme.getStyleCount(); i++) { + Style style = scheme.getStyle(i); + if (style != null) { + if (style.font != null) { + // Keep the style (bold/italic) but use scaled size + style.font = style.font.deriveFont(baseFont.getSize2D()); + } else { + style.font = baseFont; + } } } + jSyntaxTextArea.setFont(baseFont); + jSyntaxTextArea.setSyntaxScheme(scheme); + jSyntaxTextArea.setFractionalFontMetricsEnabled(true); + + if (isFlatlafTheme) { + jSyntaxTextArea.setForeground(UIManager.getColor("TextArea.foreground")); + jSyntaxTextArea.setCaretColor(UIManager.getColor("TextArea.caretForeground")); + jSyntaxTextArea.setSelectionColor(UIManager.getColor("TextArea.selectionBackground")); + jSyntaxTextArea.setSelectedTextColor(UIManager.getColor("TextArea.selectionForeground")); + if (UIManager.getColor("Hyperlink.linkColor") != null) { + jSyntaxTextArea.setHyperlinkForeground(UIManager.getColor("Hyperlink.linkColor")); + } + } + if (!isDarklafTheme) { // Darklaf themes provide a custom background color for editors, so we don't overwrite it. Color color = UIManager.getColor("TextArea.background"); @@ -241,14 +284,31 @@ public JSyntaxTextArea(int rows, int cols, boolean disableUndo) { super.setAntiAliasingEnabled(true); super.setLineWrap(LINE_WRAP); super.setWrapStyleWord(WRAP_STYLE_WORD); + super.setMarkOccurrences(HIGHLIGHT_OCCURRENCES); this.disableUndo = disableUndo; + + // Add component listener to handle window resizing + addComponentListener(new java.awt.event.ComponentAdapter() { + @Override + public void componentResized(java.awt.event.ComponentEvent e) { + // Ensure text wraps to the new width + revalidate(); + repaint(); + } + }); + + int fontSize = USER_FONT_SIZE > 0 ? USER_FONT_SIZE : getFont().getSize(); + Font font = getFont(); if (USER_FONT_FAMILY != null) { - int fontSize = USER_FONT_SIZE > 0 ? USER_FONT_SIZE : getFont().getSize(); - setFont(JMeterUIDefaults.createFont(USER_FONT_FAMILY, Font.PLAIN, fontSize)); + font = JMeterUIDefaults.createFont(USER_FONT_FAMILY, Font.PLAIN, fontSize); + } else { + font = font.deriveFont(font.getStyle(), fontSize); + } + setFont(font); if (log.isDebugEnabled()) { log.debug("Font is set to: {}", getFont()); } - } + if(disableUndo) { TextComponentUI.uninstallUndo(this); // We need to do this to force recreation of undoManager which diff --git a/src/core/src/main/java/org/apache/jmeter/gui/util/TextAreaCellRenderer.java b/src/core/src/main/java/org/apache/jmeter/gui/util/TextAreaCellRenderer.java index cb8600a5d80..5e8131f98b6 100644 --- a/src/core/src/main/java/org/apache/jmeter/gui/util/TextAreaCellRenderer.java +++ b/src/core/src/main/java/org/apache/jmeter/gui/util/TextAreaCellRenderer.java @@ -21,8 +21,11 @@ import java.awt.Component; import javax.swing.JTable; +import javax.swing.UIManager; import javax.swing.table.TableCellRenderer; +import org.apache.jmeter.gui.action.LookAndFeelCommand; + public class TextAreaCellRenderer implements TableCellRenderer { private JSyntaxTextArea rend = createRenderer(""); //$NON-NLS-1$ @@ -36,13 +39,20 @@ public Component getTableCellRendererComponent(JTable table, Object value, } else { rend = createRenderer(""); //$NON-NLS-1$ } + if (hasFocus || isSelected) { - rend.setBackground(Color.blue); + if (LookAndFeelCommand.isFlatlafTheme()) { + rend.setBackground(UIManager.getColor("Table.selectionBackground")); + rend.setForeground(UIManager.getColor("Table.selectionForeground")); + } else { + rend.setBackground(Color.pink); rend.setForeground(Color.white); } + } if (table.getRowHeight(row) < getPreferredHeight()) { table.setRowHeight(row, getPreferredHeight()); } + return JTextScrollPane.getInstance(rend); } diff --git a/src/jorphan/src/main/java/org/apache/jorphan/gui/JMeterUIDefaults.java b/src/jorphan/src/main/java/org/apache/jorphan/gui/JMeterUIDefaults.java index b8e98da783a..8605dc14973 100644 --- a/src/jorphan/src/main/java/org/apache/jorphan/gui/JMeterUIDefaults.java +++ b/src/jorphan/src/main/java/org/apache/jorphan/gui/JMeterUIDefaults.java @@ -103,11 +103,13 @@ private JMeterUIDefaults() { @API(since = "5.3", status = API.Status.INTERNAL) public void install() { DynamicStyle.onLaFChange(() -> { + log.info("LAF changed, updating JMeter-specific properties"); // $NON-NLS-1$ // We put JMeter-specific properties into getLookAndFeelDefaults, // so the properties are removed when LaF is changed UIDefaults defaults = UIManager.getLookAndFeelDefaults(); if (Math.abs(scale - 1.0f) > 0.01f) { + log.info("Applying scale factor: {}", scale); // $NON-NLS-1$ scaleFonts(defaults); scaleIntProperties(defaults, scale); // We don't want to make controls extra big, so we damp the scaling factors @@ -183,8 +185,9 @@ private static void configureRowHeight(UIDefaults defaults, float scale, String if (f == null) { height = 16 * scale; } else { - Canvas c = new Canvas(); - height = c.getFontMetrics(f).getHeight(); + //Canvas c = new Canvas(); + //height = c.getFontMetrics(f).getHeight(); + height = f.getSize2D(); } // Set line height to be 1.3 of the font size. The number of completely made up, // 1.2 seems to be the minimal usable scale. 1.3 looks good. diff --git a/xdocs/stylesheets/website-style.xsl b/xdocs/stylesheets/website-style.xsl index 9b8dbddae96..e826bdf2796 100644 --- a/xdocs/stylesheets/website-style.xsl +++ b/xdocs/stylesheets/website-style.xsl @@ -38,7 +38,7 @@ - + diff --git a/xdocs/usermanual/properties_reference.xml b/xdocs/usermanual/properties_reference.xml index d74ece0613d..df5fb25b29d 100644 --- a/xdocs/usermanual/properties_reference.xml +++ b/xdocs/usermanual/properties_reference.xml @@ -1507,6 +1507,10 @@ JMETER-SERVER Set to zero to disable undo feature in JSyntaxTextArea.
Defaults to: 50 + + Set to false to disable word highlight in JSyntaxTextArea.
+ Defaults to: true +
Change the font on the (JSyntax) Text Areas. (Useful for HiDPI screens).
Defaults to empty value, which means platform default monospaced font @@ -1515,6 +1519,13 @@ JMETER-SERVER Change the size of the (JSyntax) Text Areas. Will be used only, when jsyntaxtextarea.font.family is set.
Defaults to: -1
+ + Change the default theme of the (JSyntax) Text Areas.
+ Defaults to: themes/default.xml
+ + Change the default dark theme of the (JSyntax) Text Areas. When LAF is + detected to be of 'dark' type this is also applied in (JSyntax) Text Areas.
+ Defaults to: themes/dark.xml
Set this to false to disable the use of JSyntaxTextArea for the Console Logger panel.