module GraphRewrite.Main.Utils where import GraphRewrite import GraphRewrite.Main.Visualize import qualified Graphics.UI.Gtk as G hiding (Color) import qualified Graphics.UI.Gtk.Gdk.Events as G import qualified Graphics.Rendering.Cairo as C import qualified Graphics.Rendering.Cairo.SVG as C import Data.Supply import Control.Monad import Control.Concurrent.MVar.Strict import Control.Concurrent (forkIO) import qualified Control.Exception as C import System.Process import System.IO import System.Exit type AssocList a b = [(a, b)] handleKeys :: (Monad m, G.WidgetClass w) => AssocList String (w -> MVar a -> m c) -> w -> MVar a -> G.Event -> m Bool handleKeys m w ma (G.Key {G.eventKeyName = key}) = case lookup key m of Just a -> a w ma >> return True _ -> return True updateCanvasTo :: G.DrawingArea -> PointedGraph -> FilePath -> RewriteSystem -> Supply Int -> IO Bool updateCanvasTo canvas pg exe rs ids = do let dot = renderDot ids rs pg svg <- dotToSVG exe dot updateCanvas svg canvas dotToSVG :: FilePath -> String -> IO C.SVG dotToSVG dotexe dot = do svgstring <- myReadProcess dotexe ["-Tsvg"] dot C.svgNewFromString svgstring updateCanvas :: C.SVG -> G.DrawingArea -> IO Bool updateCanvas svg canvas = do win <- G.widgetGetDrawWindow canvas (width, height) <- G.widgetGetSize canvas let (w,h) = (fromIntegral width, fromIntegral height) (sw, sh) = C.svgGetSize svg G.renderWithDrawable win $ do C.setAntialias C.AntialiasDefault C.setLineCap C.LineCapSquare C.scale (w / fromIntegral sw) (h / fromIntegral sh) C.svgRender svg return True myReadProcess :: FilePath -- ^ command to run -> [String] -- ^ any arguments -> String -- ^ standard input -> IO String -- ^ stdout + stderr myReadProcess cmd args input = do (Just inh, Just outh, _, pid) <- createProcess (proc cmd args){ std_in = CreatePipe, std_out = CreatePipe, std_err = Inherit } -- fork off a thread to start consuming the output output <- hGetContents outh outMVar <- newEmptyMVar forkIO $ C.evaluate (length output) >> putMVar outMVar () -- now write and flush any input unless (null input) $ do hPutStr inh input; hFlush inh hClose inh -- done with stdin -- wait on the output takeMVar outMVar hClose outh -- wait on the process ex <- waitForProcess pid case ex of ExitSuccess -> return output ExitFailure _ -> return output readInput :: Maybe String -> IO String readInput Nothing = getContents readInput (Just f) = readFile f