diff --git a/MetaBrush.cabal b/MetaBrush.cabal index dd35262..d302330 100644 --- a/MetaBrush.cabal +++ b/MetaBrush.cabal @@ -85,8 +85,8 @@ executable MetaBrush other-modules: MetaBrush.Asset.Colours , MetaBrush.Asset.Cursor + , MetaBrush.Asset.InfoBar , MetaBrush.Asset.Logo - , MetaBrush.Asset.Magnifier , MetaBrush.Asset.TickBox , MetaBrush.Asset.Tools , MetaBrush.Asset.WindowIcons diff --git a/app/Main.hs b/app/Main.hs index ae0fbdd..e04946e 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -2,6 +2,7 @@ {-# LANGUAGE ConstraintKinds #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-} +{-# LANGUAGE NegativeLiterals #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TypeApplications #-} @@ -28,6 +29,9 @@ import qualified System.Directory as Directory import qualified GI.Cairo.Render.Connector as Cairo ( renderWithContext ) +-- gi-cairo-render +import qualified GI.Cairo.Render as Cairo + -- gi-gdk import qualified GI.Gdk as GDK @@ -40,9 +44,11 @@ import qualified Data.Text as Text -- MetaBrush import MetaBrush.Asset.Colours - ( ColourRecord(..), getColours ) + ( getColours ) import MetaBrush.Asset.Cursor ( drawCursorIcon ) +import MetaBrush.Asset.InfoBar + ( drawMagnifier, drawTopLeftCornerRect ) import MetaBrush.Asset.Logo ( drawLogo ) import MetaBrush.Asset.Tools @@ -138,6 +144,11 @@ main = do widgetAddClass uiGrid "bg" --------------------------------------------------------- + -- Title bar + + widgetAddClass titleBar "titleBar" + + -------- -- Logo widgetAddClass logo "logo" @@ -148,10 +159,8 @@ main = do void $ GTK.onWidgetDraw logoArea $ Cairo.renderWithContext ( drawLogo colours ) - --------------------------------------------------------- - -- Title bar - - widgetAddClass titleBar "titleBar" + ------------ + -- Menu bar ( menuBar, _menu ) <- newMenuBar widgetAddClasses menuBar [ "menuBar", "text", "plain" ] @@ -258,12 +267,6 @@ main = do brushToolArea <- GTK.drawingAreaNew metaToolArea <- GTK.drawingAreaNew -{- - for_ [ selectionToolArea, brushToolArea, metaToolArea ] \ toolArea -> do - GTK.widgetSetValign toolArea GTK.AlignCenter - GTK.widgetSetHalign toolArea GTK.AlignCenter --} - GTK.containerAdd selectionTool selectionToolArea GTK.containerAdd penTool penToolArea GTK.containerAdd pathTool pathToolArea @@ -422,7 +425,83 @@ main = do --------------------------------------------------------- -- Info bar - widgetAddClass infoBar "infoBar" + widgetAddClasses infoBar [ "infoBar", "monospace", "contrast" ] + + zoomBox <- GTK.boxNew GTK.OrientationHorizontal 0 + cursorPosBox <- GTK.boxNew GTK.OrientationHorizontal 0 + topLeftPosBox <- GTK.boxNew GTK.OrientationHorizontal 0 + botRightPosBox <- GTK.boxNew GTK.OrientationHorizontal 0 + + for_ [ botRightPosBox, topLeftPosBox, cursorPosBox, zoomBox ] \ box -> do + GTK.boxPackEnd infoBar box False False 0 + widgetAddClass box "infoBarBox" + + ------------- + -- Magnifier + + magnifierArea <- GTK.drawingAreaNew + zoomText <- GTK.labelNew ( Just "300%" ) + + GTK.boxPackStart zoomBox magnifierArea True True 0 + GTK.boxPackStart zoomBox zoomText True True 0 + + void $ GTK.onWidgetDraw magnifierArea \ctx -> + ( `Cairo.renderWithContext` ctx ) $ do + Cairo.scale 0.9 0.9 + Cairo.translate 14 10 + drawMagnifier colours + + ------------------- + -- Cursor position + + cursorPosArea <- GTK.drawingAreaNew + cursorPosText <- GTK.labelNew ( Just "x: 212.12 px\ny: 120.23 px" ) + + GTK.boxPackStart cursorPosBox cursorPosArea False False 0 + GTK.boxPackStart cursorPosBox cursorPosText False False 0 + + void $ GTK.onWidgetDraw cursorPosArea \ctx -> + ( `Cairo.renderWithContext` ctx ) $ do + Cairo.scale 0.75 0.75 + Cairo.translate 10 7 + drawCursorIcon colours + + --------------------- + -- Top left position + + topLeftPosArea <- GTK.drawingAreaNew + topLeftPosText <- GTK.labelNew ( Just "x: 212.12 px\ny: 120.23 px" ) + + GTK.boxPackStart topLeftPosBox topLeftPosArea False False 0 + GTK.boxPackStart topLeftPosBox topLeftPosText False False 0 + + void $ GTK.onWidgetDraw topLeftPosArea + $ Cairo.renderWithContext + ( drawTopLeftCornerRect colours ) + + ------------------------- + -- Bottom right position + + botRightPosArea <- GTK.drawingAreaNew + botRightPosText <- GTK.labelNew ( Just "x: 212.12 px\ny: 120.23 px" ) + + GTK.boxPackStart botRightPosBox botRightPosArea False False 0 + GTK.boxPackStart botRightPosBox botRightPosText False False 0 + + void $ GTK.onWidgetDraw botRightPosArea \ctx -> + ( `Cairo.renderWithContext` ctx ) $ do + Cairo.scale -1 -1 + Cairo.translate -40 -40 + drawTopLeftCornerRect colours + + ------------------------- + + for_ [ magnifierArea, cursorPosArea, topLeftPosArea, botRightPosArea ] \ area -> do + widgetAddClass area "infoBarIcon" + GTK.widgetSetSizeRequest area 40 40 -- not sure why this is needed...? + + for_ [ zoomText, cursorPosText, topLeftPosText, botRightPosText ] \ info -> do + widgetAddClass info "infoBarInfo" --------------------------------------------------------- -- Actions diff --git a/assets/theme.css b/assets/theme.css index 84a5b6a..9907f40 100644 --- a/assets/theme.css +++ b/assets/theme.css @@ -10,7 +10,7 @@ background-color: rgb(72,70,61); } .highlight { - color: rgb(234,223,204) + color: rgb(234,223,204); } .cursor { color:rgb(234,223,204); @@ -48,6 +48,8 @@ .viewport { background-color: rgb(236, 223, 210); -GtkWidget-window-dragging: false; + min-width: 120px; + min-height: 90px; } .viewportScrollbar { background-color: rgba(45, 39, 39, 0.66); @@ -165,6 +167,7 @@ tooltip { } .menuItem { + color: rgba(212, 190, 152,0.5); background-color: rgb(41, 40, 40); padding-left: 8px; padding-right: 8px; @@ -175,21 +178,25 @@ tooltip { /* Menu item hover effect (workaround) */ .menuItem:selected { border-color: rgb(72,70,61); + color: rgb(212, 190, 152); } /* Styling for active menu item */ .menuItem:active, .menuItem:checked, .menuItem:hover { border-color: rgb(234,223,204); background-color: rgb(72,70,61); + color: rgb(212, 190, 152); } .menuItem > * > * { box-shadow: 2px 4px 3px -1px rgba(28,25,25,0.5); border: 1px solid rgb(28,25,25); border-top: 1px solid rgb(72,70,61); + color: rgb(212, 190, 152); } .submenuItem { + color: rgb(212, 190, 152); padding-top: 4px; padding-bottom: 4px; padding-left: 10px; diff --git a/img/MetaBrush_ui_mockup.svg b/img/MetaBrush_ui_mockup.svg index e156bef..e7fa673 100644 --- a/img/MetaBrush_ui_mockup.svg +++ b/img/MetaBrush_ui_mockup.svg @@ -8,9 +8,9 @@ xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="379.03928mm" + width="376.4017mm" height="233.0961mm" - viewBox="0 0 379.03928 233.0961" + viewBox="0 0 376.40171 233.0961" version="1.1" id="svg6301" inkscape:version="1.0 (4035a4fb49, 2020-05-01)" @@ -42,9 +42,9 @@ borderopacity="1.0" inkscape:pageopacity="0.0" inkscape:pageshadow="2" - inkscape:zoom="1.4142136" - inkscape:cx="385.83839" - inkscape:cy="253.70522" + inkscape:zoom="1" + inkscape:cx="549.39054" + inkscape:cy="345.34923" inkscape:document-units="mm" inkscape:current-layer="layer1" showgrid="false" @@ -66,6 +66,8 @@ inkscape:document-rotation="0" inkscape:lockguides="false"> @@ -77,7 +79,7 @@ image/svg+xml - + @@ -85,7 +87,7 @@ inkscape:label="Layer 1" inkscape:groupmode="layer" id="layer1" - transform="translate(162.74701,208.59428)" + transform="translate(160.10944,208.59428)" style="display:inline"> + style="opacity:1;fill:#2e2b4a;fill-opacity:1;stroke:none;stroke-width:0.0144343;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers" /> hover:select: hover:select: + style="opacity:1;fill:#f7ebf6;fill-opacity:1;stroke:#e3b9df;stroke-width:0.339009;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers" /> + style="opacity:1;fill:#48463d;fill-opacity:1;stroke:none;stroke-width:0.522892;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.992157;paint-order:stroke fill markers" /> + style="fill:#2b81b1;fill-opacity:1;stroke-width:0.854462;stroke-linecap:round;paint-order:stroke fill markers" /> + style="stroke-width:0.206108;stroke-miterlimit:4;stroke-dasharray:none"> + style="fill:none;stroke:#d4be98;stroke-width:0.229022;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> @@ -594,14 +596,14 @@ cy="-196.56718" r="1.040269" /> + style="fill:none;stroke:#a1dde9;stroke-width:0.529167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + style="fill:none;stroke:#a1dde9;stroke-width:0.529167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + style="fill:none;stroke:#a1dde9;stroke-width:0.529167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + style="fill:none;stroke:#a1dde9;stroke-width:0.529167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + style="fill:none;stroke:#a1dde9;stroke-width:0.529167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + style="fill:none;stroke:#a1dde9;stroke-width:0.529167;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> Stroke 3 + style="opacity:1;fill:none;fill-opacity:1;stroke:#eadfcc;stroke-width:0.452;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers" /> + style="opacity:1;fill:#eadfcc;fill-opacity:1;stroke:#48463d;stroke-width:0.548;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers" /> View + style="opacity:1;fill:#48463d;fill-opacity:1;stroke:none;stroke-width:2.59514;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.992157;paint-order:stroke fill markers" /> + style="opacity:1;fill:none;fill-opacity:1;stroke:#eadfcc;stroke-width:0.452;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers" /> Stroke 5 x: 212.12 pxy: 120.23 px @@ -5334,7 +5336,7 @@ sodipodi:role="line">x: 10.05 pxy: 340.23 px x: 410.12 pxy: 20.00 px 300% Transform settings ... + style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#eadfcc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.452;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> + style="opacity:1;fill:#eadfcc;fill-opacity:1;stroke:none;stroke-width:0.548;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers" /> + style="color:#000000;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:medium;line-height:normal;font-family:sans-serif;font-variant-ligatures:normal;font-variant-position:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-alternates:normal;font-feature-settings:normal;text-indent:0;text-align:start;text-decoration:none;text-decoration-line:none;text-decoration-style:solid;text-decoration-color:#000000;letter-spacing:normal;word-spacing:normal;text-transform:none;writing-mode:lr-tb;direction:ltr;text-orientation:mixed;dominant-baseline:auto;baseline-shift:baseline;text-anchor:start;white-space:normal;shape-padding:0;clip-rule:nonzero;display:inline;overflow:visible;visibility:visible;opacity:1;isolation:auto;mix-blend-mode:normal;color-interpolation:sRGB;color-interpolation-filters:linearRGB;solid-color:#000000;solid-opacity:1;vector-effect:none;fill:#eadfcc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.452;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:stroke fill markers;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate" /> Cairo.Render Bool +drawTopLeftCornerRect ( Colours { bg, viewport } ) = do + + Cairo.newPath + Cairo.moveTo 8 10 + Cairo.lineTo 32 10 + Cairo.lineTo 32 30 + Cairo.lineTo 8 30 + Cairo.closePath + + withRGBA viewport Cairo.setSourceRGBA + Cairo.fill + + Cairo.newPath + Cairo.moveTo 12 24 + Cairo.lineTo 12 14 + Cairo.lineTo 24 14 + + Cairo.setLineWidth 4 + withRGBA bg Cairo.setSourceRGBA + Cairo.stroke pure True