Compare commits

54 Commits

Author SHA1 Message Date
751f878a32 Update src/main/java/dev/sillyangel/calc/Calculator.java
Some checks failed
Build the Jar / build (push) Failing after 9s
2025-12-22 08:48:39 -06:00
3d1d98ee7b Add src/main/java/dev/sillyangel/calc/CalculatorHistory.java
Some checks failed
Build the Jar / build (push) Failing after 6s
2025-12-22 08:44:41 -06:00
bf126de5b9 Update src/main/java/dev/sillyangel/calc/Calculator.java
Some checks failed
Build the Jar / build (push) Failing after 6s
2025-12-17 10:01:53 -06:00
485dccdf3b Update src/main/java/dev/sillyangel/calc/Calculator.java
Some checks failed
Build the Jar / build (push) Failing after 6s
2025-12-17 09:57:41 -06:00
5b9568013d Update src/main/java/dev/sillyangel/calc/Calculator.java
Some checks failed
Build the Jar / build (push) Failing after 7s
2025-12-17 09:54:05 -06:00
48c2e0abd9 Update .gitea/workflows/build.yml
All checks were successful
Build the Jar / build (push) Successful in 8s
2025-12-17 09:25:28 -06:00
ebdf464c31 Upload files to "lib"
Some checks failed
Build the Jar / build (push) Failing after 6s
2025-12-17 09:02:06 -06:00
b812535366 Update src/main/java/dev/sillyangel/calc/Calculator.java
Some checks failed
Build the Jar / build (push) Failing after 6s
2025-12-17 09:00:15 -06:00
a52fe8dc78 Update src/main/java/dev/sillyangel/calc/Calculator.java
Some checks failed
Build the Jar / build (push) Failing after 6s
2025-12-17 08:59:30 -06:00
cc2a625fc1 update something?
Some checks failed
Build the Jar / build (push) Failing after 6s
2025-12-17 08:53:50 -06:00
c7659bb44e Update src/main/java/dev/sillyangel/calc/Calculator.java
All checks were successful
Build the Jar / build (push) Successful in 9s
2025-12-17 08:47:08 -06:00
16e85a3fe3 delete now deletes 😭
Some checks failed
Build the Jar / build (push) Failing after 7s
2025-12-17 08:44:40 -06:00
c8aa7a9648 Update src/main/java/dev/sillyangel/calc/Calculator.java
All checks were successful
Build the Jar / build (push) Successful in 7s
2025-12-16 14:01:08 -06:00
cdc05c9b67 Update src/main/java/dev/sillyangel/calc/Calculator.java
All checks were successful
Build the Jar / build (push) Successful in 8s
2025-12-16 13:45:03 -06:00
250384e738 Update src/main/java/dev/sillyangel/calc/Calculator.java
All checks were successful
Build the Jar / build (push) Successful in 8s
2025-12-16 13:39:29 -06:00
1c749e1098 Update src/main/java/dev/sillyangel/calc/Calculator.java
All checks were successful
Build the Jar / build (push) Successful in 8s
2025-12-16 13:08:36 -06:00
c3756e1982 Update src/main/java/dev/sillyangel/calc/Calculator.java
All checks were successful
Build the Jar / build (push) Successful in 9s
2025-12-16 12:13:27 -06:00
97777f1046 Upload files to "lib"
All checks were successful
Build the Jar / build (push) Successful in 8s
2025-12-15 14:15:58 -06:00
c59fdc4430 Delete CalcShortforCalculator.jar
All checks were successful
Build the Jar / build (push) Successful in 7s
2025-12-15 14:12:05 -06:00
8499e364ae Update src/main/java/dev/sillyangel/calc/Calculator.java
All checks were successful
Build the Jar / build (push) Successful in 7s
2025-12-15 12:52:33 -06:00
f9c1ac535f Add src/main/java/dev/sillyangel/calc/themes/MacDarkBlue.properties
All checks were successful
Build the Jar / build (push) Successful in 7s
2025-12-15 12:09:46 -06:00
726923d589 Update src/main/java/dev/sillyangel/calc/themes/MacDarkRed.java
All checks were successful
Build the Jar / build (push) Successful in 7s
2025-12-15 12:06:16 -06:00
365d09854b Add src/main/java/dev/sillyangel/calc/themes/MacDarkBlue.java
Some checks failed
Build the Jar / build (push) Failing after 6s
2025-12-15 12:06:03 -06:00
508fe15ff9 Update src/main/java/dev/sillyangel/calc/themes/MacDarkRed.java
Some checks failed
Build the Jar / build (push) Failing after 9s
2025-12-15 12:05:48 -06:00
024db2edae Add src/main/java/dev/sillyangel/calc/themes/MacDarkRed.properties
All checks were successful
Build the Jar / build (push) Successful in 8s
2025-12-15 12:03:22 -06:00
3d2e0348ae Update src/main/java/dev/sillyangel/calc/themes/MacDarkRed.java
All checks were successful
Build the Jar / build (push) Successful in 7s
2025-12-15 12:02:55 -06:00
201c73a854 Add src/main/java/dev/sillyangel/calc/themes/MacDarkRed
Some checks failed
Build the Jar / build (push) Failing after 5s
2025-12-15 12:02:46 -06:00
44b8e74d56 Add src/main/java/dev/sillyangel/calc/CalculatorModes.java
Some checks failed
Build the Jar / build (push) Failing after 6s
2025-12-15 12:02:19 -06:00
d4f815d1e7 Update src/main/java/dev/sillyangel/calc/Calculator.java
Some checks failed
Build the Jar / build (push) Failing after 7s
2025-12-15 11:57:27 -06:00
6034304923 fix
All checks were successful
Build the Jar / build (push) Successful in 2m49s
2025-12-14 08:34:44 -06:00
d335a3dd80 fix
All checks were successful
Build the Jar / build (push) Successful in 9s
2025-12-14 08:26:58 -06:00
cfa433fd90 fixed build process and added project configuration files from idea
Some checks failed
Build the Jar / build (push) Failing after 11s
2025-12-14 08:22:47 -06:00
d472f6ac5e Upload files to "lib"
All checks were successful
Build the Jar / build (push) Successful in 5s
2025-12-12 13:07:07 -06:00
2854b9e7e9 Update src/main/java/dev/sillyangel/calc/Calculator.java
All checks were successful
Build the Jar / build (push) Successful in 5s
2025-12-12 13:06:41 -06:00
86854843e8 Add .gitea/workflows/build.yml
All checks were successful
Build the Jar / build (push) Successful in 2m18s
2025-12-12 09:33:49 -06:00
2474fc05b1 update to the new GUI version along with the addition to the new icons 2025-12-12 09:24:34 -06:00
eee5475548 Upload files to "src/main/java" 2025-12-12 09:21:28 -06:00
68ab7a427f Upload files to "src/main/resources/images" 2025-12-12 09:19:56 -06:00
ef1b5d98ef Delete src/main/resources/images/appIcon.png 2025-12-12 09:19:46 -06:00
77359ae842 Upload files to "src/main/resources/images" 2025-12-12 09:19:41 -06:00
3b063c74ba Upload files to "src/main/resources" 2025-12-12 09:19:09 -06:00
536e462d1f Delete src/main/resources/appIcon.png 2025-12-12 09:18:46 -06:00
4bda32d6cd Update .classpath 2025-12-12 09:18:21 -06:00
2b74166b70 Update .project 2025-12-12 09:16:14 -06:00
3c10f531e3 Update README.md 2025-12-11 12:50:11 -06:00
27c36aad36 Upload files to "/" 2025-12-11 12:49:58 -06:00
db04a8b1aa Upload files to "/" 2025-12-11 12:49:40 -06:00
4683e38fe3 Upload files to "/" 2025-12-11 12:48:53 -06:00
f03af67a33 Delete Screenshot 2025-11-13 122107.png 2025-12-11 12:48:43 -06:00
c785d221d2 Update src/main/java/dev/sillyangel/calc/Calculator.java 2025-11-14 12:54:59 -06:00
02467170a8 Update README.md 2025-11-13 12:22:08 -06:00
0ba07ca47c Upload files to "/" 2025-11-13 12:21:49 -06:00
a6f5bee680 Update src/main/java/dev/sillyangel/calc/Calculator.java 2025-11-13 12:20:44 -06:00
83ff39dd9f Update src/main/java/dev/sillyangel/calc/Calculator.java 2025-11-13 11:57:20 -06:00
41 changed files with 959 additions and 244 deletions

