-- | An integer list editor module LGtk.Demos.IntListEditor where import LGtk import Data.List (sortBy) import Data.Function (on) import Prelude hiding ((.), id) intListEditor :: (EffRef m, Read a, Show a, Integral a) => (a, Bool) -- ^ default element -> Int -- ^ maximum number of elements -> Ref m [(a, Bool)] -- ^ state reference -> Ref m Bool -- ^ settings reference -> Widget m intListEditor def maxi list_ range = action $ do (undo, redo) <- undoTr ((==) `on` map fst) list_ return $ notebook [ (,) "Editor" $ vcat [ hcat [ entryShow $ toRef len , smartButton (return "+1") len (+1) , smartButton (return "-1") len (+(-1)) , smartButton (liftM (("DeleteAll " ++) . show) $ readRef $ toRef len) len $ const 0 , button (return "undo") undo , button (return "redo") redo ] , hcat [ smartButton (return "+1") list $ map $ first (+1) , smartButton (return "-1") list $ map $ first (+(-1)) , smartButton (return "sort") list $ sortBy (compare `on` fst) , smartButton (return "SelectAll") list $ map $ second $ const True , smartButton (return "SelectPos") list $ map $ \(a,_) -> (a, a>0) , smartButton (return "SelectEven") list $ map $ \(a,_) -> (a, even a) , smartButton (return "InvertSel") list $ map $ second not , smartButton (liftM (("DelSel " ++) . show . length) sel) list $ filter $ not . snd , smartButton (return "CopySel") safeList $ concatMap $ \(x,b) -> (x,b): [(x,False) | b] , smartButton (return "+1 Sel") list $ map $ mapSel (+1) , smartButton (return "-1 Sel") list $ map $ mapSel (+(-1)) ] , label $ liftM (("Sum: " ++) . show . sum . map fst) sel , action $ listEditor def (map itemEditor [0..]) list_ ] , (,) "Settings" $ hcat [ label $ return "Create range" , checkbox range ] ] where list = eqRef list_ itemEditor i r = return $ hcat [ label $ return $ show (i+1) ++ "." , entryShow $ fstLens `lensMap` r , checkbox $ sndLens `lensMap` r , button_ (return "Del") (return True) $ modRef list $ \xs -> take i xs ++ drop (i+1) xs , button_ (return "Copy") (return True) $ modRef list $ \xs -> take (i+1) xs ++ drop i xs ] safeList = lens id (const . take maxi) `lensMap` list sel = liftM (filter snd) $ readRef list len = joinRef $ liftM ((`lensMap` safeList) . lens length . extendList) $ readRef range extendList r n xs = take n $ (reverse . drop 1 . reverse) xs ++ (uncurry zip . (iterate (+ if r then 1 else 0) *** repeat)) (head $ reverse xs ++ [def]) mapSel f (x, y) = (if y then f x else x, y) listEditor :: EffRef m => a -> [Ref m a -> m (Widget m)] -> Ref m [a] -> m (Widget m) listEditor def (ed: eds) r = do q <- extRef r listLens (False, (def, [])) return $ cell (liftM fst $ readRef q) $ \b -> case b of False -> empty True -> action $ do t1 <- ed $ fstLens . sndLens `lensMap` q t2 <- listEditor def eds $ sndLens . sndLens `lensMap` q return $ vcat [t1, t2]