on develop help sign in
widgets: fill now takes a char behavior; update cpu example
commit3d5967f4017ee20a1038647eb835e4dfa8819782 authorAli Abrar <aliabrar@gmail.com> dateWed 24 Mar 2021, 20:54 (6 years ago) parent32e74f6
3 files changed+60−15
ChangeLog.md+1 src-bin/Example/CPU.hs+51−11 src/Reflex/Vty/Widget.hs+8−4
ChangeLog.md+1
@@ -57,6 +57,7 @@
5757* Bug: fix distribution of available space when it cannot be evenly distributed. Previously, all leftover space would be allocated to the first stretchable widget.
5858* Add a CPU usage indicator to the example executable
5959* _Breaking Change_: `boxTitle` now takes a `Behavior t Text` as its title, instead of a plain `Text`
60+* _Breaking Change_: `fill` now takes a `Behavior t Char` instead of a `Char`
6061
6162## 0.1.4.1
6263* Migrate to new dependent-sum / dependent-map (after the "some" package split)
src-bin/Example/CPU.hs+51−11
@@ -6,6 +6,7 @@ module Example.CPU where
66import Control.Exception
77import Control.Monad.Fix
88import Control.Monad.IO.Class
9+import Data.Ratio
910import Data.Time
1011import Data.Word
1112import qualified Data.Text as T
@@ -112,38 +113,77 @@ cpuStats = do
112113 Just get' -> Just (sumStats get' nonIdleStats, sumStats get' idleStats)
113114 active <- foldDyn cpuPercentStep ((0, 0), 0) cpuStat
114115 let pct = fmap snd active
115− title = current $ ffor pct $ \x -> " CPU Usage: " <> T.pack (printf "%3.0f" $ x * 100) <> "% "
116− boxTitle (pure doubleBoxStyle) title $ col $ do
116+ chart pct
117+
118+chart
119+ :: ( MonadFix m
120+ , MonadFocus t m
121+ , MonadLayout t m
122+ , MonadNodeId m
123+ , ImageWriter t m
124+ , HasVtyInput t m
125+ , HasVtyWidgetCtx t m
126+ , HasDisplaySize t m
127+ )
128+ => Dynamic t (Ratio Word64) -> m ()
129+chart pct = do
130+ let title = ffor pct $ \x -> mconcat
131+ [ " CPU Usage: "
132+ , T.pack (printf "%3d" $ (ceiling $ x * 100 :: Int))
133+ , "% "
134+ ]
135+ boxTitle (pure doubleBoxStyle) (current title) $ col $ do
117136 grout flex blank
118137 dh <- displayHeight
119− let h :: Dynamic t Int = ceiling <$> ((*) <$> (fromIntegral <$> dh) <*> pct)
120− tile (fixed h) $ fill '█'
138+ let heights = calcRowHeights <$> dh <*> pct
139+ tile (fixed 1) $ fill $ current $ eighthBlocks . snd <$> heights
140+ tile (fixed $ fst <$> heights) $ fill $ pure '█'
141+ where
142+ -- Calculate number of full rows, height of partial row
143+ calcRowHeights :: Int -> Ratio Word64 -> (Int, Int)
144+ calcRowHeights h r =
145+ let (full, leftovers) = divMod (numerator r * fromIntegral h) (denominator r)
146+ partial = ceiling $ 8 * (leftovers % denominator r)
147+ in (fromIntegral full, partial)
148+
149+eighthBlocks :: (Eq a, Num a, Ord a) => a -> Char
150+eighthBlocks n =
151+ if
152+ | n <= 0 -> ' '
153+ | n == 1 -> '▁'
154+ | n == 2 -> '▂'
155+ | n == 3 -> '▃'
156+ | n == 4 -> '▄'
157+ | n == 5 -> '▅'
158+ | n == 6 -> '▆'
159+ | n == 7 -> '▇'
160+ | otherwise -> '█'
121161
122162-- | Determine the current percentage usage according to this algorithm:
123163--
124164-- PrevIdle = previdle + previowait
125165-- Idle = idle + iowait
126−--
166+--
127167-- PrevNonIdle = prevuser + prevnice + prevsystem + previrq + prevsoftirq + prevsteal
128168-- NonIdle = user + nice + system + irq + softirq + steal
129−--
169+--
130170-- PrevTotal = PrevIdle + PrevNonIdle
131171-- Total = Idle + NonIdle
132−--
172+--
133173-- totald = Total - PrevTotal
134174-- idled = Idle - PrevIdle
135−--
175+--
136176-- CPU_Percentage = (totald - idled)/totald
137177--
138178-- Source: https://stackoverflow.com/questions/23367857/accurate-calculation-of-cpu-usage-given-in-percentage-in-linux
139179cpuPercentStep
140180 :: (Word64, Word64) -- Current active, Current idle
141− -> ((Word64, Word64), Double) -- (Previous idle, Previous total), previous percent
142− -> ((Word64, Word64), Double) -- (New idle, new total), percent
181+ -> ((Word64, Word64), Ratio Word64) -- (Previous idle, Previous total), previous percent
182+ -> ((Word64, Word64), Ratio Word64) -- (New idle, new total), percent
143183cpuPercentStep (nonidle, idle) ((previdle, prevtotal), _) =
144184 let total = idle + nonidle
145185 idled = idle - previdle
146186 totald = total - prevtotal
147187 in ( (idle, total)
148− , (fromIntegral $ totald - idled) / fromIntegral totald
188+ , (totald - idled) % totald
149189 )
src/Reflex/Vty/Widget.hs+8−4
@@ -527,16 +527,20 @@ splitVDrag wS wA wB = do
527527 return (m, x')
528528
529529-- | Fill the background with a particular character.
530−fill :: (HasDisplaySize t m, ImageWriter t m) => Char -> m ()
531−fill c = do
530+fill :: (HasDisplaySize t m, ImageWriter t m) => Behavior t Char -> m ()
531+fill bc = do
532532 dw <- displayWidth
533533 dh <- displayHeight
534− let fillImg = current $ liftA2 (\w h -> [V.charFill V.defAttr c w h]) dw dh
534+ let fillImg =
535+ (\w h c -> [V.charFill V.defAttr c w h])
536+ <$> current dw
537+ <*> current dh
538+ <*> bc
535539 tellImages fillImg
536540
537541-- | Fill the background with the bottom box style
538542hRule :: (HasDisplaySize t m, ImageWriter t m) => BoxStyle -> m ()
539−hRule boxStyle = fill (_boxStyle_s boxStyle)
543+hRule boxStyle = fill $ pure (_boxStyle_s boxStyle)
540544
541545-- | Defines a set of symbols to use to draw the outlines of boxes
542546-- C.f. https://en.wikipedia.org/wiki/Box-drawing_character