Compare commits
19 Commits
latest
...
751f878a32
| Author | SHA1 | Date | |
|---|---|---|---|
| 751f878a32 | |||
| 3d1d98ee7b | |||
| bf126de5b9 | |||
| 485dccdf3b | |||
| 5b9568013d | |||
| 48c2e0abd9 | |||
| ebdf464c31 | |||
| b812535366 | |||
| a52fe8dc78 | |||
| cc2a625fc1 | |||
| c7659bb44e | |||
| 16e85a3fe3 | |||
| c8aa7a9648 | |||
| cdc05c9b67 | |||
| 250384e738 | |||
| 1c749e1098 | |||
| c3756e1982 | |||
| 97777f1046 | |||
| c59fdc4430 |
@@ -26,7 +26,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Compile Java files
|
- name: Compile Java files
|
||||||
run: |
|
run: |
|
||||||
javac -encoding UTF-8 -cp "lib/flatlaf-3.7.jar" -d out/production/Calc \
|
javac -encoding UTF-8 -cp "lib/flatlaf-3.7.jar:lib/flatlaf-extras-3.7.jar" -d out/production/Calc \
|
||||||
$(find src/main/java -name "*.java")
|
$(find src/main/java -name "*.java")
|
||||||
|
|
||||||
- name: Copy resources
|
- name: Copy resources
|
||||||
|
|||||||
Binary file not shown.
BIN
lib/flatlaf-3.7-sources.jar
Normal file
BIN
lib/flatlaf-3.7-sources.jar
Normal file
Binary file not shown.
BIN
lib/flatlaf-extras-3.7-javadoc.jar
Normal file
BIN
lib/flatlaf-extras-3.7-javadoc.jar
Normal file
Binary file not shown.
BIN
lib/flatlaf-extras-3.7-sources.jar
Normal file
BIN
lib/flatlaf-extras-3.7-sources.jar
Normal file
Binary file not shown.
BIN
lib/flatlaf-extras-3.7.jar
Normal file
BIN
lib/flatlaf-extras-3.7.jar
Normal file
Binary file not shown.
@@ -15,13 +15,22 @@ import javax.swing.LayoutStyle.ComponentPlacement;
|
|||||||
import javax.swing.GroupLayout;
|
import javax.swing.GroupLayout;
|
||||||
import javax.swing.GroupLayout.Alignment;
|
import javax.swing.GroupLayout.Alignment;
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
|
import com.formdev.flatlaf.FlatDarculaLaf;
|
||||||
|
import com.formdev.flatlaf.FlatIntelliJLaf;
|
||||||
|
import java.util.prefs.Preferences;
|
||||||
|
import com.formdev.flatlaf.FlatLaf;
|
||||||
|
import com.formdev.flatlaf.extras.FlatAnimatedLafChange;
|
||||||
import com.formdev.flatlaf.FlatClientProperties;
|
import com.formdev.flatlaf.FlatClientProperties;
|
||||||
|
import com.formdev.flatlaf.util.SystemInfo;
|
||||||
import dev.sillyangel.calc.themes.*;
|
import dev.sillyangel.calc.themes.*;
|
||||||
import dev.sillyangel.calc.CalculatorModes;
|
|
||||||
|
|
||||||
|
|
||||||
public class Calculator extends JFrame implements KeyListener {
|
public class Calculator extends JFrame implements KeyListener {
|
||||||
|
|
||||||
|
private static final String PREF_NODE_NAME = "dev/sillyangel/calc";
|
||||||
|
private static boolean
|
||||||
|
private static int
|
||||||
|
public static final Preferences prefs = Preferences.userRoot().node(PREF_NODE_NAME);
|
||||||
|
public static String APPILCATION_VERSION = "1.0.0pre";
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
private JPanel contentPane;
|
private JPanel contentPane;
|
||||||
private JTextField display;
|
private JTextField display;
|
||||||
@@ -36,15 +45,31 @@ public class Calculator extends JFrame implements KeyListener {
|
|||||||
protected double result;
|
protected double result;
|
||||||
private String[] Modes = new String[] {"Standard", "Scientific", "Data calculation"};
|
private String[] Modes = new String[] {"Standard", "Scientific", "Data calculation"};
|
||||||
private JComboBox<String> modeselect;
|
private JComboBox<String> modeselect;
|
||||||
|
private final CalculatorHistory history;
|
||||||
|
|
||||||
|
public static final String getVersion() {
|
||||||
|
return APPILCATION_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
// IntelliJTheme.setup(Calculator.class.getResourceAsStream("/DarkPurple.theme.json"));
|
// IntelliJTheme.setup(Calculator.class.getResourceAsStream("/DarkPurple.theme.json"));
|
||||||
// FlatMacDarkLaf.setup();
|
// FlatMacDarkLaf.setup();
|
||||||
// MacDarkRed.setup();
|
// MacDarkRed.setup();
|
||||||
MacDarkBlue.setup();
|
MacDarkBlue.setup();
|
||||||
|
System.out.println("\nangel's awesome calculator (acc) " + Calculator.getVersion());
|
||||||
|
System.out.println("created by angel");
|
||||||
|
System.out.println("---------------------------------");
|
||||||
|
if( SystemInfo.isMacOS ) {
|
||||||
|
System.setProperty( "apple.laf.useScreenMenuBar", "true" );
|
||||||
|
System.setProperty( "apple.awt.application.name", "Calculator" );
|
||||||
|
System.setProperty( "apple.awt.application.appearance", "system" );
|
||||||
|
}
|
||||||
|
if( SystemInfo.isLinux ) { // why is linux different
|
||||||
|
JFrame.setDefaultLookAndFeelDecorated(true);
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
// UIManager.setLookAndFeel("com.formdev.flatlaf.themes.FlatMacDarkLaf");
|
// UIManager.setLookAndFeel("com.formdev.flatlaf.themes.FlatMacDarkLaf");
|
||||||
|
UIManager.put("defaultFont", new Font("Segoe UI", Font.PLAIN, 29));
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
@@ -59,11 +84,12 @@ public class Calculator extends JFrame implements KeyListener {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public Calculator() {
|
public Calculator() {
|
||||||
|
history = new CalculatorHistory();
|
||||||
|
|
||||||
setBackground(new Color(32, 32, 32));
|
setBackground(new Color(32, 32, 32));
|
||||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
// setIconImage(Toolkit.getDefaultToolkit().getImage(Calculator.class.getResource("/images/appIcon.png")));
|
//setIconImage(Toolkit.getDefaultToolkit().getImage(Calculator.class.getResource("/images/appIcon.png")));
|
||||||
List<Image> icons = new ArrayList<>();
|
List<Image> icons = new ArrayList<>();
|
||||||
icons.add(Toolkit.getDefaultToolkit().getImage(Calculator.class.getResource("/images/appIcon16.png")));
|
icons.add(Toolkit.getDefaultToolkit().getImage(Calculator.class.getResource("/images/appIcon16.png")));
|
||||||
icons.add(Toolkit.getDefaultToolkit().getImage(Calculator.class.getResource("/images/appIcon32.png")));
|
icons.add(Toolkit.getDefaultToolkit().getImage(Calculator.class.getResource("/images/appIcon32.png")));
|
||||||
@@ -72,7 +98,7 @@ public class Calculator extends JFrame implements KeyListener {
|
|||||||
icons.add(Toolkit.getDefaultToolkit().getImage(Calculator.class.getResource("/images/appIcon512.png")));
|
icons.add(Toolkit.getDefaultToolkit().getImage(Calculator.class.getResource("/images/appIcon512.png")));
|
||||||
icons.add(Toolkit.getDefaultToolkit().getImage(Calculator.class.getResource("/images/appIcon1024.png")));
|
icons.add(Toolkit.getDefaultToolkit().getImage(Calculator.class.getResource("/images/appIcon1024.png")));
|
||||||
setIconImages(icons);
|
setIconImages(icons);
|
||||||
|
|
||||||
setTitle("AAC");
|
setTitle("AAC");
|
||||||
setBounds(100, 100, 368, 556);
|
setBounds(100, 100, 368, 556);
|
||||||
setFocusable(true);
|
setFocusable(true);
|
||||||
@@ -96,7 +122,8 @@ public class Calculator extends JFrame implements KeyListener {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
JPanel panel = new JPanel();
|
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
|
||||||
|
|
||||||
GroupLayout gl_contentPane = new GroupLayout(contentPane);
|
GroupLayout gl_contentPane = new GroupLayout(contentPane);
|
||||||
gl_contentPane.setHorizontalGroup(
|
gl_contentPane.setHorizontalGroup(
|
||||||
gl_contentPane.createParallelGroup(Alignment.LEADING)
|
gl_contentPane.createParallelGroup(Alignment.LEADING)
|
||||||
@@ -125,14 +152,55 @@ public class Calculator extends JFrame implements KeyListener {
|
|||||||
JMenuBar menubar = new JMenuBar();
|
JMenuBar menubar = new JMenuBar();
|
||||||
|
|
||||||
JMenu help = new JMenu("Help");
|
JMenu help = new JMenu("Help");
|
||||||
|
JMenu file = new JMenu("File");
|
||||||
|
JMenu edit = new JMenu("Edit");
|
||||||
|
/*
|
||||||
|
* Edit Will have
|
||||||
|
* Undo
|
||||||
|
* Redo
|
||||||
|
* Cut
|
||||||
|
* Copy
|
||||||
|
* Paste
|
||||||
|
* Delete which is just Backspace or Clear all a
|
||||||
|
* Settings
|
||||||
|
* */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
JMenuItem Exit = new JMenuItem("Exit");
|
||||||
|
Exit.addActionListener(e -> System.exit(1));
|
||||||
|
Exit.setMnemonic('E');
|
||||||
|
|
||||||
JMenuItem about = new JMenuItem("About");
|
JMenuItem about = new JMenuItem("About");
|
||||||
about.setMnemonic('A');
|
about.setMnemonic('A');
|
||||||
about.addActionListener(e -> aboutActionPerformed());
|
about.addActionListener(e -> aboutActionPerformed());
|
||||||
|
|
||||||
|
JMenuItem undo = new JMenuItem("Undo");
|
||||||
|
JMenuItem redo = new JMenuItem("Redo");
|
||||||
|
JMenuItem cut = new JMenuItem("Cut");
|
||||||
|
JMenuItem copy = new JMenuItem("Copy");
|
||||||
|
JMenuItem paste = new JMenuItem("Paste");
|
||||||
|
JMenuItem delete = new JMenuItem("Delete");
|
||||||
|
delete.addActionListener(e -> clearEntry());
|
||||||
|
JMenuItem preferencesm = new JMenuItem("Preferences");
|
||||||
|
preferencesm.setMnemonic('P');
|
||||||
|
preferencesm.addActionListener(e -> PreferencesAction());
|
||||||
|
|
||||||
|
edit.add(undo);
|
||||||
|
edit.add(redo);
|
||||||
|
edit.add(cut);
|
||||||
|
edit.add(copy);
|
||||||
|
edit.add(paste);
|
||||||
|
edit.add(delete);
|
||||||
|
edit.add(preferencesm);
|
||||||
|
|
||||||
|
file.add(Exit);
|
||||||
|
file.setMnemonic('F');
|
||||||
help.add(about);
|
help.add(about);
|
||||||
help.setMnemonic('H');
|
help.setMnemonic('H');
|
||||||
|
edit.setMnemonic('E');
|
||||||
|
menubar.add(file);
|
||||||
|
menubar.add(edit);
|
||||||
menubar.add(help);
|
menubar.add(help);
|
||||||
setJMenuBar(menubar);
|
setJMenuBar(menubar);
|
||||||
|
|
||||||
@@ -345,30 +413,30 @@ public class Calculator extends JFrame implements KeyListener {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
btnBackspace.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
// btnBackspace.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
||||||
btnClear.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
// btnClear.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
||||||
btnClearEntry.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
// btnClearEntry.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
||||||
btnPlusMin.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
// btnPlusMin.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
||||||
btnEq.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
// btnEq.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
||||||
btnDot.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
// btnDot.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
||||||
btn0.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
// btn0.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
||||||
btn1.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
// btn1.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
||||||
btn2.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
// btn2.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
||||||
btn3.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
// btn3.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
||||||
btn4.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
// btn4.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
||||||
btn5.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
// btn5.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
||||||
btn6.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
// btn6.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
||||||
btn7.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
// btn7.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
||||||
btn8.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
// btn8.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
||||||
btn9.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
// btn9.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
||||||
btnMul.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
// btnMul.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
||||||
btnMin.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
// btnMin.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
||||||
btnDiv.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
// btnDiv.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
||||||
btnPlus.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
// btnPlus.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
||||||
btnPercent.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
// btnPercent.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
||||||
btnReciprocal.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
// btnReciprocal.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
||||||
btnSquare.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
// btnSquare.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
||||||
btnSquareRoot.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
// btnSquareRoot.setFont(new Font("Segoe UI", Font.PLAIN, 29));
|
||||||
|
|
||||||
// Make all buttons non-focusable so keyboard input always goes to the frame because if we don't it breaks
|
// Make all buttons non-focusable so keyboard input always goes to the frame because if we don't it breaks
|
||||||
btnBackspace.setFocusable(false);
|
btnBackspace.setFocusable(false);
|
||||||
@@ -424,7 +492,86 @@ public class Calculator extends JFrame implements KeyListener {
|
|||||||
contentPane.setLayout(gl_contentPane);
|
contentPane.setLayout(gl_contentPane);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
private void PreferencesAction() {
|
||||||
|
JDialog dialog = new JDialog(this, "Preferences", true);
|
||||||
|
dialog.setSize(320, 220);
|
||||||
|
dialog.setLocationRelativeTo(this);
|
||||||
|
dialog.setLayout(new BorderLayout(10, 10));
|
||||||
|
|
||||||
|
JPanel panel = new JPanel();
|
||||||
|
panel.setBorder(new EmptyBorder(10, 10, 10, 10));
|
||||||
|
panel.setLayout(new GridLayout(0, 2, 8, 8));
|
||||||
|
|
||||||
|
// Theme selector
|
||||||
|
JComboBox<String> themeBox = new JComboBox<>(new String[]{"Dark", "Light"});
|
||||||
|
themeBox.setSelectedItem(prefs.get(PREF_THEME, "Dark"));
|
||||||
|
|
||||||
|
// Font size
|
||||||
|
JSpinner fontSizeSpinner = new JSpinner(
|
||||||
|
new SpinnerNumberModel(
|
||||||
|
prefs.getInt(PREF_FONT_SIZE, 22),
|
||||||
|
12, 48, 1
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Always on top
|
||||||
|
JCheckBox alwaysOnTopBox = new JCheckBox(
|
||||||
|
"Always on top",
|
||||||
|
prefs.getBoolean(PREF_ALWAYS_ON_TOP, false)
|
||||||
|
);
|
||||||
|
|
||||||
|
panel.add(new JLabel("Theme"));
|
||||||
|
panel.add(themeBox);
|
||||||
|
|
||||||
|
panel.add(new JLabel("Font size"));
|
||||||
|
panel.add(fontSizeSpinner);
|
||||||
|
|
||||||
|
panel.add(new JLabel(""));
|
||||||
|
panel.add(alwaysOnTopBox);
|
||||||
|
|
||||||
|
JButton apply = new JButton("Apply");
|
||||||
|
JButton close = new JButton("Close");
|
||||||
|
|
||||||
|
apply.addActionListener(e -> {
|
||||||
|
String theme = (String) themeBox.getSelectedItem();
|
||||||
|
int fontSize = (int) fontSizeSpinner.getValue();
|
||||||
|
boolean alwaysOnTop = alwaysOnTopBox.isSelected();
|
||||||
|
|
||||||
|
prefs.put(PREF_THEME, theme);
|
||||||
|
prefs.putInt(PREF_FONT_SIZE, fontSize);
|
||||||
|
prefs.putBoolean(PREF_ALWAYS_ON_TOP, alwaysOnTop);
|
||||||
|
|
||||||
|
applyPreferences(theme, fontSize, alwaysOnTop);
|
||||||
|
});
|
||||||
|
|
||||||
|
close.addActionListener(e -> dialog.dispose());
|
||||||
|
|
||||||
|
JPanel buttons = new JPanel(new FlowLayout(FlowLayout.RIGHT));
|
||||||
|
buttons.add(apply);
|
||||||
|
buttons.add(close);
|
||||||
|
|
||||||
|
dialog.add(panel, BorderLayout.CENTER);
|
||||||
|
dialog.add(buttons, BorderLayout.SOUTH);
|
||||||
|
dialog.setVisible(true);
|
||||||
|
}
|
||||||
|
private void applyPreferences(String theme, int fontSize, boolean alwaysOnTop) {
|
||||||
|
display.setFont(new Font("Segoe UI", Font.PLAIN, fontSize));
|
||||||
|
setAlwaysOnTop(alwaysOnTop);
|
||||||
|
|
||||||
|
try {
|
||||||
|
FlatAnimatedLafChange.showSnapshot();
|
||||||
|
if ("Light".equals(theme)) {
|
||||||
|
FlatIntelliJLaf.setup();
|
||||||
|
} else {
|
||||||
|
FlatDarculaLaf.setup();
|
||||||
|
}
|
||||||
|
FlatLaf.updateUI();
|
||||||
|
FlatAnimatedLafChange.hideSnapshotWithAnimation();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void aboutActionPerformed() {
|
private void aboutActionPerformed() {
|
||||||
JLabel titleLabel = new JLabel( "Angel's Awesome Calculator" );
|
JLabel titleLabel = new JLabel( "Angel's Awesome Calculator" );
|
||||||
titleLabel.putClientProperty( FlatClientProperties.STYLE_CLASS, "h1" );
|
titleLabel.putClientProperty( FlatClientProperties.STYLE_CLASS, "h1" );
|
||||||
@@ -451,6 +598,7 @@ public class Calculator extends JFrame implements KeyListener {
|
|||||||
titleLabel,
|
titleLabel,
|
||||||
"a very okay calculator app created in java (uses flatlaf)",
|
"a very okay calculator app created in java (uses flatlaf)",
|
||||||
" ",
|
" ",
|
||||||
|
"Version " + Calculator.getVersion(),
|
||||||
"Copyright " + Year.now() + " angel",
|
"Copyright " + Year.now() + " angel",
|
||||||
linkLabel,
|
linkLabel,
|
||||||
},
|
},
|
||||||
@@ -567,6 +715,42 @@ public class Calculator extends JFrame implements KeyListener {
|
|||||||
display.setText(""+result);
|
display.setText(""+result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void loadPreferences() {
|
||||||
|
int fontSize = prefs.getInt(PREF_FONT_SIZE, 22);
|
||||||
|
boolean alwaysOnTop = prefs.getBoolean(PREF_ALWAYS_ON_TOP, false);
|
||||||
|
|
||||||
|
display.setFont(new Font("Segoe UI", Font.PLAIN, fontSize));
|
||||||
|
setAlwaysOnTop(alwaysOnTop);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void changeThemes(String theme) {
|
||||||
|
boolean dark = switch (theme.toLowerCase()) {
|
||||||
|
case "dark", "darcula", "macdarkblue", "macdarkred" -> true;
|
||||||
|
default -> false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Only switch if needed
|
||||||
|
if (FlatLaf.isLafDark() != dark || isCustomMacTheme(theme)) {
|
||||||
|
EventQueue.invokeLater(() -> {
|
||||||
|
FlatAnimatedLafChange.showSnapshot();
|
||||||
|
try {
|
||||||
|
switch (theme.toLowerCase()) {
|
||||||
|
case "light" -> FlatIntelliJLaf.setup();
|
||||||
|
case "dark", "darcula" -> FlatDarculaLaf.setup();
|
||||||
|
case "macdarkblue" -> MacDarkBlue.setup();
|
||||||
|
case "macdarkred" -> MacDarkRed.setup();
|
||||||
|
default -> FlatDarculaLaf.setup();
|
||||||
|
}
|
||||||
|
FlatLaf.updateUI();
|
||||||
|
} finally {
|
||||||
|
FlatAnimatedLafChange.hideSnapshotWithAnimation();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Implement the keyPressed method
|
// Implement the keyPressed method
|
||||||
@Override
|
@Override
|
||||||
public void keyPressed(KeyEvent e) {
|
public void keyPressed(KeyEvent e) {
|
||||||
|
|||||||
138
src/main/java/dev/sillyangel/calc/CalculatorHistory.java
Normal file
138
src/main/java/dev/sillyangel/calc/CalculatorHistory.java
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
package dev.sillyangel.calc;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.file.*;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages calculation history for the calculator application.
|
||||||
|
* Stores calculations in a file and provides methods to retrieve and manage history.
|
||||||
|
*/
|
||||||
|
public class CalculatorHistory {
|
||||||
|
private final List<String> calculationHistory = new ArrayList<>();
|
||||||
|
private final Path historyFilePath;
|
||||||
|
private static final String HISTORY_DIR = System.getProperty("user.home") + File.separator + ".calculator";
|
||||||
|
private static final String HISTORY_FILE = "calc_history.txt";
|
||||||
|
private final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
|
public CalculatorHistory() {
|
||||||
|
historyFilePath = Paths.get(HISTORY_DIR, HISTORY_FILE);
|
||||||
|
initializeHistoryFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the history file and directory structure.
|
||||||
|
* Creates the directory and file if they don't exist, and loads existing history.
|
||||||
|
*/
|
||||||
|
private void initializeHistoryFile() {
|
||||||
|
try {
|
||||||
|
// Create directory if it doesn't exist
|
||||||
|
Path dir = Paths.get(HISTORY_DIR);
|
||||||
|
if (!Files.exists(dir)) {
|
||||||
|
Files.createDirectories(dir);
|
||||||
|
System.out.println("Created history directory: " + HISTORY_DIR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create file if it doesn't exist
|
||||||
|
if (!Files.exists(historyFilePath)) {
|
||||||
|
Files.createFile(historyFilePath);
|
||||||
|
System.out.println("Created history file: " + historyFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load existing history
|
||||||
|
loadHistory();
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.err.println("Error initializing history file: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves a calculation to the history file.
|
||||||
|
* @param calculation The calculation string to save (e.g., "5 + 3 = 8")
|
||||||
|
*/
|
||||||
|
public void saveToHistory(String calculation) {
|
||||||
|
try {
|
||||||
|
String timestamp = LocalDateTime.now().format(formatter);
|
||||||
|
String entry = "[" + timestamp + "] " + calculation;
|
||||||
|
|
||||||
|
// Add to memory list
|
||||||
|
calculationHistory.add(entry);
|
||||||
|
|
||||||
|
// Append to file
|
||||||
|
Files.write(historyFilePath,
|
||||||
|
(entry + System.lineSeparator()).getBytes(),
|
||||||
|
StandardOpenOption.APPEND);
|
||||||
|
|
||||||
|
System.out.println("Saved to history: " + entry);
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.err.println("Error saving to history: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads history from the file into memory.
|
||||||
|
*/
|
||||||
|
private void loadHistory() {
|
||||||
|
try {
|
||||||
|
if (Files.exists(historyFilePath)) {
|
||||||
|
List<String> lines = Files.readAllLines(historyFilePath);
|
||||||
|
calculationHistory.addAll(lines);
|
||||||
|
System.out.println("Loaded " + lines.size() + " history entries");
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.err.println("Error loading history: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a copy of all calculation history entries.
|
||||||
|
* @return A list of history entries with timestamps
|
||||||
|
*/
|
||||||
|
public List<String> getCalculationHistory() {
|
||||||
|
return new ArrayList<>(calculationHistory);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the most recent N history entries.
|
||||||
|
* @param count The number of entries to return
|
||||||
|
* @return A list of the most recent history entries
|
||||||
|
*/
|
||||||
|
public List<String> getRecentHistory(int count) {
|
||||||
|
int size = calculationHistory.size();
|
||||||
|
int fromIndex = Math.max(0, size - count);
|
||||||
|
return new ArrayList<>(calculationHistory.subList(fromIndex, size));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears all history entries from memory and file.
|
||||||
|
*/
|
||||||
|
public void clearHistory() {
|
||||||
|
try {
|
||||||
|
calculationHistory.clear();
|
||||||
|
Files.write(historyFilePath, new byte[0], StandardOpenOption.TRUNCATE_EXISTING);
|
||||||
|
System.out.println("History cleared");
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.err.println("Error clearing history: " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of history entries.
|
||||||
|
* @return The count of history entries
|
||||||
|
*/
|
||||||
|
public int getHistoryCount() {
|
||||||
|
return calculationHistory.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the path to the history file.
|
||||||
|
* @return The file path as a string
|
||||||
|
*/
|
||||||
|
public String getHistoryFilePath() {
|
||||||
|
return historyFilePath.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user