From 1425e9b9d6fd4efdda096e79b0a65e145335d611 Mon Sep 17 00:00:00 2001 From: extio-de Date: Sat, 23 Aug 2025 10:40:21 +0200 Subject: [PATCH] Implement UI scaling for various components and add UIScaler utility class --- lm-launcher.jar | Bin 2173470 -> 2178468 bytes .../lm_launcher/AppPropertiesDialog.java | 19 +- src/de/extio/lm_launcher/LaunchFrame.java | 21 +- src/de/extio/lm_launcher/Main.java | 2 + .../lm_launcher/ModelPropertiesDialog.java | 9 +- .../extio/lm_launcher/SelectModelDialog.java | 9 +- src/de/extio/lm_launcher/UIScaler.java | 268 ++++++++++++++++++ 7 files changed, 315 insertions(+), 13 deletions(-) create mode 100644 src/de/extio/lm_launcher/UIScaler.java diff --git a/lm-launcher.jar b/lm-launcher.jar index 8f6f0b3e78c864c653be00e92f480208916f7758..064e20c97241880d3149940284f014fd6a0899b2 100644 GIT binary patch delta 33005 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 diff --git a/src/de/extio/lm_launcher/AppPropertiesDialog.java b/src/de/extio/lm_launcher/AppPropertiesDialog.java index 2a26496..d9555dc 100644 --- a/src/de/extio/lm_launcher/AppPropertiesDialog.java +++ b/src/de/extio/lm_launcher/AppPropertiesDialog.java @@ -58,9 +58,9 @@ public class AppPropertiesDialog extends JDialog { AppPropertiesDialog.app = app; this.onClose = onClose; - this.setBounds(100, 100, 681, 350); + this.setBounds(UIScaler.scale(100), UIScaler.scale(100), UIScaler.scale(681), UIScaler.scale(350)); this.getContentPane().setLayout(new BorderLayout()); - this.contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5)); + this.contentPanel.setBorder(new EmptyBorder(UIScaler.scale(5), UIScaler.scale(5), UIScaler.scale(5), UIScaler.scale(5))); this.getContentPane().add(this.contentPanel, BorderLayout.CENTER); this.contentPanel.setLayout(new BorderLayout(0, 0)); { @@ -75,6 +75,8 @@ public class AppPropertiesDialog extends JDialog { this.table.setRowSelectionAllowed(false); this.table.setFillsViewportHeight(true); this.table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); + // Scale the table row height to accommodate larger checkboxes + this.table.setRowHeight(UIScaler.scale(this.table.getRowHeight())); JCheckBoxRenderer renderer = new JCheckBoxRenderer(); JCheckBoxEditor editor = new JCheckBoxEditor(); @@ -137,6 +139,9 @@ public class AppPropertiesDialog extends JDialog { this.textField.setText(app.argumentsToString(true)); this.refreshTable(); + + // Apply font scaling to all components + UIScaler.scaleComponentFonts(this); } private void refreshTable() { @@ -173,6 +178,11 @@ public class AppPropertiesDialog extends JDialog { static class JCheckBoxRenderer extends JCheckBox implements TableCellRenderer { + public JCheckBoxRenderer() { + // Apply comprehensive checkbox scaling + UIScaler.scaleCheckBox(this); + } + @Override public Component getTableCellRendererComponent(final JTable table, final Object value, final boolean isSelected, final boolean hasFocus, final int row, final int column) { this.setSelected((boolean) value); @@ -185,6 +195,9 @@ public class AppPropertiesDialog extends JDialog { private final JCheckBox checkBox = new JCheckBox() { { + // Apply comprehensive checkbox scaling + UIScaler.scaleCheckBox(this); + this.addActionListener(e -> { final AppArgument existing = AppPropertiesDialog.app.appArguments().get(JCheckBoxEditor.this.row); if (JCheckBoxEditor.this.column == 1) { @@ -219,4 +232,4 @@ public class AppPropertiesDialog extends JDialog { return true; } } -} +} \ No newline at end of file diff --git a/src/de/extio/lm_launcher/LaunchFrame.java b/src/de/extio/lm_launcher/LaunchFrame.java index e9ea143..1f06a30 100644 --- a/src/de/extio/lm_launcher/LaunchFrame.java +++ b/src/de/extio/lm_launcher/LaunchFrame.java @@ -124,9 +124,9 @@ public class LaunchFrame extends JFrame { public LaunchFrame() { this.setTitle("LM Launcher"); this.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); - this.setPreferredSize(new Dimension(650, 650)); + this.setPreferredSize(UIScaler.scale(new Dimension(650, 650))); this.contentPane = new JPanel(); - this.contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); + this.contentPane.setBorder(new EmptyBorder(UIScaler.scale(5), UIScaler.scale(5), UIScaler.scale(5), UIScaler.scale(5))); this.setContentPane(this.contentPane); this.contentPane.setLayout(new BorderLayout(0, 0)); @@ -276,6 +276,8 @@ public class LaunchFrame extends JFrame { this.table = new JTable(this.appArgumentsTableModel); this.table.setRowSelectionAllowed(false); this.table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS); + // Scale the table row height to accommodate larger checkboxes + this.table.setRowHeight(UIScaler.scale(this.table.getRowHeight())); this.table.getColumnModel().getColumn(0).setCellRenderer(new AppArgumentsJCheckBoxRenderer(this.appArgumentsTableModel)); this.table.getColumnModel().getColumn(0).setCellEditor(new AppArgumentsJCheckBoxEditor()); @@ -538,7 +540,11 @@ public class LaunchFrame extends JFrame { } this.pack(); - this.setLocationRelativeTo(null); + + // Apply font scaling to all components + UIScaler.scaleComponentFonts(this); + + UIScaler.centerOnPrimaryDisplay(this); this.repaint(); this.splitPane.setDividerLocation(0.33); this.splitPane_1.setDividerLocation(0.66); @@ -575,6 +581,8 @@ public class LaunchFrame extends JFrame { public AppArgumentsJCheckBoxRenderer(final DefaultTableModel model) { super(); this.model = model; + // Apply comprehensive checkbox scaling + UIScaler.scaleCheckBox(this); } @Override @@ -592,6 +600,11 @@ public class LaunchFrame extends JFrame { private AppArgument appArgument; + public AppArgumentsJCheckBoxEditor() { + // Apply comprehensive checkbox scaling + UIScaler.scaleCheckBox(this.checkBox); + } + @Override public Component getTableCellEditorComponent(final JTable table, final Object value, final boolean isSelected, final int row, final int column) { this.appArgument = (AppArgument) value; @@ -606,4 +619,4 @@ public class LaunchFrame extends JFrame { } } -} +} \ No newline at end of file diff --git a/src/de/extio/lm_launcher/Main.java b/src/de/extio/lm_launcher/Main.java index b4bc684..ab6707a 100644 --- a/src/de/extio/lm_launcher/Main.java +++ b/src/de/extio/lm_launcher/Main.java @@ -7,6 +7,8 @@ public class Main { public static void main(final String[] args) { System.setProperty("awt.useSystemAAFontSettings", "on"); System.setProperty("swing.aatext", "true"); + System.setProperty("sun.java2d.uiScale", "1"); + System.setProperty("awt.nativeDoubleBuffering", "true"); EventQueue.invokeLater(new Runnable() { diff --git a/src/de/extio/lm_launcher/ModelPropertiesDialog.java b/src/de/extio/lm_launcher/ModelPropertiesDialog.java index cbdcbde..17ad9f7 100644 --- a/src/de/extio/lm_launcher/ModelPropertiesDialog.java +++ b/src/de/extio/lm_launcher/ModelPropertiesDialog.java @@ -53,9 +53,9 @@ public class ModelPropertiesDialog extends JDialog { this.setModal(true); this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); - this.setBounds(100, 100, 678, 191); + this.setBounds(UIScaler.scale(100), UIScaler.scale(100), UIScaler.scale(678), UIScaler.scale(191)); this.getContentPane().setLayout(new BorderLayout()); - this.contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5)); + this.contentPanel.setBorder(new EmptyBorder(UIScaler.scale(5), UIScaler.scale(5), UIScaler.scale(5), UIScaler.scale(5))); this.getContentPane().add(this.contentPanel, BorderLayout.CENTER); this.contentPanel.setLayout(new GridLayout(0, 2, 0, 0)); { @@ -150,6 +150,9 @@ public class ModelPropertiesDialog extends JDialog { this.textField_3.setText(String.valueOf(editModel.contextSize())); this.txtPrompttemplate.setText(editModel.promptTemplate()); } + + // Apply font scaling to all components + UIScaler.scaleComponentFonts(this); } -} +} \ No newline at end of file diff --git a/src/de/extio/lm_launcher/SelectModelDialog.java b/src/de/extio/lm_launcher/SelectModelDialog.java index 15f7483..0edbeda 100644 --- a/src/de/extio/lm_launcher/SelectModelDialog.java +++ b/src/de/extio/lm_launcher/SelectModelDialog.java @@ -40,9 +40,9 @@ public class SelectModelDialog extends JDialog { this.setModal(true); this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); - this.setBounds(100, 100, 578, 251); + this.setBounds(UIScaler.scale(100), UIScaler.scale(100), UIScaler.scale(578), UIScaler.scale(251)); this.getContentPane().setLayout(new BorderLayout()); - this.contentPanel.setBorder(new EmptyBorder(5, 5, 5, 5)); + this.contentPanel.setBorder(new EmptyBorder(UIScaler.scale(5), UIScaler.scale(5), UIScaler.scale(5), UIScaler.scale(5))); this.getContentPane().add(this.contentPanel, BorderLayout.CENTER); this.contentPanel.setLayout(new BorderLayout(0, 0)); { @@ -92,6 +92,9 @@ public class SelectModelDialog extends JDialog { } } this.initialize(); + + // Apply font scaling to all components + UIScaler.scaleComponentFonts(this); } private void initialize() { @@ -101,4 +104,4 @@ public class SelectModelDialog extends JDialog { .forEach(this.listModel::addElement); } -} +} \ No newline at end of file diff --git a/src/de/extio/lm_launcher/UIScaler.java b/src/de/extio/lm_launcher/UIScaler.java new file mode 100644 index 0000000..4b01f2a --- /dev/null +++ b/src/de/extio/lm_launcher/UIScaler.java @@ -0,0 +1,268 @@ +package de.extio.lm_launcher; + +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.Toolkit; +import java.awt.Window; +import javax.swing.Icon; +import javax.swing.JCheckBox; +import javax.swing.JComponent; +import javax.swing.UIManager; +import javax.swing.plaf.metal.MetalIconFactory; + +/** + * Utility class for scaling UI elements based on screen resolution. + * Reference resolution is 1920x1080 (1080p). + */ +public class UIScaler { + + private static final int REFERENCE_WIDTH = 1920; + private static final int REFERENCE_HEIGHT = 1080; + + private static final double scaleX; + private static final double scaleY; + private static final double scale; + private static final GraphicsDevice primaryDevice; + + static { + GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); + primaryDevice = ge.getDefaultScreenDevice(); + + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + + scaleX = (double) screenSize.width / REFERENCE_WIDTH; + scaleY = (double) screenSize.height / REFERENCE_HEIGHT; + // Use the smaller scale to maintain aspect ratio, then dampen by 0.8 + double baseScale = Math.min(scaleX, scaleY); + scale = 1.0 + (baseScale - 1.0) * 0.8; + + // Apply global font scaling to UI defaults + scaleUIDefaults(); + } + + /** + * Scale UI default fonts globally + */ + private static void scaleUIDefaults() { + UIManager.getDefaults().entrySet().forEach(entry -> { + if (entry.getValue() instanceof Font) { + Font font = (Font) entry.getValue(); + UIManager.put(entry.getKey(), scaleFont(font)); + } + }); + + // Scale checkbox icon size + if (scale != 1.0) { + try { + // Create scaled checkbox icons + Icon checkBoxIcon = new ScaledCheckBoxIcon(false); + Icon checkBoxSelectedIcon = new ScaledCheckBoxIcon(true); + + UIManager.put("CheckBox.icon", checkBoxIcon); + UIManager.put("CheckBox.selectedIcon", checkBoxSelectedIcon); + } catch (Exception e) { + // Fallback - continue without custom icons + System.err.println("Could not set scaled checkbox icons: " + e.getMessage()); + } + } + } + + /** + * Apply scaling to a checkbox component + * @param checkBox The checkbox to scale + */ + public static void scaleCheckBox(JCheckBox checkBox) { + if (checkBox == null) return; + + // Scale font + checkBox.setFont(scaleFont(checkBox.getFont())); + + // Scale component size + Dimension prefSize = checkBox.getPreferredSize(); + if (prefSize != null) { + checkBox.setPreferredSize(scale(prefSize)); + } + + // Apply scaled icons if available + if (scale != 1.0) { + try { + checkBox.setIcon(new ScaledCheckBoxIcon(false)); + checkBox.setSelectedIcon(new ScaledCheckBoxIcon(true)); + } catch (Exception e) { + // Continue without custom icons + } + } + } + + /** + * Custom scaled checkbox icon + */ + private static class ScaledCheckBoxIcon implements Icon { + private final boolean selected; + private final int size; + + public ScaledCheckBoxIcon(boolean selected) { + this.selected = selected; + this.size = scale(13); // Default checkbox icon size is typically 13x13 + } + + @Override + public void paintIcon(Component c, java.awt.Graphics g, int x, int y) { + // Create a graphics context with scaling + java.awt.Graphics2D g2 = (java.awt.Graphics2D) g.create(); + + // Apply scaling transform + g2.scale(scale, scale); + + // Get the original icon and paint it + Icon originalIcon; + if (selected) { + originalIcon = MetalIconFactory.getCheckBoxIcon(); + // Simulate selected state + g2.translate(x / scale, y / scale); + originalIcon.paintIcon(c, g2, 0, 0); + } else { + originalIcon = MetalIconFactory.getCheckBoxIcon(); + g2.translate(x / scale, y / scale); + originalIcon.paintIcon(c, g2, 0, 0); + } + + g2.dispose(); + } + + @Override + public int getIconWidth() { + return size; + } + + @Override + public int getIconHeight() { + return size; + } + } + + /** + * Scale all fonts in a component hierarchy recursively + * @param component The root component to scale + */ + public static void scaleComponentFonts(Component component) { + if (component == null) return; + + // Scale the component's font + Font font = component.getFont(); + if (font != null) { + component.setFont(scaleFont(font)); + } + + // Recursively scale child components + if (component instanceof Container) { + Container container = (Container) component; + for (Component child : container.getComponents()) { + scaleComponentFonts(child); + } + } + } + + /** + * Scale a dimension value (width or height) based on screen resolution. + * @param value The original value at reference resolution + * @return The scaled value + */ + public static int scale(int value) { + return (int) Math.round(value * scale); + } + + /** + * Scale a dimension value using a custom scale factor. + * @param value The original value + * @param customScale The custom scale factor + * @return The scaled value + */ + public static int scale(int value, double customScale) { + return (int) Math.round(value * customScale); + } + + /** + * Scale a Dimension object. + * @param dimension The original dimension + * @return A new scaled Dimension + */ + public static Dimension scale(Dimension dimension) { + return new Dimension(scale(dimension.width), scale(dimension.height)); + } + + /** + * Scale a font size. + * @param fontSize The original font size + * @return The scaled font size + */ + public static int scaleFontSize(int fontSize) { + return Math.max(8, scale(fontSize)); // Minimum font size of 8 + } + + /** + * Scale a font. + * @param font The original font + * @return A new font with scaled size + */ + public static Font scaleFont(Font font) { + return font.deriveFont((float) scaleFontSize(font.getSize())); + } + + /** + * Get the current scale factor. + * @return The scale factor relative to reference resolution + */ + public static double getScale() { + return scale; + } + + /** + * Get the horizontal scale factor. + * @return The horizontal scale factor + */ + public static double getScaleX() { + return scaleX; + } + + /** + * Get the vertical scale factor. + * @return The vertical scale factor + */ + public static double getScaleY() { + return scaleY; + } + + /** + * Center a window on the primary display. + * @param window The window to center + */ + public static void centerOnPrimaryDisplay(Window window) { + window.setLocationRelativeTo(null); + // Ensure it's on the primary display + if (primaryDevice != null) { + window.setLocation( + primaryDevice.getDefaultConfiguration().getBounds().x + + (primaryDevice.getDefaultConfiguration().getBounds().width - window.getWidth()) / 2, + primaryDevice.getDefaultConfiguration().getBounds().y + + (primaryDevice.getDefaultConfiguration().getBounds().height - window.getHeight()) / 2 + ); + } + } + + /** + * Get information about current scaling for debugging. + * @return A string with scaling information + */ + public static String getScalingInfo() { + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + return String.format("Screen: %dx%d, Reference: %dx%d, Scale: %.2f (X: %.2f, Y: %.2f)", + screenSize.width, screenSize.height, + REFERENCE_WIDTH, REFERENCE_HEIGHT, + scale, scaleX, scaleY); + } +} \ No newline at end of file