lua corona - how to disable touch events widget.newScrollView - button

I have a widget.newScrollView component and a widget.newButton in front of it. Unfortunately when i click my button it also calls my ScrollView "tap" handler. How do i stop my ScrollView from getting this event?
Here is some of the code I'm using:
local function handleButtonEvent( event )
if ( "ended" == event.phase ) then
print( "Button was pressed and released" )
end
return true; **I tried this - but it had no effect**
end
added
local button1 = widget.newButton(
{
label = "button",
onEvent = handleButtonEvent,
emboss = false,
shape = "roundedRect",
width = 400,
height = 100,
cornerRadius = 32,
fillColor = { default={1,0,0,1}, over={1,0.1,0.7,1} },
strokeColor = { default={1,0.4,0,1}, over={0.8,0.8,1,1} },
strokeWidth = 4,
fontSize=100;
}
I've got an array (planets) of display.NewImages and my handler - like this:
local planets = {};
planets[1] = display.newImage( "planetHexs/001.png", _topLeft_x, _topLeft_y);
planets[2] = display.newImage( "planetHexs/002.png", _topLeft_x, _topLeft_y + _planet_height2 );
....
local scrollView = widget.newScrollView(
{
top = 0,
left = 0,
width = display.actualContentWidth,
height = display.actualContentHeight,
scrollWidth = 0,
scrollHeight = 0,
backgroundColor = { 0, 0, 0, 0.5},
verticalScrollDisabled=true;
}
for i = 1, #planets do
local k = planets[i];
scrollView:insert( k )
end
function PlanetTapped( num )
print( "You touched the object!"..num );
end
for i = 1, #planets do
local k = planets[i];
k:addEventListener( "tap", function() PlanetTapped(i) end )
end
I get this print log:
Button was pressed and released
You touched the object2

You must return true on your event functions to prevent propagation. This essentially tells Corona that the event was handled correctly and that no more event listeners for that event should be fired. You can read more about event propagation here in the docs.
"tap" and "touch" events are handled with different listeners, so if you wish to stop taps when you touch the button, you will have add a "tap" listener to your button as well, that essentially just returns true to prevent, or block tap events to anything behind it.
button1:addEventListener("tap", function() return true end)
Since the button does not have a tap event, tap events simply go through the button, to any objects behind it which do have a "tap" event.

Related

How to select a single Curve in a Path in Paper.js?

I need to distinctly select a single Curve of a clicked Path, how can I do that?
For example, in this sketch we can select a whole path when clicked on it:
Currently I can detect the curve (not sure if it is the appropriate approach, anyway):
..onMouseDown = (event) ~>
hit = scope.project.hitTest event.point
if hit?item
# select only that specific segment
curves = hit.item.getCurves!
nearest = null
dist = null
for i, curve of curves
_dist = curve.getNearestPoint(event.point).getDistance(event.point)
if _dist < dist or not nearest?
nearest = i
dist = _dist
selected-curve = curves[nearest]
..selected = yes
But whole path is selected anyway:
What I want to achieve is something like this:
There is an easier way to achieve what you want.
You can know if hit was on a curve by checking its location property.
If it is set, you can easily get the curve points and manually draw your selection.
Here is a sketch demonstrating it.
var myline = new Path(new Point(100, 100));
myline.strokeColor = 'red';
myline.strokeWidth = 6;
myline.add(new Point(200, 100));
myline.add(new Point(260, 170));
myline.add(new Point(360, 170));
myline.add(new Point(420, 250));
function onMouseDown(event) {
hit = paper.project.hitTest(event.point);
// check if hit is on curve
if (hit && hit.location) {
// get curve
var curve = hit.location.curve;
// draw selection
var selection = new Group(
new Path.Line({
from: curve.point1,
to: curve.point2,
strokeColor: 'blue',
strokeWidth: 3
}),
new Path.Rectangle({
from: curve.point1 - 5,
to: curve.point1 + 5,
fillColor: 'blue'
}),
new Path.Rectangle({
from: curve.point2 - 5,
to: curve.point2 + 5,
fillColor: 'blue'
})
);
// make it automatically be removed on next down event
selection.removeOnDown();
}
}
Update
As an alternative, to avoid messing up with the exported drawing, you can simply select the line instead of applying it a stroke style.
See this sketch.
var selection = new Path.Line({
from: curve.point1,
to: curve.point2,
selected: true
});
There is no built-in way to do what you'd like AFAIK.
You basically need to walk through the segments, construct a line, and see if the hit is on that particular line. The line cannot be transparent or it's not considered a hit which is why I give it color and width to match the visible line; it's also why it's deleted after the test.
Here's the sketch solution that implements a bit more around this:
function onMouseDown(event){
if (!myline.hitTest(event.point)) {
return
}
c1.remove()
c2.remove()
// there's a hit so this should find it
let p = event.point
let segs = myline.segments
for (let i = 1; i < segs.length; i++) {
let line = new Path.Line(segs[i - 1].point, segs[i].point)
line.strokeWidth = 6
line.strokeColor = 'black'
if (line.hitTest(p)) {
c1 = new Path.Circle(segs[i-1].point, 6)
c2 = new Path.Circle(segs[i].point, 6)
c1.fillColor = 'black'
c2.fillColor = 'black'
line.remove()
return
}
line.remove()
}
throw new Error("could not find hit")
}
Here's what I draw:

Triggering mouse/touch events in Matter.js

How would one go about adding programmatically triggered touch/mouse events in Matter.js? I have a few collision events set up for the engine, but can not trigger a mouseup event that stops the current dragging action. I've tried various combinations of targeting the canvas element, the mouse/mouseConstraint, and the non-static body.
If you, like me, came here trying to figure out how to be able to click on a Matter.js body object, let me give you one way. My goal in my project was to assign some attributes to my rectangle objects and call a function when they were clicked on.
The first thing to do was to distinguish between dragging and clicking, so I wrote(using Jquery):
$("body").on("mousedown", function(e){
mouseX1 = e.pageX;
mouseY1 = e.pageY;
});
$("body").on("mouseup", function(e){
mouseX2 = e.pageX;
mouseY2 = e.pageY;
if((mouseX1 == mouseX2) && (mouseY1 == mouseY2)){
//alert("click!\n" + mouseX2 + " " + mouseY2 +"\n");
var bodiesUnder = Matter.Query.point(books, { x: mouseX2, y: mouseY2 });
//alert("click!\n" + mouseX2 + " " + mouseY2 +"\n");
if (bodiesUnder.length > 0) {
var bodyToClick = bodiesUnder[0];
alert(bodyToClick.title2);
}
}
});
This was accomplished when listening for "mouseup" and asking if ((mouseX1 == mouseX2) && (mouseY1 == mouseY2)).
Second- the juicy part- create a var array to hold the objects, or 'bodies', we are going to dig up under the mouse. Thankfully there's this function:
var bodiesUnder = Matter.Query.point(books, { x: mouseX2, y: mouseY2 });
For the first element in here I entered "books". For you this needs to be the name of an array you've put all your objects, or 'bodies' into. If you don't have them in an array, it's not hard to throw them all in, like so:
var books = [book1, book2, book3];
Once that was all done, I was able to alert(book1.title2) to see what the title of that book (body) is. My bodies were coded as follows:
var book2 = Bodies.rectangle(390, 200, 66, 70, {
render : {
sprite : {
texture: "img/tradingIcon.jpg"
}
},
restitution : 0.3,
title1 : 'Vanessa and Terry',
title2 : 'Trading'
});
Hope that helps! This one had me hung up for a whole day.
It turns out I had incorrectly configured the Matter.Mouse module, and was re-assigning the mouse input that had already been set in MouseConstraint. The following works in regards to my original question:
Matter.mouseConstraint.mouse.mouseup(event);

Knowing button press in corona sdk

In my corona aplication, I've a widget button to move an image. I was able to find the onPress method, but failed to find a method to check whether the button is still pressed. So that user don't have to tap the same button over and over again for moving the image...
Code:
function move( event )
local phase = event.phase
if "began" == phase then
define_robo()
image.x=image.x+2;
end
end
local movebtn = widget.newButton
{
width = 50,
height = 50,
defaultFile = "left.png",
overFile = "left.png",
onPress = move,
}
Any help is appreciable...
If your question is that you would like to know when the user's finger is moved, or when he releases the button, you can add handlers for those events:
"moved" a finger moved on the screen.
"ended" a finger was lifted from the screen.
"began" only handles when he starts touching the screen.
So your move function would be like:
function move( event )
local phase = event.phase
if "began" == phase then
define_robo()
image.x=image.x+2;
elseif "moved" == phase then
-- your moved code
elseif "ended" == phase then
-- your ended code
end
end
-- Updated according to comment:
Use this, replacing nDelay by the delay between each move, and nTimes by the number of times you wanna do the move:
function move( event )
local phase = event.phase
if "began" == phase then
local nDelay = 1000
local nTimes = 3
define_robo()
timer.performWithDelay(nDelay, function() image.x=image.x+2 end, nTimes )
end
end
Try this:
local image = display.newRect(100,100,50,50) -- Your image
local timer_1 -- timer
local function move()
print("move...")
image.x=image.x+2;
timer_1 = timer.performWithDelay(10,move,1) -- you can set the time as per your need
end
local function stopMove()
print("stopMove...")
if(timer_1)then timer.cancel(timer_1) end
end
local movebtn = widget.newButton {
width = 50,
height = 50,
defaultFile = "obj1.png",
overFile = "obj1.png",
onPress = move, -- This will get called when you 'press' the button
onRelease = stopMove, -- This will get called when you 'release' the button
}
Keep coding................ :)

How can I remove onEvent from button widget in Corona?

I am trying to remove onEvent listener from button widget. I tried to assign nil to onEvent attribute but it didn't work and lastly I tried this:
buttonWidget : removeEventListener("touch", buttonWidget.onEvent)
I have several button like that and it just stopped all button's event listeners. What do you suggest? How can I remove the event listener for one button widget? Thanks.
Here is how I create my button widgets:
for i=0,2 do
for j=0,8 do
count=count+1
letterBtn[count] = widget.newButton{
id = alphabet[count],
left = 5+j*50,
top = H-160+i*50,
label = alphabet[count],
width = 45,
height = 45,
font = nil,
fontSize = 18,
labelColor = { default = {0,0,0}, over = {255,255,255}},
onEvent = btnOnEventHandler
};
end
end
Can you tell me how can I remove onEvent later?
Okey, I tried Button: setEnabled(false) but still it disables all buttons not just one. I already tried your second advice but it gives the same result. I am copying the rest of the code. Can you please look at it and tell me what I am missing?
local function checkLetter(e)
if(guessWord) then
for i=1, #guessWord do
local c = guessWord:sub(i,i)
if c==e.target.id then
letter[i].text = e.target.id
letterCount = letterCount +1
print("letterCount"..letterCount)
e.target:setEnabled(false)
end
end
if (letterCount == #guessWord and not hanged) then
timer.performWithDelay(500, function()
letterCount=0
rightWGuess = rightWGuess+1
for k,v in pairs(notGuessedWord) do
if v == guessWord then
notGuessedWord[k]=nil
end
end
enableButtons()
startGame() end ,1)
end
end
end
local function btnOnEventHandler(e)
if(e.phase == "began") then
checkLetter(e)
print(e.target.id)
end
return true
end
If you want to temporarily (or permanently) stop a button from responding to touch events, you can use Button:setEnabled(false).
The following worked for me for removing a listener from just 2 buttons. Button 1 and 3 stopped responding to events as expected while 2, 4, and 5 still did.
Update: To disable, you have to do it on the 'ended' phase or Corona gets confused.
widget = require 'widget'
local function btnOnEventHandler(event)
print('Event', event.target.id, event.phase)
if event.phase == 'ended' then
-- Disable the button so it can't be clicked again
-- Must disable in the end state or Corona gets
-- confused
event.target:setEnabled(false)
end
end
local buttons = {}
for i=1,5 do
buttons[i] = widget.newButton{
id = 'button' .. i,
left = display.contentCenterX - 50,
top = 60 * i,
label = 'Button ' .. i,
width = 100,
height = 50,
onEvent = btnOnEventHandler
}
end
buttons[1]:removeEventListener('touch', buttons[1].onEvent)
buttons[3]:removeEventListener('touch', buttons[3].onEvent)

MDI Child Windows overdraw frame toolbar?

I have write a MDI application with toolbar, but the child window overdraw the frame window's toolbar. Here is the effect, I have to click the left corner to see the toolbar icons.
I create the toolbar with following code:
CToolBar::CToolBar(HINSTANCE hInst, HWND hParent, LPCTSTR lpszWindowName) :
CWindow(hInst, hParent, lpszWindowName)
{
INITCOMMONCONTROLSEX icex;
// Ensure that the common control DLL is loaded.
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_BAR_CLASSES;
InitCommonControlsEx(&icex);
lstrcpy(m_szClassName, TOOLBARCLASSNAME);
}
BOOL CToolBar::Create()
{
//create the toolbar
m_hWnd = CreateWindowEx(0, TOOLBARCLASSNAME, (LPCTSTR) NULL,
WS_CHILD, 0, 0, 0, 0, m_hParent,
(HMENU) ID_TOOLBAR, m_hInst, NULL);
//for backword compatibility
SendMessage(m_hWnd, TB_BUTTONSTRUCTSIZE, (WPARAM) sizeof(TBBUTTON), 0);
if (m_hWnd == NULL)
return FALSE;
return TRUE;
}
BOOL CToolBar::Init()
{
TBBUTTON tbb[3];
TBADDBITMAP tbab;
if (! Create() )
return FALSE;
//Add standard toolbar bitmaps
tbab.hInst = HINST_COMMCTRL;
tbab.nID = IDB_STD_SMALL_COLOR;
SendMessage(m_hWnd, TB_ADDBITMAP, 0, (LPARAM)&tbab);
//Add buttons
ZeroMemory(tbb, sizeof(tbb));
tbb[0].iBitmap = STD_CUT;
tbb[0].idCommand = IDS_CUT;
tbb[0].fsState = TBSTATE_ENABLED;
tbb[0].fsStyle = TBSTYLE_BUTTON;
tbb[1].iBitmap = STD_COPY;
tbb[1].idCommand = IDS_COPY;
tbb[1].fsState = TBSTATE_ENABLED;
tbb[1].fsStyle = TBSTYLE_BUTTON;
tbb[2].iBitmap = STD_PASTE;
tbb[2].idCommand = IDS_PASTE;
tbb[2].fsState = TBSTATE_ENABLED;
tbb[2].fsStyle = TBSTYLE_BUTTON;
SendMessage(m_hWnd, TB_ADDBUTTONS, (WPARAM) 3, (LPARAM) (LPTBBUTTON) &tbb);
ShowWindow(m_hWnd, SW_NORMAL);
return TRUE;
}
I test it with SDI windows, it works well, but after I create the MDICLIENT(client) window, it sucks.
Please help me to work around this peculiar problem.
You COULD get all the source code at https://code.google.com/p/jcyangs-code/source/browse/trunk/com/lib/
Thanks.
Handle WM_SIZE message of Frame Window.

Resources