Multiple Class Blocks in One Script File
WinWrap® Basic is an embedded macro language control available for .NET/COM 32/64 bit Windows applications. The WinWrap® Basic Component is compatible with VBA, Sax Basic, VB.NET and Visual Basic 6.0 style scripts.
Mix subroutines, functions, class blocks, and module blocks in a single script file. Share public subroutines, functions, class blocks, and module blocks from a single file with '#Uses.
Inline Class and Module Blocks
- Mix subroutines, functions, class blocks, and module blocks in a single
file
- Alternative to VB6 style class files
- Drop in VB.NET class code with little or no changes
- Full auto completion support
Notice how easy it is to write a macro (Sub Main) and classes together in one
file. Terrific!
More Easily Incorporate VB.NET Code into WWB.NET Scripts
'#Language "WWB.NET"
Imports System
Imports System.Collections.Generic
Dim DialogParameters As New Dictionary(Of String, DialogParameter)
Sub Main()
CreateUI
End Sub
Class Triangle
Private Corners As New List(Of TriangleCorner)
Public Sub New(Sa As Double, Sb As Double, Sc As Double,
AA As Double, AB As Double, AC As Double)
Corners.add(New TriangleCorner("A", Sa, AA))
Corners.add(New TriangleCorner("B", Sb, AB))
Corners.add(New TriangleCorner("C", Sc, AC))
End Sub
Public Function Angle(index As Integer) As Double
Return Corners(index).Angle
End Function
Public Function Side(index As Integer) As Double
Return Corners(index).Side
End Function
Public Sub Solve()
Dim n As Integer
Do
n = Sides + Angles
If Angles = 2 Then TryAA()
If Sides = 3 Then TrySSS()
If Sides = 2 AndAlso Angles >= 1 Then TrySAS()
If Sides = 2 AndAlso Angles >= 1 Then TrySSA()
If Sides = 1 AndAlso Angles >= 2 Then TryAAS()
Loop While Not Solved AndAlso Sides + Angles > n ' continue while making progress
SortNames()
End Sub
Public ReadOnly Property Solved As Boolean
Get
Return Sides = 3 AndAlso Angles = 3
End Get
End Property
Private Sub TrySSA()
SortAngles()
If Side(2) <> 0 AndAlso Angle(1) = 0 Then
' Law of Sines: a/sin(A) = b/sin(B) = c/sin(C)
' solve for B: sin(B)/b = sin(C)/c
' solve for B: B = asin(sin(C)*b/c)
' side b is Side(1)
' side c is Side(2)
' angle C is Angle(2)
Dim asin = Math.Sin(Angle(2)) * Side(1) / Side(2)
' cope with asin slightly out of range
If asin < -1 Then asin = -1
If asin > 1 Then asin = 1
Corners(1).Angle = Math.ASin(asin)
End If
' http://www.mathsisfun.com/algebra/trig-solving-triangles.html
End Sub
Private Sub TrySAS()
SortSides()
If Angle(0) <> 0 AndAlso Side(0) = 0 Then
' Law of Cosines: a^2 = b^2 + c^2 - 2*b*c*cos(A)
' solve for a: a = sqrt(b^2 + c^2 - 2*b*c*cos(A))
' angle A is Angle(0)
' side b is Side(1)
' side c Side(2)
' side a is Side(0)
Corners(0).Side = Math.Sqrt(Side(1)^2 + Side(2)^2 - 2 * Side(1) * Side(2) * Math.Cos(Angle(0)))
End If
End Sub
Private Sub TryAA()
SortAngles()
If Angle(0) = 0 Then
' Law of Angles: A + B + C = 180
' solve for A: A = 180 - B - C
' angle A is Angle(0)
' angle B is Angle(1)
' angle C is Angle(2)
Corners(0).Angle = Math.PI - Angle(1) - Angle(2)
End If
End Sub
Private Sub TryAAS()
SortSides()
If Side(1) = 0 Then
SortAngles()
' Law of Sines: a/sin(A) = b/sin(B) = c/sin(C)
' solve for b: b = c*sin(B)/sin(C)
' side b is Side(1)
' angle B is Angle(1)
' side c is Side(2)
' angle C is Angle(2)
Corners(1).Side = Side(2) * Math.Sin(Angle(1)) / Math.Sin(Angle(2))
End If
End Sub
Private Sub TrySSS()
SortAngles()
If Angle(0) = 0 Then
' Law of Cosines: a^2 = b^2 + c^2 - 2*b*c*cos(A)
' solve for A: A = acos((b^2 + c^2 - a^2)/(2*b*c))
' side a is Side(0)
' side b is Side(1)
' side c is Side(2)
' angle A is Angle(0)
Corners(0).Angle = Math.Acos((Side(1)^2 + Side(2)^2 - Side(0)^2) / (2 * Side(1) * Side(2)))
End If
End Sub
Private Sub SortNames()
Dim tc As New TriangleCornerNameComparer
Corners.Sort(tc)
End Sub
Private Sub SortSides()
Dim tc As New TriangleCornerSideComparer
Corners.Sort(tc)
End Sub
Private Sub SortAngles()
Dim tc As New TriangleCornerAngleComparer
Corners.Sort(tc)
End Sub
Private ReadOnly Property Sides() As Integer
Get
Dim cnt As Integer = 0
For Each Corner As TriangleCorner In Corners
If Corner.Side <> 0 Then cnt = cnt + 1
Next
Return cnt
End Get
End Property
Private ReadOnly Property Angles() As Integer
Get
Dim cnt As Integer = 0
For Each Corner As TriangleCorner In Corners
If Corner.Angle <> 0 Then cnt = cnt + 1
Next
Return cnt
End Get
End Property
Private Function PieceDescription(piece As Double) As String
If piece = 0 Then
Return "0(Empty)"
Else
Return piece.ToString()
End If
End Function
Public Overrides Function ToString() As String
Dim s As String = ""
For Each Corner As TriangleCorner In Corners
Dim sCorner As String = "(Side=" & PieceDescription(Corner.Side) & ", Angle=" & PieceDescription(Corner.Angle * 180/Math.Pi) & ")"
s = If(s <> "", s & " ", s) & sCorner
Next
Return s
End Function
End Class
Class TriangleCorner
Public Name As String
Public Side As Double
Public Angle As Double
Public Sub New(aname As String, aside As Double, aangle As Double)
Name = aname
Side = aside
Angle = aangle
End Sub
Public Overrides Function ToString() As String
Return String.Format("Side={0}, Angle={1}", Side, Angle)
End Function
End Class
Class TriangleCornerNameComparer
Implements IComparer(Of TriangleCorner)
Public Function Compare(x As TriangleCorner, y As TriangleCorner) As Integer Implements IComparer(Of TriangleCorner).Compare
Return x.Name.CompareTo(y.Name)
End Function
End Class
Class TriangleCornerSideComparer
Implements IComparer(Of TriangleCorner)
Public Function Compare(x As TriangleCorner, y As TriangleCorner) As Integer Implements IComparer(Of TriangleCorner).Compare
Return If(x.Side = y.Side, x.Angle.CompareTo(y.Angle), x.Side.CompareTo(y.Side))
End Function
End Class
Class TriangleCornerAngleComparer
Implements IComparer(Of TriangleCorner)
Public Function Compare(x As TriangleCorner, y As TriangleCorner) As Integer Implements IComparer(Of TriangleCorner).Compare
Return If(x.Angle = y.Angle, x.Side.CompareTo(y.Side), x.Angle.CompareTo(y.Angle))
End Function
End Class
Sub CreateUI()
For Each di As String In {"AA", "AB", "AC", "Sa", "Sb", "Sc"}
DialogParameters.Add(di, New DialogParameter(di))
Next
Begin Dialog UserDialog 390,196,"Triangle Solver",.DlgFunc ' %GRID:10,7,1,1
GroupBox 10,7,80,105,"Select",.GroupBox1
OptionGroup .Group1
OptionButton 20,21,60,14,"SSS"
OptionButton 20,35,60,14,"SAS"
OptionButton 20,49,60,14,"SSA"
OptionButton 20,63,60,14,"AAA"
OptionButton 20,77,60,14,"ASA"
OptionButton 20,91,60,14,"AAS"
Picture 120,14,110,63,"",0,.Picture1
GroupBox 120,84,120,63,"Sides"
Text 130,98,10,14,"a"
Text 130,112,10,14,"b"
Text 130,126,10,14,"c"
TextBox 140,98,90,14,.Sa
TextBox 140,112,90,14,.Sb
TextBox 140,126,90,14,.Sc
GroupBox 260,84,120,63,"Angles"
Text 270,98,10,14,"A"
Text 270,112,10,14,"B"
Text 270,126,10,14,"C"
TextBox 280,98,90,14,.AA
TextBox 280,112,90,14,.AB
TextBox 280,126,90,14,.AC
PushButton 280,28,80,35,"Solve",.Solve
CancelButton 300,168,80,21
End Dialog
Dim dlg As UserDialog
Dim result = Dialog(dlg)
End Sub
Rem See DialogFunc help topic for more information.
Private Function DlgFunc(DlgItem$, Action%, SuppValue&) As Boolean
Select Case Action%
Case 1 ' Dialog box initialization
SelectTriangle(0)
DialogParameters!Sa.Value = 3
DialogParameters!Sb.Value = 4
DialogParameters!Sc.Value = 5
Case 2 ' Value changing or button pressed
Select Case DlgItem
Case "Group1"
SelectTriangle(DlgValue("Group1"))
Case "Solve"
SolveTriangle
DlgFunc = True
End Select
Rem DlgFunc = True ' Prevent button press from closing the dialog box
Case 3 ' TextBox or ComboBox text changed
Case 4 ' Focus changed
Case 5 ' Idle
Rem Wait .1 : DlgFunc = True ' Continue getting idle actions
Case 6 ' Function key
End Select
End Function
Sub SelectTriangle(index As Integer)
Dim Category As String = {"SSS", "SAS", "SSA", "AAA", "ASA", "AAS"}(index)
Dim enables As String = {"abc", "Abc", "Bbc", "ABC", "ABc", "ACc"}(index)
DlgSetPicture "Picture1", MacroDir & " riangle-" & Category & ".bmp", 0
For Each dp As DialogParameter In DialogParameters.Values
dp.ConditionalEnable(enables)
Next
End Sub
Sub SolveTriangle()
For Each dp As DialogParameter In DialogParameters.Values
If Not dp.Enable Then dp.Value = 0
Next
Dim Sa As Double = DialogParameters!Sa.Value
Dim Sb As Double = DialogParameters!Sb.Value
Dim Sc As Double = DialogParameters!Sc.Value
Dim AA As Double = DialogParameters!AA.Value
Dim AB As Double = DialogParameters!AB.Value
Dim AC As Double = DialogParameters!AC.Value
Dim t As New Triangle(Sa, Sb, Sc, AA, AB, AC)
t.Solve()
If Not t.Solved Then MsgBox "Can't solve triangle"
DialogParameters!Sa.Value = t.Side(0)
DialogParameters!Sb.Value = t.Side(1)
DialogParameters!Sc.Value = t.Side(2)
DialogParameters!AA.Value = t.Angle(0)
DialogParameters!AB.Value = t.Angle(1)
DialogParameters!AC.Value = t.Angle(2)
End Sub
Class DialogParameter
Private field As String
Public Sub New(afield As String)
field = afield
End Sub
Public Sub ConditionalEnable(enables As String)
Enable = enables.Contains(Right(field, 1))
End Sub
Public Property Enable As Boolean
Get
Return DlgEnable(field)
End Get
Set(ByVal Value As Boolean)
DlgEnable field, Value
End Set
End Property
Public Property Value As Double
Get
Dim v As Double = Val(DlgText(field))
If Left(field, 1) = "A" Then v *= Math.PI/180
Return v
End Get
Set(ByVal NewValue As Double)
If Left(field, 1) = "A" Then NewValue *= 180/Math.PI
DlgText field, CStr(NewValue)
End Set
End Property
End Class
More Class Blocks Features
- Clear modular structure for WWB.NET scripts
- Supports object enclosure (no inheritance)
- Implement .NET interfaces with WWB.NET script classes
- Supports generic collections of WWB.NET script class objects
WinWrap® Basic Class Blocks Demo Code on GitHub
This demo solves a partially specified triangle for the remaining sides and angles. A form is displayed with the 3 solved sides and 3 solved angles for the specified triangle.
You can see the demo code at github.com/WinWrap/CodeExamples/tree/master/Triangle. Open Triangle2.wwd with WinWrap Director to run the code. You can get WinWrap Director with a WinWrap Basic evaluation download
here.
Conclusion
Mix subroutines, functions, class blocks, and module blocks in a single script file.
Copyright Polar Engineering, Inc.