add CSS for stroke popover menu

This commit is contained in:
sheaf 2024-10-17 18:54:15 +02:00
parent 60b65a38e1
commit bcd0b9fb13
6 changed files with 245 additions and 105 deletions

View file

@ -5,33 +5,33 @@
}
*/
.toggle, .dialogButton, .titlebar, .titleBar, .windowIcon, .fileBarCloseButton,
.newFileButton, .header, .paned, .panel, .tabs, .frame {
.metabrush .toggle, .metabrush .dialogButton, .metabrush .titlebar,
.metabrush .windowIcon, .metabrush .fileBarCloseButton,
.metabrush .newFileButton, .metabrush .header,
.metabrush .paned, .metabrush .panel, .metabrush .tabs, .metabrush .frame {
all: unset;
}
windowcontrols {
.metabrush windowcontrols {
all: unset;
}
.reorderable-page {
.metabrush .reorderable-page {
all: unset;
}
.menu * {
.metabrush .headerMenu * {
all: unset;
}
.frame > * {
.metabrush .frame > * {
all: unset;
}
.notebook {
.metabrush .notebook {
all: unset;
}
@import url("colours.css");
/* Colours parsed by application */
@ -100,24 +100,24 @@ windowcontrols {
.pointSelected {
color: @pointSelected;
}
.viewport {
.metabrush .viewport {
background-color: @base;
color: @base;
min-width: 120px;
min-height: 90px;
}
.viewportScrollbar {
.metabrush .viewportScrollbar {
background-color: @scrollbar;
color: @scrollbar;
margin: 4px;
min-width: 8px;
min-height: 8px;
}
.tabScrollbar {
.metabrush .tabScrollbar {
background-color: @scrollbar;
color: @scrollbar;
}
.ruler {
.metabrush .ruler {
background-color: @ruler;
color: @ruler;
min-width: 16px;
@ -159,7 +159,7 @@ tooltip {
}
.window, .dialog {
.metabrush .window, .metabrush .dialog {
border-radius: 0px;
border-color: @border;
box-shadow:
@ -172,54 +172,54 @@ tooltip {
/* Basic text colour */
/* Basic text font */
.text {
.metabrush .text {
font-family: "Lato", "Roboto", "Helvetica", sans-serif;
}
/* Monospace font */
.monospace {
.metabrush .monospace {
font-family: "Fira Code", "Inconsolata", "Courier", "Courier New", monospace;
}
/* High-constrast text colour */
.contrast {
.metabrush .contrast {
color: @contrast;
}
/* Active (highlighting) colour */
.highlight {
.metabrush .highlight {
color: @highlight;
}
/* Logo area */
.logo {
.metabrush .logo {
margin-left: 4px;
min-width: 28px;
}
/* Logo base colour */
.logo_base {
.metabrush .logo_base {
color: @highlight;
}
/* Logo highlight colour */
.logo_highlight {
.metabrush .logo_highlight {
color: @splash;
}
/* Rulers */
.leftRuler {
.metabrush .leftRuler {
border-right: 1px solid @rulerBorder;
min-width: 16px;
}
.topRuler {
.metabrush .topRuler {
border-bottom: 1px solid @rulerBorder;
min-height: 16px;
}
.rulerCorner {
.metabrush .rulerCorner {
min-width: 8px;
min-height: 8px;
border-bottom: 1px solid @rulerBorder;
@ -227,44 +227,44 @@ tooltip {
}
/* Cursor colour */
.cursor {
.metabrush .cursor {
color: @cursor;
}
/* Bézier path point colour */
.point {
.metabrush .point {
color: @pathPoint;
}
/* Bézier control point colour */
.control {
.metabrush .control {
color: @controlPoint;
}
/* Title bar */
.titleBar {
.metabrush .titleBar {
min-height: 24px;
font-size: 12px;
background-color: @bg;
}
/*
.titleBar > * :hover {
.metabrush .titleBar > * :hover {
background-color: rgb(72,70,61);
}
*/
.title {
.metabrush .title {
border-top: 2px solid @bg;
}
.dialog {
.metabrush .dialog {
border: 1px solid @border;
border-radius: 6px;
}
/* dialog button */
.dialogButton {
.metabrush .dialogButton {
background-color: @active;
border: 1px solid @border;
border-radius: 4px;
@ -272,11 +272,11 @@ tooltip {
padding: 2px 10px 2px 10px;
}
.dialogButton:hover {
.metabrush .dialogButton:hover {
border-color: @plain;
}
.dialogButton:active, .dialogButton:checked {
.metabrush .dialogButton:active, .metabrush .dialogButton:checked {
color: @active;
border-color: @border;
background-color: @highlight;
@ -284,31 +284,31 @@ tooltip {
/* Menu bar */
.menu label {
.metabrush .headerMenu label {
color:@plain;
}
.menu :disabled {
.metabrush .headerMenu :disabled {
color: @disabled;
}
.menu :focus-within {
.metabrush .headerMenu :focus-within {
border-color: @plain;
}
.menu :focus{
.metabrush .headerMenu :focus{
border-color: @active;
background-color: @bg;
}
.menu item {
.metabrush .headerMenu item {
padding-left: 8px;
padding-right: 8px;
color: @plain;
border-top: 2px solid @bg;
}
.menu item > * :hover {
.metabrush .headerMenu item > * :hover {
border-color: @plain;
background-color: @active;
}
@ -318,15 +318,15 @@ tooltip {
"The visible part of the popover can have a shadow.
To specify it in CSS, set the box-shadow of the contents node."
*/
.menu item > popover > contents {
.metabrush .headerMenu item > popover > contents {
box-shadow: 2px 3px 3px rgba(0,0,0,0.5)
, -2px 3px 3px rgba(0,0,0,0.5)
, 0px 4px 3px rgba(0,0,0,0.5);
}
/* Look at the CSS with the GTK inspector to figure this out... */
.menu item > popover > contents > scrolledwindow > viewport > stack > box > box > modelbutton,
.menu item > popover > contents > scrolledwindow > viewport > stack > box > box > box > box > modelbutton
.metabrush .headerMenu item > popover > contents > scrolledwindow > viewport > stack > box > box > modelbutton,
.metabrush .headerMenu item > popover > contents > scrolledwindow > viewport > stack > box > box > box > box > modelbutton
{
background-color: @bg;
color: @active;
@ -335,46 +335,95 @@ To specify it in CSS, set the box-shadow of the contents node."
padding: 6px 10px 6px 10px;
}
.menu item > popover > contents > scrolledwindow > viewport > stack > box > box > box > separator,
.menu item > popover > contents > scrolledwindow > viewport > stack > box > box > box > separator :hover {
.metabrush .headerMenu item > popover > contents > scrolledwindow > viewport > stack > box > box > box > separator,
.metabrush .headerMenu item > popover > contents > scrolledwindow > viewport > stack > box > box > box > separator :hover {
background-color: @active;
padding: 1px 0px 0px 1px;
}
.menu item > popover > contents > scrolledwindow > viewport > stack > box > box > modelbutton > accelerator,
.menu item > popover > contents > scrolledwindow > viewport > stack > box > box > box > box > modelbutton > accelerator {
.metabrush .headerMenu item > popover > contents > scrolledwindow > viewport > stack > box > box > modelbutton > accelerator,
.metabrush .headerMenu item > popover > contents > scrolledwindow > viewport > stack > box > box > box > box > modelbutton > accelerator {
font-size: 10px;
color: @shortcutKey;
padding-left: 10px;
}
.windowIcon {
.metabrush .listViewPane :selected {
background-color: unset;
font-weight: bold;
color: black;
}
/* Stroke popover menu */
/* TODO: refactor with menu */
.metabrush .strokeMenu > * {
background-color: @bg;
}
.metabrush .strokeMenu contents {
border: unset;
border-radius: 0px;
margin: 0px;
padding: 0px;
border: 1px solid black;
}
.metabrush .strokeMenu .flat {
border-left: 2px solid @bg;
border-top: 0px;
}
.metabrush .strokeMenu :selected {
color: @plain;
background-color: @active;
font-weight: normal;
border-left: 2px solid @plain;
border-radius: 0px;
}
.metabrush .strokeMenu separator {
background-color: @contrast;
margin: 0px;
}
.metabrush .strokeMenu .separator {
color: black;
background-color: @contrast;
font-weight: normal;
opacity: 1;
margin: 4px 10px 4px 10px;
padding: 0px 6px 0px 6px;
border: 0px solid black;
border-radius: 2px;
}
.metabrush .windowIcon {
min-width: 24px;
}
.windowIcon:hover {
.metabrush .windowIcon:hover {
background-color: @windowButtonHover;
}
.windowIcon:active, .windowIcon:checked {
.metabrush .windowIcon:active, .metabrush .windowIcon:checked {
background-color: @windowButtonActive;
}
.closeWindowIcon:hover {
.metabrush .closeWindowIcon:hover {
background-color: @closeButtonHover;
}
.closeWindowIcon:active, .closeWindowIcon:checked {
.metabrush .closeWindowIcon:active, .metabrush .closeWindowIcon:checked {
background-color: @closeButtonActive;
}
/* Tool bar */
.toolBar {
.metabrush .toolBar {
min-width: 32px;
margin-top: 28px;
}
.toolBarSeparator {
.metabrush .toolBarSeparator {
min-height: 2px;
margin-left: 10px;
margin-right: 10px;
@ -383,7 +432,7 @@ To specify it in CSS, set the box-shadow of the contents node."
background-color: @active;
}
.toolItem {
.metabrush .toolItem {
border-left: 2px solid @bg;
min-height: 40px;
min-width: 40px;
@ -393,42 +442,42 @@ To specify it in CSS, set the box-shadow of the contents node."
padding-right: 3px;
}
.toolItem:hover {
.metabrush .toolItem:hover {
border-color: @active;
}
.toolItem:active, .toolItem:checked {
.metabrush .toolItem:active, .metabrush .toolItem:checked {
border-color: @base;
background-color: @active;
}
/* File bar */
.fileBar {
.metabrush .fileBar {
min-height: 24px;
font-size: 12px;
margin-top: 2px;
}
.fileBarTab {
.metabrush .fileBarTab {
border-top: 2px solid @bg;
}
.fileBarTab:hover {
.metabrush .fileBarTab:hover {
border-color: @active;
}
.fileBarTab:active, .fileBarTab:checked {
.metabrush .fileBarTab:active, .metabrush .fileBarTab:checked {
border-color: @base;
background-color: @active;
}
.fileBarTabButton {
.metabrush .fileBarTabButton {
padding-left: 8px;
padding-right: 2px;
margin: 0px;
}
.fileBarCloseButton {
.metabrush .fileBarCloseButton {
min-width: 10px;
min-height: 22px;
padding-left: 1px;
@ -437,15 +486,15 @@ To specify it in CSS, set the box-shadow of the contents node."
color: @plain;
}
.fileBarCloseButton:hover {
.metabrush .fileBarCloseButton:hover {
color: @closeButtonHover;
}
.fileBarCloseButton:active, .fileBarCloseButton:checked {
.metabrush .fileBarCloseButton:active, .metabrush .fileBarCloseButton:checked {
color: @closeButtonActive;
}
.newFileButton {
.metabrush .newFileButton {
color: @newFileButton;
font-size: 16px;
font-weight: bold;
@ -455,55 +504,55 @@ To specify it in CSS, set the box-shadow of the contents node."
border-left: 1px solid @bg;
}
.newFileButton:hover, .newFileButton:active, newFileButton:checked {
.metabrush .newFileButton:hover, .metabrush .newFileButton:active, .metabrush newFileButton:checked {
color: @newFileButtonActive;
}
.newFileButton:active, .newFileButton:checked {
.metabrush .newFileButton:active, .metabrush .newFileButton:checked {
border-color: @newFileButtonActive;
}
/* Panels */
.panels {
.metabrush .panels {
min-width: 120px;
font-size: 12px;
}
.panels tab {
.metabrush .panels tab {
padding-left: 6px;
padding-right: 6px;
border-top: 2px solid @bg;
}
.panels tab:hover {
.metabrush .panels tab:hover {
border-color: @active;
}
.panels tab:active, .panels tab:checked {
.metabrush .panels tab:active, .metabrush .panels tab:checked {
background-color: @active;
border-color: rgb(234,223,204);
}
.panel {
.metabrush .panel {
background-color: @active;
min-height: 20px;
}
/* Info bar */
.infoBar {
.metabrush .infoBar {
min-height: 40px;
font-size: 10px;
}
.infoBarInfo {
.metabrush .infoBarInfo {
margin-left: -4px;
padding-right: 16px;
}
/* Stroke hierarchy layers */
row {
.metabrush row {
border-top: 0px;
border-bottom: 0px;
margin-top: -2px;
@ -511,18 +560,12 @@ row {
}
/* Slightly hacky way to align layers and groups */
indent {
.metabrush indent {
margin-left: 4px;
margin-right: 4px;
}
:selected {
background-color: rgba(255,255,255,0);
font-weight: bold;
color: black;
}
.layer-item, .brush-item {
.metabrush .layer-item, .metabrush .brush-item {
color: @plain;
background-color: @active;
border: 0px solid @bg;
@ -536,22 +579,22 @@ indent {
padding-left: 3px;
}
:selected .layer-item, :selected .brush-item {
.metabrush :selected .layer-item, .metabrush :selected .brush-item {
color: black;
background-color: @contrast;
border: 0px solid @contrast;
}
/* Add "drop here" areas when a drag has been initiated */
.dragging-item .layer-item {
.metabrush .dragging-item .layer-item {
}
/* Style when dragging over an item */
.drag-over.layer-item {
.metabrush .drag-over.layer-item {
}
/* Style when dragging layer item over the top part of an item */
.dragging-item .drag-top.layer-item {
.metabrush .dragging-item .drag-top.layer-item {
border-top: 2px solid @highlight;
margin-top: -2px;
box-shadow:
@ -559,7 +602,7 @@ indent {
}
/* Style when dragging layer item over the bottom part of an item */
.dragging-item .drag-bot.layer-item {
.metabrush .dragging-item .drag-bot.layer-item {
border-bottom: 2px solid @highlight;
margin-bottom: -2px;
box-shadow:
@ -567,7 +610,7 @@ indent {
}
/* Style when dragging brush over an item */
.dragging-brush .drag-top.layer-item, .dragging-brush .drag-bot.layer-item {
.metabrush .dragging-brush .drag-top.layer-item, .dragging-brush .drag-bot.layer-item {
border-top: 2px solid @brushStroke;
border-bottom: 2px solid @brushStroke;
border-left: 0px;
@ -578,7 +621,7 @@ indent {
}
/* Style for item being dragged */
.dragged.layer-item {
.metabrush .dragged.layer-item {
background-color: @bg;
transition:
background-color 0.4s ease-in-out;

View file

@ -686,6 +686,34 @@ instance HandleAction Delete where
-- TODO: handle deletion of layers by checking the current focus.
_ -> pure ()
------------------
-- Delete layer --
------------------
data DeleteLayer = DeleteLayer !MetaBrush.Layer.Layer
deriving stock Show
instance HandleAction MetaBrush.Application.Action.DeleteLayer where
handleAction
uiElts
vars@( Variables { toolTVar, modeTVar } )
_ =
return ()
---------------
-- New group --
---------------
data GroupPosition = GroupAbove | GroupBelow | GroupContaining
deriving stock Show
data NewGroup = NewGroup !GroupPosition !MetaBrush.Layer.Layer
deriving stock Show
instance HandleAction NewGroup where
handleAction ( UIElements { viewport = Viewport {..} } ) ( Variables { redrawStrokesTVar, showGuidesTVar } ) ( NewGroup pos lay ) = do
return ()
-------------------
-- Toggle guides --
-------------------

View file

@ -7,6 +7,10 @@ import Data.Word
-- gi-gtk
import qualified GI.Gtk as GTK
-- text
import Data.Text
( Text )
-- MetaBrush
import Math.Linear
( (..), T(..) )
@ -15,9 +19,12 @@ import MetaBrush.UI.Viewport
( Ruler(..) )
import MetaBrush.Unique
( Unique )
import MetaBrush.Layer (Layer)
--------------------------------------------------------------------------------
actionPrefix :: ActionName -> Text
class HandleAction action where
handleAction :: UIElements -> Variables -> action -> IO ()
@ -38,6 +45,9 @@ instance HandleAction Save
data SaveAs = SaveAs
instance HandleAction SaveAs
data Export = Export
instance HandleAction Export
data Close
= CloseActive
| CloseThis
@ -76,6 +86,13 @@ instance HandleAction Duplicate
data Delete = Delete
instance HandleAction Delete
data DeleteLayer = DeleteLayer !Layer
instance HandleAction DeleteLayer
data GroupPosition = GroupAbove | GroupBelow | GroupContaining
data NewGroup = NewGroup !GroupPosition !Layer
instance HandleAction NewGroup
data ToggleGuides = ToggleGuides
instance HandleAction ToggleGuides
@ -85,6 +102,9 @@ instance HandleAction Confirm
data About = About
instance HandleAction About
data OpenPrefs = OpenPrefs
instance HandleAction OpenPrefs
data MouseMove = MouseMove !( 2 )
instance HandleAction MouseMove

View file

@ -39,8 +39,7 @@ import qualified Data.HashSet as HashSet
( fromList, toMap )
-- MetaBrush
import MetaBrush.Application.Action
hiding ( save, saveAs )
import {-# SOURCE #-} MetaBrush.Application.Action
import MetaBrush.Application.Context
import MetaBrush.Asset.Colours
( Colours )
@ -48,6 +47,8 @@ import MetaBrush.Asset.WindowIcons
( drawMinimise, drawRestoreDown, drawMaximise, drawClose )
import MetaBrush.GTK.Util
( widgetAddClass, widgetAddClasses )
import MetaBrush.Layer
( Layer(..) )
--------------------------------------------------------------------------------
-- Types for describing menu items.
@ -92,6 +93,11 @@ menuActionNames = HashSet.fromList
, WinAction "about"
-- preferences
, WinAction "prefs"
-- stroke actions
, WinAction "newGroupAbove"
, WinAction "newGroupBelow"
, WinAction "newGroupContaining"
, WinAction "deleteLayer"
]
createMenuActions :: IO ( HashMap ActionName GIO.SimpleAction )
@ -165,6 +171,18 @@ helpMenuDescription =
[ MenuItemDescription "About MetaBrush" ( Just $ WinAction "about", About ) ( Just "<Ctrl>question" )
]
strokeMenuDescription :: Layer -> [ MenuItem ]
strokeMenuDescription lay =
[ case lay of
StrokeLayer {} -> MenuItemDescription "Delete stroke" ( Nothing, DeleteLayer lay) Nothing
GroupLayer {} -> MenuItemDescription "Delete group" ( Nothing, DeleteLayer lay) Nothing
, Section ( Just "New group" ) $
[ MenuItemDescription "...above" ( Nothing, NewGroup GroupAbove lay ) Nothing
, MenuItemDescription "...below" ( Nothing, NewGroup GroupBelow lay ) Nothing
, MenuItemDescription "...containing" ( Nothing, NewGroup GroupContaining lay ) Nothing
]
]
--------------------------------------------------------------------------------
-- Creating a GTK popover menu bar from a menu description.
@ -225,7 +243,7 @@ createMenuBar uiElts@( UIElements { application, window, titleBar } ) vars colou
--GTK.windowAddAccelGroup window accelGroup
menu <- createMenu uiElts vars
menuBar <- GTK.popoverMenuBarNewFromModel ( Just menu )
widgetAddClasses menuBar [ "menu", "text", "plain" ]
widgetAddClasses menuBar [ "headerMenu", "text", "plain" ]
GTK.headerBarPackStart titleBar menuBar
-- TODO: this is a bit of a workaround to add hover highlight to top-level menu items.

View file

@ -67,7 +67,7 @@ createPanelBar panelBox = do
for_ [ strokesTab, brushesTab, transformTab, historyTab ] \ tab -> do
widgetAddClasses tab [ "plain", "text", "panelTab" ]
for_ [ layersScrolledWindow, brushesScrolledWindow ] \ w -> widgetAddClass w "panel"
for_ [ layersScrolledWindow, brushesScrolledWindow ] \ w -> widgetAddClasses w [ "panel", "listViewPane" ]
for_ [ transformPanelBox, historyPanelBox ] \ panel -> do
widgetAddClass panel "panel"

View file

@ -89,9 +89,13 @@ import MetaBrush.Brush
import MetaBrush.Document
import MetaBrush.Document.Diff
import MetaBrush.Document.History
import MetaBrush.GTK.Util
import MetaBrush.Layer
import MetaBrush.Stroke hiding ( Layer(..) )
import MetaBrush.Unique
import MetaBrush.UI.Menu
( strokeMenuDescription, makeMenu )
--------------------------------------------------------------------------------
@ -418,6 +422,9 @@ newLayerView :: UIElements -> Variables -> IO GTK.ListView
newLayerView uiElts@( UIElements { window } ) vars = mdo
layersListFactory <- GTK.signalListItemFactoryNew
layerMenu <- GIO.menuNew
layerPopover <- GTK.popoverMenuNewFromModel ( Nothing @GIO.Menu )
widgetAddClasses layerPopover [ "strokeMenu", "text", "plain" ]
-- Connect to "setup" signal to create generic widgets for viewing the tree.
--
@ -440,13 +447,36 @@ newLayerView uiElts@( UIElements { window } ) vars = mdo
expander <- newLayerViewWidget
GTK.listItemSetChild listItem ( Just expander )
GTK.widgetAddCssClass expander "layer-item"
widgetAddClass expander "layer-item"
LayerViewWidget
{ layerViewLabel = label
, layerViewCheckButton = visibleButton }
<- getLayerViewWidget expander
------------------
-- GestureClick --
------------------
click <- GTK.gestureClickNew
void $ GTK.onGestureClickPressed click $ \ clickNo x y -> do
case clickNo of
_ -> do
GTK.widgetUnparent layerPopover
GTK.widgetSetParent layerPopover expander
layer <- getLayerData listItem
GIO.menuRemoveAll layerMenu
makeMenu uiElts vars layerMenu ( strokeMenuDescription layer )
GTK.popoverMenuSetMenuModel layerPopover ( Just layerMenu )
rect <- GDK.newZeroRectangle
GDK.setRectangleX rect ( round x )
GDK.setRectangleY rect ( round y )
GTK.popoverSetPointingTo layerPopover ( Just rect )
GTK.popoverPopup layerPopover
_ -> return ()
----------------------------
-- Visibility CheckButton --
----------------------------
@ -516,7 +546,7 @@ newLayerView uiElts@( UIElements { window } ) vars = mdo
}
val <- GDK.contentProviderNewForValue =<< GIO.toGValue ( GI.HValue dnd_sourceItem )
GTK.widgetAddCssClass window "dragging-item"
widgetAddClass window "dragging-item"
return $ Just val
void $ GTK.onDragSourceDragBegin dragSource $ \ _drag -> do
@ -528,7 +558,7 @@ newLayerView uiElts@( UIElements { window } ) vars = mdo
-}
noPaintable <- GDK.paintableNewEmpty 0 0
GTK.dragSourceSetIcon ?self ( Just noPaintable ) 0 0
GTK.widgetAddCssClass expander "dragged"
widgetAddClass expander "dragged"
-- TODO: add "dragged" class for all descendants as well.
void $ GTK.onDragSourceDragCancel dragSource $ \ _drag _reason -> do
GTK.widgetRemoveCssClass window "dragging-item"
@ -720,38 +750,39 @@ newLayerView uiElts@( UIElements { window } ) vars = mdo
return True
void $ GTK.onDropTargetEnter dropTarget $ \ _x y -> do
GTK.widgetAddCssClass expander "drag-over"
widgetAddClass expander "drag-over"
h <- GTK.widgetGetHeight expander
if y < 0.5 * fromIntegral h
then do
GTK.widgetAddCssClass expander "drag-top"
widgetAddClass expander "drag-top"
else do
GTK.widgetAddCssClass expander "drag-bot"
widgetAddClass expander "drag-bot"
mbNextItem <- getNextItem_maybe expander
for_ mbNextItem $ \ nextItem -> do
GTK.widgetAddCssClass nextItem "drag-top"
widgetAddClass nextItem "drag-top"
return [ GDK.DragActionCopy ]
void $ GTK.onDropTargetMotion dropTarget $ \ _x y -> do
h <- GTK.widgetGetHeight expander
if y < 0.5 * fromIntegral h
then do
GTK.widgetRemoveCssClass expander "drag-bot"
GTK.widgetAddCssClass expander "drag-top"
widgetAddClass expander "drag-top"
mbNextItem <- getNextItem_maybe expander
for_ mbNextItem $ \ nextItem -> do
GTK.widgetRemoveCssClass nextItem "drag-top"
else do
GTK.widgetRemoveCssClass expander "drag-top"
GTK.widgetAddCssClass expander "drag-bot"
widgetAddClass expander "drag-bot"
mbNextItem <- getNextItem_maybe expander
for_ mbNextItem $ \ nextItem -> do
GTK.widgetAddCssClass nextItem "drag-top"
widgetAddClass nextItem "drag-top"
return [ GDK.DragActionCopy ]
void $ GTK.onDropTargetLeave dropTarget $ do
dropTargetCleanup
GTK.widgetAddController expander dragSource
GTK.widgetAddController expander dropTarget
GTK.widgetAddController expander click
-- Connect to "bind" signal to modify the generic widget to display the data for this list item.
_ <- GTK.onSignalListItemFactoryBind layersListFactory $ \ listItem0 -> do