├── .gitignore ├── LICENSE ├── build.bat ├── docs ├── LICENSE ├── README.md └── screenshot.png ├── requirements.txt └── src ├── calculations.py ├── config.json ├── icon.ico └── main.py /.gitignore: -------------------------------------------------------------------------------- 1 | src/__pycache__/calculations.cpython-310.pyc 2 | desktop.ini 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Futura Software 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /build.bat: -------------------------------------------------------------------------------- 1 | cd src 2 | rmdir /s /q dist 3 | pyinstaller main.py --onedir --windowed --collect-data sv_ttk --icon "icon.ico" --add-data "config.json;." 4 | del main.spec 5 | xcopy icon.ico dist 6 | cd dist 7 | ren main.exe FluxCalc.exe -------------------------------------------------------------------------------- /docs/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 HuyHung1408 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |

FluxCalc

4 | 5 | 7 | 8 |

9 |

10 | 11 |

12 | 13 | ## About FluxCalc: 14 | A very simple calculator with a modern UI made in Python thanks to the stunning [Sun-Valley-ttk-theme](https://github.com/rdbende/Sun-Valley-ttk-theme) and Segoe UI Variable font. 15 | 16 | ### Usage: 17 | - Ctrl + M to disable/enable Mica (only for Windows 11). 18 | >Disabled Mica by default since users reported some issues with it. 19 | 20 | ### Supported Platforms: 21 | - Windows 10* and Windows 11. 22 | 23 | >*Need the Segoe UI Variable font to work properly! 24 | 25 | 26 | ### Other awesome repositories: 27 | - [TimerX](https://github.com/Futura-Py/TimerX) 29 | - [Sun-Valley-ttk-theme](https://github.com/rdbende/Sun-Valley-ttk-theme) 30 | -------------------------------------------------------------------------------- /docs/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Futura-Py/FluxCalc/56aea799ad7a71d251bd2aa9d799870aa3045402/docs/screenshot.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | win32mica 2 | darkdetect 3 | ntkutils >= 2.2.1 4 | pyinstaller 5 | strsplit 6 | sv_ttk -------------------------------------------------------------------------------- /src/calculations.py: -------------------------------------------------------------------------------- 1 | import strsplit 2 | 3 | calculation = "" 4 | 5 | def bracketcheck(): 6 | global calculation 7 | if "(" in calculation: 8 | for i in range(10): 9 | if strsplit.before(calculation, "(").endswith(str(i)): 10 | calculation = strsplit.before(calculation, "(") + "*" + str(eval(strsplit.inbetween(calculation, "(", ")"))) + strsplit.after(calculation, ")") 11 | if "(" in calculation and strsplit.before(calculation, "(") == "": 12 | calculation = strsplit.after(calculation, "(") 13 | calculation = str(eval(strsplit.before(calculation, ")"))) + strsplit.after(calculation, ")") 14 | bracketcheck() 15 | else: pass 16 | 17 | 18 | def _btnClick(key): 19 | global calculation 20 | calculation = calculation + str(key) 21 | return calculation 22 | 23 | def _btnEqualsInput(): 24 | global calculation 25 | try: 26 | bracketcheck() 27 | return [eval(calculation), calculation] 28 | except ZeroDivisionError: 29 | return ["r u dumb", ""] 30 | except: 31 | return ["Error", ""] 32 | 33 | def _backspace(): 34 | global calculation 35 | calculation = calculation[:-1] 36 | 37 | def _square(): 38 | global calculation 39 | try: 40 | int(calculation) 41 | squared = eval("{}*{}".format(calculation, calculation)) 42 | if str(squared).endswith(".0"): squared = str(squared).rstrip(".0") 43 | return [squared, calculation + '²'] 44 | except ValueError: 45 | if not calculation == "": 46 | return ["development", "feature still in"] 47 | else: 48 | return ["0", ""] -------------------------------------------------------------------------------- /src/config.json: -------------------------------------------------------------------------------- 1 | {"mica": "False"} -------------------------------------------------------------------------------- /src/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Futura-Py/FluxCalc/56aea799ad7a71d251bd2aa9d799870aa3045402/src/icon.ico -------------------------------------------------------------------------------- /src/main.py: -------------------------------------------------------------------------------- 1 | from tkinter import BooleanVar, ttk, Label, StringVar, messagebox 2 | import tkinter as tk 3 | import darkdetect, sv_ttk, ntkutils 4 | import calculations as c 5 | import webbrowser 6 | import json 7 | 8 | #region functions 9 | def aot(): 10 | if always_on_top.get() == 1: 11 | root.attributes('-topmost', True) 12 | else: 13 | root.attributes('-topmost', False) 14 | 15 | def btnClick(key): 16 | content.set(c._btnClick(key)) 17 | 18 | def btnClearDisplay(): 19 | content2.set("") 20 | content.set("") 21 | c.calculation = "" 22 | 23 | def backspace(event=None): 24 | c.calculation = c.calculation[:-1] 25 | content2.set("") 26 | content.set(c.calculation) 27 | 28 | def square(): 29 | result = c._square() 30 | content.set(result[0]) 31 | content2.set(result[1]) 32 | c.calculation = "" 33 | 34 | x = StringVar 35 | x = 0 36 | def btnEqualsInput(event=None): 37 | global x 38 | result = c._btnEqualsInput() 39 | content.set(result[0]) 40 | content2.set(result[1]) 41 | if content.get() == 'r u dumb': 42 | x += 1 43 | if x == 2: 44 | content.set("") 45 | c.calculation = "" 46 | messagebox.showerror("hey!", "Stop dividing by zero!") 47 | if x == 3: 48 | content.set("") 49 | c.calculation = "" 50 | e = messagebox.askyesno("hey!", "Seriously? Stop") 51 | if e == 'yes': 52 | pass 53 | else: 54 | webbrowser.open('https://www.youtube.com/watch?v=dQw4w9WgXcQ') 55 | if x == 4: 56 | content.set("") 57 | c.calculation = "" 58 | messagebox.showerror("Error", "FluxCalc will shut down if there is one more division by zero") 59 | if x == 5: 60 | content.set("") 61 | c.calculation = "" 62 | messagebox.showerror("Error", "FluxCalc will shut down in 5 seconds") 63 | root.destroy() 64 | 65 | def updateConfig(): 66 | with open("config.json", "w") as jsonfile: 67 | json.dump(data, jsonfile) 68 | jsonfile.close() 69 | 70 | with open("config.json", "r") as config: 71 | data = json.load(config) 72 | #endregion 73 | 74 | #region window 75 | root=tk.Tk() 76 | root.resizable(False, False) 77 | root.geometry('318x480') 78 | root.title('') 79 | root.iconbitmap(r'icon.ico') 80 | 81 | if darkdetect.theme() == "Dark": 82 | sv_ttk.set_theme("dark") 83 | ntkutils.dark_title_bar(root) 84 | else: 85 | sv_ttk.set_theme("light") 86 | 87 | def setmica(event=None): 88 | if data['mica'] == 'True': 89 | data['mica'] = 'False' 90 | micaval = "Off" 91 | else: 92 | data['mica'] = 'True' 93 | micaval = "On" 94 | 95 | updateConfig() 96 | content2.set("Mica: " + micaval) 97 | 98 | if data['mica'] == 'True': 99 | ntkutils.blur_window_background(root) 100 | if darkdetect.theme() == "Dark": 101 | ntkutils.dark_title_bar(root) 102 | else: 103 | pass 104 | 105 | #endregion 106 | 107 | always_on_top = BooleanVar() 108 | content= StringVar() 109 | content2 = StringVar() 110 | 111 | #region widgets 112 | Display = Label(root, textvariable=content, font=('Segoe UI Variable Display Semibold','35'),anchor="e",width=11).place(x=0, y=60) 113 | Display2 =Label(root,textvariable=content2, font=('Segoe UI Variable Display Semibold','15'),anchor="e",width=11, fg='#707476').place(x=162,y=30) 114 | 115 | btn1=ttk.Button(root, text="1", command=lambda:btnClick(1)).place(x=4, y=368, height=53, width=76) 116 | btn2=ttk.Button(root, text="2", command=lambda:btnClick(2)).place(x=82, y=368, height=53, width=76) 117 | btn3=ttk.Button(root, text="3", command=lambda:btnClick(3)).place(x=160, y=368, height=53, width=76) 118 | btn4=ttk.Button(root, text="4", command=lambda:btnClick(4)).place(x=4, y=313, height=53, width=76) 119 | btn5=ttk.Button(root, text="5", command=lambda:btnClick(5)).place(x=82, y=313, height=53, width=76) 120 | btn6=ttk.Button(root, text="6", command=lambda:btnClick(6)).place(x=160, y=313, height=53, width=76) 121 | btn7=ttk.Button(root, text="7", command=lambda:btnClick(7)).place(x=4, y=258, height=53, width=76) 122 | btn8=ttk.Button(root, text="8", command=lambda:btnClick(8)).place(x=82, y=258, height=53, width=76) 123 | btn9=ttk.Button(root, text="9", command=lambda:btnClick(9)).place(x=160, y=258, height=53, width=76) 124 | btn0=ttk.Button(root, text="0", command=lambda:btnClick(0)).place(x=4, y=423, height=53, width=154) 125 | 126 | alwaysontop=ttk.Checkbutton(root, text="", variable = always_on_top,onvalue=1, offvalue=0, style="Toggle.TButton",command=lambda:aot()).place(x=4, y=148, height=53, width=76) 127 | openbtn=ttk.Button(root, text="(", command=lambda:btnClick('(')).place(x=82, y=148, height=53, width=76) 128 | closebtn=ttk.Button(root, text=")", command=lambda:btnClick(')')).place(x=160, y=148, height=53, width=76) 129 | btnClear=ttk.Button(root, text="C", command=lambda:btnClearDisplay()).place(x=82, y= 203, height=53, width=76) 130 | Backspace = ttk.Button(root, text='', command=lambda:backspace()).place(x=160, y=203, height=53, width=76) 131 | btndot=ttk.Button(root, text=".", command=lambda:btnClick('.')).place(x=160, y=423, height=53, width=76) 132 | 133 | Divsion=ttk.Button(root, text="", command=lambda:btnClick("/")).place(x=238, y=148, height=53, width=76) 134 | Multiple=ttk.Button(root, text="", command=lambda:btnClick("*")).place(x=238, y=203, height=53, width=76) 135 | Subtraction=ttk.Button(root, text="", command=lambda:btnClick("-")).place(x=238, y=258, height=53, width=76) 136 | Addition=ttk.Button(root, text="", command=lambda:btnClick("+")).place(x=238, y=313, height=53, width=76) 137 | btnsquare=ttk.Button(root, text="x²", command=lambda:square()).place(x=4, y=203, height=53, width=76) 138 | equal=ttk.Button(root, text="", command=lambda:btnEqualsInput()).place(x=238, y=368, height=108, width=76) 139 | #endregion 140 | 141 | #Keyboard binding 142 | root.bind('', btnEqualsInput) 143 | root.bind('', backspace) 144 | root.bind("1", lambda e:btnClick(1)) 145 | root.bind("2", lambda e:btnClick(2)) 146 | root.bind("3", lambda e:btnClick(3)) 147 | root.bind("4", lambda e:btnClick(4)) 148 | root.bind("5", lambda e:btnClick(5)) 149 | root.bind("6", lambda e:btnClick(6)) 150 | root.bind("7", lambda e:btnClick(7)) 151 | root.bind("8", lambda e:btnClick(8)) 152 | root.bind("9", lambda e:btnClick(9)) 153 | root.bind("0", lambda e:btnClick(0)) 154 | root.bind("<+>", lambda e:btnClick("+")) 155 | root.bind("-", lambda e:btnClick("-")) 156 | root.bind("<*>", lambda e:btnClick("*")) 157 | root.bind("/", lambda e:btnClick("/")) 158 | root.bind("=", lambda e:btnEqualsInput()) 159 | root.bind("(", lambda e:btnClick("(")) 160 | root.bind(")", lambda e:btnClick(")")) 161 | root.bind('', setmica) 162 | #endregion 163 | 164 | root.mainloop() --------------------------------------------------------------------------------