Add 'MouseDown', 'MouseUp', and 'MouseMove' events in DrawingArea. Add 'Enter' and 'Leave' events in WebControl.

[GB.WEB.GUI]
* NEW: WebControl: Implement 'Enter' and 'Leave' event.
* NEW: DrawingArea: Implement 'MouseDown', 'MouseUp', and 'MouseMove' events. At the moment 'MouseMove' are raised only when a button is pressed.
* BUG: Paint: Do not crash if no brush has been defined. Let the underlying driver use the default brush instead.
This commit is contained in:
Benoît Minisini 2022-08-11 18:34:26 +02:00
parent 4819adfa52
commit 441fd57ceb
8 changed files with 298 additions and 30 deletions

View file

@ -0,0 +1,98 @@
' Gambas class file
Export
Static Property Read X As Integer
Static Property Read Y As Integer
Static Property Read ScreenX As Integer
Static Property Read ScreenY As Integer
Static Property Read Button As Integer
Static Property Read Left As Boolean
Static Property Read Middle As Boolean
Static Property Read Right As Boolean
Static Property Read StartX As Integer
Static Property Read StartY As Integer
Static Private $cEvent As Collection
Static Private $bMouseDown As Boolean
Static Private $iStartX As Integer
Static Private $iStartY As Integer
Static Public Sub _Define(sType As String, cEvent As Collection)
$cEvent = cEvent
If sType = "MouseDown" Then
$bMouseDown = True
$iStartX = cEvent["x"]
$iStartY = cEvent["y"]
Endif
End
Static Private Function X_Read() As Integer
Return $cEvent["x"]
End
Static Private Function Y_Read() As Integer
Return $cEvent["y"]
End
Static Private Function Button_Read() As Integer
Dim I As Integer
Dim iButtons As Integer
If $cEvent["type"] = "MouseDown" Then Return $cEvent["button"]
iButtons = $cEvent["buttons"]
For I = 0 To 2
If BTst(iButtons, I) Then Return I
Next
End
Static Private Function ScreenX_Read() As Integer
Return $cEvent["sx"]
End
Static Private Function ScreenY_Read() As Integer
Return $cEvent["sy"]
End
Static Private Function Left_Read() As Boolean
Return $cEvent["buttons"] And 1
End
Static Private Function Middle_Read() As Boolean
Return $cEvent["buttons"] And 2
End
Static Private Function Right_Read() As Boolean
Return $cEvent["buttons"] And 4
End
Static Private Function StartX_Read() As Integer
Return $iStartX
End
Static Private Function StartY_Read() As Integer
Return $iStartY
End

View file

@ -9,6 +9,7 @@ Public Sub Begin()
Dim hDrawingArea As WebDrawingArea
WebForm._AddJavascript("{ var $_c = $_(" & JS(Me.Device.Name & ":canvas") & ").getContext('2d');")
WebForm._AddJavascript("$_c.save();")
WebForm._AddJavascript("$_c.beginPath();")
hDrawingArea = Me.Device
@ -20,6 +21,7 @@ End
Public Sub End()
WebForm._AddJavascript("$_c.restore();")
WebForm._AddJavascript($aEnd.Join(""))
WebForm._AddJavascript("}")
End
@ -48,6 +50,7 @@ Private Sub HandleStyle(hStyle As Variant, sProperty As String) As Boolean
Dim hGradient As Gradient
If IsNull(hStyle) Then hStyle = Me.Brush
If IsNull(hStyle) Then Return ' default brush
If TypeOf(hStyle) = gb.Integer Then

View file

@ -2,6 +2,10 @@
Export
Private $X As Integer
Private $Y As Integer
Private $iHue As Integer
Public Sub WebDrawingArea1_Draw()
Paint.LineWidth = 8
@ -36,14 +40,15 @@ Public Sub WebDrawingArea1_Draw()
Paint.DrawImage("favicon.png", 150, 10, 200, 200, 0.5, Rect(10, 10, 100, 100))
Paint.Rectangle(5.5, 5.5, Paint.W - 12, Paint.H - 12)
Paint.LineWidth = 1
Paint.LineWidth = 2
Paint.LineDash = [8, 4]
Paint.Stroke(Color.Red)
End
Static Public Sub _init()
WebForm.Debug = True
'WebForm.Debug = True
End
@ -52,3 +57,36 @@ Public Sub WebButton1_Click()
WebDrawingArea1.Refresh
End
Public Sub WebDrawingArea1_MouseDown()
WebForm.Print("MouseDown: " & CStr(Mouse.X) & "," & CStr(Mouse.Y))
$X = Mouse.X
$Y = Mouse.Y
End
Public Sub WebDrawingArea1_MouseMove()
'WebForm.Print("MouseMove: " & CStr(Mouse.X) & "," & CStr(Mouse.Y))
Paint.Begin(Last)
Paint.LineWidth = 4
Paint.MoveTo($X, $Y)
Paint.LineTo(Mouse.X, Mouse.Y)
$iHue = ($iHue + 2) Mod 360
Paint.Stroke(Subst("hsl(&1,75%,50%)", $iHue))
Paint.End
$X = Mouse.X
$Y = Mouse.Y
End
Public Sub WebDrawingArea1_MouseUp()
WebForm.Print("MouseUp: " & CStr(Mouse.X) & "," & CStr(Mouse.Y))
Paint.Begin(Last)
Paint.Arc($X, $Y, 8)
Paint.Fill(Color.SetAlpha(Color.Black, 192))
Paint.End
End

