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 +46/−0
- ChangeLog +2/−0
- LICENCE +30/−0
- README.glade +2/−0
- Setup.lhs +3/−0
- src/Data/Number/ER/MiscSTM.hs +31/−0
- src/Data/Number/ER/RnToRm/Plot/FnView.hs +765/−0
- src/Data/Number/ER/RnToRm/Plot/GLDrawable.hs +165/−0
- src/Data/Number/ER/RnToRm/Plot/Params.hs +144/−0
- src/FnView.glade +466/−0
- tests/Demo.hs +113/−0
- tests/FnView.glade +466/−0
+ 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>