packages feed

AERN-RnToRm-Plot (empty) → 0.1.0

raw patch · 12 files changed

+2233/−0 lines, 12 filesdep +AERN-Realdep +AERN-RnToRmdep +GLUTsetup-changed

Dependencies added: AERN-Real, AERN-RnToRm, GLUT, OpenGL, base, binary, containers, directory, filepath, glade, glib, gtk, gtkglext, old-time, stm

Files

+ AERN-RnToRm-Plot.cabal view
@@ -0,0 +1,46 @@+Name:           AERN-RnToRm-Plot+Version:        0.1.0+Cabal-Version:  >= 1.2+Build-Type:     Simple+License:        BSD3+License-File:   LICENCE+Author:         Michal Konecny (Aston University)+Copyright:      (c) 2007-2008 Michal Konecny+Maintainer:     mik@konecny.aow.cz+Stability:      experimental+Category:       Data, Math+Synopsis:       GL plotting of polynomial function enclosures (PFEs)+Tested-with:    GHC ==6.8.3+Description:+    This library extends AERN-RnToRm with support for plotting unary function enclosures+    in any GL context and a Gtk window for inspecting these enclosures.+    .+    Simple examples of usage can be found in module @Demo.hs@ in folder @tests@.+Extra-source-files:+    tests/Demo.hs tests/FnView.glade src/FnView.glade+Data-files:+    ChangeLog README.glade+Flag containers-in-base+    Default: False++Library+  hs-source-dirs:  src+  if flag(containers-in-base)+    Build-Depends:+      base < 3, binary >= 0.4, directory, filepath, old-time, stm,+      AERN-Real >= 0.9.7.1, AERN-RnToRm >= 0.4.1, +      OpenGL >= 2.2.1.1, GLUT >= 2.1.1.1,+      gtk >= 0.9.12.1, gtkglext >= 0.9.12.1, glib >= 0.9.12.1, glade >= 0.9.12.1+  else+    Build-Depends:+      base >= 3, containers, binary >= 0.4, directory, filepath, old-time, stm, +      AERN-Real >= 0.9.7.1, AERN-RnToRm >= 0.4.1, +      OpenGL >= 2.2.1.1, GLUT >= 2.1.1.1,+      gtk >= 0.9.12.1, gtkglext >= 0.9.12.1, glib >= 0.9.12.1, glade >= 0.9.12.1+  Exposed-modules:+    Data.Number.ER.RnToRm.Plot.FnView,+    Data.Number.ER.RnToRm.Plot.GLDrawable,+    Data.Number.ER.RnToRm.Plot.Params,+    Data.Number.ER.MiscSTM+    +  
+ ChangeLog view
@@ -0,0 +1,2 @@+0.1.0: 1 October 2008+    * initial release of AERN-RnToRm-Plot
+ LICENCE view
@@ -0,0 +1,30 @@+Copyright (c) 2007-2008 Michal Konecny++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:++1. Redistributions of source code must retain the above copyright+   notice, this list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright+   notice, this list of conditions and the following disclaimer in the+   documentation and/or other materials provided with the distribution.++3. Neither the name of the author nor the names of his contributors+   may be used to endorse or promote products derived from this software+   without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS+OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE+DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.
+ README.glade view
@@ -0,0 +1,2 @@+The Gtk window module expects the supplied file FnView.glade +to be in $(GLADE_DIR), which defaults to the current directory.
+ Setup.lhs view
@@ -0,0 +1,3 @@+#!/usr/bin/env runhaskell+> import Distribution.Simple+> main = defaultMain
+ src/Data/Number/ER/MiscSTM.hs view
@@ -0,0 +1,31 @@+{-|+    Utilities related to concurrency.+-}+module Data.Number.ER.MiscSTM where++import Control.Concurrent as Concurrent+import Control.Concurrent.STM as STM++modifyTVar tv update =+    do+    value <- readTVar tv+    writeTVar tv $ update value++modifyTVarGetOldVal tv update =+    do+    value <- readTVar tv+    writeTVar tv $ update value+    return value++modifyTVarHasChanged tv update =+    do+    value <- readTVar tv+    let newValue = update value+    if value == newValue+        then return False+        else +            do+            writeTVar tv $ update value+            return True+    +    
+ src/Data/Number/ER/RnToRm/Plot/FnView.hs view
@@ -0,0 +1,765 @@+{-# LANGUAGE CPP #-}+#ifdef GLADE_DIR+#else+#define GLADE_DIR "./"+#endif +{-|+    Module      :  Data.Number.ER.RnToRm.Plot.FAView+    Description :  plot function enclosures on GL canvas+    Copyright   :  (c) 2007-2008 Michal Konecny+    License     :  BSD3++    Maintainer  :  mik@konecny.aow.cz+    Stability   :  experimental+    Portability :  portable++    This module provides a generic plotter for a set of function approximations.+    The functions must be unary at present (R->R^n).+    +    To be imported qualified, usually with the synonym FNV.    +-}+module Data.Number.ER.RnToRm.Plot.FnView +(+    FaData (..),+    FnData (..),+    defaultFaData,+    defaultFnData,+    new,+    module Data.Number.ER.RnToRm.Plot.Params+)+where++--import IVPs++import Data.Number.ER.RnToRm.Plot.Params+import qualified Data.Number.ER.Real.Approx as RA+import qualified Data.Number.ER.RnToRm.Approx as FA+import qualified Data.Number.ER.Real.DomainBox as DBox+import Data.Number.ER.RnToRm.Plot.GLDrawable+import Data.Number.ER.BasicTypes+import Data.Number.ER.Misc++import qualified Graphics.UI.Gtk as Gtk+import Graphics.UI.Gtk (AttrOp((:=)))+import qualified Graphics.UI.Gtk.Glade as Glade+import qualified Graphics.UI.Gtk.OpenGL as GtkGL+import qualified Graphics.UI.GLUT as GLUT+import qualified System.Glib.Signals as Signals++import qualified Graphics.Rendering.OpenGL as GL+import Graphics.Rendering.OpenGL (HasSetter(($=)))++import Control.Concurrent as Concurrent+import Control.Concurrent.STM as STM+import Data.Number.ER.MiscSTM+import Data.IORef++import Data.Maybe++import qualified System.FilePath as FilePath+import System.Directory++{-|+    Two transactional variables with values of the following two types+    will be used by the client(s) to communicate to the viewer what it+    should be showing.+-}+data FaData fa =+    FaData+    {+        dataFAs :: [fa] -- ^ functions to plot+    }++data FnData =+    FnData+    {+        dataDestroyed :: Bool, -- ^ command to destroy OR signal that user destroyed+        dataFAsUpdated :: Bool, -- ^ avoid checking fas for equality+        dataDomName :: String, -- ^ name of the domain variable (eg "t")+        dataDomL :: Double, -- ^ left endpoint of the domain+        dataDomR :: Double, -- ^ right endpoint of the domain+        dataValLO :: Double, -- ^ lower bounds for values of all functions+        dataValHI :: Double, -- ^ upper bounds for values of all functions+        dataFnNames :: [String],+        dataResultNames :: [[String]], -- ^ for each function list of result variable names+        dataDefaultEvalPoint :: Double, -- ^ show the values of the functions at this point+        dataDefaultEvalPointName :: String, -- ^ label to put on the button+        dataDefaultPlotParams :: PlotParams+    }+    deriving (Eq, Show)++defaultFaData =+    FaData+    {+        dataFAs = []+    }++defaultFnData =+    FnData+    {+        dataDestroyed = False,+        dataFAsUpdated = False,+        dataDomName = "t",+        dataDomL = 0,+        dataDomR = 1,+        dataValLO = 0,+        dataValHI = 1,+        dataFnNames = [],+        dataResultNames = [],+        dataDefaultEvalPoint = 0,+        dataDefaultEvalPointName = "default",+        dataDefaultPlotParams = defaultPlotParams+    }++readBothTVars :: +    (TVar a, TVar a1) -> +    STM (a, a1)+readBothTVars (fadataTV, fndataTV) =+    do+    fadata <- readTVar fadataTV+    fndata <- readTVar fndataTV+    return (fadata, fndata)++readAll3TVars :: +    (TVar a1, TVar a2) -> +    TVar a -> +    STM ((a1, a2), a)+readAll3TVars fndataTVs stateTV =+    do+    state <- readTVar stateTV+    fndatas <- readBothTVars fndataTVs +    return (fndatas, state)++{-|+    Create a new viewer linked to the given data variable.+-}+new ::+    (FA.ERFnApprox box varid domra ranra fa, ERFnGLDrawable box varid domra ranra fa) =>+    (TVar (FaData fa),+     TVar (FnData)) ->+    (Maybe Gtk.Window) {- ^ parent window -} -> +    IO Gtk.Window+new fndataTVs@(fadataTV, fndataTV) maybeParentWindow =+    do+    -- create initial state objects:+    stateTV <- atomically $+        do+        fadata <- readTVar fadataTV+        fndata <- readTVar fndataTV+        STM.newTVar $ initState (fadata, fndata)+    dynWidgetsRef <- newIORef initERFnViewDynWidgets+    -- create most widgets:+    widgets <- loadGlade (FilePath.combine GLADE_DIR "FnView.glade")+    -- create plotting canvas:+    widgets <- makeCanvas widgets fndataTVs stateTV+    -- attach handlers to widgets+    Gtk.onDestroy (window widgets) $+        do+        atomically $ modifyTVar fndataTV $ \fndata -> fndata { dataDestroyed = True }+        Gtk.mainQuit+    setHandlers widgets dynWidgetsRef fndataTVs stateTV+    -- start thread that reponds to changes in fndataTVs:+    forkIO $ dataWatchThread widgets dynWidgetsRef fndataTVs stateTV+    Gtk.widgetShowAll $ window widgets+    return $ window widgets++loadGlade :: +    FilePath ->+    IO Widgets+loadGlade gladeFileName =+    do+    gotGladeFile <- doesFileExist gladeFileName+    case gotGladeFile of+        True -> return ()+        False -> error $ "RnToRm.Plot.FnView: glade file " ++ gladeFileName ++ " not found" +    Just xml <- Glade.xmlNew gladeFileName+    window <- Glade.xmlGetWidget xml Gtk.castToWindow "window1"+    canvasAlignment <- Glade.xmlGetWidget xml Gtk.castToAlignment "canvasAlignment1"+    coorSystemCombo <- Glade.xmlGetWidget xml Gtk.castToComboBox "coorSystemCombo1"+    evalPointEntry <- Glade.xmlGetWidget xml Gtk.castToEntry "evalPointEntry1"+    defaultEvalPointButton <- Glade.xmlGetWidget xml Gtk.castToButton "defaultEvalPointButton1"+    dimTable <- Glade.xmlGetWidget xml Gtk.castToTable "dimTable1"+    domVarLabel <- Glade.xmlGetWidget xml Gtk.castToLabel "domVarLabel1"+    zoomEntry <- Glade.xmlGetWidget xml Gtk.castToEntry "zoomEntry1"+    centreXEntry <- Glade.xmlGetWidget xml Gtk.castToEntry "centreXEntry1"+    centreYEntry <- Glade.xmlGetWidget xml Gtk.castToEntry "centreYEntry1"+    exportJPGButton <- Glade.xmlGetWidget xml Gtk.castToButton "exportJPGButton1"+    printTXTButton <- Glade.xmlGetWidget xml Gtk.castToButton "printTXTButton1"+    return $ Widgets+        {+            window = window,+            canvasAlignment = canvasAlignment,+            coorSystemCombo = coorSystemCombo,+            evalPointEntry = evalPointEntry,+            defaultEvalPointButton = defaultEvalPointButton,+            dimTable = dimTable,+            domVarLabel = domVarLabel,+            zoomEntry = zoomEntry,+            centreXEntry = centreXEntry,+            centreYEntry = centreYEntry,+            exportJPGButton = exportJPGButton,+            printTXTButton = printTXTButton,+            canvas = error "canvas not created yet"+        }++data Widgets = +    Widgets+    {+        window :: Gtk.Window,+        canvasAlignment :: Gtk.Alignment,+        coorSystemCombo :: Gtk.ComboBox,+        evalPointEntry :: Gtk.Entry,+        defaultEvalPointButton :: Gtk.Button,+        dimTable :: Gtk.Table,+        domVarLabel :: Gtk.Label,+        zoomEntry :: Gtk.Entry,+        centreXEntry :: Gtk.Entry,+        centreYEntry :: Gtk.Entry,+        exportJPGButton :: Gtk.Button,+        printTXTButton :: Gtk.Button,+        canvas :: GtkGL.GLDrawingArea+    }++data ERFnViewDynWidgets = +    ERFnViewDynWidgets+    {+        valueLabels :: [[Gtk.Label]]+    }++initERFnViewDynWidgets :: ERFnViewDynWidgets+initERFnViewDynWidgets =+    ERFnViewDynWidgets []    +    +data ERFnViewState =+    ERFnViewState+    {+        favstActiveDims :: [[Bool]],+        favstTrackingDefaultEvalPt :: Bool,+        favstPlotParams :: PlotParams+    }++initState :: +    (t, FnData) -> +    ERFnViewState+initState (fadata, fndata) =+    ERFnViewState+    {+        favstActiveDims = map (map $ const True) $ dataResultNames fndata,+        favstTrackingDefaultEvalPt = True,+        favstPlotParams = dataDefaultPlotParams fndata    +    }+    +updateDimActive :: +    TVar ERFnViewState -> +    Int -> +    Int -> +    Bool -> +    STM ERFnViewState+updateDimActive stateTV fnNo dimNo isActive =+    do+    modifyTVar stateTV update+    readTVar stateTV+    where+    update state =+        state+        {+            favstActiveDims = updateDim $ favstActiveDims state+        }+    updateDim activeDims =+        listUpdate fnNo activeFnDims activeDims+        where+        activeFnDims =+            listUpdate dimNo isActive (activeDims !! fnNo)++setHandlers :: +    (FA.ERFnApprox box varid domra ranra fa, +     ERFnGLDrawable box varid domra ranra fa) =>+    Widgets -> +    IORef ERFnViewDynWidgets -> +    (TVar (FaData fa), TVar FnData) -> +    TVar ERFnViewState -> +    IO ()+setHandlers widgets dynWidgetsRef fndataTVs@(fadataTV, fndataTV) stateTV =+    do+    setHandlerPrintTXTButton+    setHandlerDefaultEvalPointButton+    setHandlerEvalPointEntry+    setHandlerCoordSystem+    return ()+    where+    setHandlerCoordSystem =+        do+        Gtk.onChanged (coorSystemCombo widgets) $+            do+            maybeCSysIx <- Gtk.comboBoxGetActive (coorSystemCombo widgets)+            case maybeCSysIx of+                Nothing -> return ()+                Just ix ->+                    do+                    coordSystem <-+                        atomically $+                            do+                            fndata <- readTVar fndataTV+                            let coordSystem = case ix of+                                    0 -> CoordSystemLogSqueeze+                                    1 -> +                                        CoordSystemLinear $ Rectangle +                                            ((toRational $ dataValHI fndata) + 0.2)+                                            ((toRational $ dataValLO fndata) - 0.2)+                                            ((toRational $ dataDomL fndata) - 0.1)+                                            ((toRational $ dataDomR fndata) + 0.1)+                            modifyTVar stateTV $ update coordSystem+                            return coordSystem +                    changeCoordSystem coordSystem+                    where+                    update coordSystem state =+                        state +                        { +                            favstPlotParams = +                                (favstPlotParams state) +                                    { pltprmCoordSystem = coordSystem } +                        } +    changeCoordSystem coordSystem =+        do+        resetZoom coordSystem+        (fndatas, state) <- atomically $ readAll3TVars fndataTVs stateTV+        repaintCanvas (canvas widgets) fndatas state+        return ()+        +    resetZoom CoordSystemLogSqueeze =+        do+        Gtk.editableSetEditable (zoomEntry widgets) False+        Gtk.editableSetEditable (centreXEntry widgets) False+        Gtk.editableSetEditable (centreYEntry widgets) False+        Gtk.entrySetText (zoomEntry widgets) ""+        Gtk.entrySetText (centreXEntry widgets) ""+        Gtk.entrySetText (centreYEntry widgets) ""+    resetZoom (CoordSystemLinear (Rectangle hi lo l r)) =+        do+--        Gtk.editableSetEditable (zoomEntry widgets) True+--        Gtk.editableSetEditable (centreXEntry widgets) True+--        Gtk.editableSetEditable (centreYEntry widgets) True+        Gtk.editableSetEditable (zoomEntry widgets) False+        Gtk.editableSetEditable (centreXEntry widgets) False+        Gtk.editableSetEditable (centreYEntry widgets) False+        Gtk.entrySetText (zoomEntry widgets) "100"+        Gtk.entrySetText (centreXEntry widgets) $ show $ (l + r)/2+        Gtk.entrySetText (centreYEntry widgets) $ show $ (hi + lo)/2+        +    setHandlerPrintTXTButton =+        Gtk.onClicked (printTXTButton widgets) $+            do+            (state, FaData fas) <- +                atomically $+                    do+                    state <- readTVar stateTV+                    fas <- readTVar fadataTV+                    return (state, fas)+            putStrLn $+--                (show $ head fas)+--                ++ "\n---------------\n" ++ +--                (show $ combustionField 7 $ head fas) +                unlines $ map show $ fas+    setHandlerDefaultEvalPointButton =+        Gtk.onClicked (defaultEvalPointButton widgets) $+            do+            (state, fndata) <- +                atomically $+                    do+                    state <- readTVar stateTV+                    fndata <- readTVar fndataTV+                    return (state, fndata)+            case favstTrackingDefaultEvalPt state of+                False ->+                    do+                    Gtk.entrySetText (evalPointEntry widgets) $ +                        show $ dataDefaultEvalPoint fndata+                    atomically $ modifyTVar stateTV $+                        \ st -> st { favstTrackingDefaultEvalPt = True }+                    updateValueDisplayTV widgets dynWidgetsRef fndataTVs stateTV +                True -> -- already tracking the default+                    return ()+    setHandlerEvalPointEntry =+        do+        Gtk.onEntryActivate (evalPointEntry widgets) $ +            do+            updateEvalPointHandler+        Gtk.onFocusOut (evalPointEntry widgets) $ \ _ -> +            do+            updateEvalPointHandler+            return False+        where+        updateEvalPointHandler =+            do+            -- indicate that we no longer wish to track the default point:  +            atomically $ modifyTVar stateTV $ +                \ st -> st { favstTrackingDefaultEvalPt = False }+            -- update the values for the new point:  +            updateValueDisplayTV widgets dynWidgetsRef fndataTVs stateTV++{-|+    Reconfigure the GUI to show variable names appropriate+    for the given fndata.+-}+updateDimWidgets ::+    (FA.ERFnApprox box varid domra ranra fa, ERFnGLDrawable box varid domra ranra fa) =>+    Widgets ->+    IORef ERFnViewDynWidgets ->+    FnData ->+    (TVar (FaData fa),+     TVar FnData) ->+    (TVar ERFnViewState) ->+    IO ()+updateDimWidgets widgets dynWidgetsRef fndata fndataTVs stateTV =+    do+    return ()+    -- update the name of the domain variable:+    Gtk.labelSetText (domVarLabel widgets) $ domName ++ "="+    -- set the default evaluation point:+    Gtk.entrySetText (evalPointEntry widgets) $ show $ dataDefaultEvalPoint fndata+    -- remove any old dim rows from dimTable:+    children <- Gtk.containerGetChildren table+    mapM (Gtk.containerRemove table) children  +    -- add new dim rows:+    Gtk.tableResize table (dimRows + 1) 3+    -- fill each row with widgets and return all newly created value entries:+    valueLabels <- addRows [] [] 0 (-1) 0 fnNames ([] : resultNames)+    -- layout the table:+    Gtk.widgetShowAll table+    Gtk.containerResizeChildren table+    -- remember valueEntries for later use: +    modifyIORef dynWidgetsRef $ \ dynWidgets ->+        dynWidgets+        {+            valueLabels = valueLabels+        } +    where+    table = dimTable widgets+    domName = dataDomName fndata+    dimRows = (length fnNames) + (sum $ map length resultNames)+    fnNames = dataFnNames fndata+    resultNames = dataResultNames fndata+    addRows ::+        [[Gtk.Label]] -> -- accumulator for label groups+        [Gtk.Label] -> -- accumulator for labels in the current group+        Int -> -- current table row number+        Int -> -- current function index+        Int -> -- current dimension index+        [String] -> -- function names+        [[String]] -> -- variable names per result dimension+        IO ([[Gtk.Label]])+    addRows prevLabels prevLs nextRowNo fnNo dimNo [] ([]: _) = +        return $ tail $ reverse $ prevLs : prevLabels+    addRows prevLabels prevLs nextRowNo fnNo dimNo (fnName : restFnNames) ([] : resultNames) =+        do+        -- add a function label:+        fnLabel <- Gtk.labelNew (Just fnName)        +        Gtk.tableAttachDefaults table fnLabel 1 2 nextRowNo nextRowNoPlus1+        Gtk.set table [ Gtk.tableChildXOptions fnLabel := []]+        Gtk.miscSetAlignment fnLabel 0 0.5+        -- continue:+        addRows newPrevLabels [] nextRowNoPlus1 (fnNo + 1) 0 restFnNames resultNames+        where+        nextRowNoPlus1 = nextRowNo + 1+        newPrevLabels = (reverse prevLs) : prevLabels+    addRows prevLabels prevLs nextRowNo fnNo dimNo fnNames ((dimName : dimNames) : resultNames) =+        do+        -- add variable label:+        dimLabel <- Gtk.labelNew (Just labelText)+        Gtk.tableAttachDefaults table dimLabel 1 2 nextRowNo nextRowNoPlus1+        Gtk.miscSetAlignment dimLabel 0 0.5+        -- add value label:+        valLabel <- Gtk.labelNew Nothing+        Gtk.tableAttachDefaults table valLabel 2 3 nextRowNo nextRowNoPlus1+        -- add a check button:+        showCheckButton <- Gtk.checkButtonNew+        Gtk.tableAttachDefaults table showCheckButton 0 1 nextRowNo nextRowNoPlus1+        -- make it ticked:+        Gtk.toggleButtonSetActive showCheckButton True+        -- give the check button a handler:+        Gtk.onToggled showCheckButton $+            do+            isActive <- Gtk.toggleButtonGetActive showCheckButton+            state <- atomically $ updateDimActive stateTV fnNo dimNo isActive+            fndatas <- atomically $ readBothTVars fndataTVs+            repaintCanvas (canvas widgets) fndatas state+            return ()+        -- attempt at a simpler rendering:+        Gtk.set table +            [Gtk.tableChildXOptions dimLabel := [], +             Gtk.tableChildXOptions showCheckButton := []]+        -- continue:+        addRows prevLabels (valLabel : prevLs) nextRowNoPlus1 fnNo (dimNo + 1) fnNames (dimNames : resultNames)  +        where+        labelText = " " ++ dimName ++ "(" ++ domName ++ ")="+        nextRowNoPlus1 = nextRowNo + 1+        +updateView ::+    (FA.ERFnApprox box varid domra ranra fa, ERFnGLDrawable box varid domra ranra fa) =>+    Widgets ->+    IORef ERFnViewDynWidgets ->+    (ERFnViewState) ->+    ((FaData fa),+     FnData) ->+    IO ()+updateView widgets dynWidgetsRef state (fadata, fndata) =+    do+    updateValueDisplay widgets dynWidgetsRef state (fadata, fndata)+    repaintCanvas (canvas widgets) (fadata, fndata) state+    return ()++{-| +    update the values shown against variable names+-}+updateValueDisplay ::+    (FA.ERFnApprox box varid domra ranra fa) =>+    Widgets ->+    IORef ERFnViewDynWidgets ->+    (ERFnViewState) ->+    ((FaData fa),+     FnData) ->+    IO ()+updateValueDisplay widgets dynWidgetsRef state (fadata, fndata) =+    do+    evalPointText <- Gtk.entryGetText $ evalPointEntry widgets+    let maybeFnValueTexts = getFnValueTexts evalPointText +    case maybeFnValueTexts of+        Nothing -> do return () -- putStrLn $ "failed to parse eval point: " ++ evalPointText+        Just fnValueTexts ->+            do+            dynWidgets <- readIORef dynWidgetsRef+            mapM (mapM $ uncurry Gtk.labelSetText) $ +                zipWith zip (valueLabels dynWidgets) fnValueTexts+            return ()+    where+    getFnValueTexts evalPointText =+        fmap (eval . RA.double2ra) $ readMaybe evalPointText+        where+--        eval :: (ERIntApprox ira) => ra -> [[String]] +        eval evalPoint =+            map (map show . getDimValueTexts) $ dataFAs fadata+            where+--            getDimValueTexts :: (FA.ERFnApprox box varid domra ranra fa) => fa -> [ra]+            getDimValueTexts fa = +                FA.eval (DBox.unary evalPoint) fa++updateValueDisplayTV widgets dynWidgetsRef fndataTVs stateTV =+    do+--    putStrLn "updateValueDisplayTVERFA"+    (fndatas, state) <- atomically $ readAll3TVars fndataTVs stateTV+    updateValueDisplay widgets dynWidgetsRef state fndatas    +             +dataWatchThread ::+    (FA.ERFnApprox box varid domra ranra fa, ERFnGLDrawable box varid domra ranra fa) =>+    Widgets ->+    IORef ERFnViewDynWidgets ->+    (TVar (FaData fa),+     TVar FnData) ->+    (TVar ERFnViewState) ->+    IO ()+dataWatchThread widgets dynWidgetsRef fndataTVs@(fadataTV, fndataTV) stateTV =+    do+    fndata <- atomically $ readTVar fndataTV+    dataWatchLoop fndata+    where+    dataWatchLoop fndataOld =+        do+        ((dataChange, fndatas@(_, fndata)), state) <- waitForChange fndataOld+        Gtk.timeoutAdd (do { action dataChange fndatas state; return False }) 10+        Concurrent.yield+        case dataChange of+            DataChangeClose -> return ()+            _ -> dataWatchLoop fndata+    action DataChangeClose (fadata, fndata) state =+        do+        return ()+    action DataChangeMeta (fadata, fndata) state =+        do+--        putStrLn $ "DataChangeMeta"+--        putStrLn $ show $ dataFAs fadata+        updateDimWidgets widgets dynWidgetsRef fndata fndataTVs stateTV+        let initialisedState = initState (fadata, fndata)+        atomically $ writeTVar stateTV initialisedState+        updateView widgets dynWidgetsRef initialisedState (fadata, fndata)+    action DataChangeFA (fadata, fndata) state =+        do+--        putStrLn $ "DataChangeFA"+--        putStrLn $ show $ dataFAs fadata+        case favstTrackingDefaultEvalPt state of+            True -> +                Gtk.entrySetText (evalPointEntry widgets) $ +                    show $ (dataDefaultEvalPoint fndata)+            False -> +                return () +        updateView widgets dynWidgetsRef state (fadata, fndata)+    action DataChangeDefaultEvalPoint (fadata, fndata) state =+        do+--        putStrLn $ "DataChangeDefaultEvalPoint"+        case favstTrackingDefaultEvalPt state of+            True ->+                do+                Gtk.entrySetText (evalPointEntry widgets) $ +                    show $ (dataDefaultEvalPoint fndata) +                updateView widgets dynWidgetsRef state (fadata, fndata)+            False -> return ()+    waitForChange fndataOld =+        do+        waitFC fndataOld+        where+        waitFC fndataOld =+            atomically $+            do+            fndata <- readTVar fndataTV+            (change, fndatas) <- +                case fndata == fndataOld of+                    True -> retry+                    False ->+                        case dataFAsUpdated fndata of+                            True ->+                                do+                                fadata <- readTVar fadataTV+                                let change = returnChange fndataOld fndata fadata+                                let fndataNew = fndata { dataFAsUpdated = False }+                                writeTVar fndataTV fndataNew+                                return (change, (fadata, fndataNew))+                            False ->+                                do+                                let change = returnChange fndataOld fndata undefined+                                return (change, (undefined, fndata))+            state <- readTVar stateTV+            return ((change, fndatas), state) +        returnChange fndataOld fndata fadata+            | dataDestroyed fndata =+                DataChangeClose+            | namesChanged = +                DataChangeMeta+            | dataFAsUpdated fndata =+                DataChangeFA+            | evalPtChanged =+                DataChangeDefaultEvalPoint+            | otherwise =+                error $ +                    "ERFnView: returnChange: cannot detect type of change:\n" +                        ++ show fndata ++ "\n" ++ show fndataOld  +            where+            changed field = +                field fndata /= field fndataOld+            namesChanged =+                domNameChanged || resNamesChanged || fnNamesChanged+            domNameChanged = changed dataDomName+            resNamesChanged = changed dataResultNames+            fnNamesChanged = changed dataFnNames +            evalPtChanged = changed dataDefaultEvalPoint+    +data DataChange +    = DataChangeClose -- signals the end...+    | DataChangeMeta -- all change+    | DataChangeFA -- only fn & eval point may have changed+    | DataChangeDefaultEvalPoint -- only eval point has changes++makeCanvas widgets fndataTVs@(fadataTV, fndataTV) stateTV =+    do+    -- create canvas:+    glconfig <- +        GtkGL.glConfigNew +            [GtkGL.GLModeRGBA,+             GtkGL.GLModeDepth,+             GtkGL.GLModeDouble]+    canvas <- GtkGL.glDrawingAreaNew glconfig+    -- set canvas properties:+    Gtk.onRealize canvas $ GtkGL.withGLDrawingArea canvas $ \ _ ->+        do+        GL.clearColor $= (GL.Color4 0.05 0.0 0.2 0.0)+        GL.matrixMode $= GL.Projection+        GL.loadIdentity+        GL.ortho 0.0 1.0 0.0 1.0 (-1.0) 1.0+        GL.depthFunc $= Just GL.Less+        GL.drawBuffer $= GL.BackBuffers+    -- set the canvas repaint handler:+    Gtk.onExpose canvas $ \ event ->+        do+        (fndatas, state) <- atomically $+            do+            fadata <- readTVar fadataTV+            fndata <- readTVar fndataTV+            state <- readTVar stateTV+            return ((fadata, fndata), state)  +        repaintCanvas canvas fndatas state+    -- plug the GL canvas in the GUI:+    Gtk.set (canvasAlignment widgets)+        [ Gtk.containerChild := canvas ]+    return $ widgets { canvas = canvas }+    +repaintCanvas ::+    (FA.ERFnApprox box varid domra ranra fa, ERFnGLDrawable box varid domra ranra fa) =>+    GtkGL.GLDrawingArea ->+    ((FaData fa),+     FnData) ->+    (ERFnViewState) ->+    IO Bool    +repaintCanvas canvas (fadata, fndata) state =+    do+    GtkGL.withGLDrawingArea canvas $ \glwindow ->+        do+        GL.clear [GL.DepthBuffer, GL.ColorBuffer]+        drawFG1 $ zip (dataFAs fadata) (favstActiveDims state)+        drawCoords+        GtkGL.glDrawableSwapBuffers glwindow+    return True+    where+    plotParams = favstPlotParams state+    coordSystem = pltprmCoordSystem plotParams+    drawFG1 [] = return ()+    drawFG1 ((fa, activeDims) : rest) =+        do+        GL.color $ GL.Color3 0.0 0.7 (0.8 :: GL.GLfloat)+        glDraw (plotParams { pltprmPlotDimensions = activeDims }) fa+        drawFG2 rest+    drawFG2 [] = return ()+    drawFG2 ((fa, activeDims) : rest) =+        do+        GL.color $ GL.Color3 0.8 0.4 (0.4 :: GL.GLfloat)+        glDraw (plotParams { pltprmPlotDimensions = activeDims }) fa+        drawFG1 rest+    drawCoords =+        do+        GL.color $ GL.Color3 1 0.2 (0.4 :: GL.GLfloat)+        drawPointLabel 0 0 "0"+        case pltprmCoordSystem plotParams of+            CoordSystemLogSqueeze ->+                do+                mapM drawXmarks $ [0.1, 0.5, 1, 10, 100]+                mapM drawYmarks $ [0.1, 0.5, 1, 2, 5, 10, 100, 1000, 1000000, 1000000000000]+            CoordSystemLinear _ ->+                do+                mapM drawXmarks $ [0.25, 0.5, 0.75, 1] -- TODO: use the rectangle+                mapM drawYmarks $ [0.25, 0.5, 0.75, 1]+        where+        drawXmarks xm =+            do+            drawPointLabel xm 0 (show xm)+            drawPointLabel (-xm) 0 (show $ - xm)+        drawYmarks ym =+            do+            drawPointLabel 0 ym (show ym)+            drawPointLabel 0 (-ym) (show $ - ym)+        drawPointLabel xModel yModel label =+            do+            GL.renderPrimitive GL.Lines $+                do+                GL.vertex $ GL.Vertex3 (x - d) y z  +                GL.vertex $ GL.Vertex3 (x + d) y z+                GL.vertex $ GL.Vertex3 x (y - d) z+                GL.vertex $ GL.Vertex3 x (y + d) z+                GL.vertex $ GL.Vertex3 x y (z - d)+                GL.vertex $ GL.Vertex3 x y (z + d)+                drawLabel (x + 2 * d,y - 2 * d,z) label        +            where+            d = 0.01 :: GL.GLfloat+            (x,y) = translateToCoordSystem coordSystem [xModel, yModel]+            z = 0 +        drawLabel (x,y,z) label =+            do+            GL.rasterPos $ GL.Vertex3 x y z+            GLUT.renderString GLUT.Fixed9By15 label+    
+ src/Data/Number/ER/RnToRm/Plot/GLDrawable.hs view
@@ -0,0 +1,165 @@+{-# LANGUAGE MultiParamTypeClasses  #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE UndecidableInstances   #-}+{-# LANGUAGE FlexibleInstances   #-}+{-|+    Module      :  Data.Number.ER.RnToRm.Plot.GLDrawable+    Description :  plot function enclosures on GL canvas+    Copyright   :  (c) 2007-2008 Michal Konecny+    License     :  BSD3++    Maintainer  :  mik@konecny.aow.cz+    Stability   :  experimental+    Portability :  portable++    Type class for GL plottable function enclosures,+    its default implementation, and instance declarations+    for enclosure types in package AERN-RnToRm. +-}+module Data.Number.ER.RnToRm.Plot.GLDrawable +(+    ERFnGLDrawable(..)+)+where++import qualified Data.Number.ER.RnToRm.Approx as FA+import qualified Data.Number.ER.RnToRm.UnitDom.Approx as UFA+import qualified Data.Number.ER.Real.Approx as RA++import Data.Number.ER.RnToRm.Approx.DomTransl+import Data.Number.ER.RnToRm.Approx.DomEdges+import Data.Number.ER.RnToRm.Approx.Tuple+import Data.Number.ER.RnToRm.Approx.PieceWise++import qualified Data.Number.ER.RnToRm.BisectionTree as BISTR+import qualified Data.Number.ER.Real.DomainBox as DBox+import Data.Number.ER.Real.DomainBox (VariableID(..), DomainBoxMappable, DomainIntBox)+import Data.Number.ER.RnToRm.Plot.Params++import Data.Number.ER.Misc++import qualified Graphics.Rendering.OpenGL as GL++import qualified Data.Map as Map+import qualified Data.List as List++class+    (FA.ERFnDomApprox box varid domra ranra fa) =>+    ERFnGLDrawable box varid domra ranra fa+    | fa -> box varid domra ranra +    where+    {-|+        Plot the function as follows:+        +         * @R -> R^n@: draw @n@ 2D graphs in viewport and colours specified by plot params+          +         * @R^2 -> R^n@: draw @n@ 3D graphs in viewport and colours specified by plot params+     -}+    glDraw :: +        PlotParams ->+        fa -> +        IO ()+    glDraw plotParams f =+        do+--        putStrLn $ show partition+        mapM_ plotEnclosure enclosures+        return ()+        where+        enclosures =+            map (zip partition) $+            List.transpose $+            map pickActiveVals $+            map (\pt -> FA.eval pt f) $+            map (DBox.unary) partition+        partition =+            [domLO] ++ (map iL [1..(segCnt -1)]) ++ [domHI]+            where+            (domLO, domHI) = RA.bounds dom+            dom = +                case DBox.elems $ FA.dom f of+                    [dom] -> dom+                    [] -> RA.bottomApprox+            segCnt = getSegmentCount segPerUnit coordSystem dom+            segCntRA = fromInteger segCnt+            iL i =+                ((segCntRA - iRA) * domLO + iRA * domHI) / segCntRA+                where+                iRA = fromInteger i+        coordSystem = pltprmCoordSystem plotParams+        segPerUnit = pltprmSegsPerUnit plotParams+        activeDimensions = pltprmPlotDimensions plotParams+        pickActiveVals vals =+            fst $ unzip $ filter snd $ zip vals activeDimensions+        plotEnclosure :: +            (RA.ERIntApprox domra, RA.ERIntApprox ranra) => +            [(domra,ranra)] -> +            IO ()+        plotEnclosure interpCoords =+            do+            GL.renderPrimitive GL.LineLoop $+                do+--                putStrLn $ show interpCoords+--                putStrLn $ show $ interpCoordsDoubleUpper ++ interpCoordsDoubleLowerReversed+                mapM_ mkVertexNorm $+                    interpCoordsDoubleUpper ++ interpCoordsDoubleLowerReversed+            where+            interpCoordsDoubleLowerReversed = reverse interpCoordsDoubleLower+            (interpCoordsDoubleLower, interpCoordsDoubleUpper) = +                unzip $ map convertCoords interpCoords+            convertCoords (d,v) +                | RA.isEmpty d =+                    ((0,0),(0,0))+                | RA.isEmpty v =+                    ((dD,0),(dD,0))+                | otherwise =+                    ((dD,vD1),(dD,vD2))+                where+                (vD1,vD2) = RA.doubleBounds v+                dD = snd $ RA.doubleBounds d+        mkVertexNorm (d,v) =+            do+            GL.vertex $ GL.Vertex3 dNorm vNorm 0+            where+            (dNorm, vNorm) =+                translateToCoordSystem coordSystem [d, v]++                +getSegmentCount segPerUnit coordSystem dom +    | RA.isEmpty dom = 0+    | otherwise = +--        unsafePrint ("GLDrawable: getSegmentCount: dom = " ++ show dom ++ " domWidthScreen = " ++ show domWidthScreen) $+        ceiling (segPerUnitRA * domWidthScreen)+    where+    segPerUnitRA = fromInteger $ toInteger $ segPerUnit+    domWidthScreen = min 1 $ domHIScreen - domLOScreen+    (domLOScreen, _) = +        translateToCoordSystem coordSystem [domLO, 0]+    (domHIScreen, _) = +        translateToCoordSystem coordSystem [domHI, 0]+    (domLO, domHI) = RA.doubleBounds dom++instance +    (UFA.ERUnitFnApprox box varid domra ranra ufa,+     DomainIntBox box varid domra,+     DomainBoxMappable dtrbox box varid (DomTransl domra) domra, +     DomainBoxMappable box dtrbox varid domra (DomTransl domra), +     Eq dtrbox) =>+    ERFnGLDrawable box varid domra ranra (ERFnDomTranslApprox dtrbox varid ufa domra)+    +instance+    (FA.ERFnDomApprox box varid domra ranra fa, +     VariableID varid, Show box) =>+    ERFnGLDrawable box varid domra ranra (ERFnDomEdgesApprox varid fa)++instance+    (FA.ERFnDomApprox box varid domra ranra fa) =>+    ERFnGLDrawable box varid domra ranra (ERFnTuple fa)+    +instance+    (ERFnGLDrawable box varid domra ranra fa, RA.ERIntApprox fa, +     Show box, DomainBoxMappable box box varid domra domra) =>+    ERFnGLDrawable box varid domra ranra (ERFnPiecewise box varid domra fa)+    where+    glDraw plotParams (ERFnPiecewise bistr) =+        BISTR.doBistr (\dom -> glDraw plotParams) (Just 15) bistr+        
+ src/Data/Number/ER/RnToRm/Plot/Params.hs view
@@ -0,0 +1,144 @@+{-# LANGUAGE DeriveDataTypeable   #-}+{-|+    Module      :  Data.Number.ER.RnToRm.Plot.Params+    Description :  parameters for function plotting+    Copyright   :  (c) 2007-2008 Michal Konecny+    License     :  BSD3++    Maintainer  :  mik@konecny.aow.cz+    Stability   :  experimental+    Portability :  portable++    Data defining in detail how to plot a function and+    low-level methods related to plotting.+-}+module Data.Number.ER.RnToRm.Plot.Params +(+    PlotParams(..),+    defaultPlotParams,+    CoordSystem(..),+    Rectangle(..),+    translateToCoordSystem+)+where++import Data.Typeable+import Data.Generics.Basics+import Data.Binary++data PlotParams =+    PlotParams+    {+        pltprmCoordSystem :: CoordSystem, +--        pltprmPlotColours :: [GL.Color4 GL.GLfloat],+        pltprmPlotDimensions :: [Bool],+        pltprmSegsPerUnit :: Int+    }+    deriving (Eq, Show, Typeable, Data)+  +{- the following has been generated by BinaryDerive -}     +instance Binary PlotParams where+  put (PlotParams a b c) = put a >> put b >> put c+  get = get >>= \a -> get >>= \b -> get >>= \c -> return (PlotParams a b c)+{- the above has been generated by BinaryDerive -}+  ++data CoordSystem +    = CoordSystemLinear Rectangle+    | CoordSystemLog Rectangle+    | CoordSystemSqueeze+    | CoordSystemLogSqueeze+    deriving (Eq, Ord, Show, Typeable, Data)++data Rectangle =+    Rectangle +    {+        rectTop :: Rational,+        rectBottom :: Rational,+        rectLeft :: Rational,+        rectRight :: Rational+    }+    deriving (Eq, Ord, Show, Typeable, Data)+    +    +{- the following has been generated by BinaryDerive -}+instance Binary CoordSystem where+  put (CoordSystemLinear a) = putWord8 0 >> put a+  put (CoordSystemLog a) = putWord8 1 >> put a+  put CoordSystemSqueeze = putWord8 2+  put CoordSystemLogSqueeze = putWord8 3+  get = do+    tag_ <- getWord8+    case tag_ of+      0 -> get >>= \a -> return (CoordSystemLinear a)+      1 -> get >>= \a -> return (CoordSystemLog a)+      2 -> return CoordSystemSqueeze+      3 -> return CoordSystemLogSqueeze+      _ -> fail "no parse"+instance Binary Rectangle where+  put (Rectangle a b c d) = put a >> put b >> put c >> put d+  get = get >>= \a -> get >>= \b -> get >>= \c -> get >>= \d -> return (Rectangle a b c d)+{- the above has been generated by BinaryDerive -}++    +defaultPlotParams =+    PlotParams+    {+        pltprmCoordSystem = CoordSystemLogSqueeze,+--        pltprmPlotColours = [GL.Color4 1 0.2 (0.4 :: GL.GLfloat) 1],+        pltprmPlotDimensions = replicate 4 True,+        pltprmSegsPerUnit = 100+    }+    +{-|+    Translate a point given by a number of coordinates to+    a 2D point assuming that only result points in the rectangle+    (0,0) --- (1,1) are visible, the origin being at the top left.+-}+translateToCoordSystem ::+    (Floating ra, Ord ra) =>+    CoordSystem ->+    [ra] ->+    (ra, ra)+translateToCoordSystem csys pt =+    case (csys, pt) of+        (CoordSystemLogSqueeze, [x,y]) ->+            (logSqueeze 0.5 x, logSqueeze 0.5 y)+        (CoordSystemLinear (Rectangle t b l r), [x,y]) ->+            (linTransViaRat l r x, +             linTransViaRat b t y)++linTransViaRat r0 r1 x =+    linTransform (fromRational r0) (fromRational r1) x ++linTransform x0 x1 x =+    (x - x0) / (x1 - x0)++logSqueeze v1 =+    (\x -> (x + 1) /2) . (normalise v1) . logScale+    +{-|+    Convert a number from range [-oo,+oo] to+    range (-1,1), mapping 1 to v1.+-}+normalise :: +    (Fractional a, Ord a) => +    a {-^ v1 -} -> +    a {-^ x -} -> +    a+normalise v1 x +    | v1ok && x < 0 = - 1 + a/(a - x)+    | v1ok = 1 - a/(a + x)+    where+    v1ok = 0 < v1 && v1 < 1+    a = (1 - v1) / v1+    +{-|+    Map the range [-oo,oo] to itself with a logarithmic scale.+-}+logScale :: (Floating a, Ord a) => a -> a+logScale x+    | x < 0 = - (logScale (-x))+    | otherwise = log (x + 1)++    
+ src/FnView.glade view
@@ -0,0 +1,466 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">+<!--Generated with glade3 3.4.5 on Wed Oct  1 15:09:10 2008 -->+<glade-interface>+  <widget class="GtkWindow" id="window1">+    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+    <child>+      <widget class="GtkHBox" id="hbox1">+        <property name="visible">True</property>+        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+        <child>+          <widget class="GtkVBox" id="vbox1">+            <property name="visible">True</property>+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+            <child>+              <widget class="GtkFrame" id="frame1">+                <property name="visible">True</property>+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                <property name="label_xalign">0</property>+                <property name="shadow_type">GTK_SHADOW_ETCHED_OUT</property>+                <child>+                  <widget class="GtkAlignment" id="canvasAlignment1">+                    <property name="width_request">500</property>+                    <property name="height_request">500</property>+                    <property name="visible">True</property>+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                    <property name="left_padding">12</property>+                    <child>+                      <placeholder/>+                    </child>+                  </widget>+                </child>+                <child>+                  <widget class="GtkLabel" id="label1">+                    <property name="visible">True</property>+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                    <property name="label" translatable="yes">plot</property>+                  </widget>+                  <packing>+                    <property name="type">label_item</property>+                  </packing>+                </child>+              </widget>+            </child>+            <child>+              <widget class="GtkHBox" id="hbox2">+                <property name="visible">True</property>+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                <child>+                  <widget class="GtkFrame" id="frame2">+                    <property name="visible">True</property>+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                    <property name="label_xalign">0</property>+                    <property name="shadow_type">GTK_SHADOW_ETCHED_OUT</property>+                    <child>+                      <widget class="GtkAlignment" id="alignment2">+                        <property name="visible">True</property>+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                        <property name="left_padding">12</property>+                        <child>+                          <widget class="GtkVBox" id="vbox3">+                            <property name="visible">True</property>+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                            <child>+                              <widget class="GtkComboBox" id="coorSystemCombo1">+                                <property name="visible">True</property>+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                                <property name="items" translatable="yes">log + squeeze+linear</property>+                              </widget>+                            </child>+                            <child>+                              <widget class="GtkHBox" id="hbox6">+                                <property name="visible">True</property>+                                <child>+                                  <placeholder/>+                                </child>+                              </widget>+                              <packing>+                                <property name="position">1</property>+                              </packing>+                            </child>+                            <child>+                              <widget class="GtkHBox" id="hbox7">+                                <property name="visible">True</property>+                                <child>+                                  <placeholder/>+                                </child>+                              </widget>+                              <packing>+                                <property name="position">2</property>+                              </packing>+                            </child>+                          </widget>+                        </child>+                      </widget>+                    </child>+                    <child>+                      <widget class="GtkLabel" id="label2">+                        <property name="visible">True</property>+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                        <property name="label" translatable="yes">coord system</property>+                        <property name="use_markup">True</property>+                      </widget>+                      <packing>+                        <property name="type">label_item</property>+                      </packing>+                    </child>+                  </widget>+                </child>+                <child>+                  <widget class="GtkFrame" id="frame3">+                    <property name="visible">True</property>+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                    <property name="label_xalign">0</property>+                    <property name="shadow_type">GTK_SHADOW_ETCHED_OUT</property>+                    <child>+                      <widget class="GtkAlignment" id="alignment3">+                        <property name="visible">True</property>+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                        <property name="left_padding">12</property>+                        <child>+                          <widget class="GtkTable" id="table2">+                            <property name="visible">True</property>+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                            <property name="n_rows">4</property>+                            <property name="n_columns">1</property>+                            <child>+                              <placeholder/>+                            </child>+                            <child>+                              <widget class="GtkButton" id="defaultZoomPanButton1">+                                <property name="visible">True</property>+                                <property name="can_focus">True</property>+                                <property name="receives_default">True</property>+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                                <property name="label" translatable="yes">set to defaults</property>+                                <property name="response_id">0</property>+                              </widget>+                              <packing>+                                <property name="y_options">GTK_FILL</property>+                              </packing>+                            </child>+                            <child>+                              <widget class="GtkHBox" id="hbox4">+                                <property name="visible">True</property>+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                                <child>+                                  <widget class="GtkLabel" id="label6">+                                    <property name="visible">True</property>+                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                                    <property name="xalign">0</property>+                                    <property name="label" translatable="yes">zoom=</property>+                                  </widget>+                                  <packing>+                                    <property name="expand">False</property>+                                  </packing>+                                </child>+                                <child>+                                  <widget class="GtkEntry" id="zoomEntry1">+                                    <property name="visible">True</property>+                                    <property name="can_focus">True</property>+                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                                    <property name="width_chars">5</property>+                                    <property name="truncate_multiline">True</property>+                                  </widget>+                                  <packing>+                                    <property name="expand">False</property>+                                    <property name="fill">False</property>+                                    <property name="position">1</property>+                                  </packing>+                                </child>+                                <child>+                                  <widget class="GtkLabel" id="label7">+                                    <property name="visible">True</property>+                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                                    <property name="label" translatable="yes">%</property>+                                  </widget>+                                  <packing>+                                    <property name="expand">False</property>+                                    <property name="position">2</property>+                                  </packing>+                                </child>+                              </widget>+                              <packing>+                                <property name="top_attach">1</property>+                                <property name="bottom_attach">2</property>+                                <property name="y_options">GTK_FILL</property>+                              </packing>+                            </child>+                            <child>+                              <widget class="GtkTable" id="table3">+                                <property name="visible">True</property>+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                                <property name="n_rows">2</property>+                                <property name="n_columns">3</property>+                                <child>+                                  <placeholder/>+                                </child>+                                <child>+                                  <placeholder/>+                                </child>+                                <child>+                                  <widget class="GtkLabel" id="label8">+                                    <property name="visible">True</property>+                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                                    <property name="xalign">0</property>+                                    <property name="label" translatable="yes">centre x=</property>+                                  </widget>+                                  <packing>+                                    <property name="x_options">GTK_FILL</property>+                                  </packing>+                                </child>+                                <child>+                                  <widget class="GtkLabel" id="label9">+                                    <property name="visible">True</property>+                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                                    <property name="xalign">0</property>+                                    <property name="label" translatable="yes">centre y=</property>+                                  </widget>+                                  <packing>+                                    <property name="top_attach">1</property>+                                    <property name="bottom_attach">2</property>+                                    <property name="x_options">GTK_FILL</property>+                                  </packing>+                                </child>+                                <child>+                                  <widget class="GtkEntry" id="centreXEntry1">+                                    <property name="visible">True</property>+                                    <property name="can_focus">True</property>+                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                                    <property name="width_chars">5</property>+                                  </widget>+                                  <packing>+                                    <property name="left_attach">1</property>+                                    <property name="right_attach">2</property>+                                    <property name="x_options">GTK_FILL</property>+                                  </packing>+                                </child>+                                <child>+                                  <widget class="GtkEntry" id="centreYEntry1">+                                    <property name="visible">True</property>+                                    <property name="can_focus">True</property>+                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                                    <property name="width_chars">5</property>+                                  </widget>+                                  <packing>+                                    <property name="left_attach">1</property>+                                    <property name="right_attach">2</property>+                                    <property name="top_attach">1</property>+                                    <property name="bottom_attach">2</property>+                                    <property name="x_options">GTK_FILL</property>+                                  </packing>+                                </child>+                              </widget>+                              <packing>+                                <property name="top_attach">2</property>+                                <property name="bottom_attach">3</property>+                                <property name="y_options">GTK_FILL</property>+                              </packing>+                            </child>+                          </widget>+                        </child>+                      </widget>+                    </child>+                    <child>+                      <widget class="GtkLabel" id="label3">+                        <property name="visible">True</property>+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                        <property name="label" translatable="yes">zoom/pan</property>+                        <property name="use_markup">True</property>+                      </widget>+                      <packing>+                        <property name="type">label_item</property>+                      </packing>+                    </child>+                  </widget>+                  <packing>+                    <property name="position">1</property>+                  </packing>+                </child>+              </widget>+              <packing>+                <property name="position">1</property>+              </packing>+            </child>+          </widget>+        </child>+        <child>+          <widget class="GtkVBox" id="vbox2">+            <property name="visible">True</property>+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+            <child>+              <widget class="GtkHBox" id="hbox5">+                <property name="visible">True</property>+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                <child>+                  <widget class="GtkButton" id="defaultEvalPointButton1">+                    <property name="visible">True</property>+                    <property name="can_focus">True</property>+                    <property name="receives_default">True</property>+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                    <property name="label" translatable="yes">default</property>+                    <property name="response_id">0</property>+                  </widget>+                </child>+                <child>+                  <widget class="GtkLabel" id="domVarLabel1">+                    <property name="visible">True</property>+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                    <property name="label" translatable="yes">==</property>+                  </widget>+                  <packing>+                    <property name="position">1</property>+                  </packing>+                </child>+                <child>+                  <widget class="GtkEntry" id="evalPointEntry1">+                    <property name="visible">True</property>+                    <property name="can_focus">True</property>+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                  </widget>+                  <packing>+                    <property name="position">2</property>+                  </packing>+                </child>+              </widget>+              <packing>+                <property name="expand">False</property>+                <property name="padding">2</property>+              </packing>+            </child>+            <child>+              <widget class="GtkTable" id="dimTable1">+                <property name="visible">True</property>+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                <property name="resize_mode">GTK_RESIZE_IMMEDIATE</property>+                <property name="n_rows">4</property>+                <property name="n_columns">3</property>+                <property name="column_spacing">1</property>+                <property name="row_spacing">5</property>+                <child>+                  <placeholder/>+                </child>+                <child>+                  <placeholder/>+                </child>+                <child>+                  <placeholder/>+                </child>+                <child>+                  <placeholder/>+                </child>+                <child>+                  <placeholder/>+                </child>+                <child>+                  <placeholder/>+                </child>+                <child>+                  <placeholder/>+                </child>+                <child>+                  <placeholder/>+                </child>+                <child>+                  <placeholder/>+                </child>+                <child>+                  <placeholder/>+                </child>+                <child>+                  <placeholder/>+                </child>+                <child>+                  <placeholder/>+                </child>+              </widget>+              <packing>+                <property name="expand">False</property>+                <property name="padding">2</property>+                <property name="position">1</property>+              </packing>+            </child>+            <child>+              <placeholder/>+            </child>+            <child>+              <widget class="GtkFrame" id="frame4">+                <property name="visible">True</property>+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                <property name="label_xalign">0</property>+                <property name="shadow_type">GTK_SHADOW_ETCHED_OUT</property>+                <child>+                  <widget class="GtkAlignment" id="alignment1">+                    <property name="visible">True</property>+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                    <property name="left_padding">12</property>+                    <child>+                      <widget class="GtkHBox" id="hbox3">+                        <property name="visible">True</property>+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                        <child>+                          <widget class="GtkButton" id="exportJPGButton1">+                            <property name="can_focus">True</property>+                            <property name="receives_default">True</property>+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                            <property name="label" translatable="yes">jpg</property>+                            <property name="response_id">0</property>+                          </widget>+                        </child>+                        <child>+                          <widget class="GtkButton" id="printTXTButton1">+                            <property name="visible">True</property>+                            <property name="can_focus">True</property>+                            <property name="receives_default">True</property>+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                            <property name="label" translatable="yes">txt</property>+                            <property name="response_id">0</property>+                          </widget>+                          <packing>+                            <property name="position">1</property>+                          </packing>+                        </child>+                        <child>+                          <widget class="GtkVBox" id="vbox4">+                            <property name="visible">True</property>+                            <child>+                              <placeholder/>+                            </child>+                          </widget>+                          <packing>+                            <property name="position">2</property>+                          </packing>+                        </child>+                      </widget>+                    </child>+                  </widget>+                </child>+                <child>+                  <widget class="GtkLabel" id="label4">+                    <property name="visible">True</property>+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                    <property name="label" translatable="yes">export functions</property>+                    <property name="use_markup">True</property>+                  </widget>+                  <packing>+                    <property name="type">label_item</property>+                  </packing>+                </child>+              </widget>+              <packing>+                <property name="expand">False</property>+                <property name="pack_type">GTK_PACK_END</property>+                <property name="position">3</property>+              </packing>+            </child>+          </widget>+          <packing>+            <property name="position">1</property>+          </packing>+        </child>+      </widget>+    </child>+  </widget>+</glade-interface>
+ tests/Demo.hs view
@@ -0,0 +1,113 @@+module Main where++import qualified Data.Number.ER.Real as AERN+import qualified Data.Number.ER.RnToRm as AERNFunc+import qualified Data.Number.ER.RnToRm.Plot.FnView as FNV++import Control.Concurrent as Concurrent+import Control.Concurrent.STM as STM++import qualified Graphics.UI.Gtk as Gtk+import Graphics.UI.Gtk (AttrOp((:=)))+import qualified Graphics.UI.Gtk.Glade as Glade+import qualified Graphics.UI.Gtk.OpenGL as GtkGL+import qualified Graphics.UI.GLUT as GLUT++type B = AERN.BM+--type B = AERN.BMPFR+type RA = AERN.RA B+type IRA = AERN.IRA B+type FA = AERNFunc.FAPWP B+type Box a = AERNFunc.Box a+type VarID = AERNFunc.VarID++main =+    do+    AERN.initialiseBaseArithmetic (0 :: RA)+    initGtkGL    +    fadataTV <- newTVarIO faData+    fndataTV <- newTVarIO FNV.defaultFnData+    fnviewWindow <- FNV.new (fadataTV, fndataTV) Nothing+    forkIO $ signalData fndataTV+    Gtk.mainGUI+    +faData = +    FNV.defaultFaData+    {+        FNV.dataFAs = [f1,f2]+    }++f1 = AERN.cos ix $ g -- cos(10x)+f2 = AERNFunc.integrateUnary 3 f1 dom 0 [-1] -- integ(cos(10x)) - 1+ix = 16++g = AERNFunc.scale 10 x++x :: FA+x =+    AERNFunc.bisectUnbisectDepth 5 $+    AERNFunc.setMaxDegree 3 $+    AERNFunc.proj xdom 0++xdom = AERNFunc.fromAscList [(0, dom)]+    +const01 :: FA+const01 =+    AERNFunc.const xdom [0 AERN.\/ 1]+    +dom = domL AERN.\/ domR+(domL, domR) = (-1, 1)+(valLO, valHI) = (-2,2) ++fnData =+    setExtents domL domR valLO valHI $ +    FNV.defaultFnData+    {+        FNV.dataFAsUpdated = True,+        FNV.dataDomName = "x",+        FNV.dataFnNames = ["f1","f2"],+        FNV.dataResultNames = [["y1"],["y2"]],+        FNV.dataDefaultEvalPoint = 0    +    }++setExtents left right bot top fnData =+    fnData+    {+        FNV.dataDomL = td left,+        FNV.dataDomR = td right,+        FNV.dataValLO = td bot,+        FNV.dataValHI = td top,+        FNV.dataDefaultPlotParams =+            FNV.defaultPlotParams+            {+                FNV.pltprmCoordSystem = +                    FNV.CoordSystemLinear $+                        FNV.Rectangle +                            (tr $ top + 0.1) +                            (tr $ bot - 0.1) +                            (tr $ left - 0.1) +                            (tr $ right + 0.1) +            }        +    }+    where+    tr = toRational . td+    td = fst . AERN.doubleBounds++initGtkGL =+    do+    Gtk.initGUI+    -- enable multithreaded GUI:+    Gtk.timeoutAddFull +        (Concurrent.yield >> Concurrent.yield >> Concurrent.yield >> return True) +        Gtk.priorityDefaultIdle 20+      -- see http://haskell.org/gtk2hs/archives/2005/07/24/writing-multi-threaded-guis/+    GtkGL.initGL+    GLUT.initialize "AERN Function View" [] -- needed for text in GL canvas+    +signalData fndataTV =+    do+    threadDelay 200000 -- 0.2s+    atomically $+        do+        writeTVar fndataTV fnData+    
+ tests/FnView.glade view
@@ -0,0 +1,466 @@+<?xml version="1.0" encoding="UTF-8" standalone="no"?>+<!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">+<!--Generated with glade3 3.4.5 on Wed Oct  1 15:09:10 2008 -->+<glade-interface>+  <widget class="GtkWindow" id="window1">+    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+    <child>+      <widget class="GtkHBox" id="hbox1">+        <property name="visible">True</property>+        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+        <child>+          <widget class="GtkVBox" id="vbox1">+            <property name="visible">True</property>+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+            <child>+              <widget class="GtkFrame" id="frame1">+                <property name="visible">True</property>+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                <property name="label_xalign">0</property>+                <property name="shadow_type">GTK_SHADOW_ETCHED_OUT</property>+                <child>+                  <widget class="GtkAlignment" id="canvasAlignment1">+                    <property name="width_request">500</property>+                    <property name="height_request">500</property>+                    <property name="visible">True</property>+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                    <property name="left_padding">12</property>+                    <child>+                      <placeholder/>+                    </child>+                  </widget>+                </child>+                <child>+                  <widget class="GtkLabel" id="label1">+                    <property name="visible">True</property>+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                    <property name="label" translatable="yes">plot</property>+                  </widget>+                  <packing>+                    <property name="type">label_item</property>+                  </packing>+                </child>+              </widget>+            </child>+            <child>+              <widget class="GtkHBox" id="hbox2">+                <property name="visible">True</property>+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                <child>+                  <widget class="GtkFrame" id="frame2">+                    <property name="visible">True</property>+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                    <property name="label_xalign">0</property>+                    <property name="shadow_type">GTK_SHADOW_ETCHED_OUT</property>+                    <child>+                      <widget class="GtkAlignment" id="alignment2">+                        <property name="visible">True</property>+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                        <property name="left_padding">12</property>+                        <child>+                          <widget class="GtkVBox" id="vbox3">+                            <property name="visible">True</property>+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                            <child>+                              <widget class="GtkComboBox" id="coorSystemCombo1">+                                <property name="visible">True</property>+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                                <property name="items" translatable="yes">log + squeeze+linear</property>+                              </widget>+                            </child>+                            <child>+                              <widget class="GtkHBox" id="hbox6">+                                <property name="visible">True</property>+                                <child>+                                  <placeholder/>+                                </child>+                              </widget>+                              <packing>+                                <property name="position">1</property>+                              </packing>+                            </child>+                            <child>+                              <widget class="GtkHBox" id="hbox7">+                                <property name="visible">True</property>+                                <child>+                                  <placeholder/>+                                </child>+                              </widget>+                              <packing>+                                <property name="position">2</property>+                              </packing>+                            </child>+                          </widget>+                        </child>+                      </widget>+                    </child>+                    <child>+                      <widget class="GtkLabel" id="label2">+                        <property name="visible">True</property>+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                        <property name="label" translatable="yes">coord system</property>+                        <property name="use_markup">True</property>+                      </widget>+                      <packing>+                        <property name="type">label_item</property>+                      </packing>+                    </child>+                  </widget>+                </child>+                <child>+                  <widget class="GtkFrame" id="frame3">+                    <property name="visible">True</property>+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                    <property name="label_xalign">0</property>+                    <property name="shadow_type">GTK_SHADOW_ETCHED_OUT</property>+                    <child>+                      <widget class="GtkAlignment" id="alignment3">+                        <property name="visible">True</property>+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                        <property name="left_padding">12</property>+                        <child>+                          <widget class="GtkTable" id="table2">+                            <property name="visible">True</property>+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                            <property name="n_rows">4</property>+                            <property name="n_columns">1</property>+                            <child>+                              <placeholder/>+                            </child>+                            <child>+                              <widget class="GtkButton" id="defaultZoomPanButton1">+                                <property name="visible">True</property>+                                <property name="can_focus">True</property>+                                <property name="receives_default">True</property>+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                                <property name="label" translatable="yes">set to defaults</property>+                                <property name="response_id">0</property>+                              </widget>+                              <packing>+                                <property name="y_options">GTK_FILL</property>+                              </packing>+                            </child>+                            <child>+                              <widget class="GtkHBox" id="hbox4">+                                <property name="visible">True</property>+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                                <child>+                                  <widget class="GtkLabel" id="label6">+                                    <property name="visible">True</property>+                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                                    <property name="xalign">0</property>+                                    <property name="label" translatable="yes">zoom=</property>+                                  </widget>+                                  <packing>+                                    <property name="expand">False</property>+                                  </packing>+                                </child>+                                <child>+                                  <widget class="GtkEntry" id="zoomEntry1">+                                    <property name="visible">True</property>+                                    <property name="can_focus">True</property>+                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                                    <property name="width_chars">5</property>+                                    <property name="truncate_multiline">True</property>+                                  </widget>+                                  <packing>+                                    <property name="expand">False</property>+                                    <property name="fill">False</property>+                                    <property name="position">1</property>+                                  </packing>+                                </child>+                                <child>+                                  <widget class="GtkLabel" id="label7">+                                    <property name="visible">True</property>+                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                                    <property name="label" translatable="yes">%</property>+                                  </widget>+                                  <packing>+                                    <property name="expand">False</property>+                                    <property name="position">2</property>+                                  </packing>+                                </child>+                              </widget>+                              <packing>+                                <property name="top_attach">1</property>+                                <property name="bottom_attach">2</property>+                                <property name="y_options">GTK_FILL</property>+                              </packing>+                            </child>+                            <child>+                              <widget class="GtkTable" id="table3">+                                <property name="visible">True</property>+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                                <property name="n_rows">2</property>+                                <property name="n_columns">3</property>+                                <child>+                                  <placeholder/>+                                </child>+                                <child>+                                  <placeholder/>+                                </child>+                                <child>+                                  <widget class="GtkLabel" id="label8">+                                    <property name="visible">True</property>+                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                                    <property name="xalign">0</property>+                                    <property name="label" translatable="yes">centre x=</property>+                                  </widget>+                                  <packing>+                                    <property name="x_options">GTK_FILL</property>+                                  </packing>+                                </child>+                                <child>+                                  <widget class="GtkLabel" id="label9">+                                    <property name="visible">True</property>+                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                                    <property name="xalign">0</property>+                                    <property name="label" translatable="yes">centre y=</property>+                                  </widget>+                                  <packing>+                                    <property name="top_attach">1</property>+                                    <property name="bottom_attach">2</property>+                                    <property name="x_options">GTK_FILL</property>+                                  </packing>+                                </child>+                                <child>+                                  <widget class="GtkEntry" id="centreXEntry1">+                                    <property name="visible">True</property>+                                    <property name="can_focus">True</property>+                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                                    <property name="width_chars">5</property>+                                  </widget>+                                  <packing>+                                    <property name="left_attach">1</property>+                                    <property name="right_attach">2</property>+                                    <property name="x_options">GTK_FILL</property>+                                  </packing>+                                </child>+                                <child>+                                  <widget class="GtkEntry" id="centreYEntry1">+                                    <property name="visible">True</property>+                                    <property name="can_focus">True</property>+                                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                                    <property name="width_chars">5</property>+                                  </widget>+                                  <packing>+                                    <property name="left_attach">1</property>+                                    <property name="right_attach">2</property>+                                    <property name="top_attach">1</property>+                                    <property name="bottom_attach">2</property>+                                    <property name="x_options">GTK_FILL</property>+                                  </packing>+                                </child>+                              </widget>+                              <packing>+                                <property name="top_attach">2</property>+                                <property name="bottom_attach">3</property>+                                <property name="y_options">GTK_FILL</property>+                              </packing>+                            </child>+                          </widget>+                        </child>+                      </widget>+                    </child>+                    <child>+                      <widget class="GtkLabel" id="label3">+                        <property name="visible">True</property>+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                        <property name="label" translatable="yes">zoom/pan</property>+                        <property name="use_markup">True</property>+                      </widget>+                      <packing>+                        <property name="type">label_item</property>+                      </packing>+                    </child>+                  </widget>+                  <packing>+                    <property name="position">1</property>+                  </packing>+                </child>+              </widget>+              <packing>+                <property name="position">1</property>+              </packing>+            </child>+          </widget>+        </child>+        <child>+          <widget class="GtkVBox" id="vbox2">+            <property name="visible">True</property>+            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+            <child>+              <widget class="GtkHBox" id="hbox5">+                <property name="visible">True</property>+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                <child>+                  <widget class="GtkButton" id="defaultEvalPointButton1">+                    <property name="visible">True</property>+                    <property name="can_focus">True</property>+                    <property name="receives_default">True</property>+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                    <property name="label" translatable="yes">default</property>+                    <property name="response_id">0</property>+                  </widget>+                </child>+                <child>+                  <widget class="GtkLabel" id="domVarLabel1">+                    <property name="visible">True</property>+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                    <property name="label" translatable="yes">==</property>+                  </widget>+                  <packing>+                    <property name="position">1</property>+                  </packing>+                </child>+                <child>+                  <widget class="GtkEntry" id="evalPointEntry1">+                    <property name="visible">True</property>+                    <property name="can_focus">True</property>+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                  </widget>+                  <packing>+                    <property name="position">2</property>+                  </packing>+                </child>+              </widget>+              <packing>+                <property name="expand">False</property>+                <property name="padding">2</property>+              </packing>+            </child>+            <child>+              <widget class="GtkTable" id="dimTable1">+                <property name="visible">True</property>+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                <property name="resize_mode">GTK_RESIZE_IMMEDIATE</property>+                <property name="n_rows">4</property>+                <property name="n_columns">3</property>+                <property name="column_spacing">1</property>+                <property name="row_spacing">5</property>+                <child>+                  <placeholder/>+                </child>+                <child>+                  <placeholder/>+                </child>+                <child>+                  <placeholder/>+                </child>+                <child>+                  <placeholder/>+                </child>+                <child>+                  <placeholder/>+                </child>+                <child>+                  <placeholder/>+                </child>+                <child>+                  <placeholder/>+                </child>+                <child>+                  <placeholder/>+                </child>+                <child>+                  <placeholder/>+                </child>+                <child>+                  <placeholder/>+                </child>+                <child>+                  <placeholder/>+                </child>+                <child>+                  <placeholder/>+                </child>+              </widget>+              <packing>+                <property name="expand">False</property>+                <property name="padding">2</property>+                <property name="position">1</property>+              </packing>+            </child>+            <child>+              <placeholder/>+            </child>+            <child>+              <widget class="GtkFrame" id="frame4">+                <property name="visible">True</property>+                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                <property name="label_xalign">0</property>+                <property name="shadow_type">GTK_SHADOW_ETCHED_OUT</property>+                <child>+                  <widget class="GtkAlignment" id="alignment1">+                    <property name="visible">True</property>+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                    <property name="left_padding">12</property>+                    <child>+                      <widget class="GtkHBox" id="hbox3">+                        <property name="visible">True</property>+                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                        <child>+                          <widget class="GtkButton" id="exportJPGButton1">+                            <property name="can_focus">True</property>+                            <property name="receives_default">True</property>+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                            <property name="label" translatable="yes">jpg</property>+                            <property name="response_id">0</property>+                          </widget>+                        </child>+                        <child>+                          <widget class="GtkButton" id="printTXTButton1">+                            <property name="visible">True</property>+                            <property name="can_focus">True</property>+                            <property name="receives_default">True</property>+                            <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                            <property name="label" translatable="yes">txt</property>+                            <property name="response_id">0</property>+                          </widget>+                          <packing>+                            <property name="position">1</property>+                          </packing>+                        </child>+                        <child>+                          <widget class="GtkVBox" id="vbox4">+                            <property name="visible">True</property>+                            <child>+                              <placeholder/>+                            </child>+                          </widget>+                          <packing>+                            <property name="position">2</property>+                          </packing>+                        </child>+                      </widget>+                    </child>+                  </widget>+                </child>+                <child>+                  <widget class="GtkLabel" id="label4">+                    <property name="visible">True</property>+                    <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>+                    <property name="label" translatable="yes">export functions</property>+                    <property name="use_markup">True</property>+                  </widget>+                  <packing>+                    <property name="type">label_item</property>+                  </packing>+                </child>+              </widget>+              <packing>+                <property name="expand">False</property>+                <property name="pack_type">GTK_PACK_END</property>+                <property name="position">3</property>+              </packing>+            </child>+          </widget>+          <packing>+            <property name="position">1</property>+          </packing>+        </child>+      </widget>+    </child>+  </widget>+</glade-interface>