Drafting scaling options for HiDPI
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
Dmitry Isaenko 2025-11-20 01:28:09 +03:00
parent e973d7c863
commit 005247cc0b
5 changed files with 145 additions and 25 deletions

View file

@ -2,7 +2,7 @@
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="tihwin.MainAppUi"> <form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="tihwin.MainAppUi">
<grid id="27dc6" binding="mainPanel" layout-manager="FormLayout"> <grid id="27dc6" binding="mainPanel" layout-manager="FormLayout">
<rowspec value="center:max(d;4px):noGrow"/> <rowspec value="center:max(d;4px):noGrow"/>
<rowspec value="top:m:grow"/> <rowspec value="top:m:grow(1.1)"/>
<rowspec value="top:4dlu:noGrow"/> <rowspec value="top:4dlu:noGrow"/>
<rowspec value="center:max(d;4px):noGrow"/> <rowspec value="center:max(d;4px):noGrow"/>
<rowspec value="top:4dlu:noGrow"/> <rowspec value="top:4dlu:noGrow"/>
@ -14,7 +14,7 @@
<rowspec value="top:4dlu:noGrow"/> <rowspec value="top:4dlu:noGrow"/>
<rowspec value="center:max(d;4px):noGrow"/> <rowspec value="center:max(d;4px):noGrow"/>
<rowspec value="top:4dlu:noGrow"/> <rowspec value="top:4dlu:noGrow"/>
<rowspec value="center:max(d;1dlu):noGrow"/> <rowspec value="center:max(d;4px):noGrow"/>
<colspec value="fill:p:noGrow"/> <colspec value="fill:p:noGrow"/>
<colspec value="left:4dlu:noGrow"/> <colspec value="left:4dlu:noGrow"/>
<colspec value="fill:p:noGrow"/> <colspec value="fill:p:noGrow"/>
@ -23,9 +23,9 @@
<colspec value="fill:max(d;4px):noGrow"/> <colspec value="fill:max(d;4px):noGrow"/>
<colspec value="fill:d:grow"/> <colspec value="fill:d:grow"/>
<colspec value="left:4dlu:noGrow"/> <colspec value="left:4dlu:noGrow"/>
<colspec value="fill:p:noGrow"/> <colspec value="fill:p:grow(0.2)"/>
<constraints> <constraints>
<xy x="0" y="0" width="763" height="488"/> <xy x="0" y="0" width="1155" height="462"/>
</constraints> </constraints>
<properties/> <properties/>
<border type="none"/> <border type="none"/>
@ -146,7 +146,7 @@
<indeterminate value="false"/> <indeterminate value="false"/>
</properties> </properties>
</component> </component>
<grid id="a5cce" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <grid id="a5cce" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/> <margin top="0" left="0" bottom="0" right="0"/>
<constraints> <constraints>
<grid row="0" column="0" row-span="1" col-span="9" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/> <grid row="0" column="0" row-span="1" col-span="9" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
@ -159,7 +159,7 @@
<children> <children>
<component id="2c1c4" class="javax.swing.JLabel"> <component id="2c1c4" class="javax.swing.JLabel">
<constraints> <constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="7" anchor="0" fill="0" indent="0" use-parent-layout="false"/> <grid row="0" column="0" row-span="2" col-span="1" vsize-policy="0" hsize-policy="7" anchor="0" fill="0" indent="0" use-parent-layout="false"/>
</constraints> </constraints>
<properties> <properties>
<icon value="banner.png"/> <icon value="banner.png"/>
@ -178,6 +178,47 @@
<html.disable class="java.lang.Boolean" value="false"/> <html.disable class="java.lang.Boolean" value="false"/>
</clientProperties> </clientProperties>
</component> </component>
<grid id="b11cc" layout-manager="FlowLayout" hgap="0" vgap="0" flow-align="2">
<constraints>
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="5" fill="0" indent="2" use-parent-layout="false"/>
</constraints>
<properties>
<alignmentX value="0.0"/>
<alignmentY value="0.0"/>
<focusable value="false"/>
<opaque value="false"/>
</properties>
<border type="none"/>
<children>
<component id="825ab" class="javax.swing.JButton" binding="zoomInBtn">
<constraints/>
<properties>
<alignmentY value="0.0"/>
<borderPainted value="false"/>
<contentAreaFilled value="false"/>
<focusPainted value="true"/>
<icon value="zoom-in.png"/>
<iconTextGap value="0"/>
<opaque value="false"/>
<preferredSize width="25" height="25"/>
</properties>
</component>
<component id="c79b2" class="javax.swing.JButton" binding="zoomOutBtn">
<constraints/>
<properties>
<alignmentY value="0.0"/>
<borderPainted value="false"/>
<contentAreaFilled value="false"/>
<focusPainted value="true"/>
<foreground color="-9251843"/>
<icon value="zoom-out.png"/>
<iconTextGap value="0"/>
<opaque value="false"/>
<preferredSize width="25" height="25"/>
</properties>
</component>
</children>
</grid>
</children> </children>
</grid> </grid>
<component id="824ea" class="javax.swing.JButton" binding="ulCfgBtn"> <component id="824ea" class="javax.swing.JButton" binding="ulCfgBtn">
@ -187,14 +228,10 @@
</constraints> </constraints>
<properties> <properties>
<background color="-2031648"/> <background color="-2031648"/>
<margin top="1" left="1" bottom="1" right="1"/>
<minimumSize width="130" height="30"/>
<preferredSize width="140" height="30"/>
<text resource-bundle="locale" key="editUlCfgBtn"/> <text resource-bundle="locale" key="editUlCfgBtn"/>
</properties> </properties>
</component> </component>
<grid id="8b0eb" binding="statusJPanel" layout-manager="GridLayoutManager" row-count="1" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <grid id="8b0eb" binding="statusJPanel" layout-manager="FlowLayout" hgap="5" vgap="5" flow-align="0">
<margin top="5" left="5" bottom="5" right="5"/>
<constraints> <constraints>
<grid row="13" column="0" row-span="1" col-span="9" vsize-policy="0" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/> <grid row="13" column="0" row-span="1" col-span="9" vsize-policy="0" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
<forms/> <forms/>
@ -207,9 +244,7 @@
</border> </border>
<children> <children>
<component id="2cf16" class="javax.swing.JLabel" binding="statusLbl"> <component id="2cf16" class="javax.swing.JLabel" binding="statusLbl">
<constraints> <constraints/>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties> <properties>
<text resource-bundle="locale" key="WelcomeText"/> <text resource-bundle="locale" key="WelcomeText"/>
</properties> </properties>

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2022-2023 Dmitry Isaenko Copyright 2022-2025 Dmitry Isaenko
This file is part of Tihwin. This file is part of Tihwin.
@ -58,7 +58,10 @@ public class MainAppUi extends JFrame {
private JLabel diskImageRoLbl; private JLabel diskImageRoLbl;
private JLabel titleRoLbl; private JLabel titleRoLbl;
private JLabel ulDestinationRoLbl; private JLabel ulDestinationRoLbl;
private JButton zoomInBtn;
private JButton zoomOutBtn;
private ResourceBundle resourceBundle; private ResourceBundle resourceBundle;
int scale;
private String recentRomLocation; private String recentRomLocation;
private File diskImage; private File diskImage;
@ -68,6 +71,7 @@ public class MainAppUi extends JFrame {
private Thread splitThread; private Thread splitThread;
public MainAppUi(String appName) { public MainAppUi(String appName) {
super(appName);
$$$setupUI$$$(); $$$setupUI$$$();
resourceBundle = ResourceBundle.getBundle("locale"); resourceBundle = ResourceBundle.getBundle("locale");
AwesomeMediator.setMainUi(this); AwesomeMediator.setMainUi(this);
@ -80,6 +84,8 @@ public class MainAppUi extends JFrame {
destinationSelectBtn.addActionListener(actionEvent -> destinationSelectEventHandler()); destinationSelectBtn.addActionListener(actionEvent -> destinationSelectEventHandler());
convertBtn.addActionListener(actionEvent -> convertButtonAction()); convertBtn.addActionListener(actionEvent -> convertButtonAction());
ulCfgBtn.addActionListener(actionEvent -> ulConfigButtonAction()); ulCfgBtn.addActionListener(actionEvent -> ulConfigButtonAction());
zoomInBtn.addActionListener(actionEvent -> zoomIn());
zoomOutBtn.addActionListener(actionEvent -> zoomOut());
((AbstractDocument) titleField.getDocument()).setDocumentFilter(new TitleFieldFilter()); ((AbstractDocument) titleField.getDocument()).setDocumentFilter(new TitleFieldFilter());
if (Settings.INSTANCE.getDvdSelected()) if (Settings.INSTANCE.getDvdSelected())
DVDRadioButton.setSelected(true); DVDRadioButton.setSelected(true);
@ -94,6 +100,7 @@ public class MainAppUi extends JFrame {
Settings.INSTANCE.setDestination(destinationDirectoryLbl.getText()); Settings.INSTANCE.setDestination(destinationDirectoryLbl.getText());
Settings.INSTANCE.setDvdSelected(DVDRadioButton.isSelected()); Settings.INSTANCE.setDvdSelected(DVDRadioButton.isSelected());
Settings.INSTANCE.setLocale(((LocaleHolder) ulLangComboBox.getSelectedItem()).getLocaleCode()); Settings.INSTANCE.setLocale(((LocaleHolder) ulLangComboBox.getSelectedItem()).getLocaleCode());
Settings.INSTANCE.setScaleFactor(scale);
} }
}); });
@ -102,10 +109,56 @@ public class MainAppUi extends JFrame {
BorderFactory.createEmptyBorder(5, 5, 5, 5)); BorderFactory.createEmptyBorder(5, 5, 5, 5));
diskImageSelectBtn.setBorder(fitMoreTextOnButtonBorder); diskImageSelectBtn.setBorder(fitMoreTextOnButtonBorder);
destinationSelectBtn.setBorder(fitMoreTextOnButtonBorder); destinationSelectBtn.setBorder(fitMoreTextOnButtonBorder);
ulCfgBtn.setBorder(fitMoreTextOnButtonBorder);
diskImageSelectBtn.addMouseListener(new TwButtonsActionListener()); diskImageSelectBtn.addMouseListener(new TwButtonsActionListener());
destinationSelectBtn.addMouseListener(new TwButtonsActionListener()); destinationSelectBtn.addMouseListener(new TwButtonsActionListener());
titleField.setBorder(new LineBorder(Color.lightGray)); titleField.setBorder(new LineBorder(Color.lightGray));
scale = Settings.INSTANCE.getScaleFactor();
applyScaling();
}
private void applyScaling() {
if (scale == 0)
return;
for (Component component : mainPanel.getComponents())
applyScalingOnComponent(component);
applyScalingOnComponent(statusLbl);
applyScalingOnComponent(ulLangComboBox);
}
private void applyScalingOnComponent(Component component) {
Font defaultFont = component.getFont();
component.setFont(new Font(defaultFont.getName(), defaultFont.getStyle(), defaultFont.getSize() + scale));
}
private void zoomIn() {
for (Component c : mainPanel.getComponents())
increaseElementScale(c);
increaseElementScale(statusLbl);
increaseElementScale(ulLangComboBox);
scale++;
}
private void increaseElementScale(Component component) {
Font defaultFont = component.getFont();
component.setFont(new Font(defaultFont.getName(), defaultFont.getStyle(), defaultFont.getSize() + 1));
}
private void zoomOut() {
if (scale == 0)
return;
for (Component c : mainPanel.getComponents())
decreaseElementScale(c);
decreaseElementScale(statusLbl);
decreaseElementScale(ulLangComboBox);
scale--;
}
private void decreaseElementScale(Component component) {
Font defaultFont = component.getFont();
component.setFont(new Font(defaultFont.getName(), defaultFont.getStyle(), defaultFont.getSize() - 1));
} }
private void diskImageSelectEventHandler() { private void diskImageSelectEventHandler() {
@ -241,7 +294,7 @@ public class MainAppUi extends JFrame {
private void $$$setupUI$$$() { private void $$$setupUI$$$() {
createUIComponents(); createUIComponents();
mainPanel = new JPanel(); mainPanel = new JPanel();
mainPanel.setLayout(new FormLayout("fill:p:noGrow,left:4dlu:noGrow,fill:p:noGrow,left:4dlu:noGrow,fill:p:noGrow,fill:max(d;4px):noGrow,fill:d:grow,left:4dlu:noGrow,fill:p:noGrow", "center:max(d;4px):noGrow,top:m:grow,top:4dlu:noGrow,center:max(d;4px):noGrow,top:4dlu:noGrow,center:max(d;4px):noGrow,top:4dlu:noGrow,center:max(d;4px):noGrow,top:4dlu:noGrow,center:max(d;4px):noGrow,top:4dlu:noGrow,center:max(d;4px):noGrow,top:4dlu:noGrow,center:max(d;1dlu):noGrow")); mainPanel.setLayout(new FormLayout("fill:p:noGrow,left:4dlu:noGrow,fill:p:noGrow,left:4dlu:noGrow,fill:p:noGrow,fill:max(d;4px):noGrow,fill:d:grow,left:4dlu:noGrow,fill:p:grow(0.2)", "center:max(d;4px):noGrow,top:m:grow(1.1),top:4dlu:noGrow,center:max(d;4px):noGrow,top:4dlu:noGrow,center:max(d;4px):noGrow,top:4dlu:noGrow,center:max(d;4px):noGrow,top:4dlu:noGrow,center:max(d;4px):noGrow,top:4dlu:noGrow,center:max(d;4px):noGrow,top:4dlu:noGrow,center:max(d;4px):noGrow"));
diskImageSelectBtn = new JButton(); diskImageSelectBtn = new JButton();
diskImageSelectBtn.setBackground(new Color(-2034433)); diskImageSelectBtn.setBackground(new Color(-2034433));
this.$$$loadButtonText$$$(diskImageSelectBtn, this.$$$getMessageFromBundle$$$("locale", "SelectBtn")); this.$$$loadButtonText$$$(diskImageSelectBtn, this.$$$getMessageFromBundle$$$("locale", "SelectBtn"));
@ -285,31 +338,56 @@ public class MainAppUi extends JFrame {
progressBar.setIndeterminate(false); progressBar.setIndeterminate(false);
mainPanel.add(progressBar, cc.xyw(1, 12, 9, CellConstraints.FILL, CellConstraints.TOP)); mainPanel.add(progressBar, cc.xyw(1, 12, 9, CellConstraints.FILL, CellConstraints.TOP));
final JPanel panel1 = new JPanel(); final JPanel panel1 = new JPanel();
panel1.setLayout(new GridLayoutManager(1, 2, new Insets(0, 0, 0, 0), -1, -1)); panel1.setLayout(new GridLayoutManager(2, 2, new Insets(0, 0, 0, 0), -1, -1));
panel1.setBackground(new Color(-9251843)); panel1.setBackground(new Color(-9251843));
mainPanel.add(panel1, cc.xyw(1, 1, 9)); mainPanel.add(panel1, cc.xyw(1, 1, 9));
final JLabel label1 = new JLabel(); final JLabel label1 = new JLabel();
label1.setIcon(new ImageIcon(getClass().getResource("/banner.png"))); label1.setIcon(new ImageIcon(getClass().getResource("/banner.png")));
label1.setText(""); label1.setText("");
panel1.add(label1, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); panel1.add(label1, new GridConstraints(0, 0, 2, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
ulLangComboBox.setBackground(new Color(-9251843)); ulLangComboBox.setBackground(new Color(-9251843));
ulLangComboBox.setForeground(new Color(-1)); ulLangComboBox.setForeground(new Color(-1));
ulLangComboBox.putClientProperty("html.disable", Boolean.FALSE); ulLangComboBox.putClientProperty("html.disable", Boolean.FALSE);
panel1.add(ulLangComboBox, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_NORTHWEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 1, false)); panel1.add(ulLangComboBox, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_NORTHWEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 1, false));
final JPanel panel2 = new JPanel();
panel2.setLayout(new FlowLayout(FlowLayout.RIGHT, 0, 0));
panel2.setAlignmentX(0.0f);
panel2.setAlignmentY(0.0f);
panel2.setFocusable(false);
panel2.setOpaque(false);
panel1.add(panel2, new GridConstraints(1, 1, 1, 1, GridConstraints.ANCHOR_NORTHEAST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, null, null, 2, false));
zoomInBtn = new JButton();
zoomInBtn.setAlignmentY(0.0f);
zoomInBtn.setBorderPainted(false);
zoomInBtn.setContentAreaFilled(false);
zoomInBtn.setFocusPainted(true);
zoomInBtn.setIcon(new ImageIcon(getClass().getResource("/zoom-in.png")));
zoomInBtn.setIconTextGap(0);
zoomInBtn.setOpaque(false);
zoomInBtn.setPreferredSize(new Dimension(25, 25));
panel2.add(zoomInBtn);
zoomOutBtn = new JButton();
zoomOutBtn.setAlignmentY(0.0f);
zoomOutBtn.setBorderPainted(false);
zoomOutBtn.setContentAreaFilled(false);
zoomOutBtn.setFocusPainted(true);
zoomOutBtn.setForeground(new Color(-9251843));
zoomOutBtn.setIcon(new ImageIcon(getClass().getResource("/zoom-out.png")));
zoomOutBtn.setIconTextGap(0);
zoomOutBtn.setOpaque(false);
zoomOutBtn.setPreferredSize(new Dimension(25, 25));
panel2.add(zoomOutBtn);
ulCfgBtn = new JButton(); ulCfgBtn = new JButton();
ulCfgBtn.setBackground(new Color(-2031648)); ulCfgBtn.setBackground(new Color(-2031648));
ulCfgBtn.setMargin(new Insets(1, 1, 1, 1));
ulCfgBtn.setMinimumSize(new Dimension(130, 30));
ulCfgBtn.setPreferredSize(new Dimension(140, 30));
this.$$$loadButtonText$$$(ulCfgBtn, this.$$$getMessageFromBundle$$$("locale", "editUlCfgBtn")); this.$$$loadButtonText$$$(ulCfgBtn, this.$$$getMessageFromBundle$$$("locale", "editUlCfgBtn"));
mainPanel.add(ulCfgBtn, new CellConstraints(9, 4, 1, 1, CellConstraints.DEFAULT, CellConstraints.DEFAULT, new Insets(0, 0, 0, 5))); mainPanel.add(ulCfgBtn, new CellConstraints(9, 4, 1, 1, CellConstraints.DEFAULT, CellConstraints.DEFAULT, new Insets(0, 0, 0, 5)));
statusJPanel = new JPanel(); statusJPanel = new JPanel();
statusJPanel.setLayout(new GridLayoutManager(1, 1, new Insets(5, 5, 5, 5), -1, -1)); statusJPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 5, 5));
statusJPanel.setBackground(new Color(-1)); statusJPanel.setBackground(new Color(-1));
mainPanel.add(statusJPanel, cc.xyw(1, 14, 9)); mainPanel.add(statusJPanel, cc.xyw(1, 14, 9));
statusLbl = new JLabel(); statusLbl = new JLabel();
this.$$$loadLabelText$$$(statusLbl, this.$$$getMessageFromBundle$$$("locale", "WelcomeText")); this.$$$loadLabelText$$$(statusLbl, this.$$$getMessageFromBundle$$$("locale", "WelcomeText"));
statusJPanel.add(statusLbl, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false)); statusJPanel.add(statusLbl);
ButtonGroup buttonGroup; ButtonGroup buttonGroup;
buttonGroup = new ButtonGroup(); buttonGroup = new ButtonGroup();
buttonGroup.add(DVDRadioButton); buttonGroup.add(DVDRadioButton);

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2022 Dmitry Isaenko Copyright 2022-2025 Dmitry Isaenko
This file is part of Tihwin. This file is part of Tihwin.
@ -55,4 +55,11 @@ public class Settings {
public Locale getLocale(){ return this.locale; } public Locale getLocale(){ return this.locale; }
public void setLocale(String localeId){ preferences.put("locale", localeId); } public void setLocale(String localeId){ preferences.put("locale", localeId); }
public int getScaleFactor(){
return preferences.getInt("scale", 0);
}
public void setScaleFactor(int value){
preferences.putInt("scale", value);
}
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB