{-# OPTIONS_GHC -Wall #-} {-# Language GADTs #-} {-# LANGUAGE PackageImports #-} module PlotHo.PlotTypes ( AxisType(..) , Axes(..) , Channel(..) , Channel'(..) , Element(..) , Element'(..) , GraphComms(..) , ListViewInfo(..) , MarkedState(..) , PlotterOptions(..) , SignalTree , XY(..) , debug , defaultHistoryRange ) where import qualified Control.Concurrent as CC import Control.Monad.IO.Class ( MonadIO ) -- , liftIO ) import Data.Default.Class ( Default(..) ) import Data.IORef ( IORef ) import qualified Data.Map.Strict as M import Data.Tree ( Tree ) import qualified "gtk3" Graphics.UI.Gtk as Gtk debug :: MonadIO m => String -> m () --debug = liftIO . putStrLn debug = const (return ()) data MarkedState = On | Off | Inconsistent deriving (Eq, Show) data Element where Element :: Element' a -> Element data Element' a = Element' { eChannel :: Channel' a , eMsgStore :: CC.MVar (Maybe (a, Maybe (SignalTree a))) , ePlotValueRef :: IORef a , eIndex :: Int } data ListViewInfo where ListViewInfo :: { lviName :: ![String] , lviTypeOrGetter :: !(Either String (a -> [[(Double,Double)]])) , lviMarked :: !MarkedState , lviPlotValueRef :: IORef a } -> ListViewInfo instance Show ListViewInfo where show (ListViewInfo n (Left t) m _) = "ListViewInfo " ++ show (n,t,m) show (ListViewInfo n (Right _) m _) = "ListViewInfo " ++ show (n,m) type SignalTree a = Tree ( [String] , Either String (a -> [[(Double, Double)]]) ) data AxisType = LinearScalingAutoRange | LinearScalingHistoryRange | LinearScalingManualRange | LogScaling deriving (Enum) defaultHistoryRange :: (Double, Double) defaultHistoryRange = (read "Infinity", - read "Infinity") data XY a = XY { xaxis :: !a , yaxis :: !a } data Axes a = Axes { axesType :: !(XY AxisType) , axesManualRange :: !(XY (a, a)) } data GraphComms a = GraphComms { gcRedrawSignal :: IO () , gcMsgStore :: CC.MVar (Maybe (a, Maybe (SignalTree a))) -- ^ The MVar is always full, we use Maybe to decide if a first message has been received. -- If the signal tree is Just, a rebuild is needed. } data Channel where Channel :: Channel' a -> Channel data Channel' a = Channel' { chanName :: String , chanSameSignalTree :: a -> a -> Bool , chanToSignalTree :: a -> SignalTree a , chanMaxHistory :: IORef Int , chanClearHistory :: Maybe (a -> a) , chanGraphCommsMap :: CC.MVar (M.Map Gtk.Window (GraphComms a)) , chanLatestValueMVar :: CC.MVar (Maybe (a, SignalTree a)) } -- | Some options data PlotterOptions = PlotterOptions { maxDrawRate :: Double -- ^ limit the draw frequency to this number in Hz , defaultXAxis :: AxisType , defaultYAxis :: AxisType } instance Default PlotterOptions where def = PlotterOptions { maxDrawRate = 40 , defaultXAxis = LinearScalingAutoRange , defaultYAxis = LinearScalingAutoRange }