2021-02-23 19:58:53 +00:00
|
|
|
{-# LANGUAGE BangPatterns #-}
|
2020-08-20 01:57:26 +00:00
|
|
|
{-# LANGUAGE BlockArguments #-}
|
2020-09-10 16:43:42 +00:00
|
|
|
{-# LANGUAGE DataKinds #-}
|
2020-08-20 01:57:26 +00:00
|
|
|
{-# LANGUAGE NamedFieldPuns #-}
|
|
|
|
{-# LANGUAGE NegativeLiterals #-}
|
2020-11-12 17:34:46 +00:00
|
|
|
{-# LANGUAGE OverloadedLabels #-}
|
2020-08-20 01:57:26 +00:00
|
|
|
{-# LANGUAGE OverloadedStrings #-}
|
2020-09-02 02:52:08 +00:00
|
|
|
{-# LANGUAGE RecordWildCards #-}
|
2020-09-06 12:54:18 +00:00
|
|
|
{-# LANGUAGE RecursiveDo #-}
|
2020-08-20 01:57:26 +00:00
|
|
|
{-# LANGUAGE ScopedTypeVariables #-}
|
|
|
|
{-# LANGUAGE TypeApplications #-}
|
2020-11-12 17:34:46 +00:00
|
|
|
{-# LANGUAGE TypeOperators #-}
|
2020-08-05 20:23:16 +00:00
|
|
|
|
2020-08-04 06:15:06 +00:00
|
|
|
module Main
|
|
|
|
( main )
|
|
|
|
where
|
|
|
|
|
2020-08-05 20:23:16 +00:00
|
|
|
-- base
|
2021-02-23 19:58:53 +00:00
|
|
|
import Control.Arrow
|
|
|
|
( (&&&) )
|
2020-08-06 03:06:18 +00:00
|
|
|
import Control.Monad
|
2021-02-23 19:58:53 +00:00
|
|
|
( forever, void )
|
2020-09-05 22:35:00 +00:00
|
|
|
import Data.Foldable
|
|
|
|
( for_ )
|
2020-09-10 16:43:42 +00:00
|
|
|
import Data.Function
|
|
|
|
( (&) )
|
2020-08-05 20:23:16 +00:00
|
|
|
import Data.Int
|
|
|
|
( Int32 )
|
|
|
|
import System.Exit
|
|
|
|
( exitSuccess )
|
2020-09-07 15:38:22 +00:00
|
|
|
import GHC.Conc
|
2021-02-23 19:58:53 +00:00
|
|
|
( forkIO, getNumProcessors, setNumCapabilities )
|
2020-08-05 20:23:16 +00:00
|
|
|
|
2020-08-10 14:38:27 +00:00
|
|
|
-- containers
|
2020-09-01 19:56:59 +00:00
|
|
|
import Data.Map.Strict
|
|
|
|
( Map )
|
2020-09-04 18:54:48 +00:00
|
|
|
import qualified Data.Map.Strict as Map
|
2020-11-12 17:34:46 +00:00
|
|
|
( adjust, empty )
|
2020-08-19 15:23:20 +00:00
|
|
|
import qualified Data.Sequence as Seq
|
|
|
|
( fromList )
|
2020-09-02 02:52:08 +00:00
|
|
|
import Data.Set
|
|
|
|
( Set )
|
|
|
|
import qualified Data.Set as Set
|
|
|
|
( empty )
|
2020-08-10 14:38:27 +00:00
|
|
|
|
2020-08-05 20:23:16 +00:00
|
|
|
-- directory
|
|
|
|
import qualified System.Directory as Directory
|
|
|
|
( canonicalizePath )
|
|
|
|
|
2020-09-10 16:43:42 +00:00
|
|
|
-- generic-lens
|
|
|
|
import Data.Generics.Product.Fields
|
|
|
|
( field' )
|
|
|
|
|
2020-11-12 17:34:46 +00:00
|
|
|
-- gi-cairo-render
|
|
|
|
import qualified GI.Cairo.Render as Cairo
|
|
|
|
( Render )
|
|
|
|
|
2020-08-04 06:15:06 +00:00
|
|
|
-- gi-cairo-connector
|
|
|
|
import qualified GI.Cairo.Render.Connector as Cairo
|
|
|
|
( renderWithContext )
|
|
|
|
|
|
|
|
-- gi-gdk
|
|
|
|
import qualified GI.Gdk as GDK
|
|
|
|
|
|
|
|
-- gi-gtk
|
|
|
|
import qualified GI.Gtk as GTK
|
|
|
|
|
2020-09-10 16:43:42 +00:00
|
|
|
-- lens
|
|
|
|
import Control.Lens
|
2020-11-12 17:34:46 +00:00
|
|
|
( (.~), set )
|
2020-11-14 22:32:23 +00:00
|
|
|
import Control.Lens.At
|
|
|
|
( at )
|
2020-09-10 16:43:42 +00:00
|
|
|
|
2020-08-10 14:38:27 +00:00
|
|
|
-- stm
|
2020-09-02 02:52:08 +00:00
|
|
|
import qualified Control.Concurrent.STM as STM
|
2021-02-23 19:58:53 +00:00
|
|
|
( atomically, retry )
|
2020-08-10 14:38:27 +00:00
|
|
|
import qualified Control.Concurrent.STM.TVar as STM
|
2021-02-23 19:58:53 +00:00
|
|
|
( modifyTVar', newTVarIO, readTVar, writeTVar )
|
2020-11-12 17:34:46 +00:00
|
|
|
|
|
|
|
-- superrecord
|
|
|
|
import qualified SuperRecord as Super
|
|
|
|
( Rec )
|
|
|
|
import qualified SuperRecord
|
|
|
|
( (:=)(..), (&), rnil )
|
2020-08-10 14:38:27 +00:00
|
|
|
|
2020-08-05 20:23:16 +00:00
|
|
|
-- text
|
|
|
|
import qualified Data.Text as Text
|
|
|
|
( pack )
|
|
|
|
|
2020-11-14 22:32:23 +00:00
|
|
|
-- transformers
|
|
|
|
import Control.Monad.Trans.Reader
|
|
|
|
( runReaderT )
|
|
|
|
|
|
|
|
-- unordered-containers
|
|
|
|
import Data.HashMap.Strict
|
|
|
|
( HashMap )
|
|
|
|
import qualified Data.HashMap.Strict as HashMap
|
|
|
|
( fromList )
|
|
|
|
|
2020-08-04 06:15:06 +00:00
|
|
|
-- MetaBrush
|
2020-09-07 15:38:22 +00:00
|
|
|
import Math.Bezier.Cubic.Fit
|
|
|
|
( FitParameters(..) )
|
2020-11-12 17:34:46 +00:00
|
|
|
import Math.Bezier.Spline
|
|
|
|
( Spline(..), Curves(..), Curve(..), NextPoint(..) )
|
2020-08-19 21:34:43 +00:00
|
|
|
import Math.Bezier.Stroke
|
2020-11-12 17:34:46 +00:00
|
|
|
( CachedStroke(..) )
|
2020-08-10 14:38:27 +00:00
|
|
|
import Math.Vector2D
|
2020-08-10 22:07:09 +00:00
|
|
|
( Point2D(..) )
|
2020-09-05 22:35:00 +00:00
|
|
|
import MetaBrush.Action
|
|
|
|
( ActionOrigin(..) )
|
2020-11-12 17:34:46 +00:00
|
|
|
import qualified MetaBrush.Asset.Brushes as Asset.Brushes
|
|
|
|
( circle )
|
2020-08-05 20:23:16 +00:00
|
|
|
import MetaBrush.Asset.Colours
|
2020-08-08 03:33:35 +00:00
|
|
|
( getColours )
|
2020-08-05 20:23:16 +00:00
|
|
|
import MetaBrush.Asset.Logo
|
|
|
|
( drawLogo )
|
2020-11-14 22:32:23 +00:00
|
|
|
import MetaBrush.Brush
|
|
|
|
( Brush, newBrushReference )
|
2020-09-02 02:52:08 +00:00
|
|
|
import MetaBrush.Context
|
|
|
|
( UIElements(..), Variables(..)
|
|
|
|
, Modifier(..)
|
|
|
|
, HoldAction(..), PartialPath(..)
|
|
|
|
)
|
2020-08-10 14:38:27 +00:00
|
|
|
import MetaBrush.Document
|
2020-09-05 22:35:00 +00:00
|
|
|
( Document(..), emptyDocument
|
|
|
|
, Stroke(..), FocusState(..)
|
2020-11-12 17:34:46 +00:00
|
|
|
, PointData(..)
|
2020-08-10 14:38:27 +00:00
|
|
|
)
|
2020-09-10 16:43:42 +00:00
|
|
|
import MetaBrush.Document.History
|
|
|
|
( DocumentHistory(..), newHistory )
|
|
|
|
import MetaBrush.Document.Update
|
|
|
|
( activeDocument, withActiveDocument )
|
2020-08-05 20:23:16 +00:00
|
|
|
import MetaBrush.Event
|
2020-09-02 02:52:08 +00:00
|
|
|
( handleEvents )
|
2020-08-15 21:49:14 +00:00
|
|
|
import MetaBrush.Render.Document
|
2021-02-23 19:58:53 +00:00
|
|
|
( blankRender, getDocumentRender )
|
2020-09-07 13:37:55 +00:00
|
|
|
import MetaBrush.Render.Rulers
|
|
|
|
( renderRuler )
|
2020-08-10 22:07:09 +00:00
|
|
|
import MetaBrush.UI.FileBar
|
2020-09-02 02:52:08 +00:00
|
|
|
( FileBar(..), createFileBar )
|
2020-08-10 22:07:09 +00:00
|
|
|
import MetaBrush.UI.InfoBar
|
2020-09-05 22:35:00 +00:00
|
|
|
( InfoBar(..), createInfoBar, updateInfoBar )
|
2020-08-05 20:23:16 +00:00
|
|
|
import MetaBrush.UI.Menu
|
2020-09-06 12:54:18 +00:00
|
|
|
( createMenuBar )
|
2020-08-10 22:07:09 +00:00
|
|
|
import MetaBrush.UI.Panels
|
|
|
|
( createPanelBar )
|
|
|
|
import MetaBrush.UI.ToolBar
|
2020-08-13 22:47:10 +00:00
|
|
|
( Tool(..), Mode(..), createToolBar )
|
2020-08-10 22:07:09 +00:00
|
|
|
import MetaBrush.UI.Viewport
|
2020-09-05 22:35:00 +00:00
|
|
|
( Viewport(..), Ruler(..), createViewport )
|
2020-08-16 22:09:16 +00:00
|
|
|
import MetaBrush.Unique
|
2020-09-01 19:56:59 +00:00
|
|
|
( newUniqueSupply
|
2020-11-14 22:32:23 +00:00
|
|
|
, Unique, freshUnique
|
2020-09-01 19:56:59 +00:00
|
|
|
, uniqueMapFromList
|
|
|
|
)
|
|
|
|
import MetaBrush.Util
|
|
|
|
( widgetAddClass, widgetAddClasses )
|
2020-08-05 20:23:16 +00:00
|
|
|
import qualified Paths_MetaBrush as Cabal
|
2020-08-04 06:15:06 +00:00
|
|
|
( getDataFileName )
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
main :: IO ()
|
|
|
|
main = do
|
|
|
|
|
2020-09-07 15:38:22 +00:00
|
|
|
procs <- getNumProcessors
|
|
|
|
let
|
|
|
|
caps :: Int
|
|
|
|
caps
|
|
|
|
| procs >= 6
|
|
|
|
= procs - 2
|
|
|
|
| procs >= 2
|
|
|
|
= procs - 1
|
|
|
|
| otherwise
|
|
|
|
= procs
|
|
|
|
setNumCapabilities caps
|
|
|
|
|
2020-08-10 14:38:27 +00:00
|
|
|
---------------------------------------------------------
|
|
|
|
-- Initialise state
|
|
|
|
|
2020-11-12 17:34:46 +00:00
|
|
|
uniqueSupply <- newUniqueSupply
|
|
|
|
|
|
|
|
circleBrush <- Asset.Brushes.circle uniqueSupply
|
2020-11-14 22:32:23 +00:00
|
|
|
circleBrushUnique <- runReaderT freshUnique uniqueSupply
|
|
|
|
docUnique <- runReaderT freshUnique uniqueSupply
|
|
|
|
strokeUnique <- runReaderT freshUnique uniqueSupply
|
2020-11-12 17:34:46 +00:00
|
|
|
|
|
|
|
let
|
2020-11-14 22:32:23 +00:00
|
|
|
|
|
|
|
testBrushes :: HashMap Brush Unique
|
|
|
|
testBrushes = HashMap.fromList
|
|
|
|
[ ( circleBrush, circleBrushUnique ) ]
|
|
|
|
|
2020-11-12 17:34:46 +00:00
|
|
|
testDocuments :: Map Unique DocumentHistory
|
|
|
|
testDocuments = fmap newHistory $ uniqueMapFromList
|
2020-11-14 22:32:23 +00:00
|
|
|
[ emptyDocument "Test" docUnique
|
2020-11-12 17:34:46 +00:00
|
|
|
& ( field' @"documentContent" . field' @"strokes" ) .~
|
|
|
|
[ Stroke
|
2020-11-14 22:32:23 +00:00
|
|
|
{ strokeName = "Stroke 1"
|
|
|
|
, strokeVisible = True
|
|
|
|
, strokeUnique = strokeUnique
|
|
|
|
, strokeBrushRef = newBrushReference @'[ "r" SuperRecord.:= Double ] circleBrushUnique
|
|
|
|
, strokeSpline =
|
2020-11-12 17:34:46 +00:00
|
|
|
Spline
|
|
|
|
{ splineStart = mkPoint ( Point2D 10 -20 ) 2
|
|
|
|
, splineCurves = OpenCurves $ Seq.fromList
|
|
|
|
[ LineTo { curveEnd = NextPoint ( mkPoint ( Point2D 10 10 ) 5 ), curveData = CachedStroke Nothing }
|
|
|
|
, LineTo { curveEnd = NextPoint ( mkPoint ( Point2D -10 10 ) 5 ), curveData = CachedStroke Nothing }
|
|
|
|
, LineTo { curveEnd = NextPoint ( mkPoint ( Point2D -10 -20 ) 2 ), curveData = CachedStroke Nothing }
|
|
|
|
]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
]
|
2020-11-14 22:32:23 +00:00
|
|
|
& ( field' @"documentBrushes" . at circleBrushUnique ) .~ ( Just circleBrush )
|
2020-11-12 17:34:46 +00:00
|
|
|
]
|
|
|
|
where
|
|
|
|
mkPoint :: Point2D Double -> Double -> PointData ( Super.Rec '[ "r" SuperRecord.:= Double ] )
|
|
|
|
mkPoint pt r = PointData pt Normal ( #r SuperRecord.:= r SuperRecord.& SuperRecord.rnil )
|
|
|
|
|
2021-02-23 19:58:53 +00:00
|
|
|
recomputeStrokesTVar <- STM.newTVarIO @Bool False
|
|
|
|
documentRenderTVar <- STM.newTVarIO @( Cairo.Render () ) ( pure () )
|
|
|
|
activeDocumentTVar <- STM.newTVarIO @( Maybe Unique ) Nothing
|
|
|
|
openDocumentsTVar <- STM.newTVarIO @( Map Unique DocumentHistory ) testDocuments
|
|
|
|
brushesTVar <- STM.newTVarIO @( HashMap Brush Unique ) testBrushes
|
|
|
|
mousePosTVar <- STM.newTVarIO @( Maybe ( Point2D Double ) ) Nothing
|
|
|
|
mouseHoldTVar <- STM.newTVarIO @( Maybe HoldAction ) Nothing
|
|
|
|
modifiersTVar <- STM.newTVarIO @( Set Modifier ) Set.empty
|
|
|
|
toolTVar <- STM.newTVarIO @Tool Selection
|
|
|
|
modeTVar <- STM.newTVarIO @Mode PathMode
|
|
|
|
debugTVar <- STM.newTVarIO @Bool False
|
|
|
|
partialPathTVar <- STM.newTVarIO @( Maybe PartialPath ) Nothing
|
|
|
|
fileBarTabsTVar <- STM.newTVarIO @( Map Unique ( GTK.Box, GTK.RadioButton ) ) Map.empty
|
|
|
|
showGuidesTVar <- STM.newTVarIO @Bool True
|
|
|
|
maxHistorySizeTVar <- STM.newTVarIO @Int 1000
|
|
|
|
fitParametersTVar <- STM.newTVarIO @FitParameters
|
|
|
|
( FitParameters
|
|
|
|
{ maxSubdiv = 6
|
|
|
|
, nbSegments = 12
|
|
|
|
, dist_tol = 5e-3
|
|
|
|
, t_tol = 1e-4
|
|
|
|
, maxIters = 100
|
|
|
|
}
|
|
|
|
)
|
2020-08-10 14:38:27 +00:00
|
|
|
|
2020-09-02 02:52:08 +00:00
|
|
|
-- Put all these stateful variables in a record for conciseness.
|
|
|
|
let
|
|
|
|
variables :: Variables
|
2020-09-05 22:35:00 +00:00
|
|
|
variables = Variables {..}
|
2020-09-02 02:52:08 +00:00
|
|
|
|
2020-08-04 06:15:06 +00:00
|
|
|
---------------------------------------------------------
|
|
|
|
-- Initialise GTK
|
|
|
|
|
2020-08-06 03:06:18 +00:00
|
|
|
void $ GTK.init Nothing
|
2020-08-04 06:15:06 +00:00
|
|
|
Just screen <- GDK.screenGetDefault
|
|
|
|
|
2020-08-05 20:23:16 +00:00
|
|
|
themePath <- Text.pack <$> ( Directory.canonicalizePath =<< Cabal.getDataFileName "theme.css" )
|
2020-08-04 06:15:06 +00:00
|
|
|
cssProvider <- GTK.cssProviderNew
|
|
|
|
GTK.cssProviderLoadFromPath cssProvider themePath
|
|
|
|
GTK.styleContextAddProviderForScreen screen cssProvider 1000
|
|
|
|
|
|
|
|
window <- GTK.windowNew GTK.WindowTypeToplevel
|
|
|
|
windowWidgetPath <- GTK.widgetGetPath window
|
|
|
|
widgetAddClass window "window"
|
|
|
|
GTK.setWindowResizable window True
|
2020-08-10 14:38:27 +00:00
|
|
|
GTK.setWindowDecorated window False
|
2020-08-04 06:15:06 +00:00
|
|
|
GTK.setWindowTitle window "MetaBrush"
|
2020-09-14 04:03:45 +00:00
|
|
|
GTK.windowSetDefaultSize window 1024 768
|
2020-08-12 20:43:47 +00:00
|
|
|
GTK.widgetAddEvents window
|
|
|
|
[ GDK.EventMaskKeyPressMask, GDK.EventMaskKeyReleaseMask ]
|
2020-08-04 06:15:06 +00:00
|
|
|
|
|
|
|
let
|
|
|
|
baseMinWidth, baseMinHeight :: Int32
|
2020-08-05 20:23:16 +00:00
|
|
|
baseMinWidth = 480
|
2020-08-04 06:15:06 +00:00
|
|
|
baseMinHeight = 240
|
|
|
|
|
|
|
|
windowGeometry <- GDK.newZeroGeometry
|
|
|
|
GDK.setGeometryMinWidth windowGeometry baseMinWidth
|
|
|
|
GDK.setGeometryMinHeight windowGeometry baseMinHeight
|
|
|
|
GTK.windowSetGeometryHints window ( Nothing @GTK.Widget )
|
|
|
|
( Just windowGeometry )
|
|
|
|
[ GDK.WindowHintsMinSize ]
|
|
|
|
|
2020-08-07 19:39:24 +00:00
|
|
|
iconPath <- Directory.canonicalizePath =<< Cabal.getDataFileName "icon.png"
|
|
|
|
GTK.windowSetIconFromFile window iconPath
|
|
|
|
|
2020-08-07 22:41:08 +00:00
|
|
|
colours <- getColours windowWidgetPath
|
2020-08-05 20:23:16 +00:00
|
|
|
|
2020-08-04 06:15:06 +00:00
|
|
|
---------------------------------------------------------
|
|
|
|
-- Create base UI elements
|
|
|
|
|
|
|
|
baseOverlay <- GTK.overlayNew
|
2020-08-05 20:23:16 +00:00
|
|
|
GTK.setContainerChild window baseOverlay
|
2020-08-04 06:15:06 +00:00
|
|
|
|
|
|
|
uiGrid <- GTK.gridNew
|
2020-08-05 20:23:16 +00:00
|
|
|
GTK.setContainerChild baseOverlay uiGrid
|
2020-08-04 06:15:06 +00:00
|
|
|
|
2020-08-08 13:53:06 +00:00
|
|
|
logo <- GTK.boxNew GTK.OrientationVertical 0
|
|
|
|
titleBar <- GTK.boxNew GTK.OrientationHorizontal 0
|
|
|
|
toolBar <- GTK.boxNew GTK.OrientationVertical 0
|
|
|
|
mainPane <- GTK.panedNew GTK.OrientationHorizontal
|
|
|
|
panelBox <- GTK.boxNew GTK.OrientationVertical 0
|
2020-08-04 06:15:06 +00:00
|
|
|
|
|
|
|
GTK.gridAttach uiGrid logo 0 0 1 2
|
2020-08-07 19:39:24 +00:00
|
|
|
GTK.gridAttach uiGrid titleBar 1 0 2 1
|
|
|
|
GTK.gridAttach uiGrid toolBar 0 2 2 1
|
|
|
|
GTK.gridAttach uiGrid mainPane 2 2 1 1
|
2020-08-05 21:30:36 +00:00
|
|
|
|
|
|
|
mainView <- GTK.boxNew GTK.OrientationVertical 0
|
|
|
|
|
2020-08-08 13:53:06 +00:00
|
|
|
GTK.panedPack1 mainPane mainView True False
|
|
|
|
GTK.panedPack2 mainPane panelBox False False
|
2020-08-05 21:30:36 +00:00
|
|
|
|
2020-08-06 00:45:20 +00:00
|
|
|
viewportGrid <- GTK.gridNew
|
|
|
|
|
2020-08-05 20:23:16 +00:00
|
|
|
---------------------------------------------------------
|
|
|
|
-- Background
|
|
|
|
|
|
|
|
widgetAddClass uiGrid "bg"
|
|
|
|
|
|
|
|
---------------------------------------------------------
|
2020-08-08 03:33:35 +00:00
|
|
|
-- Title bar
|
|
|
|
|
|
|
|
widgetAddClass titleBar "titleBar"
|
|
|
|
|
|
|
|
--------
|
2020-08-05 20:23:16 +00:00
|
|
|
-- Logo
|
|
|
|
|
|
|
|
widgetAddClass logo "logo"
|
|
|
|
|
|
|
|
logoArea <- GTK.drawingAreaNew
|
|
|
|
GTK.boxPackStart logo logoArea True True 0
|
|
|
|
|
2020-08-06 03:06:18 +00:00
|
|
|
void $ GTK.onWidgetDraw logoArea
|
2020-08-07 22:41:08 +00:00
|
|
|
$ Cairo.renderWithContext ( drawLogo colours )
|
2020-08-05 20:23:16 +00:00
|
|
|
|
2020-08-10 22:07:09 +00:00
|
|
|
------------
|
|
|
|
-- Title
|
2020-08-07 19:39:24 +00:00
|
|
|
|
2020-08-10 22:07:09 +00:00
|
|
|
title <- GTK.labelNew ( Just "MetaBrush" )
|
|
|
|
widgetAddClasses title [ "text", "title", "plain" ]
|
|
|
|
GTK.boxSetCenterWidget titleBar ( Just title )
|
2020-08-07 19:39:24 +00:00
|
|
|
|
2020-08-10 22:07:09 +00:00
|
|
|
---------------------------------------------------------
|
|
|
|
-- Main viewport
|
2020-08-07 19:39:24 +00:00
|
|
|
|
2020-11-12 17:34:46 +00:00
|
|
|
viewport@( Viewport {..} ) <- createViewport viewportGrid
|
2020-08-15 21:49:14 +00:00
|
|
|
|
|
|
|
-----------------
|
|
|
|
-- Viewport rendering
|
|
|
|
|
2021-02-23 19:58:53 +00:00
|
|
|
-- Update the document render data in a separate thread.
|
|
|
|
_ <- forkIO $ forever do
|
|
|
|
viewportWidth <- GTK.widgetGetAllocatedWidth viewportDrawingArea
|
|
|
|
viewportHeight <- GTK.widgetGetAllocatedHeight viewportDrawingArea
|
|
|
|
( !mbUpdatedDoc, renderDoc ) <- STM.atomically do
|
|
|
|
needsRecomputation <- STM.readTVar recomputeStrokesTVar
|
|
|
|
case needsRecomputation of
|
|
|
|
False -> STM.retry
|
|
|
|
True -> do
|
|
|
|
mbDocNow <- fmap present <$> activeDocument variables
|
|
|
|
case mbDocNow of
|
|
|
|
Nothing -> pure ( Nothing, blankRender colours )
|
|
|
|
Just doc -> do
|
|
|
|
modifiers <- STM.readTVar modifiersTVar
|
|
|
|
mbMousePos <- STM.readTVar mousePosTVar
|
|
|
|
mbHoldAction <- STM.readTVar mouseHoldTVar
|
|
|
|
mbPartialPath <- STM.readTVar partialPathTVar
|
|
|
|
mode <- STM.readTVar modeTVar
|
|
|
|
showGuides <- STM.readTVar showGuidesTVar
|
|
|
|
debug <- STM.readTVar debugTVar
|
|
|
|
fitParameters <- STM.readTVar fitParametersTVar
|
|
|
|
STM.writeTVar recomputeStrokesTVar False
|
|
|
|
let
|
|
|
|
addRulers :: ( Maybe Document, Cairo.Render () ) -> Cairo.Render ()
|
|
|
|
addRulers ( Nothing , newRender ) = newRender
|
|
|
|
addRulers ( Just newDoc, newRender ) = do
|
|
|
|
newRender
|
|
|
|
renderRuler
|
|
|
|
colours ( viewportWidth, viewportHeight ) ViewportOrigin ( viewportWidth, viewportHeight )
|
|
|
|
mbMousePos mbHoldAction showGuides
|
|
|
|
newDoc
|
|
|
|
pure $
|
|
|
|
( fst &&& addRulers ) $ getDocumentRender
|
|
|
|
colours fitParameters mode debug ( viewportWidth, viewportHeight )
|
|
|
|
modifiers mbMousePos mbHoldAction mbPartialPath
|
|
|
|
doc
|
|
|
|
STM.atomically do
|
|
|
|
STM.writeTVar documentRenderTVar renderDoc
|
|
|
|
for_ mbUpdatedDoc \ newDoc -> do
|
2020-11-12 17:34:46 +00:00
|
|
|
mbCurrDocUnique <- STM.readTVar activeDocumentTVar
|
|
|
|
for_ mbCurrDocUnique \ currDocUnique -> do
|
|
|
|
STM.modifyTVar' openDocumentsTVar ( Map.adjust ( set ( field' @"present" ) newDoc ) currDocUnique )
|
2021-02-23 19:58:53 +00:00
|
|
|
GTK.widgetQueueDraw viewportDrawingArea
|
2020-09-02 02:52:08 +00:00
|
|
|
|
2021-02-23 19:58:53 +00:00
|
|
|
-- Render the document using the latest available draw data.
|
|
|
|
void $ GTK.onWidgetDraw viewportDrawingArea \ ctx -> do
|
|
|
|
-- Get the Cairo instructions for rendering the current document
|
|
|
|
mbDoc <- fmap present <$> STM.atomically ( activeDocument variables )
|
|
|
|
render <- case mbDoc of
|
|
|
|
Nothing -> pure ( blankRender colours )
|
|
|
|
Just _ -> STM.atomically do
|
|
|
|
STM.readTVar documentRenderTVar
|
|
|
|
Cairo.renderWithContext render ctx
|
2020-08-15 21:49:14 +00:00
|
|
|
pure True
|
2020-08-07 19:39:24 +00:00
|
|
|
|
2021-02-23 19:58:53 +00:00
|
|
|
for_ [ ( rulerCornerDrawingArea , RulerCorner )
|
|
|
|
, ( topRulerDrawingArea , TopRuler )
|
|
|
|
, ( leftRulerDrawingArea , LeftRuler )
|
|
|
|
] \ ( rulerDrawingArea, ruler ) -> do
|
2020-09-05 22:35:00 +00:00
|
|
|
void $ GTK.onWidgetDraw rulerDrawingArea \ ctx -> do
|
|
|
|
viewportWidth <- GTK.widgetGetAllocatedWidth viewportDrawingArea
|
|
|
|
viewportHeight <- GTK.widgetGetAllocatedHeight viewportDrawingArea
|
|
|
|
width <- GTK.widgetGetAllocatedWidth rulerDrawingArea
|
|
|
|
height <- GTK.widgetGetAllocatedHeight rulerDrawingArea
|
2020-11-12 17:34:46 +00:00
|
|
|
mbRender <- STM.atomically $ withActiveDocument variables \ doc -> do
|
2020-09-05 22:35:00 +00:00
|
|
|
mbMousePos <- STM.readTVar mousePosTVar
|
|
|
|
mbHoldAction <- STM.readTVar mouseHoldTVar
|
2020-09-06 03:32:03 +00:00
|
|
|
showGuides <- STM.readTVar showGuidesTVar
|
2020-09-05 22:35:00 +00:00
|
|
|
pure do
|
2020-09-07 13:37:55 +00:00
|
|
|
renderRuler
|
|
|
|
colours ( viewportWidth, viewportHeight ) ( RulerOrigin ruler ) ( width, height )
|
|
|
|
mbMousePos mbHoldAction showGuides
|
|
|
|
doc
|
2020-09-05 22:35:00 +00:00
|
|
|
for_ mbRender \ render -> Cairo.renderWithContext render ctx
|
|
|
|
|
|
|
|
pure True
|
|
|
|
|
2020-08-20 01:57:26 +00:00
|
|
|
---------------------------------------------------------
|
|
|
|
-- Tool bar
|
|
|
|
|
2021-02-23 19:58:53 +00:00
|
|
|
_ <- createToolBar variables colours toolBar
|
2020-08-20 01:57:26 +00:00
|
|
|
|
2020-08-10 22:07:09 +00:00
|
|
|
---------------------------------------------------------
|
|
|
|
-- Info bar
|
2020-08-07 19:39:24 +00:00
|
|
|
|
2020-09-02 02:52:08 +00:00
|
|
|
infoBar@( InfoBar { infoBarArea } ) <- createInfoBar colours
|
2020-08-06 03:06:18 +00:00
|
|
|
|
2020-09-06 12:54:18 +00:00
|
|
|
rec
|
2020-09-01 19:56:59 +00:00
|
|
|
|
2020-09-06 12:54:18 +00:00
|
|
|
---------------------------------------------------------
|
|
|
|
-- File bar
|
2020-08-10 14:38:27 +00:00
|
|
|
|
2020-09-06 12:54:18 +00:00
|
|
|
fileBar@( FileBar { fileBarBox } ) <-
|
|
|
|
createFileBar
|
|
|
|
colours
|
|
|
|
variables
|
|
|
|
window titleBar title viewport infoBar menu
|
2020-09-02 20:49:50 +00:00
|
|
|
|
2020-09-06 12:54:18 +00:00
|
|
|
------------
|
|
|
|
-- Menu bar
|
|
|
|
|
|
|
|
let
|
|
|
|
uiElements :: UIElements
|
|
|
|
uiElements = UIElements { menu, fileBar, .. }
|
2020-09-02 20:49:50 +00:00
|
|
|
|
2020-09-06 12:54:18 +00:00
|
|
|
menu <- createMenuBar uiElements variables colours
|
2020-09-05 22:35:00 +00:00
|
|
|
|
2020-09-06 12:54:18 +00:00
|
|
|
GTK.boxPackStart mainView fileBarBox False False 0
|
|
|
|
GTK.boxPackStart mainView viewportGrid True True 0
|
|
|
|
GTK.boxPackStart mainView infoBarArea False False 0
|
2020-09-02 20:49:50 +00:00
|
|
|
|
2020-08-05 20:23:16 +00:00
|
|
|
---------------------------------------------------------
|
|
|
|
-- Panels
|
|
|
|
|
2020-08-10 22:07:09 +00:00
|
|
|
createPanelBar panelBox
|
2020-08-05 20:23:16 +00:00
|
|
|
|
|
|
|
---------------------------------------------------------
|
2020-08-04 06:15:06 +00:00
|
|
|
-- Actions
|
|
|
|
|
2020-09-02 20:49:50 +00:00
|
|
|
handleEvents uiElements variables
|
2020-08-07 19:39:24 +00:00
|
|
|
|
2020-08-05 20:23:16 +00:00
|
|
|
---------------------------------------------------------
|
|
|
|
-- GTK main loop
|
2020-08-04 06:15:06 +00:00
|
|
|
|
|
|
|
GTK.widgetShowAll window
|
2020-09-10 16:43:42 +00:00
|
|
|
mbDoc <- fmap present <$> ( STM.atomically $ activeDocument variables )
|
|
|
|
updateInfoBar viewportDrawingArea infoBar variables mbDoc -- need to update the info bar after widgets have been realized
|
2020-08-04 06:15:06 +00:00
|
|
|
GTK.main
|
2020-08-05 20:23:16 +00:00
|
|
|
|
|
|
|
exitSuccess
|