{-# LANGUAGE CPP #-} module HyperGraphicsF2( module HyperGraphicsF2, GfxCommand(..),GfxChange(..),GfxEvent(..),replaceGfx,highlightGfx ) where import AllFudgets import Data.Maybe(fromJust,mapMaybe) import HbcUtils(mapFst) import qualified Data.Map as Map --import Fudget --import Defaults(paperColor) --import InputMsg(inputDone) --import Utils(swap) --import Xtypes(ColorName) --import Loops(loopThroughRightF) --import SerCompF(mapstateF) --import Graphic --import Drawing --import DrawingOps --import GraphicsF --import FDefaults --import ListUtil(assoc) --import Sizing(Sizing(..)) --import GCAttrs() -- instances --import Event(Pressed(..)) --import Maptrace(ctrace) -- debugging --import SpyF(teeF) -- debugging --import CompOps((>==<)) -- debugging #include "../hsrc/exists.h" hyperGraphicsF2 x = hyperGraphicsF2' standard x hyperGraphicsF2' custom init = loopThroughRightF (mapstateF ctrl state0) ({-teeF show "\n" >==<-} graphicsDispF' (custom . params)) where --tr x = ctrace "hyper" (show x) x -- debugging params = setInitDisp init . setGfxEventMask [GfxButtonMask] . setSizing Dynamic state0 = (annotPaths init,init) ctrl state@(paths,drawing) = either gfxEvent gfxCommand where same = (state,[]) lbl2path lbl = fromJust (Map.lookup lbl paths) gfxCommand lcmd = case mapGfxCommandPath lbl2path lcmd of cmd@(ChangeGfx changes) -> (changeState changes,[Left cmd]) cmd -> (state,[Left cmd]) where changeState changes = (paths',drawing') where drawing' = foldr replace drawing changes replace (path,GfxReplace (_,Just d)) drawing = replacePart drawing path d replace (path,GfxReplace _) drawing = drawing replace (path,GfxGroup from count) drawing = updatePart drawing path (groupParts from count) replace (path,GfxUngroup pos) drawing = updatePart drawing path (ungroupParts pos) paths' = annotPaths drawing' -- Space leak: drawing' isn't used until user clicks -- in the window, so the old drawing is retained in -- the closure for drawing' gfxEvent msg = (state,[Right msg']) where msg' = mapGfxEventPath path2lbl msg path2lbl path = do let part = drawingAnnotPart drawing path LabelD a _ <- maybeDrawingPart drawing part return a annotPaths = Map.fromList . map swap . drawingAnnots mouseClicksSP = mapFilterSP isMouseClick isMouseClick msg = case msg of GfxButtonEvent { gfxType=Pressed, gfxPaths=(path,_):_ } -> Just path _ -> Nothing --- mapGfxCommandPath f cmd = case cmd of ChangeGfx changes -> ChangeGfx (mapFst f changes) ShowGfx path a -> ShowGfx (f path) a GetGfxPlaces paths -> GetGfxPlaces (map f paths) -- _ -> cmd -- Operationally, the rest is the same as this line. ChangeGfxBg c -> ChangeGfxBg c ChangeGfxBgPixmap pm b -> ChangeGfxBgPixmap pm b #ifdef USE_EXIST_Q ChangeGfxBgGfx gfx -> ChangeGfxBgGfx gfx #endif ChangeGfxCursor cursor -> ChangeGfxCursor cursor ChangeGfxFontCursor shape -> ChangeGfxFontCursor shape BellGfx n -> BellGfx n mapGfxEventPath f event = case event of GfxButtonEvent t s ty b ps -> GfxButtonEvent t s ty b (mapPaths ps) GfxMotionEvent t s ps -> GfxMotionEvent t s (mapPaths ps) GfxKeyEvent t m k l -> GfxKeyEvent t m k l GfxFocusEvent b -> GfxFocusEvent b GfxPlaces rs -> GfxPlaces rs GfxResized s -> GfxResized s where -- mapPats :: [(a,(Point,Rect))] -> [(b,(Point,Rect))] mapPaths = mapMaybe f' -- f' :: (a,(Point,Rect)) -> Maybe (b,(Point,Rect)) f' (path,place) = fmap (\p->(p,place)) (f path) -- nullPath = null . gfxPaths -- would be ok if gfxPaths was a total function nullPath = maybe False null . gfxEventPaths gfxEventPaths event = case event of -- enumerate all constructors that have a path argument: GfxButtonEvent {gfxPaths=ps} -> Just ps GfxMotionEvent {gfxPaths=ps} -> Just ps _ -> Nothing isGfxButtonEvent (GfxButtonEvent {gfxType=Pressed,gfxButton=b}) = Just b isGfxButtonEvent _ = Nothing