mirror of
https://gitlab.com/sheaf/metabrush.git
synced 2024-11-05 23:03:38 +00:00
dynamic file tab close button behaviour
This commit is contained in:
parent
86729cb462
commit
264fa8dff0
|
@ -98,6 +98,7 @@ executable MetaBrush
|
||||||
other-modules:
|
other-modules:
|
||||||
MetaBrush.Action
|
MetaBrush.Action
|
||||||
, MetaBrush.Asset.Brushes
|
, MetaBrush.Asset.Brushes
|
||||||
|
, MetaBrush.Asset.CloseTabButton
|
||||||
, MetaBrush.Asset.Colours
|
, MetaBrush.Asset.Colours
|
||||||
, MetaBrush.Asset.Cursor
|
, MetaBrush.Asset.Cursor
|
||||||
, MetaBrush.Asset.InfoBar
|
, MetaBrush.Asset.InfoBar
|
||||||
|
|
|
@ -332,6 +332,7 @@ main = do
|
||||||
|
|
||||||
fileBar@( FileBar { fileBarBox } ) <-
|
fileBar@( FileBar { fileBarBox } ) <-
|
||||||
createFileBar
|
createFileBar
|
||||||
|
colours
|
||||||
variables
|
variables
|
||||||
window titleBar title viewportDrawingArea infoBar
|
window titleBar title viewportDrawingArea infoBar
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,9 @@
|
||||||
.active {
|
.active {
|
||||||
background-color: rgb(72,70,61);
|
background-color: rgb(72,70,61);
|
||||||
}
|
}
|
||||||
|
.close {
|
||||||
|
color: rgb(181,43,43);
|
||||||
|
}
|
||||||
.highlight {
|
.highlight {
|
||||||
color: rgb(234,223,204);
|
color: rgb(234,223,204);
|
||||||
}
|
}
|
||||||
|
@ -349,11 +352,13 @@ tooltip {
|
||||||
|
|
||||||
.fileBarTabButton {
|
.fileBarTabButton {
|
||||||
padding-left: 8px;
|
padding-left: 8px;
|
||||||
padding-right: 3px;
|
padding-right: 2px;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fileBarCloseButton {
|
.fileBarCloseButton {
|
||||||
|
min-width: 10px;
|
||||||
|
min-height: 22px;
|
||||||
padding-left: 1px;
|
padding-left: 1px;
|
||||||
padding-right: 5px;
|
padding-right: 5px;
|
||||||
margin: 0px;
|
margin: 0px;
|
||||||
|
|
|
@ -126,7 +126,7 @@ data NewFile = NewFile TabLocation
|
||||||
|
|
||||||
instance HandleAction NewFile where
|
instance HandleAction NewFile where
|
||||||
handleAction uiElts vars ( NewFile tabLoc ) =
|
handleAction uiElts vars ( NewFile tabLoc ) =
|
||||||
newFileTab vars uiElts Nothing tabLoc
|
newFileTab uiElts vars Nothing tabLoc
|
||||||
|
|
||||||
---------------
|
---------------
|
||||||
-- Open file --
|
-- Open file --
|
||||||
|
@ -155,7 +155,7 @@ instance HandleAction OpenFile where
|
||||||
case mbDoc of
|
case mbDoc of
|
||||||
Left _errMessage -> pure () -- TODO: show warning dialog?
|
Left _errMessage -> pure () -- TODO: show warning dialog?
|
||||||
Right doc -> do
|
Right doc -> do
|
||||||
newFileTab vars uiElts ( Just doc ) tabLoc
|
newFileTab uiElts vars ( Just doc ) tabLoc
|
||||||
|
|
||||||
-----------------
|
-----------------
|
||||||
-- Open folder --
|
-- Open folder --
|
||||||
|
@ -184,7 +184,7 @@ instance HandleAction OpenFolder where
|
||||||
case mbDoc of
|
case mbDoc of
|
||||||
Left _errMessage -> pure () -- TODO: show warning dialog?
|
Left _errMessage -> pure () -- TODO: show warning dialog?
|
||||||
Right doc -> do
|
Right doc -> do
|
||||||
newFileTab vars uiElts ( Just doc ) tabLoc
|
newFileTab uiElts vars ( Just doc ) tabLoc
|
||||||
pure ()
|
pure ()
|
||||||
|
|
||||||
---------------
|
---------------
|
||||||
|
|
75
src/app/MetaBrush/Asset/CloseTabButton.hs
Normal file
75
src/app/MetaBrush/Asset/CloseTabButton.hs
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
{-# LANGUAGE BlockArguments #-}
|
||||||
|
{-# LANGUAGE NegativeLiterals #-}
|
||||||
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
|
|
||||||
|
module MetaBrush.Asset.CloseTabButton
|
||||||
|
( drawCloseTabButton )
|
||||||
|
where
|
||||||
|
|
||||||
|
-- gi-cairo-render
|
||||||
|
import qualified GI.Cairo.Render as Cairo
|
||||||
|
|
||||||
|
-- gi-gtk
|
||||||
|
import qualified GI.Gtk as GTK
|
||||||
|
|
||||||
|
-- MetaBrush
|
||||||
|
import MetaBrush.Asset.Colours
|
||||||
|
( ColourRecord(..), Colours )
|
||||||
|
import MetaBrush.Util
|
||||||
|
( withRGBA )
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
-- | "Close tab" button.
|
||||||
|
drawCloseTabButton :: Colours -> Bool -> [ GTK.StateFlags ] -> Cairo.Render Bool
|
||||||
|
drawCloseTabButton ( Colours { .. } ) unsavedChanges flags = do
|
||||||
|
|
||||||
|
Cairo.setLineCap Cairo.LineCapRound
|
||||||
|
Cairo.setLineJoin Cairo.LineJoinMiter
|
||||||
|
|
||||||
|
if unsavedChanges
|
||||||
|
then do
|
||||||
|
if clicked
|
||||||
|
then withRGBA close Cairo.setSourceRGBA
|
||||||
|
else withRGBA plain Cairo.setSourceRGBA
|
||||||
|
Cairo.arc 5 11 5 0 ( 2 * pi )
|
||||||
|
Cairo.fill
|
||||||
|
if clicked
|
||||||
|
then withRGBA bg Cairo.setSourceRGBA
|
||||||
|
else
|
||||||
|
if hover
|
||||||
|
then withRGBA close Cairo.setSourceRGBA
|
||||||
|
else withRGBA bg Cairo.setSourceRGBA
|
||||||
|
else
|
||||||
|
if clicked
|
||||||
|
then do
|
||||||
|
Cairo.setLineWidth 5
|
||||||
|
withRGBA close Cairo.setSourceRGBA
|
||||||
|
drawCross
|
||||||
|
|
||||||
|
withRGBA bg Cairo.setSourceRGBA
|
||||||
|
else
|
||||||
|
if hover
|
||||||
|
then withRGBA close Cairo.setSourceRGBA
|
||||||
|
else withRGBA plain Cairo.setSourceRGBA
|
||||||
|
|
||||||
|
Cairo.setLineWidth 2
|
||||||
|
|
||||||
|
drawCross
|
||||||
|
|
||||||
|
pure True
|
||||||
|
where
|
||||||
|
hover, clicked :: Bool
|
||||||
|
hover = any ( == GTK.StateFlagsPrelight ) flags
|
||||||
|
clicked = any ( == GTK.StateFlagsActive ) flags
|
||||||
|
|
||||||
|
drawCross :: Cairo.Render ()
|
||||||
|
drawCross = do
|
||||||
|
Cairo.newPath
|
||||||
|
Cairo.moveTo 3 9
|
||||||
|
Cairo.lineTo 7 13
|
||||||
|
Cairo.stroke
|
||||||
|
|
||||||
|
Cairo.moveTo 3 13
|
||||||
|
Cairo.lineTo 7 9
|
||||||
|
Cairo.stroke
|
|
@ -30,7 +30,7 @@ import Data.Text
|
||||||
|
|
||||||
data ColourRecord a
|
data ColourRecord a
|
||||||
= Colours
|
= Colours
|
||||||
{ bg, active, highlight, cursor, cursorOutline
|
{ bg, active, close, highlight, cursor, cursorOutline
|
||||||
, plain, base, splash
|
, plain, base, splash
|
||||||
, pathPoint, pathPointOutline, controlPoint, controlPointOutline
|
, pathPoint, pathPointOutline, controlPoint, controlPointOutline
|
||||||
, path, brush, brushStroke, brushCenter
|
, path, brush, brushStroke, brushCenter
|
||||||
|
@ -58,6 +58,7 @@ colourNames :: ColourRecord ColourName
|
||||||
colourNames = Colours
|
colourNames = Colours
|
||||||
{ bg = ColourName "bg" BackgroundColour [ GTK.StateFlagsNormal ]
|
{ bg = ColourName "bg" BackgroundColour [ GTK.StateFlagsNormal ]
|
||||||
, active = ColourName "active" BackgroundColour [ GTK.StateFlagsNormal ]
|
, active = ColourName "active" BackgroundColour [ GTK.StateFlagsNormal ]
|
||||||
|
, close = ColourName "close" Colour [ GTK.StateFlagsNormal ]
|
||||||
, highlight = ColourName "highlight" Colour [ GTK.StateFlagsNormal ]
|
, highlight = ColourName "highlight" Colour [ GTK.StateFlagsNormal ]
|
||||||
, cursor = ColourName "cursor" Colour [ GTK.StateFlagsNormal ]
|
, cursor = ColourName "cursor" Colour [ GTK.StateFlagsNormal ]
|
||||||
, cursorOutline = ColourName "cursorStroke" Colour [ GTK.StateFlagsNormal ]
|
, cursorOutline = ColourName "cursorStroke" Colour [ GTK.StateFlagsNormal ]
|
||||||
|
|
|
@ -52,6 +52,8 @@ import Data.Text
|
||||||
-- MetaBrush
|
-- MetaBrush
|
||||||
import Math.Vector2D
|
import Math.Vector2D
|
||||||
( Point2D )
|
( Point2D )
|
||||||
|
import MetaBrush.Asset.Colours
|
||||||
|
( Colours )
|
||||||
import MetaBrush.Document
|
import MetaBrush.Document
|
||||||
( Document(..) )
|
( Document(..) )
|
||||||
import MetaBrush.Document.Draw
|
import MetaBrush.Document.Draw
|
||||||
|
@ -77,6 +79,7 @@ data UIElements
|
||||||
, fileBar :: !FileBar
|
, fileBar :: !FileBar
|
||||||
, viewportDrawingArea :: !GTK.DrawingArea
|
, viewportDrawingArea :: !GTK.DrawingArea
|
||||||
, infoBar :: !InfoBar
|
, infoBar :: !InfoBar
|
||||||
|
, colours :: !Colours
|
||||||
}
|
}
|
||||||
|
|
||||||
data Variables
|
data Variables
|
||||||
|
|
|
@ -24,6 +24,10 @@ import Data.Traversable
|
||||||
import qualified Data.Map.Strict as Map
|
import qualified Data.Map.Strict as Map
|
||||||
( lookup, insert, delete )
|
( lookup, insert, delete )
|
||||||
|
|
||||||
|
-- gi-cairo-connector
|
||||||
|
import qualified GI.Cairo.Render.Connector as Cairo
|
||||||
|
( renderWithContext )
|
||||||
|
|
||||||
-- gi-gtk
|
-- gi-gtk
|
||||||
import qualified GI.Gtk as GTK
|
import qualified GI.Gtk as GTK
|
||||||
|
|
||||||
|
@ -36,6 +40,10 @@ import qualified Control.Concurrent.STM.TVar as STM
|
||||||
-- MetaBrush
|
-- MetaBrush
|
||||||
import MetaBrush.Action
|
import MetaBrush.Action
|
||||||
( SwitchTo(..), Close(..), handleAction )
|
( SwitchTo(..), Close(..), handleAction )
|
||||||
|
import MetaBrush.Asset.CloseTabButton
|
||||||
|
( drawCloseTabButton )
|
||||||
|
import MetaBrush.Asset.Colours
|
||||||
|
( Colours )
|
||||||
import MetaBrush.Context
|
import MetaBrush.Context
|
||||||
( UIElements(..), Variables(..)
|
( UIElements(..), Variables(..)
|
||||||
, updateTitle
|
, updateTitle
|
||||||
|
@ -66,14 +74,14 @@ data TabLocation
|
||||||
deriving stock Show
|
deriving stock Show
|
||||||
|
|
||||||
newFileTab
|
newFileTab
|
||||||
:: Variables
|
:: UIElements
|
||||||
-> UIElements
|
-> Variables
|
||||||
-> Maybe Document
|
-> Maybe Document
|
||||||
-> TabLocation
|
-> TabLocation
|
||||||
-> IO ()
|
-> IO ()
|
||||||
newFileTab
|
newFileTab
|
||||||
vars@( Variables { .. } )
|
|
||||||
uiElts@( UIElements { fileBar = FileBar {..}, .. } )
|
uiElts@( UIElements { fileBar = FileBar {..}, .. } )
|
||||||
|
vars@( Variables { .. } )
|
||||||
mbDoc
|
mbDoc
|
||||||
newTabLoc
|
newTabLoc
|
||||||
= do
|
= do
|
||||||
|
@ -87,10 +95,24 @@ newFileTab
|
||||||
newDocUniq <- STM.atomically $ freshUnique uniqueSupply
|
newDocUniq <- STM.atomically $ freshUnique uniqueSupply
|
||||||
pure ( emptyDocument ( "Untitled " <> uniqueText newDocUniq ) newDocUniq )
|
pure ( emptyDocument ( "Untitled " <> uniqueText newDocUniq ) newDocUniq )
|
||||||
|
|
||||||
|
let
|
||||||
|
newUnique :: Unique
|
||||||
|
newUnique = documentUnique newDoc
|
||||||
|
|
||||||
-- File tab elements.
|
-- File tab elements.
|
||||||
pgButton <- GTK.radioButtonNewWithLabelFromWidget ( Just fileBarPhantomRadioButton ) ( displayName newDoc )
|
pgButton <- GTK.radioButtonNewWithLabelFromWidget ( Just fileBarPhantomRadioButton ) ( displayName newDoc )
|
||||||
GTK.toggleButtonSetMode pgButton False -- don't display radio indicator
|
GTK.toggleButtonSetMode pgButton False -- don't display radio indicator
|
||||||
closeFileButton <- GTK.buttonNewWithLabel "x"
|
closeFileButton <- GTK.buttonNew
|
||||||
|
closeFileArea <- GTK.drawingAreaNew
|
||||||
|
GTK.containerAdd closeFileButton closeFileArea
|
||||||
|
|
||||||
|
void $ GTK.onWidgetDraw closeFileArea \ cairoContext -> do
|
||||||
|
mbTabDoc <- Map.lookup newUnique <$> STM.readTVarIO openDocumentsTVar
|
||||||
|
let
|
||||||
|
unsaved :: Bool
|
||||||
|
unsaved = maybe False unsavedChanges mbTabDoc
|
||||||
|
flags <- GTK.widgetGetStateFlags closeFileButton
|
||||||
|
Cairo.renderWithContext ( drawCloseTabButton colours unsaved flags ) cairoContext
|
||||||
|
|
||||||
-- Create box for file tab elements.
|
-- Create box for file tab elements.
|
||||||
tab <- GTK.boxNew GTK.OrientationHorizontal 0
|
tab <- GTK.boxNew GTK.OrientationHorizontal 0
|
||||||
|
@ -131,9 +153,6 @@ newFileTab
|
||||||
pure False
|
pure False
|
||||||
|
|
||||||
-- Update the state: switch to this new document.
|
-- Update the state: switch to this new document.
|
||||||
let
|
|
||||||
newUnique :: Unique
|
|
||||||
newUnique = documentUnique newDoc
|
|
||||||
STM.atomically do
|
STM.atomically do
|
||||||
STM.modifyTVar' openDocumentsTVar ( Map.insert newUnique newDoc )
|
STM.modifyTVar' openDocumentsTVar ( Map.insert newUnique newDoc )
|
||||||
STM.modifyTVar' fileBarTabsTVar ( Map.insert newUnique tab )
|
STM.modifyTVar' fileBarTabsTVar ( Map.insert newUnique tab )
|
||||||
|
@ -151,13 +170,11 @@ newFileTab
|
||||||
( SwitchTo newUnique )
|
( SwitchTo newUnique )
|
||||||
else do
|
else do
|
||||||
GTK.widgetSetStateFlags tab ( filter ( /= GTK.StateFlagsActive ) flags ) True
|
GTK.widgetSetStateFlags tab ( filter ( /= GTK.StateFlagsActive ) flags ) True
|
||||||
GTK.labelSetText title "MetaBrush"
|
GTK.widgetQueueDraw closeFileArea
|
||||||
GTK.setWindowTitle window "MetaBrush"
|
|
||||||
|
|
||||||
void $ GTK.onButtonClicked closeFileButton
|
void $ GTK.onButtonClicked closeFileButton do
|
||||||
( handleAction uiElts vars
|
GTK.widgetQueueDraw closeFileArea
|
||||||
( CloseThis newUnique )
|
handleAction uiElts vars ( CloseThis newUnique )
|
||||||
)
|
|
||||||
|
|
||||||
GTK.toggleButtonSetActive pgButton True
|
GTK.toggleButtonSetActive pgButton True
|
||||||
|
|
||||||
|
@ -165,10 +182,11 @@ newFileTab
|
||||||
--
|
--
|
||||||
-- Updates the active document when buttons are clicked.
|
-- Updates the active document when buttons are clicked.
|
||||||
createFileBar
|
createFileBar
|
||||||
:: Variables
|
:: Colours -> Variables
|
||||||
-> GTK.Window -> GTK.Box -> GTK.Label -> GTK.DrawingArea -> InfoBar
|
-> GTK.Window -> GTK.Box -> GTK.Label -> GTK.DrawingArea -> InfoBar
|
||||||
-> IO FileBar
|
-> IO FileBar
|
||||||
createFileBar
|
createFileBar
|
||||||
|
colours
|
||||||
vars@( Variables { openDocumentsTVar } )
|
vars@( Variables { openDocumentsTVar } )
|
||||||
window titleBar title viewportDrawingArea infoBar
|
window titleBar title viewportDrawingArea infoBar
|
||||||
= do
|
= do
|
||||||
|
@ -184,8 +202,8 @@ createFileBar
|
||||||
newFileButton <- GTK.buttonNewWithLabel "+"
|
newFileButton <- GTK.buttonNewWithLabel "+"
|
||||||
widgetAddClasses newFileButton [ "newFileButton" ]
|
widgetAddClasses newFileButton [ "newFileButton" ]
|
||||||
|
|
||||||
GTK.boxPackStart fileBarBox fileTabsScroll True True 0
|
GTK.boxPackEnd fileBarBox newFileButton False False 0
|
||||||
GTK.boxPackStart fileBarBox newFileButton False False 0
|
GTK.boxPackStart fileBarBox fileTabsScroll True True 0
|
||||||
|
|
||||||
fileTabsBox <- GTK.boxNew GTK.OrientationHorizontal 0
|
fileTabsBox <- GTK.boxNew GTK.OrientationHorizontal 0
|
||||||
GTK.containerAdd fileTabsScroll fileTabsBox
|
GTK.containerAdd fileTabsScroll fileTabsBox
|
||||||
|
@ -203,15 +221,13 @@ createFileBar
|
||||||
documents <- STM.readTVarIO openDocumentsTVar
|
documents <- STM.readTVarIO openDocumentsTVar
|
||||||
for_ documents \ doc ->
|
for_ documents \ doc ->
|
||||||
newFileTab
|
newFileTab
|
||||||
vars
|
uiElements vars
|
||||||
uiElements
|
|
||||||
( Just doc )
|
( Just doc )
|
||||||
LastTab
|
LastTab
|
||||||
|
|
||||||
void $ GTK.onButtonClicked newFileButton do
|
void $ GTK.onButtonClicked newFileButton do
|
||||||
newFileTab
|
newFileTab
|
||||||
vars
|
uiElements vars
|
||||||
uiElements
|
|
||||||
Nothing
|
Nothing
|
||||||
LastTab
|
LastTab
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,8 @@ module MetaBrush.UI.FileBar
|
||||||
import qualified GI.Gtk as GTK
|
import qualified GI.Gtk as GTK
|
||||||
|
|
||||||
-- MetaBrush
|
-- MetaBrush
|
||||||
|
import MetaBrush.Asset.Colours
|
||||||
|
( Colours )
|
||||||
import {-# SOURCE #-} MetaBrush.Context
|
import {-# SOURCE #-} MetaBrush.Context
|
||||||
( Variables, UIElements )
|
( Variables, UIElements )
|
||||||
import MetaBrush.Document
|
import MetaBrush.Document
|
||||||
|
@ -34,10 +36,16 @@ data TabLocation
|
||||||
instance Show TabLocation
|
instance Show TabLocation
|
||||||
|
|
||||||
createFileBar
|
createFileBar
|
||||||
:: Variables
|
:: Colours -> Variables
|
||||||
-> GTK.Window -> GTK.Box -> GTK.Label -> GTK.DrawingArea -> InfoBar
|
-> GTK.Window -> GTK.Box -> GTK.Label -> GTK.DrawingArea -> InfoBar
|
||||||
-> IO FileBar
|
-> IO FileBar
|
||||||
|
|
||||||
newFileTab :: Variables -> UIElements -> Maybe Document -> TabLocation -> IO ()
|
newFileTab
|
||||||
|
:: UIElements -> Variables
|
||||||
|
-> Maybe Document -> TabLocation
|
||||||
|
-> IO ()
|
||||||
|
|
||||||
removeFileTab :: GTK.Window -> GTK.Label -> GTK.DrawingArea -> InfoBar -> Variables -> Unique -> IO ()
|
removeFileTab
|
||||||
|
:: GTK.Window -> GTK.Label -> GTK.DrawingArea -> InfoBar -> Variables
|
||||||
|
-> Unique
|
||||||
|
-> IO ()
|
||||||
|
|
Loading…
Reference in a new issue