View file

@ -121,6 +121,7 @@
}
{ WebHBox3 WebHBox
#MoveScaled(1,8,133.75,6)
Font = "serif,bold"
Spacing = True
{ WebComboBox1 WebComboBox
#MoveScaled(1,1,30,4)

View file

@ -18,6 +18,12 @@ Event Render
'' This event is raised when a keyboard key is pressed while the control has the focus.
Event KeyPress
'' This event is raised when the mouse cursor enters the control.
Event Enter
'' This event is raised when the mouse cursor leaves the control.
Event Leave
'' Return the server control identifier.
Property Read Id As Integer
@ -334,7 +340,6 @@ Private Sub GetCellName() As String
End
Public Sub _GetClassId(Optional sClass As String) As String
Dim sResult As String
@ -347,6 +352,9 @@ Public Sub _GetClassId(Optional sClass As String) As String
sResult = " class=\"" & Html(sClass) & "\" id=\"" & Html(GetCellName()) & "\""
If $sTooltip Then sResult &= " title=\"" & Html($sTooltip) & "\""
If Object.CanRaise(Me, "Enter") Then sResult &= _GetEventJS("onmouseover", "Enter")
If Object.CanRaise(Me, "Leave") Then sResult &= _GetEventJS("onmouseout", "Leave")
Return sResult
End
@ -679,7 +687,7 @@ Catch
End
Public Sub _GetEventJS(sProp As String, sEvent As String, Optional sArg As String) As String
Public Sub _GetEventJS(sProp As String, sEvent As String, Optional sArg As String, sMore As String) As String
Dim sStr As String
@ -696,7 +704,7 @@ Public Sub _GetEventJS(sProp As String, sEvent As String, Optional sArg As Strin
Endif
sStr &= "," & JS(sEvent)
If sArg Then sStr &= "," & sArg
sStr &= ");"
sStr &= ");" & sMore
sStr &= "\""
If sProp = "onclick" Then sStr &= " onmousedown=\"event.stopPropagation();\""
@ -1275,3 +1283,10 @@ Static Public Sub _SetCurrentCell(Optional hCtrl As WebControl, sCell As String)
$sCellId = sCell
End
Public Sub _RaiseMouseEvent(sEvent As String, cEvent As Variant)
Mouse._Define(sEvent, cEvent)
Object.Raise(Me, sEvent)
End

View file

@ -10,10 +10,19 @@ Public Const _DefaultEvent As String = "Draw"
Public _Width As Integer
Public _Height As Integer
'' This event is raised when the DrawingArea contents must be drawn.
Event Draw
' Event MouseDown
' Event MouseMove
' Event MouseUp
'' This event is raised when a mouse button is pressed while the mouse cursor is inside the control.
Event MouseDown
'' This event is raised when a mouse button is released.
''
'' It is always raised for the control that triggered the corresponding [../.mouseup] event.
Event MouseUp
'' This event is raised when the mouse cursor moves.
Event MouseMove
Public Sub _new()
@ -24,8 +33,23 @@ End
Public Sub _Render()
Print "<canvas id=\""; Html(Me.Name & ":canvas"); "\"></canvas>";
WebForm._AddJavascript("gw.paint.init(" & JS(Me.Name) & ");")
Dim bMouseDown As Boolean
Dim bMouseMove As Boolean
Dim bMouseUp As Boolean
Print "<canvas id=\""; Html(Me.Name & ":canvas"); "\"";
bMouseDown = Object.CanRaise(Me, "MouseDown")
bMouseMove = Object.CanRaise(Me, "MouseMove")
bMouseUp = Object.CanRaise(Me, "MouseUp")
If bMouseDown Or If bMouseMove Or If bMouseUp Then
' TODO: Replace Me.Name by GetCellName()
Print " onmousedown=\"gw.drawingarea.onMouseDown(event,"; JS(Me.Name); ","; JS(bMouseDown); ","; JS(bMouseMove); ","; JS(bMouseUp); ");\"";
Endif
Print "></canvas>";
WebForm._AddJavascript("gw.drawingarea.init(" & JS(Me.Name) & ");")
End
@ -35,8 +59,19 @@ Public Sub _UpdateProperty(sProp As String, vValue As Variant)
_Width = vValue[0]
_Height = vValue[1]
Paint.Begin(Me)
WebForm._AddJavascript("$_c.clearRect(0,0," & CStr(_Width) & "," & CStr(_Height) & ");")
Raise Draw
Paint.End
Endif
End
Public Sub Refresh()
Paint.Begin(Me)
WebForm._AddJavascript("$_c.clearRect(0,0," & CStr(_Width) & "," & CStr(_Height) & ");")
Raise Draw
Paint.End
End

View file

@ -1003,6 +1003,10 @@ Public Sub _HandleMessage()
hForm._RaiseKeyPress(aCmd[2])
Endif
Case "mouse"
GoSub GET_TARGET
If hCtrl Then hCtrl._RaiseMouseEvent(aCmd[2], aCmd[3])
Case "finish"
Upload.Finish(aCmd[1])

View file

@ -70,6 +70,7 @@ gw = {
lock: 0,
needKeyPress: {},
drawingContext: [],
images: {},
log: function(msg)
{
@ -208,18 +209,15 @@ gw = {
},
wait: function(lock) {
var elt;
if (lock)
{
if (gw.lock == 0)
{
elt = $_('gw-lock');
elt.style.zIndex = 1000;
elt.style.display = 'block';
gw.lock_id = setTimeout(function() {
$_('gw-lock').style.opacity = '1';
var elt = $_('gw-lock');
elt.style.zIndex = 1000;
elt.style.display = 'block';
elt.style.opacity = '1';
gw.lock_id = undefined;
}, 500);
}
@ -236,7 +234,7 @@ gw = {
clearTimeout(gw.lock_id);
gw.lock_id = undefined;
}
elt = $_('gw-lock');
var elt = $_('gw-lock');
elt.style.display = 'none';
elt.style.opacity = '0';
}
@ -1782,7 +1780,7 @@ gw = {
}
},
paint:
drawingarea:
{
init: function(id)
{
@ -1791,24 +1789,71 @@ gw = {
gw.resizeObserver = new ResizeObserver(function(entries)
{
for (let elt of entries)
gw.paint.update(elt.target.id);
gw.drawingarea.update(elt.target.id);
});
}
gw.resizeObserver.observe($_(id));
gw.paint.update(id);
gw.drawingarea.update(id);
},
update: function(id)
{
var w = $_(id + ':canvas').offsetWidth;
var h = $_(id + ':canvas').offsetHeight;
$_(id + ':canvas').width = w;
$_(id + ':canvas').height = h;
console.log('gw.paint.update: ' + w + ',' + h);
if (w != $_(id + ':canvas').width || h != $_(id + ':canvas').height)
{
$_(id + ':canvas').width = w;
$_(id + ':canvas').height = h;
}
gw.update(id, '#', [w, h]);
},
onMouseDown: function(event, id, down, move, up)
{
window.addEventListener('mouseup', gw.drawingarea.onMouseUp);
if (move)
window.addEventListener('mousemove', gw.drawingarea.onMouseMove);
gw.grab = {
'id': id,
'move': move,
'up': up,
'dx': event.screenX - event.offsetX,
'dy': event.screenY - event.offsetY,
'sx': event.offsetX,
'sy': event.offsetY
};
if (down)
gw.sendMouseEvent(event, 'MouseDown');
},
onMouseUp: function(event)
{
if (gw.grab.up) gw.sendMouseEvent(event, 'MouseUp');
if (gw.grab.move) window.removeEventListener('mousemove', gw.drawingarea.onMouseMove);
window.removeEventListener('mouseup', gw.drawingarea.onMouseUp);
gw.grab = undefined;
},
sendMouseMoveEvent: function()
{
gw.sendMouseEvent(gw.mouseMove, 'MouseMove', function() { gw.mouseMove = undefined; })
},
onMouseMove: function(event)
{
var send = gw.mouseMove == undefined;
gw.mouseMove = event;
if (send)
gw.drawingarea.sendMouseMoveEvent();
}
},
paint:
{
makeGradient: function(ctx, mo, coords, stops)
{
var grad, i, st;
@ -1832,9 +1877,18 @@ gw = {
loadImage: function(url, func)
{
var img = new Image();
img.onload = function() { func(img); }
img.src = url;
var img = gw.images[url];
if (img)
{
func(img);
}
else
{
img = new Image();
img.onload = function() { func(img); gw.images[url] = img; }
img.src = url;
}
}
},
@ -1890,6 +1944,29 @@ gw = {
null);
},
sendMouseEvent: function(event, type, func)
{
gw.send(['mouse', gw.grab.id, type,
{
'x': event.screenX - gw.grab.dx,
'y': event.screenY - gw.grab.dy,
'sx': event.screenX,
'sy': event.screenY,
'button': event.button,
'buttons': event.buttons,
'altKey': event.altKey,
'ctrlKey': event.ctrlKey,
'metaKey': event.meta,
'shiftKey': event.shiftKey
}],
func);
},
raise: function(id, event, args, no_wait)
{
gw.send(['raise', id, event, args, no_wait]);
},
onKeyDown: function(event)
{
var elt;
@ -1944,6 +2021,3 @@ gw = {
}
document.onkeydown = gw.onKeyDown;