import gradio as gr from typing import Literal import re from dotenv import load_dotenv load_dotenv() Operation = Literal["+", "-", "x", "/"] currOp: Operation = None currInput = 0 currOutput = 0 def __cleanedOutput(output: str) -> str: if output == "0": return "" print(f"==={output=}") # output = str(round(float(output), 3)) return output.rstrip('0').rstrip('.') if '.' in output else output def calc(input1: str, input2: str, operation: Operation) -> float: input1 = float(input1) input2 = float(input2) if operation == "+": return input1 + input2 if operation == "-": return input1 - input2 if operation == "x": return input1 * input2 if operation == "/": return input1 / input2 def calcAndSetOutput(outputBoxValue: str, isFinalCalc: bool = True): global currOp global currInput global currOutput isOutputSingleNumber = len(re.sub(r"[0-9\.]", "", outputBoxValue)) == 0 print(f"{isOutputSingleNumber=}") if isOutputSingleNumber: currOutput = float(outputBoxValue) else: currOutput = calc(currOutput, currInput, currOp) if isFinalCalc: newOutputBoxValue = __cleanedOutput(str(currOutput)) print(f"{newOutputBoxValue=}") currOp = None else: newOutputBoxValue = __cleanedOutput(outputBoxValue) + currOp currInput = 0 return newOutputBoxValue def reset(): global currOp global currInput global currOutput currOp = None currInput = 0 currOutput = 0 return currOutput def setOperation(opsBtnValue: str, outputBoxValue: str) -> None: global currOp currOp = opsBtnValue return calcAndSetOutput(outputBoxValue, False) def setInput(input: str, outputBoxValue: str) -> None: global currInput currInput = currInput * 10 + int(input) print(f"{currInput=}", f"{outputBoxValue=}") return __cleanedOutput(outputBoxValue) + str(input) with gr.Blocks() as demo: with gr.Row(variant="default", elem_classes=["body-container"], equal_height=False): with gr.Row(variant="compact", elem_classes=["main-container"]): outputBox = gr.Textbox( label="Output", value=currOutput, text_align="right", max_lines=1, elem_classes=["output-box"], show_label=False ) calcBtn = gr.Button("=", variant="primary", elem_classes=["calc-btn"]).click( fn=calcAndSetOutput, inputs=[outputBox], outputs=outputBox, api_name="calc" ) with gr.Row(variant="compact", elem_classes=["input-container"], equal_height=True): with gr.Row(variant="compact", elem_classes=["num-container"]) as numBtnRow: [ gr.Button(str(i), elem_classes=["num-btn"]) for i in range(1, 10) ] gr.Button("0", elem_classes=["num-btn", "num-btn-0"]) for btn in numBtnRow.children: btn: gr.Button = btn btn.click(fn=setInput, inputs=[btn, outputBox], outputs=outputBox, api_name="setInput") with gr.Row(variant="panel", elem_classes=["ops-container"]) as opsBtnRow: plus_btn = gr.Button("+", elem_classes=["ops-btn"], variant="primary") minus_btn = gr.Button("-", elem_classes=["ops-btn"], variant="primary") multiply_btn = gr.Button("x", elem_classes=["ops-btn"], variant="primary") divide_btn = gr.Button("/", elem_classes=["ops-btn"], variant="primary") for btn in opsBtnRow.children: btn.click(fn=setOperation, inputs=[btn, outputBox], outputs=outputBox, api_name="setOperation") resetBtn = gr.Button("Reset", elem_classes=["reset-btn"], variant="stop").click(fn=reset, inputs=None, outputs=outputBox, api_name="reset") # with gr.Row(variant="panel", elem_classes=["debug-container"]): # gr.Markdown("## Debugging") # gr.Textbox(label="currInput", value=(lambda: currInput), every=1) # gr.Textbox(label="currOutput", value=(lambda: currOutput), every=1) # gr.Textbox(label="currOp", value=(lambda: currOp), every=1) demo.css = """ .gradio-container { padding: 5px !important; # padding-right: 0px !important; } .body-container { flex-direction: row; # min-width: 500px; # max-width: 500px; # width: 500px; # margin: 0 auto; # text-align: center; align-items: center; } .debug-container { flex-direction: column; # max-width: 500px; width: 300px; # margin: 0 auto; text-align: center; # align-items: center; } .main-container { flex-direction: column; max-width: 400px !important; margin: 0 auto; text-align: center; align-items: center; } .output-box input { font-size: 1.8rem; } .output-box { margin: -0.5rem auto -0.2rem auto; } .calc-btn { font-size: 1.5rem; width: 100%; } .reset-btn { width: 100%; } .input-container { max-width: 350px !important; min-width: 300px !important; # max-width: 400px; flex-direction: column; # max-width: 500px; # width: 500px; # margin: 0 auto; # text-align: center; # align-items: center; justify-content: center; margin-top: -1rem; } .num-container { min-width: 80%; # flex-direction: row; justify-content: center; # width: 300px; # margin: 0 auto; } .num-btn { font-size: 1.5rem; min-width: 5rem; max-width: 6rem; # max-width: 2rem; } .ops-container { flex-direction: row; align-items: center; margin: -1rem auto; # width: 100px; # max-width: 30%; # min-width: 20%; # margin: 0 auto; } .ops-btn { font-size: 1.5rem; min-width: 20%; # min-width: 40%; } """ if __name__ == "__main__": demo.launch(debug=True)