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

Responding to Mouse Events

Topic Progress:
← Back to Lesson

Responding to user actions

The Rotated Text widget responded to clicks by sending a mouseUp message.

We could do the same with the Pie Chart widget but it would be more useful to tell the user which segment had been clicked on.

To do this we will

  • Work out which sector of the pie chart was clicked on
  • Post a sectorClicked message with a pSectorNumber parameter.

Working out which sector was clicked

To work out with sector was clicked we will use some simple trigonometry.  There are a few pieces of information and steps to find the clicked sector number.

  1. Get the location the user clicked at
  2. Check the click location is within the pie chart (not anywhere else in the widget)
  3. Calculate the horizontal and vertical distances from the origin of the circle to the click point
  4. Use these values to calculate the angle, the value will be between -90° and 90°
  5. Work out which quadrant of the circle was clicked in
  6. Calculate the angle as a value between 0° and 359°
  7. Iterate through each sector checking if the calculated angle is between its start and end angles
  8. Send a sectorClicked message with the clicked sector number as a parameter.

sectors

Using instance variables

There was some information used when drawing the pie chart that we need here.

  • Chart origin
  • Chart radius
  • Start and end angles of each sector

We don’t have access to these values at the moment so we will update the code to use instance variables for these values. The values will be calculated and used in OnCreate and used in OnMouseUp.

Add 3 more instance variable declarations.

  • mChartOrigin: a point
  • mRadius: a number
  • mSectorAngles: a list of lists. Each element being a list of 3 numbers, the start and end angles of the sector.
widget community.livecode.elanorb.piechart
… module imports
… metadata
… existing instance variables

private variable mChartOrigin as Point
private variable mRadius as Number
private variable mSectorAngles as List

… code continues
end widget

Update the points in the OnPaint handler that use these variables.

  • Delete the tRadius declaration.
  • Delete the tChartOrigin declaration.
  • Update the line that sets the radius value to set mRadius
  • Update the line that sets the origin value to set mChartOrigin
  • Update the line that calculates the sector path using tRadius and tChartOrigin and ensure it uses  mRadius and mChartOrigin.
public handler OnPaint()
   … previous code
   variable tRadius as Number
   variable tChartOrigin as Point
   … other variable definitions

   put tDiameter / 2 into tRadius
   put point [the width of tChartRect/2,the height of tChartRect/2] into tChartOrigin
   put tDiameter / 2 into mRadius
   put point [the width of tChartRect/2,the height of tChartRect/2] into mChartOrigin

   repeat for each element tElement in mValues
      … previous code
      put sector path centered at tChartOrigin with radii [tRadius,tRadius] from tStartAngle to (tStartAngle + tAngle) into tPath
      put sector path centered at mChartOrigin with radii [mRadius,mRadius] from tStartAngle to (tStartAngle + tAngle) into tPath
      … code continues
   end repeat
end handler

Next we need to add a line that stores the start and end angles of each sector in  mSectorAngles.

After drawing each sector add a line that pushes the list [tStartAngle,(tStartAngle + tAngle)] onto mSectorAngles.

The order of the elements in the list will correspond to the sector numbers.

public handler OnPaint()
   … previous code
   repeat for each element tElement in mValues
     … previous code
     fill tPath on this canvas
     push [tStartAngle,(tStartAngle + tAngle)] onto mSectorAngles
     add tAngle to tStartAngle
   end repeat
   … code continues
end handler

The OnMouseUp handler

We want the widget to send a message when the Pie Chart is clicked.

To do this we handle the LCB OnMouseUp message and post a message to the widget object.

Start by declaring the OnMouseUp handler and variables.

public handler OnMouseUp()
   variable tClickLoc as Point
   variable tClickAngle as Number
   variable tClickX as Number
   variable tClickY as Number
   variable tOriginX as Number
   variable tOriginY as Number
   variable tDeltaX as Number
   variable tDeltaY as Number
   variable tChartRect as Rectangle
    … code continues
end handler

Checking the click loc

Firstly we want to check the user clicked within the pie chart. If they clicked anywhere else in  the widget no message is sent.

  • Get the click position. This returns a Point. A point is a list of 2 numbers, the x and y coordinates of the point.
  • Get the rectangle of the pie chart
    • Get the path of the circle centered at mChartOrigin with radius mRadius.
    • Get the bounding box of the path. This returns the smallest rectangle that completely encloses a path.
  • Check the click location is within the bounding box of the pie chart.
public handler OnMouseUp()
   … previous code
   put the click position into tClickLoc
   put the bounding box of circle path centered at mChartOrigin with radius mRadius into tChartRect

   if tClickLoc is within tChartRect then
     … code continues
   end if
end handler

Calculating the angle

Next we work out which sector was clicked in. To do this we use some high school trigonometry. If you need a refresher have a look at http://www.bbc.co.uk/education/guides/zq4w7ty/revision.

The first step is to calculate the angle of the click location, relative to the origin of the chart.

To calculate this angle we need to find the horizontal and vertical differences between the click location and the origin.

angle

To calculate the angle we use the arctangent because we know the length of the sides opposite and adjacent to the angle we want to calculate.

  • deltaY = opposite
  • deltaX = adjacent
  • tanΘ = opposite/adjacent
  • The angle is in radians so convert to degrees.
  • Round the angle to get a whole number.
public handler OnMouseUp()
   … previous code
   if tClickLoc is within tChartRect then
      … previous code
     put the arctangent of (tDeltaY/tDeltaX) into tClickAngle
     put tClickAngle * (180/pi) into tClickAngle
     round(tClickAngle)
     … code continues
   end if
end handler

The angle will be a value between -90° and 90°.

To convert the angle to a value between 0° and 259° we need to work out which quadrant of the circle the user clicked. 

Quadrant tDeltaX tDeltaY
Q1 positive positive
Q2 negative positive
Q3 negative negative
Q4 positive negative

 

sectors2

Add the code to convert the angle to a value between 0° and 360°.

  1. The angle is positive so nothing needs to be done.
  2. The angle is negative to adding 180 gives an angle between 91° and 180°.
  3. The angle is positive so adding 180 gives an angle between 181° and 270°.
  4. The angle is negative so adding 360 gives a value between 271° and 259°.
public handler OnMouseUp()
   … previous code
  if tClickLoc is within tChartRect then
    … previous code
      if (tDeltaX >= 0) and (tDeltaY >= 0) then
         -- Q1 - do nothing
      else if (tDeltaX < 0) and (tDeltaY >= 0) then
         -- Q2
         add 180 to tClickAngle
      else if (tDeltaX < 0) and (tDeltaY < 0) then
         -- Q3
         add 180 to tClickAngle
      else if (tDeltaX >= 0) and (tDeltaY < 0) then
         -- Q4
         add 360 to tClickAngle
      end if
      … code continues
  end if
end handler

Finding the sector

Now that we have the angle of the click we need to find the sector it belongs to.

Iterate across each each element of mSectorAngles, remember that each contains the start and end angle of a sector and the elements are in order.

If tClickAngle is between the start and end angle of the sector this is the sector that was clicked in.

Once the correct sector has been identified assign the sector number to tSectorNumber and exit the loop.

public handler OnMouseUp()
   … previous code
   if tClickLoc is within tChartRect then
      … previous code
     variable tSector as List
     variable tSectorNumber as Number
     variable tClickSector as Number

     put 0 into tSectorNumber
     repeat for each element tSector in mSectorAngles
         add 1 to tSectorNumber
         if tClickAngle > element 1 of tSector and tClickAngle < element 2 of tSector then
            put tSectorNumber into tClickSector
            exit repeat
         end if
      end repeat
   … code continues
  end if
end handler

Sending the message

Now the sector number has been found we want to tell the widget to send a message.

To send a message with parameters use the statement

post Message to Object [ with Arguments ]

Arguments is a list of arguments. In this case it is a list with one element but must still be contained in ‘[‘ and ‘]’.

public handler OnMouseUp()
   … previous code
  if tClickLoc is within tChartRect then
     … previous code
     post "sectorClicked" with [tClickSector]
  end if
end handler

Test the widget

To test the widget:

    • Open the Extension Builder from the Tools menu
    • Load ‘pieChart.lcb’
    • Click Test
    • Select the widget
    • Open the Code Editor
    • Add a sectorClicked handler
on sectorClicked pSector
   put pSector
end sectorClicked

pieTest

 

 

← 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
 

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