mouse events use local widget coordinates
This commit is contained in:
		| @@ -145,7 +145,7 @@ clickHandler btn pos@(x,y) = do | ||||
|   case hits of | ||||
|        [] -> liftIO $ putStrLn $ unwords [show btn ++ ":press on (",show x,",",show y,")"] | ||||
|        _  -> do | ||||
|          changes <- mapM (\uid -> do | ||||
|          changes <- mapM (\(uid, pos') -> do | ||||
|            let w = toGUIAny hMap uid | ||||
|                short = w ^. baseProperties.shorthand | ||||
|            bound <- w ^. baseProperties.boundary | ||||
| @@ -153,8 +153,8 @@ clickHandler btn pos@(x,y) = do | ||||
|            liftIO $ putStrLn $ "hitting(" ++ show btn ++ ") " ++ short ++ ": " ++ show bound ++ " " | ||||
|                              ++ show prio ++ " at [" ++ show x ++ "," ++ show y ++ "]" | ||||
|            case w ^. eventHandlers.(at MouseEvent) of | ||||
|                 Just ma -> do w'  <- fromJust (ma ^? onMousePress) btn pos w -- TODO unsafe fromJust | ||||
|                               w'' <- fromJust (ma ^? onMouseRelease) btn pos True 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 | ||||
|                               return $ Just (uid, w'') | ||||
|                 Nothing  -> return Nothing | ||||
|            ) hits | ||||
|   | ||||
| @@ -44,6 +44,10 @@ f >: (x, y) = (f x, f y) | ||||
| (*:) = merge (*) | ||||
| {-# INLINABLE (*:) #-} | ||||
|  | ||||
| infixl 7 *: | ||||
| infixl 6 +:, -: | ||||
| infixl 5 >: | ||||
|  | ||||
| -- |Id to reference a specific widget, must be unique. | ||||
| 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 = Graphics (return 3) | ||||
|  | ||||
| isInsideRect :: (ScreenUnit, ScreenUnit, ScreenUnit, ScreenUnit) -> Pixel -> Bool | ||||
| isInsideRect (x,y,w,h) (x',y') = (x' - x <= w) && (x' - x >= 0) && (y' - y <= h) && (y' - y >= 0) | ||||
| -- |Extracts width and height from a '_boundary' property of a 'GUIBaseProperties'. | ||||
| 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 bnd chld prio short = | ||||
|     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 | ||||
|  | ||||
| debugShowWidget' :: (Monad m) => GUIWidget m -> m String | ||||
|   | ||||
| @@ -21,7 +21,7 @@ toGUIAnys m = mapMaybe (`Map.lookup` m) | ||||
|  | ||||
|  | ||||
| -- |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 | ||||
| --  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 | ||||
|             -> Pixel  -- ^screen position | ||||
|             -> UIId  -- ^the parent widget | ||||
|             -> Pioneers [UIId] | ||||
|             -> Pioneers [(UIId, Pixel)] | ||||
| getInsideId hMap px uid = do | ||||
|   let wg = toGUIAny hMap uid | ||||
|   let wg  = toGUIAny hMap uid | ||||
|   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 | ||||
|     then do | ||||
|       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 | ||||
|            [] -> return [uid] | ||||
|            [] -> return [(uid, px')] | ||||
|            _  -> return hitChildren | ||||
|     else return [] | ||||
| --TODO: Priority queue? | ||||
|   | ||||
		Reference in New Issue
	
	Block a user