diff --git a/comp/src/gb.web.gui/.src/Mouse.class b/comp/src/gb.web.gui/.src/Mouse.class
new file mode 100644
index 000000000..c2bb32131
--- /dev/null
+++ b/comp/src/gb.web.gui/.src/Mouse.class
@@ -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
diff --git a/comp/src/gb.web.gui/.src/Paint/PaintDriver_WebDrawingArea.class b/comp/src/gb.web.gui/.src/Paint/PaintDriver_WebDrawingArea.class
index c742d675a..b68138f0b 100644
--- a/comp/src/gb.web.gui/.src/Paint/PaintDriver_WebDrawingArea.class
+++ b/comp/src/gb.web.gui/.src/Paint/PaintDriver_WebDrawingArea.class
@@ -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
diff --git a/comp/src/gb.web.gui/.src/Test/FTestDrawingArea.class b/comp/src/gb.web.gui/.src/Test/FTestDrawingArea.class
index 679289119..579fd1376 100644
--- a/comp/src/gb.web.gui/.src/Test/FTestDrawingArea.class
+++ b/comp/src/gb.web.gui/.src/Test/FTestDrawingArea.class
@@ -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
diff --git a/comp/src/gb.web.gui/.src/Test/Webform1.webform b/comp/src/gb.web.gui/.src/Test/Webform1.webform
index ef5049d12..a07b4b000 100644
--- a/comp/src/gb.web.gui/.src/Test/Webform1.webform
+++ b/comp/src/gb.web.gui/.src/Test/Webform1.webform
@@ -121,6 +121,7 @@
}
{ WebHBox3 WebHBox
#MoveScaled(1,8,133.75,6)
+ Font = "serif,bold"
Spacing = True
{ WebComboBox1 WebComboBox
#MoveScaled(1,1,30,4)
diff --git a/comp/src/gb.web.gui/.src/WebControl.class b/comp/src/gb.web.gui/.src/WebControl.class
index e756a9bbf..f150fda72 100644
--- a/comp/src/gb.web.gui/.src/WebControl.class
+++ b/comp/src/gb.web.gui/.src/WebControl.class
@@ -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
diff --git a/comp/src/gb.web.gui/.src/WebDrawingArea.class b/comp/src/gb.web.gui/.src/WebDrawingArea.class
index 472e21dfd..84a429e57 100644
--- a/comp/src/gb.web.gui/.src/WebDrawingArea.class
+++ b/comp/src/gb.web.gui/.src/WebDrawingArea.class
@@ -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 "";
- WebForm._AddJavascript("gw.paint.init(" & JS(Me.Name) & ");")
+ Dim bMouseDown As Boolean
+ Dim bMouseMove As Boolean
+ Dim bMouseUp As Boolean
+
+ Print "";
+ 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
+
diff --git a/comp/src/gb.web.gui/.src/WebForm.class b/comp/src/gb.web.gui/.src/WebForm.class
index 7cbc9a2db..f4fc71b09 100644
--- a/comp/src/gb.web.gui/.src/WebForm.class
+++ b/comp/src/gb.web.gui/.src/WebForm.class
@@ -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])
diff --git a/comp/src/gb.web.gui/lib.js b/comp/src/gb.web.gui/lib.js
index d96ed17e5..ab8725941 100644
--- a/comp/src/gb.web.gui/lib.js
+++ b/comp/src/gb.web.gui/lib.js
@@ -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;
-
-
-