taffybar-4.1.2: src/System/Taffybar/Widget/Inhibitor.hs
{-# LANGUAGE OverloadedStrings #-}
-----------------------------------------------------------------------------
-- |
-- Module : System.Taffybar.Widget.Inhibitor
-- Copyright : (c) Ivan A. Malison
-- License : BSD3-style (see LICENSE)
--
-- Maintainer : Ivan A. Malison
-- Stability : unstable
-- Portability : unportable
--
-- This module provides a widget for controlling idle/sleep inhibitors.
-- The widget displays the current inhibitor state and allows toggling
-- the inhibitor on/off with a click.
--
-- Example usage:
--
-- > import System.Taffybar.Widget.Inhibitor
-- >
-- > main = do
-- > -- Simple inhibitor widget that inhibits idle
-- > let inhibitor = inhibitorNew
-- >
-- > -- Or with custom configuration
-- > let customInhibitor = inhibitorNewWithConfig defaultInhibitorConfig
-- > { inhibitWhat = [InhibitIdle, InhibitSleep]
-- > , inhibitorActiveText = "AWAKE"
-- > , inhibitorInactiveText = "zzz"
-- > }
-----------------------------------------------------------------------------
module System.Taffybar.Widget.Inhibitor
( -- * Widget constructors
inhibitorNew
, inhibitorNewWithConfig
, inhibitorIconNew
, inhibitorIconNewWithConfig
, inhibitorLabelNew
, inhibitorLabelNewWithConfig
-- * Configuration
, InhibitorConfig(..)
, defaultInhibitorConfig
-- * Re-exports
, InhibitType(..)
) where
import Control.Monad
import Control.Monad.IO.Class
import Control.Monad.Trans.Reader
import qualified Data.Text as T
import qualified GI.Gdk as Gdk
import GI.Gtk as Gtk
import System.Taffybar.Context
import System.Taffybar.Information.Inhibitor
import System.Taffybar.Util
import System.Taffybar.Widget.Generic.ChannelWidget
import System.Taffybar.Widget.Util
-- | Configuration for the inhibitor widget
data InhibitorConfig = InhibitorConfig
{ -- | What types of inhibitors to manage (default: [InhibitIdle])
inhibitWhat :: [InhibitType]
-- | Text to display when inhibitor is active
, inhibitorActiveText :: T.Text
-- | Text to display when inhibitor is inactive
, inhibitorInactiveText :: T.Text
-- | Icon to display when inhibitor is active (default: U+F0F4, nf-fa-coffee)
, inhibitorActiveIcon :: T.Text
-- | Icon to display when inhibitor is inactive (default: U+F236, nf-fa-bed)
, inhibitorInactiveIcon :: T.Text
-- | CSS class prefix (results in "prefix-active" and "prefix-inactive")
, inhibitorCssPrefix :: T.Text
} deriving (Eq, Show)
-- | Default configuration: inhibits idle, shows simple icon-style text
defaultInhibitorConfig :: InhibitorConfig
defaultInhibitorConfig = InhibitorConfig
{ inhibitWhat = [InhibitIdle]
, inhibitorActiveText = "INHIBIT"
, inhibitorInactiveText = "inhibit"
, inhibitorActiveIcon = T.pack "\xF0F4"
, inhibitorInactiveIcon = T.pack "\xF236"
, inhibitorCssPrefix = "inhibitor"
}
-- | Create a combined icon+label inhibitor widget with default configuration
inhibitorNew :: TaffyIO Widget
inhibitorNew = inhibitorNewWithConfig defaultInhibitorConfig
-- | Create a combined icon+label inhibitor widget with custom configuration.
-- The icon changes dynamically based on inhibitor state.
-- Click to toggle the inhibitor on/off.
inhibitorNewWithConfig :: InhibitorConfig -> TaffyIO Widget
inhibitorNewWithConfig config = do
let types = inhibitWhat config
iconWidget <- inhibitorIconNewWithConfig config
labelWidget <- inhibitorLabelNewWithConfig config
ctx <- ask
liftIO $ do
box <- buildIconLabelBox iconWidget labelWidget
ebox <- eventBoxNew
containerAdd ebox box
_ <- widgetSetClassGI ebox "inhibitor"
_ <- onWidgetButtonPressEvent ebox $ \event -> do
button <- Gdk.getEventButtonButton event
when (button == 1) $
runReaderT (toggleInhibitor types) ctx
return True
widgetShowAll ebox
toWidget ebox
-- | Create an icon-only inhibitor widget with default configuration
inhibitorIconNew :: TaffyIO Widget
inhibitorIconNew = inhibitorIconNewWithConfig defaultInhibitorConfig
-- | Create an icon-only inhibitor widget with custom configuration.
-- The icon changes dynamically based on inhibitor state.
inhibitorIconNewWithConfig :: InhibitorConfig -> TaffyIO Widget
inhibitorIconNewWithConfig config = do
let types = inhibitWhat config
chan <- getInhibitorChan types
ctx <- ask
liftIO $ do
label <- labelNew Nothing
let updateIcon state = postGUIASync $
labelSetText label $
if inhibitorActive state
then inhibitorActiveIcon config
else inhibitorInactiveIcon config
void $ onWidgetRealize label $ do
initialState <- runReaderT (getInhibitorState types) ctx
updateIcon initialState
widgetShowAll label
toWidget =<< channelWidgetNew label chan updateIcon
-- | Create a label-only inhibitor widget with default configuration.
-- Click to toggle the inhibitor on/off.
inhibitorLabelNew :: TaffyIO Widget
inhibitorLabelNew = inhibitorLabelNewWithConfig defaultInhibitorConfig
-- | Create a label-only inhibitor widget with custom configuration.
-- Displays text and CSS classes based on inhibitor state.
-- Click to toggle the inhibitor on/off.
inhibitorLabelNewWithConfig :: InhibitorConfig -> TaffyIO Widget
inhibitorLabelNewWithConfig config = do
let types = inhibitWhat config
chan <- getInhibitorChan types
ctx <- ask
liftIO $ do
label <- labelNew Nothing
ebox <- eventBoxNew
-- Set initial CSS class
_ <- widgetSetClassGI ebox "inhibitor"
containerAdd ebox label
-- Set up click handler
_ <- onWidgetButtonPressEvent ebox $ \event -> do
button <- Gdk.getEventButtonButton event
when (button == 1) $
runReaderT (toggleInhibitor types) ctx
return True
-- Update function for the widget
let updateWidget state = postGUIASync $ do
let (text, activeClass, inactiveClass) =
if inhibitorActive state
then ( inhibitorActiveText config
, inhibitorCssPrefix config <> "-active"
, inhibitorCssPrefix config <> "-inactive"
)
else ( inhibitorInactiveText config
, inhibitorCssPrefix config <> "-inactive"
, inhibitorCssPrefix config <> "-active"
)
labelSetText label text
addClassIfMissing activeClass ebox
removeClassIfPresent inactiveClass ebox
-- Set initial state
void $ onWidgetRealize ebox $ do
initialState <- runReaderT (getInhibitorState types) ctx
updateWidget initialState
-- Connect to state changes
toWidget =<< channelWidgetNew ebox chan updateWidget