View File

@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="src/main/java"/>
<classpathentry kind="src" path="src/main/resources"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-21">
<attributes>
<attribute name="module" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@@ -0,0 +1,61 @@
name: Build the Jar
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- name: Set up JDK 20
uses: actions/setup-java@v5
with:
java-version: '20'
distribution: 'temurin'
- name: Create output directories
run: |
mkdir -p out/production/Calc
mkdir -p dist
- name: Compile Java files
run: |
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")
- name: Copy resources
run: |
if [ -d "src/main/resources" ]; then
cp -r src/main/resources/* out/production/Calc/ 2>/dev/null || true
fi
- name: Extract FlatLaf library
run: |
cd out/production/Calc
jar xf ../../../lib/flatlaf-3.7.jar
# Remove META-INF to avoid conflicts
rm -rf META-INF
cd ../../..
- name: Create manifest
run: |
echo "Manifest-Version: 1.0" > manifest.txt
echo "Main-Class: dev.sillyangel.calc.Calculator" >> manifest.txt
- name: Create fat JAR
run: |
cd out/production/Calc
jar cfm ../../../dist/CalcShortforCalculator.jar ../../../manifest.txt .
cd ../../..
- name: Upload JAR artifact
uses: actions/upload-artifact@v3
with:
name: CalcShortforCalculator
path: dist/CalcShortforCalculator.jar

3
.gitignore vendored
View File

@@ -1,3 +1,4 @@
/bin/
bin
*.class
*.class
out

10
.idea/.gitignore generated vendored Normal file
View File

@@ -0,0 +1,10 @@
# Default ignored files
/shelf/
/workspace.xml
# Ignored default folder with query files
/queries/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/

6
.idea/copilot.data.migration.agent.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AgentMigrationStateService">
<option name="migrationStatus" value="COMPLETED" />
</component>
</project>

6
.idea/copilot.data.migration.ask.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AskMigrationStateService">
<option name="migrationStatus" value="COMPLETED" />
</component>
</project>

6
.idea/copilot.data.migration.edit.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EditMigrationStateService">
<option name="migrationStatus" value="COMPLETED" />
</component>
</project>

7
.idea/discord.xml generated Normal file
View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DiscordProjectSettings">
<option name="show" value="APPLICATION" />
<option name="description" value="" />
</component>
</project>

10
.idea/libraries/lib.xml generated Normal file
View File

@@ -0,0 +1,10 @@
<component name="libraryTable">
<library name="lib">
<CLASSES>
<root url="jar://$PROJECT_DIR$/lib/flatlaf-3.7.jar!/" />
<root url="jar://$PROJECT_DIR$/lib/flatlaf-3.7-javadoc.jar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>

6
.idea/misc.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_20" project-jdk-name="temurin-20" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

8
.idea/modules.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/Calc.iml" filepath="$PROJECT_DIR$/Calc.iml" />
</modules>
</component>
</project>

6
.idea/vcs.xml generated Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
</component>
</project>

View File

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>CalculatorButBetter</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
<filteredResources>
<filter>
<id>1762972468245</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.core.resources.regexFilterMatcher</id>
<arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription>

View File

@@ -1,2 +0,0 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8

View File

@@ -1,12 +0,0 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=20
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=20
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=warning
org.eclipse.jdt.core.compiler.release=enabled
org.eclipse.jdt.core.compiler.source=20

15
Calc.iml Normal file
View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/.gitea" />
<excludeFolder url="file://$MODULE_DIR$/.idea" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="lib" level="project" />
</component>
</module>

Binary file not shown.

View File

@@ -1,2 +1,4 @@
you need java 20 to run this, THIS IS NONTHING BAD JUST A CALCULATOR NOTHING MUCH :sob:
anyway, this might be the best or the worst calculator you have ever seen!?1
anyway, this might be the best or the worst calculator you have ever seen!?1
![image](https://git.sillyangel.dev/angel/calc/raw/branch/main/screenshot.png)

BIN
lib/flatlaf-3.7-javadoc.jar Normal file

Binary file not shown.

BIN
lib/flatlaf-3.7-sources.jar Normal file

Binary file not shown.

BIN
lib/flatlaf-3.7.jar Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
lib/flatlaf-extras-3.7.jar Normal file

Binary file not shown.

BIN
screenshot.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -1,42 +1,75 @@
package dev.sillyangel.calc;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
//a b c d e f g h i j k l m n o p q r s t u v w x y z
// java to javax, com, dev
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
import java.io.IOException;
import java.net.URI;
import java.time.Year;
import java.net.URISyntaxException;
import javax.swing.border.EmptyBorder;
import javax.swing.UIManager;
import javax.swing.LayoutStyle.ComponentPlacement;
import javax.swing.GroupLayout;
import javax.swing.GroupLayout.Alignment;
import javax.swing.JTextField;
import java.awt.GridLayout;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.Color;
import java.awt.Font;
import java.awt.Toolkit;
import javax.swing.JMenuBar;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
public class Calculator extends JFrame {
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.util.SystemInfo;
import dev.sillyangel.calc.themes.*;
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 JPanel contentPane;
private JTextField display;
private String operand1;
private String operator;
private String operand2;
private JButton btnDiv;
private JButton btnMul;
private JButton btnMin;
private JButton btnPlus;
protected boolean resultVisible;
protected double result;
private String[] Modes = new String[] {"Standard", "Scientific", "Data calculation"};
private JComboBox<String> modeselect;
private final CalculatorHistory history;
/**
* Launch the application.
*/
public static final String getVersion() {
return APPILCATION_VERSION;
}
public static void main(String[] args) {
// IntelliJTheme.setup(Calculator.class.getResourceAsStream("/DarkPurple.theme.json"));
// FlatMacDarkLaf.setup();
// MacDarkRed.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 {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
// UIManager.setLookAndFeel("com.formdev.flatlaf.themes.FlatMacDarkLaf");
UIManager.put("defaultFont", new Font("Segoe UI", Font.PLAIN, 29));
} catch (Throwable e) {
e.printStackTrace();
}
@@ -51,59 +84,163 @@ public class Calculator extends JFrame {
}
});
}
/**
* Create the frame.
*/
public Calculator() {
history = new CalculatorHistory();
setBackground(new Color(32, 32, 32));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setIconImage(Toolkit.getDefaultToolkit().getImage(Calculator.class.getResource("/images/appIcon.png")));
setTitle("Calc (short for calculator)");
setBounds(100, 100, 634, 553);
//setIconImage(Toolkit.getDefaultToolkit().getImage(Calculator.class.getResource("/images/appIcon.png")));
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/appIcon32.png")));
icons.add(Toolkit.getDefaultToolkit().getImage(Calculator.class.getResource("/images/appIcon48.png")));
icons.add(Toolkit.getDefaultToolkit().getImage(Calculator.class.getResource("/images/appIcon256.png")));
icons.add(Toolkit.getDefaultToolkit().getImage(Calculator.class.getResource("/images/appIcon512.png")));
icons.add(Toolkit.getDefaultToolkit().getImage(Calculator.class.getResource("/images/appIcon1024.png")));
setIconImages(icons);
JMenuBar menuBar = new JMenuBar();
JMenu fileMenu = new JMenu("File");
JMenuItem exitItem = new JMenuItem("Exit");
exitItem.addActionListener(e -> System.exit(0));
fileMenu.add(exitItem);
menuBar.add(fileMenu);
setJMenuBar(menuBar);
setTitle("AAC");
setBounds(100, 100, 368, 556);
setFocusable(true);
addKeyListener(this);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
display = new JTextField();
display.setForeground(new Color(30, 144, 255));
display.setBackground(new Color(255, 255, 255));
display.setEditable(false);
display.setFont(new Font("Tahoma", Font.PLAIN, 22));
display.setFont(new Font("Segoe UI", Font.PLAIN, 22));
display.setColumns(10);
JPanel buttonPanel = new JPanel();
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
Dimension size = e.getComponent().getSize();
System.out.println("Window resized to " + size.width + "x" + size.height);
}
});
JPanel panel = new JPanel(new FlowLayout(FlowLayout.LEFT));
GroupLayout gl_contentPane = new GroupLayout(contentPane);
gl_contentPane.setHorizontalGroup(
gl_contentPane.createParallelGroup(Alignment.LEADING)
.addGroup(Alignment.TRAILING, gl_contentPane.createSequentialGroup()
.addGroup(gl_contentPane.createSequentialGroup()
.addContainerGap()
.addGroup(gl_contentPane.createParallelGroup(Alignment.TRAILING)
.addComponent(buttonPanel, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 587, Short.MAX_VALUE)
.addComponent(display, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 587, Short.MAX_VALUE))
.addComponent(display, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 359, Short.MAX_VALUE)
.addComponent(buttonPanel, Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 359, Short.MAX_VALUE))
.addContainerGap())
.addComponent(panel, Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, 379, Short.MAX_VALUE)
);
gl_contentPane.setVerticalGroup(
gl_contentPane.createParallelGroup(Alignment.LEADING)
.addGroup(gl_contentPane.createSequentialGroup()
.addGap(23)
.addComponent(panel, GroupLayout.PREFERRED_SIZE, 36, GroupLayout.PREFERRED_SIZE)
.addPreferredGap(ComponentPlacement.RELATED)
.addComponent(display, GroupLayout.PREFERRED_SIZE, 78, GroupLayout.PREFERRED_SIZE)
.addGap(18)
.addComponent(buttonPanel, GroupLayout.DEFAULT_SIZE, 349, Short.MAX_VALUE)
.addContainerGap())
.addGap(27)
.addComponent(buttonPanel, GroupLayout.PREFERRED_SIZE, 359, GroupLayout.PREFERRED_SIZE)
.addContainerGap(199, Short.MAX_VALUE))
);
buttonPanel.setLayout(new GridLayout(0, 5, 0, 0));
buttonPanel.setLayout(new GridLayout(0, 4, 0, 0));
// Menu Bar
JMenuBar menubar = new JMenuBar();
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");
about.setMnemonic('A');
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.setMnemonic('H');
edit.setMnemonic('E');
menubar.add(file);
menubar.add(edit);
menubar.add(help);
setJMenuBar(menubar);
modeselect = new JComboBox<>(Modes);
modeselect.addActionListener(new ActionListener() {
@SuppressWarnings("unchecked")
public void actionPerformed(ActionEvent e) {
JComboBox<String> cb = (JComboBox<String>)e.getSource();
String Mode = (String)cb.getSelectedItem();
UpdateMode(Mode);
}
});
modeselect.setEditable(false);
modeselect.setFocusable(false);
JButton btnNewButton_1 = new JButton("New button");
btnNewButton_1.setFocusable(false);
JLabel lblNewLabel = new JLabel("New label");
lblNewLabel.setFocusable(false);
btnNewButton_1.setVisible(false);
lblNewLabel.setVisible(false);
panel.add(modeselect);
panel.add(lblNewLabel);
panel.add(btnNewButton_1);
JButton btnPercent = new JButton("%");
JButton btnClearEntry = new JButton("CE");
JButton btnReciprocal = new JButton("1/x");
JButton btnSquare = new JButton("");
JButton btnSquareRoot = new JButton("√x");
// Use FlatLaf Tree.icon.collapsed as backspace-like icon (or just use text)
JButton btnBackspace = new JButton("");
JButton btnClear = new JButton("C");
JButton btnPlusMin = new JButton("+/-");
JButton btnDot = new JButton(".");
JButton btnEq = new JButton("=");
JButton btn0 = new JButton("0");
JButton btn1 = new JButton("1");
JButton btn2 = new JButton("2");
@@ -111,112 +248,138 @@ public class Calculator extends JFrame {
JButton btn4 = new JButton("4");
JButton btn5 = new JButton("5");
JButton btn6 = new JButton("6"); // why was 6 afraid of 7... because 7 8 9 :sob:
JButton btn7 = new JButton("7"); // 67!
JButton btn7 = new JButton("7"); // 67!
JButton btn8 = new JButton("8");
JButton btn9 = new JButton("9");
btn0.setFont(new Font("Tahoma", Font.PLAIN, 29));
btnDiv = new JButton("/");
btnMul = new JButton("*");
btnMin = new JButton("-");
btnPlus = new JButton("+");
btnDot.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String n = display.getText(); // get the text on the display
if (n.contains(".")) return; // if it already contains a "." skip rest of this
processDigit(e.getActionCommand());
}
});
btnEq.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
math();
}
});
btnBackspace.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
backspace();
}
});
btnClearEntry.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
clearEntry();
}
});
btnClear.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
clearAll();
}
});
btnPlus.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setOperator(e.getActionCommand());
}
});
btnDiv.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setOperator(e.getActionCommand());
}
});
btnMul.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setOperator(e.getActionCommand());
}
});
btnMin.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setOperator(e.getActionCommand());
}
});
btn0.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
processDigit(e.getActionCommand());
}
});
btn1.setFont(new Font("Tahoma", Font.PLAIN, 29));
btn1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
processDigit(e.getActionCommand());
}
});
btn2.setFont(new Font("Tahoma", Font.PLAIN, 29));
btn2.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
processDigit(e.getActionCommand());
}
});
btn3.setFont(new Font("Tahoma", Font.PLAIN, 29));
btn3.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
processDigit(e.getActionCommand());
}
});
btn4.setFont(new Font("Tahoma", Font.PLAIN, 29));
btn4.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
processDigit(e.getActionCommand());
}
});
btn5.setFont(new Font("Tahoma", Font.PLAIN, 29));
btn5.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
processDigit(e.getActionCommand());
}
});
btn6.setFont(new Font("Tahoma", Font.PLAIN, 29));
btn6.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
processDigit(e.getActionCommand());
}
});
btn7.setFont(new Font("Tahoma", Font.PLAIN, 29));
btn7.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
processDigit(e.getActionCommand());
}
});
btn8.setFont(new Font("Tahoma", Font.PLAIN, 29));
btn8.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
processDigit(e.getActionCommand());
}
});
btn9.setFont(new Font("Tahoma", Font.PLAIN, 29));
btn9.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
processDigit(e.getActionCommand());
}
});
// other stuff
JButton btnErase = new JButton("DEL");
JButton empty = new JButton("");
JButton btnClear = new JButton("C");
JButton btnPlusMin = new JButton("+/-");
JButton btnDot = new JButton(".");
btnErase.setFont(new Font("Tahoma", Font.PLAIN, 29));
btnErase.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
clear();
}
});
empty.setBackground(Color.WHITE);
empty.setEnabled(false);
btnClear.setFont(new Font("Tahoma", Font.PLAIN, 29));
btnClear.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
clear();
}
});
btnPlusMin.setFont(new Font("Tahoma", Font.PLAIN, 29));
btnPlusMin.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String tmp = display.getText();
if (tmp == null || tmp.isEmpty()) return;
char first = tmp.charAt(0);
if (first == '-') {
tmp = tmp.substring(1, tmp.length());
tmp = tmp.substring(1, tmp.length());
display.setText(tmp);
} else {
display.setText("-" + tmp);
@@ -224,127 +387,239 @@ public class Calculator extends JFrame {
}
});
btnDot.setFont(new Font("Tahoma", Font.PLAIN, 29));
btnDot.addActionListener(new ActionListener() {
btnPercent.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String n = display.getText(); // get the text on the display
if (n.contains(".")) return; // if it already contains a "." skip rest of this
processDigit(e.getActionCommand());
}
});
// math stuff
JButton btnDiv = new JButton("/");
JButton btnMul = new JButton("*");
JButton btnMin = new JButton("-");
JButton btnPlus = new JButton("+");
btnDiv.setFont(new Font("Tahoma", Font.PLAIN, 29));
btnDiv.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setOperator(e.getActionCommand());
btnDiv.setForeground(new Color(30, 144, 255));
btnMul.setForeground(new Color(0, 0, 0));
btnPlus.setForeground(new Color(0, 0, 0));
btnMin.setForeground(new Color(0, 0, 0));
setOperator("%");
}
});
btnMul.setFont(new Font("Tahoma", Font.PLAIN, 29));
btnMul.addActionListener(new ActionListener() {
btnReciprocal.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setOperator(e.getActionCommand());
btnDiv.setForeground(new Color(0, 0, 0));
btnMul.setForeground(new Color(30, 144, 255));
btnPlus.setForeground(new Color(0, 0, 0));
btnMin.setForeground(new Color(0, 0, 0));
reciprocal();
}
});
btnMin.setFont(new Font("Tahoma", Font.PLAIN, 29));
btnMin.addActionListener(new ActionListener() {
btnSquare.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setOperator(e.getActionCommand());
btnDiv.setForeground(new Color(0, 0, 0));
btnMul.setForeground(new Color(0, 0, 0));
btnPlus.setForeground(new Color(0, 0, 0));
btnMin.setForeground(new Color(30, 144, 255));
square();
}
});
btnPlus.setFont(new Font("Tahoma", Font.PLAIN, 29));
btnPlus.addActionListener(new ActionListener() {
btnSquareRoot.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
setOperator(e.getActionCommand());
btnDiv.setForeground(new Color(0, 0, 0));
btnMul.setForeground(new Color(0, 0, 0));
btnPlus.setForeground(new Color(30, 144, 255));
btnMin.setForeground(new Color(0, 0, 0));
squareRoot();
}
});
JButton btnEq = new JButton("=");
btnEq.setFont(new Font("Tahoma", Font.PLAIN, 29));
btnEq.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
operand2 = display.getText();
double o1 = Double.parseDouble(operand1);
double o2 = Double.parseDouble(operand2);
if (operator == "+") {
result = o1+o2;
} else if (operator == "-") {
result = o1-o2;
} else if (operator == "*") {
result = o1*o2;
} else if (operator == "/") {
result = o1/o2;
}
operator = "";
operand1 = "";
operand2 = "";
btnDiv.setForeground(new Color(0, 0, 0));
btnMul.setForeground(new Color(0, 0, 0));
btnPlus.setForeground(new Color(0, 0, 0));
btnMin.setForeground(new Color(0, 0, 0));
resultVisible = true;
display.setText(""+result);
}
});
// btnBackspace.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));
// btnPlusMin.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));
// btn0.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));
// btn3.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));
// btn6.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));
// btn9.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));
// btnDiv.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));
// btnReciprocal.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));
// Make all buttons non-focusable so keyboard input always goes to the frame because if we don't it breaks
btnBackspace.setFocusable(false);
btnClear.setFocusable(false);
btnClearEntry.setFocusable(false);
btnPlusMin.setFocusable(false);
btnEq.setFocusable(false);
btnDot.setFocusable(false);
btn0.setFocusable(false);
btn1.setFocusable(false);
btn2.setFocusable(false);
btn3.setFocusable(false);
btn4.setFocusable(false);
btn5.setFocusable(false);
btn6.setFocusable(false);
btn7.setFocusable(false);
btn8.setFocusable(false);
btn9.setFocusable(false);
btnMul.setFocusable(false);
btnMin.setFocusable(false);
btnDiv.setFocusable(false);
btnPlus.setFocusable(false);
btnPercent.setFocusable(false);
btnReciprocal.setFocusable(false);
btnSquare.setFocusable(false);
btnSquareRoot.setFocusable(false);
buttonPanel.add(btnPercent);
buttonPanel.add(btnClearEntry);
buttonPanel.add(btnClear);
buttonPanel.add(btnBackspace);
buttonPanel.add(btnReciprocal);
buttonPanel.add(btnSquare);
buttonPanel.add(btnSquareRoot);
buttonPanel.add(btnDiv);
buttonPanel.add(btn7);
buttonPanel.add(btn8);
buttonPanel.add(btn9);
buttonPanel.add(btnDiv);
buttonPanel.add(btnErase);
buttonPanel.add(btnMul);
buttonPanel.add(btn4);
buttonPanel.add(btn5);
buttonPanel.add(btn6);
buttonPanel.add(btnMul);
buttonPanel.add(btnClear);
buttonPanel.add(btnMin);
buttonPanel.add(btn1);
buttonPanel.add(btn2);
buttonPanel.add(btn3);
buttonPanel.add(btnPlus);
buttonPanel.add(empty);
buttonPanel.add(btnPlusMin);
buttonPanel.add(btn0);
buttonPanel.add(btnDot);
buttonPanel.add(btnMin);
buttonPanel.add(btnEq);
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));
protected void clear() {
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() {
JLabel titleLabel = new JLabel( "Angel's Awesome Calculator" );
titleLabel.putClientProperty( FlatClientProperties.STYLE_CLASS, "h1" );
String link = "https://git.sillyangel.dev/angel/calc";
JLabel linkLabel = new JLabel( "<html><a href=\"#\">" + link + "</a></html>" );
linkLabel.setCursor( Cursor.getPredefinedCursor( Cursor.HAND_CURSOR ) );
linkLabel.addMouseListener( new MouseAdapter() {
@Override
public void mouseClicked( MouseEvent e ) {
try {
Desktop.getDesktop().browse( new URI( link ) );
} catch( IOException | URISyntaxException ex ) {
JOptionPane.showMessageDialog( linkLabel,
"Failed to open '" + link + "' in browser.",
"About", JOptionPane.PLAIN_MESSAGE );
}
}
} );
JOptionPane.showMessageDialog( this,
new Object[] {
titleLabel,
"a very okay calculator app created in java (uses flatlaf)",
" ",
"Version " + Calculator.getVersion(),
"Copyright " + Year.now() + " angel",
linkLabel,
},
"About", JOptionPane.PLAIN_MESSAGE );
}
private void UpdateMode(String Mode) {
if (Mode == "Standard") {
System.out.println("User has Selected Standard");
} else if (Mode == "Scientific") {
// System.out.println("User has Selected Scientific Calculator");
CalculatorModes.Scientific();
} else if (Mode == "Data calculation") {
// System.out.println("User has Selected Date calculation mode");
CalculatorModes.DateCalculation();
} else {
System.out.println(Mode);
}
}
private void backspace() {
String tmp = display.getText();
if (tmp.length()>1) // if there is more than 1 character
display.setText( tmp.substring(0, tmp.length()-1) );
@@ -352,17 +627,170 @@ public class Calculator extends JFrame {
display.setText("");
}
protected void processDigit(String actionCommand) {
private void clearEntry() {
// Clear only the current display (entry)
display.setText("");
}
private void clearAll() {
// Clear everything including operands and operator
display.setText("");
operand1 = "";
operand2 = "";
operator = "";
resultVisible = false;
}
private void reciprocal() {
String tmp = display.getText();
if (tmp == null || tmp.isEmpty()) return;
double value = Double.parseDouble(tmp);
if (value != 0) {
result = 1.0 / value;
display.setText("" + result);
resultVisible = true;
}
}
private void square() {
String tmp = display.getText();
if (tmp == null || tmp.isEmpty()) return;
double value = Double.parseDouble(tmp);
result = value * value;
display.setText("" + result);
resultVisible = true;
}
private void squareRoot() {
String tmp = display.getText();
if (tmp == null || tmp.isEmpty()) return;
double value = Double.parseDouble(tmp);
if (value >= 0) {
result = Math.sqrt(value);
display.setText("" + result);
resultVisible = true;
}
}
private void processDigit(String actionCommand) {
if (resultVisible == true) {
display.setText("");
resultVisible = false;
}
display.setText(display.getText() + actionCommand);
}
protected void setOperator(String actionCommand) {
private void setOperator(String daop) {
operand1 = display.getText();
operator = actionCommand;
operator = daop;
display.setText("");
}
private void math() {
operand2 = display.getText();
double op1 = Double.parseDouble(operand1);
double op2 = Double.parseDouble(operand2);
if (operator == "+") {
result = op1+op2;
} else if (operator == "-") {
result = op1-op2;
} else if (operator == "*") {
result = op1*op2;
} else if (operator == "/") {
result = op1/op2;
} else if (operator == "%") {
result = op1 % op2;
} else {
result = op2;
System.out.println("Op: " + op1);
System.out.println("Op2: " + op2);
}
operator = "";
operand1 = "";
operand2 = "";
resultVisible = true;
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
@Override
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
// System.out.println("Key Pressed: " + KeyEvent.getKeyText(keyCode));
if (KeyEvent.getKeyText(keyCode) == "Enter") {
math();
} else if (e.getKeyCode() == KeyEvent.VK_BACK_SPACE) {
backspace();
}
}
// Implement the keyReleased method
@Override
public void keyReleased(KeyEvent e) {
// int keyCode = e.getKeyCode();
// System.out.println("Key Released: " + KeyEvent.getKeyText(keyCode));
}
// Implement the keyTyped method
@Override
public void keyTyped(KeyEvent e) {
char c = e.getKeyChar();
// System.out.println("Key Typed: " + keyChar);
System.out.println(c + " KT");
if (c >= '0' && c <= '9') {
processDigit(String.valueOf(c));
}
if (c == '+') {
setOperator("+");
} else if (c == '*') {
setOperator("*");
} else if (c == '/') {
setOperator("/");
} else if (c == '-') {
setOperator("-");
}
if (c == '=') {
math();
}
}
}

View 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();
}
}

View File

@@ -0,0 +1,12 @@
package dev.sillyangel.calc;
import javax.swing.JFrame;
public class CalculatorModes extends JFrame {
public static void Scientific() {
}
public static void DateCalculation() {
}
}

View File

@@ -0,0 +1,20 @@
package dev.sillyangel.calc.themes;
import com.formdev.flatlaf.themes.FlatMacDarkLaf;
public class MacDarkBlue extends FlatMacDarkLaf {
public static final String NAME = "MacDarkBlue";
public static boolean setup() {
return setup( new MacDarkBlue() );
}
public static void installLafInfo() {
installLafInfo( NAME, MacDarkBlue.class );
}
@Override
public String getName() {
return NAME;
}
}

View File

@@ -0,0 +1,4 @@
# base theme (light, dark, intellij, darcula, maclight or macdark); only used by theme editor
@baseTheme = macdark
@accentColor = #0e59c3ff

View File

@@ -0,0 +1,20 @@
package dev.sillyangel.calc.themes;
import com.formdev.flatlaf.themes.FlatMacDarkLaf;
public class MacDarkRed extends FlatMacDarkLaf {
public static final String NAME = "MacDarkRed";
public static boolean setup() {
return setup( new MacDarkRed() );
}
public static void installLafInfo() {
installLafInfo( NAME, MacDarkRed.class );
}
@Override
public String getName() {
return NAME;
}
}

View File

@@ -0,0 +1,2 @@
@baseTheme = macdark
@accentColor = #a83e32

Binary file not shown.

Before

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 451 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB