Microsoft Small Basic

Program Listing: XFZ657-10
' Shapes 1.0
' Copyright (c) 2012 Nonki Takahashi. All rights reserved.
'
' History :
' 1.0 2012/09/15 Supported copy and paste. (XFZ657-10)
' 0.9 2012/09/14 Supported rotating shapes. (XFZ657-9)
' 0.8 2012/09/12 Supported re-sizing shapes. (XFZ657-8)
' 0.72 2012/09/11 Bug fixed (pen width). (XFZ657-7)
' 0.71 2012/09/11 Bug fixed (output). Minor change. (XFZ657-6)
' 0.7 2012/09/11 Supported color palette. (XFZ657-5)
' 0.6 2012/09/10 Supported cut menu. (XFZ657-4)
' 0.5 2012/09/09 Changed to add function of moving shapes. (XFZ657-3)
' 0.4 2012/09/09 Changed to add function of selecting shapes. (XFZ657-2)
' 0.3 2012/09/08 Changed to output shape array. (XFZ657-1)
' 0.2 2012/09/07 Bug fixed. Supported offset scale, and angle of shapes. (XFZ657-0)
' 0.1 2012/09/06 Created. (XFZ657)
'
title = "Shapes 1.0"
GraphicsWindow.Title = title
debug = "False"
WQ = Text.GetCharacter(34)
CRLF = Text.GetCharacter(13) + Text.GetCharacter(10)
pw = "1=2;2=4;3=8;4=16;5=0;6=1;" ' pen width
pen = 1 ' pen width index
nPen = 6 ' number of pen width
pwidth = GraphicsWindow.PenWidth
pcolor = GraphicsWindow.PenColor
bcolor = GraphicsWindow.BrushColor
CS_InitPalette() ' initialize palette for color slider
DrawMenu()
shape = ""
nShapes = 0
cont = "True" ' continue
param = "down=True;move=False;up=False;" ' wait to click
Mouse_SetHandler()
While cont
If clicked Then
SearchClickedObject()
DoObject()
clicked = "False"
Else
Program.Delay(100)
EndIf
EndWhile
' end of program

Sub CalcPinchPos
' param i - shape index
' return mxM, myM - center of pinch
_x = shape[i]["x"]
_y = shape[i]["y"]
width = shape[i]["width"]
height = shape[i]["height"]
angle = shape[i]["angle"]
param = "width=0;height=0;angle=" + angle + ";"
param["cx"] = _x + width / 2
param["cy"] = _y + height / 2
Stack.PushValue("local", x)
Stack.PushValue("local", y)
Stack.PushValue("local", _x)
Stack.PushValue("local", _y)
param["x"] = param["cx"]
param["y"] = param["cy"] - 10
Shapes_CalcRotatePos()
mxM = x
myM = y
_y = Stack.PopValue("local")
_x = Stack.PopValue("local")
y = Stack.PopValue("local")
x = Stack.PopValue("local")
EndSub

Sub CalcVertexes
' param obj - pinch name
' param angle - angle of a shape
' param selectedshape - parent shape index of pinch
' param shape[] - shape data
' return mxM, myM - free vertex
' return mxD, myD - fixed vertex
iPinch = Text.GetSubTextToEnd(obj, 6)
If shape[selectedshape]["func"] = "line" Then
If iPinch = 1 Then
mxM = shape[selectedshape]["x"] + shape[selectedshape]["x1"]
myM = shape[selectedshape]["y"] + shape[selectedshape]["y1"]
mxD = shape[selectedshape]["x"] + shape[selectedshape]["x2"]
myD = shape[selectedshape]["y"] + shape[selectedshape]["y2"]
ElseIf iPinch = 2 Then
mxM = shape[selectedshape]["x"] + shape[selectedshape]["x2"]
myM = shape[selectedshape]["y"] + shape[selectedshape]["y2"]
mxD = shape[selectedshape]["x"] + shape[selectedshape]["x1"]
myD = shape[selectedshape]["y"] + shape[selectedshape]["y1"]
EndIf
Else
If iPinch = 1 Then
mxM = shape[selectedshape]["x"]
myM = shape[selectedshape]["y"]
mxD = shape[selectedshape]["x"] + shape[selectedshape]["width"]
myD = shape[selectedshape]["y"] + shape[selectedshape]["height"]
ElseIf iPinch = 2 Then
mxM = shape[selectedshape]["x"] + shape[selectedshape]["width"]
myM = shape[selectedshape]["y"]
mxD = shape[selectedshape]["x"]
myD = shape[selectedshape]["y"] + shape[selectedshape]["height"]
ElseIf iPinch = 3 Then
mxM = shape[selectedshape]["x"]
myM = shape[selectedshape]["y"] + shape[selectedshape]["height"]
mxD = shape[selectedshape]["x"] + shape[selectedshape]["width"]
myD = shape[selectedshape]["y"]
ElseIf iPinch = 4 Then
mxM = shape[selectedshape]["x"] + shape[selectedshape]["width"]
myM = shape[selectedshape]["y"] + shape[selectedshape]["height"]
mxD = shape[selectedshape]["x"]
myD = shape[selectedshape]["y"]
EndIf
param = "x=" + mxD + ";y=" + myD + ";width=0;height=0;angle=" + angle
param = param + ";cx=" + (mxD + mxM) / 2 + ";cy=" + (myD + myM) / 2 + ";"
Shapes_CalcRotatePos()
mxD = x
myD = y
param["x"] = mxM
param["y"] = myM
Shapes_CalcRotatePos()
mxM = x
myM = y
EndIf
EndSub

Sub DoMenu
While Text.StartsWith(obj, "menu")
i = Text.GetSubTextToEnd(obj, 5)
obj = ""
func = menu[i]["func"]
select = "True"
ItemSelect() ' menu item select
selecteditem = i
If func = "cut" Then
If selectedshape <> "" Then
Shapes.Remove(shape[selectedshape]["obj"])
shape["clipboard"] = shape[selectedshape]
nShapes = nShapes - 1
For _i = selectedshape To nShapes
shape[_i] = shape[_i + 1]
EndFor
selectedshape = ""
EndIf
ElseIf func = "copy" Then
If selectedshape <> "" Then
shape["clipboard"] = shape[selectedshape]
shape["clipboard"]["x"] = shape["clipboard"]["x"] + 10
shape["clipboard"]["y"] = shape["clipboard"]["y"] + 10
shape["clipboard"]["_x0"] = shape["clipboard"]["_x0"] + 10
shape["clipboard"]["_x1"] = shape["clipboard"]["_x1"] + 10
shape["clipboard"]["_y0"] = shape["clipboard"]["_y0"] + 10
shape["clipboard"]["_y1"] = shape["clipboard"]["_y1"] + 10
needClick = "True" ' in DoShape()
EndIf
ElseIf func = "paste" Then
If shape["clipboard"] <> "" Then
nShapes = nShapes + 1
shape[nShapes] = shape["clipboard"]
shape["clipboard"]["x"] = shape["clipboard"]["x"] + 10
shape["clipboard"]["y"] = shape["clipboard"]["y"] + 10
shape["clipboard"]["_x0"] = shape["clipboard"]["_x0"] + 10
shape["clipboard"]["_x1"] = shape["clipboard"]["_x1"] + 10
shape["clipboard"]["_y0"] = shape["clipboard"]["_y0"] + 10
shape["clipboard"]["_y1"] = shape["clipboard"]["_y1"] + 10
iMin = nShapes
iMax = nShapes
scale = 1
shX = 0
shY = 0
Shapes_Add()
obj = "shape" + nShapes
needClick = "True" ' in DoShape()
EndIf
ElseIf func = "rect" Or func = "ell" Or func = "tri" Then
' rectangle, ellipse or triangle
needClick = "True" ' in DoShape()
WaitToClick() ' to get mxD, myD
SearchClickedObject() ' for clicked menu
If Text.StartsWith(obj, "menu") = "False" Then
mxM = mxD
myM = myD
angle = 0
WaitToRelease() ' to get mxU, myU
nShapes = nShapes + 1
obj = "shape" + nShapes
i = nShapes ' to set shape[nShapes]
resize = "False"
SetShapeData()
GraphicsWindow.BrushColor = bcolor
GraphicsWindow.PenWidth = pwidth
If pwidth > 0 Then
GraphicsWindow.PenColor = pcolor
EndIf
If func = "rect" Then
shape[nShapes]["obj"] = Shapes.AddRectangle(w, h)
ElseIf func = "ell" Then
shape[nShapes]["obj"] = Shapes.AddEllipse(w, h)
ElseIf func = "tri" Then
shape[nShapes]["obj"] = Shapes.AddTriangle(xt, 0, 0, h, w, h)
EndIf
Shapes.Move(shape[nShapes]["obj"], xmin, ymin)
EndIf
ElseIf func = "line" Then ' line
needClick = "True" ' in DoShape()
WaitToClick() ' to get mxD, myD
SearchClickedObject() ' for menu clicked
If Text.StartsWith(obj, "menu") = "False" Then
mxM = mxD
myM = myD
WaitToRelease() ' to get mxU, myU
nShapes = nShapes + 1
obj = "shape" + nShapes
i = nShapes ' to set shape[nShapes]
resize = "False"
SetShapeData()
GraphicsWindow.BrushColor = bcolor
GraphicsWindow.PenWidth = pwidth
If pwidth > 0 Then
GraphicsWindow.PenColor = pcolor
EndIf
shape[nShapes]["obj"] = Shapes.AddLine(mxD - xmin, myD - ymin, mxU - xmin, myU - ymin)
Shapes.Move(shape[nShapes]["obj"], xmin, ymin)
EndIf
ElseIf func = "pc" Then ' pen color
color = pcolor
CS_ShowPopup()
pcolor = color
DrawMenuItem()
ElseIf func = "pw" Then ' pen width
If pen = nPen Then
pen = 1
Else
pen = pen + 1
EndIf
pwidth = pw[pen]
x = menu[i]["_x0"]
y = menu[i]["_y0"]
size = menu[i]["_x1"] - x
GraphicsWindow.BrushColor = "LightGray"
GraphicsWindow.FillRectangle(x, y, size, size)
DrawMenuItem()
ElseIf func = "bc" Then ' brush color
color = bcolor
CS_ShowPopup()
bcolor = color
DrawMenuItem()
ElseIf func = "save" Then ' save shapes
param = "down=False;move=False;up=False;" ' wait button pushed
Mouse_SetHandler()
WriteShapes()
EndIf
param = "down=True;move=False;up=False;" ' wait next obj click
Mouse_SetHandler()
i = selecteditem
select = "False"
ItemSelect() ' menu item unselect
EndWhile
EndSub

Sub DoObject
' param obj - clicked object
While obj <> ""
fromMenu = "False"
DoMenu()
If obj <> "" Then
DoShape()
EndIf
If obj <> "" Then
DoPinch()
EndIf
EndWhile
EndSub

Sub DoPinch
' param obj - clicked object
' param selectedshape - parent shape index of the pinch
If Text.StartsWith(obj, "pinch") Then
i = Text.GetSubTextToEnd(obj, 6)
If i = 5 Then ' rotate a shape
i = selectedshape
WaitToRelease3() ' to get angle
Shapes.Rotate(shape[i]["obj"], angle)
shape[i]["angle"] = Math.Floor(angle)
select = "False"
ShapeSelect() ' remove pinches
Else ' re-size a shape
angle = shape[selectedshape]["angle"]
CalcVertexes() ' to get mxM, myM, mxD, myD
WaitToRelease() ' to get mxU, myU
i = selectedshape
select = "False"
ShapeSelect() ' remove pinches
' selectedshape is broken in ShapeSelect() so use i instead
resize = "True"
SetShapeData() ' re-size shape[i]
iMin = i ' to re-size Shapes
iMax = nShapes ' to keep z-order of Shapes
Shapes_Remove()
scale = 1
shX = 0
shY = 0
Shapes_Add()
EndIf
param = "down=True;move=False;up=False;" ' wait next obj click
Mouse_SetHandler()
obj = "shape" + i
needClick = "True"
EndIf
EndSub

Sub DoShape
currentobj = ""
While Text.StartsWith(obj, "shape")
If currentobj <> obj Then
i = Text.GetSubTextToEnd(obj, 6)
func = shape[i]["func"]
select = "True"
ShapeSelect() ' shows pinches
currentobj = obj
EndIf
If needClick Then ' after a shape menu selected
obj = ""
WaitToClick() ' wait to click a new positon
SearchClickedObject()
needClick = "False"
EndIf
If obj = currentobj Then
WaitToRelease2() ' for moving a shape
needClick = "True"
ElseIf Text.StartsWith(obj, "pinch") = "False" Then
_shape = selectedshape
select = "False"
ShapeSelect() ' remove pinches
If obj = "menu2" Or obj = "menu3" Then ' for cut or copy
selectedshape = _shape ' keep selected shape index to remove
EndIf
EndIf
EndWhile
EndSub

Sub DrawMenu
cxMenu = 6
cyMenu = 6
sizeMenu = 40
nMenu = 11
GraphicsWindow.BrushColor = "LightGray"
GraphicsWindow.FillRectangle(0, 0, 16 + sizeMenu * 2, GraphicsWindow.Height)
For i = 1 To nMenu
xMenu = cxMenu + Math.Remainder(i - 1, 2) * (sizeMenu + 4)
yMenu = cyMenu + Math.Floor((i - 1) / 2) * (sizeMenu + 14)
GraphicsWindow.BrushColor = "LightGray"
GraphicsWindow.FillRectangle(xMenu, yMenu, sizeMenu, sizeMenu)
menu[i]["_x0"] = xMenu
menu[i]["_y0"] = yMenu
menu[i]["_x1"] = xMenu + sizeMenu
menu[i]["_y1"] = yMenu + sizeMenu
DrawMenuItem()
EndFor
EndSub

Sub DrawMenuItem
' param i - item number
' param pwidth - pen width
' param pcolor - pen color
' param bcolor - brush color
margin = 4
x = menu[i]["_x0"]
y = menu[i]["_y0"]
size = menu[i]["_x1"] - x
GraphicsWindow.PenColor = "Black"
GraphicsWindow.PenWidth = 2
GraphicsWindow.FontBold = "False"
GraphicsWindow.FontSize = 8
If i = 1 Then
menu[i]["func"] = "save"
GraphicsWindow.BrushColor = "SteelBlue"
GraphicsWindow.FillRectangle(x + margin, y + margin, size - margin * 2, size - margin * 2)
GraphicsWindow.BrushColor = "White"
GraphicsWindow.FillRectangle(x + margin + 4, y + margin, size - (margin + 4) * 2, (size - margin * 2) / 3)
GraphicsWindow.BrushColor = "Gray"
GraphicsWindow.FillRectangle(x + margin + 6, y + size - 15, size - (margin + 8) * 2, 15 - margin)
GraphicsWindow.BrushColor = "Black"
itemname[i] = "Save"
ElseIf i = 2 Then
menu[i]["func"] = "cut"
' initialize shapes
Scissors_Init()
nShapes = Array.GetItemCount(shape)
' add shapes
scale = 0.11
iMin = 1
iMax = nShapes
Shapes_Add()
x = x + 14
Shapes_Move()
x = x - 14
nShapes = 3
For t = 0 To 360 * 0.3
angle = 30 - 30 * Math.Cos(t * Math.Pi / 180)
Shapes_Rotate()
EndFor
itemname[i] = "Cut"
ElseIf i = 3 Then
menu[i]["func"] = "copy"
' initialize shapes
Copy_Init()
nShapes = Array.GetItemCount(shape)
' add shapes
scale = 0.14
iMin = 1
iMax = nShapes
Shapes_Add()
x = x - size + 9
y = y - size / 2
Shapes_Move()
x = x + size - 9
y = y + size / 2
itemname[i] = "Copy"
ElseIf i = 4 Then
menu[i]["func"] = "paste"
' initialize shapes
Paste_Init()
nShapes = Array.GetItemCount(shape)
' add shapes
scale = 0.12
iMin = 1
iMax = nShapes
Shapes_Add()
x = x + 7
y = y + 4
Shapes_Move()
x = x - 7
y = y - 4
itemname[i] = "Paste"
ElseIf i = 5 Then
menu[i]["func"] = "rect"
GraphicsWindow.DrawRectangle(x + margin, y + margin, size - margin * 2, size - margin * 2)
itemname[i] = "Rectangle"
ElseIf i = 6 Then
menu[i]["func"] = "ell"
GraphicsWindow.DrawEllipse(x + margin, y + margin, size - margin * 2, size - margin * 2)
itemname[i] = "Ellipse"
ElseIf i = 7 Then
menu[i]["func"] = "tri"
x1 = x + size / 2
y1 = y + margin
x2 = x + margin
y2 = y + size - margin
x3 = x + size - margin
y3 = y + size - margin
GraphicsWindow.DrawTriangle(x1, y1, x2, y2, x3, y3)
itemname[i] = "Triangle"
ElseIf i = 8 Then
menu[i]["func"] = "line"
x1 = x + margin
y1 = y + margin
x2 = x + size - margin
y2 = y + size - margin
GraphicsWindow.DrawLine(x1, y1, x2, y2)
itemname[i] = "Line"
ElseIf i = 9 Then
menu[i]["func"] = "pw"
GraphicsWindow.PenWidth = pwidth
x1 = x + margin
y1 = y + size / 2
x2 = x + size - margin
y2 = y + size / 2
GraphicsWindow.DrawLine(x1, y1, x2, y2)
itemname[i] = "Pen Width"
ElseIf i = 10 Then
menu[i]["func"] = "pc"
margin = 6
GraphicsWindow.PenWidth = 4
GraphicsWindow.PenColor = pcolor
GraphicsWindow.DrawRectangle(x + margin, y + margin, size - margin * 2, size - margin * 2)
itemname[i] = "Pen Color"
ElseIf i = 11 Then
menu[i]["func"] = "bc"
GraphicsWindow.BrushColor = bcolor
GraphicsWindow.FillRectangle(x + margin, y + margin, size - margin * 2, size - margin * 2)
GraphicsWindow.PenColor = "Black"
GraphicsWindow.PenWidth = 2
GraphicsWindow.DrawRectangle(x + margin, y + margin, size - margin * 2, size - margin * 2)
itemname[i] = "Brush Color"
EndIf
If itemname[i] <> "" And oItem[i] = "" Then
GraphicsWindow.BrushColor = "Black"
oItem[i] = Shapes.AddText(itemname[i])
Shapes.Move(oItem[i], x + margin, y + size)
EndIf
GraphicsWindow.FontBold = "True"
GraphicsWindow.FontSize = 12
EndSub

Sub ItemSelect
' i - menu index
' select - "True" if selected
If select Then
GraphicsWindow.PenColor = "Orange"
Else
GraphicsWindow.PenColor = "LightGray"
EndIf
GraphicsWindow.PenWidth = 2
x = menu[i]["_x0"] - 1
y = menu[i]["_y0"] - 1
width = menu[i]["_x1"] - x + 1
height = menu[i]["_y1"] - y + 1
GraphicsWindow.DrawRectangle(x, y, width, height)
EndSub

Sub NormalizePos
' param mxD, myD - fixed vertex of a shape rotated
' param mxM, myM - opposite vertex of a shape rotated
' param angle - angle of a shape
' return _mxD, _myD - fixed vertex of a shape not rotated
' return _mxM, _myM - opposite vertex of a shape not rotated
param = "x=" + mxD + ";y=" + myD + ";width=0;height=0;"
param["cx"] = (mxD + mxM) / 2
param["cy"] = (myD + myM) / 2
param["angle"] = -angle
Shapes_CalcRotatePos()
_mxD = Math.Floor(x)
_myD = Math.Floor(y)
param["x"] = mxM
param["y"] = myM
Shapes_CalcRotatePos()
_mxM = Math.Floor(x)
_myM = Math.Floor(y)
EndSub

Sub SearchClickedObject
' return obj - name of object (menu, shape or pinch)
Stack.PushValue("local", i)
obj = ""
For i = 1 To nPinch
If pinch[i]["_x0"] <= mxD And mxD <= pinch[i]["_x1"] And pinch[i]["_y0"] <= myD And myD <= pinch[i]["_y1"] Then
obj = "pinch" + i
Goto sco_exit
EndIf
EndFor
For i = 1 To nMenu
If menu[i]["_x0"] <= mxD And mxD <= menu[i]["_x1"] And menu[i]["_y0"] <= myD And myD <= menu[i]["_y1"] Then
obj = "menu" + i
Goto sco_exit
EndIf
EndFor
For i = nShapes To 1 Step -1
param = "x=" + mxD + ";y=" + myD + ";width=0;height=0;"
param["cx"] = (shape[i]["_x0"] + shape[i]["_x1"]) / 2
param["cy"] = (shape[i]["_y0"] + shape[i]["_y1"]) / 2
param["angle"] = -shape[i]["angle"]
Shapes_CalcRotatePos()
If shape[i]["_x0"] <= x And x <= shape[i]["_x1"] And shape[i]["_y0"] <= y And y <= shape[i]["_y1"] Then
If shape[i]["func"] = "rect" Or shape[i]["func"] = "line" Then
obj = "shape" + i
Goto sco_exit
ElseIf shape[i]["func"] = "ell" Then
x = (x - param["cx"]) / shape[i]["width"] * 2
y = (y - param["cy"]) / shape[i]["height"] * 2
r = Math.SquareRoot(x * x + y * y)
If r <= 1 Then
obj = "shape" + i
Goto sco_exit
EndIf
ElseIf shape[i]["func"] = "tri" Then
x = (x - param["cx"]) / shape[i]["width"] * 2
y = (y - shape[i]["_y1"]) / shape[i]["height"]
r = Math.Abs(x) + Math.Abs(y)
If r <= 1 And y <= 0 Then
obj = "shape" + i
Goto sco_exit
EndIf
EndIf
EndIf
EndFor
sco_exit:
i = Stack.PopValue("local")
EndSub

Sub SetShapeData
' param i - index of shapes
' param resize - "True" then following 4 params ignored
' param func - "rect", "ell", "tri" or "line"
' param pwidth - pen width
' param pcolor - pen color
' param bcolor - brush color
' param mxD, myD - fixed vertex
' param mxU, myU - opposite vertex
' return shape[i] - shape data
If resize = "False" Then
shape[i]["func"] = func
shape[i]["pw"] = pwidth
If pwidth > 0 Then
shape[i]["pc"] = pcolor
Else
shape[i]["pc"] = ""
EndIf
If func <> "line" Then ' rectangle, ellipse or triangle
shape[i]["bc"] = bcolor
EndIf
Endif
If func = "line" Then ' line
xmin = Math.Min(mxD, mxU)
ymin = Math.Min(myD, myU)
xmax = Math.Max(mxD, mxU)
ymax = Math.Max(myD, myU)
shape[i]["x1"] = mxD - xmin
shape[i]["y1"] = myD - ymin
shape[i]["x2"] = mxU - xmin
shape[i]["y2"] = myU - ymin
x = mxU - mxD
y = myU - myD
Math_CartesianToPolar()
If a >= 180 Then
a = a - 180
EndIf
shape[i]["angle"] = a
cx = (xmin + xmax) / 2
cy = (ymin + ymax) / 2
len = Math.SquareRoot(x * x + y * y)
shape[i]["_x0"] = Math.Floor(cx - len / 2)
shape[i]["_x1"] = Math.Floor(cx + len / 2)
shape[i]["_y0"] = cy - 4
shape[i]["_y1"] = cy + 4
Else ' rectangle, ellipse or triangle
mxM = mxU
myM = myU
angle = shape[i]["angle"]
NormalizePos()
xmin = Math.Min(_mxD, _mxM)
ymin = Math.Min(_myD, _myM)
xmax = Math.Max(_mxD, _mxM)
ymax = Math.Max(_myD, _myM)
w = xmax - xmin
h = ymax - ymin
shape[i]["width"] = w
shape[i]["height"] = h
shape[i]["_x0"] = xmin
shape[i]["_y0"] = ymin
shape[i]["_x1"] = xmin + w
shape[i]["_y1"] = ymin + h
EndIf
shape[i]["x"] = xmin
shape[i]["y"] = ymin
If func = "tri" Then ' triangle
xt = Math.Floor((xmax - xmin) / 2) ' x top
shape[i]["x1"] = xt
shape[i]["y1"] = 0
shape[i]["x2"] = 0
shape[i]["y2"] = h
shape[i]["x3"] = w
shape[i]["y3"] = h
EndIf
EndSub

Sub ShapeSelect
' Show or remove pinches for a selected shape
' i - shape index
' select - "True" if selected
If select Then
Stack.PushValue("local", x)
Stack.PushValue("local", y)
GraphicsWindow.PenColor = "Black"
GraphicsWindow.PenWidth = 1
sizePinch = 10
selectedshape = i
shX = shape[i]["x"]
shY = shape[i]["y"]
GraphicsWindow.BrushColor = "Lime"
If shape[i]["func"] = "line" Then
nPinch = 2
For _i = 1 To nPinch
pinch[_i]["obj"] = Shapes.AddEllipse(sizePinch, sizePinch)
x = shX + shape[i]["x" + _i] - sizePinch / 2
y = shY + shape[i]["y" + _i] - sizePinch / 2
Shapes.Move(pinch[_i]["obj"], x, y)
pinch[_i]["_x0"] = x
pinch[_i]["_y0"] = y
pinch[_i]["_x1"] = x + sizePinch
pinch[_i]["_y1"] = y + sizePinch
EndFor
Else
pinch[5]["obj"] = Shapes.AddEllipse(sizePinch, sizePinch)
shWidth = shape[i]["width"]
shHeight = shape[i]["height"]
param["cx"] = shX + shWidth / 2
param["cy"] = shY + shHeight / 2
param["angle"] = shape[i]["angle"]
param["x"] = shX + shWidth / 2 - sizePinch / 2
param["y"] = shY - 30 - sizePinch / 2
param["width"] = sizePinch
param["height"] = sizePinch
Shapes_CalcRotatePos()
Shapes.Move(pinch[5]["obj"], x, y)
pinch[5]["_x0"] = x
pinch[5]["_y0"] = y
pinch[5]["_x1"] = x + sizePinch
pinch[5]["_y1"] = y + sizePinch
nPinch = 5
xPinch = "1=0;2=" + shWidth + ";3=0;4=" + shWidth + ";"
yPinch = "1=0;2=0;3=" + shHeight + ";4=" + shHeight + ";"
GraphicsWindow.BrushColor = "#639AE7"
For _i = 1 To 4
pinch[_i]["obj"] = Shapes.AddEllipse(sizePinch, sizePinch)
param["x"] = shX + xPinch[_i] - sizePinch / 2
param["y"] = shY + yPinch[_i] - sizePinch / 2
Shapes_CalcRotatePos()
Shapes.Move(pinch[_i]["obj"], x, y)
pinch[_i]["_x0"] = x
pinch[_i]["_y0"] = y
pinch[_i]["_x1"] = x + sizePinch
pinch[_i]["_y1"] = y + sizePinch
EndFor
EndIf
y = Stack.PopValue("local")
x = Stack.PopValue("local")
Else
selectedshape = ""
For _i = 1 To nPinch
Shapes.Remove(pinch[_i]["obj"])
EndFor
nPinch = 0
EndIf
EndSub

Sub WaitToClick
' return mxD, myD - clicked point
param = "down=True;move=False;up=False;" ' wait to click
Mouse_SetHandler()
While clicked = "False"
Program.Delay(100)
EndWhile
EndSub

Sub WaitToRelease ' for sizing a shape
' param func - "rect", "ell", "tri" or "line"
' param mxD, myD - fixed vertex of a shape
' param mxM, myM - opposite vertex of a shape
' param angle - angle of a shape
' return mxU, myU - opposite vertex of a shape
GraphicsWindow.PenWidth = 1
GraphicsWindow.PenColor = "Black"
GraphicsWindow.BrushColor = "White"
param = "down=False;move=True;up=True;" ' for sizing a shape / wait to release
Mouse_SetHandler()
moved = "True"
While released = "False"
If moved Then
param = "move=False;" ' while sizing a shape
Mouse_SetHandler()
If func = "rect" Or func = "ell" Or func = "tri" Then
If oFrame[func] <> "" Then
Shapes.Remove(oFrame[func])
EndIf
NormalizePos()
xmin = Math.Min(_mxD, _mxM)
ymin = Math.Min(_myD, _myM)
xmax = Math.Max(_mxD, _mxM)
ymax = Math.Max(_myD, _myM)
If func = "rect" Then
oFrame[func] = Shapes.AddRectangle(xmax - xmin, ymax - ymin)
ElseIf func = "ell" Then
oFrame[func] = Shapes.AddEllipse(xmax - xmin, ymax - ymin)
ElseIf func = "tri" Then
oFrame[func] = Shapes.AddTriangle((xmax - xmin) / 2, 0, 0, ymax - ymin, xmax - xmin, ymax - ymin)
EndIf
Shapes.SetOpacity(oFrame[func], 0)
Shapes.Move(oFrame[func], xmin, ymin)
Shapes.Rotate(oFrame[func], angle)
Shapes.SetOpacity(oFrame[func], 50)
ElseIf func = "line" Then
If oFrame[func] <> "" Then
Shapes.Remove(oFrame[func])
EndIf
oFrame[func] = Shapes.AddLine(mxD, myD, mxM, myM)
Shapes.SetOpacity(oFrame[func], 50)
EndIf
param = "move=True;" ' for next sizing a shape
Mouse_SetHandler()
Else
Program.Delay(100)
EndIf
EndWhile
param = "move=False;up=False;" ' mouse released
Mouse_SetHandler()
If oFrame[func] <> "" Then
Shapes.Remove(oFrame[func])
oFrame[func] = ""
EndIf
EndSub

Sub WaitToRelease2 ' for moving a shape
' param i - shape index
' param mxD, myD - fixed vertex of a shape
' return mxU, myU - opposite vertex of a shape
GraphicsWindow.PenWidth = 1
GraphicsWindow.PenColor = "Black"
GraphicsWindow.BrushColor = "White"
param = "down=False;move=True;up=True;" ' for moving a shape / wait to release
Mouse_SetHandler()
_x = shape[i]["x"]
_y = shape[i]["y"]
shAngle = shape[i]["angle"]
mxM = mxD
myM = myD
moved = "True"
While released = "False"
If moved Then
param = "move=False;" ' while moving a shape
Mouse_SetHandler()
_x = shape[i]["x"] + mxM - mxD
_y = shape[i]["y"] + myM - myD
If oFrame[func] = "" Then
If func = "rect" Then
oFrame[func] = Shapes.AddRectangle(shape[i]["width"], shape[i]["height"])
ElseIf func = "ell" Then
oFrame[func] = Shapes.AddEllipse(shape[i]["width"], shape[i]["height"])
ElseIf func = "tri" Then
_x1 = shape[i]["x1"]
_y1 = shape[i]["y1"]
_x2 = shape[i]["x2"]
_y2 = shape[i]["y2"]
_x3 = shape[i]["x3"]
_y3 = shape[i]["y3"]
oFrame[func] = Shapes.AddTriangle(_x1, _y1, _x2, _y2, _x3, _y3)
ElseIf func = "line" Then
_x1 = shape[i]["x1"]
_y1 = shape[i]["y1"]
_x2 = shape[i]["x2"]
_y2 = shape[i]["y2"]
oFrame[func] = Shapes.AddLine(_x1, _y1, _x2, _y2)
Shapes.SetOpacity(oFrame[func], 50)
EndIf
EndIf
If func = "rect" Or func = "ell" Or func = "tri" Then
Shapes.SetOpacity(oFrame[func], 0)
Shapes.Move(oFrame[func], _x, _y)
Shapes.Rotate(oFrame[func], shAngle)
Shapes.SetOpacity(oFrame[func], 50)
ElseIf func = "line" Then
Shapes.Move(oFrame[func], _x, _y)
EndIf
param = "move=True;" ' for next moving a shape
Mouse_SetHandler()
Else
Program.Delay(100)
EndIf
EndWhile
param = "move=False;up=False;" ' mouse released
Mouse_SetHandler()
dx = _x - shape[i]["x"]
dy = _y - shape[i]["y"]
shape[i]["x"] = _x
shape[i]["y"] = _y
shape[i]["_x0"] = shape[i]["_x0"] + dx
shape[i]["_x1"] = shape[i]["_x1"] + dx
shape[i]["_y0"] = shape[i]["_y0"] + dy
shape[i]["_y1"] = shape[i]["_y1"] + dy
Shapes.Move(shape[i]["obj"], _x, _y)
If shape[i]["func"] = "line" Then
_iMax = 2
Else
_iMax = 5
EndIf
For _i = 1 To _iMax
pinch[_i]["_x0"] = pinch[_i]["_x0"] + dx
pinch[_i]["_x1"] = pinch[_i]["_x1"] + dx
pinch[_i]["_y0"] = pinch[_i]["_y0"] + dy
pinch[_i]["_y1"] = pinch[_i]["_y1"] + dy
Shapes.Move(pinch[_i]["obj"], pinch[_i]["_x0"], pinch[_i]["_y0"])
EndFor
If oFrame[func] <> "" Then
Shapes.Remove(oFrame[func])
oFrame[func] = ""
EndIf
EndSub

Sub WaitToRelease3 ' for rotating a shape
' param i - shape index
' return angle - angle for rotation
GraphicsWindow.PenWidth = 1
GraphicsWindow.PenColor = "Black"
GraphicsWindow.BrushColor = "White"
param = "down=False;move=True;up=True;" ' for rotating a shape / wait to release
Mouse_SetHandler()
CalcPinchPos() ' into mxM, myM
cx = param["cx"]
cy = param["cy"]
If func = "tri" Then
x1 = shape[i]["x1"]
y1 = shape[i]["y1"]
x2 = shape[i]["x2"]
y2 = shape[i]["y2"]
x3 = shape[i]["x3"]
y3 = shape[i]["y3"]
EndIf
moved = "True"
While released = "False"
If moved Then
param = "move=False;" ' while sizing a shape
Mouse_SetHandler()
If oFrame[func] <> "" Then
Shapes.Remove(oFrame[func])
EndIf
If func = "rect" Then
oFrame[func] = Shapes.AddRectangle(width, height)
ElseIf func = "ell" Then
oFrame[func] = Shapes.AddEllipse(width, height)
ElseIf func = "tri" Then
oFrame[func] = Shapes.AddTriangle(x1, y1, x2, y2, x3, y3)
EndIf
Shapes.SetOpacity(oFrame[func], 0)
Shapes.Move(oFrame[func], _x, _y)
x = mxM - cx
y = myM - cy
If x <> 0 Or y <> 0 Then
Math_CartesianToPolar()
angle = Math.Floor(a + 90)
If angle >= 360 Then
angle = angle - 360
EndIf
EndIf
Shapes.Rotate(oFrame[func], angle)
Shapes.SetOpacity(oFrame[func], 50)
param = "move=True;" ' for next sizing a shape
Mouse_SetHandler()
Else
Program.Delay(100)
EndIf
EndWhile
param = "move=False;up=False;" ' mouse released
Mouse_SetHandler()
If oFrame[func] <> "" Then
Shapes.Remove(oFrame[func])
oFrame[func] = ""
EndIf
EndSub

Sub WriteShapes
Stack.PushValue("local", i)
buf = "' " + Clock.Date + " " + Clock.Time + " Generated" + CRLF
buf = buf + "' by " + title + CRLF
buf = buf + "'" + CRLF
buf = buf + "' initialize shapes" + CRLF
buf = buf + "Shapes_Init()" + CRLF
buf = buf + "' add shapes" + CRLF
buf = buf + "scale = 1" + CRLF
buf = buf + "Shapes_Add()" + CRLF
buf = buf + "angle = 0" + CRLF
buf = buf + CRLF
buf = buf + "Sub Shapes_Init" + CRLF
buf = buf + " ' Shapes | Initialize shapes data" + CRLF
buf = buf + " ' return shX, shY - current position of shapes" + CRLF
buf = buf + " ' return shape - array of shapes" + CRLF
If nShapes > 0 Then
xmin = shape[1]["x"]
ymin = shape[1]["y"]
xman = shape[1]["x"]
yman = shape[1]["y"]
EndIf
For i = 2 To nShapes
If shape[i]["x"] < xmin Then
xmin = shape[i]["x"]
EndIf
If shape[i]["y"] < ymin Then
ymin = shape[i]["y"]
EndIf
If xmax < shape[i]["x"] Then
xmax = shape[i]["x"]
EndIf
If ymax < shape[i]["y"] Then
ymax = shape[i]["y"]
EndIf
EndFor
buf = buf + " shX = " + xmin + " ' x offset" + CRLF
buf = buf + " shY = " + ymin + " ' y offset" + CRLF
buf = buf + " shape = " + WQ + WQ + CRLF
For i = 1 To nShapes
If shape[i]["func"] = "rect" Or shape[i]["func"] = "ell" Then
buf = buf + " shape[" + i + "] = " + WQ + "func=" + shape[i]["func"] + ";"
buf = buf + "x=" + (shape[i]["x"] - xmin) + ";"
buf = buf + "y=" + (shape[i]["y"] - ymin) + ";"
buf = buf + "width=" + shape[i]["width"] + ";"
buf = buf + "height=" + shape[i]["height"] + ";"
If shape[i]["angle"] <> 0 And shape[i]["angle"] <> "" Then
buf = buf + "angle=" + shape[i]["angle"] + ";"
EndIf
buf = buf + "bc=" + shape[i]["bc"] + ";"
ElseIf shape[i]["func"] = "tri" Then
buf = buf + " shape[" + i + "] = " + WQ + "func=tri;"
buf = buf + "x=" + (shape[i]["x"] - xmin) + ";"
buf = buf + "y=" + (shape[i]["y"] - ymin) + ";"
buf = buf + "x1=" + shape[i]["x1"] + ";"
buf = buf + "y1=" + shape[i]["y1"] + ";"
buf = buf + "x2=" + shape[i]["x2"] + ";"
buf = buf + "y2=" + shape[i]["y2"] + ";"
buf = buf + "x3=" + shape[i]["x3"] + ";"
buf = buf + "y3=" + shape[i]["y3"] + ";"
If shape[i]["angle"] <> 0 And shape[i]["angle"] <> "" Then
buf = buf + "angle=" + shape[i]["angle"] + ";"
EndIf
buf = buf + "bc=" + shape[i]["bc"] + ";"
ElseIf shape[i]["func"] = "line" Then
buf = buf + " shape[" + i + "] = " + WQ + "func=line;"
buf = buf + "x=" + (shape[i]["x"] - xmin) + ";"
buf = buf + "y=" + (shape[i]["y"] - ymin) + ";"
buf = buf + "x1=" + shape[i]["x1"] + ";"
buf = buf + "y1=" + shape[i]["y1"] + ";"
buf = buf + "x2=" + shape[i]["x2"] + ";"
buf = buf + "y2=" + shape[i]["y2"] + ";"
EndIf
If shape[i]["pw"] > 0 Then
buf = buf + "pc=" + shape[i]["pc"] + ";"
EndIf
buf = buf + "pw=" + shape[i]["pw"] + ";" + WQ + CRLF
EndFor
buf = buf + "EndSub" + CRLF
buf = buf + CRLF
buf = buf + "Sub Shapes_Add" + CRLF
buf = buf + " ' Shapes | Add shapes as shapes data" + CRLF
buf = buf + " ' param shape - array of shapes" + CRLF
buf = buf + " ' param scale - to zoom" + CRLF
buf = buf + " ' return shWidth, shHeight - total size of shapes" + CRLF
buf = buf + " ' return shAngle - current angle of shapes" + CRLF
buf = buf + " Stack.PushValue(" + WQ + "local" + WQ + ", i)" + CRLF
buf = buf + " Stack.PushValue(" + WQ + "local" + WQ + ", x)" + CRLF
buf = buf + " Stack.PushValue(" + WQ + "local" + WQ + ", y)" + CRLF
buf = buf + " Shapes_CalcWidthAndHeight()" + CRLF
buf = buf + " s = scale" + CRLF
buf = buf + " For i = 1 To nShapes" + CRLF
buf = buf + " GraphicsWindow.PenWidth = shape[i][" + WQ + "pw" + WQ + "] * s" + CRLF
buf = buf + " If shape[i][" + WQ + "pw" + WQ + "] > 0 Then" + CRLF
buf = buf + " GraphicsWindow.PenColor = shape[i][" + WQ + "pc" + WQ + "]" + CRLF
buf = buf + " EndIf" + CRLF
buf = buf + " If shape[i][" + WQ + "func" + WQ + "] = " + WQ + "rect" + WQ + " Then" + CRLF
buf = buf + " GraphicsWindow.BrushColor = shape[i][" + WQ + "bc" + WQ + "]" + CRLF
buf = buf + " x = shape[i][" + WQ + "x" + WQ + "]" + CRLF
buf = buf + " y = shape[i][" + WQ + "y" + WQ + "]" + CRLF
buf = buf + " width = shape[i][" + WQ + "width" + WQ + "]" + CRLF
buf = buf + " height = shape[i][" + WQ + "height" + WQ + "]" + CRLF
buf = buf + " shape[i][" + WQ + "obj" + WQ + "] = Shapes.AddRectangle(width * s, height * s)" + CRLF
buf = buf + " Shapes.Move(shape[i][" + WQ + "obj" + WQ + "], shX + x * s, shY + y * s)" + CRLF
buf = buf + " If shape[i][" + WQ + "angle" + WQ + "] <> 0 Then" + CRLF
buf = buf + " Shapes.Rotate(shape[i][" + WQ + "obj" + WQ + "], shape[i][" + WQ + "angle" + WQ + "])" + CRLF
buf = buf + " EndIf" + CRLF
buf = buf + " ElseIf shape[i][" + WQ + "func" + WQ + "] = " + WQ + "ell" + WQ + " Then" + CRLF
buf = buf + " GraphicsWindow.BrushColor = shape[i][" + WQ + "bc" + WQ + "]" + CRLF
buf = buf + " x = shape[i][" + WQ + "x" + WQ + "]" + CRLF
buf = buf + " y = shape[i][" + WQ + "y" + WQ + "]" + CRLF
buf = buf + " width = shape[i][" + WQ + "width" + WQ + "]" + CRLF
buf = buf + " height = shape[i][" + WQ + "height" + WQ + "]" + CRLF
buf = buf + " shape[i][" + WQ + "obj" + WQ + "] = Shapes.AddEllipse(width * s, height * s)" + CRLF
buf = buf + " Shapes.Move(shape[i][" + WQ + "obj" + WQ + "], shX + x * s, shY + y * s)" + CRLF
buf = buf + " If shape[i][" + WQ + "angle" + WQ + "] <> 0 Then" + CRLF
buf = buf + " Shapes.Rotate(shape[i][" + WQ + "obj" + WQ + "], shape[i][" + WQ + "angle" + WQ + "])" + CRLF
buf = buf + " EndIf" + CRLF
buf = buf + " ElseIf shape[i][" + WQ + "func" + WQ + "] = " + WQ + "tri" + WQ + " Then" + CRLF
buf = buf + " GraphicsWindow.BrushColor = shape[i][" + WQ + "bc" + WQ + "]" + CRLF
buf = buf + " x = shape[i][" + WQ + "x" + WQ + "]" + CRLF
buf = buf + " y = shape[i][" + WQ + "y" + WQ + "]" + CRLF
buf = buf + " x1 = shape[i][" + WQ + "x1" + WQ + "]" + CRLF
buf = buf + " y1 = shape[i][" + WQ + "y1" + WQ + "]" + CRLF
buf = buf + " x2 = shape[i][" + WQ + "x2" + WQ + "]" + CRLF
buf = buf + " y2 = shape[i][" + WQ + "y2" + WQ + "]" + CRLF
buf = buf + " x3 = shape[i][" + WQ + "x3" + WQ + "]" + CRLF
buf = buf + " y3 = shape[i][" + WQ + "y3" + WQ + "]" + CRLF
buf = buf + " shape[i][" + WQ + "obj" + WQ + "] = Shapes.AddTriangle(x1 * s, y1 * s, x2 * s, y2 * s, x3 * s, y3 * s)" + CRLF
buf = buf + " Shapes.Move(shape[i][" + WQ + "obj" + WQ + "], shX + x * s, shY + y * s)" + CRLF
buf = buf + " If shape[i][" + WQ + "angle" + WQ + "] <> 0 Then" + CRLF
buf = buf + " Shapes.Rotate(shape[i][" + WQ + "obj" + WQ + "], shape[i][" + WQ + "angle" + WQ + "])" + CRLF
buf = buf + " EndIf" + CRLF
buf = buf + " ElseIf shape[i][" + WQ + "func" + WQ + "] = " + WQ + "line" + WQ + " Then" + CRLF
buf = buf + " x = shape[i][" + WQ + "x" + WQ + "]" + CRLF
buf = buf + " y = shape[i][" + WQ + "y" + WQ + "]" + CRLF
buf = buf + " x1 = shape[i][" + WQ + "x1" + WQ + "]" + CRLF
buf = buf + " y1 = shape[i][" + WQ + "y1" + WQ + "]" + CRLF
buf = buf + " x2 = shape[i][" + WQ + "x2" + WQ + "]" + CRLF
buf = buf + " y2 = shape[i][" + WQ + "y2" + WQ + "]" + CRLF
buf = buf + " shape[i][" + WQ + "obj" + WQ + "] = Shapes.AddLine(x1 * s, y1 * s, x2 * s, y2 * s)" + CRLF
buf = buf + " Shapes.Move(shape[i][" + WQ + "obj" + WQ + "], shX + x * s, shY + y * s)" + CRLF
buf = buf + " EndIf" + CRLF
buf = buf + " shape[i][" + WQ + "rx" + WQ + "] = x" + CRLF
buf = buf + " shape[i][" + WQ + "ry" + WQ + "] = y" + CRLF
buf = buf + " EndFor" + CRLF
buf = buf + " shAngle = 0" + CRLF
buf = buf + " y = Stack.PopValue(" + WQ + "local" + WQ + ")" + CRLF
buf = buf + " x = Stack.PopValue(" + WQ + "local" + WQ + ")" + CRLF
buf = buf + " i = Stack.PopValue(" + WQ + "local" + WQ + ")" + CRLF
buf = buf + "EndSub" + CRLF
buf = buf + CRLF
buf = buf + "Sub Shapes_CalcWidthAndHeight" + CRLF
buf = buf + " ' Shapes | Calculate total width and height of shapes" + CRLF
buf = buf + " ' return nShapes - number of shapes" + CRLF
buf = buf + " ' return shWidth, shHeight - total size of shapes" + CRLF
buf = buf + " nShapes = Array.GetItemCount(shape)" + CRLF
buf = buf + " For i = 1 To nShapes" + CRLF
buf = buf + " If shape[i][" + WQ + "func" + WQ + "] = " + WQ + "tri" + WQ + " Or shape[i][" + WQ + "func" + WQ + "] = " + WQ + "line" + WQ + " Then" + CRLF
buf = buf + " xmin = shape[i][" + WQ + "x1" + WQ + "]" + CRLF
buf = buf + " xmax = shape[i][" + WQ + "x1" + WQ + "]" + CRLF
buf = buf + " ymin = shape[i][" + WQ + "y1" + WQ + "]" + CRLF
buf = buf + " ymax = shape[i][" + WQ + "y1" + WQ + "]" + CRLF
buf = buf + " If shape[i][" + WQ + "x2" + WQ + "] < xmin Then" + CRLF
buf = buf + " xmin = shape[i][" + WQ + "x2" + WQ + "]" + CRLF
buf = buf + " EndIf" + CRLF
buf = buf + " If xmax < shape[i][" + WQ + "x2" + WQ + "] Then" + CRLF
buf = buf + " xmax = shape[i][" + WQ + "x2" + WQ + "]" + CRLF
buf = buf + " EndIf" + CRLF
buf = buf + " If shape[i][" + WQ + "y2" + WQ + "] < ymin Then" + CRLF
buf = buf + " ymin = shape[i][" + WQ + "y2" + WQ + "]" + CRLF
buf = buf + " EndIf" + CRLF
buf = buf + " If ymax < shape[i][" + WQ + "y2" + WQ + "] Then" + CRLF
buf = buf + " ymax = shape[i][" + WQ + "y2" + WQ + "]" + CRLF
buf = buf + " EndIf" + CRLF
buf = buf + " If shape[i][" + WQ + "func" + WQ + "] = " + WQ + "tri" + WQ + " Then" + CRLF
buf = buf + " If shape[i][" + WQ + "x3" + WQ + "] < xmin Then" + CRLF
buf = buf + " xmin = shape[i][" + WQ + "x3" + WQ + "]" + CRLF
buf = buf + " EndIf" + CRLF
buf = buf + " If xmax < shape[i][" + WQ + "x3" + WQ + "] Then" + CRLF
buf = buf + " xmax = shape[i][" + WQ + "x3" + WQ + "]" + CRLF
buf = buf + " EndIf" + CRLF
buf = buf + " If shape[i][" + WQ + "y3" + WQ + "] < ymin Then" + CRLF
buf = buf + " ymin = shape[i][" + WQ + "y3" + WQ + "]" + CRLF
buf = buf + " EndIf" + CRLF
buf = buf + " If ymax < shape[i][" + WQ + "y3" + WQ + "] Then" + CRLF
buf = buf + " ymax = shape[i][" + WQ + "y3" + WQ + "]" + CRLF
buf = buf + " EndIf" + CRLF
buf = buf + " EndIf" + CRLF
buf = buf + " shape[i][" + WQ + "width" + WQ + "] = xmax - xmin" + CRLF
buf = buf + " shape[i][" + WQ + "height" + WQ + "] = ymax - ymin" + CRLF
buf = buf + " EndIf" + CRLF
buf = buf + " If i = 1 Then" + CRLF
buf = buf + " shWidth = shape[i][" + WQ + "x" + WQ + "] + shape[i][" + WQ + "width" + WQ + "]" + CRLF
buf = buf + " shHeight = shape[i][" + WQ + "y" + WQ + "] + shape[i][" + WQ + "height" + WQ + "]" + CRLF
buf = buf + " Else" + CRLF
buf = buf + " If shWidth < shape[i][" + WQ + "x" + WQ + "] + shape[i][" + WQ + "width" + WQ + "] Then" + CRLF
buf = buf + " shWidth = shape[i][" + WQ + "x" + WQ + "] + shape[i][" + WQ + "width" + WQ + "]" + CRLF
buf = buf + " EndIf" + CRLF
buf = buf + " If shHeight < shape[i][" + WQ + "y" + WQ + "] + shape[i][" + WQ + "height" + WQ + "] Then" + CRLF
buf = buf + " shHeight = shape[i][" + WQ + "y" + WQ + "] + shape[i][" + WQ + "height" + WQ + "]" + CRLF
buf = buf + " EndIf" + CRLF
buf = buf + " EndIf" + CRLF
buf = buf + " EndFor" + CRLF
buf = buf + "EndSub" + CRLF
buf = buf + CRLF
' Import GTV460 and insert here if you need move and rotation in output program.
File_Save()
i = Stack.PopValue("local")
EndSub

Sub Color_ColorToRGB
' Color | Convert Color to RGB
' param sColor - "#rrggbb"
' return iR, iG, iB - [0, 255]
sR = Text.GetSubText(sColor, 2, 2)
sG = Text.GetSubText(sColor, 4, 2)
sB = Text.GetSubText(sColor, 6, 2)
sHex = sR
Math_Hex2Dec()
iR = iDec
sHex = sG
Math_Hex2Dec()
iG = iDec
sHex = sB
Math_Hex2Dec()
iB = iDec
EndSub

Sub Color_HSLtoRGB
' Color | Convert HSL to RGB
' param rHue - [0, 360) or UNDEFINED
' param rLightness - [0, 1]
' param rSaturation - [0, 1]
' return iR, iG, iB - RGB color
' return sColor - "#rrggbb"
If rLightness <= 0.5 Then
rN2 = rLightness * (1 + rSaturation)
Else
rN2 = rLightness + rSaturation - rLightness * rSaturation
EndIf
rN1 = 2 * rLightness - rN2
If rSaturation = 0 Then
iR = Math.Round(rLightness * 255)
iG = Math.Round(rLightness * 255)
iB = Math.Round(rLightness * 255)
Else
rH = rHue + 120
Color_Value()
iR = iValue
rH = rHue
Color_Value()
iG = iValue
rH = rHue - 120
Color_Value()
iB = iValue
EndIf
sColor = GraphicsWindow.GetColorFromRGB(iR, iG, iB)
EndSub

Sub Color_RGBtoHSL
' Color | Convert RGB to HSL
' param sColor - "#rrggbb"
' return rHue - [0, 360) or UNDEFINED
' return rLightness - (0, 1)
' return rSaturation - (0, 1)
Color_ColorToRGB()
' rR = iR / 255 ' occurs Math.Max() bug
rR = Math.Round(iR / 255 * 10000) / 10000
' rG = iG / 255 ' occurs Math.Max() bug
rG = Math.Round(iG / 255 * 10000) / 10000
' rB = iB / 255 ' occurs Math.Max() bug
rB = Math.Round(iB / 255 * 10000) / 10000
rMax = Math.Max(rR, rG)
rMax = Math.Max(rMax, rB)
rMin = Math.Min(rR, rG)
rMin = Math.Min(rMin, rB)
rLightness = (rMax + rMin) / 2
If rMax = rMin Then ' rR = rG = rB
rSaturation = 0
rHue = UNDEFINED
Else
If rLightness <= 0.5 Then
rSaturation = (rMax - rMin) / (rMax + rMin)
Else
rSaturation = (rMax - rMin) / (2 - rMax - rMin)
EndIf
rRC = (rMax - rR) / (rMax - rMin)
rGC = (rMax - rG) / (rMax - rMin)
rBC = (rMax - rB) / (rMax - rMin)
If rR = rMax Then ' between Yellow and Magenta
rHue = rBC - rGC
ElseIf rG = rMax Then ' between Cyan and Yellow
rHue = 2 + rRC - rBC
ElseIf rB = rMax Then ' between Magenta and Cyan
rHue = 4 + rGC - rRC
Else
TextWindow.WriteLine("Error:")
TextWindow.WriteLine("rMax=" + rMax)
TextWindow.WriteLine("rR=" + rR + ",sR=" + sR)
TextWindow.WriteLine("rG=" + rG + ",sG=" + sG)
TextWindow.WriteLine("rB=" + rB + ",sB=" + sB)
EndIf
rHue = rHue * 60
If rHue < 0 Then
rHue = rHue + 360
EndIf
EndIf
EndSub

Sub Color_Value
' Color | Function value
' param rN1, rN2
' param rH - [-120, 480)
' return iValue - 0..255
If rH >= 360 Then
rH = rH - 360
EndIF
If rH < 0 Then
rH = rH + 360
EndIF
If rH < 60 Then
rV = rN1 + (rN2 - rN1) * rH / 60
ElseIf rH < 180 Then
rV = rN2
ElseIf rH < 240 Then
rV = rN1 + (rN2 - rN1) * (240 - rH) / 60
Else
rV = rN1
EndIf
iValue = Math.Round(rV * 255)
EndSub

Sub CS_AddColorToPalette
' Color Selector | Add color to palette
' param color - color to set
' param maxPalette
' param nPalette
' param palette
' param tPalette - target palette
Stack.PushValue("local", i)
For i = 1 To nPalette
If color = palette[i]["color"] Then
Goto csactp_not_new_color
EndIf
EndFor
palette[tPalette]["color"] = color
If nPalette < maxPalette Then
nPalette = nPalette + 1
EndIf
tPalette = tPalette + 1
If maxPalette < tPalette Then
tPalette = 1
EndIf
csactp_not_new_color:
i = Stack.PopValue("local")
EndSub

Sub CS_AdjustSlider
' Color Selector | Adjust slider
' param iSlider - moved slider
Stack.PushValue("local", iSlider)
If iSlider = iHue Or iSlider = iLightness Or iSlider = iSaturation Then
If iSlider = iHue Then
Slider_GetLevel()
rHue = level
ElseIf iSlider = iLightness Then
Slider_GetLevel()
rLightness = level / 100
Else
Slider_GetLevel()
rSaturation = level / 100
EndIf
Color_HSLtoRGB()
iSlider = iRed
level = iR
Slider_SetLevel()
iSlider = iGreen
level = iG
Slider_SetLevel()
iSlider = iBlue
level = iB
Slider_SetLevel()
Else
CS_GetColorFromSlider()
sColor = GraphicsWindow.GetColorFromRGB(red, green, blue)
Color_RGBtoHSL()
If rHue = UNDEFINED Then
rHue = 0
EndIf
level = Math.Floor(rHue)
iSlider = iHue
Slider_SetLevel()
level = Math.Floor(rSaturation * 100)
iSlider = iSaturation
Slider_SetLevel()
level = Math.Floor(rLightness * 100)
iSlider = iLightness
Slider_SetLevel()
EndIf
iSlider = Stack.PopValue("local")
EndSub

Sub CS_DoObject
' Color Selector | Do object
' param - obj
While obj <> ""
CS_DoSlider()
If obj <> "" Then
CS_DoPalette()
EndIf
EndWhile
EndSub

Sub CS_DoPalette
' Color Selector | Do palette
' param obj - clicked object
If Text.StartsWith(obj, "palette") Then
iPalette = Text.GetSubTextToEnd(obj, 8)
color = palette[iPalette]["color"]
CS_SetColorToSlider() ' set color to slider
CS_ShowNewColor() ' show new color name
CS_DrawColorRect() ' draw new color rectangle
obj = ""
param = "down=True;move=False;up=False;" ' wait to click
Mouse_SetHandler()
EndIf
EndSub

Sub CS_DoSlider
' Color Selector | Do slider
' param obj - clicked object
' param iSlider - index of slider
If Text.StartsWith(obj, "slider") Then
Slider_WaitToRelease()
obj = ""
param = "down=True;move=False;up=False;" ' wait to click
Mouse_SetHandler()
EndIf
EndSub

Sub CS_DrawColorRect
' Color Selector | Draw color rectangle
' param color - color of rectangle
' param x, y - position of rectangle
' param width, height - size of rectangle
' return oRect - rectangle object
GraphicsWindow.BrushColor = color
GraphicsWindow.PenColor = BORDERCOLOR
If oRect <> "" Then
Shapes.Remove(oRect)
EndIf
oRect = Shapes.AddRectangle(width, height)
Shapes.Move(oRect, x, y)
EndSub

Sub CS_DrawPalette
' Color Selector | Draw palette
' param palette[] - color palette
' param nPalette - number of color in palette
' param x, y - position of rectangle
' param width, height - size of rectangle
' return oPalette[] - palette object array
Stack.PushValue("local", i)
GraphicsWindow.PenColor = BORDERCOLOR
For i = 1 To nPalette
GraphicsWindow.BrushColor = palette[i]["color"]
palette[i]["oCell"] = Shapes.AddRectangle(width, height)
dx = Math.Remainder((i - 1), 8) * (width + 4)
dy = Math.Floor((i - 1) / 8) * (height + 4)
Shapes.Move(palette[i]["oCell"], x + dx, y + dy)
palette[i]["x"] = x + dx
palette[i]["y"] = y + dy
palette[i]["width"] = width
palette[i]["height"] = height
EndFor
i = Stack.PopValue("local")
EndSub

Sub CS_GetColorFromSlider
' Color Selector | get color from slider
' return color
Stack.PushValue("local", iSlider)
iSlider = iRed ' slider index
Slider_GetLevel()
red = level
iSlider = iGreen ' slider index
Slider_GetLevel()
green = level
iSlider = iBlue ' slider index
Slider_GetLevel()
blue = level
color = GraphicsWindow.GetColorFromRGB(red, green, blue)
iSlider = Stack.PopValue("local")
EndSub

Sub CS_Init
' Color Selector | Initialize sliders
width = 256
min = 0
max = 255
left = 190
' add red slider
top = TOPY
caption = "R"
Slider_Add()
iRed = iSlider ' index of slider
' add green slider
top = top + DELTAY
caption = "G"
Slider_Add()
iGreen = iSlider ' index of slider
' add blue slider
top = top + DELTAY
caption = "B"
Slider_Add()
iBlue = iSlider ' index of slider
' add hue slider
width = 360
top = top + DELTAY
max = 360
caption = "H"
Slider_Add()
iHue = iSlider ' index of slider
' add saturation slider
width = 100
top = top + DELTAY
max = 100
caption = "S"
Slider_Add()
iSaturation = iSlider ' index of slider
' add lightness slider
width = 100
top = top + DELTAY
max = 100
caption = "L"
Slider_Add()
iLightness = iSlider ' index of slider
' draw color rectangle
CS_GetColorFromSlider()
CS_ShowNewColor()
x = LEFTX
y = TOPY + DELTAY * 4
width = 100
height = 100
CS_DrawColorRect()
' add text box
GraphicsWindow.BrushColor = CAPTIONCOLOR
top = y + height + 4
oNewColor = Shapes.AddText("")
Shapes.Move(oNewColor, LEFTX, top)
EndSub

Sub CS_DumpSlider
' Color Selector | Dump slider for debug
For i = 1 To numSlider
TextWindow.WriteLine("slider" + i)
TextWindow.WriteLine(slider[i])
EndFor
EndSub

Sub CS_InitPalette
' Color Selector | Initialize palette
' This subroutine should be called before CS_ShowPopup().
maxPalette = 16 ' max cell number of palette
nPalette = 2 ' number of palette in use
tPalette = 3 ' index of update target cell
palette[1]["color"] = pcolor
palette[2]["color"] = bcolor
EndSub

Sub CS_RemovePalette
' Color Selector | Remove palette
' param nPalette - number of color in palette
' return oPalette[] - palette object array
Stack.PushValue("local", i)
For i = 1 To nPalette
oPalette = "Palette" + i
Shapes.Remove(palette[i]["oCell"])
EndFor
i = Stack.PopValue("local")
EndSub

Sub CS_RemoveSliders
' Color Selector | Remove sliders
For iSlider = 1 To numSlider
Slider_Remove()
EndFor
numSlider = 0
EndSub

Sub CS_SearchClickedObject
' Color Selector | Check slider clicked
' param mxD, myD - clicked point
' return obj - clicked slider or palette
' return iSlider - index if obj is slider
' return iPalette - index if obj is palette
Stack.PushValue("local", i)
For iSlider = 1 To numSlider
obj = "slider" + iSlider
x2 = slider[iSlider]["x2"]
y2 = slider[iSlider]["y2"]
x3 = slider[iSlider]["x3"]
y3 = slider[iSlider]["y3"]
If x2 <= mxD And mxD <= x3 And y2 <= myD And myD <= y3 Then
Goto scco_obj_found
EndIf
EndFor
For iPalette = 1 To nPalette
obj = "palette" + iPalette
x2 = palette[iPalette]["x"]
y2 = palette[iPalette]["y"]
x3 = palette[iPalette]["x"] + palette[iPalette]["width"]
y3 = palette[iPalette]["y"] + palette[iPalette]["height"]
If x2 <= mxD And mxD <= x3 And y2 <= myD And myD <= y3 Then
Goto scco_obj_found
EndIf
EndFor
obj = ""
scco_obj_found:
i = Stack.PopValue("local")
EndSub

Sub CS_SetColorToSlider
' Color Selector | Set color to slider
' param color
Stack.PushValue("local", iSlider)
sColor = color
Color_ColorToRGB()
iSlider = iRed
level = iR
Slider_SetLevel()
iSlider = iGreen
level = iG
Slider_SetLevel()
iSlider = iBlue
level = iB
Slider_SetLevel()
CS_AdjustSlider()
iSlider = Stack.PopValue("local")
EndSub

Sub CS_ShowNewColor
' Color Selector | Show new color
' param oColor
' param color
Shapes.SetText(oNewColor, color)
EndSub

Sub CS_ShowPopup
' Color Selector | Show popup
' param color - current color
' return color - new color
' define constant
Stack.PushValue("local", cont)
colorInit = color ' initial color
TOPY = 80 ' top y
LEFTX = 36 ' left x
BORDERCOLOR = "#666666"
BOXCOLOR = "LightGray"
CAPTIONCOLOR = "White"
DELTAY = 36 ' delta y
SLITCOLOR = "#555555"
TEXTCOLOR = "Black"
UNDEFINED = "N/A"
POPUPCOLOR = "Black"
GraphicsWindow.PenWidth = 2
GraphicsWindow.PenColor = POPUPCOLOR
GraphicsWindow.BrushColor = POPUPCOLOR
oPopup = Shapes.AddRectangle(570, 310)
Shapes.SetOpacity(oPopup, 64)
Shapes.Move(oPopup, LEFTX - 10, TOPY - 10)
oOK = Controls.AddButton("OK", LEFTX + 440, TOPY + 260)
oCancel = Controls.AddButton("Cancel", LEFTX + 480, TOPY + 260)
Controls.ButtonClicked = CS_OnButtonClicked
CS_Init()
Stack.PushValue("local", y)
y = TOPY
color = colorInit
CS_DrawColorRect() ' original color
oRectCurrent = oRect
oRect = "" ' keep current color
GraphicsWindow.SetPixel(0, 0, colorInit)
color = GraphicsWindow.GetPixel(0, 0)
GraphicsWindow.SetPixel(0, 0, "LightGray")
GraphicsWindow.BrushColor = CAPTIONCOLOR
oColor = Shapes.AddText(colorInit)
Shapes.Move(oColor, x, y + height + 2)
If color <> colorInit Then
oColor2 = Shapes.AddText(color)
Shapes.Move(oColor2, x, y + height + 14)
EndIf
y = Stack.PopValue("local")
CS_SetColorToSlider()
CS_DrawColorRect() ' draw new color rectangle
CS_ShowNewColor() ' show new color name
Stack.PushValue("local", x)
Stack.PushValue("local", y)
Stack.PushValue("local", width)
Stack.PushValue("local", height)
x = x + width + 30
y = TOPY + height * 2 + 24
width = 30
height = 30
CS_DrawPalette()
height = Stack.PopValue("local")
width = Stack.PopValue("local")
y = Stack.PopValue("local")
x = Stack.PopValue("local")
cont = "True" ' continue
param = "down=True;move=False;up=False;" ' wait click
Mouse_SetHandler()
While cont
If clicked Then
CS_SearchClickedObject()
CS_DoObject()
clicked = "False"
Else
Program.Delay(100)
EndIf
EndWhile
If cancel Then
color = colorInit
Else
CS_AddColorToPalette()
EndIf
CS_RemovePalette()
CS_RemoveSliders()
Shapes.Remove(oColor)
Shapes.Remove(oColor2)
Shapes.Remove(oNewColor)
Shapes.Remove(oRectCurrent)
Shapes.Remove(oRect)
Controls.Remove(oOK)
Controls.Remove(oCancel)
Shapes.Remove(oPopup)
cont = Stack.PopValue("local")
EndSub

Sub CS_OnButtonClicked
' Color Selector | Event handler on button clicked
cont = "False"
If Controls.LastClickedButton = oCancel Then
cancel = "True"
Else
cancel = "False"
EndIf
EndSub

Sub File_Save
' File | Show output program to save
' param buf - program buffer
' define constant
Stack.PushValue("local", cont)
colorInit = color ' initial color
TOPY = 80 ' top y
LEFTX = 36 ' left x
DELTAY = 40 ' delta y
CAPTIONCOLOR = "White"
POPUPCOLOR = "Black"
TEXTCOLOR = "Black"
GraphicsWindow.PenWidth = 0
GraphicsWindow.BrushColor = POPUPCOLOR
oPopup = Shapes.AddRectangle(570, 310)
Shapes.SetOpacity(oPopup, 64)
Shapes.Move(oPopup, LEFTX - 10, TOPY - 10)
oText = Controls.AddTextBox(LEFTX, TOPY)
Controls.SetSize(oText, 550, 240)
Controls.SetTextBoxText(oText, buf)
oOK = Controls.AddButton("OK", LEFTX + 500, TOPY + 260)
cont = "True" ' continue
Controls.ButtonClicked = File_OnButtonClicked
While cont
Program.Delay(200)
EndWhile
Controls.Remove(oText)
Controls.Remove(oOK)
Controls.Remove(oPopup)
cont = Stack.PopValue("local")
EndSub

Sub File_OnButtonClicked
' File | Button event handler
cont = "False"
EndSub

Sub Math_CartesianToPolar
' Math | convert cartesian coodinate to polar coordinate
' param x, y - cartesian coordinate
' return r, a - polar coordinate
r = Math.SquareRoot(x * x + y * y)
If x = 0 And y > 0 Then
a = 90 ' [degree]
ElseIf x = 0 And y < 0 Then
a = -90
Else
a = Math.ArcTan(y / x) * 180 / Math.Pi
EndIf
If x < 0 Then
a = a + 180
ElseIf x > 0 And y < 0 Then
a = a + 360
EndIf
EndSub

Sub Math_Hex2Dec
' Math | Convert hexadecimal to decimal
' param sHex
' return iDec
iDec = 0
iLen = Text.GetLength(sHex)
For iPtr = 1 To iLen
iDec = iDec * 16 + Text.GetIndexOf("0123456789ABCDEF", Text.GetSubText(sHex, iPtr, 1)) - 1
EndFor
EndSub

Sub Copy_Init
' Copy | Initialize shapes data for menu icon
' return shX, shY - current position of shapes
' return shape - array of shapes
shX = 220 ' x offset
shY = 30 ' y offset
shape = ""
shape[1] = "func=rect;x=256;y=220;width=168;height=173;bc=#FFFFFF;pc=#2E2E2E;pw=4;"
shape[2] = "func=rect;x=312;y=169;width=168;height=173;bc=#FFFFFF;pc=#2E2E2E;pw=4;"
EndSub

Sub Paste_Init
' Paste | Initialize shapes data for menu icon
' return shX, shY - current position of shapes
' return shape - array of shapes
shX = 220 ' x offset
shY = 86 ' y offset
shape = ""
shape[1] = "func=rect;x=0;y=0;width=219;height=276;bc=#AE895B;pw=0;"
shape[2] = "func=rect;x=27;y=31;width=165;height=222;bc=#FFFFFF;pw=0;"
shape[3] = "func=rect;x=53;y=22;width=112;height=21;bc=#AFAFAF;pw=0;"
EndSub

Sub Scissors_Init
' Scissors | Initialize shapes data for menu icon
' return shX, shY - current position of shapes
' return shape - array of shapes
shX = 237 ' x offset
shY = 30 ' y offset
shape = ""
shape[1] = "func=tri;x=45;y=0;x1=22;y1=0;x2=0;y2=213;x3=44;y3=213;bc=#6E6E6E;pw=0;"
shape[2] = "func=rect;x=45;y=212;width=15;height=47;bc=#6E6E6E;pw=0;"
shape[3] = "func=ell;x=0;y=235;width=66;height=104;bc=LightGray;pc=#0C95BB;pw=16;"
shape[4] = "func=tri;x=45;y=0;x1=22;y1=0;x2=0;y2=213;x3=44;y3=213;bc=#939393;pw=0;"
shape[5] = "func=rect;x=75;y=212;width=14;height=49;bc=#919191;pw=0;"
shape[6] = "func=ell;x=61;y=163;width=13;height=15;bc=#6E6E6E;pw=0;"
shape[7] = "func=ell;x=70;y=236;width=64;height=104;bc=LightGray;pc=#0C95BB;pw=16;"
EndSub

Sub Shapes_Add
' Shapes | add shapes as shapes data
' param shape - array of shapes
' param iMin, iMax - shape indices to add
' param scale - 1 if same scale
' return shWidth, shHeight - total size of shapes
' return shAngle - current angle of shapes
Stack.PushValue("local", i)
Stack.PushValue("local", x)
Stack.PushValue("local", y)
Shapes_CalcWidthAndHeight()
s = scale
For i = iMin To iMax
GraphicsWindow.PenWidth = shape[i]["pw"] * s
If shape[i]["pw"] > 0 Then
GraphicsWindow.PenColor = shape[i]["pc"]
EndIf
If shape[i]["func"] = "rect" Then
GraphicsWindow.BrushColor = shape[i]["bc"]
x = shape[i]["x"]
y = shape[i]["y"]
width = shape[i]["width"]
height = shape[i]["height"]
angle = shape[i]["angle"]
shape[i]["obj"] = Shapes.AddRectangle(width * s, height * s)
Shapes.Move(shape[i]["obj"], shX + x * s, shY + y * s)
Shapes.Rotate(shape[i]["obj"], angle)
ElseIf shape[i]["func"] = "ell" Then
GraphicsWindow.BrushColor = shape[i]["bc"]
x = shape[i]["x"]
y = shape[i]["y"]
width = shape[i]["width"]
height = shape[i]["height"]
angle = shape[i]["angle"]
shape[i]["obj"] = Shapes.AddEllipse(width * s, height * s)
Shapes.Move(shape[i]["obj"], shX + x * s, shY + y * s)
Shapes.Rotate(shape[i]["obj"], angle)
ElseIf shape[i]["func"] = "tri" Then
GraphicsWindow.BrushColor = shape[i]["bc"]
x = shape[i]["x"]
y = shape[i]["y"]
x1 = shape[i]["x1"]
y1 = shape[i]["y1"]
x2 = shape[i]["x2"]
y2 = shape[i]["y2"]
x3 = shape[i]["x3"]
y3 = shape[i]["y3"]
angle = shape[i]["angle"]
shape[i]["obj"] = Shapes.AddTriangle(x1 * s, y1 * s, x2 * s, y2 * s, x3 * s, y3 * s)
Shapes.Move(shape[i]["obj"], shX + x * s, shY + y * s)
Shapes.Rotate(shape[i]["obj"], angle)
ElseIf shape[i]["func"] = "line" Then
x = shape[i]["x"]
y = shape[i]["y"]
x1 = shape[i]["x1"]
y1 = shape[i]["y1"]
x2 = shape[i]["x2"]
y2 = shape[i]["y2"]
shape[i]["obj"] = Shapes.AddLine(x1 * s, y1 * s, x2 * s, y2 * s)
Shapes.Move(shape[i]["obj"], shX + x * s, shY + y * s)
EndIf
EndFor
shAngle = 0
y = Stack.PopValue("local")
x = Stack.PopValue("local")
i = Stack.PopValue("local")
EndSub

Sub Shapes_CalcWidthAndHeight
' Shapes | Calculate total width and height of shapes
' param iMin, iMax - shape indices to add
' return nShapes - number of shapes
' return shWidth, shHeight - total size of shapes
For i = iMin To iMax
If shape[i]["func"] = "tri" Or shape[i]["func"] = "line" Then
xmin = shape[i]["x1"]
xmax = shape[i]["x1"]
ymin = shape[i]["y1"]
ymax = shape[i]["y1"]
If shape[i]["x2"] < xmin Then
xmin = shape[i]["x2"]
EndIf
If xmax < shape[i]["x2"] Then
xmax = shape[i]["x2"]
EndIf
If shape[i]["y2"] < ymin Then
ymin = shape[i]["y2"]
EndIf
If ymax < shape[i]["y2"] Then
ymax = shape[i]["y2"]
EndIf
If shape[i]["func"] = "tri" Then
If shape[i]["x3"] < xmin Then
xmin = shape[i]["x3"]
EndIf
If xmax < shape[i]["x3"] Then
xmax = shape[i]["x3"]
EndIf
If shape[i]["y3"] < ymin Then
ymin = shape[i]["y3"]
EndIf
If ymax < shape[i]["y3"] Then
ymax = shape[i]["y3"]
EndIf
EndIf
shape[i]["width"] = xmax - xmin
shape[i]["height"] = ymax - ymin
EndIf
If i = 1 Then
shWidth = shape[i]["x"] + shape[i]["width"]
shHeight = shape[i]["y"] + shape[i]["height"]
Else
If shWidth < shape[i]["x"] + shape[i]["width"] Then
shWidth = shape[i]["x"] + shape[i]["width"]
EndIf
If shHeight < shape[i]["y"] + shape[i]["height"] Then
shHeight = shape[i]["y"] + shape[i]["height"]
EndIf
EndIf
EndFor
EndSub

Sub Shapes_CalcRotatePos
' Shapes | Calculate position for rotated shape
' param["x"], param["y"] - position of a shape
' param["width"], param["height"] - size of a shape
' param ["cx"], param["cy"] - center of shapes
' param ["angle"] - rotate angle
' return x, y - rotated position of a shape
_cx = param["x"] + param["width"] / 2
_cy = param["y"] + param["height"] / 2
x = _cx - param["cx"]
y = _cy - param["cy"]
Math_CartesianToPolar()
a = a + param["angle"]
x = r * Math.Cos(a * Math.Pi / 180)
y = r * Math.Sin(a * Math.Pi / 180)
_cx = x + param["cx"]
_cy = y + param["cy"]
x = _cx - param["width"] / 2
y = _cy - param["height"] / 2
EndSub

Sub Shapes_Move
' Shapes | Move shapes
' param shape - array of shapes
' param scale
' param x, y - position to move
' return shX, shY - new position of shapes
Stack.PushValue("local", i)
Stack.PushValue("local", x)
Stack.PushValue("local", y)
shX = x
shY = y
For i = 1 To nShapes
_x = shape[i]["x"]
_y = shape[i]["y"]
Shapes.Move(shape[i]["obj"], shX + _x * s, shY + _y * s)
EndFor
y = Stack.PopValue("local")
x = Stack.PopValue("local")
i = Stack.PopValue("local")
EndSub

Sub Shapes_Remove
' Shapes | Remove shapes
' param iMin, iMax - shapes indices to remove
' param shape - array of shapes
Stack.PushValue("local", i)
For i = iMin To iMax
Shapes.Remove(shape[i]["obj"])
EndFor
i = Stack.PopValue("local")
EndSub

Sub Shapes_Rotate
' Shapes | Rotate shapes
' param shape - array of shapes
' param scale - to zoom
' param angle - to rotate
Stack.PushValue("local", i)
Stack.PushValue("local", x)
Stack.PushValue("local", y)
s = scale
param["angle"] = angle
param["cx"] = shWidth / 2
param["cy"] = shHeight / 2
For i = 1 To nShapes
param["x"] = shape[i]["x"]
param["y"] = shape[i]["y"]
param["width"] = shape[i]["width"]
param["height"] = shape[i]["height"]
Shapes_CalcRotatePos()
Shapes.Move(shape[i]["obj"], shX + x * s, shY + y * s)
Shapes.Rotate(shape[i]["obj"], angle)
EndFor
y = Stack.PopValue("local")
x = Stack.PopValue("local")
i = Stack.PopValue("local")
EndSub

Sub Slider_Add
' Slider | Add slider as shapes and property
' param width
' param caption
' param min, max
' param left, top
' return slider[] - property of slider
' return iSlider - added slider index
numSlider = numSlider + 1
iSlider = numSlider
' add shapes for slider
GraphicsWindow.BrushColor = CAPTIONCOLOR
len = Text.GetLength(caption)
slider[iSlider]["oCaption"] = Shapes.AddText(caption)
Shapes.Move(slider[iSlider]["oCaption"], left - (len * 5 + 10), top + 1)
level = Math.Floor((min + max) / 2)
slider[iSlider]["level"] = level ' property
slider[iSlider]["min"] = min
slider[iSlider]["max"] = max
GraphicsWindow.PenColor = BORDERCOLOR
mag = (level - min) / (max - min)
GraphicsWindow.BrushColor = SLITCOLOR
slider[iSlider]["oSlit"] = Shapes.AddRectangle(width, 10)
GraphicsWindow.PenColor = BORDERCOLOR
GraphicsWindow.BrushColor = BOXCOLOR
slider[iSlider]["oBox"] = Shapes.AddRectangle(10, 18)
GraphicsWindow.BrushColor = CAPTIONCOLOR
slider[iSlider]["oLevel"] = Shapes.AddText(level)
slider[iSlider]["x0"] = left
slider[iSlider]["x1"] = left + width
slider[iSlider]["y0"] = top
Shapes.Move(slider[iSlider]["oLevel"], left + width + 5, top)
' move and zoom shapes for slider
Shapes.Move(slider[iSlider]["oSlit"], left, top + 4)
Slider_SetLevel()
EndSub

Sub Slider_CallBack
' Slider | Call back
' param iSlider - changed slider
CS_AdjustSlider()
CS_GetColorFromSlider()
CS_ShowNewColor() ' show new color name
CS_DrawColorRect() ' draw new color rectangle
EndSub

Sub Slider_GetLevel
' Slider | Get latest level of slider
' param iSlider
' return level
level = slider[iSlider]["level"]
EndSub

Sub Slider_GetMouseLevel
' Slider | Get mouse level of slider
' param iSlider
' return level
x0 = slider[iSlider]["x0"]
x1 = slider[iSlider]["x1"]
max = slider[iSlider]["max"]
min = slider[iSlider]["min"]
level = min + Math.Floor((max - min) * (mxM - x0) / (x1 - x0))
EndSub

Sub Slider_WaitToRelease
' Slider | Get released point for slider moving
' param iSlider
param = "down=False;move=True;up=True;" ' for slider moving / wait to release
Mouse_SetHandler()
While released = "False"
If moved Then
param = "move=False;" ' while slider moving
Mouse_SetHandler()
x0_ = slider[iSlider]["x0"]
x1_ = slider[iSlider]["x1"]
If mxM < x0_ Then
mxM = x0_
EndIf
If x1_ < mxM Then
mxM = x1_
EndIf
Slider_GetMouseLevel() ' get mouse level of slider
Slider_SetLevel() ' set slider level and move slider box
Slider_CallBack()
param = "move=True;" ' for next slider moving
Mouse_SetHandler()
Else
Program.Delay(100)
EndIf
EndWhile
param = "move=False;up=False;" ' mouse released
Mouse_SetHandler()
EndSub

Sub Slider_Remove
' Slider | Remove a slider
' param iSlider
Shapes.Remove(slider[iSlider]["oCaption"])
Shapes.Remove(slider[iSlider]["oSlit"])
Shapes.Remove(slider[iSlider]["oBox"])
Shapes.Remove(slider[iSlider]["oLevel"])
EndSub

Sub Slider_SetLevel
' Slider | Set slider level and move slider box
' param iSlider
' param level
Stack.PushValue("local", width)
x0 = slider[iSlider]["x0"]
x1 = slider[iSlider]["x1"]
y0 = slider[iSlider]["y0"]
width = x1 - x0
slider[iSlider]["level"] = level
Shapes.SetText(slider[iSlider]["oLevel"], level)
' move bar
min = slider[iSlider]["min"]
max = slider[iSlider]["max"]
mag = (level - min) / (max - min)
' move box
Shapes.Move(slider[iSlider]["oBox"], x0 + Math.Floor(width * mag) - 5, y0)
slider[iSlider]["x2"] = x0 + Math.Floor(width * mag) - 5
slider[iSlider]["x3"] = x0 + Math.Floor(width * mag) - 5 + 10
slider[iSlider]["y2"] = y0
slider[iSlider]["y3"] = y0 + 18
width = Stack.PopValue("local")
EndSub

Sub Mouse_SetHandler
' Mouse | Common event handler setting
' param["down"] - "True" if set, "False" if reset mouse event handler
' param["move"] - "True" if set, "False" if reset mouse event handler
' param["up"] - - "True" if set, "False" if reset mouse event handler
' return clicked - "False" if set MouseDown
' return moved - "False" if set MouseMove
' return released - "False" if set MouseUp
' return dmu - which handlers are set for debug
If param["down"] Then
clicked = "False"
GraphicsWindow.MouseDown = Mouse_OnDown
handler["down"] = "D"
ElseIf param["down"] = "False" Then
GraphicsWindow.MouseDown = Mouse_DoNothing
handler["down"] = ""
EndIf
If param["move"] Then
moved = "False"
GraphicsWindow.MouseMove = Mouse_OnMove
handler["move"] = "M"
ElseIf param["move"] = "False" Then
GraphicsWindow.MouseMove = Mouse_DoNothing
handler["move"] = ""
EndIf
If param["up"] Then
released = "False"
GraphicsWindow.MouseUp = Mouse_OnUp
handler["up"] = "U"
ElseIf param["up"] = "False" Then
GraphicsWindow.MouseUp = Mouse_DoNothing
handler["up"] = ""
EndIf
dmu = handler["down"] + handler["move"] + handler["up"]
If debug Then
GraphicsWindow.Title = title + " set " + dmu
EndIf
EndSub

Sub Mouse_OnDown
' Mouse | Common event handler on mouse down
' return mxD, myD - position on mouse down
mxD = GraphicsWindow.MouseX
myD = GraphicsWindow.MouseY
clicked = "True"
If debug Then
GraphicsWindow.Title = title + " clicked " + mxD + "," + myD + " " + dmu
EndIf
EndSub

Sub Mouse_DoNothing
' Mouse | Common event handler to do nothing
EndSub

Sub Mouse_OnMove
' Mouse | Common event handler on mouse move
' return mxM, myM - position on mouse move
mxM = GraphicsWindow.MouseX
myM = GraphicsWindow.MouseY
moved = "True"
If debug Then
GraphicsWindow.Title = title + " moved " + mxM + "," + myM + " " + dmu
EndIf
EndSub

Sub Mouse_OnUp
' Mouse | Common event handler on mouse up
' return mxU, myU - position on mouse up
mxU = GraphicsWindow.MouseX
myU = GraphicsWindow.MouseY
released = "True"
If debug Then
GraphicsWindow.Title = title + " released " + mxU + "," + myU + " " + dmu
EndIf
EndSub