packages feed

plot-gtk-ui (empty) → 0.0.1.0

raw patch · 10 files changed

+2136/−0 lines, 10 filesdep +basedep +cairodep +coloursetup-changed

Dependencies added: base, cairo, colour, fixed-vector, gtk, hmatrix, plot, text, vector

Files

+ LICENSE view
@@ -0,0 +1,339 @@+		    GNU GENERAL PUBLIC LICENSE+		       Version 2, June 1991++ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA+ Everyone is permitted to copy and distribute verbatim copies+ of this license document, but changing it is not allowed.++			    Preamble++  The licenses for most software are designed to take away your+freedom to share and change it.  By contrast, the GNU General Public+License is intended to guarantee your freedom to share and change free+software--to make sure the software is free for all its users.  This+General Public License applies to most of the Free Software+Foundation's software and to any other program whose authors commit to+using it.  (Some other Free Software Foundation software is covered by+the GNU Lesser General Public License instead.)  You can apply it to+your programs, too.++  When we speak of free software, we are referring to freedom, not+price.  Our General Public Licenses are designed to make sure that you+have the freedom to distribute copies of free software (and charge for+this service if you wish), that you receive source code or can get it+if you want it, that you can change the software or use pieces of it+in new free programs; and that you know you can do these things.++  To protect your rights, we need to make restrictions that forbid+anyone to deny you these rights or to ask you to surrender the rights.+These restrictions translate to certain responsibilities for you if you+distribute copies of the software, or if you modify it.++  For example, if you distribute copies of such a program, whether+gratis or for a fee, you must give the recipients all the rights that+you have.  You must make sure that they, too, receive or can get the+source code.  And you must show them these terms so they know their+rights.++  We protect your rights with two steps: (1) copyright the software, and+(2) offer you this license which gives you legal permission to copy,+distribute and/or modify the software.++  Also, for each author's protection and ours, we want to make certain+that everyone understands that there is no warranty for this free+software.  If the software is modified by someone else and passed on, we+want its recipients to know that what they have is not the original, so+that any problems introduced by others will not reflect on the original+authors' reputations.++  Finally, any free program is threatened constantly by software+patents.  We wish to avoid the danger that redistributors of a free+program will individually obtain patent licenses, in effect making the+program proprietary.  To prevent this, we have made it clear that any+patent must be licensed for everyone's free use or not licensed at all.++  The precise terms and conditions for copying, distribution and+modification follow.++		    GNU GENERAL PUBLIC LICENSE+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION++  0. This License applies to any program or other work which contains+a notice placed by the copyright holder saying it may be distributed+under the terms of this General Public License.  The "Program", below,+refers to any such program or work, and a "work based on the Program"+means either the Program or any derivative work under copyright law:+that is to say, a work containing the Program or a portion of it,+either verbatim or with modifications and/or translated into another+language.  (Hereinafter, translation is included without limitation in+the term "modification".)  Each licensee is addressed as "you".++Activities other than copying, distribution and modification are not+covered by this License; they are outside its scope.  The act of+running the Program is not restricted, and the output from the Program+is covered only if its contents constitute a work based on the+Program (independent of having been made by running the Program).+Whether that is true depends on what the Program does.++  1. You may copy and distribute verbatim copies of the Program's+source code as you receive it, in any medium, provided that you+conspicuously and appropriately publish on each copy an appropriate+copyright notice and disclaimer of warranty; keep intact all the+notices that refer to this License and to the absence of any warranty;+and give any other recipients of the Program a copy of this License+along with the Program.++You may charge a fee for the physical act of transferring a copy, and+you may at your option offer warranty protection in exchange for a fee.++  2. You may modify your copy or copies of the Program or any portion+of it, thus forming a work based on the Program, and copy and+distribute such modifications or work under the terms of Section 1+above, provided that you also meet all of these conditions:++    a) You must cause the modified files to carry prominent notices+    stating that you changed the files and the date of any change.++    b) You must cause any work that you distribute or publish, that in+    whole or in part contains or is derived from the Program or any+    part thereof, to be licensed as a whole at no charge to all third+    parties under the terms of this License.++    c) If the modified program normally reads commands interactively+    when run, you must cause it, when started running for such+    interactive use in the most ordinary way, to print or display an+    announcement including an appropriate copyright notice and a+    notice that there is no warranty (or else, saying that you provide+    a warranty) and that users may redistribute the program under+    these conditions, and telling the user how to view a copy of this+    License.  (Exception: if the Program itself is interactive but+    does not normally print such an announcement, your work based on+    the Program is not required to print an announcement.)++These requirements apply to the modified work as a whole.  If+identifiable sections of that work are not derived from the Program,+and can be reasonably considered independent and separate works in+themselves, then this License, and its terms, do not apply to those+sections when you distribute them as separate works.  But when you+distribute the same sections as part of a whole which is a work based+on the Program, the distribution of the whole must be on the terms of+this License, whose permissions for other licensees extend to the+entire whole, and thus to each and every part regardless of who wrote it.++Thus, it is not the intent of this section to claim rights or contest+your rights to work written entirely by you; rather, the intent is to+exercise the right to control the distribution of derivative or+collective works based on the Program.++In addition, mere aggregation of another work not based on the Program+with the Program (or with a work based on the Program) on a volume of+a storage or distribution medium does not bring the other work under+the scope of this License.++  3. You may copy and distribute the Program (or a work based on it,+under Section 2) in object code or executable form under the terms of+Sections 1 and 2 above provided that you also do one of the following:++    a) Accompany it with the complete corresponding machine-readable+    source code, which must be distributed under the terms of Sections+    1 and 2 above on a medium customarily used for software interchange; or,++    b) Accompany it with a written offer, valid for at least three+    years, to give any third party, for a charge no more than your+    cost of physically performing source distribution, a complete+    machine-readable copy of the corresponding source code, to be+    distributed under the terms of Sections 1 and 2 above on a medium+    customarily used for software interchange; or,++    c) Accompany it with the information you received as to the offer+    to distribute corresponding source code.  (This alternative is+    allowed only for noncommercial distribution and only if you+    received the program in object code or executable form with such+    an offer, in accord with Subsection b above.)++The source code for a work means the preferred form of the work for+making modifications to it.  For an executable work, complete source+code means all the source code for all modules it contains, plus any+associated interface definition files, plus the scripts used to+control compilation and installation of the executable.  However, as a+special exception, the source code distributed need not include+anything that is normally distributed (in either source or binary+form) with the major components (compiler, kernel, and so on) of the+operating system on which the executable runs, unless that component+itself accompanies the executable.++If distribution of executable or object code is made by offering+access to copy from a designated place, then offering equivalent+access to copy the source code from the same place counts as+distribution of the source code, even though third parties are not+compelled to copy the source along with the object code.++  4. You may not copy, modify, sublicense, or distribute the Program+except as expressly provided under this License.  Any attempt+otherwise to copy, modify, sublicense or distribute the Program is+void, and will automatically terminate your rights under this License.+However, parties who have received copies, or rights, from you under+this License will not have their licenses terminated so long as such+parties remain in full compliance.++  5. You are not required to accept this License, since you have not+signed it.  However, nothing else grants you permission to modify or+distribute the Program or its derivative works.  These actions are+prohibited by law if you do not accept this License.  Therefore, by+modifying or distributing the Program (or any work based on the+Program), you indicate your acceptance of this License to do so, and+all its terms and conditions for copying, distributing or modifying+the Program or works based on it.++  6. Each time you redistribute the Program (or any work based on the+Program), the recipient automatically receives a license from the+original licensor to copy, distribute or modify the Program subject to+these terms and conditions.  You may not impose any further+restrictions on the recipients' exercise of the rights granted herein.+You are not responsible for enforcing compliance by third parties to+this License.++  7. If, as a consequence of a court judgment or allegation of patent+infringement or for any other reason (not limited to patent issues),+conditions are imposed on you (whether by court order, agreement or+otherwise) that contradict the conditions of this License, they do not+excuse you from the conditions of this License.  If you cannot+distribute so as to satisfy simultaneously your obligations under this+License and any other pertinent obligations, then as a consequence you+may not distribute the Program at all.  For example, if a patent+license would not permit royalty-free redistribution of the Program by+all those who receive copies directly or indirectly through you, then+the only way you could satisfy both it and this License would be to+refrain entirely from distribution of the Program.++If any portion of this section is held invalid or unenforceable under+any particular circumstance, the balance of the section is intended to+apply and the section as a whole is intended to apply in other+circumstances.++It is not the purpose of this section to induce you to infringe any+patents or other property right claims or to contest validity of any+such claims; this section has the sole purpose of protecting the+integrity of the free software distribution system, which is+implemented by public license practices.  Many people have made+generous contributions to the wide range of software distributed+through that system in reliance on consistent application of that+system; it is up to the author/donor to decide if he or she is willing+to distribute software through any other system and a licensee cannot+impose that choice.++This section is intended to make thoroughly clear what is believed to+be a consequence of the rest of this License.++  8. If the distribution and/or use of the Program is restricted in+certain countries either by patents or by copyrighted interfaces, the+original copyright holder who places the Program under this License+may add an explicit geographical distribution limitation excluding+those countries, so that distribution is permitted only in or among+countries not thus excluded.  In such case, this License incorporates+the limitation as if written in the body of this License.++  9. The Free Software Foundation may publish revised and/or new versions+of the General Public License from time to time.  Such new versions will+be similar in spirit to the present version, but may differ in detail to+address new problems or concerns.++Each version is given a distinguishing version number.  If the Program+specifies a version number of this License which applies to it and "any+later version", you have the option of following the terms and conditions+either of that version or of any later version published by the Free+Software Foundation.  If the Program does not specify a version number of+this License, you may choose any version ever published by the Free Software+Foundation.++  10. If you wish to incorporate parts of the Program into other free+programs whose distribution conditions are different, write to the author+to ask for permission.  For software which is copyrighted by the Free+Software Foundation, write to the Free Software Foundation; we sometimes+make exceptions for this.  Our decision will be guided by the two goals+of preserving the free status of all derivatives of our free software and+of promoting the sharing and reuse of software generally.++			    NO WARRANTY++  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,+REPAIR OR CORRECTION.++  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE+POSSIBILITY OF SUCH DAMAGES.++		     END OF TERMS AND CONDITIONS++	    How to Apply These Terms to Your New Programs++  If you develop a new program, and you want it to be of the greatest+possible use to the public, the best way to achieve this is to make it+free software which everyone can redistribute and change under these terms.++  To do so, attach the following notices to the program.  It is safest+to attach them to the start of each source file to most effectively+convey the exclusion of warranty; and each file should have at least+the "copyright" line and a pointer to where the full notice is found.++    <one line to give the program's name and a brief idea of what it does.>+    Copyright (C) <year>  <name of author>++    This program is free software; you can redistribute it and/or modify+    it under the terms of the GNU General Public License as published by+    the Free Software Foundation; either version 2 of the License, or+    (at your option) any later version.++    This program is distributed in the hope that it will be useful,+    but WITHOUT ANY WARRANTY; without even the implied warranty of+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the+    GNU General Public License for more details.++    You should have received a copy of the GNU General Public License along+    with this program; if not, write to the Free Software Foundation, Inc.,+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.++Also add information on how to contact you by electronic and paper mail.++If the program is interactive, make it output a short notice like this+when it starts in an interactive mode:++    Gnomovision version 69, Copyright (C) year name of author+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.+    This is free software, and you are welcome to redistribute it+    under certain conditions; type `show c' for details.++The hypothetical commands `show w' and `show c' should show the appropriate+parts of the General Public License.  Of course, the commands you use may+be called something other than `show w' and `show c'; they could even be+mouse-clicks or menu items--whatever suits your program.++You should also get your employer (if you work as a programmer) or your+school, if any, to sign a "copyright disclaimer" for the program, if+necessary.  Here is a sample; alter the names:++  Yoyodyne, Inc., hereby disclaims all copyright interest in the program+  `Gnomovision' (which makes passes at compilers) written by James Hacker.++  <signature of Ty Coon>, 1 April 1989+  Ty Coon, President of Vice++This General Public License does not permit incorporating your program into+proprietary programs.  If your program is a subroutine library, you may+consider it more useful to permit linking proprietary applications with the+library.  If this is what you want to do, use the GNU Lesser General+Public License instead of this License.
+ README.md view
@@ -0,0 +1,84 @@+# plot-gtk-ui++An ambitious attempt to provide mathematica like dynamic plotting for free.++## Installation++### Linux++The installation for gtk requires that+[gtk2hs-buildtools](https://hackage.haskell.org/package/gtk2hs-buildtools)+be installed, and the binary be in your $PATH.  The below commands take+care of that, without permanently changing the $PATH.++```bash+$ cabal update+$ cabal install gtk2hs-buildtools+$ env PATH="~/.cabal/bin:$PATH" cabal install plot-gtk-ui+```++### Windows++* Install gtk2hs with instructions from+  [here](http://projects.haskell.org/gtk2hs/download/#Windows).++* Then use cabal to install `plot-gtk-ui`.++```batch+cmd> cabal install plot-gtk-ui+```++## Usage++Import `Graphics.Rendering.Plot.Gtk.UI` and follow the examples below. ++```haskell+import Graphics.UI.Gtk+import Graphics.Rendering.Plot.Gtk.UI++main = do+  initGUI+  plotStatic sin (-pi, pi)+  -- Plot sin(x) from -pi to pi+  mainGUI+```++![sinx](screenshots/sinx.png)++Another simple example.++```haskell+import Graphics.UI.Gtk+import Graphics.Rendering.Plot.Gtk.UI++main = do+  initGUI+  plotDynamic (\(x, a) -> sin(a * x)) ((-pi, pi), (0, 1))+  -- Plot sin(a * x), where 'x' ranges from -pi to+  -- pi and 'a' ranges between 0 to 1+  mainGUI+```++![sinax](screenshots/sinax.png)++## Errors++The error messages might not be completely correct, as there is not a good way to diagnose what caused the error.++Issues that cause errors:++- Invalid ranges, e.g. X-Range = `(1, -1)`+- Automatic-determination of ranges resulting in unplottable ranges, e.g. `(0, 0)`++If you land on the "grey screen of on plots" or any other incorrect error message, please raise an issue here.++## Implementation++The `plotStatic` and `plotDynamic` functions are implemented in a+type-safe manner using `fixed-vector`.++It also allows one to write functions using appropriate tuples as in the+above examples.++Plotting is done using the excellent [plot](https://github.com/amcphail/plot)+package.
+ Setup.lhs view
@@ -0,0 +1,3 @@+#! /usr/bin/env runhaskell+> import Distribution.Simple+> main = defaultMain
+ lib/Graphics/Rendering/Plot/Gtk/UI.hs view
@@ -0,0 +1,96 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  Graphics.Rendering.Plot.Gtk.UI+-- Copyright   :  (c) Sumit Sahrawat+-- License     :  GPL-2+--+-- Maintainer  :  sumit.sahrawat.apm13@iitbhu.ac.in+-- Stability   :  provisional+-- Portability :  portable+--+-- Quick plotting for functions + dynamic plotting of functions+--+-- 'plotStatic' can be used to plot functions of the form /f(x)=.../+--+-- 'plotDynamic' can be used to plot functions of the form /f(x, a, b) =+-- .../ where /a/ and /b/ are additional parameters. Sliders are+-- provided for manipulating the values of /a/ and /b/, and the plot is+-- animated in real-time.+--+--------------------------------------------------------------------------------+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeFamilies     #-}++module Graphics.Rendering.Plot.Gtk.UI+    ( plotStatic+    , plotDynamic+    ) where++--------------------------------------------------------------------------------+-- Standard Libraries++import           Data.IORef                                (newIORef)++--------------------------------------------------------------------------------+-- Other Libraries++import           Data.Vector.Fixed                         (Dim, S, Vector, Z)+import qualified Data.Vector.Fixed                         as V+import           Data.Vector.Fixed.Unboxed                 (Vec)++--------------------------------------------------------------------------------+-- Custom Modules++import           Paths_plot_gtk_ui                         (getDataFileName)+import           Graphics.Rendering.Plot.Gtk.UI.PlotWindow+import           Graphics.Rendering.Plot.Gtk.UI.Settings++--------------------------------------------------------------------------------++defSet :: FigureSettings+defSet = defaultFigureSettings++--------------------------------------------------------------------------------++-- | Quickly create AdjustmentSettings+argRange :: (Double, Double)    -- ^ Lower and upper range+         -> AdjustmentSettings+argRange (x, y) = aSetRange ((x + y) / 2) x y++--------------------------------------------------------------------------------++-- | Plots functions of multiple arguments, provided all arguments+-- have specified ranges.+plot :: ([Double] -> Double -> Double) -- ^ Function+     -> [(Double, Double)]             -- ^ Ranges for all but the primary arg+     -> FigureSettings                 -- ^ Should contain the primary range+     -> IO ()+plot func rangeTail fset = do+  iofset    <- newIORef fset+  plotGlade <- getDataFileName "plot-window.glade"+  plotWindow plotGlade iofset (map argRange rangeTail) func++--------------------------------------------------------------------------------++-- | Plot functions that don't depend on extra parameters+plotStatic :: (Double -> Double) -- ^ Function to plot+           -> (Double, Double)   -- ^ Range for abscissa (horizontal axis)+           -> IO ()+plotStatic func r =+  let f :: Vec (S Z) Double -> Double+      f = func . V.head+  in plotDynamic f ((V.convert . V.Only $ r) :: Vec (S Z) (Double, Double))++--------------------------------------------------------------------------------++-- | Plot functions that depend on extra parameters+plotDynamic :: (Vector u a, Vector v (a, a),+                a ~ Double, Dim u ~ Dim v, Dim v ~ S n, V.Arity n)+            => (u Double -> Double)+            -> v (Double, Double)+            -> IO ()+plotDynamic func ranges = let (x:xs) = V.toList ranges+                              f zs z = func . V.fromList $ (z:zs)+                          in plot f xs defSet { xRange = Just x }++--------------------------------------------------------------------------------
+ lib/Graphics/Rendering/Plot/Gtk/UI/Events.hs view
@@ -0,0 +1,224 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  Graphics.Rendering.Plot.Gtk.UI.Events+-- Copyright   :  (c) Sumit Sahrawat+-- License     :  GPL-2+--+-- Maintainer  :  sumit.sahrawat.apm13@iitbhu.ac.in+-- Stability   :  provisional+-- Portability :  portable+--+-- Attach event handlers for the plot window.+--+--------------------------------------------------------------------------------++module Graphics.Rendering.Plot.Gtk.UI.Events (attachHandlers) where++--------------------------------------------------------------------------------+-- Standard Libraries++import           Data.Char                               (toLower)+import           Data.IORef                              (IORef, modifyIORef,+                                                          readIORef)+import           Data.Text                               (unpack)++--------------------------------------------------------------------------------+-- Other Libraries++import           Graphics.Rendering.Plot+import           Graphics.UI.Gtk                         hiding (Circle, Color,+                                                          Cross)++--------------------------------------------------------------------------------+-- Custom Modules++import           Graphics.Rendering.Plot.Gtk.UI.Figure   (figurePlot)+import           Graphics.Rendering.Plot.Gtk.UI.Settings++--------------------------------------------------------------------------------++attachHandlers :: (ComboBoxClass cbox) =>+                  Builder+                  -> IORef FigureSettings+                  -> [Adjustment]+                  -> (DrawingArea -> IORef FigureSettings+                                  -> [Adjustment]+                                  -> IO ())+                  -> ([Double] -> Double -> Double)+                  -> cbox+                  -> IO ()+attachHandlers builder iofset adjs updateCanvas g combo = do+  -- Canvas+  canvas <- builderGetObject builder castToDrawingArea "Plotting Canvas"+  let redraw = updateCanvas canvas iofset adjs+  _ <- onExpose canvas $ \_ -> redraw >> return False++  -- Adjustments for parameter sliders+  mapM_ (`onValueChanged` redraw) adjs++  -- Plot-Title Entry+  titleEntry <- builderGetObject builder castToEntry "Plot Title Entry"+  _ <- onEntryActivate titleEntry $ do+    titleNew <- entryGetText titleEntry+    modifyIORef iofset $ \f -> f { plotTitle = Just titleNew }+    redraw++  -- Plot-Title Font Size+  titleSize <- builderGetObject builder castToAdjustment "Title Font Size"+  _ <- onValueChanged titleSize $ do+    size <- adjustmentGetValue titleSize+    modifyIORef iofset $ \f -> f { plotTitleSize = size }+    redraw++  -- Subtitle Entry+  subEntry <- builderGetObject builder castToEntry "Subtitle Entry"+  _ <- onEntryActivate subEntry $ do+    titleNew <- entryGetText subEntry+    modifyIORef iofset $ \f -> f { subTitle = Just titleNew }+    redraw++  -- Subtitle Font Size+  subSize  <- builderGetObject builder castToAdjustment "Subtitle Font Size"+  _ <- onValueChanged subSize $ do+    size <- adjustmentGetValue subSize+    modifyIORef iofset $ \f -> f { subTitleSize = size }+    redraw++  -- Show X-Axis CheckButton+  showX <- builderGetObject builder castToCheckButton "X-Axis Check"+  _ <- onToggled showX $ do+    state <- toggleButtonGetActive showX+    modifyIORef iofset+      (\f -> f { showXAxis = state })+    redraw++  -- Show Y-Axis CheckButton+  showY <- builderGetObject builder castToCheckButton "Y-Axis Check"+  _ <- onToggled showY $ do+    state <- toggleButtonGetActive showY+    modifyIORef iofset+      (\f -> f { showYAxis = state })+    redraw++  let adjustmentPairValues (a1, a2) = do v1 <- adjustmentGetValue a1+                                         v2 <- adjustmentGetValue a2+                                         return (v1, v2)+  -- X-Axis Range+  xLower <- builderGetObject builder castToAdjustment "X-Lower"+  xUpper <- builderGetObject builder castToAdjustment "X-Upper"+  let updateX x = onValueChanged x $ do+        (xl, xu) <- adjustmentPairValues (xLower, xUpper)+        modifyIORef iofset $ \f -> f { xRange = Just (xl, xu) }+        redraw+    in mapM_ updateX [xLower, xUpper]++  -- X-Range Auto-determination CheckBox+  xRangeEntries <- builderGetObject builder castToHBox "X-Range Entries"+  autoXCheck <- builderGetObject builder castToCheckButton "X-Range Check"+  _ <- onToggled autoXCheck $ do+    state <- toggleButtonGetActive autoXCheck+    if state+      then error "Invalid xRange"+           -- do modifyIORef iofset $ \f -> f { xRange = Nothing }+           --    widgetHideAll xRangeEntries+      else do lower <- builderGetObject builder castToAdjustment "X-Lower"+              upper <- builderGetObject builder castToAdjustment "X-Upper"+              (l, u) <- adjustmentPairValues (lower, upper)+              widgetShowAll xRangeEntries+              modifyIORef iofset $ \f -> f { xRange = Just (l, u) }+    redraw++  -- Y-Axis Range+  yLower <- builderGetObject builder castToAdjustment "Y-Lower"+  yUpper <- builderGetObject builder castToAdjustment "Y-Upper"+  let updateY y = onValueChanged y $ do+        (yl, yu) <- adjustmentPairValues (yLower, yUpper)+        modifyIORef iofset $ \f -> f { yRange = Just (yl, yu) }+        redraw+    in mapM_ updateY [yLower, yUpper]++  -- Y-Range Auto-determination CheckBox+  yRangeEntries <- builderGetObject builder castToHBox "Y-Range Entries"+  autoYCheck <- builderGetObject builder castToCheckButton "Y-Range Check"+  _ <- onToggled autoYCheck $ do+    state <- toggleButtonGetActive autoYCheck+    if state+      then do modifyIORef iofset $ \f -> f { yRange = Nothing }+              widgetHideAll yRangeEntries+      else do lower <- builderGetObject builder castToAdjustment "Y-Lower"+              upper <- builderGetObject builder castToAdjustment "Y-Upper"+              (l, u) <- adjustmentPairValues (lower, upper)+              widgetShowAll yRangeEntries+              modifyIORef iofset $ \f -> f { yRange = Just (l, u) }+    redraw++  -- Sampling Rate+  sampleRate  <- builderGetObject builder castToAdjustment "Sampling Adj"+  _ <- onValueChanged sampleRate $ do+    rate <- adjustmentGetValue sampleRate+    modifyIORef iofset $ \f -> f { samplingRate = rate }+    redraw++  -- X-Label Entry+  xLabelEntry <- builderGetObject builder castToEntry "X-Label Entry"+  _ <- onEntryActivate xLabelEntry $ do+    label' <- entryGetText xLabelEntry+    modifyIORef iofset $ \f -> f { xLabel = Just label' }+    redraw++  -- X-Label Size+  xlSize <- builderGetObject builder castToAdjustment "X-Label Size"+  _ <- onValueChanged xlSize $ do+    size <- adjustmentGetValue xlSize+    modifyIORef iofset $ \f -> f { xLabelSize = size }+    redraw++  -- Y-Label Entry+  yLabelEntry <- builderGetObject builder castToEntry "Y-Label Entry"+  _ <- onEntryActivate yLabelEntry $ do+    label' <- entryGetText yLabelEntry+    modifyIORef iofset $ \f -> f { yLabel = Just label' }+    redraw++  ylSize <- builderGetObject builder castToAdjustment "Y-Label Size"+  _ <- onValueChanged ylSize $ do+    size <- adjustmentGetValue ylSize+    modifyIORef iofset $ \f -> f { yLabelSize = size }+    redraw++  -- Export Filename extry++  -- Export Button+  export <- builderGetObject builder castToButton "Export Button"+  _ <- onClicked export $ do+    fset      <- readIORef iofset+    comboText <- comboBoxGetActiveText combo+    nameEntry <- builderGetObject builder castToEntry "File Entry"+    nameText  <- entryGetText nameEntry++    modifyIORef iofset $ \f -> f { fileName = nameText }++    figure <- figurePlot g iofset adjs++    let dimensions = exportSize fset++        parseType txt = case txt of+                         "PNG" -> PNG+                         "SVG" -> SVG+                         "PS"  -> PS+                         "PDF" -> PDF+                         _     -> error "Invalid FileType!"++        filetype = parseType $ maybe (error "Invalid Type!") unpack comboText++        parseExt fileType = case fileType of+                              PNG -> "PNG"+                              SVG -> "SVG"+                              PS  -> "PS"+                              PDF -> "PDF"++        filename = nameText ++ "." ++ map toLower (parseExt filetype)+    writeFigure filetype filename dimensions figure+  return ()++--------------------------------------------------------------------------------
+ lib/Graphics/Rendering/Plot/Gtk/UI/Figure.hs view
@@ -0,0 +1,119 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  Graphics.Rendering.Plot.Gtk.UI+-- Copyright   :  (c) Sumit Sahrawat+-- License     :  GPL-2+--+-- Maintainer  :  sumit.sahrawat.apm13@iitbhu.ac.in+-- Stability   :  provisional+-- Portability :  portable+--+-- Functions to build and make changes to 'Figure's+--+--------------------------------------------------------------------------------++module Graphics.Rendering.Plot.Gtk.UI.Figure where++--------------------------------------------------------------------------------+-- Standard Libraries++import           Control.Monad                           (unless, when)+import           Data.IORef                              (IORef, readIORef)+import           Data.Maybe                              (fromJust, isJust)++--------------------------------------------------------------------------------+-- Other Libraries++-- import           Data.Colour.SRGB                        (sRGB24read)+import           Graphics.Rendering.Plot+import           Graphics.UI.Gtk                         (Adjustment,+                                                          adjustmentGetValue)+import           Numeric.LinearAlgebra                   (linspace, mapVector)++--------------------------------------------------------------------------------+-- Custom Modules++import           Graphics.Rendering.Plot.Gtk.UI.Settings++--------------------------------------------------------------------------------++updateFigureText :: (Text () -> Figure ())+                 -> Maybe String -> Double -> Figure ()+updateFigureText withSomething txt size =+    case txt of+      Nothing  -> return ()+      Just str -> withSomething . unless (null str) $ do+                    setText str+                    setFontSize size++--------------------------------------------------------------------------------++updateAxis :: AxisType -> Bool -> (AxisPosn, AxisSide) -> Maybe (Double, Double)+           -> Scale -> Maybe String -> FontSize -> Plot ()+updateAxis axis state location range scale label size = do+  let (position, side) = location++  when state $ addAxis axis position+           (when (isJust label) $ withAxisLabel $ do setText . fromJust $ label+                                                     setFontSize size)++  maybe (setRangeFromData axis side scale)+    (uncurry (setRange axis side scale))+    range++--------------------------------------------------------------------------------++figurePlot :: ([Double] -> Double -> Double)+           -> IORef FigureSettings+           -> [Adjustment]+           -> IO (Figure ())+figurePlot g iofset adjs = do+  fset     <- readIORef iofset+  vars     <- mapM adjustmentGetValue adjs++  let rate    = samplingRate fset+      range   = fromJust $ xRange fset+      samples = round $ (\(x, y) -> rate * (y - x)) range+      domain  = linspace samples range+      func    = g vars+      stype   = plotType fset+      dset    = [(stype, domain, mapVector func domain)]+  return $ buildFigure dset fset++--------------------------------------------------------------------------------++buildFigure :: Dataset a => a -> FigureSettings -> Figure ()+buildFigure dset fset = do+  withTextDefaults $ setFontFamily (fontFamily fset)++  let str  = plotTitle fset+      size = plotTitleSize fset+    in updateFigureText withTitle str size++  let str  = subTitle fset+      size = subTitleSize fset+    in updateFigureText withSubTitle str size++  setPlots 1 1+  withPlot (1, 1) $ do+    setDataset dset++    -- X-Axis+    let state = showXAxis fset+        label = xLabel fset+        size  = xLabelSize fset+        loc   = xLocation fset+        range = xRange fset+        scale = plotScaleX fset+      in updateAxis XAxis state loc range scale label size++    -- Y-Axis+    let state = showYAxis fset+        label = yLabel fset+        size  = yLabelSize fset+        loc   = yLocation fset+        range = yRange fset+        scale = plotScaleY fset+      in updateAxis YAxis state loc range scale label size++--------------------------------------------------------------------------------
+ lib/Graphics/Rendering/Plot/Gtk/UI/PlotWindow.hs view
@@ -0,0 +1,168 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  Graphics.Rendering.Plot.Gtk.UI+-- Copyright   :  (c) Sumit Sahrawat+-- License     :  GPL-2+--+-- Maintainer  :  sumit.sahrawat.apm13@iitbhu.ac.in+-- Stability   :  provisional+-- Portability :  portable+--+-- Functions related to the plot window+--+--------------------------------------------------------------------------------++module Graphics.Rendering.Plot.Gtk.UI.PlotWindow where++--------------------------------------------------------------------------------+-- Standard Libraries++import           Control.Exception                       (SomeException (..),+                                                          catch)+import           Control.Monad                           (when)+import           Data.IORef                              (IORef, readIORef)+import           Data.Maybe                              (fromJust, isJust,+                                                          isNothing)+import           Data.Text                               (pack)++--------------------------------------------------------------------------------+-- Other Libraries++import           Graphics.Rendering.Plot+import           Graphics.UI.Gtk++--------------------------------------------------------------------------------+-- Custom Modules++import           Graphics.Rendering.Plot.Gtk.UI.ErrorFig (errorFig)+import           Graphics.Rendering.Plot.Gtk.UI.Events   (attachHandlers)+import           Graphics.Rendering.Plot.Gtk.UI.Figure   (figurePlot)+import           Graphics.Rendering.Plot.Gtk.UI.Settings++--------------------------------------------------------------------------------++updateCanvas :: ([Double] -> Double -> Double)+             -> DrawingArea+             -> IORef FigureSettings+             -> [Adjustment]+             -> IO ()+updateCanvas g canvas iofset adjs = do+  s@(w, h) <- widgetGetSize canvas+  drw      <- widgetGetDrawWindow canvas+  fig      <- figurePlot g iofset adjs++  box <- regionRectangle $ Rectangle 0 0 w h+  drawWindowBeginPaintRegion drw box+  catch (renderWithDrawable drw (render fig s))+            (\(SomeException _) -> do+               fset <- readIORef iofset+               renderWithDrawable drw (errorFig fset s))+  drawWindowEndPaint drw++--------------------------------------------------------------------------------++addSlidersToBox :: [AdjustmentSettings] -> VBox -> IO [Adjustment]+addSlidersToBox conf box = do+  let newAdj (ASet a b c d e f) = adjustmentNew a b c d e f+      newAdjList    = mapM newAdj+      newHScaleList = mapM hScaleNew++  adjs <- newAdjList conf+  sliders <- newHScaleList adjs+  mapM_ (`scaleSetValuePos` PosRight) sliders+  mapM_ (`scaleSetDigits` 2) sliders+  mapM_ (\x -> boxPackEnd box x PackNatural 0) sliders+  return adjs++--------------------------------------------------------------------------------++plotWindow :: String -> IORef FigureSettings -> [AdjustmentSettings]+             -> ([Double] -> Double -> Double) -> IO ()+plotWindow plotGlade iofset conf fun = do+  builder <- builderNew+  builderAddFromFile builder plotGlade++  plotBox <- builderGetObject builder castToVBox "Plot Region"+  adjs    <- addSlidersToBox conf plotBox+  fset    <- readIORef iofset++  let updateEntryText entryGlade txt =+        when (isJust txt) $ do entry <- builderGetObject builder+                                        castToEntry entryGlade+                               entrySetText entry $ fromJust txt+    in do updateEntryText "Plot Title Entry" $ plotTitle fset+          updateEntryText "Subtitle Entry"   $ subTitle fset+          updateEntryText "X-Label Entry"    $ xLabel fset+          updateEntryText "Y-Label Entry"    $ yLabel fset+          updateEntryText "File Entry"       $ Just (fileName fset)++  let adjApplyValue adjGlade val = do+        adj <- builderGetObject builder castToAdjustment adjGlade+        adjustmentSetValue adj val+    in do adjApplyValue "Title Font Size"    $ plotTitleSize fset+          adjApplyValue "Subtitle Font Size" $ subTitleSize fset+          adjApplyValue "Sampling Adj"       $ samplingRate fset+          adjApplyValue "X-Label Size"       $ xLabelSize fset+          adjApplyValue "Y-Label Size"       $ yLabelSize fset++  let checkApplyState checkGlade state = do+        check <- builderGetObject builder castToCheckButton checkGlade+        toggleButtonSetActive check state+    in do checkApplyState "X-Axis Check"  $ showXAxis fset+          checkApplyState "Y-Axis Check"  $ showYAxis fset+          checkApplyState "Y-Range Check" $ isNothing . yRange $ fset++  when (isJust . yRange $ fset) $ do+    let (l, u) = fromJust . yRange $ fset+    lower <- builderGetObject builder castToAdjustment "Y-Lower"+    upper <- builderGetObject builder castToAdjustment "Y-Upper"+    adjustmentSetValue lower l+    adjustmentSetValue upper u++  -- X-Axis Range+  let range = xRange fset+    in if isNothing range+       then error "Invalid xRange"+       else let (l, u) = fromJust range+            in do lower <- builderGetObject builder castToAdjustment "X-Lower"+                  upper <- builderGetObject builder castToAdjustment "X-Upper"+                  adjustmentSetValue lower l+                  adjustmentSetValue upper u++  -- Export Size+  let (w, h) = exportSize fset+    in do widthAdj  <- builderGetObject builder castToAdjustment "Export Width"+          heightAdj <- builderGetObject builder castToAdjustment "Export Height"+          adjustmentSetValue widthAdj  $ fromIntegral w+          adjustmentSetValue heightAdj $ fromIntegral h++  -- Export ComboBox+  combo <- comboBoxNewText+  _     <- mapM (\(x, y) -> comboBoxInsertText combo x $ pack y)+           [(1, "PNG"), (2, "SVG"), (3, "PS"), (4, "PDF")]+  comboBoxSetActive combo 0++  comboArea <- builderGetObject builder castToHBox "File Name"+  boxPackEndDefaults comboArea combo++  -- Attach Event Handlers+  _ <- attachHandlers builder iofset adjs (updateCanvas fun) fun combo++  -- Show Widgets+  window <- builderGetObject builder castToWindow "Plot Window"+  widgetShowAll window++  -- Hide the useless checkButton for now+  check <- builderGetObject builder castToCheckButton "X-Range Check"+  widgetHide check++  -- Hide the entries if not required+  let range = yRange fset+    in when (isNothing range) $ do+      entries  <- builderGetObject builder castToHBox "Y-Range Entries"+      widgetHideAll entries++  _ <- onDestroy window mainQuit+  return ()++--------------------------------------------------------------------------------
+ lib/Graphics/Rendering/Plot/Gtk/UI/Settings.hs view
@@ -0,0 +1,96 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  Graphics.Rendering.Plot.Gtk.UI+-- Copyright   :  (c) Sumit Sahrawat+-- License     :  GPL-2+--+-- Maintainer  :  sumit.sahrawat.apm13@iitbhu.ac.in+-- Stability   :  provisional+-- Portability :  portable+--+-- Helper functions and data for the figures and sliders+--+--------------------------------------------------------------------------------+module Graphics.Rendering.Plot.Gtk.UI.Settings+    ( FigureSettings (..)+    , defaultFigureSettings+    , AdjustmentSettings (..)+    , aSetRange+    ) where++--------------------------------------------------------------------------------+-- Datatypes used by plot package for configuration++import           Graphics.Rendering.Plot (AxisPosn (..), AxisSide (..),+                                          Scale (..), SeriesType (..))++--------------------------------------------------------------------------------++data FigureSettings = FigureSettings {+      fontFamily    :: String+    , plotTitle     :: Maybe String+    , plotTitleSize :: Double+    , subTitle      :: Maybe String+    , subTitleSize  :: Double+    , xRange        :: Maybe (Double, Double)+    , yRange        :: Maybe (Double, Double)+    , samplingRate  :: Double+    , xLabel        :: Maybe String+    , xLabelSize    :: Double+    , yLabel        :: Maybe String+    , yLabelSize    :: Double+    , showXAxis     :: Bool+    , xLocation     :: (AxisPosn, AxisSide)+    , showYAxis     :: Bool+    , yLocation     :: (AxisPosn, AxisSide)+    , plotScaleX    :: Scale+    , plotScaleY    :: Scale+    , exportSize    :: (Int, Int)+    , fileName      :: String+    , plotType      :: SeriesType+    }++--------------------------------------------------------------------------------++defaultFigureSettings :: FigureSettings+defaultFigureSettings = FigureSettings {+                          fontFamily    = "Sans"+                        , plotTitle     = Nothing+                        , plotTitleSize = 10+                        , subTitle      = Nothing+                        , subTitleSize  = 10+                        , xRange        = Nothing+                        , yRange        = Nothing+                        , samplingRate  = 50+                        , xLabel        = Nothing+                        , xLabelSize    = 10+                        , yLabel        = Nothing+                        , yLabelSize    = 10+                        , showXAxis     = True+                        , xLocation     = (Side Lower, Lower)+                        , showYAxis     = True+                        , yLocation     = (Side Lower, Lower)+                        , plotScaleX    = Linear+                        , plotScaleY    = Linear+                        , exportSize    = (1000, 1000)+                        , fileName      = "plot"+                        , plotType      = Line+                        }++--------------------------------------------------------------------------------++data AdjustmentSettings = ASet {+      initVal  :: Double+    , minBound :: Double+    , maxBound :: Double+    , stepIncr :: Double+    , pageIncr :: Double+    , pageSize :: Double+    }++--------------------------------------------------------------------------------++aSetRange :: Double -> Double -> Double -> AdjustmentSettings+aSetRange x y z = ASet x y z 0.01 0.01 0.00++--------------------------------------------------------------------------------
+ plot-gtk-ui.cabal view
@@ -0,0 +1,49 @@+Name:                plot-gtk-ui+Version:             0.0.1.0+License:             GPL-2+License-file:        LICENSE+Author:              Sumit Sahrawat+Maintainer:          sumit.sahrawat.apm13@iitbhu.ac.in+Stability:           experimental+Homepage:            https://github.com/sumitsahrawat/plot-gtk-ui+Synopsis:            A quick way to use Mathematica like Manipulation abilities+Description:+            A pre-built ui for plotting based on plot. Quicker to use than+            plot-gtk, but less configurable, and less versatile.+            .+            Only provides ability to plot mathematical functions. But, also+            allows dynamic plotting functionality similar to Mathematica.++Category:            Math++Tested-with:         GHC==7.8.3+Cabal-version:       >=1.18+Build-type:          Simple++Extra-source-files:  README.md+Data-dir:            ui+Data-files:          plot-window.glade++Library+  Build-depends:       base >=4.7 && <4.8+                     , colour >=2.3 && <2.4+                     , plot >=0.2 && <0.3+                     , gtk >=0.13 && <0.14+                     , cairo >=0.13 && <0.14+                     , hmatrix >=0.16 && <0.17+                     , text >=1.2 && <1.3+                     , vector >=0.10.12.2 && <0.10.13.0+                     , fixed-vector >=0.7.0.0+  hs-source-dirs:      lib+  exposed-modules:     Graphics.Rendering.Plot.Gtk.UI+  other-modules:       Paths_plot_gtk_ui+                     , Graphics.Rendering.Plot.Gtk.UI.Events+                     , Graphics.Rendering.Plot.Gtk.UI.Figure+                     , Graphics.Rendering.Plot.Gtk.UI.Settings+                     , Graphics.Rendering.Plot.Gtk.UI.PlotWindow+  ghc-options:         -Wall+  default-language:    Haskell2010++source-repository head+  type:     git+  location: https://github.com/sumitsahrawat/plot-gtk-ui.git
+ ui/plot-window.glade view
@@ -0,0 +1,958 @@+<?xml version="1.0" encoding="UTF-8"?>+<interface>+  <requires lib="gtk+" version="2.24"/>+  <!-- interface-naming-policy project-wide -->+  <object class="GtkAdjustment" id="Export Height">+    <property name="lower">1</property>+    <property name="upper">5120</property>+    <property name="value">1</property>+    <property name="step_increment">50</property>+    <property name="page_increment">200</property>+  </object>+  <object class="GtkAdjustment" id="Export Width">+    <property name="lower">1</property>+    <property name="upper">5120</property>+    <property name="value">1</property>+    <property name="step_increment">50</property>+    <property name="page_increment">200</property>+  </object>+  <object class="GtkAdjustment" id="Sampling Adj">+    <property name="lower">1</property>+    <property name="upper">1000</property>+    <property name="value">1</property>+    <property name="step_increment">0.050000000000000003</property>+    <property name="page_increment">0.5</property>+  </object>+  <object class="GtkAdjustment" id="Subtitle Font Size">+    <property name="lower">1</property>+    <property name="upper">72</property>+    <property name="value">1</property>+    <property name="step_increment">0.5</property>+    <property name="page_increment">1</property>+  </object>+  <object class="GtkAdjustment" id="Title Font Size">+    <property name="lower">1</property>+    <property name="upper">72</property>+    <property name="value">1</property>+    <property name="step_increment">0.5</property>+    <property name="page_increment">1</property>+  </object>+  <object class="GtkAdjustment" id="X-Label Size">+    <property name="lower">1</property>+    <property name="upper">72</property>+    <property name="value">1</property>+    <property name="step_increment">0.5</property>+    <property name="page_increment">1</property>+  </object>+  <object class="GtkAdjustment" id="X-Lower">+    <property name="lower">-1.7976931348623157e+308</property>+    <property name="upper">1.7976931348623157e+308</property>+    <property name="step_increment">0.01</property>+    <property name="page_increment">1</property>+  </object>+  <object class="GtkAdjustment" id="X-Upper">+    <property name="lower">-1.7976931348623157e+308</property>+    <property name="upper">1.7976931348623157e+308</property>+    <property name="step_increment">0.01</property>+    <property name="page_increment">1</property>+  </object>+  <object class="GtkAdjustment" id="Y-Label Size">+    <property name="lower">1</property>+    <property name="upper">72</property>+    <property name="value">1</property>+    <property name="step_increment">0.5</property>+    <property name="page_increment">1</property>+  </object>+  <object class="GtkAdjustment" id="Y-Lower">+    <property name="lower">-1.7976931348623157e+308</property>+    <property name="upper">1.7976931348623157e+308</property>+    <property name="step_increment">0.01</property>+    <property name="page_increment">1</property>+  </object>+  <object class="GtkAdjustment" id="Y-Upper">+    <property name="lower">-1.7976931348623157e+308</property>+    <property name="upper">1.7976931348623157e+308</property>+    <property name="step_increment">0.01</property>+    <property name="page_increment">1</property>+  </object>+  <object class="GtkWindow" id="Plot Window">+    <property name="can_focus">False</property>+    <property name="border_width">1</property>+    <property name="title" translatable="yes">Your Plot</property>+    <child>+      <object class="GtkHBox" id="Vertical Division">+        <property name="visible">True</property>+        <property name="can_focus">False</property>+        <child>+          <object class="GtkVBox" id="Plot Region">+            <property name="visible">True</property>+            <property name="can_focus">False</property>+            <property name="border_width">5</property>+            <child>+              <object class="GtkAspectFrame" id="Canvas Aspect">+                <property name="visible">True</property>+                <property name="can_focus">False</property>+                <property name="label_xalign">0</property>+                <property name="shadow_type">in</property>+                <child>+                  <object class="GtkDrawingArea" id="Plotting Canvas">+                    <property name="width_request">500</property>+                    <property name="height_request">500</property>+                    <property name="visible">True</property>+                    <property name="can_focus">False</property>+                    <property name="events">GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK</property>+                  </object>+                </child>+              </object>+              <packing>+                <property name="expand">True</property>+                <property name="fill">True</property>+                <property name="pack_type">end</property>+                <property name="position">0</property>+              </packing>+            </child>+          </object>+          <packing>+            <property name="expand">True</property>+            <property name="fill">True</property>+            <property name="position">0</property>+          </packing>+        </child>+        <child>+          <object class="GtkVSeparator" id="Separator">+            <property name="visible">True</property>+            <property name="can_focus">False</property>+          </object>+          <packing>+            <property name="expand">False</property>+            <property name="fill">True</property>+            <property name="position">1</property>+          </packing>+        </child>+        <child>+          <object class="GtkScrolledWindow" id="Settings Palette Scroll">+            <property name="visible">True</property>+            <property name="can_focus">True</property>+            <property name="hscrollbar_policy">never</property>+            <property name="vscrollbar_policy">automatic</property>+            <child>+              <object class="GtkViewport" id="Settings Palette Viewport">+                <property name="visible">True</property>+                <property name="can_focus">False</property>+                <property name="shadow_type">none</property>+                <child>+                  <object class="GtkVBox" id="Settings Palette">+                    <property name="width_request">250</property>+                    <property name="visible">True</property>+                    <property name="can_focus">False</property>+                    <property name="border_width">10</property>+                    <child>+                      <object class="GtkFrame" id="Plot Title">+                        <property name="visible">True</property>+                        <property name="can_focus">False</property>+                        <property name="border_width">3</property>+                        <property name="label_xalign">0</property>+                        <property name="shadow_type">in</property>+                        <child>+                          <object class="GtkHBox" id="Plot Title Input Widget">+                            <property name="visible">True</property>+                            <property name="can_focus">False</property>+                            <property name="border_width">3</property>+                            <property name="spacing">2</property>+                            <child>+                              <object class="GtkEntry" id="Plot Title Entry">+                                <property name="visible">True</property>+                                <property name="can_focus">True</property>+                                <property name="invisible_char">●</property>+                                <property name="invisible_char_set">True</property>+                                <property name="primary_icon_activatable">False</property>+                                <property name="secondary_icon_activatable">False</property>+                                <property name="primary_icon_sensitive">True</property>+                                <property name="secondary_icon_sensitive">True</property>+                              </object>+                              <packing>+                                <property name="expand">True</property>+                                <property name="fill">True</property>+                                <property name="position">0</property>+                              </packing>+                            </child>+                            <child>+                              <object class="GtkSpinButton" id="Plot Title Size">+                                <property name="visible">True</property>+                                <property name="can_focus">True</property>+                                <property name="invisible_char">●</property>+                                <property name="progress_pulse_step">0.5</property>+                                <property name="primary_icon_activatable">False</property>+                                <property name="secondary_icon_activatable">False</property>+                                <property name="primary_icon_sensitive">True</property>+                                <property name="secondary_icon_sensitive">True</property>+                                <property name="adjustment">Title Font Size</property>+                                <property name="digits">1</property>+                                <property name="snap_to_ticks">True</property>+                                <property name="numeric">True</property>+                                <property name="update_policy">if-valid</property>+                              </object>+                              <packing>+                                <property name="expand">True</property>+                                <property name="fill">True</property>+                                <property name="position">1</property>+                              </packing>+                            </child>+                          </object>+                        </child>+                        <child type="label">+                          <object class="GtkLabel" id="Plot Title Frame Label">+                            <property name="visible">True</property>+                            <property name="can_focus">False</property>+                            <property name="label" translatable="yes">&lt;b&gt;Plot Title&lt;/b&gt;</property>+                            <property name="use_markup">True</property>+                          </object>+                        </child>+                      </object>+                      <packing>+                        <property name="expand">False</property>+                        <property name="fill">True</property>+                        <property name="position">0</property>+                      </packing>+                    </child>+                    <child>+                      <object class="GtkFrame" id="Subtitle">+                        <property name="visible">True</property>+                        <property name="can_focus">False</property>+                        <property name="border_width">3</property>+                        <property name="label_xalign">0</property>+                        <property name="shadow_type">in</property>+                        <child>+                          <object class="GtkHBox" id="Subtitle Input Widget">+                            <property name="visible">True</property>+                            <property name="can_focus">False</property>+                            <property name="border_width">3</property>+                            <property name="spacing">2</property>+                            <child>+                              <object class="GtkEntry" id="Subtitle Entry">+                                <property name="visible">True</property>+                                <property name="can_focus">True</property>+                                <property name="invisible_char">●</property>+                                <property name="truncate_multiline">True</property>+                                <property name="invisible_char_set">True</property>+                                <property name="primary_icon_activatable">False</property>+                                <property name="secondary_icon_activatable">False</property>+                                <property name="primary_icon_sensitive">True</property>+                                <property name="secondary_icon_sensitive">True</property>+                              </object>+                              <packing>+                                <property name="expand">True</property>+                                <property name="fill">True</property>+                                <property name="position">0</property>+                              </packing>+                            </child>+                            <child>+                              <object class="GtkSpinButton" id="Subtitle Size">+                                <property name="visible">True</property>+                                <property name="can_focus">True</property>+                                <property name="invisible_char">●</property>+                                <property name="progress_pulse_step">0.5</property>+                                <property name="primary_icon_activatable">False</property>+                                <property name="secondary_icon_activatable">False</property>+                                <property name="primary_icon_sensitive">True</property>+                                <property name="secondary_icon_sensitive">True</property>+                                <property name="adjustment">Subtitle Font Size</property>+                                <property name="digits">1</property>+                                <property name="snap_to_ticks">True</property>+                                <property name="numeric">True</property>+                                <property name="update_policy">if-valid</property>+                              </object>+                              <packing>+                                <property name="expand">True</property>+                                <property name="fill">True</property>+                                <property name="position">1</property>+                              </packing>+                            </child>+                          </object>+                        </child>+                        <child type="label">+                          <object class="GtkLabel" id="Sub-Title Frame Label">+                            <property name="visible">True</property>+                            <property name="can_focus">False</property>+                            <property name="label" translatable="yes">&lt;b&gt;Subtitle&lt;/b&gt;</property>+                            <property name="use_markup">True</property>+                          </object>+                        </child>+                      </object>+                      <packing>+                        <property name="expand">False</property>+                        <property name="fill">True</property>+                        <property name="position">1</property>+                      </packing>+                    </child>+                    <child>+                      <object class="GtkFrame" id="Axes">+                        <property name="visible">True</property>+                        <property name="can_focus">False</property>+                        <property name="border_width">3</property>+                        <property name="label_xalign">0</property>+                        <property name="shadow_type">in</property>+                        <child>+                          <object class="GtkHBox" id="Axes Box">+                            <property name="visible">True</property>+                            <property name="can_focus">False</property>+                            <property name="border_width">3</property>+                            <child>+                              <object class="GtkCheckButton" id="X-Axis Check">+                                <property name="label" translatable="yes">Show X-Axis</property>+                                <property name="visible">True</property>+                                <property name="can_focus">True</property>+                                <property name="receives_default">False</property>+                                <property name="active">True</property>+                                <property name="draw_indicator">True</property>+                              </object>+                              <packing>+                                <property name="expand">True</property>+                                <property name="fill">True</property>+                                <property name="position">0</property>+                              </packing>+                            </child>+                            <child>+                              <object class="GtkCheckButton" id="Y-Axis Check">+                                <property name="label" translatable="yes">Show Y-Axis</property>+                                <property name="visible">True</property>+                                <property name="can_focus">True</property>+                                <property name="receives_default">False</property>+                                <property name="active">True</property>+                                <property name="draw_indicator">True</property>+                              </object>+                              <packing>+                                <property name="expand">True</property>+                                <property name="fill">True</property>+                                <property name="position">1</property>+                              </packing>+                            </child>+                          </object>+                        </child>+                        <child type="label">+                          <object class="GtkLabel" id="Axes Frame Label">+                            <property name="visible">True</property>+                            <property name="can_focus">False</property>+                            <property name="label" translatable="yes">&lt;b&gt;Axes&lt;/b&gt;</property>+                            <property name="use_markup">True</property>+                          </object>+                        </child>+                      </object>+                      <packing>+                        <property name="expand">False</property>+                        <property name="fill">True</property>+                        <property name="position">2</property>+                      </packing>+                    </child>+                    <child>+                      <object class="GtkFrame" id="X-Range">+                        <property name="visible">True</property>+                        <property name="can_focus">False</property>+                        <property name="border_width">3</property>+                        <property name="label_xalign">0</property>+                        <property name="shadow_type">in</property>+                        <child>+                          <object class="GtkVBox" id="X-Range Box">+                            <property name="visible">True</property>+                            <property name="can_focus">False</property>+                            <property name="border_width">3</property>+                            <child>+                              <object class="GtkCheckButton" id="X-Range Check">+                                <property name="label" translatable="yes">Auto-Determine X-Range</property>+                                <property name="visible">True</property>+                                <property name="can_focus">True</property>+                                <property name="receives_default">False</property>+                                <property name="draw_indicator">True</property>+                              </object>+                              <packing>+                                <property name="expand">True</property>+                                <property name="fill">True</property>+                                <property name="position">0</property>+                              </packing>+                            </child>+                            <child>+                              <object class="GtkHBox" id="X-Range Entries">+                                <property name="visible">True</property>+                                <property name="can_focus">False</property>+                                <property name="spacing">2</property>+                                <property name="homogeneous">True</property>+                                <child>+                                  <object class="GtkSpinButton" id="X-Range Lower Entry">+                                    <property name="visible">True</property>+                                    <property name="can_focus">True</property>+                                    <property name="invisible_char">●</property>+                                    <property name="progress_pulse_step">0.25</property>+                                    <property name="primary_icon_activatable">False</property>+                                    <property name="secondary_icon_activatable">False</property>+                                    <property name="primary_icon_sensitive">True</property>+                                    <property name="secondary_icon_sensitive">True</property>+                                    <property name="adjustment">X-Lower</property>+                                    <property name="digits">2</property>+                                    <property name="numeric">True</property>+                                  </object>+                                  <packing>+                                    <property name="expand">True</property>+                                    <property name="fill">True</property>+                                    <property name="position">0</property>+                                  </packing>+                                </child>+                                <child>+                                  <object class="GtkSpinButton" id="X-Range Upper Entry">+                                    <property name="visible">True</property>+                                    <property name="can_focus">True</property>+                                    <property name="invisible_char">●</property>+                                    <property name="progress_pulse_step">0.25</property>+                                    <property name="primary_icon_activatable">False</property>+                                    <property name="secondary_icon_activatable">False</property>+                                    <property name="primary_icon_sensitive">True</property>+                                    <property name="secondary_icon_sensitive">True</property>+                                    <property name="adjustment">X-Upper</property>+                                    <property name="digits">2</property>+                                    <property name="numeric">True</property>+                                  </object>+                                  <packing>+                                    <property name="expand">True</property>+                                    <property name="fill">True</property>+                                    <property name="position">1</property>+                                  </packing>+                                </child>+                              </object>+                              <packing>+                                <property name="expand">True</property>+                                <property name="fill">True</property>+                                <property name="position">1</property>+                              </packing>+                            </child>+                          </object>+                        </child>+                        <child type="label">+                          <object class="GtkLabel" id="X-Range Frame Label">+                            <property name="visible">True</property>+                            <property name="can_focus">False</property>+                            <property name="label" translatable="yes">&lt;b&gt;X-Range&lt;/b&gt;</property>+                            <property name="use_markup">True</property>+                          </object>+                        </child>+                      </object>+                      <packing>+                        <property name="expand">False</property>+                        <property name="fill">True</property>+                        <property name="position">3</property>+                      </packing>+                    </child>+                    <child>+                      <object class="GtkFrame" id="Y-Range">+                        <property name="visible">True</property>+                        <property name="can_focus">False</property>+                        <property name="border_width">3</property>+                        <property name="label_xalign">0</property>+                        <property name="shadow_type">in</property>+                        <child>+                          <object class="GtkVBox" id="Y-Range Box">+                            <property name="visible">True</property>+                            <property name="can_focus">False</property>+                            <property name="border_width">2</property>+                            <child>+                              <object class="GtkCheckButton" id="Y-Range Check">+                                <property name="label" translatable="yes">Auto-Determine Y-Range</property>+                                <property name="visible">True</property>+                                <property name="can_focus">True</property>+                                <property name="receives_default">False</property>+                                <property name="draw_indicator">True</property>+                              </object>+                              <packing>+                                <property name="expand">True</property>+                                <property name="fill">True</property>+                                <property name="position">0</property>+                              </packing>+                            </child>+                            <child>+                              <object class="GtkHBox" id="Y-Range Entries">+                                <property name="visible">True</property>+                                <property name="can_focus">False</property>+                                <property name="spacing">2</property>+                                <property name="homogeneous">True</property>+                                <child>+                                  <object class="GtkSpinButton" id="Y-Range Lower Entry">+                                    <property name="visible">True</property>+                                    <property name="can_focus">True</property>+                                    <property name="invisible_char">●</property>+                                    <property name="progress_pulse_step">0.25</property>+                                    <property name="primary_icon_activatable">False</property>+                                    <property name="secondary_icon_activatable">False</property>+                                    <property name="primary_icon_sensitive">True</property>+                                    <property name="secondary_icon_sensitive">True</property>+                                    <property name="adjustment">Y-Lower</property>+                                    <property name="digits">2</property>+                                    <property name="numeric">True</property>+                                  </object>+                                  <packing>+                                    <property name="expand">True</property>+                                    <property name="fill">True</property>+                                    <property name="position">0</property>+                                  </packing>+                                </child>+                                <child>+                                  <object class="GtkSpinButton" id="Y-Range Upper Entry">+                                    <property name="visible">True</property>+                                    <property name="can_focus">True</property>+                                    <property name="invisible_char">●</property>+                                    <property name="progress_pulse_step">0.25</property>+                                    <property name="primary_icon_activatable">False</property>+                                    <property name="secondary_icon_activatable">False</property>+                                    <property name="primary_icon_sensitive">True</property>+                                    <property name="secondary_icon_sensitive">True</property>+                                    <property name="adjustment">Y-Upper</property>+                                    <property name="digits">2</property>+                                    <property name="numeric">True</property>+                                  </object>+                                  <packing>+                                    <property name="expand">True</property>+                                    <property name="fill">True</property>+                                    <property name="position">1</property>+                                  </packing>+                                </child>+                              </object>+                              <packing>+                                <property name="expand">True</property>+                                <property name="fill">True</property>+                                <property name="position">1</property>+                              </packing>+                            </child>+                          </object>+                        </child>+                        <child type="label">+                          <object class="GtkLabel" id="Y-Range Frame Label">+                            <property name="visible">True</property>+                            <property name="can_focus">False</property>+                            <property name="label" translatable="yes">&lt;b&gt;Y-Range&lt;/b&gt;</property>+                            <property name="use_markup">True</property>+                          </object>+                        </child>+                      </object>+                      <packing>+                        <property name="expand">False</property>+                        <property name="fill">True</property>+                        <property name="position">4</property>+                      </packing>+                    </child>+                    <child>+                      <object class="GtkFrame" id="Sampling Rate">+                        <property name="visible">True</property>+                        <property name="can_focus">False</property>+                        <property name="border_width">3</property>+                        <property name="label_xalign">0</property>+                        <property name="shadow_type">in</property>+                        <child>+                          <object class="GtkVBox" id="Sampling Rate Box">+                            <property name="visible">True</property>+                            <property name="can_focus">False</property>+                            <property name="border_width">3</property>+                            <child>+                              <object class="GtkSpinButton" id="Sampling Rate Entry">+                                <property name="visible">True</property>+                                <property name="can_focus">True</property>+                                <property name="invisible_char">●</property>+                                <property name="primary_icon_activatable">False</property>+                                <property name="secondary_icon_activatable">False</property>+                                <property name="primary_icon_sensitive">True</property>+                                <property name="secondary_icon_sensitive">True</property>+                                <property name="adjustment">Sampling Adj</property>+                                <property name="digits">1</property>+                                <property name="snap_to_ticks">True</property>+                                <property name="numeric">True</property>+                                <property name="update_policy">if-valid</property>+                              </object>+                              <packing>+                                <property name="expand">True</property>+                                <property name="fill">True</property>+                                <property name="position">0</property>+                              </packing>+                            </child>+                          </object>+                        </child>+                        <child type="label">+                          <object class="GtkLabel" id="Sampling Frame Label">+                            <property name="visible">True</property>+                            <property name="can_focus">False</property>+                            <property name="label" translatable="yes">&lt;b&gt;Sampling Rate&lt;/b&gt;</property>+                            <property name="use_markup">True</property>+                          </object>+                        </child>+                      </object>+                      <packing>+                        <property name="expand">False</property>+                        <property name="fill">True</property>+                        <property name="position">5</property>+                      </packing>+                    </child>+                    <child>+                      <object class="GtkFrame" id="Labels">+                        <property name="visible">True</property>+                        <property name="can_focus">False</property>+                        <property name="border_width">3</property>+                        <property name="label_xalign">0</property>+                        <property name="shadow_type">in</property>+                        <child>+                          <object class="GtkVBox" id="Labels Box">+                            <property name="visible">True</property>+                            <property name="can_focus">False</property>+                            <child>+                              <object class="GtkVBox" id="X-Axis Label Widget">+                                <property name="visible">True</property>+                                <property name="can_focus">False</property>+                                <child>+                                  <object class="GtkHBox" id="X-Label Input Widget">+                                    <property name="visible">True</property>+                                    <property name="can_focus">False</property>+                                    <property name="border_width">2</property>+                                    <property name="spacing">2</property>+                                    <child>+                                      <object class="GtkEntry" id="X-Label Entry">+                                        <property name="visible">True</property>+                                        <property name="can_focus">True</property>+                                        <property name="invisible_char">●</property>+                                        <property name="invisible_char_set">True</property>+                                        <property name="primary_icon_activatable">False</property>+                                        <property name="secondary_icon_activatable">False</property>+                                        <property name="primary_icon_sensitive">True</property>+                                        <property name="secondary_icon_sensitive">True</property>+                                      </object>+                                      <packing>+                                        <property name="expand">True</property>+                                        <property name="fill">True</property>+                                        <property name="position">0</property>+                                      </packing>+                                    </child>+                                    <child>+                                      <object class="GtkSpinButton" id="X-Label Font Input">+                                        <property name="visible">True</property>+                                        <property name="can_focus">True</property>+                                        <property name="invisible_char">●</property>+                                        <property name="progress_pulse_step">0.5</property>+                                        <property name="primary_icon_activatable">False</property>+                                        <property name="secondary_icon_activatable">False</property>+                                        <property name="primary_icon_sensitive">True</property>+                                        <property name="secondary_icon_sensitive">True</property>+                                        <property name="adjustment">X-Label Size</property>+                                        <property name="digits">1</property>+                                        <property name="snap_to_ticks">True</property>+                                        <property name="numeric">True</property>+                                        <property name="update_policy">if-valid</property>+                                      </object>+                                      <packing>+                                        <property name="expand">True</property>+                                        <property name="fill">True</property>+                                        <property name="position">1</property>+                                      </packing>+                                    </child>+                                  </object>+                                  <packing>+                                    <property name="expand">True</property>+                                    <property name="fill">True</property>+                                    <property name="position">-1</property>+                                  </packing>+                                </child>+                                <child>+                                  <object class="GtkLabel" id="X-Axis Label">+                                    <property name="visible">True</property>+                                    <property name="can_focus">False</property>+                                    <property name="label" translatable="yes">X-Axis Label</property>+                                    <property name="use_markup">True</property>+                                  </object>+                                  <packing>+                                    <property name="expand">True</property>+                                    <property name="fill">True</property>+                                    <property name="position">0</property>+                                  </packing>+                                </child>+                              </object>+                              <packing>+                                <property name="expand">True</property>+                                <property name="fill">True</property>+                                <property name="position">0</property>+                              </packing>+                            </child>+                            <child>+                              <object class="GtkVBox" id="Y-Axis Label Widget">+                                <property name="visible">True</property>+                                <property name="can_focus">False</property>+                                <child>+                                  <object class="GtkHBox" id="Y-Axis Input Widget">+                                    <property name="visible">True</property>+                                    <property name="can_focus">False</property>+                                    <property name="border_width">2</property>+                                    <property name="spacing">2</property>+                                    <child>+                                      <object class="GtkEntry" id="Y-Label Entry">+                                        <property name="visible">True</property>+                                        <property name="can_focus">True</property>+                                        <property name="invisible_char">●</property>+                                        <property name="invisible_char_set">True</property>+                                        <property name="primary_icon_activatable">False</property>+                                        <property name="secondary_icon_activatable">False</property>+                                        <property name="primary_icon_sensitive">True</property>+                                        <property name="secondary_icon_sensitive">True</property>+                                      </object>+                                      <packing>+                                        <property name="expand">True</property>+                                        <property name="fill">True</property>+                                        <property name="position">0</property>+                                      </packing>+                                    </child>+                                    <child>+                                      <object class="GtkSpinButton" id="Y-Label Font Input">+                                        <property name="visible">True</property>+                                        <property name="can_focus">True</property>+                                        <property name="invisible_char">●</property>+                                        <property name="progress_pulse_step">0.5</property>+                                        <property name="primary_icon_activatable">False</property>+                                        <property name="secondary_icon_activatable">False</property>+                                        <property name="primary_icon_sensitive">True</property>+                                        <property name="secondary_icon_sensitive">True</property>+                                        <property name="adjustment">Y-Label Size</property>+                                        <property name="digits">1</property>+                                        <property name="snap_to_ticks">True</property>+                                        <property name="numeric">True</property>+                                        <property name="update_policy">if-valid</property>+                                      </object>+                                      <packing>+                                        <property name="expand">True</property>+                                        <property name="fill">True</property>+                                        <property name="position">1</property>+                                      </packing>+                                    </child>+                                  </object>+                                  <packing>+                                    <property name="expand">True</property>+                                    <property name="fill">True</property>+                                    <property name="position">-1</property>+                                  </packing>+                                </child>+                                <child>+                                  <object class="GtkLabel" id="Y-Axis Label">+                                    <property name="visible">True</property>+                                    <property name="can_focus">False</property>+                                    <property name="label" translatable="yes">Y-Axis Label</property>+                                  </object>+                                  <packing>+                                    <property name="expand">True</property>+                                    <property name="fill">True</property>+                                    <property name="position">0</property>+                                  </packing>+                                </child>+                              </object>+                              <packing>+                                <property name="expand">True</property>+                                <property name="fill">True</property>+                                <property name="position">1</property>+                              </packing>+                            </child>+                          </object>+                        </child>+                        <child type="label">+                          <object class="GtkLabel" id="Labels Frame Label">+                            <property name="visible">True</property>+                            <property name="can_focus">False</property>+                            <property name="label" translatable="yes">&lt;b&gt;Labels&lt;/b&gt;</property>+                            <property name="use_markup">True</property>+                          </object>+                        </child>+                      </object>+                      <packing>+                        <property name="expand">False</property>+                        <property name="fill">True</property>+                        <property name="position">6</property>+                      </packing>+                    </child>+                    <child>+                      <object class="GtkFrame" id="Export">+                        <property name="visible">True</property>+                        <property name="can_focus">False</property>+                        <property name="border_width">3</property>+                        <property name="label_xalign">0</property>+                        <property name="shadow_type">in</property>+                        <child>+                          <object class="GtkVBox" id="Export Box">+                            <property name="visible">True</property>+                            <property name="can_focus">False</property>+                            <property name="border_width">1</property>+                            <child>+                              <object class="GtkVBox" id="Dimensions">+                                <property name="visible">True</property>+                                <property name="can_focus">False</property>+                                <property name="border_width">2</property>+                                <child>+                                  <object class="GtkLabel" id="Dimensions Label">+                                    <property name="visible">True</property>+                                    <property name="can_focus">False</property>+                                    <property name="label" translatable="yes">Dimensions</property>+                                  </object>+                                  <packing>+                                    <property name="expand">True</property>+                                    <property name="fill">True</property>+                                    <property name="position">0</property>+                                  </packing>+                                </child>+                                <child>+                                  <object class="GtkHBox" id="Dimension Entries">+                                    <property name="visible">True</property>+                                    <property name="can_focus">False</property>+                                    <property name="spacing">2</property>+                                    <property name="homogeneous">True</property>+                                    <child>+                                      <object class="GtkSpinButton" id="Dimensions Width">+                                        <property name="visible">True</property>+                                        <property name="can_focus">True</property>+                                        <property name="invisible_char">●</property>+                                        <property name="progress_pulse_step">0.25</property>+                                        <property name="primary_icon_activatable">False</property>+                                        <property name="secondary_icon_activatable">False</property>+                                        <property name="primary_icon_sensitive">True</property>+                                        <property name="secondary_icon_sensitive">True</property>+                                        <property name="adjustment">Export Width</property>+                                        <property name="numeric">True</property>+                                        <property name="update_policy">if-valid</property>+                                      </object>+                                      <packing>+                                        <property name="expand">True</property>+                                        <property name="fill">True</property>+                                        <property name="position">0</property>+                                      </packing>+                                    </child>+                                    <child>+                                      <object class="GtkSpinButton" id="Dimensions Height">+                                        <property name="visible">True</property>+                                        <property name="can_focus">True</property>+                                        <property name="invisible_char">●</property>+                                        <property name="progress_pulse_step">0.25</property>+                                        <property name="primary_icon_activatable">False</property>+                                        <property name="secondary_icon_activatable">False</property>+                                        <property name="primary_icon_sensitive">True</property>+                                        <property name="secondary_icon_sensitive">True</property>+                                        <property name="adjustment">Export Height</property>+                                        <property name="numeric">True</property>+                                        <property name="update_policy">if-valid</property>+                                      </object>+                                      <packing>+                                        <property name="expand">True</property>+                                        <property name="fill">True</property>+                                        <property name="position">1</property>+                                      </packing>+                                    </child>+                                  </object>+                                  <packing>+                                    <property name="expand">True</property>+                                    <property name="fill">True</property>+                                    <property name="position">1</property>+                                  </packing>+                                </child>+                              </object>+                              <packing>+                                <property name="expand">True</property>+                                <property name="fill">True</property>+                                <property name="position">0</property>+                              </packing>+                            </child>+                            <child>+                              <object class="GtkVBox" id="File Name &amp; Type">+                                <property name="visible">True</property>+                                <property name="can_focus">False</property>+                                <child>+                                  <object class="GtkLabel" id="File Name Label">+                                    <property name="visible">True</property>+                                    <property name="can_focus">False</property>+                                    <property name="label" translatable="yes">File Name &amp; Type</property>+                                  </object>+                                  <packing>+                                    <property name="expand">True</property>+                                    <property name="fill">True</property>+                                    <property name="position">0</property>+                                  </packing>+                                </child>+                                <child>+                                  <object class="GtkHBox" id="File Name">+                                    <property name="visible">True</property>+                                    <property name="can_focus">False</property>+                                    <property name="border_width">1</property>+                                    <property name="spacing">2</property>+                                    <child>+                                      <object class="GtkEntry" id="File Entry">+                                        <property name="visible">True</property>+                                        <property name="can_focus">True</property>+                                        <property name="tooltip_text" translatable="yes">File Name</property>+                                        <property name="invisible_char">●</property>+                                        <property name="invisible_char_set">True</property>+                                        <property name="primary_icon_activatable">False</property>+                                        <property name="secondary_icon_activatable">False</property>+                                        <property name="primary_icon_sensitive">True</property>+                                        <property name="secondary_icon_sensitive">True</property>+                                      </object>+                                      <packing>+                                        <property name="expand">True</property>+                                        <property name="fill">True</property>+                                        <property name="position">0</property>+                                      </packing>+                                    </child>+                                    <child>+                                      <placeholder/>+                                    </child>+                                  </object>+                                  <packing>+                                    <property name="expand">True</property>+                                    <property name="fill">True</property>+                                    <property name="position">1</property>+                                  </packing>+                                </child>+                              </object>+                              <packing>+                                <property name="expand">True</property>+                                <property name="fill">True</property>+                                <property name="position">1</property>+                              </packing>+                            </child>+                            <child>+                              <object class="GtkButton" id="Export Button">+                                <property name="label" translatable="yes">Export</property>+                                <property name="visible">True</property>+                                <property name="can_focus">True</property>+                                <property name="receives_default">True</property>+                              </object>+                              <packing>+                                <property name="expand">True</property>+                                <property name="fill">True</property>+                                <property name="position">2</property>+                              </packing>+                            </child>+                          </object>+                        </child>+                        <child type="label">+                          <object class="GtkLabel" id="Export Frame Label">+                            <property name="visible">True</property>+                            <property name="can_focus">False</property>+                            <property name="label" translatable="yes">&lt;b&gt;Export&lt;/b&gt;</property>+                            <property name="use_markup">True</property>+                          </object>+                        </child>+                      </object>+                      <packing>+                        <property name="expand">False</property>+                        <property name="fill">True</property>+                        <property name="position">7</property>+                      </packing>+                    </child>+                  </object>+                </child>+              </object>+            </child>+          </object>+          <packing>+            <property name="expand">False</property>+            <property name="fill">True</property>+            <property name="position">2</property>+          </packing>+        </child>+      </object>+    </child>+  </object>+</interface>