| 1 | {- | |
|---|
| 2 | Module : $Header$ |
|---|
| 3 | Copyright : (c) Uni Bremen 2003-2007 |
|---|
| 4 | License : similar to LGPL, see HetCATS/LICENSE.txt or LIZENZ.txt |
|---|
| 5 | |
|---|
| 6 | Maintainer : raider@informatik.uni-bremen.de |
|---|
| 7 | Stability : unstable |
|---|
| 8 | Portability : non-portable |
|---|
| 9 | |
|---|
| 10 | This Modul provides a function to display a Library Dependency Graph. |
|---|
| 11 | -} |
|---|
| 12 | |
|---|
| 13 | module GUI.ShowLibGraph (showLibGraph, mShowGraph) where |
|---|
| 14 | |
|---|
| 15 | import Driver.Options (HetcatsOpts(outtypes), putIfVerbose) |
|---|
| 16 | import Driver.ReadFn |
|---|
| 17 | import Driver.AnaLib |
|---|
| 18 | |
|---|
| 19 | import Static.DevGraph |
|---|
| 20 | |
|---|
| 21 | import GUI.UDGUtils as UDG |
|---|
| 22 | import GUI.HTkUtils |
|---|
| 23 | |
|---|
| 24 | import GUI.GraphTypes |
|---|
| 25 | import GUI.GraphLogic(getLibDeps, hideNodes) |
|---|
| 26 | import GUI.GraphDisplay |
|---|
| 27 | import qualified GUI.GraphAbstraction as GA |
|---|
| 28 | |
|---|
| 29 | import Common.LibName |
|---|
| 30 | import qualified Common.Lib.Rel as Rel |
|---|
| 31 | |
|---|
| 32 | import Data.IORef |
|---|
| 33 | import qualified Data.Map as Map |
|---|
| 34 | |
|---|
| 35 | import Control.Concurrent.MVar |
|---|
| 36 | import Control.Concurrent(threadDelay) |
|---|
| 37 | |
|---|
| 38 | import Interfaces.DataTypes |
|---|
| 39 | |
|---|
| 40 | type NodeArcList = ([DaVinciNode LIB_NAME],[DaVinciArc (IO String)]) |
|---|
| 41 | |
|---|
| 42 | {- | Creates a new uDrawGraph Window and shows the Library Dependency Graph of |
|---|
| 43 | the given LibEnv.-} |
|---|
| 44 | showLibGraph :: LibFunc |
|---|
| 45 | showLibGraph gInfo@(GInfo {windowCount = wc}) = do |
|---|
| 46 | count <- takeMVar wc |
|---|
| 47 | putMVar wc $ count + 1 |
|---|
| 48 | depGRef <- newIORef daVinciSort |
|---|
| 49 | nodeArcRef <- newIORef (([],[])::NodeArcList) |
|---|
| 50 | let |
|---|
| 51 | globalMenu = GlobalMenu (UDG.Menu Nothing [ |
|---|
| 52 | Button "Reload Libraries" |
|---|
| 53 | (reload gInfo depGRef nodeArcRef) |
|---|
| 54 | ]) |
|---|
| 55 | graphParms = globalMenu $$ |
|---|
| 56 | GraphTitle "Library Graph" $$ |
|---|
| 57 | OptimiseLayout True $$ |
|---|
| 58 | AllowClose (close gInfo) $$ |
|---|
| 59 | FileMenuAct ExitMenuOption (Just (exit gInfo)) $$ |
|---|
| 60 | emptyGraphParms |
|---|
| 61 | depG <- newGraph daVinciSort graphParms |
|---|
| 62 | addNodesAndArcs gInfo depG nodeArcRef |
|---|
| 63 | writeIORef depGRef depG |
|---|
| 64 | redraw depG |
|---|
| 65 | return depG |
|---|
| 66 | |
|---|
| 67 | -- | Reloads all Libraries and the Library Dependency Graph |
|---|
| 68 | reload :: GInfo -> IORef DaVinciGraphTypeSyn -> IORef NodeArcList -> IO() |
|---|
| 69 | reload gInfo@(GInfo {gi_hetcatsOpts = opts |
|---|
| 70 | }) depGRef nodeArcRef = do |
|---|
| 71 | ost <- readIORef $ intState gInfo |
|---|
| 72 | case i_state ost of |
|---|
| 73 | Nothing -> return () |
|---|
| 74 | Just ist -> do |
|---|
| 75 | let ln = i_ln ist |
|---|
| 76 | depG <- readIORef depGRef |
|---|
| 77 | (nodes', arcs) <- readIORef nodeArcRef |
|---|
| 78 | let |
|---|
| 79 | libfile = libNameToFile opts ln |
|---|
| 80 | m <- anaLib opts { outtypes = [] } libfile |
|---|
| 81 | case m of |
|---|
| 82 | Nothing -> fail $ |
|---|
| 83 | "Error when reloading file '" ++ libfile ++ "'" |
|---|
| 84 | Just (_, _) -> do |
|---|
| 85 | mapM_ (deleteArc depG) arcs |
|---|
| 86 | mapM_ (deleteNode depG) nodes' |
|---|
| 87 | addNodesAndArcs gInfo depG nodeArcRef |
|---|
| 88 | writeIORef depGRef depG |
|---|
| 89 | redraw depG |
|---|
| 90 | |
|---|
| 91 | -- | Adds the Librarys and the Dependencies to the Graph |
|---|
| 92 | addNodesAndArcs :: GInfo -> DaVinciGraphTypeSyn -> IORef NodeArcList -> IO () |
|---|
| 93 | addNodesAndArcs gInfo@(GInfo { gi_hetcatsOpts = opts}) depG nodeArcRef = do |
|---|
| 94 | ost <- readIORef $ intState gInfo |
|---|
| 95 | case i_state ost of |
|---|
| 96 | Nothing -> return () |
|---|
| 97 | Just ist -> do |
|---|
| 98 | let |
|---|
| 99 | le = i_libEnv ist |
|---|
| 100 | lookup' x y = Map.findWithDefault (error "lookup': node not found") y x |
|---|
| 101 | keys = Map.keys le |
|---|
| 102 | subNodeMenu = LocalMenu(UDG.Menu Nothing [ |
|---|
| 103 | Button "Show Graph" $ mShowGraph gInfo, |
|---|
| 104 | Button "Show spec/View Names" $ showSpec le]) |
|---|
| 105 | subNodeTypeParms = subNodeMenu $$$ |
|---|
| 106 | Box $$$ |
|---|
| 107 | ValueTitle (\ x -> return (show x)) $$$ |
|---|
| 108 | Color (getColor opts Green True True) $$$ |
|---|
| 109 | emptyNodeTypeParms |
|---|
| 110 | subNodeType <- newNodeType depG subNodeTypeParms |
|---|
| 111 | subNodeList <- mapM (newNode depG subNodeType) keys |
|---|
| 112 | let |
|---|
| 113 | nodes' = Map.fromList $ zip keys subNodeList |
|---|
| 114 | subArcMenu = LocalMenu(UDG.Menu Nothing []) |
|---|
| 115 | subArcTypeParms = subArcMenu $$$ |
|---|
| 116 | ValueTitle id $$$ |
|---|
| 117 | Color (getColor opts Black False False) $$$ |
|---|
| 118 | emptyArcTypeParms |
|---|
| 119 | subArcType <- newArcType depG subArcTypeParms |
|---|
| 120 | let |
|---|
| 121 | insertSubArc = \ (node1, node2) -> newArc depG subArcType (return "") |
|---|
| 122 | (lookup' nodes' node1) (lookup' nodes' node2) |
|---|
| 123 | subArcList <- mapM insertSubArc $ Rel.toList $ Rel.intransKernel $ |
|---|
| 124 | Rel.transClosure $ Rel.fromList $ getLibDeps le |
|---|
| 125 | writeIORef nodeArcRef (subNodeList, subArcList) |
|---|
| 126 | |
|---|
| 127 | mShowGraph :: GInfo -> LIB_NAME -> IO() |
|---|
| 128 | mShowGraph gInfo@(GInfo {gi_hetcatsOpts = opts}) ln = do |
|---|
| 129 | putIfVerbose opts 3 "Converting Graph" |
|---|
| 130 | gInfo' <- copyGInfo gInfo ln |
|---|
| 131 | convertGraph gInfo' "Development Graph" showLibGraph |
|---|
| 132 | let gv = gi_GraphInfo gInfo' |
|---|
| 133 | GA.deactivateGraphWindow gv |
|---|
| 134 | hideNodes gInfo' |
|---|
| 135 | GA.redisplay gv |
|---|
| 136 | threadDelay 2000000 |
|---|
| 137 | GA.layoutImproveAll gv |
|---|
| 138 | GA.showTemporaryMessage gv "Development Graph initialized." |
|---|
| 139 | GA.activateGraphWindow gv |
|---|
| 140 | return () |
|---|
| 141 | |
|---|
| 142 | -- | Displays the Specs of a Library in a Textwindow |
|---|
| 143 | showSpec :: LibEnv -> LIB_NAME -> IO() |
|---|
| 144 | showSpec le ln = do |
|---|
| 145 | let |
|---|
| 146 | ge = globalEnv $ lookupDGraph ln le |
|---|
| 147 | sp = unlines $ map show $ Map.keys $ ge |
|---|
| 148 | createTextDisplay ("Contents of " ++ show ln) sp [size(80,25)] |
|---|
| 149 | |
|---|
| 150 | close :: GInfo -> IO Bool |
|---|
| 151 | close (GInfo { exitMVar = exit' |
|---|
| 152 | , windowCount = wc |
|---|
| 153 | }) = do |
|---|
| 154 | count <- takeMVar wc |
|---|
| 155 | case count == 1 of |
|---|
| 156 | True -> putMVar exit' () |
|---|
| 157 | False -> putMVar wc $ count - 1 |
|---|
| 158 | return True |
|---|
| 159 | |
|---|
| 160 | exit :: GInfo -> IO () |
|---|
| 161 | exit (GInfo {exitMVar = exit'}) = do |
|---|
| 162 | putMVar exit' () |
|---|