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:
parent
4819adfa52
commit
441fd57ceb
8 changed files with 298 additions and 30 deletions
98
comp/src/gb.web.gui/.src/Mouse.class
Normal file
98
comp/src/gb.web.gui/.src/Mouse.class
Normal 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
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -121,6 +121,7 @@
|
|||
}
|
||||
{ WebHBox3 WebHBox
|
||||
#MoveScaled(1,8,133.75,6)
|
||||
Font = "serif,bold"
|
||||
Spacing = True
|
||||
{ WebComboBox1 WebComboBox
|
||||
#MoveScaled(1,1,30,4)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue