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; - - -