From cc96802f8e54469fd5dacf8f5df352bab7921fae Mon Sep 17 00:00:00 2001 From: sheaf Date: Fri, 7 Aug 2020 21:39:24 +0200 Subject: [PATCH] window icons, tool bar --- MetaBrush.cabal | 2 + app/Main.hs | 140 +++++++++++++++++++++++-- assets/icon.png | Bin 0 -> 4824 bytes assets/theme.css | 60 +++++++++-- img/MetaBrush_ui_mockup.svg | 98 ++++++++++++----- src/app/MetaBrush/Asset/Cursor.hs | 47 +++++++++ src/app/MetaBrush/Asset/WindowIcons.hs | 97 +++++++++++++++-- 7 files changed, 390 insertions(+), 54 deletions(-) create mode 100644 assets/icon.png create mode 100644 src/app/MetaBrush/Asset/Cursor.hs diff --git a/MetaBrush.cabal b/MetaBrush.cabal index 0d9602e..622a6a1 100644 --- a/MetaBrush.cabal +++ b/MetaBrush.cabal @@ -10,6 +10,7 @@ data-dir: assets data-files: theme.css + icon.png description: MetaBrush is a GUI for brush calligraphy based on Bézier curves. @@ -84,6 +85,7 @@ executable MetaBrush other-modules: MetaBrush.Asset.Brush , MetaBrush.Asset.Colours + , MetaBrush.Asset.Cursor , MetaBrush.Asset.Logo , MetaBrush.Asset.Magnifier , MetaBrush.Asset.Meta diff --git a/app/Main.hs b/app/Main.hs index da06f6b..86eef31 100644 --- a/app/Main.hs +++ b/app/Main.hs @@ -39,10 +39,18 @@ import qualified Data.Text as Text ( pack ) -- MetaBrush +import MetaBrush.Asset.Brush + ( drawBrush ) import MetaBrush.Asset.Colours ( ColourRecord(..), colours ) +import MetaBrush.Asset.Cursor + ( drawCursorIcon ) import MetaBrush.Asset.Logo ( drawLogo ) +import MetaBrush.Asset.Meta + ( drawMeta ) +import MetaBrush.Asset.WindowIcons + ( drawMinimise, drawRestoreDown, drawMaximise, drawClose ) import MetaBrush.Event ( handleKeyboardPressEvent, handleKeyboardReleaseEvent ) import MetaBrush.Render.Util @@ -88,6 +96,9 @@ main = do ( Just windowGeometry ) [ GDK.WindowHintsMinSize ] + iconPath <- Directory.canonicalizePath =<< Cabal.getDataFileName "icon.png" + GTK.windowSetIconFromFile window iconPath + Colours { .. } <- colours windowWidgetPath --------------------------------------------------------- @@ -106,9 +117,9 @@ main = do panelGrid <- GTK.gridNew GTK.gridAttach uiGrid logo 0 0 1 2 - GTK.gridAttach uiGrid titleBar 1 0 3 1 - GTK.gridAttach uiGrid toolBar 0 2 2 2 - GTK.gridAttach uiGrid mainPane 2 1 2 4 + GTK.gridAttach uiGrid titleBar 1 0 2 1 + GTK.gridAttach uiGrid toolBar 0 2 2 1 + GTK.gridAttach uiGrid mainPane 2 2 1 1 mainView <- GTK.boxNew GTK.OrientationVertical 0 @@ -149,6 +160,20 @@ main = do widgetAddClasses menuBar [ "menuBar", "text", "plain" ] GTK.boxPackStart titleBar menuBar False False 0 + -- TODO: this is a bit of a workaround to add hover highlight to top-level menu items. + -- Activating a menu somehow sets the "hover" setting, + -- so instead we use the "selected" setting for actual hover highlighting. + topLevelMenuItems <- GTK.containerGetChildren menuBar + for_ topLevelMenuItems \ topLevelMenuItem -> do + void $ GTK.onWidgetEnterNotifyEvent topLevelMenuItem \ _ -> do + flags <- GTK.widgetGetStateFlags topLevelMenuItem + GTK.widgetSetStateFlags topLevelMenuItem ( GTK.StateFlagsSelected : flags ) True + pure False + void $ GTK.onWidgetLeaveNotifyEvent topLevelMenuItem \ _ -> do + flags <- GTK.widgetGetStateFlags topLevelMenuItem + GTK.widgetSetStateFlags topLevelMenuItem ( filter ( /= GTK.StateFlagsSelected ) flags ) True + pure False + windowIcons <- GTK.boxNew GTK.OrientationHorizontal 0 widgetAddClasses windowIcons [ "windowIcon" ] GTK.boxPackEnd titleBar windowIcons False False 0 @@ -157,11 +182,91 @@ main = do widgetAddClasses title [ "text", "title", "plain" ] GTK.boxSetCenterWidget titleBar ( Just title ) + minimiseButton <- GTK.buttonNew + fullscreenButton <- GTK.buttonNew + closeButton <- GTK.buttonNew + + GTK.boxPackStart windowIcons minimiseButton True True 0 + GTK.boxPackStart windowIcons fullscreenButton True True 0 + GTK.boxPackStart windowIcons closeButton True True 0 + + minimiseArea <- GTK.drawingAreaNew + fullscreenArea <- GTK.drawingAreaNew + closeArea <- GTK.drawingAreaNew + + GTK.containerAdd minimiseButton minimiseArea + GTK.containerAdd fullscreenButton fullscreenArea + GTK.containerAdd closeButton closeArea + + void $ GTK.onWidgetDraw minimiseArea + $ Cairo.renderWithContext + ( drawMinimise plain ) + + void $ GTK.onWidgetDraw fullscreenArea \ cairoContext -> do + Just gdkWindow <- GTK.widgetGetWindow window + windowState <- GDK.windowGetState gdkWindow + if any ( \case { GDK.WindowStateFullscreen -> True; GDK.WindowStateMaximized -> True; _ -> False } ) windowState + then Cairo.renderWithContext ( drawRestoreDown plain ) cairoContext + else Cairo.renderWithContext ( drawMaximise plain ) cairoContext + + void $ GTK.onWidgetDraw closeArea + $ Cairo.renderWithContext + ( drawClose plain ) + + + for_ [ minimiseButton, fullscreenButton, closeButton ] \ button -> do + widgetAddClass button "windowIcon" + + widgetAddClass closeButton "closeWindowIcon" + --------------------------------------------------------- -- Tool bar widgetAddClass toolBar "toolBar" + GTK.widgetSetValign toolBar GTK.AlignStart + GTK.widgetSetVexpand toolBar True + + toolBarPhantomRadioButton <- GTK.radioButtonNew ( [] @GTK.RadioButton ) + + selectionTool <- GTK.radioButtonNewFromWidget ( Just toolBarPhantomRadioButton ) + brushTool <- GTK.radioButtonNewFromWidget ( Just toolBarPhantomRadioButton ) + metaTool <- GTK.radioButtonNewFromWidget ( Just toolBarPhantomRadioButton ) + + GTK.boxPackStart toolBar selectionTool True True 0 + GTK.boxPackStart toolBar brushTool True True 0 + GTK.boxPackStart toolBar metaTool True True 0 + + for_ [ selectionTool, brushTool, metaTool ] \ tool -> do + GTK.toggleButtonSetMode tool False -- don't display radio indicator + widgetAddClass tool "toolItem" + + selectionToolArea <- GTK.drawingAreaNew + 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 brushTool brushToolArea + GTK.containerAdd metaTool metaToolArea + + void $ GTK.onWidgetDraw selectionToolArea + $ Cairo.renderWithContext + ( drawCursorIcon logo_base ) + + void $ GTK.onWidgetDraw brushToolArea + $ Cairo.renderWithContext + ( drawBrush logo_base logo_highlight logo_base ) + + void $ GTK.onWidgetDraw metaToolArea + $ Cairo.renderWithContext + ( drawMeta logo_highlight ) + --------------------------------------------------------- -- File bar @@ -171,11 +276,11 @@ main = do GTK.containerAdd fileBar fileTabs widgetAddClasses fileTabs [ "fileBar", "plain", "text" ] - phantomRadioButton <- GTK.radioButtonNew ( [] @GTK.RadioButton ) + fileBarPhantomRadioButton <- GTK.radioButtonNew ( [] @GTK.RadioButton ) for_ [ 1 .. 12 ] \ i -> do -- File tab elements. - pgButton <- GTK.radioButtonNewWithLabelFromWidget ( Just phantomRadioButton ) ( "New Document (" <> Text.pack ( show i ) <> ")" ) + pgButton <- GTK.radioButtonNewWithLabelFromWidget ( Just fileBarPhantomRadioButton ) ( "New Document (" <> Text.pack ( show i ) <> ")" ) GTK.toggleButtonSetMode pgButton False -- don't display radio indicator closeFileButton <- GTK.buttonNewWithLabel "x" @@ -189,6 +294,8 @@ main = do widgetAddClasses pgButton [ "fileBarTabButton" ] widgetAddClasses closeFileButton [ "fileBarCloseButton" ] + -- Make both file tab elements activate styling on the whole tab + -- (e.g. hovering over the close file button should highlight the whole tab). void $ GTK.onButtonClicked pgButton do active <- GTK.toggleButtonGetActive pgButton flags <- GTK.widgetGetStateFlags tab @@ -297,14 +404,27 @@ main = do --------------------------------------------------------- -- Actions + GTK.widgetAddEvents window [GDK.EventMaskKeyPressMask, GDK.EventMaskKeyReleaseMask] + + _ <- GTK.onButtonClicked closeButton GTK.mainQuit + _ <- GTK.onButtonClicked minimiseButton ( GTK.windowIconify window ) + _ <- GTK.onButtonClicked fullscreenButton do + Just gdkWindow <- GTK.widgetGetWindow window + windowState <- GDK.windowGetState gdkWindow + if GDK.WindowStateFullscreen `elem` windowState + then GTK.windowUnfullscreen window + else + if GDK.WindowStateMaximized `elem` windowState + then GTK.windowUnmaximize window + else GTK.windowMaximize window + + _ <- GTK.onWidgetKeyPressEvent window handleKeyboardPressEvent + _ <- GTK.onWidgetKeyReleaseEvent window handleKeyboardReleaseEvent + _ <- GTK.onWidgetDestroy window GTK.mainQuit + --------------------------------------------------------- -- GTK main loop - GTK.widgetAddEvents window [GDK.EventMaskKeyPressMask, GDK.EventMaskKeyReleaseMask] - _ <- GTK.onWidgetKeyPressEvent window handleKeyboardPressEvent - _ <- GTK.onWidgetKeyReleaseEvent window handleKeyboardReleaseEvent - _ <- GTK.onWidgetDestroy window GTK.mainQuit - GTK.widgetShowAll window GTK.main diff --git a/assets/icon.png b/assets/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e1ca0479a03620d920113473b97a5217a28b2bb7 GIT binary patch literal 4824 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 * :hover { background-color: rgb(72,70,61); } +*/ .title { border-top: 2px solid rgb(41, 40, 40); @@ -132,12 +133,17 @@ border-top: 2px solid rgb(41, 40, 40); } -.menuItem:hover { +/* Menu item hover effect (workaround) */ +.menuItem:selected { + border-color: rgb(72,70,61); +} + +/* Styling for active menu item */ +.menuItem:active, .menuItem:checked, .menuItem:hover { border-color: rgb(234,223,204); background-color: rgb(72,70,61); } -/* Menu drop shadow */ .menuItem > * > * { box-shadow: 2px 4px 3px -1px rgba(28,25,25,0.5); border: 1px solid rgb(28,25,25); @@ -153,6 +159,10 @@ border-left: 2px solid rgb(41, 40, 40); } +.submenuItem:hover{ + background-color: rgb(72,70,61); +} + .submenuItem:disabled { color: rgb(149,149,149); } @@ -166,14 +176,48 @@ border-color: rgb(234,223,204); } -/* .windowIcon { + min-width: 24px; +} + +.windowIcon:hover { + background-color: rgb(34,131,186); +} + +.windowIcon:active, .windowIcon:checked { + background-color: rgb(23,108,156); +} + +.closeWindowIcon:hover { + background-color: rgb(181,43,43); +} + +.closeWindowIcon:active, .closeWindowIcon:checked { + background-color: rgb(160,37,37); } -*/ /* Tool bar */ .toolBar { - min-width: 60px; + min-width: 32px; + margin-top: 28px; +} + +.toolItem { + border-left: 2px solid rgb(41, 40, 40); + min-height: 32px; + min-width: 38px; + padding-top: 12px; + padding-bottom: 8px; + padding-left: 6px; +} + +.toolItem:hover { + border-color: rgb(72,70,61); +} + +.toolItem:active, .toolItem:checked { + border-color: rgb(234,223,204); + background-color: rgb(72,70,61); } /* File bar */ @@ -184,7 +228,7 @@ } .fileBarTab { - border-top: 3px solid rgb(41, 40, 40); + border-top: 2px solid rgb(41, 40, 40); } .fileBarTab:hover { diff --git a/img/MetaBrush_ui_mockup.svg b/img/MetaBrush_ui_mockup.svg index b02bb02..5a1aeb8 100644 --- a/img/MetaBrush_ui_mockup.svg +++ b/img/MetaBrush_ui_mockup.svg @@ -5,6 +5,7 @@ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" + 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" sodipodi:docname="MetaBrush_ui_mockup.svg" @@ -55,15 +56,19 @@ showgrid="false" inkscape:current-layer="layer1" inkscape:document-units="mm" - inkscape:cy="399.13966" - inkscape:cx="834.67434" - inkscape:zoom="0.70710678" + inkscape:cy="-120.95892" + inkscape:cx="667.79746" + inkscape:zoom="1" inkscape:pageshadow="2" inkscape:pageopacity="0.0" borderopacity="1.0" bordercolor="#666666" pagecolor="#ffffff" - id="base" /> + id="base"> + + @@ -447,16 +452,16 @@ d="m 53.697983,130.46852 c -0.398481,-0.58922 -0.794322,-1.7911 -1.048322,-1.73818 -0.137583,-0.0423 -2.879333,4.01184 -3.122749,4.29759 -0.275167,-0.28575 -0.645584,0.0212 -0.677334,0.45508 0,0.22225 0.538837,0.84005 1.005417,0.16933 0.04401,-0.0633 2.128203,-2.97885 2.322592,-3.26489 0.169333,0.34925 0.869778,1.57275 0.912111,1.62567 0.413037,-0.20721 0.507142,-0.33141 0.729392,-0.59599 0.254032,-0.35144 0.287311,-0.3959 0.629738,-0.84526 0.15875,0.32808 0.651865,0.86911 1.100666,1.44991 0.169643,0.21954 0.893474,0.96206 1.105878,0.87896 0.113388,-0.0444 0.516106,-0.40729 0.587459,-0.79224 0.01599,-0.0863 0.05612,-0.41482 -0.01708,-0.48091 -0.05177,-0.0468 -0.483647,0.19656 -0.618249,0.14287 -0.232945,-0.34124 -0.51833,-0.93511 -0.765006,-1.34591 -0.391583,-0.70908 -0.69744,-1.58033 -1.012682,-1.38728 -0.218958,0.13409 -0.343747,0.30086 -0.391584,0.37042 -0.219248,0.31882 -0.322696,0.47584 -0.740261,1.06082 z" /> + sodipodi:nodetypes="ccccc" + id="path4307" + d="m 194.23426,-203.9466 v 0.99478 h 3.09843 v -0.99478 z" + 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-variant-east-asian:normal;font-feature-settings:normal;font-variation-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;shape-margin:0;inline-size: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:#d4be98;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.415235;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;color-rendering:auto;image-rendering:auto;shape-rendering:auto;text-rendering:auto;enable-background:accumulate;stop-color:#000000;stop-opacity:1" /> @@ -464,25 +469,18 @@ inkscape:connector-curvature="0" id="path1755" d="m 151.28645,19.176929 1.56634,-1.56634" - style="fill:none;stroke:#d4be98;stroke-width:0.20610821;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> + style="fill:none;stroke:#d4be98;stroke-width:0.22902154;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /> - + sodipodi:nodetypes="ccccccccccccccccccccc" + transform="matrix(0.13348279,0,0,0.13596576,-38.35818,15.738262)" + d="m 1378.666,7.5722656 v 5.0508574 h -3.5117 v 9.876341 h 10.8697 v -4.345243 h 3.5117 V 7.5722656 Z m 1.5352,3.0839624 h 7.7838 v 5.974556 h -1.961 v -4.007661 h -5.8228 z m -3.5117,5.05281 h 7.7837 v 5.280661 h -7.7837 z" + 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-variant-east-asian:normal;font-feature-settings:normal;font-variation-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;shape-margin:0;inline-size: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:#d4be98;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.52992;stroke-linecap:butt;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;stop-color:#000000;stop-opacity:1" + id="path4298" /> + style="opacity:1;vector-effect:none;fill:#332727;fill-opacity:0.57647061;stroke:none;stroke-width:0.45031363;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal" /> . . . + + + diff --git a/src/app/MetaBrush/Asset/Cursor.hs b/src/app/MetaBrush/Asset/Cursor.hs new file mode 100644 index 0000000..00e6064 --- /dev/null +++ b/src/app/MetaBrush/Asset/Cursor.hs @@ -0,0 +1,47 @@ +module MetaBrush.Asset.Cursor + ( drawCursor, drawCursorIcon ) + where + +-- gi-cairo-render +import qualified GI.Cairo.Render as Cairo + +-- gi-gdk +import qualified GI.Gdk as GDK + +-- MetaBrush +import MetaBrush.Render.Util + ( withRGBA ) + +-------------------------------------------------------------------------------- + +-- | "Selection" mouse cursor. 18 x 18. +drawCursor :: GDK.RGBA -> GDK.RGBA -> Cairo.Render Bool +drawCursor cursorColour outlineColour = do + + Cairo.setLineWidth 1 + withRGBA outlineColour Cairo.setSourceRGBA + Cairo.newPath + Cairo.moveTo 12.625 10.582031 + Cairo.curveTo 5.699219 11.101563 4.097656 12.3125 0 17.976563 + Cairo.lineTo 0.078125 0 + Cairo.closePath + Cairo.strokePreserve + + withRGBA cursorColour Cairo.setSourceRGBA + Cairo.fillPreserve + + pure True + +-- | "Selection" tool icon. 30 x 30. +drawCursorIcon :: GDK.RGBA -> Cairo.Render Bool +drawCursorIcon cursorColour = do + + withRGBA cursorColour Cairo.setSourceRGBA + Cairo.newPath + Cairo.moveTo 24.023438 16.3125 + Cairo.curveTo 15.636719 16.9375 13.699219 18.40625 8.742188 25.261719 + Cairo.lineTo 8.835938 3.503906 + Cairo.closePath + Cairo.fillPreserve + + pure True diff --git a/src/app/MetaBrush/Asset/WindowIcons.hs b/src/app/MetaBrush/Asset/WindowIcons.hs index 1531ca4..da9bd2b 100644 --- a/src/app/MetaBrush/Asset/WindowIcons.hs +++ b/src/app/MetaBrush/Asset/WindowIcons.hs @@ -9,23 +9,98 @@ import qualified GI.Cairo.Render as Cairo import qualified GI.Gdk as GDK -- MetaBrush ---import MetaBrush.Render.Util --- ( withRGBA ) +import MetaBrush.Render.Util + ( withRGBA ) -------------------------------------------------------------------------------- --- | Minimise window icon. -drawMinimise :: GDK.RGBA -> Cairo.Render () -drawMinimise iconColour = pure () +-- | Minimise window icon. +drawMinimise :: GDK.RGBA -> Cairo.Render Bool +drawMinimise iconColour = do + + withRGBA iconColour Cairo.setSourceRGBA + + Cairo.newPath + Cairo.moveTo 6.144531 12.914063 + Cairo.lineTo 6.144531 16.675781 + Cairo.lineTo 17.855469 16.675781 + Cairo.lineTo 17.855469 12.914063 + Cairo.closePath + Cairo.fillPreserve + + pure True -- | Restore down window icon. -drawRestoreDown :: GDK.RGBA -> Cairo.Render () -drawRestoreDown iconColour = pure () +drawRestoreDown :: GDK.RGBA -> Cairo.Render Bool +drawRestoreDown iconColour = do + + withRGBA iconColour Cairo.setSourceRGBA + + Cairo.newPath + Cairo.moveTo 8.453125 4.179688 + Cairo.lineTo 8.453125 9.230469 + Cairo.lineTo 4.941406 9.230469 + Cairo.lineTo 4.941406 19.105469 + Cairo.lineTo 15.8125 19.105469 + Cairo.lineTo 15.8125 14.761719 + Cairo.lineTo 19.324219 14.761719 + Cairo.lineTo 19.324219 4.179688 + Cairo.closePath + Cairo.moveTo 9.988281 7.261719 + Cairo.lineTo 17.773438 7.261719 + Cairo.lineTo 17.773438 13.238281 + Cairo.lineTo 15.8125 13.238281 + Cairo.lineTo 15.8125 9.230469 + Cairo.lineTo 9.988281 9.230469 + Cairo.closePath + Cairo.moveTo 6.476563 12.316406 + Cairo.lineTo 14.261719 12.316406 + Cairo.lineTo 14.261719 17.597656 + Cairo.lineTo 6.476563 17.597656 + Cairo.closePath + Cairo.fillPreserve + + pure True -- | Maximise window icon. -drawMaximise :: GDK.RGBA -> Cairo.Render () -drawMaximise iconColour = pure () +drawMaximise :: GDK.RGBA -> Cairo.Render Bool +drawMaximise iconColour = do + + withRGBA iconColour Cairo.setSourceRGBA + + Cairo.newPath + Cairo.moveTo 5.386719 5.449219 + Cairo.lineTo 5.386719 18.550781 + Cairo.lineTo 18.613281 18.550781 + Cairo.lineTo 18.613281 5.449219 + Cairo.closePath + Cairo.moveTo 6.921875 9.128906 + Cairo.lineTo 17.078125 9.128906 + Cairo.lineTo 17.078125 17.023438 + Cairo.lineTo 6.921875 17.023438 + Cairo.closePath + Cairo.fillPreserve + + pure True -- | Close window icon. -drawClose :: GDK.RGBA -> Cairo.Render () -drawClose iconColour = pure () +drawClose :: GDK.RGBA -> Cairo.Render Bool +drawClose iconColour = do + + Cairo.setLineWidth 2 + withRGBA iconColour Cairo.setSourceRGBA + + Cairo.setLineCap Cairo.LineCapRound + Cairo.setLineJoin Cairo.LineJoinMiter + + Cairo.newPath + Cairo.moveTo 6.132813 6.238281 + Cairo.lineTo 17.867188 17.761719 + Cairo.strokePreserve + + Cairo.newPath + Cairo.moveTo 6.132813 17.761719 + Cairo.lineTo 17.867188 6.23828 + Cairo.strokePreserve + + pure True