mirror of
https://gitlab.com/sheaf/metabrush.git
synced 2024-11-05 23:03:38 +00:00
closing documents / removing file tabs
This commit is contained in:
parent
5f3bbc891a
commit
341a8ed0ca
|
@ -146,6 +146,8 @@ executable MetaBrush
|
||||||
>= 2.0.27 && < 2.1
|
>= 2.0.27 && < 2.1
|
||||||
, gi-glib
|
, gi-glib
|
||||||
>= 2.0.23 && < 2.1
|
>= 2.0.23 && < 2.1
|
||||||
|
, gi-gobject
|
||||||
|
^>= 2.0.24
|
||||||
, gi-gtk
|
, gi-gtk
|
||||||
>= 3.0.35 && < 3.1
|
>= 3.0.35 && < 3.1
|
||||||
, gi-cairo-render
|
, gi-cairo-render
|
||||||
|
|
|
@ -124,7 +124,7 @@ testDocuments = uniqueMapFromList
|
||||||
, Document
|
, Document
|
||||||
{ displayName = "Line"
|
{ displayName = "Line"
|
||||||
, mbFilePath = Nothing
|
, mbFilePath = Nothing
|
||||||
, unsavedChanges = True
|
, unsavedChanges = False
|
||||||
, viewportCenter = Point2D 0 0
|
, viewportCenter = Point2D 0 0
|
||||||
, zoomFactor = 1
|
, zoomFactor = 1
|
||||||
, documentUnique = unsafeUnique 1
|
, documentUnique = unsafeUnique 1
|
||||||
|
|
|
@ -95,7 +95,7 @@ tooltip {
|
||||||
border: 1px solid rgb(28,25,25);
|
border: 1px solid rgb(28,25,25);
|
||||||
}
|
}
|
||||||
|
|
||||||
.window {
|
.window, .dialog {
|
||||||
-GtkWidget-window-dragging: true;
|
-GtkWidget-window-dragging: true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,6 +179,30 @@ tooltip {
|
||||||
border-top: 2px solid rgb(41, 40, 40);
|
border-top: 2px solid rgb(41, 40, 40);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dialog {
|
||||||
|
border: 1px solid black;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialogButton {
|
||||||
|
background-color: rgb(72,70,61);
|
||||||
|
border: 1px solid black;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin: 6px;
|
||||||
|
padding: 2px 10px 2px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialogButton:hover {
|
||||||
|
border-color:rgb(212, 190, 152);
|
||||||
|
}
|
||||||
|
|
||||||
|
.dialogButton:active, .dialogButton:checked {
|
||||||
|
color: rgb(72,70,61);
|
||||||
|
border-color: black;
|
||||||
|
background-color: #eadfcc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.menuBar {
|
.menuBar {
|
||||||
padding-left: 4px;
|
padding-left: 4px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
{-# LANGUAGE MultiParamTypeClasses #-}
|
{-# LANGUAGE MultiParamTypeClasses #-}
|
||||||
{-# LANGUAGE NamedFieldPuns #-}
|
{-# LANGUAGE NamedFieldPuns #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE PatternSynonyms #-}
|
||||||
{-# LANGUAGE RecordWildCards #-}
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
{-# LANGUAGE TypeApplications #-}
|
{-# LANGUAGE TypeApplications #-}
|
||||||
{-# LANGUAGE UndecidableInstances #-}
|
{-# LANGUAGE UndecidableInstances #-}
|
||||||
|
@ -18,6 +19,8 @@ import Control.Monad
|
||||||
( guard, when, unless, void )
|
( guard, when, unless, void )
|
||||||
import Data.Foldable
|
import Data.Foldable
|
||||||
( for_ )
|
( for_ )
|
||||||
|
import Data.Int
|
||||||
|
( Int32 )
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
( catMaybes, listToMaybe )
|
( catMaybes, listToMaybe )
|
||||||
import Data.Word
|
import Data.Word
|
||||||
|
@ -33,7 +36,7 @@ import Data.Act
|
||||||
|
|
||||||
-- containers
|
-- containers
|
||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
( insert )
|
( lookup, insert, delete )
|
||||||
import Data.Sequence
|
import Data.Sequence
|
||||||
( Seq(..) )
|
( Seq(..) )
|
||||||
import qualified Data.Sequence as Seq
|
import qualified Data.Sequence as Seq
|
||||||
|
@ -93,10 +96,14 @@ import MetaBrush.UI.Coordinates
|
||||||
( toViewportCoordinates )
|
( toViewportCoordinates )
|
||||||
import MetaBrush.UI.InfoBar
|
import MetaBrush.UI.InfoBar
|
||||||
( updateInfoBar )
|
( updateInfoBar )
|
||||||
import MetaBrush.UI.FileBar
|
import {-# SOURCE #-} MetaBrush.UI.FileBar
|
||||||
( TabLocation(..), newFileTab )
|
( TabLocation(..), newFileTab, removeFileTab )
|
||||||
import MetaBrush.UI.ToolBar
|
import MetaBrush.UI.ToolBar
|
||||||
( Tool(..) )
|
( Tool(..) )
|
||||||
|
import MetaBrush.Unique
|
||||||
|
( Unique )
|
||||||
|
import MetaBrush.Util
|
||||||
|
( widgetAddClass, widgetAddClasses )
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -193,7 +200,7 @@ instance HandleAction Save where
|
||||||
Nothing -> pure () -- could show a warning message
|
Nothing -> pure () -- could show a warning message
|
||||||
Just doc@( Document { mbFilePath, unsavedChanges } )
|
Just doc@( Document { mbFilePath, unsavedChanges } )
|
||||||
| Nothing <- mbFilePath
|
| Nothing <- mbFilePath
|
||||||
-> saveAs uiElts vars doc
|
-> saveAs uiElts vars True doc
|
||||||
| False <- unsavedChanges
|
| False <- unsavedChanges
|
||||||
-> pure ()
|
-> pure ()
|
||||||
| Just filePath <- mbFilePath
|
| Just filePath <- mbFilePath
|
||||||
|
@ -217,10 +224,10 @@ instance HandleAction SaveAs where
|
||||||
mbDoc <- STM.atomically $ currentDocument vars
|
mbDoc <- STM.atomically $ currentDocument vars
|
||||||
case mbDoc of
|
case mbDoc of
|
||||||
Nothing -> pure () -- could show a warning message
|
Nothing -> pure () -- could show a warning message
|
||||||
Just doc -> saveAs uiElts vars doc
|
Just doc -> saveAs uiElts vars True doc
|
||||||
|
|
||||||
saveAs :: UIElements -> Variables -> Document -> IO ()
|
saveAs :: UIElements -> Variables -> Bool -> Document -> IO ()
|
||||||
saveAs ( UIElements { window } ) ( Variables { openDocumentsTVar } ) doc = do
|
saveAs ( UIElements { window, fileBar } ) vars@( Variables { openDocumentsTVar } ) keepOpen doc = do
|
||||||
fileChooser <-
|
fileChooser <-
|
||||||
GTK.fileChooserNativeNew ( Just "Save MetaBrush document..." ) ( Just window )
|
GTK.fileChooserNativeNew ( Just "Save MetaBrush document..." ) ( Just window )
|
||||||
GTK.FileChooserActionSave
|
GTK.FileChooserActionSave
|
||||||
|
@ -244,22 +251,68 @@ saveAs ( UIElements { window } ) ( Variables { openDocumentsTVar } ) doc = do
|
||||||
| otherwise
|
| otherwise
|
||||||
= filePath <.> "mb"
|
= filePath <.> "mb"
|
||||||
saveDocument fullFilePath doc
|
saveDocument fullFilePath doc
|
||||||
|
if keepOpen
|
||||||
|
then
|
||||||
STM.atomically $
|
STM.atomically $
|
||||||
STM.modifyTVar' openDocumentsTVar
|
STM.modifyTVar' openDocumentsTVar
|
||||||
( Map.insert ( documentUnique doc )
|
( Map.insert ( documentUnique doc )
|
||||||
( doc { mbFilePath = Just fullFilePath, unsavedChanges = False } )
|
( doc { mbFilePath = Just fullFilePath, unsavedChanges = False } )
|
||||||
)
|
)
|
||||||
|
else removeFileTab fileBar vars ( documentUnique doc )
|
||||||
|
|
||||||
-----------
|
-----------
|
||||||
-- Close --
|
-- Close --
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
data Close = Close
|
data Close
|
||||||
deriving stock Show
|
= CloseActive -- ^ Close active document.
|
||||||
|
| CloseThis -- ^ Close a specific tab (action to destroy tab is directly given).
|
||||||
|
{ docToClose :: Unique
|
||||||
|
, destroyTabAction :: IO ()
|
||||||
|
}
|
||||||
|
|
||||||
|
instance Show Close where
|
||||||
|
show CloseActive = "CloseActive"
|
||||||
|
show ( CloseThis docToClose _ ) = "CloseThis " <> show docToClose
|
||||||
|
|
||||||
|
pattern JustClose, SaveAndClose, CancelClose :: Int32
|
||||||
|
pattern JustClose = 1
|
||||||
|
pattern SaveAndClose = 2
|
||||||
|
pattern CancelClose = 3
|
||||||
|
|
||||||
-- TODO
|
|
||||||
instance HandleAction Close where
|
instance HandleAction Close where
|
||||||
handleAction _ _ _ = pure ()
|
handleAction uiElts@( UIElements { window, fileBar } ) vars@( Variables { .. } ) close = do
|
||||||
|
mbDoc <- case close of
|
||||||
|
CloseActive -> STM.atomically $ currentDocument vars
|
||||||
|
CloseThis unique _ -> Map.lookup unique <$> STM.readTVarIO openDocumentsTVar
|
||||||
|
case mbDoc of
|
||||||
|
Nothing -> pure () -- could show a warning message
|
||||||
|
Just doc@( Document { displayName, documentUnique } ) -> do
|
||||||
|
dialog <- GTK.new GTK.MessageDialog []
|
||||||
|
GTK.setMessageDialogText dialog ( " \n\"" <> displayName <> "\" contains unsaved changes.\nClose anyway?" )
|
||||||
|
GTK.setMessageDialogMessageType dialog GTK.MessageTypeQuestion
|
||||||
|
GTK.setWindowResizable dialog False
|
||||||
|
GTK.setWindowDecorated dialog False
|
||||||
|
GTK.widgetAddEvents dialog
|
||||||
|
[ GDK.EventMaskKeyPressMask, GDK.EventMaskKeyReleaseMask ]
|
||||||
|
GTK.windowSetTransientFor dialog ( Just window )
|
||||||
|
GTK.windowSetModal dialog True
|
||||||
|
widgetAddClasses dialog [ "bg", "plain", "text", "dialog" ]
|
||||||
|
closeButton <- GTK.dialogAddButton dialog "Close" JustClose
|
||||||
|
saveButton <- GTK.dialogAddButton dialog "Save and close" SaveAndClose
|
||||||
|
cancelButton <- GTK.dialogAddButton dialog "Cancel" CancelClose
|
||||||
|
GTK.dialogSetDefaultResponse dialog 1
|
||||||
|
for_ [ closeButton, saveButton, cancelButton ] \ button -> widgetAddClass button "dialogButton"
|
||||||
|
choice <- GTK.dialogRun dialog
|
||||||
|
GTK.widgetDestroy dialog
|
||||||
|
case choice of
|
||||||
|
JustClose -> case close of
|
||||||
|
CloseActive -> removeFileTab fileBar vars documentUnique
|
||||||
|
CloseThis _ destroyTab -> do
|
||||||
|
destroyTab
|
||||||
|
STM.atomically $ STM.modifyTVar' openDocumentsTVar ( Map.delete documentUnique )
|
||||||
|
SaveAndClose -> saveAs uiElts vars False doc
|
||||||
|
_ -> pure ()
|
||||||
|
|
||||||
--------------
|
--------------
|
||||||
-- Quitting --
|
-- Quitting --
|
||||||
|
|
|
@ -91,7 +91,7 @@ getOrCreateDrawAnchor uniqueSupply c doc@( Document { zoomFactor } ) =
|
||||||
}
|
}
|
||||||
: )
|
: )
|
||||||
newDoc
|
newDoc
|
||||||
pure ( newDoc', AnchorAtEnd uniq, c )
|
pure ( newDoc' { unsavedChanges = True }, AnchorAtEnd uniq, c )
|
||||||
where
|
where
|
||||||
-- Deselect all points, and try to find a valid anchor for drawing
|
-- Deselect all points, and try to find a valid anchor for drawing
|
||||||
-- (a path start/end point at mouse click point).
|
-- (a path start/end point at mouse click point).
|
||||||
|
@ -128,7 +128,7 @@ getOrCreateDrawAnchor uniqueSupply c doc@( Document { zoomFactor } ) =
|
||||||
squaredNorm ( c --> p :: Vector2D Double ) < 16 / ( zoomFactor * zoomFactor )
|
squaredNorm ( c --> p :: Vector2D Double ) < 16 / ( zoomFactor * zoomFactor )
|
||||||
|
|
||||||
addToAnchor :: DrawAnchor -> Seq ( StrokePoint PointData ) -> Document -> Document
|
addToAnchor :: DrawAnchor -> Seq ( StrokePoint PointData ) -> Document -> Document
|
||||||
addToAnchor anchor newPts = over ( field' @"strokes" . mapped ) addToStroke
|
addToAnchor anchor newPts = set ( field' @"unsavedChanges" ) True . over ( field' @"strokes" . mapped ) addToStroke
|
||||||
where
|
where
|
||||||
addToStroke :: Stroke -> Stroke
|
addToStroke :: Stroke -> Stroke
|
||||||
addToStroke stroke@( Stroke { strokeUnique, strokePoints = pts } )
|
addToStroke stroke@( Stroke { strokeUnique, strokePoints = pts } )
|
||||||
|
|
|
@ -271,9 +271,11 @@ translateSelection mode t
|
||||||
| Brush <- mode
|
| Brush <- mode
|
||||||
= over ( field' @"strokes" . mapped . field' @"strokePoints" . mapped . field' @"pointData" . field' @"brushShape" . mapped )
|
= over ( field' @"strokes" . mapped . field' @"strokePoints" . mapped . field' @"pointData" . field' @"brushShape" . mapped )
|
||||||
updateStrokePoint
|
updateStrokePoint
|
||||||
|
. set ( field' @"unsavedChanges" ) True
|
||||||
| otherwise
|
| otherwise
|
||||||
= over ( field' @"strokes" . mapped . field' @"strokePoints" . mapped )
|
= over ( field' @"strokes" . mapped . field' @"strokePoints" . mapped )
|
||||||
updateStrokePoint
|
updateStrokePoint
|
||||||
|
. set ( field' @"unsavedChanges" ) True
|
||||||
where
|
where
|
||||||
updateStrokePoint :: HasType FocusState pt => StrokePoint pt -> StrokePoint pt
|
updateStrokePoint :: HasType FocusState pt => StrokePoint pt -> StrokePoint pt
|
||||||
updateStrokePoint pt
|
updateStrokePoint pt
|
||||||
|
@ -288,12 +290,14 @@ deleteSelected mode doc = fst . runIdentity . ( `Tardis.runTardisT` ( False, Fal
|
||||||
Brush ->
|
Brush ->
|
||||||
( field' @"strokes" . traverse . field' @"strokePoints" . traverse . field' @"pointData" . field' @"brushShape" )
|
( field' @"strokes" . traverse . field' @"strokePoints" . traverse . field' @"pointData" . field' @"brushShape" )
|
||||||
updateStroke
|
updateStroke
|
||||||
doc
|
doc'
|
||||||
_ ->
|
_ ->
|
||||||
( field' @"strokes" . traverse . field' @"strokePoints" )
|
( field' @"strokes" . traverse . field' @"strokePoints" )
|
||||||
updateStroke
|
updateStroke
|
||||||
doc
|
doc'
|
||||||
where
|
where
|
||||||
|
doc' :: Document
|
||||||
|
doc' = doc { unsavedChanges = True }
|
||||||
updateStroke
|
updateStroke
|
||||||
:: forall pt
|
:: forall pt
|
||||||
. HasType FocusState pt
|
. HasType FocusState pt
|
||||||
|
|
|
@ -136,6 +136,7 @@ renderDocument
|
||||||
modifiedStrokes
|
modifiedStrokes
|
||||||
| Just ( DragMoveHold p0 ) <- mbHoldEvent
|
| Just ( DragMoveHold p0 ) <- mbHoldEvent
|
||||||
, Just p1 <- mbMousePos
|
, Just p1 <- mbMousePos
|
||||||
|
, p0 /= p1
|
||||||
= strokes $ translateSelection mode ( p0 --> p1 ) doc
|
= strokes $ translateSelection mode ( p0 --> p1 ) doc
|
||||||
| Just ( PartialPath p0 cp0 _ _ ) <- mbPartialPath
|
| Just ( PartialPath p0 cp0 _ _ ) <- mbPartialPath
|
||||||
, let
|
, let
|
||||||
|
|
|
@ -6,22 +6,32 @@
|
||||||
{-# LANGUAGE TypeApplications #-}
|
{-# LANGUAGE TypeApplications #-}
|
||||||
|
|
||||||
module MetaBrush.UI.FileBar
|
module MetaBrush.UI.FileBar
|
||||||
( FileBar(..), createFileBar, newFileTab
|
( FileBar(..)
|
||||||
|
, createFileBar, newFileTab, removeFileTab
|
||||||
, TabLocation(..)
|
, TabLocation(..)
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
|
||||||
-- base
|
-- base
|
||||||
import Control.Monad
|
import Control.Monad
|
||||||
( void )
|
( unless, void, when )
|
||||||
import Data.Maybe
|
import Data.Maybe
|
||||||
( listToMaybe )
|
( listToMaybe )
|
||||||
import Data.Foldable
|
import Data.Foldable
|
||||||
( for_ )
|
( for_ )
|
||||||
|
import qualified Foreign.Marshal.Alloc as Foreign
|
||||||
|
( malloc, free )
|
||||||
|
import qualified Foreign.Ptr as Foreign
|
||||||
|
( castPtr, nullPtr )
|
||||||
|
import qualified Foreign.Storable as Foreign
|
||||||
|
( peek, poke )
|
||||||
|
|
||||||
-- containers
|
-- containers
|
||||||
import qualified Data.Map.Strict as Map
|
import qualified Data.Map.Strict as Map
|
||||||
( lookup, insert )
|
( lookup, insert, delete )
|
||||||
|
|
||||||
|
-- gi-gobject
|
||||||
|
import qualified GI.GObject as GObject
|
||||||
|
|
||||||
-- gi-gtk
|
-- gi-gtk
|
||||||
import qualified GI.Gtk as GTK
|
import qualified GI.Gtk as GTK
|
||||||
|
@ -37,6 +47,8 @@ import Data.Text
|
||||||
( Text )
|
( Text )
|
||||||
|
|
||||||
-- MetaBrush
|
-- MetaBrush
|
||||||
|
import MetaBrush.Action
|
||||||
|
( Close(..), handleAction )
|
||||||
import MetaBrush.Context
|
import MetaBrush.Context
|
||||||
( UIElements(..), Variables(..) )
|
( UIElements(..), Variables(..) )
|
||||||
import MetaBrush.Document
|
import MetaBrush.Document
|
||||||
|
@ -72,7 +84,7 @@ newFileTab
|
||||||
-> IO ()
|
-> IO ()
|
||||||
newFileTab
|
newFileTab
|
||||||
vars@( Variables { uniqueSupply, activeDocumentTVar, openDocumentsTVar } )
|
vars@( Variables { uniqueSupply, activeDocumentTVar, openDocumentsTVar } )
|
||||||
( UIElements { fileBar = FileBar {..}, .. } )
|
uiElts@( UIElements { fileBar = FileBar {..}, .. } )
|
||||||
mbDoc
|
mbDoc
|
||||||
newTabLoc
|
newTabLoc
|
||||||
= do
|
= do
|
||||||
|
@ -99,9 +111,18 @@ newFileTab
|
||||||
GTK.boxPackStart tab closeFileButton False False 0
|
GTK.boxPackStart tab closeFileButton False False 0
|
||||||
widgetAddClasses pgButton [ "fileBarTabButton" ]
|
widgetAddClasses pgButton [ "fileBarTabButton" ]
|
||||||
widgetAddClasses closeFileButton [ "fileBarCloseButton" ]
|
widgetAddClasses closeFileButton [ "fileBarCloseButton" ]
|
||||||
|
|
||||||
GTK.widgetShowAll tab
|
GTK.widgetShowAll tab
|
||||||
|
|
||||||
|
-- Associate each tab with the corresponding document unique,
|
||||||
|
-- so we can know which document corresponds to each file tab
|
||||||
|
-- by only looking at the tab.
|
||||||
|
let
|
||||||
|
newUnique :: Unique
|
||||||
|
newUnique = documentUnique newDoc
|
||||||
|
uniquePtr <- Foreign.malloc @Unique
|
||||||
|
Foreign.poke uniquePtr newUnique
|
||||||
|
GObject.objectSetData tab "unique" ( Foreign.castPtr @Unique @() uniquePtr )
|
||||||
|
|
||||||
-- We've placed the new tab at the end. Now rearrange it if needed.
|
-- We've placed the new tab at the end. Now rearrange it if needed.
|
||||||
case newTabLoc of
|
case newTabLoc of
|
||||||
LastTab -> pure ()
|
LastTab -> pure ()
|
||||||
|
@ -134,9 +155,7 @@ 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.writeTVar activeDocumentTVar ( Just newUnique )
|
STM.writeTVar activeDocumentTVar ( Just newUnique )
|
||||||
|
@ -171,14 +190,14 @@ newFileTab
|
||||||
GTK.labelSetText title "MetaBrush"
|
GTK.labelSetText title "MetaBrush"
|
||||||
GTK.setWindowTitle window "MetaBrush"
|
GTK.setWindowTitle window "MetaBrush"
|
||||||
|
|
||||||
--void $ GTK.onButtonClicked closeFileButton
|
void $ GTK.onButtonClicked closeFileButton
|
||||||
-- ( STM.atomically $ signalAction actionTQueue Close )
|
( handleAction uiElts vars
|
||||||
|
( CloseThis newUnique ( Foreign.free uniquePtr *> GTK.widgetDestroy tab ) )
|
||||||
--void $ GTK.onButtonClicked closeFileButton ... ... ...
|
)
|
||||||
|
|
||||||
GTK.toggleButtonSetActive pgButton True
|
GTK.toggleButtonSetActive pgButton True
|
||||||
|
|
||||||
-- | Add the file bar: tabs allowing selection of the active document.
|
-- | Create a file bar: tabs allowing selection of the active document.
|
||||||
--
|
--
|
||||||
-- Updates the active document when buttons are clicked.
|
-- Updates the active document when buttons are clicked.
|
||||||
createFileBar
|
createFileBar
|
||||||
|
@ -233,3 +252,17 @@ createFileBar
|
||||||
LastTab
|
LastTab
|
||||||
|
|
||||||
pure fileBar
|
pure fileBar
|
||||||
|
|
||||||
|
-- | Close a document: remove the corresponding file tab from the file bar.
|
||||||
|
removeFileTab :: FileBar -> Variables -> Unique -> IO ()
|
||||||
|
removeFileTab ( FileBar { fileTabsBox } ) ( Variables { openDocumentsTVar } ) docUnique = do
|
||||||
|
GTK.containerForeach fileTabsBox \ tab -> do
|
||||||
|
|
||||||
|
uniquePtr <- Foreign.castPtr @() @Unique <$> GObject.objectGetData tab "unique"
|
||||||
|
unless ( uniquePtr == Foreign.nullPtr ) do
|
||||||
|
tabUnique <- Foreign.peek uniquePtr
|
||||||
|
when ( docUnique == tabUnique ) do
|
||||||
|
Foreign.free uniquePtr
|
||||||
|
GTK.widgetDestroy tab
|
||||||
|
|
||||||
|
STM.atomically $ STM.modifyTVar' openDocumentsTVar ( Map.delete docUnique )
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
module MetaBrush.UI.FileBar
|
module MetaBrush.UI.FileBar
|
||||||
( FileBar(..), createFileBar, newFileTab
|
( FileBar(..)
|
||||||
|
, createFileBar, newFileTab, removeFileTab
|
||||||
, TabLocation(..)
|
, TabLocation(..)
|
||||||
)
|
)
|
||||||
where
|
where
|
||||||
|
@ -14,6 +15,8 @@ import MetaBrush.Document
|
||||||
( Document )
|
( Document )
|
||||||
import {-# SOURCE #-} MetaBrush.UI.InfoBar
|
import {-# SOURCE #-} MetaBrush.UI.InfoBar
|
||||||
( InfoBar )
|
( InfoBar )
|
||||||
|
import MetaBrush.Unique
|
||||||
|
( Unique )
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@ -36,3 +39,5 @@ createFileBar
|
||||||
-> IO FileBar
|
-> IO FileBar
|
||||||
|
|
||||||
newFileTab :: Variables -> UIElements -> Maybe Document -> TabLocation -> IO ()
|
newFileTab :: Variables -> UIElements -> Maybe Document -> TabLocation -> IO ()
|
||||||
|
|
||||||
|
removeFileTab :: FileBar -> Variables -> Unique -> IO ()
|
||||||
|
|
|
@ -184,7 +184,7 @@ fileMenuDescription
|
||||||
, openFolder = MenuItemDescription "Open folder" [ "submenuItem" ] ( OpenFolder AfterCurrentTab ) ( Just ( GDK.KEY_O, [ Control L, Shift L ] ) ) NoSubresource
|
, openFolder = MenuItemDescription "Open folder" [ "submenuItem" ] ( OpenFolder AfterCurrentTab ) ( Just ( GDK.KEY_O, [ Control L, Shift L ] ) ) NoSubresource
|
||||||
, save = MenuItemDescription "Save" [ "submenuItem" ] Save ( Just ( GDK.KEY_S, [ Control L ] ) ) NoSubresource
|
, save = MenuItemDescription "Save" [ "submenuItem" ] Save ( Just ( GDK.KEY_S, [ Control L ] ) ) NoSubresource
|
||||||
, saveAs = MenuItemDescription "Save as" [ "submenuItem" ] SaveAs ( Just ( GDK.KEY_S, [ Control L, Shift L ] ) ) NoSubresource
|
, saveAs = MenuItemDescription "Save as" [ "submenuItem" ] SaveAs ( Just ( GDK.KEY_S, [ Control L, Shift L ] ) ) NoSubresource
|
||||||
, close = MenuItemDescription "Close" [ "submenuItem" ] Close ( Just ( GDK.KEY_W, [ Control L ] ) ) NoSubresource
|
, close = MenuItemDescription "Close" [ "submenuItem" ] CloseActive ( Just ( GDK.KEY_W, [ Control L ] ) ) NoSubresource
|
||||||
, quit = MenuItemDescription "Quit" [ "submenuItem" ] Quit ( Just ( GDK.KEY_Q, [ Control L ] ) ) NoSubresource
|
, quit = MenuItemDescription "Quit" [ "submenuItem" ] Quit ( Just ( GDK.KEY_Q, [ Control L ] ) ) NoSubresource
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue