mouse events use local widget coordinates

This commit is contained in:
tpajenka 2014-05-09 00:17:31 +02:00
parent 75edc11a1e
commit 5f29ce7610
3 changed files with 29 additions and 12 deletions

View File

@ -145,7 +145,7 @@ clickHandler btn pos@(x,y) = do
case hits of case hits of
[] -> liftIO $ putStrLn $ unwords [show btn ++ ":press on (",show x,",",show y,")"] [] -> liftIO $ putStrLn $ unwords [show btn ++ ":press on (",show x,",",show y,")"]
_ -> do _ -> do
changes <- mapM (\uid -> do changes <- mapM (\(uid, pos') -> do
let w = toGUIAny hMap uid let w = toGUIAny hMap uid
short = w ^. baseProperties.shorthand short = w ^. baseProperties.shorthand
bound <- w ^. baseProperties.boundary bound <- w ^. baseProperties.boundary
@ -153,8 +153,8 @@ clickHandler btn pos@(x,y) = do
liftIO $ putStrLn $ "hitting(" ++ show btn ++ ") " ++ short ++ ": " ++ show bound ++ " " liftIO $ putStrLn $ "hitting(" ++ show btn ++ ") " ++ short ++ ": " ++ show bound ++ " "
++ show prio ++ " at [" ++ show x ++ "," ++ show y ++ "]" ++ show prio ++ " at [" ++ show x ++ "," ++ show y ++ "]"
case w ^. eventHandlers.(at MouseEvent) of case w ^. eventHandlers.(at MouseEvent) of
Just ma -> do w' <- fromJust (ma ^? onMousePress) btn pos w -- TODO unsafe fromJust Just ma -> do w' <- fromJust (ma ^? onMousePress) btn pos' w -- TODO unsafe fromJust
w'' <- fromJust (ma ^? onMouseRelease) btn pos True w' -- TODO unsafe fromJust w'' <- fromJust (ma ^? onMouseRelease) btn pos' True w' -- TODO unsafe fromJust
return $ Just (uid, w'') return $ Just (uid, w'')
Nothing -> return Nothing Nothing -> return Nothing
) hits ) hits

View File

@ -44,6 +44,10 @@ f >: (x, y) = (f x, f y)
(*:) = merge (*) (*:) = merge (*)
{-# INLINABLE (*:) #-} {-# INLINABLE (*:) #-}
infixl 7 *:
infixl 6 +:, -:
infixl 5 >:
-- |Id to reference a specific widget, must be unique. -- |Id to reference a specific widget, must be unique.
newtype UIId = UIId Int deriving (Eq, Ord, Bounded, Ix, Hashable, Show, Read) newtype UIId = UIId Int deriving (Eq, Ord, Bounded, Ix, Hashable, Show, Read)
@ -275,13 +279,25 @@ buttonMouseActions a = MouseHandler press' release'
emptyGraphics :: (Monad m) => GUIGraphics m emptyGraphics :: (Monad m) => GUIGraphics m
emptyGraphics = Graphics (return 3) emptyGraphics = Graphics (return 3)
isInsideRect :: (ScreenUnit, ScreenUnit, ScreenUnit, ScreenUnit) -> Pixel -> Bool -- |Extracts width and height from a '_boundary' property of a 'GUIBaseProperties'.
isInsideRect (x,y,w,h) (x',y') = (x' - x <= w) && (x' - x >= 0) && (y' - y <= h) && (y' - y >= 0) extractExtent :: (ScreenUnit, ScreenUnit, ScreenUnit, ScreenUnit) -> (ScreenUnit, ScreenUnit)
extractExtent (_,_,w,h) = (w,h)
{-# INLINABLE extractExtent #-}
-- |Calculates whether a point's value exceed the given width and height.
isInsideExtent :: (ScreenUnit, ScreenUnit) -> Pixel -> Bool
isInsideExtent (w,h) (x',y') = (x' <= w) && (x' >= 0) && (y' <= h) && (y' >= 0)
-- |Calculates whether a point is within a given rectangle.
isInsideRect :: (ScreenUnit, ScreenUnit, ScreenUnit, ScreenUnit) -> Pixel -> Bool
isInsideRect (x,y,w,h) px = isInsideExtent (w, h) $ px -: (x, y)
-- |@GUIBaseProperties@ with a rectangular base that fills the bounds.
rectangularBase :: (Monad m) => (ScreenUnit, ScreenUnit, ScreenUnit, ScreenUnit) -> [UIId] -> Int -> String -> GUIBaseProperties m rectangularBase :: (Monad m) => (ScreenUnit, ScreenUnit, ScreenUnit, ScreenUnit) -> [UIId] -> Int -> String -> GUIBaseProperties m
rectangularBase bnd chld prio short = rectangularBase bnd chld prio short =
BaseProperties (return bnd) (return chld) BaseProperties (return bnd) (return chld)
(\w p -> liftM (`isInsideRect` p) (w ^. baseProperties.boundary)) -- isInside (\w p -> liftM (flip isInsideExtent p . extractExtent) (w ^. baseProperties.boundary)) -- isInside
(return prio) short (return prio) short
debugShowWidget' :: (Monad m) => GUIWidget m -> m String debugShowWidget' :: (Monad m) => GUIWidget m -> m String

View File

@ -21,7 +21,7 @@ toGUIAnys m = mapMaybe (`Map.lookup` m)
-- |The function 'getInsideId' returns child widgets that overlap with a -- |The function 'getInsideId' returns child widgets that overlap with a
-- specific screen position. -- specific screen position and the pixel's local coordinates.
-- --
-- A screen position may be inside the bounding box of a widget but not -- A screen position may be inside the bounding box of a widget but not
-- considered part of the component. The function returns all hit widgets that -- considered part of the component. The function returns all hit widgets that
@ -30,17 +30,18 @@ toGUIAnys m = mapMaybe (`Map.lookup` m)
getInsideId :: Map.HashMap UIId (GUIWidget Pioneers) -- ^map containing ui widgets getInsideId :: Map.HashMap UIId (GUIWidget Pioneers) -- ^map containing ui widgets
-> Pixel -- ^screen position -> Pixel -- ^screen position
-> UIId -- ^the parent widget -> UIId -- ^the parent widget
-> Pioneers [UIId] -> Pioneers [(UIId, Pixel)]
getInsideId hMap px uid = do getInsideId hMap px uid = do
let wg = toGUIAny hMap uid let wg = toGUIAny hMap uid
bnd@(bX, bY, _, _) <- wg ^. baseProperties.boundary bnd@(bX, bY, _, _) <- wg ^. baseProperties.boundary
inside <- liftM (isInsideRect bnd px &&) $ (wg ^. baseProperties.isInside) wg px let px' = px -: (bX, bY)
inside <- liftM (isInsideRect bnd px &&) $ (wg ^. baseProperties.isInside) wg px'
if inside -- test inside parent's bounding box if inside -- test inside parent's bounding box
then do then do
childrenIds <- wg ^. baseProperties.children childrenIds <- wg ^. baseProperties.children
hitChildren <- liftM concat $ mapM (getInsideId hMap (px -: (bX, bY))) childrenIds hitChildren <- liftM concat $ mapM (getInsideId hMap px') childrenIds
case hitChildren of case hitChildren of
[] -> return [uid] [] -> return [(uid, px')]
_ -> return hitChildren _ -> return hitChildren
else return [] else return []
--TODO: Priority queue? --TODO: Priority queue?