File: Motion.hs

package info (click to toggle)
threadscope 0.2.14.1-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 580 kB
  • sloc: haskell: 5,457; ansic: 10; makefile: 7
file content (134 lines) | stat: -rw-r--r-- 5,195 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
module GUI.Timeline.Motion (
    zoomIn, zoomOut, zoomToFit,
    scrollLeft, scrollRight, scrollToBeginning, scrollToEnd, scrollTo, centreOnCursor,
    vscrollDown, vscrollUp,
  ) where

import GUI.Timeline.Types
import GUI.Timeline.Sparks
import Events.HECs

import Graphics.UI.Gtk

import Data.IORef
import Control.Monad
-- import Text.Printf
-- import Debug.Trace

-------------------------------------------------------------------------------
-- Zoom in works by expanding the current view such that the
-- left hand edge of the original view remains at the same
-- position and the zoom in factor is 2.
-- For example, zoom into the time range 1.0 3.0
-- produces a new view with the time range 1.0 2.0

zoomIn :: TimelineState -> Timestamp -> IO ()
zoomIn  = zoom (/2)

zoomOut :: TimelineState -> Timestamp -> IO ()
zoomOut  = zoom (*2)

zoom :: (Double -> Double) -> TimelineState -> Timestamp -> IO ()
zoom factor TimelineState{timelineAdj, scaleIORef} cursor = do
  scaleValue <- readIORef scaleIORef
  -- TODO: we'd need HECs, as below, to fit maxScale to graphs at hand
  let maxScale = 10000000000  -- big enough for hours of eventlogs
      clampedFactor =
        if factor scaleValue < 0.2 || factor scaleValue > maxScale
        then id
        else factor
      newScaleValue = clampedFactor scaleValue
  writeIORef scaleIORef newScaleValue

  hadj_value <- adjustmentGetValue timelineAdj
  hadj_pagesize <- adjustmentGetPageSize timelineAdj -- Get size of bar

  let newPageSize = clampedFactor hadj_pagesize
  adjustmentSetPageSize timelineAdj newPageSize

  let cursord = fromIntegral cursor
  when (cursord >= hadj_value && cursord < hadj_value + hadj_pagesize) $
    adjustmentSetValue timelineAdj $
        cursord - clampedFactor (cursord - hadj_value)

  let pageshift = 0.9 * newPageSize
  let nudge     = 0.1 * newPageSize

  adjustmentSetStepIncrement timelineAdj nudge
  adjustmentSetPageIncrement timelineAdj pageshift

-------------------------------------------------------------------------------

zoomToFit :: TimelineState -> Maybe HECs -> IO ()
zoomToFit TimelineState{scaleIORef, maxSpkIORef,timelineAdj,
                        timelineDrawingArea} mb_hecs = do
  case mb_hecs of
    Nothing   -> return ()
    Just hecs -> do
      let lastTx = hecLastEventTime hecs
          upper = fromIntegral lastTx
          lower = 0
      (w, _) <- widgetGetSize timelineDrawingArea
      let newScaleValue = upper / fromIntegral w
          (sliceAll, profAll) = treesProfile newScaleValue 0 lastTx hecs
          -- TODO: verify that no empty lists possible below
          maxmap l = maximum (0 : map (maxSparkRenderedValue sliceAll) l)
          maxAll = map maxmap profAll
          newMaxSpkValue = maximum (0 : maxAll)

      writeIORef scaleIORef newScaleValue
      writeIORef maxSpkIORef newMaxSpkValue

      -- Configure the horizontal scrollbar units to correspond to micro-secs.
      adjustmentSetLower    timelineAdj lower
      adjustmentSetValue    timelineAdj lower
      adjustmentSetUpper    timelineAdj upper
      adjustmentSetPageSize timelineAdj upper
      -- TODO: this seems suspicious:
      adjustmentSetStepIncrement timelineAdj 0
      adjustmentSetPageIncrement timelineAdj 0

-------------------------------------------------------------------------------

scrollLeft, scrollRight, scrollToBeginning, scrollToEnd :: TimelineState -> IO ()

scrollLeft        = scroll (\val page l _ -> l `max` (val - page/2))
scrollRight       = scroll (\val page _ u -> (u - page) `min` (val + page/2))
scrollToBeginning = scroll (\_   _    l _ ->  l)
scrollToEnd       = scroll (\_   _    _ u ->  u)

scrollTo :: TimelineState -> Double -> IO ()
scrollTo s x      = scroll (\_   _    _ _ ->  x) s

centreOnCursor :: TimelineState -> Timestamp -> IO ()

centreOnCursor state cursor =
  scroll (\_ page l _u -> max l (fromIntegral cursor - page/2)) state

scroll :: (Double -> Double -> Double -> Double -> Double)
       -> TimelineState -> IO ()
scroll adjust TimelineState{timelineAdj} = do
  hadj_value <- adjustmentGetValue timelineAdj
  hadj_pagesize <- adjustmentGetPageSize timelineAdj
  hadj_lower <- adjustmentGetLower timelineAdj
  hadj_upper <- adjustmentGetUpper timelineAdj
  let newValue = adjust hadj_value hadj_pagesize hadj_lower hadj_upper
      newValue' = max hadj_lower (min (hadj_upper - hadj_pagesize) newValue)
  adjustmentSetValue timelineAdj newValue'

vscrollDown, vscrollUp :: TimelineState -> IO ()
vscrollDown = vscroll (\val page _l  u -> (u - page) `min` (val + page/8))
vscrollUp   = vscroll (\val page  l _u -> l `max` (val - page/8))

vscroll :: (Double -> Double -> Double -> Double -> Double)
        -> TimelineState -> IO ()
vscroll adjust TimelineState{timelineVAdj} = do
  hadj_value <- adjustmentGetValue timelineVAdj
  hadj_pagesize <- adjustmentGetPageSize timelineVAdj
  hadj_lower <- adjustmentGetLower timelineVAdj
  hadj_upper <- adjustmentGetUpper timelineVAdj
  let newValue = adjust hadj_value hadj_pagesize hadj_lower hadj_upper
  adjustmentSetValue timelineVAdj newValue
  adjustmentValueChanged timelineVAdj

-- -----------------------------------------------------------------------------