calculator.rs 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. #![allow(non_snake_case)]
  2. /*
  3. This example is a simple iOS-style calculator. This particular example can run any platform - Web, Mobile, Desktop.
  4. This calculator version uses React-style state management. All state is held as individual use_states.
  5. */
  6. use std::sync::Arc;
  7. use dioxus::events::*;
  8. use dioxus::prelude::*;
  9. use separator::Separatable;
  10. fn main() {
  11. dioxus::desktop::launch(app);
  12. }
  13. fn app(cx: Scope) -> Element {
  14. let cur_val = use_state(&cx, || 0.0_f64);
  15. let operator = use_state(&cx, || None as Option<&'static str>);
  16. let display_value = use_state(&cx, || String::from(""));
  17. let toggle_percent = move |_| todo!();
  18. let input_digit = move |num: u8| display_value.modify().push_str(num.to_string().as_str());
  19. cx.render(rsx!(
  20. style { [include_str!("./assets/calculator.css")] }
  21. div {
  22. class: "calculator",
  23. onkeydown: move |evt| match evt.key_code {
  24. KeyCode::Add => operator.set(Some("+")),
  25. KeyCode::Subtract => operator.set(Some("-")),
  26. KeyCode::Divide => operator.set(Some("/")),
  27. KeyCode::Multiply => operator.set(Some("*")),
  28. KeyCode::Num0 => input_digit(0),
  29. KeyCode::Num1 => input_digit(1),
  30. KeyCode::Num2 => input_digit(2),
  31. KeyCode::Num3 => input_digit(3),
  32. KeyCode::Num4 => input_digit(4),
  33. KeyCode::Num5 => input_digit(5),
  34. KeyCode::Num6 => input_digit(6),
  35. KeyCode::Num7 => input_digit(7),
  36. KeyCode::Num8 => input_digit(8),
  37. KeyCode::Num9 => input_digit(9),
  38. KeyCode::Backspace => {
  39. if !display_value.as_str().eq("0") {
  40. display_value.modify().pop();
  41. }
  42. }
  43. _ => {}
  44. },
  45. div { class: "calculator-display", [cur_val.separated_string()] }
  46. div { class: "input-keys",
  47. div { class: "function-keys",
  48. CalculatorKey {
  49. name: "key-clear",
  50. onclick: move |_| {
  51. display_value.set("0".to_string());
  52. if display_value != "0" {
  53. operator.set(None);
  54. cur_val.set(0.0);
  55. }
  56. },
  57. [if display_value == "0" { "C" } else { "AC" }]
  58. }
  59. CalculatorKey {
  60. name: "key-sign",
  61. onclick: move |_| {
  62. if display_value.starts_with("-") {
  63. display_value.set(display_value.trim_start_matches("-").to_string())
  64. } else {
  65. display_value.set(format!("-{}", *display_value))
  66. }
  67. },
  68. "±"
  69. }
  70. CalculatorKey {
  71. onclick: toggle_percent,
  72. name: "key-percent",
  73. "%"
  74. }
  75. }
  76. div { class: "digit-keys",
  77. CalculatorKey { name: "key-0", onclick: move |_| input_digit(0),
  78. "0"
  79. }
  80. CalculatorKey { name: "key-dot", onclick: move |_| display_value.modify().push_str("."),
  81. "●"
  82. }
  83. (1..9).map(|k| rsx!{
  84. CalculatorKey {
  85. key: "{k}",
  86. name: "key-{k}",
  87. onclick: move |_| input_digit(k),
  88. "{k}"
  89. }
  90. }),
  91. }
  92. div { class: "operator-keys",
  93. CalculatorKey {
  94. name: "key-divide",
  95. onclick: move |_| operator.set(Some("/")),
  96. "÷"
  97. }
  98. CalculatorKey {
  99. name: "key-multiply",
  100. onclick: move |_| operator.set(Some("*")),
  101. "×"
  102. }
  103. CalculatorKey {
  104. name: "key-subtract",
  105. onclick: move |_| operator.set(Some("-")),
  106. "−"
  107. }
  108. CalculatorKey {
  109. name: "key-add",
  110. onclick: move |_| operator.set(Some("+")),
  111. "+"
  112. }
  113. CalculatorKey {
  114. name: "key-equals",
  115. onclick: move |_| {
  116. if let Some(op) = operator.as_ref() {
  117. let rhs = display_value.parse::<f64>().unwrap();
  118. let new_val = match *op {
  119. "+" => *cur_val + rhs,
  120. "-" => *cur_val - rhs,
  121. "*" => *cur_val * rhs,
  122. "/" => *cur_val / rhs,
  123. _ => unreachable!(),
  124. };
  125. cur_val.set(new_val);
  126. display_value.set(new_val.to_string());
  127. operator.set(None);
  128. }
  129. },
  130. "="
  131. }
  132. }
  133. }
  134. }
  135. ))
  136. }
  137. #[inline_props]
  138. fn CalculatorKey<'a>(
  139. cx: Scope,
  140. name: &'static str,
  141. onclick: &'a dyn Fn(Arc<MouseEvent>),
  142. children: Element<'a>,
  143. ) -> Element {
  144. cx.render(rsx! {
  145. button {
  146. class: "calculator-key {name}",
  147. onclick: onclick,
  148. children
  149. }
  150. })
  151. }