mirror of
https://gitlab.com/sheaf/metabrush.git
synced 2024-11-05 23:03:38 +00:00
add MenuBar
This commit is contained in:
parent
c9e702e660
commit
f224c6b738
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -1,5 +1,9 @@
|
||||||
dist-newstyle/
|
dist-newstyle/
|
||||||
|
cabal.project.local
|
||||||
|
|
||||||
assets/*.svg
|
assets/*.svg
|
||||||
assets/*/
|
assets/*/
|
||||||
|
|
||||||
*.txt
|
*.txt
|
||||||
cabal.project.local
|
*.md
|
||||||
|
*.html
|
||||||
|
|
|
@ -3,11 +3,13 @@ name: MetaBrush
|
||||||
version: 0.1.0.0
|
version: 0.1.0.0
|
||||||
synopsis: GUI for brush calligraphy.
|
synopsis: GUI for brush calligraphy.
|
||||||
category: Calligraphy, Font, Geometry, Graphics, GUI
|
category: Calligraphy, Font, Geometry, Graphics, GUI
|
||||||
license: BSD-3-Clause
|
license: NONE
|
||||||
homepage: https://gitlab.com/sheaf/MetaBrush
|
homepage: https://gitlab.com/sheaf/MetaBrush
|
||||||
build-type: Simple
|
build-type: Simple
|
||||||
|
data-dir:
|
||||||
|
assets
|
||||||
data-files:
|
data-files:
|
||||||
assets/theme.css
|
theme.css
|
||||||
description:
|
description:
|
||||||
|
|
||||||
MetaBrush is a GUI for brush calligraphy based on Bézier curves.
|
MetaBrush is a GUI for brush calligraphy based on Bézier curves.
|
||||||
|
@ -39,6 +41,7 @@ common common
|
||||||
-fwarn-incomplete-patterns
|
-fwarn-incomplete-patterns
|
||||||
-fwarn-incomplete-uni-patterns
|
-fwarn-incomplete-uni-patterns
|
||||||
-fwarn-missing-deriving-strategies
|
-fwarn-missing-deriving-strategies
|
||||||
|
-fno-warn-unticked-promoted-constructors
|
||||||
|
|
||||||
library
|
library
|
||||||
|
|
||||||
|
@ -68,6 +71,9 @@ library
|
||||||
|
|
||||||
executable MetaBrush
|
executable MetaBrush
|
||||||
|
|
||||||
|
import:
|
||||||
|
common
|
||||||
|
|
||||||
hs-source-dirs:
|
hs-source-dirs:
|
||||||
src/app
|
src/app
|
||||||
, app
|
, app
|
||||||
|
@ -77,14 +83,17 @@ executable MetaBrush
|
||||||
|
|
||||||
other-modules:
|
other-modules:
|
||||||
MetaBrush.Asset.Brush
|
MetaBrush.Asset.Brush
|
||||||
|
, MetaBrush.Asset.Colours
|
||||||
, MetaBrush.Asset.Logo
|
, MetaBrush.Asset.Logo
|
||||||
, MetaBrush.Asset.Magnifier
|
, MetaBrush.Asset.Magnifier
|
||||||
, MetaBrush.Asset.Meta
|
, MetaBrush.Asset.Meta
|
||||||
, MetaBrush.Asset.TickBox
|
, MetaBrush.Asset.TickBox
|
||||||
, MetaBrush.Asset.WindowIcons
|
, MetaBrush.Asset.WindowIcons
|
||||||
, MetaBrush.Document
|
, MetaBrush.Document
|
||||||
|
, MetaBrush.Event
|
||||||
, MetaBrush.Render.Util
|
, MetaBrush.Render.Util
|
||||||
, MetaBrush.Stroke
|
, MetaBrush.Stroke
|
||||||
|
, MetaBrush.UI.Menu
|
||||||
, Paths_MetaBrush
|
, Paths_MetaBrush
|
||||||
|
|
||||||
autogen-modules:
|
autogen-modules:
|
||||||
|
@ -95,8 +104,14 @@ executable MetaBrush
|
||||||
|
|
||||||
build-depends:
|
build-depends:
|
||||||
MetaBrush
|
MetaBrush
|
||||||
|
, directory
|
||||||
|
>= 1.3.4.0 && < 1.4
|
||||||
|
, generic-lens
|
||||||
|
>= 1.2.0.1 && < 2.0
|
||||||
, gi-gdk
|
, gi-gdk
|
||||||
>= 3.0.22 && < 3.1
|
>= 3.0.22 && < 3.1
|
||||||
|
, gi-gio
|
||||||
|
>= 2.0.27 && < 2.1
|
||||||
, gi-glib
|
, gi-glib
|
||||||
>= 2.0.23 && < 2.1
|
>= 2.0.23 && < 2.1
|
||||||
, gi-gtk
|
, gi-gtk
|
||||||
|
|
164
app/Main.hs
164
app/Main.hs
|
@ -1,7 +1,22 @@
|
||||||
|
{-# LANGUAGE BlockArguments #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
|
{-# LANGUAGE TypeApplications #-}
|
||||||
|
|
||||||
module Main
|
module Main
|
||||||
( main )
|
( main )
|
||||||
where
|
where
|
||||||
|
|
||||||
|
-- base
|
||||||
|
import Data.Int
|
||||||
|
( Int32 )
|
||||||
|
import System.Exit
|
||||||
|
( exitSuccess )
|
||||||
|
|
||||||
|
-- directory
|
||||||
|
import qualified System.Directory as Directory
|
||||||
|
( canonicalizePath )
|
||||||
|
|
||||||
-- gi-cairo-connector
|
-- gi-cairo-connector
|
||||||
import qualified GI.Cairo.Render.Connector as Cairo
|
import qualified GI.Cairo.Render.Connector as Cairo
|
||||||
( renderWithContext )
|
( renderWithContext )
|
||||||
|
@ -12,8 +27,22 @@ import qualified GI.Gdk as GDK
|
||||||
-- gi-gtk
|
-- gi-gtk
|
||||||
import qualified GI.Gtk as GTK
|
import qualified GI.Gtk as GTK
|
||||||
|
|
||||||
|
-- text
|
||||||
|
import qualified Data.Text as Text
|
||||||
|
( pack )
|
||||||
|
|
||||||
-- MetaBrush
|
-- MetaBrush
|
||||||
import Paths_MetaBrush
|
import MetaBrush.Asset.Colours
|
||||||
|
( ColourRecord(..), colours )
|
||||||
|
import MetaBrush.Asset.Logo
|
||||||
|
( drawLogo )
|
||||||
|
import MetaBrush.Event
|
||||||
|
( handleKeyboardPressEvent, handleKeyboardReleaseEvent )
|
||||||
|
import MetaBrush.Render.Util
|
||||||
|
( widgetAddClass, widgetAddClasses )
|
||||||
|
import MetaBrush.UI.Menu
|
||||||
|
( newMenuBar )
|
||||||
|
import qualified Paths_MetaBrush as Cabal
|
||||||
( getDataFileName )
|
( getDataFileName )
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
@ -27,7 +56,7 @@ main = do
|
||||||
_ <- GTK.init Nothing
|
_ <- GTK.init Nothing
|
||||||
Just screen <- GDK.screenGetDefault
|
Just screen <- GDK.screenGetDefault
|
||||||
|
|
||||||
themePath <- getDataFileName "theme.css"
|
themePath <- Text.pack <$> ( Directory.canonicalizePath =<< Cabal.getDataFileName "theme.css" )
|
||||||
cssProvider <- GTK.cssProviderNew
|
cssProvider <- GTK.cssProviderNew
|
||||||
GTK.cssProviderLoadFromPath cssProvider themePath
|
GTK.cssProviderLoadFromPath cssProvider themePath
|
||||||
GTK.styleContextAddProviderForScreen screen cssProvider 1000
|
GTK.styleContextAddProviderForScreen screen cssProvider 1000
|
||||||
|
@ -36,13 +65,13 @@ main = do
|
||||||
windowWidgetPath <- GTK.widgetGetPath window
|
windowWidgetPath <- GTK.widgetGetPath window
|
||||||
widgetAddClass window "window"
|
widgetAddClass window "window"
|
||||||
GTK.setWindowResizable window True
|
GTK.setWindowResizable window True
|
||||||
GTK.setWindowDecorated window False
|
GTK.setWindowDecorated window True
|
||||||
GTK.setWindowTitle window "MetaBrush"
|
GTK.setWindowTitle window "MetaBrush"
|
||||||
GTK.windowSetDefaultSize window 800 600
|
GTK.windowSetDefaultSize window 800 600
|
||||||
|
|
||||||
let
|
let
|
||||||
baseMinWidth, baseMinHeight :: Int32
|
baseMinWidth, baseMinHeight :: Int32
|
||||||
baseMinWidth = 320
|
baseMinWidth = 480
|
||||||
baseMinHeight = 240
|
baseMinHeight = 240
|
||||||
|
|
||||||
windowGeometry <- GDK.newZeroGeometry
|
windowGeometry <- GDK.newZeroGeometry
|
||||||
|
@ -52,14 +81,16 @@ main = do
|
||||||
( Just windowGeometry )
|
( Just windowGeometry )
|
||||||
[ GDK.WindowHintsMinSize ]
|
[ GDK.WindowHintsMinSize ]
|
||||||
|
|
||||||
|
Colours { .. } <- colours windowWidgetPath
|
||||||
|
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
-- Create base UI elements
|
-- Create base UI elements
|
||||||
|
|
||||||
baseOverlay <- GTK.overlayNew
|
baseOverlay <- GTK.overlayNew
|
||||||
GT.setContainerChild window baseOverlay
|
GTK.setContainerChild window baseOverlay
|
||||||
|
|
||||||
uiGrid <- GTK.gridNew
|
uiGrid <- GTK.gridNew
|
||||||
GTK.overlaySetChild baseOverlay uiGrid
|
GTK.setContainerChild baseOverlay uiGrid
|
||||||
|
|
||||||
logo <- GTK.boxNew GTK.OrientationVertical 0
|
logo <- GTK.boxNew GTK.OrientationVertical 0
|
||||||
titleBar <- GTK.boxNew GTK.OrientationHorizontal 0
|
titleBar <- GTK.boxNew GTK.OrientationHorizontal 0
|
||||||
|
@ -77,15 +108,124 @@ main = do
|
||||||
GTK.gridAttach uiGrid panelGrid 3 2 1 2
|
GTK.gridAttach uiGrid panelGrid 3 2 1 2
|
||||||
GTK.gridAttach uiGrid infoBar 2 3 1 1
|
GTK.gridAttach uiGrid infoBar 2 3 1 1
|
||||||
|
|
||||||
--------------------------------------
|
---------------------------------------------------------
|
||||||
|
-- Background
|
||||||
|
|
||||||
|
widgetAddClass uiGrid "bg"
|
||||||
|
|
||||||
|
---------------------------------------------------------
|
||||||
|
-- Logo
|
||||||
|
|
||||||
|
widgetAddClass logo "logo"
|
||||||
|
|
||||||
|
logoArea <- GTK.drawingAreaNew
|
||||||
|
GTK.boxPackStart logo logoArea True True 0
|
||||||
|
|
||||||
|
_ <- GTK.onWidgetDraw logoArea
|
||||||
|
$ Cairo.renderWithContext
|
||||||
|
( drawLogo logo_base logo_highlight logo_base )
|
||||||
|
|
||||||
|
---------------------------------------------------------
|
||||||
|
-- Title bar
|
||||||
|
|
||||||
|
widgetAddClass titleBar "titleBar"
|
||||||
|
|
||||||
|
( menuBar, _menu ) <- newMenuBar
|
||||||
|
widgetAddClasses menuBar [ "text", "plain" ]
|
||||||
|
|
||||||
|
GTK.boxPackStart titleBar menuBar False False 0
|
||||||
|
|
||||||
|
title <- GTK.labelNew ( Just "● New Document – MetaBrush" )
|
||||||
|
widgetAddClasses title [ "text", "title", "plain" ]
|
||||||
|
GTK.labelSetJustify title GTK.JustificationCenter
|
||||||
|
GTK.widgetSetHalign title GTK.AlignCenter
|
||||||
|
GTK.boxPackStart titleBar title True True 0
|
||||||
|
|
||||||
|
---------------------------------------------------------
|
||||||
|
-- Tool bar
|
||||||
|
|
||||||
|
widgetAddClass toolBar "toolBar"
|
||||||
|
|
||||||
|
---------------------------------------------------------
|
||||||
|
-- File bar
|
||||||
|
|
||||||
|
widgetAddClass fileBar "fileBar"
|
||||||
|
|
||||||
|
---------------------------------------------------------
|
||||||
|
-- Main viewport
|
||||||
|
|
||||||
|
widgetAddClass mainView "viewport_bg"
|
||||||
|
|
||||||
|
rvRulerCorner <- GTK.revealerNew
|
||||||
|
rvLeftRuler <- GTK.revealerNew
|
||||||
|
rvTopRuler <- GTK.revealerNew
|
||||||
|
viewport <- GTK.drawingAreaNew
|
||||||
|
|
||||||
|
GTK.gridAttach mainView rvRulerCorner 0 0 1 1
|
||||||
|
GTK.gridAttach mainView rvLeftRuler 0 1 1 1
|
||||||
|
GTK.gridAttach mainView rvTopRuler 1 0 1 1
|
||||||
|
GTK.gridAttach mainView viewport 1 1 1 1
|
||||||
|
|
||||||
|
rulerCorner <- GTK.boxNew GTK.OrientationVertical 0
|
||||||
|
leftRuler <- GTK.boxNew GTK.OrientationVertical 0
|
||||||
|
topRuler <- GTK.boxNew GTK.OrientationHorizontal 0
|
||||||
|
|
||||||
|
GTK.containerAdd rvRulerCorner rulerCorner
|
||||||
|
GTK.containerAdd rvLeftRuler leftRuler
|
||||||
|
GTK.containerAdd rvTopRuler topRuler
|
||||||
|
|
||||||
|
widgetAddClass rulerCorner "ruler"
|
||||||
|
widgetAddClass leftRuler "ruler"
|
||||||
|
widgetAddClass topRuler "ruler"
|
||||||
|
|
||||||
|
GTK.revealerSetRevealChild rvRulerCorner True
|
||||||
|
GTK.revealerSetRevealChild rvLeftRuler True
|
||||||
|
GTK.revealerSetRevealChild rvTopRuler True
|
||||||
|
|
||||||
|
GTK.revealerSetTransitionType rvRulerCorner GTK.RevealerTransitionTypeSlideLeft
|
||||||
|
GTK.revealerSetTransitionType rvLeftRuler GTK.RevealerTransitionTypeSlideLeft
|
||||||
|
GTK.revealerSetTransitionType rvTopRuler GTK.RevealerTransitionTypeSlideUp
|
||||||
|
|
||||||
|
rulerCornerArea <- GTK.drawingAreaNew
|
||||||
|
GTK.boxPackStart rulerCorner rulerCornerArea True True 0
|
||||||
|
|
||||||
|
leftRulerArea <- GTK.drawingAreaNew
|
||||||
|
GTK.boxPackStart leftRuler leftRulerArea True True 0
|
||||||
|
|
||||||
|
topRulerArea <- GTK.drawingAreaNew
|
||||||
|
GTK.boxPackStart topRuler topRulerArea True True 0
|
||||||
|
|
||||||
|
GTK.widgetSetHexpand rulerCorner False
|
||||||
|
GTK.widgetSetVexpand rulerCorner False
|
||||||
|
GTK.widgetSetHexpand leftRuler False
|
||||||
|
GTK.widgetSetVexpand leftRuler True
|
||||||
|
GTK.widgetSetHexpand topRuler True
|
||||||
|
GTK.widgetSetVexpand topRuler False
|
||||||
|
GTK.widgetSetHexpand viewport True
|
||||||
|
GTK.widgetSetVexpand viewport True
|
||||||
|
|
||||||
|
---------------------------------------------------------
|
||||||
|
-- Panels
|
||||||
|
|
||||||
|
widgetAddClass panelGrid "panels"
|
||||||
|
|
||||||
|
---------------------------------------------------------
|
||||||
|
-- Info bar
|
||||||
|
|
||||||
|
widgetAddClass infoBar "infoBar"
|
||||||
|
|
||||||
|
---------------------------------------------------------
|
||||||
-- Actions
|
-- Actions
|
||||||
|
|
||||||
GTK.widgetAddEvents window [GDK.EventMaskKeyPressMask, GDK.EventMaskKeyReleaseMask]
|
---------------------------------------------------------
|
||||||
_ <- GTK.onWidgetKeyPressEvent window ( handleKeyboardPressEvent )
|
-- GTK main loop
|
||||||
_ <- GTK.onWidgetKeyReleaseEvent window ( handleKeyboardReleaseEvent )
|
|
||||||
|
|
||||||
_ <- GTK.onWidgetDestroy window ( quitAll actionTVar )
|
GTK.widgetAddEvents window [GDK.EventMaskKeyPressMask, GDK.EventMaskKeyReleaseMask]
|
||||||
_ <- GTK.onButtonClicked quitIconButton ( quitAll actionTVar )
|
_ <- GTK.onWidgetKeyPressEvent window handleKeyboardPressEvent
|
||||||
|
_ <- GTK.onWidgetKeyReleaseEvent window handleKeyboardReleaseEvent
|
||||||
|
_ <- GTK.onWidgetDestroy window GTK.mainQuit
|
||||||
|
|
||||||
GTK.widgetShowAll window
|
GTK.widgetShowAll window
|
||||||
GTK.main
|
GTK.main
|
||||||
|
|
||||||
|
exitSuccess
|
||||||
|
|
131
assets/theme.css
131
assets/theme.css
|
@ -2,87 +2,182 @@
|
||||||
all: unset;
|
all: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.window {
|
||||||
|
-GtkWidget-window-dragging: true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Window background colour */
|
/* Window background colour */
|
||||||
.bg {
|
.bg {
|
||||||
color: #292828
|
background-color: rgb(41, 40, 40);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Viewport background colour */
|
/* Viewport background colour */
|
||||||
.viewport_bg {
|
.viewport_bg {
|
||||||
color: #ecdfd2
|
background-color: rgb(236, 223, 210);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Basic text colour */
|
/* Basic text colour */
|
||||||
.plain {
|
.plain {
|
||||||
color: #d4be98
|
color: rgb(212, 190, 152);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Basic text font */
|
/* Basic text font */
|
||||||
.text {
|
.text {
|
||||||
font-family: "Lato", "Roboto", "Helvetica", sans-serif
|
font-family: "Lato", "Roboto", "Helvetica", sans-serif;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Monospace font */
|
/* Monospace font */
|
||||||
.monospace {
|
.monospace {
|
||||||
font-family: "Fira Code", "Inconsolata", "Courier", "Courier New", monospace
|
font-family: "Fira Code", "Inconsolata", "Courier", "Courier New", monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* High-constrast text colour */
|
/* High-constrast text colour */
|
||||||
.contrast {
|
.contrast {
|
||||||
color: #f7f4ef
|
color: rgb(247, 244, 239);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Active (highlighting) colour */
|
/* Active (highlighting) colour */
|
||||||
.highlight {
|
.highlight {
|
||||||
color: #eadfcc
|
color: #eadfcc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Logo area */
|
||||||
|
.logo {
|
||||||
|
padding-left: 2px;
|
||||||
|
padding-top: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Logo base colour */
|
/* Logo base colour */
|
||||||
.logo_base {
|
.logo_base {
|
||||||
color: #f7f4ef
|
color: rgb(234, 223, 204);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Logo highlight colour */
|
/* Logo highlight colour */
|
||||||
.logo_highlight {
|
.logo_highlight {
|
||||||
color: #f5881bff
|
color: rgb(245, 136, 27);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Viewport scrollbar colour */
|
/* Viewport scrollbar colour */
|
||||||
.viewport_scrollbar {
|
.viewport_scrollbar {
|
||||||
color: #28272793
|
color: rgba(40, 39, 39, 0.66);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Tab scrollbar colour */
|
/* Tab scrollbar colour */
|
||||||
.tab_scrollbar {
|
.tab_scrollbar {
|
||||||
color: #302d2693
|
color: rgba(48, 45, 38, 0.66);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Ruler colour */
|
/* Rulers */
|
||||||
.ruler {
|
.ruler {
|
||||||
color: #ede29a
|
background-color: rgb(237, 226, 154);
|
||||||
|
min-width: 16px;
|
||||||
|
min-height: 16px;
|
||||||
|
background-size: 16px 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Magnifying glass base colour */
|
/* Magnifying glass base colour */
|
||||||
.magnifier {
|
.magnifier {
|
||||||
color: #ecdfd2
|
color: rgb(236, 223, 210);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Magnifying glass glass colour */
|
/* Magnifying glass glass colour */
|
||||||
.glass {
|
.glass {
|
||||||
color: #9ce7ff72
|
color: rgba(156, 231, 255, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Cursor colour */
|
/* Cursor colour */
|
||||||
.cursor {
|
.cursor {
|
||||||
color: #f7f4ef
|
color: rgb(247, 244, 239);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bézier path point colour */
|
/* Bézier path point colour */
|
||||||
.point {
|
.point {
|
||||||
color: #8183f1
|
color: rgb(129, 131, 241);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Bézier control point colour */
|
/* Bézier control point colour */
|
||||||
.control {
|
.control {
|
||||||
color: #a1dde9
|
color: rgb(161, 221, 233);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Title bar */
|
||||||
|
.titleBar {
|
||||||
|
min-height: 20px;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Title bar */
|
||||||
|
.titleBar > * :hover {
|
||||||
|
background-color: rgb(72,70,61);
|
||||||
|
}
|
||||||
|
|
||||||
|
.menuItem {
|
||||||
|
background-color: rgb(41, 40, 40);
|
||||||
|
margin-left: 2px;
|
||||||
|
padding-left: 8px;
|
||||||
|
padding-right: 8px;
|
||||||
|
margin-left: 0px;
|
||||||
|
border-top: 2px solid rgb(41, 40, 40);
|
||||||
|
}
|
||||||
|
|
||||||
|
.menuItem:hover {
|
||||||
|
border-top: 2px solid rgb(234,223,204);
|
||||||
|
background-color: rgb(72,70,61);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Menu drop shadow */
|
||||||
|
.menuItem > * > * {
|
||||||
|
box-shadow: 2px 2px 4px 0px rgba(28,25,25,0.5);
|
||||||
|
border: 1px solid rgb(28,25,25);
|
||||||
|
border-top: 1px solid rgb(72,70,61);
|
||||||
|
}
|
||||||
|
|
||||||
|
.submenuItem {
|
||||||
|
padding-top: 4px;
|
||||||
|
padding-bottom: 4px;
|
||||||
|
padding-left: 8px;
|
||||||
|
padding-right: 8px;
|
||||||
|
background-color: rgb(41, 40, 40);
|
||||||
|
border-left: 2px solid rgb(41, 40, 40);
|
||||||
|
}
|
||||||
|
|
||||||
|
.submenuSeparator {
|
||||||
|
background-color: rgb(28,25,25);
|
||||||
|
padding-top: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submenuItem:hover {
|
||||||
|
border-left: 2px solid rgb(234,223,204);
|
||||||
|
}
|
||||||
|
|
||||||
|
.title {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Tool bar */
|
||||||
|
.toolBar {
|
||||||
|
min-width: 60px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* File bar */
|
||||||
|
.fileBar {
|
||||||
|
min-height: 25px;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Panels */
|
||||||
|
.panels {
|
||||||
|
min-width: 160px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Info bar */
|
||||||
|
.infoBar {
|
||||||
|
min-height: 40px;
|
||||||
|
font-size: 10px;
|
||||||
|
-GtkWidget-window-dragging: true;
|
||||||
|
}
|
||||||
|
|
||||||
|
.submenuItem:disabled {
|
||||||
|
color: rgb(149,149,149);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
packages: .
|
||||||
|
|
||||||
constraints:
|
constraints:
|
||||||
acts -finitary
|
acts -finitary
|
||||||
, haskell-gi >= 0.24
|
, haskell-gi >= 0.24
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
</defs>
|
</defs>
|
||||||
<sodipodi:namedview
|
<sodipodi:namedview
|
||||||
|
inkscape:lockguides="false"
|
||||||
inkscape:document-rotation="0"
|
inkscape:document-rotation="0"
|
||||||
fit-margin-bottom="0"
|
fit-margin-bottom="0"
|
||||||
fit-margin-right="0"
|
fit-margin-right="0"
|
||||||
|
@ -46,7 +47,7 @@
|
||||||
objecttolerance="1"
|
objecttolerance="1"
|
||||||
inkscape:window-maximized="1"
|
inkscape:window-maximized="1"
|
||||||
inkscape:window-y="115"
|
inkscape:window-y="115"
|
||||||
inkscape:window-x="2552"
|
inkscape:window-x="-8"
|
||||||
inkscape:window-height="1377"
|
inkscape:window-height="1377"
|
||||||
inkscape:window-width="2560"
|
inkscape:window-width="2560"
|
||||||
inkscape:guide-bbox="true"
|
inkscape:guide-bbox="true"
|
||||||
|
@ -54,9 +55,9 @@
|
||||||
showgrid="false"
|
showgrid="false"
|
||||||
inkscape:current-layer="layer1"
|
inkscape:current-layer="layer1"
|
||||||
inkscape:document-units="mm"
|
inkscape:document-units="mm"
|
||||||
inkscape:cy="849.74823"
|
inkscape:cy="421.74309"
|
||||||
inkscape:cx="768.55909"
|
inkscape:cx="750.76483"
|
||||||
inkscape:zoom="16"
|
inkscape:zoom="1"
|
||||||
inkscape:pageshadow="2"
|
inkscape:pageshadow="2"
|
||||||
inkscape:pageopacity="0.0"
|
inkscape:pageopacity="0.0"
|
||||||
borderopacity="1.0"
|
borderopacity="1.0"
|
||||||
|
@ -5524,5 +5525,17 @@
|
||||||
d="M 745.71289 847.36133 C 742.67337 847.25537 739.67408 848.77547 738.02148 851.58008 C 735.81903 855.31789 737.00422 860.22415 740.31836 862.83789 C 740.09434 863.25648 739.39877 864.56411 738.68359 864.1582 C 738.41428 864.00535 737.96229 864.29658 737.67188 864.80859 L 733.96289 871.19141 C 733.67359 871.70474 733.85258 872.35441 734.36328 872.64453 L 736.30078 873.74414 C 736.81328 874.03475 737.46322 873.85271 737.75391 873.3418 L 741.44922 866.78125 C 741.7402 866.26988 741.6576 865.91122 741.39258 865.75195 C 740.70108 865.33646 741.49263 864.19842 741.77148 863.70898 C 745.70555 865.47578 750.55309 864.08509 752.79297 860.2832 C 755.19674 856.20376 753.8392 850.94869 749.75977 848.54492 C 748.48506 847.79371 747.09449 847.40949 745.71289 847.36133 z M 745.40234 848.82227 A 7.1095623 7.1095623 0 0 1 752.29102 854.15234 A 7.1095623 7.1095623 0 0 1 747.18555 862.81445 A 7.1095623 7.1095623 0 0 1 738.52344 857.71094 A 7.1095623 7.1095623 0 0 1 743.62695 849.04688 A 7.1095623 7.1095623 0 0 1 745.40234 848.82227 z "
|
d="M 745.71289 847.36133 C 742.67337 847.25537 739.67408 848.77547 738.02148 851.58008 C 735.81903 855.31789 737.00422 860.22415 740.31836 862.83789 C 740.09434 863.25648 739.39877 864.56411 738.68359 864.1582 C 738.41428 864.00535 737.96229 864.29658 737.67188 864.80859 L 733.96289 871.19141 C 733.67359 871.70474 733.85258 872.35441 734.36328 872.64453 L 736.30078 873.74414 C 736.81328 874.03475 737.46322 873.85271 737.75391 873.3418 L 741.44922 866.78125 C 741.7402 866.26988 741.6576 865.91122 741.39258 865.75195 C 740.70108 865.33646 741.49263 864.19842 741.77148 863.70898 C 745.70555 865.47578 750.55309 864.08509 752.79297 860.2832 C 755.19674 856.20376 753.8392 850.94869 749.75977 848.54492 C 748.48506 847.79371 747.09449 847.40949 745.71289 847.36133 z M 745.40234 848.82227 A 7.1095623 7.1095623 0 0 1 752.29102 854.15234 A 7.1095623 7.1095623 0 0 1 747.18555 862.81445 A 7.1095623 7.1095623 0 0 1 738.52344 857.71094 A 7.1095623 7.1095623 0 0 1 743.62695 849.04688 A 7.1095623 7.1095623 0 0 1 745.40234 848.82227 z "
|
||||||
style="fill:#ecdfd2;fill-opacity:1;stroke-width:0.0701341"
|
style="fill:#ecdfd2;fill-opacity:1;stroke-width:0.0701341"
|
||||||
id="path2" />
|
id="path2" />
|
||||||
|
<path
|
||||||
|
sodipodi:nodetypes="ccc"
|
||||||
|
id="path4212"
|
||||||
|
d="m -137.37613,-191.90754 -0.92604,0.66146 0.95911,0.62838"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
inkscape:transform-center-y="0.080851403"
|
||||||
|
inkscape:transform-center-x="0.064642359"
|
||||||
|
style="display:inline;fill:none;stroke:#000000;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m -135.45938,-192.29552 -0.66146,-0.92604 -0.62838,0.95911"
|
||||||
|
id="path4212-4"
|
||||||
|
sodipodi:nodetypes="ccc" />
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 236 KiB After Width: | Height: | Size: 237 KiB |
|
@ -15,11 +15,11 @@ import MetaBrush.Render.Util
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- | Calligraphy brush icon. Width = 29, height = 29.
|
-- | Calligraphy brush icon. Width = 29, height = 29.
|
||||||
drawBrush :: GDK.RGBA -> GDK.RGBA -> GDK.RGBA -> Cairo.Render ()
|
drawBrush :: GDK.RGBA -> GDK.RGBA -> GDK.RGBA -> Cairo.Render Bool
|
||||||
drawBrush brushColour bodyColour loopColour = do
|
drawBrush brushColour bodyColour loopColour = do
|
||||||
|
|
||||||
-- Loop
|
-- Loop
|
||||||
Cairo.setLineWidth 0.2
|
Cairo.setLineWidth 1
|
||||||
withRGBA loopColour Cairo.setSourceRGBA
|
withRGBA loopColour Cairo.setSourceRGBA
|
||||||
Cairo.newPath
|
Cairo.newPath
|
||||||
Cairo.moveTo 23.144531 6.199219
|
Cairo.moveTo 23.144531 6.199219
|
||||||
|
@ -58,3 +58,5 @@ drawBrush brushColour bodyColour loopColour = do
|
||||||
Cairo.curveTo 10.339844 19.335938 10.339844 19.335938 10.339844 19.335938
|
Cairo.curveTo 10.339844 19.335938 10.339844 19.335938 10.339844 19.335938
|
||||||
Cairo.closePath
|
Cairo.closePath
|
||||||
Cairo.fillPreserve
|
Cairo.fillPreserve
|
||||||
|
|
||||||
|
pure True
|
||||||
|
|
94
src/app/MetaBrush/Asset/Colours.hs
Normal file
94
src/app/MetaBrush/Asset/Colours.hs
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
{-# LANGUAGE BlockArguments #-}
|
||||||
|
{-# LANGUAGE DeriveFunctor #-}
|
||||||
|
{-# LANGUAGE DeriveFoldable #-}
|
||||||
|
{-# LANGUAGE DeriveTraversable #-}
|
||||||
|
{-# LANGUAGE DerivingStrategies #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
|
|
||||||
|
{-# OPTIONS_GHC -fno-warn-deprecations #-}
|
||||||
|
|
||||||
|
module MetaBrush.Asset.Colours
|
||||||
|
( ColourRecord(..), ColourType
|
||||||
|
, colours
|
||||||
|
)
|
||||||
|
where
|
||||||
|
|
||||||
|
-- base
|
||||||
|
import Data.Traversable
|
||||||
|
( for )
|
||||||
|
|
||||||
|
-- gi-gdk
|
||||||
|
import qualified GI.Gdk as GDK
|
||||||
|
|
||||||
|
-- gi-gtk
|
||||||
|
import qualified GI.Gtk as GTK
|
||||||
|
|
||||||
|
-- text
|
||||||
|
import Data.Text
|
||||||
|
( Text )
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
data ColourRecord a
|
||||||
|
= Colours
|
||||||
|
{ bg :: !a
|
||||||
|
, viewport_bg :: !a
|
||||||
|
, plain :: !a
|
||||||
|
, contrast :: !a
|
||||||
|
, highlight :: !a
|
||||||
|
, logo_base :: !a
|
||||||
|
, logo_highlight :: !a
|
||||||
|
, viewport_scrollbar :: !a
|
||||||
|
, tab_scrollbar :: !a
|
||||||
|
, ruler :: !a
|
||||||
|
, magnifier :: !a
|
||||||
|
, glass :: !a
|
||||||
|
, cursor :: !a
|
||||||
|
, point :: !a
|
||||||
|
, control :: !a
|
||||||
|
}
|
||||||
|
deriving stock ( Show, Functor, Foldable, Traversable )
|
||||||
|
|
||||||
|
data ColourType
|
||||||
|
= Color
|
||||||
|
| BackgroundColor
|
||||||
|
deriving stock Show
|
||||||
|
|
||||||
|
data ColourName
|
||||||
|
= ColourName
|
||||||
|
{ colourName :: !Text
|
||||||
|
, colourType :: !ColourType
|
||||||
|
, stateFlags :: ![ GTK.StateFlags ]
|
||||||
|
}
|
||||||
|
deriving stock Show
|
||||||
|
|
||||||
|
colourNames :: ColourRecord ColourName
|
||||||
|
colourNames = Colours
|
||||||
|
{ bg = ColourName "bg" BackgroundColor [ GTK.StateFlagsNormal ]
|
||||||
|
, viewport_bg = ColourName "viewport_bg" BackgroundColor [ GTK.StateFlagsNormal ]
|
||||||
|
, plain = ColourName "plain" Color [ GTK.StateFlagsNormal ]
|
||||||
|
, contrast = ColourName "contrast" Color [ GTK.StateFlagsNormal ]
|
||||||
|
, highlight = ColourName "highlight" Color [ GTK.StateFlagsNormal ]
|
||||||
|
, logo_base = ColourName "logo_base" Color [ GTK.StateFlagsNormal ]
|
||||||
|
, logo_highlight = ColourName "logo_highlight" Color [ GTK.StateFlagsNormal ]
|
||||||
|
, viewport_scrollbar = ColourName "viewport_scrollbar" Color [ GTK.StateFlagsNormal ]
|
||||||
|
, tab_scrollbar = ColourName "tab_scrollbar" Color [ GTK.StateFlagsNormal ]
|
||||||
|
, ruler = ColourName "ruler" BackgroundColor [ GTK.StateFlagsNormal ]
|
||||||
|
, magnifier = ColourName "magnifier" Color [ GTK.StateFlagsNormal ]
|
||||||
|
, glass = ColourName "glass" Color [ GTK.StateFlagsNormal ]
|
||||||
|
, cursor = ColourName "cursor" Color [ GTK.StateFlagsNormal ]
|
||||||
|
, point = ColourName "point" Color [ GTK.StateFlagsNormal ]
|
||||||
|
, control = ColourName "control" Color [ GTK.StateFlagsNormal ]
|
||||||
|
}
|
||||||
|
|
||||||
|
type Colours = ColourRecord GDK.RGBA
|
||||||
|
|
||||||
|
colours :: GTK.WidgetPath -> IO Colours
|
||||||
|
colours windowWidgetPath = for colourNames \ ( ColourName { .. } ) -> do
|
||||||
|
style <- GTK.styleContextNew
|
||||||
|
GTK.styleContextSetPath style windowWidgetPath
|
||||||
|
GTK.styleContextAddClass style colourName
|
||||||
|
case colourType of
|
||||||
|
BackgroundColor -> GTK.styleContextGetBackgroundColor style stateFlags
|
||||||
|
Color -> GTK.styleContextGetColor style stateFlags
|
|
@ -15,11 +15,11 @@ import MetaBrush.Render.Util
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- | MetaBrush logo. Width = 29, height = 29.
|
-- | MetaBrush logo. Width = 29, height = 29.
|
||||||
drawLogo :: GDK.RGBA -> GDK.RGBA -> GDK.RGBA -> Cairo.Render ()
|
drawLogo :: GDK.RGBA -> GDK.RGBA -> GDK.RGBA -> Cairo.Render Bool
|
||||||
drawLogo brushColour bodyColour loopColour = do
|
drawLogo brushColour bodyColour loopColour = do
|
||||||
|
|
||||||
-- Loop
|
-- Loop
|
||||||
Cairo.setLineWidth 0.2
|
Cairo.setLineWidth 1
|
||||||
withRGBA loopColour Cairo.setSourceRGBA
|
withRGBA loopColour Cairo.setSourceRGBA
|
||||||
Cairo.newPath
|
Cairo.newPath
|
||||||
Cairo.moveTo 17.480469 7.847656
|
Cairo.moveTo 17.480469 7.847656
|
||||||
|
@ -79,3 +79,5 @@ drawLogo brushColour bodyColour loopColour = do
|
||||||
Cairo.curveTo 7.199219 18.394531 7.199219 18.394531 7.199219 18.394531
|
Cairo.curveTo 7.199219 18.394531 7.199219 18.394531 7.199219 18.394531
|
||||||
Cairo.closePath
|
Cairo.closePath
|
||||||
Cairo.fillPreserve
|
Cairo.fillPreserve
|
||||||
|
|
||||||
|
pure True
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
{-# LANGUAGE NegativeLiterals #-}
|
||||||
|
|
||||||
module MetaBrush.Asset.Magnifier
|
module MetaBrush.Asset.Magnifier
|
||||||
( drawMagnifier )
|
( drawMagnifier )
|
||||||
where
|
where
|
||||||
|
@ -15,7 +17,7 @@ import MetaBrush.Render.Util
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- | Magnifying glass icon. Width = 19, height = 25.
|
-- | Magnifying glass icon. Width = 19, height = 25.
|
||||||
drawMagnifier :: GDK.RGBA -> GDK.RGBA -> Cairo.Render ()
|
drawMagnifier :: GDK.RGBA -> GDK.RGBA -> Cairo.Render Bool
|
||||||
drawMagnifier magnifierColour glassColour = do
|
drawMagnifier magnifierColour glassColour = do
|
||||||
|
|
||||||
-- Magnifying glass.
|
-- Magnifying glass.
|
||||||
|
@ -58,3 +60,4 @@ drawMagnifier magnifierColour glassColour = do
|
||||||
Cairo.setFillRule Cairo.FillRuleWinding
|
Cairo.setFillRule Cairo.FillRuleWinding
|
||||||
Cairo.fillPreserve
|
Cairo.fillPreserve
|
||||||
|
|
||||||
|
pure True
|
||||||
|
|
|
@ -15,7 +15,7 @@ import MetaBrush.Render.Util
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- | MetaParameter icon. Width = 29, height = 29.
|
-- | MetaParameter icon. Width = 29, height = 29.
|
||||||
drawMeta :: GDK.RGBA -> Cairo.Render ()
|
drawMeta :: GDK.RGBA -> Cairo.Render Bool
|
||||||
drawMeta metaColour = do
|
drawMeta metaColour = do
|
||||||
withRGBA metaColour Cairo.setSourceRGBA
|
withRGBA metaColour Cairo.setSourceRGBA
|
||||||
Cairo.newPath
|
Cairo.newPath
|
||||||
|
@ -40,3 +40,5 @@ drawMeta metaColour = do
|
||||||
Cairo.curveTo 16.140625 11.976563 16.140625 11.976563 16.140625 11.976563
|
Cairo.curveTo 16.140625 11.976563 16.140625 11.976563 16.140625 11.976563
|
||||||
Cairo.closePath
|
Cairo.closePath
|
||||||
Cairo.fillPreserve
|
Cairo.fillPreserve
|
||||||
|
|
||||||
|
pure True
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
{-# LANGUAGE NegativeLiterals #-}
|
||||||
|
|
||||||
module MetaBrush.Asset.TickBox
|
module MetaBrush.Asset.TickBox
|
||||||
( drawBox, drawTickedBox )
|
( drawBox, drawTickedBox )
|
||||||
where
|
where
|
||||||
|
@ -15,9 +17,9 @@ import MetaBrush.Render.Util
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- | Non-ticked box. Width = 14, height = 12.
|
-- | Non-ticked box. Width = 14, height = 12.
|
||||||
drawBox :: GDK.RGBA -> Cairo.Render ()
|
drawBox :: GDK.RGBA -> Cairo.Render Bool
|
||||||
drawBox boxColour = do
|
drawBox boxColour = do
|
||||||
withRGBA loopColour Cairo.setSourceRGBA
|
withRGBA boxColour Cairo.setSourceRGBA
|
||||||
|
|
||||||
Cairo.newPath
|
Cairo.newPath
|
||||||
Cairo.moveTo 2.015625 0.769531
|
Cairo.moveTo 2.015625 0.769531
|
||||||
|
@ -43,8 +45,11 @@ drawBox boxColour = do
|
||||||
Cairo.setFillRule Cairo.FillRuleWinding
|
Cairo.setFillRule Cairo.FillRuleWinding
|
||||||
Cairo.fillPreserve
|
Cairo.fillPreserve
|
||||||
|
|
||||||
|
pure True
|
||||||
|
|
||||||
|
|
||||||
-- | Ticked box. Width = 14, height = 12.
|
-- | Ticked box. Width = 14, height = 12.
|
||||||
drawTickedBox :: GDK.RGBA -> GDK.RGBA -> Cairo.Render ()
|
drawTickedBox :: GDK.RGBA -> GDK.RGBA -> Cairo.Render Bool
|
||||||
drawTickedBox boxColour tickColour = do
|
drawTickedBox boxColour tickColour = do
|
||||||
|
|
||||||
-- Box
|
-- Box
|
||||||
|
@ -94,3 +99,5 @@ drawTickedBox boxColour tickColour = do
|
||||||
Cairo.curveTo 13.835938 0.0351563 13.632813 -0.0195313 13.421875 0.0078125
|
Cairo.curveTo 13.835938 0.0351563 13.632813 -0.0195313 13.421875 0.0078125
|
||||||
Cairo.closePath
|
Cairo.closePath
|
||||||
Cairo.fillPreserve
|
Cairo.fillPreserve
|
||||||
|
|
||||||
|
pure True
|
||||||
|
|
|
@ -2,6 +2,7 @@ module MetaBrush.Document where
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
{-
|
||||||
data Document
|
data Document
|
||||||
= Document
|
= Document
|
||||||
{ displayName :: !Text
|
{ displayName :: !Text
|
||||||
|
@ -10,3 +11,4 @@ data Document
|
||||||
, viewport :: !AABB
|
, viewport :: !AABB
|
||||||
, strokes :: !(Set Stroke)
|
, strokes :: !(Set Stroke)
|
||||||
}
|
}
|
||||||
|
-}
|
23
src/app/MetaBrush/Event.hs
Normal file
23
src/app/MetaBrush/Event.hs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
module MetaBrush.Event
|
||||||
|
( handleKeyboardPressEvent
|
||||||
|
, handleKeyboardReleaseEvent
|
||||||
|
)
|
||||||
|
where
|
||||||
|
|
||||||
|
-- gi-gdk
|
||||||
|
import qualified GI.Gdk as GDK
|
||||||
|
|
||||||
|
-- gi-gtk
|
||||||
|
import qualified GI.Gtk as GTK
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
handleKeyboardPressEvent, handleKeyboardReleaseEvent :: GDK.EventKey -> IO Bool
|
||||||
|
handleKeyboardPressEvent evt = do
|
||||||
|
keyCode <- GDK.getEventKeyKeyval evt
|
||||||
|
case keyCode of
|
||||||
|
-- escape
|
||||||
|
0xff1b -> GTK.mainQuit
|
||||||
|
_ -> pure ()
|
||||||
|
pure True
|
||||||
|
handleKeyboardReleaseEvent _ = pure True
|
|
@ -1,24 +1,31 @@
|
||||||
|
{-# LANGUAGE BlockArguments #-}
|
||||||
|
{-# LANGUAGE MonoLocalBinds #-}
|
||||||
|
|
||||||
module MetaBrush.Render.Util
|
module MetaBrush.Render.Util
|
||||||
( withRGBA, showRGBA
|
( withRGBA, showRGBA
|
||||||
, widgetAddClasses, widgetAddClass )
|
, widgetAddClasses, widgetAddClass
|
||||||
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
-- base
|
-- base
|
||||||
|
import Data.Foldable
|
||||||
|
( for_ )
|
||||||
import GHC.Stack
|
import GHC.Stack
|
||||||
( HasCallStack )
|
( HasCallStack )
|
||||||
|
|
||||||
-- gi-gdk
|
-- gi-gdk
|
||||||
import qualified GI.Gdk as GDK
|
import qualified GI.Gdk as GDK
|
||||||
|
|
||||||
|
-- gi-gtk
|
||||||
|
import qualified GI.Gtk as GTK
|
||||||
|
|
||||||
-- text
|
-- text
|
||||||
import Data.Text
|
import Data.Text
|
||||||
( Text )
|
( Text )
|
||||||
import qualified Data.Text as Text
|
|
||||||
( pack )
|
|
||||||
|
|
||||||
-- transformers
|
-- transformers
|
||||||
import Control.Monad.IO.Class
|
import Control.Monad.IO.Class
|
||||||
( MonadIO(liftIO) )
|
( MonadIO )
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@ module MetaBrush.Stroke where
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
{-
|
||||||
data StrokePoint
|
data StrokePoint
|
||||||
= StrokePoint
|
= StrokePoint
|
||||||
{ center :: Point2D Double
|
{ center :: Point2D Double
|
||||||
|
@ -9,3 +10,5 @@ data StrokePoint
|
||||||
|
|
||||||
newtype Stroke =
|
newtype Stroke =
|
||||||
Stroke { strokePoints :: Seq (
|
Stroke { strokePoints :: Seq (
|
||||||
|
|
||||||
|
-}
|
252
src/app/MetaBrush/UI/Menu.hs
Normal file
252
src/app/MetaBrush/UI/Menu.hs
Normal file
|
@ -0,0 +1,252 @@
|
||||||
|
{-# LANGUAGE BlockArguments #-}
|
||||||
|
{-# LANGUAGE DataKinds #-}
|
||||||
|
{-# LANGUAGE DeriveGeneric #-}
|
||||||
|
{-# LANGUAGE DerivingStrategies #-}
|
||||||
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
|
{-# LANGUAGE FunctionalDependencies #-}
|
||||||
|
{-# LANGUAGE NamedFieldPuns #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE PolyKinds #-}
|
||||||
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
|
{-# LANGUAGE TypeApplications #-}
|
||||||
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
|
|
||||||
|
module MetaBrush.UI.Menu
|
||||||
|
( newMenuBar
|
||||||
|
, Menu(..)
|
||||||
|
, FileMenu(..), EditMenu(..), ViewMenu(..), HelpMenu(..)
|
||||||
|
, ResourceType(..)
|
||||||
|
, MenuItem(..)
|
||||||
|
)
|
||||||
|
where
|
||||||
|
|
||||||
|
-- base
|
||||||
|
import Control.Monad
|
||||||
|
( unless )
|
||||||
|
import Data.Foldable
|
||||||
|
( for_ )
|
||||||
|
import Data.Kind
|
||||||
|
( Type )
|
||||||
|
import GHC.Generics
|
||||||
|
( Generic )
|
||||||
|
|
||||||
|
-- generic-lens
|
||||||
|
import Data.Generics.Product.Constraints
|
||||||
|
( HasConstraints(constraints) )
|
||||||
|
|
||||||
|
-- gi-gtk
|
||||||
|
import qualified GI.Gtk as GTK
|
||||||
|
|
||||||
|
-- text
|
||||||
|
import Data.Text
|
||||||
|
( Text )
|
||||||
|
|
||||||
|
-- transformers
|
||||||
|
import Control.Monad.IO.Class
|
||||||
|
( MonadIO(liftIO) )
|
||||||
|
|
||||||
|
-- MetaBrush
|
||||||
|
import MetaBrush.Render.Util
|
||||||
|
( widgetAddClasses )
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- Types for describing menu items.
|
||||||
|
|
||||||
|
data ResourceType
|
||||||
|
= Description
|
||||||
|
| Object
|
||||||
|
|
||||||
|
data family MenuItem ( submenu :: ResourceType -> Type ) ( r :: ResourceType )
|
||||||
|
data instance MenuItem submenu Description
|
||||||
|
= MenuItemDescription
|
||||||
|
{ menuItemLabel :: !Text
|
||||||
|
, menuItemClasses :: ![ Text ]
|
||||||
|
, menuItemAction :: !( Maybe Text )
|
||||||
|
, submenuDescription :: !( submenu Description )
|
||||||
|
}
|
||||||
|
data instance MenuItem submenu Object
|
||||||
|
= MenuItem
|
||||||
|
{ menuItem :: !GTK.MenuItem
|
||||||
|
, menuItemSubmenu :: !( submenu Object )
|
||||||
|
}
|
||||||
|
|
||||||
|
data family Separator ( r :: ResourceType )
|
||||||
|
data instance Separator Description
|
||||||
|
= SeparatorDescription
|
||||||
|
{ separatorClasses :: ![ Text ] }
|
||||||
|
data instance Separator Object
|
||||||
|
= Separator
|
||||||
|
{ separatorItem :: !GTK.MenuItem }
|
||||||
|
|
||||||
|
data NoSubresource ( k :: ResourceType ) = NoSubresource
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- Menu used in MetaBrush.
|
||||||
|
|
||||||
|
-- Types.
|
||||||
|
|
||||||
|
data Menu ( rt :: ResourceType )
|
||||||
|
= Menu
|
||||||
|
{ file :: !( MenuItem FileMenu rt )
|
||||||
|
, edit :: !( MenuItem EditMenu rt )
|
||||||
|
, view :: !( MenuItem ViewMenu rt )
|
||||||
|
, help :: !( MenuItem HelpMenu rt )
|
||||||
|
}
|
||||||
|
deriving stock Generic
|
||||||
|
|
||||||
|
data FileMenu ( rt :: ResourceType )
|
||||||
|
= FileMenu
|
||||||
|
{ new :: !( MenuItem NoSubresource rt )
|
||||||
|
, open :: !( MenuItem NoSubresource rt )
|
||||||
|
, save :: !( MenuItem NoSubresource rt )
|
||||||
|
, saveAs :: !( MenuItem NoSubresource rt )
|
||||||
|
, close :: !( MenuItem NoSubresource rt )
|
||||||
|
, quit :: !( MenuItem NoSubresource rt )
|
||||||
|
}
|
||||||
|
deriving stock Generic
|
||||||
|
|
||||||
|
data EditMenu ( rt :: ResourceType )
|
||||||
|
= EditMenu
|
||||||
|
{ undo :: !( MenuItem NoSubresource rt )
|
||||||
|
, redo :: !( MenuItem NoSubresource rt )
|
||||||
|
, history :: !( MenuItem NoSubresource rt )
|
||||||
|
, editSep1 :: !( Separator rt )
|
||||||
|
, cut :: !( MenuItem NoSubresource rt )
|
||||||
|
, copy :: !( MenuItem NoSubresource rt )
|
||||||
|
, paste :: !( MenuItem NoSubresource rt )
|
||||||
|
, duplicate :: !( MenuItem NoSubresource rt )
|
||||||
|
, editSep2 :: !( Separator rt )
|
||||||
|
, preferences :: !( MenuItem NoSubresource rt )
|
||||||
|
}
|
||||||
|
deriving stock Generic
|
||||||
|
|
||||||
|
data ViewMenu ( rt :: ResourceType )
|
||||||
|
= ViewMenu
|
||||||
|
{ navigator :: !( MenuItem NoSubresource rt )
|
||||||
|
, viewSep1 :: !( Separator rt )
|
||||||
|
, strokes :: !( MenuItem NoSubresource rt )
|
||||||
|
, brushes :: !( MenuItem NoSubresource rt )
|
||||||
|
, metaparameters :: !( MenuItem NoSubresource rt )
|
||||||
|
, viewSep2 :: !( Separator rt )
|
||||||
|
, transform :: !( MenuItem NoSubresource rt )
|
||||||
|
}
|
||||||
|
deriving stock Generic
|
||||||
|
|
||||||
|
data HelpMenu ( rt :: ResourceType )
|
||||||
|
= HelpMenu
|
||||||
|
{ about :: !( MenuItem NoSubresource rt ) }
|
||||||
|
deriving stock Generic
|
||||||
|
|
||||||
|
-- Descriptions.
|
||||||
|
|
||||||
|
menuDescription :: Menu Description
|
||||||
|
menuDescription
|
||||||
|
= Menu
|
||||||
|
{ file = MenuItemDescription "File" [ "menuItem", "file" ] Nothing fileMenuDescription
|
||||||
|
, edit = MenuItemDescription "Edit" [ "menuItem", "edit" ] Nothing editMenuDescription
|
||||||
|
, view = MenuItemDescription "View" [ "menuItem", "view" ] Nothing viewMenuDescription
|
||||||
|
, help = MenuItemDescription "Help" [ "menuItem", "help" ] Nothing helpMenuDescription
|
||||||
|
}
|
||||||
|
|
||||||
|
fileMenuDescription :: FileMenu Description
|
||||||
|
fileMenuDescription
|
||||||
|
= FileMenu
|
||||||
|
{ new = MenuItemDescription "New" [ "submenuItem" ] Nothing NoSubresource
|
||||||
|
, open = MenuItemDescription "Open" [ "submenuItem" ] Nothing NoSubresource
|
||||||
|
, save = MenuItemDescription "Save" [ "submenuItem" ] Nothing NoSubresource
|
||||||
|
, saveAs = MenuItemDescription "Save as" [ "submenuItem" ] Nothing NoSubresource
|
||||||
|
, close = MenuItemDescription "Close" [ "submenuItem" ] Nothing NoSubresource
|
||||||
|
, quit = MenuItemDescription "Quit" [ "submenuItem" ] Nothing NoSubresource
|
||||||
|
}
|
||||||
|
|
||||||
|
editMenuDescription :: EditMenu Description
|
||||||
|
editMenuDescription
|
||||||
|
= EditMenu
|
||||||
|
{ undo = MenuItemDescription "Undo" [ "submenuItem" ] Nothing NoSubresource
|
||||||
|
, redo = MenuItemDescription "Redo" [ "submenuItem" ] Nothing NoSubresource
|
||||||
|
, history = MenuItemDescription "History" [ "submenuItem" ] Nothing NoSubresource
|
||||||
|
, editSep1 = SeparatorDescription [ "submenuSeparator" ]
|
||||||
|
, cut = MenuItemDescription "Cut" [ "submenuItem" ] Nothing NoSubresource
|
||||||
|
, copy = MenuItemDescription "Copy" [ "submenuItem" ] Nothing NoSubresource
|
||||||
|
, paste = MenuItemDescription "Paste" [ "submenuItem" ] Nothing NoSubresource
|
||||||
|
, duplicate = MenuItemDescription "Duplicate" [ "submenuItem" ] Nothing NoSubresource
|
||||||
|
, editSep2 = SeparatorDescription [ "submenuSeparator" ]
|
||||||
|
, preferences = MenuItemDescription "Preferences" [ "submenuItem" ] Nothing NoSubresource
|
||||||
|
}
|
||||||
|
|
||||||
|
viewMenuDescription :: ViewMenu Description
|
||||||
|
viewMenuDescription
|
||||||
|
= ViewMenu
|
||||||
|
{ navigator = MenuItemDescription "Navigator" [ "submenuItem" ] Nothing NoSubresource
|
||||||
|
, viewSep1 = SeparatorDescription [ "submenuSeparator" ]
|
||||||
|
, strokes = MenuItemDescription "Strokes" [ "submenuItem" ] Nothing NoSubresource
|
||||||
|
, brushes = MenuItemDescription "Brushes" [ "submenuItem" ] Nothing NoSubresource
|
||||||
|
, metaparameters = MenuItemDescription "Metaparameters" [ "submenuItem" ] Nothing NoSubresource
|
||||||
|
, viewSep2 = SeparatorDescription [ "submenuSeparator" ]
|
||||||
|
, transform = MenuItemDescription "Transform" [ "submenuItem" ] Nothing NoSubresource
|
||||||
|
}
|
||||||
|
|
||||||
|
helpMenuDescription :: HelpMenu Description
|
||||||
|
helpMenuDescription
|
||||||
|
= HelpMenu
|
||||||
|
{ about = MenuItemDescription "About MetaBrush" [ "submenuItem" ] Nothing NoSubresource }
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
-- Creating a GTK menu bar from a menu description.
|
||||||
|
|
||||||
|
newMenuItem :: MonadIO m => MenuItem submenu Description -> m GTK.MenuItem
|
||||||
|
newMenuItem ( MenuItemDescription { .. } ) = do
|
||||||
|
menuItem <- GTK.menuItemNewWithLabel menuItemLabel
|
||||||
|
-- Could set accelerator labels...
|
||||||
|
unless ( null menuItemClasses ) do
|
||||||
|
widgetAddClasses menuItem menuItemClasses
|
||||||
|
for_ menuItemAction \ actionName -> do
|
||||||
|
GTK.actionableSetActionName menuItem ( Just actionName )
|
||||||
|
pure menuItem
|
||||||
|
|
||||||
|
class CreateMenuItem desc res | desc -> res, res -> desc where
|
||||||
|
createMenuItem :: MonadIO m => ( GTK.MenuItem -> m () ) -> desc -> m res
|
||||||
|
instance {-# OVERLAPPING #-} CreateMenuItem ( MenuItem NoSubresource Description ) ( MenuItem NoSubresource Object ) where
|
||||||
|
createMenuItem attachToParent menuItemDescription = do
|
||||||
|
menuItem <- newMenuItem menuItemDescription
|
||||||
|
attachToParent menuItem
|
||||||
|
pure
|
||||||
|
MenuItem
|
||||||
|
{ menuItem = menuItem
|
||||||
|
, menuItemSubmenu = NoSubresource
|
||||||
|
}
|
||||||
|
instance ( HasConstraints CreateMenuItem ( submenu Description ) ( submenu Object ) )
|
||||||
|
=> CreateMenuItem ( MenuItem submenu Description ) ( MenuItem submenu Object )
|
||||||
|
where
|
||||||
|
createMenuItem attachToParent menuItemDescription@( MenuItemDescription { submenuDescription } ) = do
|
||||||
|
menuItem <- newMenuItem menuItemDescription
|
||||||
|
submenu <- GTK.menuNew
|
||||||
|
submenuItems <-
|
||||||
|
constraints @CreateMenuItem
|
||||||
|
( createMenuItem ( GTK.menuShellAppend submenu ) )
|
||||||
|
submenuDescription
|
||||||
|
GTK.menuItemSetSubmenu menuItem ( Just submenu )
|
||||||
|
attachToParent menuItem
|
||||||
|
pure
|
||||||
|
MenuItem
|
||||||
|
{ menuItem = menuItem
|
||||||
|
, menuItemSubmenu = submenuItems
|
||||||
|
}
|
||||||
|
instance CreateMenuItem ( Separator Description ) ( Separator Object ) where
|
||||||
|
createMenuItem attachToParent ( SeparatorDescription { .. } ) = do
|
||||||
|
separator <- GTK.separatorMenuItemNew
|
||||||
|
unless ( null separatorClasses ) do
|
||||||
|
widgetAddClasses separator separatorClasses
|
||||||
|
sep <- liftIO ( GTK.unsafeCastTo GTK.MenuItem separator )
|
||||||
|
attachToParent sep
|
||||||
|
pure ( Separator { separatorItem = sep } )
|
||||||
|
|
||||||
|
newMenuBar :: MonadIO m => m ( GTK.MenuBar, Menu Object )
|
||||||
|
newMenuBar = do
|
||||||
|
menuBar <- GTK.menuBarNew
|
||||||
|
menu <-
|
||||||
|
constraints @CreateMenuItem
|
||||||
|
( createMenuItem ( GTK.menuShellAppend menuBar ) )
|
||||||
|
menuDescription
|
||||||
|
pure ( menuBar, menu )
|
|
@ -4,9 +4,12 @@
|
||||||
{-# LANGUAGE DeriveGeneric #-}
|
{-# LANGUAGE DeriveGeneric #-}
|
||||||
{-# LANGUAGE DeriveTraversable #-}
|
{-# LANGUAGE DeriveTraversable #-}
|
||||||
{-# LANGUAGE DerivingStrategies #-}
|
{-# LANGUAGE DerivingStrategies #-}
|
||||||
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
|
{-# LANGUAGE MultiParamTypeClasses #-}
|
||||||
{-# LANGUAGE RecordWildCards #-}
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
{-# LANGUAGE ScopedTypeVariables #-}
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
{-# LANGUAGE TypeApplications #-}
|
{-# LANGUAGE TypeApplications #-}
|
||||||
|
{-# LANGUAGE UndecidableInstances #-}
|
||||||
|
|
||||||
module Math.Bezier.Cubic
|
module Math.Bezier.Cubic
|
||||||
( Bezier(..)
|
( Bezier(..)
|
||||||
|
@ -20,9 +23,7 @@ import GHC.Generics
|
||||||
|
|
||||||
-- acts
|
-- acts
|
||||||
import Data.Act
|
import Data.Act
|
||||||
( Act
|
( Torsor
|
||||||
( (•) )
|
|
||||||
, Torsor
|
|
||||||
( (-->) )
|
( (-->) )
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -56,8 +57,8 @@ instance Module r p => Module r ( Bezier p ) where
|
||||||
bezier :: forall v r p. ( Torsor v p, Module r v ) => Bezier p -> r -> p
|
bezier :: forall v r p. ( Torsor v p, Module r v ) => Bezier p -> r -> p
|
||||||
bezier ( Bezier { .. } ) t =
|
bezier ( Bezier { .. } ) t =
|
||||||
lerp @v t
|
lerp @v t
|
||||||
( Quadratic.bezier ( Quadratic.Bezier p0 p1 p2 ) t )
|
( Quadratic.bezier @v ( Quadratic.Bezier p0 p1 p2 ) t )
|
||||||
( Quadratic.bezier ( Quadratic.Bezier p1 p2 p3 ) t )
|
( Quadratic.bezier @v ( Quadratic.Bezier p1 p2 p3 ) t )
|
||||||
|
|
||||||
-- | Derivative of cubic Bézier curve.
|
-- | Derivative of cubic Bézier curve.
|
||||||
bezier' :: forall v r p. ( Torsor v p, Module r v ) => Bezier p -> r -> v
|
bezier' :: forall v r p. ( Torsor v p, Module r v ) => Bezier p -> r -> v
|
||||||
|
|
|
@ -4,9 +4,12 @@
|
||||||
{-# LANGUAGE DeriveGeneric #-}
|
{-# LANGUAGE DeriveGeneric #-}
|
||||||
{-# LANGUAGE DeriveTraversable #-}
|
{-# LANGUAGE DeriveTraversable #-}
|
||||||
{-# LANGUAGE DerivingStrategies #-}
|
{-# LANGUAGE DerivingStrategies #-}
|
||||||
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
|
{-# LANGUAGE MultiParamTypeClasses #-}
|
||||||
{-# LANGUAGE RecordWildCards #-}
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
{-# LANGUAGE ScopedTypeVariables #-}
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
{-# LANGUAGE TypeApplications #-}
|
{-# LANGUAGE TypeApplications #-}
|
||||||
|
{-# LANGUAGE UndecidableInstances #-}
|
||||||
|
|
||||||
module Math.Bezier.Quadratic
|
module Math.Bezier.Quadratic
|
||||||
( Bezier(..)
|
( Bezier(..)
|
||||||
|
@ -20,9 +23,7 @@ import GHC.Generics
|
||||||
|
|
||||||
-- acts
|
-- acts
|
||||||
import Data.Act
|
import Data.Act
|
||||||
( Act
|
( Torsor
|
||||||
( (•) )
|
|
||||||
, Torsor
|
|
||||||
( (-->) )
|
( (-->) )
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{-# LANGUAGE AllowAmbiguousTypes #-}
|
{-# LANGUAGE AllowAmbiguousTypes #-}
|
||||||
{-# LANGUAGE MultiParamTypeClasses #-}
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
|
{-# LANGUAGE FunctionalDependencies #-}
|
||||||
{-# LANGUAGE ScopedTypeVariables #-}
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
|
|
||||||
module Math.Module
|
module Math.Module
|
||||||
|
@ -10,7 +11,9 @@ module Math.Module
|
||||||
|
|
||||||
-- acts
|
-- acts
|
||||||
import Data.Act
|
import Data.Act
|
||||||
( Torsor
|
( Act
|
||||||
|
( (•) )
|
||||||
|
, Torsor
|
||||||
( (-->) )
|
( (-->) )
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -19,7 +22,7 @@ import Data.Act
|
||||||
infixl 6 ^+^, ^-^
|
infixl 6 ^+^, ^-^
|
||||||
infix 8 ^*, *^
|
infix 8 ^*, *^
|
||||||
|
|
||||||
class Num r => Module r m where
|
class Num r => Module r m | m -> r where
|
||||||
|
|
||||||
{-# MINIMAL (^+^), ( (^*) | (*^) ) #-}
|
{-# MINIMAL (^+^), ( (^*) | (*^) ) #-}
|
||||||
|
|
||||||
|
@ -32,10 +35,5 @@ class Num r => Module r m where
|
||||||
(^*) = flip (*^)
|
(^*) = flip (*^)
|
||||||
m ^-^ n = m ^+^ (-1) *^ n
|
m ^-^ n = m ^+^ (-1) *^ n
|
||||||
|
|
||||||
instance Num a => Module a a where
|
|
||||||
(^+^) = (+)
|
|
||||||
(*^) = (*)
|
|
||||||
(^*) = (*)
|
|
||||||
|
|
||||||
lerp :: forall v r p. ( Module r v, Torsor v p ) => r -> p -> p -> p
|
lerp :: forall v r p. ( Module r v, Torsor v p ) => r -> p -> p -> p
|
||||||
lerp t p0 p1 = ( t *^ ( p0 --> p1 ) ) • p0
|
lerp t p0 p1 = ( t *^ ( p0 --> p1 :: v ) ) • p0
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
{-# LANGUAGE DeriveGeneric #-}
|
{-# LANGUAGE DeriveGeneric #-}
|
||||||
{-# LANGUAGE DeriveTraversable #-}
|
{-# LANGUAGE DeriveTraversable #-}
|
||||||
{-# LANGUAGE DerivingVia #-}
|
{-# LANGUAGE DerivingVia #-}
|
||||||
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||||
{-# LANGUAGE MultiParamTypeClasses #-}
|
{-# LANGUAGE MultiParamTypeClasses #-}
|
||||||
|
|
||||||
|
@ -11,6 +12,8 @@ module Math.Vector2D
|
||||||
where
|
where
|
||||||
|
|
||||||
-- base
|
-- base
|
||||||
|
import Data.Monoid
|
||||||
|
( Sum(..) )
|
||||||
import GHC.Generics
|
import GHC.Generics
|
||||||
( Generic )
|
( Generic )
|
||||||
|
|
||||||
|
@ -19,13 +22,17 @@ import Data.Act
|
||||||
( Act, Torsor )
|
( Act, Torsor )
|
||||||
|
|
||||||
-- generic-data
|
-- generic-data
|
||||||
import Data.Generic
|
import Generic.Data
|
||||||
( GenericProduct(..) )
|
( GenericProduct(..) )
|
||||||
|
|
||||||
-- groups
|
-- groups
|
||||||
import Data.Group
|
import Data.Group
|
||||||
( Group ( invert ) )
|
( Group ( invert ) )
|
||||||
|
|
||||||
|
-- groups-generic
|
||||||
|
import Data.Group.Generics
|
||||||
|
( )
|
||||||
|
|
||||||
-- MetaBrush
|
-- MetaBrush
|
||||||
import Math.Module
|
import Math.Module
|
||||||
( Module (..) )
|
( Module (..) )
|
||||||
|
@ -38,10 +45,9 @@ data Point2D a = Point2D !a !a
|
||||||
via Vector2D a
|
via Vector2D a
|
||||||
|
|
||||||
newtype Vector2D a = Vector2D { tip :: Point2D a }
|
newtype Vector2D a = Vector2D { tip :: Point2D a }
|
||||||
deriving stock Show
|
deriving stock ( Show, Functor, Foldable, Traversable )
|
||||||
deriving ( Semigroup, Monoid, Group )
|
deriving ( Semigroup, Monoid, Group )
|
||||||
via GenericProduct ( Point2D ( Sum a ) )
|
via GenericProduct ( Point2D ( Sum a ) )
|
||||||
deriving newtype ( Functor, Foldable, Traversable )
|
|
||||||
|
|
||||||
instance Num a => Module a ( Vector2D a ) where
|
instance Num a => Module a ( Vector2D a ) where
|
||||||
(^+^) = (<>)
|
(^+^) = (<>)
|
||||||
|
|
Loading…
Reference in a new issue