diff options
Diffstat (limited to 'accounts/gkleen@sif/taffybar/src')
3 files changed, 0 insertions, 301 deletions
diff --git a/accounts/gkleen@sif/taffybar/src/System/Taffybar/Widget/Clock.hs b/accounts/gkleen@sif/taffybar/src/System/Taffybar/Widget/Clock.hs deleted file mode 100644 index e8dc480f..00000000 --- a/accounts/gkleen@sif/taffybar/src/System/Taffybar/Widget/Clock.hs +++ /dev/null | |||
@@ -1,111 +0,0 @@ | |||
1 | {-# LANGUAGE OverloadedStrings #-} | ||
2 | module System.Taffybar.Widget.Clock | ||
3 | ( textClockNew | ||
4 | , textClockNewWith | ||
5 | , defaultClockConfig | ||
6 | , ClockConfig(..) | ||
7 | , ClockUpdateStrategy(..) | ||
8 | ) where | ||
9 | |||
10 | import Control.Monad.IO.Class | ||
11 | import Data.Maybe | ||
12 | import qualified Data.Text as T | ||
13 | import qualified Data.Time.Clock as Clock | ||
14 | import Data.Time.Format | ||
15 | import Data.Time.LocalTime | ||
16 | import qualified Data.Time.Locale.Compat as L | ||
17 | import GI.Gtk | ||
18 | import System.Taffybar.Widget.Generic.PollingLabel | ||
19 | |||
20 | type ClockFormat = L.TimeLocale -> ZonedTime -> T.Text | ||
21 | |||
22 | -- | Create the widget. I recommend passing @Nothing@ for the TimeLocale | ||
23 | -- parameter. The format string can include Pango markup | ||
24 | -- (<http://developer.gnome.org/pango/stable/PangoMarkupFormat.html>). | ||
25 | textClockNew :: | ||
26 | MonadIO m => Maybe L.TimeLocale -> ClockFormat -> Double -> m GI.Gtk.Widget | ||
27 | textClockNew userLocale format interval = | ||
28 | textClockNewWith cfg | ||
29 | where | ||
30 | cfg = defaultClockConfig { clockTimeLocale = userLocale | ||
31 | , clockFormat = format | ||
32 | , clockUpdateStrategy = ConstantInterval interval | ||
33 | } | ||
34 | |||
35 | data ClockUpdateStrategy | ||
36 | = ConstantInterval Double | ||
37 | | RoundedTargetInterval Int Double | ||
38 | deriving (Eq, Ord, Show) | ||
39 | |||
40 | data ClockConfig = ClockConfig | ||
41 | { clockTimeZone :: Maybe TimeZone | ||
42 | , clockTimeLocale :: Maybe L.TimeLocale | ||
43 | , clockFormat :: ClockFormat | ||
44 | , clockUpdateStrategy :: ClockUpdateStrategy | ||
45 | } | ||
46 | |||
47 | -- | A clock configuration that defaults to the current locale | ||
48 | defaultClockConfig :: ClockConfig | ||
49 | defaultClockConfig = ClockConfig | ||
50 | { clockTimeZone = Nothing | ||
51 | , clockTimeLocale = Nothing | ||
52 | , clockFormat = \locale zonedTime -> T.pack $ formatTime locale "%a %b %_d %r" zonedTime | ||
53 | , clockUpdateStrategy = RoundedTargetInterval 5 0.0 | ||
54 | } | ||
55 | |||
56 | systemGetTZ :: IO TimeZone | ||
57 | systemGetTZ = getCurrentTimeZone | ||
58 | |||
59 | -- | A configurable text-based clock widget. It currently allows for | ||
60 | -- a configurable time zone through the 'ClockConfig'. | ||
61 | -- | ||
62 | -- See also 'textClockNew'. | ||
63 | textClockNewWith :: MonadIO m => ClockConfig -> m Widget | ||
64 | textClockNewWith ClockConfig | ||
65 | { clockTimeZone = userZone | ||
66 | , clockTimeLocale = userLocale | ||
67 | , clockFormat = format | ||
68 | , clockUpdateStrategy = updateStrategy | ||
69 | } = liftIO $ do | ||
70 | let getTZ = maybe systemGetTZ return userZone | ||
71 | locale = fromMaybe L.defaultTimeLocale userLocale | ||
72 | |||
73 | let getUserZonedTime = | ||
74 | utcToZonedTime <$> getTZ <*> Clock.getCurrentTime | ||
75 | |||
76 | doTimeFormat = format locale | ||
77 | |||
78 | getRoundedTimeAndNextTarget = do | ||
79 | zonedTime <- getUserZonedTime | ||
80 | return $ case updateStrategy of | ||
81 | ConstantInterval interval -> | ||
82 | (doTimeFormat zonedTime, Nothing, interval) | ||
83 | RoundedTargetInterval roundSeconds offset -> | ||
84 | let roundSecondsDiffTime = fromIntegral roundSeconds | ||
85 | addTheRound = addLocalTime roundSecondsDiffTime | ||
86 | localTime = zonedTimeToLocalTime zonedTime | ||
87 | ourLocalTimeOfDay = localTimeOfDay localTime | ||
88 | seconds = round $ todSec ourLocalTimeOfDay | ||
89 | secondsFactor = seconds `div` roundSeconds | ||
90 | displaySeconds = secondsFactor * roundSeconds | ||
91 | baseLocalTimeOfDay = | ||
92 | ourLocalTimeOfDay { todSec = fromIntegral displaySeconds } | ||
93 | ourLocalTime = | ||
94 | localTime { localTimeOfDay = baseLocalTimeOfDay } | ||
95 | roundedLocalTime = | ||
96 | if seconds `mod` roundSeconds > roundSeconds `div` 2 | ||
97 | then addTheRound ourLocalTime | ||
98 | else ourLocalTime | ||
99 | roundedZonedTime = | ||
100 | zonedTime { zonedTimeToLocalTime = roundedLocalTime } | ||
101 | nextTarget = addTheRound ourLocalTime | ||
102 | amountToWait = realToFrac $ diffLocalTime nextTarget localTime | ||
103 | in (doTimeFormat roundedZonedTime, Nothing, amountToWait - offset) | ||
104 | |||
105 | label <- pollingLabelWithVariableDelay getRoundedTimeAndNextTarget | ||
106 | ebox <- eventBoxNew | ||
107 | containerAdd ebox label | ||
108 | eventBoxSetVisibleWindow ebox False | ||
109 | widgetShowAll ebox | ||
110 | toWidget ebox | ||
111 | |||
diff --git a/accounts/gkleen@sif/taffybar/src/System/Taffybar/Widget/TooltipBattery.hs b/accounts/gkleen@sif/taffybar/src/System/Taffybar/Widget/TooltipBattery.hs deleted file mode 100644 index 9dc52774..00000000 --- a/accounts/gkleen@sif/taffybar/src/System/Taffybar/Widget/TooltipBattery.hs +++ /dev/null | |||
@@ -1,101 +0,0 @@ | |||
1 | {-# LANGUAGE OverloadedStrings #-} | ||
2 | {-# LANGUAGE ScopedTypeVariables #-} | ||
3 | module System.Taffybar.Widget.TooltipBattery ( batteryIconTooltipNew ) where | ||
4 | |||
5 | import Control.Applicative | ||
6 | import Control.Monad | ||
7 | import Control.Monad.IO.Class | ||
8 | import Control.Monad.Trans.Reader | ||
9 | import Data.Int (Int64) | ||
10 | import qualified Data.Text as T | ||
11 | import GI.Gtk | ||
12 | import Prelude | ||
13 | import StatusNotifier.Tray (scalePixbufToSize) | ||
14 | import System.Taffybar.Context | ||
15 | import System.Taffybar.Information.Battery | ||
16 | import System.Taffybar.Util | ||
17 | import System.Taffybar.Widget.Generic.AutoSizeImage | ||
18 | import System.Taffybar.Widget.Generic.ChannelWidget | ||
19 | import Text.Printf | ||
20 | import Text.StringTemplate | ||
21 | import Data.Function ((&)) | ||
22 | |||
23 | -- | Just the battery info that will be used for display (this makes combining | ||
24 | -- several easier). | ||
25 | data BatteryWidgetInfo = BWI | ||
26 | { seconds :: Maybe Int64 | ||
27 | , percent :: Double | ||
28 | , status :: String | ||
29 | , rate :: Maybe Double | ||
30 | } deriving (Eq, Show) | ||
31 | |||
32 | -- | Format a duration expressed as seconds to hours and minutes | ||
33 | formatDuration :: Int64 -> String | ||
34 | formatDuration secs = let minutes, hours, minutes' :: Int64 | ||
35 | minutes = secs `div` 60 | ||
36 | (hours, minutes') = minutes `divMod` 60 | ||
37 | in printf "%02d:%02d" hours minutes' | ||
38 | |||
39 | getBatteryWidgetInfo :: BatteryInfo -> BatteryWidgetInfo | ||
40 | getBatteryWidgetInfo info = | ||
41 | let battPctNum :: Double | ||
42 | battPctNum = batteryPercentage info | ||
43 | battTime :: Maybe Int64 | ||
44 | battTime = | ||
45 | case batteryState info of | ||
46 | BatteryStateCharging -> Just $ batteryTimeToFull info | ||
47 | BatteryStateDischarging -> Just $ batteryTimeToEmpty info | ||
48 | _ -> Nothing | ||
49 | battStatus :: String | ||
50 | battStatus = | ||
51 | case batteryState info of | ||
52 | BatteryStateCharging -> "↑" | ||
53 | BatteryStateDischarging -> "↓" | ||
54 | BatteryStateEmpty -> "⤓" | ||
55 | BatteryStateFullyCharged -> "⤒" | ||
56 | _ -> "?" | ||
57 | battRate :: Maybe Double | ||
58 | battRate | rawRate < 0.1 = Nothing | ||
59 | | otherwise = Just rawRate | ||
60 | where rawRate = batteryEnergyRate info | ||
61 | in BWI{ seconds = battTime, percent = battPctNum, status = battStatus, rate = battRate } | ||
62 | |||
63 | -- | Given (maybe summarized) battery info and format: provides the string to display | ||
64 | formatBattInfo :: BatteryWidgetInfo -> String -> T.Text | ||
65 | formatBattInfo info fmt = | ||
66 | let tpl = newSTMP fmt | ||
67 | tpl' = tpl | ||
68 | & setManyAttrib [ ("percentage", printf "%.0f" $ percent info) | ||
69 | , ("status", status info) | ||
70 | ] | ||
71 | & setManyAttrib [ ("time", formatDuration <$> seconds info) | ||
72 | , ("rate", printf "%.0f" <$> rate info) | ||
73 | ] | ||
74 | in render tpl' | ||
75 | |||
76 | themeLoadFlags :: [IconLookupFlags] | ||
77 | themeLoadFlags = [IconLookupFlagsGenericFallback, IconLookupFlagsUseBuiltin] | ||
78 | |||
79 | batteryIconTooltipNew :: String -> TaffyIO Widget | ||
80 | batteryIconTooltipNew format = do | ||
81 | DisplayBatteryChanVar (chan, _) <- setupDisplayBatteryChanVar ["IconName", "State", "Percentage", "TimeToFull", "TimeToEmpty", "EnergyRate"] | ||
82 | ctx <- ask | ||
83 | liftIO $ do | ||
84 | image <- imageNew | ||
85 | styleCtx <- widgetGetStyleContext =<< toWidget image | ||
86 | defaultTheme <- iconThemeGetDefault | ||
87 | let getCurrentBatteryIconNameStringTooltip = do | ||
88 | info <- runReaderT getDisplayBatteryInfo ctx | ||
89 | let iconNameString = T.pack $ batteryIconName info | ||
90 | tooltip = formatBattInfo (getBatteryWidgetInfo info) format | ||
91 | return (iconNameString, tooltip) | ||
92 | extractPixbuf info = | ||
93 | fst <$> iconInfoLoadSymbolicForContext info styleCtx | ||
94 | setIconForSize size = do | ||
95 | (name, tooltip) <- getCurrentBatteryIconNameStringTooltip | ||
96 | widgetSetTooltipMarkup image $ Just tooltip | ||
97 | iconThemeLookupIcon defaultTheme name size themeLoadFlags >>= | ||
98 | traverse extractPixbuf >>= | ||
99 | traverse (scalePixbufToSize size OrientationHorizontal) | ||
100 | updateImage <- autoSizeImage image setIconForSize OrientationHorizontal | ||
101 | toWidget =<< channelWidgetNew image chan (const $ postGUIASync updateImage) | ||
diff --git a/accounts/gkleen@sif/taffybar/src/taffybar.hs b/accounts/gkleen@sif/taffybar/src/taffybar.hs deleted file mode 100644 index 67ee942d..00000000 --- a/accounts/gkleen@sif/taffybar/src/taffybar.hs +++ /dev/null | |||
@@ -1,89 +0,0 @@ | |||
1 | {-# LANGUAGE OverloadedStrings #-} | ||
2 | |||
3 | module Main where | ||
4 | |||
5 | import System.Taffybar (startTaffybar) | ||
6 | import System.Taffybar.Context (TaffybarConfig(..)) | ||
7 | import System.Taffybar.Hooks | ||
8 | import System.Taffybar.SimpleConfig hiding (SimpleTaffyConfig(cssPaths)) | ||
9 | import System.Taffybar.Widget | ||
10 | import qualified System.Taffybar.Widget.Clock as MyClock | ||
11 | import System.Taffybar.Widget.TooltipBattery | ||
12 | |||
13 | import Data.Time.Format | ||
14 | import Data.Time.LocalTime | ||
15 | import Data.Time.Calendar.WeekDate | ||
16 | |||
17 | import qualified Data.Text as T | ||
18 | |||
19 | import Control.Exception (SomeException, try) | ||
20 | import Control.Monad.Trans.Reader (mapReaderT) | ||
21 | |||
22 | import Paths_gkleen_sif_taffybar | ||
23 | |||
24 | import System.Log.Logger | ||
25 | |||
26 | |||
27 | main :: IO () | ||
28 | main = do | ||
29 | logger <- getLogger "System.Taffybar" | ||
30 | saveGlobalLogger $ setLevel INFO logger | ||
31 | |||
32 | myCssPath <- getDataFileName "taffybar.css" | ||
33 | startTaffybar taffybarConfig{ cssPaths = pure myCssPath } | ||
34 | |||
35 | |||
36 | taffybarConfig :: TaffybarConfig | ||
37 | taffybarConfig = | ||
38 | let myWorkspacesConfig = | ||
39 | defaultWorkspacesConfig | ||
40 | { maxIcons = Just 0 | ||
41 | , widgetGap = 7 | ||
42 | , showWorkspaceFn = \case | ||
43 | -- Workspace{ workspaceState = Empty } -> False | ||
44 | Workspace{ workspaceName } | workspaceName == "NSP" -> False | ||
45 | _other -> True | ||
46 | , getWindowIconPixbuf = \i d -> either (\(_ :: SomeException) -> Nothing) id <$> mapReaderT try (defaultGetWindowIconPixbuf i d) | ||
47 | , urgentWorkspaceState = True | ||
48 | } | ||
49 | workspaces = workspacesNew myWorkspacesConfig | ||
50 | clock = MyClock.textClockNewWith MyClock.defaultClockConfig | ||
51 | { MyClock.clockUpdateStrategy = MyClock.RoundedTargetInterval 1 0.0 | ||
52 | , MyClock.clockFormat = \tl zt@ZonedTime{ zonedTimeToLocalTime = LocalTime{ localDay } } | ||
53 | -> let date = formatTime tl "%Y-%m-%d" localDay | ||
54 | weekdate = "W" <> show2 woy <> "-" <> show dow | ||
55 | where (_, woy, dow) = toWeekDate localDay | ||
56 | show2 :: Int -> String | ||
57 | show2 x = replicate (2 - length s) '0' ++ s | ||
58 | where s = show x | ||
59 | time = formatTime tl "%H:%M:%S%Ez" zt | ||
60 | in T.intercalate " " $ map T.pack [weekdate, date, time] | ||
61 | } | ||
62 | layout = layoutNew defaultLayoutConfig | ||
63 | windowsW = windowsNew defaultWindowsConfig | ||
64 | { getMenuLabel = truncatedGetMenuLabel 80 | ||
65 | , getActiveLabel = truncatedGetActiveLabel 80 | ||
66 | } | ||
67 | worktime = commandRunnerNew 60 "worktime" [] "worktime" | ||
68 | worktimeToday = commandRunnerNew 60 "worktime" ["today"] "worktime today" | ||
69 | -- See https://github.com/taffybar/gtk-sni-tray#statusnotifierwatcher | ||
70 | -- for a better way to set up the sni tray | ||
71 | -- tray = sniTrayThatStartsWatcherEvenThoughThisIsABadWayToDoIt | ||
72 | tray = sniTrayNew | ||
73 | myConfig = defaultSimpleTaffyConfig | ||
74 | { startWidgets = | ||
75 | workspaces : map (>>= buildContentsBox) [ layout, windowsW ] | ||
76 | , endWidgets = map (>>= buildContentsBox) $ reverse | ||
77 | -- , mpris2New | ||
78 | [ worktime, worktimeToday | ||
79 | , clock | ||
80 | , tray | ||
81 | , batteryIconTooltipNew "$status$ $percentage$%$if(time)$$if(rate)$ ($rate$W $time$)$else$ ($time$)$endif$$elseif(rate)$ ($rate$W)$endif$" | ||
82 | ] | ||
83 | , barPosition = Top | ||
84 | , barPadding = 2 | ||
85 | , barHeight = ExactSize 28 | ||
86 | , widgetSpacing = 10 | ||
87 | } | ||
88 | in withBatteryRefresh $ withLogServer $ | ||
89 | withToggleServer $ toTaffyConfig myConfig | ||