taffybar-4.1.2: src/System/Taffybar/Widget/KeyboardState.hs
{-# LANGUAGE OverloadedStrings #-}
--------------------------------------------------------------------------------
-- |
-- Module : System.Taffybar.Widget.KeyboardState
-- Copyright : (c) Ivan Malison
-- License : BSD3-style (see LICENSE)
--
-- Maintainer : Ivan Malison <IvanMalison@gmail.com>
-- Stability : unstable
-- Portability : unportable
--
-- A widget that displays keyboard lock key states (Caps Lock, Num Lock,
-- Scroll Lock). States are read from sysfs LED brightness files.
--
--------------------------------------------------------------------------------
module System.Taffybar.Widget.KeyboardState
( -- * Widget Constructors
keyboardStateNew
, keyboardStateNewWithConfig
, keyboardStateLabelNew
, keyboardStateLabelNewWithConfig
, keyboardStateIconNew
, keyboardStateIconNewWithConfig
-- * Configuration
, KeyboardStateConfig(..)
, defaultKeyboardStateConfig
-- * Format Functions
, formatKeyboardState
) where
import Control.Monad.IO.Class (MonadIO, liftIO)
import qualified Data.Text as T
import qualified GI.Gtk as Gtk
import System.Taffybar.Information.KeyboardState
import System.Taffybar.Widget.Generic.PollingLabel (pollingLabelNew)
import System.Taffybar.Widget.Util (buildIconLabelBox, widgetSetClassGI)
-- | Configuration for the keyboard state widget.
data KeyboardStateConfig = KeyboardStateConfig
{ kscCapsLockOnText :: T.Text
-- ^ Text to display when Caps Lock is on. Default: "[CAPS]"
, kscCapsLockOffText :: T.Text
-- ^ Text to display when Caps Lock is off. Default: ""
, kscNumLockOnText :: T.Text
-- ^ Text to display when Num Lock is on. Default: "[NUM]"
, kscNumLockOffText :: T.Text
-- ^ Text to display when Num Lock is off. Default: ""
, kscScrollLockOnText :: T.Text
-- ^ Text to display when Scroll Lock is on. Default: "[SCROLL]"
, kscScrollLockOffText :: T.Text
-- ^ Text to display when Scroll Lock is off. Default: ""
, kscShowCapsLock :: Bool
-- ^ Whether to show Caps Lock state. Default: True
, kscShowNumLock :: Bool
-- ^ Whether to show Num Lock state. Default: False
, kscShowScrollLock :: Bool
-- ^ Whether to show Scroll Lock state. Default: False
, kscSeparator :: T.Text
-- ^ Separator between lock indicators. Default: " "
, kscPollingInterval :: Double
-- ^ Polling interval in seconds. Default: 0.5
, kscIcon :: T.Text
-- ^ Icon text for the icon widget variant. Default: keyboard icon (nf-md-keyboard)
} deriving (Eq, Show)
-- | Default configuration for the keyboard state widget.
-- Shows only Caps Lock by default, polling every 0.5 seconds.
defaultKeyboardStateConfig :: KeyboardStateConfig
defaultKeyboardStateConfig = KeyboardStateConfig
{ kscCapsLockOnText = "[CAPS]"
, kscCapsLockOffText = ""
, kscNumLockOnText = "[NUM]"
, kscNumLockOffText = ""
, kscScrollLockOnText = "[SCROLL]"
, kscScrollLockOffText = ""
, kscShowCapsLock = True
, kscShowNumLock = False
, kscShowScrollLock = False
, kscSeparator = " "
, kscPollingInterval = 0.5
, kscIcon = T.pack "\xF80B"
}
-- | Format the keyboard state according to the configuration.
formatKeyboardState :: KeyboardStateConfig -> KeyboardState -> T.Text
formatKeyboardState cfg state =
let parts = filter (not . T.null)
[ if kscShowCapsLock cfg
then if capsLock state
then kscCapsLockOnText cfg
else kscCapsLockOffText cfg
else ""
, if kscShowNumLock cfg
then if numLock state
then kscNumLockOnText cfg
else kscNumLockOffText cfg
else ""
, if kscShowScrollLock cfg
then if scrollLock state
then kscScrollLockOnText cfg
else kscScrollLockOffText cfg
else ""
]
in T.intercalate (kscSeparator cfg) parts
-- | Create a keyboard state label widget with default configuration.
-- Shows Caps Lock status, polling every 0.5 seconds.
keyboardStateLabelNew :: MonadIO m => m Gtk.Widget
keyboardStateLabelNew = keyboardStateLabelNewWithConfig defaultKeyboardStateConfig
-- | Create a keyboard state label widget with custom configuration.
-- Uses PollingLabel to periodically update the display.
keyboardStateLabelNewWithConfig :: MonadIO m => KeyboardStateConfig -> m Gtk.Widget
keyboardStateLabelNewWithConfig cfg = liftIO $ do
widget <- pollingLabelNew (kscPollingInterval cfg) (getFormattedState cfg)
_ <- widgetSetClassGI widget "keyboard-state"
return widget
-- | Create a keyboard state icon widget with default configuration.
keyboardStateIconNew :: MonadIO m => m Gtk.Widget
keyboardStateIconNew = keyboardStateIconNewWithConfig defaultKeyboardStateConfig
-- | Create a keyboard state icon widget with custom configuration.
-- Displays a static icon label.
keyboardStateIconNewWithConfig :: MonadIO m => KeyboardStateConfig -> m Gtk.Widget
keyboardStateIconNewWithConfig cfg = liftIO $ do
label <- Gtk.labelNew (Just (kscIcon cfg))
Gtk.widgetShowAll label
Gtk.toWidget label
-- | Create a combined keyboard state widget (icon + label) with default
-- configuration.
keyboardStateNew :: MonadIO m => m Gtk.Widget
keyboardStateNew = keyboardStateNewWithConfig defaultKeyboardStateConfig
-- | Create a combined keyboard state widget (icon + label) with custom
-- configuration.
keyboardStateNewWithConfig :: MonadIO m => KeyboardStateConfig -> m Gtk.Widget
keyboardStateNewWithConfig cfg = do
iconWidget <- keyboardStateIconNewWithConfig cfg
labelWidget <- keyboardStateLabelNewWithConfig cfg
liftIO $ buildIconLabelBox iconWidget labelWidget
-- | Get the formatted keyboard state text.
getFormattedState :: KeyboardStateConfig -> IO T.Text
getFormattedState cfg =
formatKeyboardState cfg <$> getKeyboardState