2020-08-05 20:23:16 +00:00
|
|
|
{-# LANGUAGE BlockArguments #-}
|
2020-08-06 03:06:18 +00:00
|
|
|
{-# LANGUAGE LambdaCase #-}
|
2020-08-10 14:38:27 +00:00
|
|
|
{-# LANGUAGE NamedFieldPuns #-}
|
2020-08-05 20:23:16 +00:00
|
|
|
{-# LANGUAGE OverloadedStrings #-}
|
2020-08-10 14:38:27 +00:00
|
|
|
{-# LANGUAGE PatternSynonyms #-}
|
2020-08-05 20:23:16 +00:00
|
|
|
{-# LANGUAGE RecordWildCards #-}
|
|
|
|
{-# LANGUAGE TypeApplications #-}
|
|
|
|
|
2020-08-04 06:15:06 +00:00
|
|
|
module Main
|
|
|
|
( main )
|
|
|
|
where
|
|
|
|
|
2020-08-05 20:23:16 +00:00
|
|
|
-- base
|
2020-08-06 03:06:18 +00:00
|
|
|
import Control.Monad
|
2020-08-10 22:07:09 +00:00
|
|
|
( void )
|
2020-08-05 20:23:16 +00:00
|
|
|
import Data.Int
|
|
|
|
( Int32 )
|
2020-08-10 14:38:27 +00:00
|
|
|
import Data.Word
|
|
|
|
( Word32 )
|
2020-08-05 20:23:16 +00:00
|
|
|
import System.Exit
|
|
|
|
( exitSuccess )
|
|
|
|
|
2020-08-10 14:38:27 +00:00
|
|
|
-- containers
|
|
|
|
import Data.IntMap.Strict
|
|
|
|
( IntMap )
|
|
|
|
import qualified Data.IntMap.Strict as IntMap
|
2020-08-10 22:07:09 +00:00
|
|
|
( fromList )
|
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-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-08-10 14:38:27 +00:00
|
|
|
-- stm
|
|
|
|
import qualified Control.Concurrent.STM.TVar as STM
|
2020-08-10 22:07:09 +00:00
|
|
|
( newTVarIO )
|
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-08-04 06:15:06 +00:00
|
|
|
-- MetaBrush
|
2020-08-10 14:38:27 +00:00
|
|
|
import Math.Vector2D
|
2020-08-10 22:07:09 +00:00
|
|
|
( Point2D(..) )
|
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-08-10 14:38:27 +00:00
|
|
|
import MetaBrush.Document
|
2020-08-13 17:05:19 +00:00
|
|
|
( Document(..), AABB(..)
|
|
|
|
, Stroke(..), StrokePoint(..), PointType(..), FocusState(..)
|
2020-08-13 22:47:10 +00:00
|
|
|
, Overlay
|
2020-08-10 14:38:27 +00:00
|
|
|
)
|
2020-08-05 20:23:16 +00:00
|
|
|
import MetaBrush.Event
|
2020-08-12 20:43:47 +00:00
|
|
|
( handleEvents )
|
2020-08-05 20:23:16 +00:00
|
|
|
import MetaBrush.Render.Util
|
|
|
|
( widgetAddClass, widgetAddClasses )
|
2020-08-13 22:47:10 +00:00
|
|
|
import MetaBrush.Time
|
|
|
|
( Time )
|
2020-08-10 22:07:09 +00:00
|
|
|
import MetaBrush.UI.FileBar
|
|
|
|
( createFileBar )
|
|
|
|
import MetaBrush.UI.InfoBar
|
|
|
|
( createInfoBar )
|
2020-08-05 20:23:16 +00:00
|
|
|
import MetaBrush.UI.Menu
|
2020-08-10 22:07:09 +00:00
|
|
|
( createMenuBar )
|
|
|
|
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
|
|
|
|
( Viewport(..), createViewport )
|
2020-08-05 20:23:16 +00:00
|
|
|
import qualified Paths_MetaBrush as Cabal
|
2020-08-04 06:15:06 +00:00
|
|
|
( getDataFileName )
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
2020-08-10 14:38:27 +00:00
|
|
|
testDocuments :: IntMap Document
|
|
|
|
testDocuments = IntMap.fromList
|
|
|
|
$ zip [0..]
|
|
|
|
[ Document
|
|
|
|
{ displayName = "Document 1"
|
|
|
|
, filePath = Nothing
|
|
|
|
, unsavedChanges = False
|
2020-08-13 17:05:19 +00:00
|
|
|
, strokes = [ Stroke
|
|
|
|
[ StrokePoint ( Point2D 0 0 ) PathPoint Normal ]
|
|
|
|
"Stroke1"
|
|
|
|
False
|
|
|
|
, Stroke
|
|
|
|
[ StrokePoint ( Point2D 100 0 ) PathPoint Hover
|
|
|
|
, StrokePoint ( Point2D 105 0 ) ControlPoint Normal
|
|
|
|
, StrokePoint ( Point2D 110 0 ) PathPoint Selected
|
|
|
|
]
|
|
|
|
"Stroke2"
|
|
|
|
True
|
|
|
|
, Stroke
|
|
|
|
[ StrokePoint ( Point2D 0 100 ) PathPoint Normal ]
|
|
|
|
"Stroke3"
|
|
|
|
True
|
|
|
|
, Stroke
|
|
|
|
[ StrokePoint ( Point2D 100 100 ) PathPoint Normal
|
|
|
|
, StrokePoint ( Point2D 105 105 ) ControlPoint Selected
|
|
|
|
, StrokePoint ( Point2D 110 100 ) PathPoint Normal
|
|
|
|
]
|
|
|
|
"Stroke4"
|
|
|
|
True
|
2020-08-10 22:07:09 +00:00
|
|
|
]
|
2020-08-13 17:05:19 +00:00
|
|
|
, bounds = AABB ( Point2D 0 0 ) ( Point2D 100 100 )
|
2020-08-10 14:38:27 +00:00
|
|
|
, viewportCenter = Point2D 50 50
|
|
|
|
, zoomFactor = 1
|
|
|
|
}
|
|
|
|
, Document
|
|
|
|
{ displayName = "Document 2"
|
|
|
|
, filePath = Nothing
|
|
|
|
, unsavedChanges = True
|
2020-08-13 17:05:19 +00:00
|
|
|
, strokes = [ Stroke
|
|
|
|
[ StrokePoint ( Point2D 0 0 ) PathPoint Normal
|
|
|
|
, StrokePoint ( Point2D 10 10 ) ControlPoint Normal
|
|
|
|
, StrokePoint ( Point2D 20 20 ) PathPoint Normal
|
|
|
|
]
|
|
|
|
"Stroke1"
|
|
|
|
True
|
|
|
|
]
|
2020-08-10 14:38:27 +00:00
|
|
|
, bounds = AABB ( Point2D 0 0 ) ( Point2D 50 50 )
|
|
|
|
, viewportCenter = Point2D 10 10
|
|
|
|
, zoomFactor = 0.25
|
|
|
|
}
|
|
|
|
]
|
|
|
|
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
|
2020-08-04 06:15:06 +00:00
|
|
|
main :: IO ()
|
|
|
|
main = do
|
|
|
|
|
2020-08-10 14:38:27 +00:00
|
|
|
---------------------------------------------------------
|
|
|
|
-- Initialise state
|
|
|
|
|
2020-08-13 22:47:10 +00:00
|
|
|
activeDocumentTVar <- STM.newTVarIO @( Maybe Int ) Nothing
|
|
|
|
openDocumentsTVar <- STM.newTVarIO @( IntMap Document ) testDocuments
|
|
|
|
mousePosTVar <- STM.newTVarIO @( Maybe ( Point2D Double ) ) Nothing
|
|
|
|
mouseHoldTVar <- STM.newTVarIO @( Maybe ( Point2D Double, Time ) ) Nothing
|
|
|
|
pressedKeysTVar <- STM.newTVarIO @[ Word32 ] []
|
|
|
|
toolTVar <- STM.newTVarIO @Tool Selection
|
|
|
|
modeTVar <- STM.newTVarIO @Mode Path
|
|
|
|
overlayTVar <- STM.newTVarIO @( Maybe Overlay ) Nothing
|
2020-08-10 14:38:27 +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"
|
|
|
|
GTK.windowSetDefaultSize window 800 600
|
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
|
|
|
fileBar <- GTK.scrolledWindowNew ( Nothing @GTK.Adjustment ) ( Nothing @GTK.Adjustment )
|
|
|
|
viewportGrid <- GTK.gridNew
|
|
|
|
infoBar <- GTK.boxNew GTK.OrientationHorizontal 0
|
|
|
|
|
|
|
|
GTK.boxPackStart mainView fileBar False False 0
|
2020-08-05 21:30:36 +00:00
|
|
|
GTK.boxPackStart mainView viewportGrid True True 0
|
|
|
|
GTK.boxPackStart mainView infoBar False False 0
|
2020-08-04 06:15:06 +00:00
|
|
|
|
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-08 03:33:35 +00:00
|
|
|
------------
|
|
|
|
-- Menu bar
|
2020-08-05 20:23:16 +00:00
|
|
|
|
2020-08-10 22:07:09 +00:00
|
|
|
_ <- createMenuBar colours window titleBar
|
2020-08-07 19:39:24 +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-05 20:23:16 +00:00
|
|
|
---------------------------------------------------------
|
|
|
|
-- Tool bar
|
|
|
|
|
2020-08-13 22:47:10 +00:00
|
|
|
_ <- createToolBar toolTVar modeTVar colours toolBar
|
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-08-10 22:07:09 +00:00
|
|
|
Viewport { viewportDrawingArea } <-
|
|
|
|
createViewport
|
|
|
|
colours
|
|
|
|
activeDocumentTVar
|
|
|
|
openDocumentsTVar
|
2020-08-13 22:47:10 +00:00
|
|
|
overlayTVar
|
2020-08-10 22:07:09 +00:00
|
|
|
viewportGrid
|
2020-08-07 19:39:24 +00:00
|
|
|
|
2020-08-10 22:07:09 +00:00
|
|
|
---------------------------------------------------------
|
|
|
|
-- Info bar
|
2020-08-07 19:39:24 +00:00
|
|
|
|
2020-08-10 22:07:09 +00:00
|
|
|
infoBarElements <- createInfoBar colours infoBar
|
2020-08-06 03:06:18 +00:00
|
|
|
|
2020-08-10 14:38:27 +00:00
|
|
|
---------------------------------------------------------
|
|
|
|
-- File bar
|
|
|
|
|
2020-08-10 22:07:09 +00:00
|
|
|
_ <-
|
|
|
|
createFileBar
|
|
|
|
activeDocumentTVar
|
|
|
|
openDocumentsTVar
|
|
|
|
window
|
|
|
|
title
|
|
|
|
viewportDrawingArea
|
2020-08-12 20:43:47 +00:00
|
|
|
infoBarElements
|
2020-08-10 22:07:09 +00:00
|
|
|
fileBar
|
2020-08-10 14:38:27 +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-08-12 20:43:47 +00:00
|
|
|
handleEvents
|
2020-08-13 22:47:10 +00:00
|
|
|
activeDocumentTVar openDocumentsTVar
|
|
|
|
mousePosTVar mouseHoldTVar pressedKeysTVar
|
|
|
|
toolTVar modeTVar
|
|
|
|
overlayTVar
|
2020-08-12 20:43:47 +00:00
|
|
|
window viewportDrawingArea infoBarElements
|
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
|
|
|
|
GTK.main
|
2020-08-05 20:23:16 +00:00
|
|
|
|
|
|
|
exitSuccess
|