Created
May 4, 2011 06:14
-
-
Save mikz/954821 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Imports Calculator.CalculatorModel | |
Public Class Calculator | |
Dim WithEvents model As CalculatorModel | |
Private Sub MemoryController(ByVal sender As System.Windows.Forms.Button, ByVal e As System.EventArgs) Handles MemCBtn.Click, MemMBtn.Click, MemPBtn.Click, MemRBtn.Click, MemSBtn.Click | |
Try | |
model.CallMemory(sender.Text) | |
Catch ex As CalculationException | |
HandleCalculationException(ex) | |
End Try | |
End Sub | |
Private Sub OperatorController(ByVal sender As System.Windows.Forms.Button, ByVal e As System.EventArgs) Handles OpAdtnBtn.Click, OpDivBtn.Click, OpMtplBtn.Click, OpSubsBtn.Click | |
Try | |
model.PutOperator(sender.Text.Chars(0)) | |
Catch ex As CalculationException | |
HandleCalculationException(ex) | |
End Try | |
End Sub | |
Private Sub FunctionController(ByVal sender As System.Windows.Forms.Button, ByVal e As System.EventArgs) Handles btnAns.Click, FncBackBtn.Click, FncCBtn.Click, FncCEBtn.Click, FncInvBtn.Click, FncPerctBtn.Click, FncPlMnBtn.Click, FncSqrtBtn.Click | |
Try | |
model.CallFunction(sender.Text) | |
Catch ex As CalculationException | |
HandleCalculationException(ex) | |
End Try | |
End Sub | |
Private Sub NumberController(ByVal sender As System.Windows.Forms.Button, ByVal e As System.EventArgs) Handles Num0Btn.Click, Num1Btn.Click, Num2Btn.Click, Num3Btn.Click, Num4Btn.Click, Num5Btn.Click, Num6Btn.Click, Num7Btn.Click, Num8Btn.Click, Num9Btn.Click, OpDelimBtn.Click | |
If model.currentValue.ToString().Length < 15 Or model.fin Then | |
model.PutNumber(sender.Text.Chars(0)) | |
End If | |
End Sub | |
Private Sub RefreshLog() | |
lblLog.Text = "" | |
If model.log.Count >= 1 Then | |
lblLog.Text = String.Join(" ", model.log.GetRange(0, model.log.Count).ToArray) | |
If lblLog.Text.Length > 25 Then | |
lblLog.Text = "«" + lblLog.Text.Substring(lblLog.Text.Length - 24, 24) | |
End If | |
End If | |
End Sub | |
Private Sub model_MemoryChange(ByVal MemoryValue As Double) Handles model.MemoryChange | |
If MemoryValue = 0 Then | |
lblMemory.Text = "" | |
Else | |
lblMemory.Text = "M" | |
End If | |
End Sub | |
Private Sub RefreshAns() Handles model.UpdatedLog | |
RefreshLog() | |
If model.currentValue.ToString().ToLower().IndexOf("e") > 0 Then | |
LogResult(model.currentValue.ToString("0.0#########e+#0")) | |
Else | |
LogResult(model.currentValue.ToString()) | |
End If | |
End Sub | |
Private Sub HandleCalculationException(ByVal ex As CalculationException) | |
RefreshLog() | |
LogResult(ex.Message) | |
End Sub | |
Private Sub LogResult(ByVal str As String) | |
If model.lastOpDecimal Then | |
str &= "," | |
End If | |
If model.Fraction.HasValue And model.Fractions > 0 And (currentValue - Math.Round(model.currentValue, 0)) <> 0 Then | |
For i = 0 To model.Fractions | |
str &= "0" | |
Next i | |
End If | |
lblCurNumber.Text = str | |
If lblCurNumber.Text.Length > 12 Then | |
lblCurNumber.Font = New Font("Consolas", 12) | |
Else | |
lblCurNumber.Font = New Font("Consolas", 18) | |
End If | |
End Sub | |
Public Sub New() | |
' This call is required by the designer. | |
InitializeComponent() | |
model = New CalculatorModel | |
RefreshAns() | |
End Sub | |
Private Sub Calculator_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles Me.KeyPress | |
If "0123456789".Contains(e.KeyChar) Then | |
model.PutNumber(Val(e.KeyChar)) | |
e.Handled = True | |
'ElseIf ",".Contains(e.KeyChar) Then | |
' model.PutNumber(CChar(",")) | |
' e.Handled = True | |
ElseIf "+-*/".Contains(e.KeyChar) Then | |
model.PutOperator(e.KeyChar) | |
e.Handled = True | |
ElseIf "=".Contains(e.KeyChar) Then | |
model.CallFunction(e.KeyChar) | |
e.Handled = True | |
ElseIf e.KeyChar = ChrW(Keys.Enter) Then | |
model.CallFunction(FunctionEnum.Ans) | |
e.Handled = True | |
End If | |
End Sub | |
Private Sub KopírovatToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles KopírovatToolStripMenuItem.Click | |
Clipboard.SetText(lblCurNumber.Text) | |
End Sub | |
Private Sub VložitToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles VložitToolStripMenuItem.Click | |
If Clipboard.GetText().Length > 0 Then | |
model.ClearEntry() | |
For i As Integer = 0 To Clipboard.GetText().Length - 1 | |
Dim ch As Char = Clipboard.GetText().Chars(i) | |
If Char.IsDigit(ch) Or ch = "," Then | |
model.PutNumber(ch) | |
End If | |
Next | |
End If | |
End Sub | |
End Class |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Class CalculatorModel | |
Dim LogArray As ArrayList = New ArrayList() | |
Dim LeftSideValue As Nullable(Of Double) = Nothing | |
Dim RightSideValue As Nullable(Of Double) = 0 | |
Dim LastRightSideValue As Nullable(Of Double) = Nothing | |
Dim MemoryValue As Nullable(Of Double) = 0 | |
Dim Fraction As Nullable(Of Double) = Nothing | |
Dim Finished As Boolean = False | |
Dim Op, LastOp As Nullable(Of OperatorEnum) | |
Dim LastOpDeci As Boolean | |
Public Event UpdatedLog() | |
Public Event MemoryChange(ByVal MemoryValue As Double) | |
Public Class CalculationException | |
Inherits Exception | |
Public Sub New(ByVal message As String) | |
MyBase.New(message) | |
End Sub | |
End Class | |
Public Enum OperatorEnum | |
Subtraction | |
Addition | |
Multiplication | |
Division | |
End Enum | |
Public Enum MemoryEnum | |
Clear | |
Recall | |
Store | |
Add | |
Subtract | |
End Enum | |
Public Enum FunctionEnum | |
Ans | |
Clear | |
ClearEntry | |
PlusMinus | |
Back | |
Percent | |
Invert | |
Sqrt | |
End Enum | |
Public ReadOnly Property Fractions() As Integer | |
Get | |
Return CStr(Fraction).Length - 1 | |
End Get | |
End Property | |
Public ReadOnly Property fin As Boolean | |
Get | |
Return Finished | |
End Get | |
End Property | |
Public ReadOnly Property lastOpDecimal As Boolean | |
Get | |
Return LastOpDeci | |
End Get | |
End Property | |
Public ReadOnly Property log As ArrayList | |
Get | |
Return LogArray | |
End Get | |
End Property | |
Public ReadOnly Property rightSide() As Nullable(Of Double) | |
Get | |
Return RightSideValue | |
End Get | |
End Property | |
Public ReadOnly Property leftSide() As Nullable(Of Double) | |
Get | |
Return LeftSideValue | |
End Get | |
End Property | |
Sub New() | |
Debug.Print("CalculatorModel New()") | |
End Sub | |
Sub Clear() | |
log.Clear() | |
LastOp = Nothing | |
LastRightSideValue = Nothing | |
ClearEntry() | |
End Sub | |
Sub ClearEntry() | |
RightSideValue = 0 | |
Finished = False | |
Fraction = Nothing | |
End Sub | |
Private Sub ResetNumber() | |
If Not rightSide.HasValue Or Finished Then | |
RightSideValue = 0 | |
Finished = False | |
Fraction = Nothing | |
End If | |
End Sub | |
Sub PutNumber(ByVal num As Char) | |
LastOpDeci = False | |
Dim number As Integer | |
If Integer.TryParse(num, number) Then | |
PutNumber(number) | |
ElseIf num = "," And (Not Fraction.HasValue Or Finished) Then | |
ResetNumber() | |
Fraction = 10 | |
LastOpDeci = True | |
RaiseEvent UpdatedLog() | |
End If | |
End Sub | |
Sub PutNumber(ByVal number As Integer) | |
ResetNumber() | |
If Fraction.HasValue Then | |
RightSideValue += number / Fraction | |
Fraction *= 10 | |
Else | |
RightSideValue *= 10 | |
RightSideValue += number | |
End If | |
RaiseEvent UpdatedLog() | |
End Sub | |
Sub PutOperator(ByVal oper As String) | |
LastOpDeci = False | |
Select Case oper | |
Case "-" | |
PutOperator(OperatorEnum.Subtraction) | |
Case "+" | |
PutOperator(OperatorEnum.Addition) | |
Case "/" | |
PutOperator(OperatorEnum.Division) | |
Case "*" | |
PutOperator(OperatorEnum.Multiplication) | |
Case Else | |
Throw New ApplicationException("Unknown operator " + oper) | |
End Select | |
End Sub | |
Sub PutOperator(ByVal oper As OperatorEnum) | |
If Not Op Is Nothing Then 'If operator was alredy set | |
If Not IsNothing(rightSide) Then 'And if we have both sides of equation | |
log.Add(rightSide) | |
log.Add(OperatorString(oper)) | |
LeftSideValue = Count() 'Count Left side | |
RightSideValue = Nothing 'Reset right side | |
Finished = True | |
'ElseIf log.Item(log.Count - 1).GetType.Name = "OperatorEnum" Then | |
Else | |
log.Item(log.Count - 1) = OperatorString(oper) | |
End If | |
Else 'We have only one operator, no counting required | |
If IsNothing(leftSide) Then 'And there is empty left side | |
log.Add(rightSide) | |
log.Add(OperatorString(oper)) | |
LeftSideValue = RightSideValue 'Assign right side to left | |
RightSideValue = Nothing 'And reset right side | |
Finished = True | |
End If | |
End If | |
Op = oper 'And assign new operator | |
RaiseEvent UpdatedLog() | |
End Sub | |
Sub CallMemory(ByVal memory As String) | |
LastOpDeci = False | |
If memory.Length = 2 Then | |
memory = memory.Chars(1) | |
End If | |
Select Case memory | |
Case "C" | |
CallMemory(MemoryEnum.Clear) | |
Case "R" | |
CallMemory(MemoryEnum.Recall) | |
Case "S" | |
CallMemory(MemoryEnum.Store) | |
Case "+" | |
CallMemory(MemoryEnum.Add) | |
Case "-" | |
CallMemory(MemoryEnum.Subtract) | |
Case Else | |
Throw New ApplicationException("Unknown memory function M" + memory) | |
End Select | |
End Sub | |
Sub CallMemory(ByVal memory As MemoryEnum) | |
Select Case memory | |
Case MemoryEnum.Clear | |
MemoryValue = 0 | |
Case MemoryEnum.Store | |
MemoryValue = RightSideValue | |
Case MemoryEnum.Recall | |
RightSideValue = MemoryValue | |
Case MemoryEnum.Add | |
MemoryValue += RightSideValue | |
Case MemoryEnum.Subtract | |
MemoryValue -= RightSideValue | |
Case Else | |
Throw New ApplicationException("Unknown memory function " + memory) | |
End Select | |
RaiseEvent MemoryChange(MemoryValue) | |
Finished = True 'Start typing new number after using Memory functions | |
RaiseEvent UpdatedLog() | |
End Sub | |
Sub CallFunction(ByVal func As String) | |
LastOpDeci = False | |
Select Case func | |
Case "=" | |
CallFunction(FunctionEnum.Ans) | |
Case "C" | |
CallFunction(FunctionEnum.Clear) | |
Case "CE" | |
CallFunction(FunctionEnum.ClearEntry) | |
Case "+/-" | |
CallFunction(FunctionEnum.PlusMinus) | |
Case "¬" | |
CallFunction(FunctionEnum.Back) | |
Case "%" | |
CallFunction(FunctionEnum.Percent) | |
Case "1/x" | |
CallFunction(FunctionEnum.Invert) | |
Case "√" | |
CallFunction(FunctionEnum.Sqrt) | |
Case Else | |
Throw New ApplicationException("Unknown function " + func) | |
End Select | |
End Sub | |
Sub CallFunction(ByVal func As FunctionEnum) | |
Select Case func | |
Case FunctionEnum.Ans | |
Me.Ans() | |
Case FunctionEnum.Clear | |
Me.Clear() | |
Case FunctionEnum.ClearEntry | |
Me.ClearEntry() | |
Case FunctionEnum.PlusMinus | |
Me.PlusMinus() | |
Case FunctionEnum.Back | |
Me.Back() | |
Case FunctionEnum.Percent | |
Me.Percent() | |
Case FunctionEnum.Invert | |
Me.Invert() | |
Case FunctionEnum.Sqrt | |
Me.Sqrt() | |
Case Else | |
Throw New ApplicationException("Unknown function") | |
End Select | |
RaiseEvent UpdatedLog() | |
End Sub | |
Private Sub Percent() | |
Dim percent As Double | |
Dim left As Double | |
left = If(leftSide.HasValue, leftSide, 0) | |
percent = currentValue() / 100 | |
RightSideValue = left * percent | |
End Sub | |
Private Sub Invert() | |
Dim value As Double = currentValue() | |
RightSideValue = 1 / value | |
log.Add("reciproc(" & value & ")") | |
End Sub | |
Private Sub Sqrt() | |
Dim value As Double = currentValue() | |
RightSideValue = Math.Sqrt(value) | |
log.Add("sqrt(" & value & ")") | |
End Sub | |
Private Sub Back() | |
If rightSide.HasValue And Not Finished Then | |
Dim str As String | |
str = rightSide.ToString | |
str = str.Remove(str.Length - 1, 1) | |
Double.TryParse(str, RightSideValue) | |
End If | |
End Sub | |
Private Sub PlusMinus() | |
RightSideValue = currentValue() * -1 | |
End Sub | |
Private Function Ans() As Double | |
log.Clear() | |
RightSideValue = Me.Count() | |
LeftSideValue = Nothing | |
Fraction = Nothing | |
Finished = True | |
Return RightSideValue | |
End Function | |
Private Function OperatorString(ByVal oper As OperatorEnum) As String | |
Select Case oper | |
Case OperatorEnum.Addition | |
OperatorString = "+" | |
Case OperatorEnum.Division | |
OperatorString = "/" | |
Case OperatorEnum.Multiplication | |
OperatorString = "*" | |
Case OperatorEnum.Subtraction | |
OperatorString = "-" | |
Case Else | |
Throw New ApplicationException("Unknown Operator") | |
End Select | |
End Function | |
Public Function currentValue() As Double | |
If rightSide.HasValue Then | |
Return rightSide | |
ElseIf leftSide.HasValue Then | |
Return leftSide | |
Else | |
Return 0 | |
End If | |
End Function | |
Private Function Count(ByVal left As Double, ByVal right As Double) As Double | |
Select Case Op | |
Case OperatorEnum.Addition | |
Count = left + right | |
Case OperatorEnum.Subtraction | |
Count = left - right | |
Case OperatorEnum.Multiplication | |
Count = left * right | |
Case OperatorEnum.Division | |
If right.Equals(0) Then | |
Throw New CalculationException("Nelze dělit nulou") | |
End If | |
Count = left / right | |
Case Else | |
Throw New ApplicationException("Unknown Operator") | |
End Select | |
LastOp = Op | |
Op = Nothing | |
Return Count | |
End Function | |
Private Function Count() As Double | |
Dim left, right As Double | |
left = If(leftSide.HasValue, leftSide, rightSide) | |
If Op Is Nothing Then | |
If LastOp.HasValue And LastRightSideValue.HasValue Then | |
Op = LastOp | |
Return Count(left, LastRightSideValue) | |
Else | |
Return currentValue() | |
End If | |
End If | |
right = currentValue() | |
LastRightSideValue = right | |
Return Count(left, right) | |
End Function | |
End Class |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment