Hi Garry,
thanks a lot for going through everything so quickly. @If TargetDesktop / TargetWeb work perfectly. ChartView (one of the next releases) will use them, and one file serves desktop and web without any manual constant.
Three follow-ups, each with a minimal repro:
- Keyboard in web projects (objo 26.10.2)
In a web project, with a plain Canvas Canvas1 on Page1:
Sub Canvas1_MouseDown(x As Double, y As Double, button As MouseButton)
If Keyboard.ShiftDown Then Return
End Sub
objo check reports:
Error: Page1:43:4: Undefined identifier 'Keyboard'.
The same line compiles in a desktop project.
- Scaled pictures: a clip followed by text disturbs all later drawing
With a scale factor above 1, everything drawn after the first clipped block and text comes out enlarged and shifted, and the orange bar at the end is missing. At scale 1 the same code is correct: four gradient squares, each labelled "12", and an orange bar below.
Var p As New Picture(300, 120, 2) # scale factor 2; with 1 it is correct
Var g As Graphics = p.Graphics
g.DrawingColour = Colour.White
g.FillRectangle(0, 0, 300, 120)
For k As Integer = 0 To 3
Var x As Double = 10 + k * 70
g.SaveState()
g.Clip(x, 10, 50, 50) # ClipToPath behaves the same
g.FillLinearGradient(x, 10, 50, 50, Colour.RGB(120, 160, 210), Colour.RGB(64, 105, 156), 90)
g.RestoreState()
g.DrawingColour = Colour.Black
g.FontSize = 11
g.DrawText("12", x + 18, 62)
Next k
g.DrawingColour = Colour.RGB(230, 120, 0)
g.FillRectangle(10, 80, 280, 30)
p.Save(SpecialFolder.Desktop.Child("scale2.png").Path)
- Scaled pictures: a shadow followed by a clip
The same effect occurs without any text, when a fill with a shadow is followed by a clip:
Var p As New Picture(300, 120, 2)
Var g As Graphics = p.Graphics
g.DrawingColour = Colour.White
g.FillRectangle(0, 0, 300, 120)
For k As Integer = 0 To 3
Var x As Double = 10 + k * 70
Var path As New GraphicsPath
path.MoveToPoint(x, 60)
path.AddLineToPoint(x, 10)
path.AddLineToPoint(x + 50, 10)
path.AddLineToPoint(x + 50, 60)
path.Close()
g.SaveState()
g.ShadowColour = Colour.RGBA(20, 30, 50, 70)
g.ShadowBlur = 6
g.ShadowOffsetY = 2
g.DrawingColour = Colour.RGB(64, 105, 156)
g.FillPath(path)
g.RestoreState()
g.SaveState()
g.ClipToPath(path)
g.FillLinearGradient(x, 10, 50, 50, Colour.RGB(120, 160, 210), Colour.RGB(64, 105, 156), 90)
g.RestoreState()
Next k
g.DrawingColour = Colour.RGB(230, 120, 0)
g.FillRectangle(10, 80, 280, 30)
p.Save(SpecialFolder.Desktop.Child("scale2-shadow.png").Path)
Shadow alone and clip alone are both fine; only the combination breaks. I haven't seen either effect on screen (Retina Canvas), only in Picture objects with a scale factor. ChartView works around it by drawing at scale 1 into a double-size picture.
- A small question: return values of own events
The docs show events with a return type (Event Validate(input As String) As Boolean), but I found no way for the class that declares the event to read the handler's result:
Class ChartView Inherits Canvas
Event AxisLabelText(axis As String, value As Double, text As String) As String
Private Function AxisText(axis As String, value As Double, text As String) As String
Var own As String = RaiseEvent AxisLabelText(axis, value, text) # "Expected expression after '='"
...
End Function
End Class
Calling the event by name (AxisLabelText(...)) gives "Undefined identifier". For now ChartView uses properties that hold a function (AddressOf or an inline Function(...)), which works nicely. If there's an intended way to get a value back from RaiseEvent, I'd be glad to know. If not, it might be worth a sentence in the events docs.
THX