LiveCode
  • Why LiveCode?
  • Customers
  • Resources
  • Education
  • Consulting
  • Pricing
  • Blog
  • Login
  • Try LiveCode
Back to
  • slides
  • tutorial
Resources

Adding graph marker mouse events

Topic Progress:
← Back to Lesson

Adding Marker Mouse Messages

In order to develop interactive charts we need some mouse events on line markers.

Users may want to display detailed data when the mouse is over a marker or show an editor when the user clicks on it.

The final modification we will make is to add add mouse events to the markers.

markers

Detecting the mouse marker

The first thing we need to do is detect which marker the mouse is in the general vicinity of.

We will use a fudge factor of 5 to create a rectangle around the mouse position and use that to determine if the calculated marker positions were relatively close to the mouse.

marker3

We use an list instance variable mMouseMarker to store the last known mouse marker X,Y.

The X,Y here is x label, y value for example “wed,889″.

Add instance variables

The first step is to add two list instance variables.

  • mMouseMarker
  • mMouseDownMarker

These list variables are used to store the last known mouse marker and mouse down marker, allowing us to determine if the mouse marker has changed.

Add the variable definitions to the LCB source after the current instance variable declarations.

widget community.livecode.elanorb.modifiedlinegraph
    … module imports
    … widget meta data
    … property definitons
    … current instance variables

    // Mouse Events
    private variable mMouseMarker as List
    private variable mMouseDownMarker as List

    … code continues
end widget

The OnMouseMove handler

The first message we will handle is OnMouseMove.

The  OnMouseMove message is sent when the mouse pointer moves within the widget’s rect.

When the message is received we work out whether the mouse has entered or left a marker and post the relevant message to the widget object.

  • Store the current mouse marker
  • Update the current mouse marker
  • Check if the new mouse marker differs from the stored(previous) mouse marker. If the mouse marker has changed
    • If the stored mouse marker is not empty(there was a previous marker) the mouse has left the stored (previous) marker so send a markerMouseLeave message to the widget object with the stored (previous) marker as a parameter.
    • If the new mouse marker is not empty(a marker was found close to the mouse position) the mouse has entered the area of a new marker so send a markerMouseEnter message to the widget object with the new marker as a parameter.
  • If the mouse has not entered or left a marker no message is sent.

Note: If you need a refresher on handling mouse events have a look back at Lesson 4: Step 4 – Mouse Events.

The OnMouseMove handler

Add the OnMouseMove handler.

  • Declare the handler.
    • public: used externally
    • returns nothing: has no return value
  • Store the current mouse marker.
  • Get the new mouse marker.
  • Check the new marker is not the previous marker.
    • If there was a previous marker  the mouse has left that marker so post markerMouseLeave to the widget object with the previous marker as a parameter.
    • If there is a new marker  the mouse has entered that marker so post markerMouseEnter to the widget object with the previous marker as a parameter
public handler OnMouseMove() returns nothing
    variable tMouseMarker as List
    put mMouseMarker into tMouseMarker
    UpdateMouseMarker()

   if mMouseMarker is not tMouseMarker then
       if tMouseMarker is not [] then
           post "markerMouseLeave" with tMouseMarker
       end if

       if mMouseMarker is not [] then
           post "markerMouseEnter" with mMouseMarker
       end if
   end if

end handler

The UpdateMouseMarker handler

The UpdateMouseMarker handler does most of the work.

  • Checks if the mouse has been clicked with the grid area
  • Iterates across each line on the graph
    • Iterates across each value in the list of values
      • Calculates the x,y position of the corresponding point on the graph
      • Works out the rect around the point using the fudge factor of 5 in each direction.
      • Works out if the mouse location is within that rectangle
        • Updates mMouseMarker
  • When the handler finished mMouseMarker will either contain
    • A reference to a marker, if one was found close enough to the click location
    • Nothing, if there was no marker close enough to the click location.

marker4

Add a constant definition kHitTestFudgeFactor. We add the constant here as only UpdateMouseMarker uses it. If you prefer you can add this definition with the other module level declarations.

Add the UpdateMouseMarker handler.

  • Declare the private handler with no return value.
  • Declare variables
    • tMouseMarker: a list to store the marker, or empty if no maker is found
    • tMouseLoc: a point to store the mouse location.

 

 

 

  • Update tMouseLoc with the mouse position.
  • Check the mouse location is within the grid area.
  • Iterate across each graph line (mData is a list variable, element 1 is the X axis labels, element 2 is the values of line 1 etc)
    • Iterate across each value (element) in the list of values for the current line.
constant kHitTestFudgeFactor is 5

private handler UpdateMouseMarker() returns nothing

variable tMouseMarker as List
variable tMouseLoc as Point

put the mouse position into tMouseLoc

if tMouseLoc is within mGridRect then
    variable tGraphLine as Integer
    repeat with tGraphLine from 2 up to the number of elements in mData
        variable tDataPoints as List
        put element tGraphLine of mData into tDataPoints

        variable tPointIndex as Integer
        repeat with tPointIndex from 1 up to the number of elements in tDataPoints
           … code continues
        end repeat
    end repeat
end if
end handler
  • Check the current value is not nothing.
  • Define variables tPointX and tPointY.
  • Calculate the X coordinate of the current value, tPointX .
    • The left of the grid + (the index of the current point -1) * column width.
  • Calculate the Y coordinate of the current value, tPointY.
    • Define variable tHeightRatio
    • Calculate tHeightRatio as the percentage of the  grid height the current value takes up.
    • tPointY = the bottom of the grid – (the grid height * tHeightRatio).
private handler UpdateMouseMarker() returns nothing   
   … previous code
  repeat with tPointIndex from 1 up to the number of elements in tDataPoints      if tDataPoints[tPointIndex] is not nothing then
          variable tPointX as Real
          variable tPointY as Real
          put the left of mGridRect + ((tPointIndex - 1) * mGridHWidth) into tPointX

          variable tHeightRatio as Real
          put (tDataPoints[tPointIndex] - mYMin) / (mYMax - mYMin) into tHeightRatio
         put the bottom of mGridRect - the height of mGridRect * tHeightRatio into tPointY

         …. code continues
      end if
   end repeat
   … previous code
end handler
  • Define rectangle variable tRect.
  • Calculate the hit area around the point and store it in tRect. The rectangle points are kHitTestFudgeFactor pixels away from the point in each direction.
  • Check if tMouseLoc is within tRect
    • If it is update tMouseMarker with
      • X = the X axis label of the point
      • Y = the value of the point
  • Update mMouseMarker with the value of tMouseMarker.

The instance variable mMouseMarker now contains a references to a mouse maker, if one was found close enough to the click location, or nothing if no maker was close enough to the click location.

private handler UpdateMouseMarker() returns nothing   
   … previous code

    if tDataPoints[tPointIndex] is not nothing then
         … previous code
          variable tRect as Rectangle
         put rectangle [tPointX - kHitTestFudgeFactor,  tPointY  - kHitTestFudgeFactor, tPointX + kHitTestFudgeFactor, tPointY + kHitTestFudgeFactor] into tRect

         if tMouseLoc is within tRect then
             put [mData[1][tPointIndex],  tDataPoints[tPointIndex]] into tMouseMarker
         end if
      end if
   … code continues
   put tMouseMarker into mMouseMarker
end handler

Handling OnMouseDown, OnMouseUp and OnMouseCancel

These handlers are a little more complicated as it is possible for the user to mouse down on one marker and then drag away.

If the user does mouse up away from the mouse down marker we need to send a markerMouseRelease event rather than a markerMouseUp. This is consistent with the mouseUp and mouseRelease messages in LiveCode Script.

In order to do that we need to store the mouse down marker in a separate instance variable to check in  OnMouseUp and OnMouseCancel.

The OnMouseCancel message is sent if the user drags right out of the widget while OnMouseUp  would be sent as long as they are in the widget which is why we need to handle both messages.

The OnMouseDown Handler

Add the OnMouseDown handler.

  • Update the mouse marker.
  • Check that there is a current mouse marker.
    • Update the current mouse down marker (mMouseDownMarker) with the current mouse marker (we will use this when we handle OnMouseUp and OnMouseCancel).
    • Post the makerMouseDown message to the widget object with the mouse down marker, mMouseDownMarker, as a parameter.
public handler OnMouseDown() returns nothing
   UpdateMouseMarker()

   if mMouseMarker is not [] then
      put mMouseMarker into mMouseDownMarker
      post "markerMouseDown" with mMouseDownMarker
   end if

end handler

The OnMouseUp Handler

Add the OnMouseUp handler.

  • Update the mouse marker.
  • Check that there is a current mouse down marker.
    • Check if the current mouse marker(mMouseMarker) is the current mouse down maker (mMouseDownMarker). If so the user did not drag away from the marker after the mouse down so post the makerMouseUp message to the widget object with the mouse down marker, mMouseDownMarker, as a parameter.
    • If the current mouse marker and mouse down marker are different the user dragged away from the marker after the mouse down so  post the makerMouseRelease message to the widget object with the mouse down marker as a parameter.
  • Clear the mouse down marker.
public handler OnMouseUp() returns nothing
   UpdateMouseMarker()

   if mMouseDownMarker is not [] then
      if mMouseMarker is mMouseDownMarker then
         post "markerMouseUp" with mMouseDownMarker
      else
         post "markerMouseRelease" with mMouseDownMarker
      end if
   end if

   put [] into mMouseDownMarker

end handler

The OnMouseCancel Handler

This message is sent when something happens which should cause the previous mouse down action to be considered cancelled. For example, moving the mouse outside the widget area.

Add the OnMouseCancel handler.

  • Check that there is a current mouse down marker
    • Post the makerMouseRelease message to the widget object with the mouse down marker, mMouseDownMarker, as a parameter.
    • Clear the mouse down marker.
public handler OnMouseCancel() returns nothing

   if mMouseDownMarker is not [] then
      post "markerMouseRelease" with mMouseDownMarker
      put [] into mMouseDownMarker
   end if
end handler

Document the marker mouse messages

Don’t forget to add in-line documentation to your LiveCode Builder Code.

For a refresher on adding documentation look back to Lesson4: Step 7 – Documenting the Widget.

Test and Install the Widget

We will test the widget and, if we are happy, install it.

  • Open the Extension Builder from the Tools Menu.
  • Load the LCB file.
  • Click Test and test out all the new properties and messages of the widget. Try adding a markerMouseUp handler to the graph.
on markerMouseUp pMarker
   answer pMarker
end markerMouseUp
  • If you are happy with it click Install.
  • Set the icons, available from the Resources for this lesson. This will differentiate it from the original Line Graph widget in the Tools Palette.
  • Check the documentation shows in the Dictionary.

markers2

← Previous Topic

← Previous Topic Next Topic →
  •  
  •  
  • (0)
  •  

Expand All | Collapse All
Lessons Status
1 - Hello World Library
  • Introduction
  • Installing a Text Editor
  • Creating an LCB library
  • LCB library definition
  • LCB handler definitions
  • Compiling and testing a library in LiveCode
  • LCB metadata
  • Installing an LCB Library
  • Packaging and sharing an LCB library
  • Including an LCB library in a standalone
  • Conclusion
2 - Extended Hello World Library
  • Introduction
  • Explicit Types
  • LCB Lists and Arrays
  • Type Conversion between LCB and LiveCode Script
  • Using Explicit Typing in the Library
  • Passing Parameters to the Library
  • Using Lists in the Library
  • Documenting the Library
  • Browsing the Documentation
  • Conclusion
3 - Rotated Text Widget
  • Introduction
  • Defining a Widget
  • LCB Module Level Variables
  • Widget Properties
  • Widget Handlers
  • LCB Canvas Operations
  • Compiling and Testing the Widget
  • Installing the Widget and adding it to a Stack
  • Including the Widget in a Standalone
  • Conclusion
4 - Extended Rotated Text Widget
  • Introduction
  • Integrating Properties
  • Accessing LiveCode Control Properties
  • Handling Mouse Events
  • Saving and Loading Widgets
  • Read Only Properties
  • Documenting the Widget
  • Conclusion
5 - Pie Chart Widget
  • Introduction
  • Planning the Widget
  • Widget Properties
  • The OnCreate Handler
  • The OnPaint Handler
  • Responding to Mouse Events
  • Saving and Loading the Widget
  • Installing and Including the Widget in a Standalone
  • Documenting the Widget
  • Conclusion
6 - Modifying the Line Graph Widget
  • Introduction
  • Duplicating the Line Graph Widget
  • Additional Color Properties
  • Filling the area below the line
  • Adding graph marker mouse events
  • Conclusion
7 - Additional Resources
  • Extending LiveCode Guide
  • LiveCode Builder Language Reference
  • LiveCode Builder Style Guide
  • LiveCode Documentation Format
 

LCB Source

LCB Source

Icons

Icons
 

Login

LiveCode

  • Why LiveCode?
  • Pricing
  • Customer Stories
  • Extensions
  • LiveCode in Education
  • LiveCode in Business

Looking for LiveCode FileMaker?

LiveCode for FM

Resources

  • Docs
  • API (Language Dictionary)
  • Lessons
  • Sample Stacks
  • Forums
  • Stackoverflow
  • User Groups
  • Support
  • Directory
  • LiveCode Services

About

  • About
  • Meet The Team
  • Careers at LiveCode
  • Contact us

Recent Posts

  • LiveCode Classic 10.0.1 Stable and 10.0.2-rc-1 Released
  • Create Progress – the Three D’s
  • LiveCode Create: Closing out the year with big steps forward
  • Create dp-5: Unified Engines and Shared Extensions
  • 3 Great New LiveCode Releases
Sitemap
Terms Privacy Policy EULA
Brought to you by LiveCode Ltd, Registered in Scotland, No. SC200728
We use cookies to ensure that we give you the best experience on our website. If you continue to use this site we will assume that you are happy with it.Ok