Skip to content

Commit 5682975

Browse files
authored
Merge pull request #147 from TuongNM/selections-out-of-bounds
Prevent Timeline selections that are out of bounds
2 parents 116df59 + 52b6540 commit 5682975

3 files changed

Lines changed: 52 additions & 30 deletions

File tree

GUI/EventsView.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ drawEvents EventsView{drawArea, adj}
331331
selected = cursorPos == n
332332
(state1, state2)
333333
| inside = (StateSelected, StateSelected)
334-
| selected = (state, state)
334+
| selected = (StateSelected, state)
335335
| otherwise = (state, StateNormal)
336336
]
337337

GUI/Main.hs

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -350,37 +350,21 @@ eventLoop uienv@UIEnv{..} eventlogState = do
350350
dispatch (EventCursorChangedIndex cursorPos') EventlogLoaded{hecs} = do
351351
let cursorTs' = eventIndexToTimestamp hecs cursorPos'
352352
selection' = PointSelection cursorTs'
353-
timelineSetSelection timelineWin selection'
354-
eventsViewSetCursor eventsView cursorPos' Nothing
355-
continueWith eventlogState {
356-
selection = selection',
357-
cursorPos = cursorPos'
358-
}
353+
mselection <- timelineSetSelection timelineWin selection'
354+
setSelection cursorPos' Nothing mselection
359355

360356
dispatch (EventCursorChangedSelection selection'@(PointSelection cursorTs'))
361357
EventlogLoaded{hecs} = do
362358
let cursorPos' = timestampToEventIndex hecs cursorTs'
363-
timelineSetSelection timelineWin selection'
364-
eventsViewSetCursor eventsView cursorPos' Nothing
365-
histogramViewSetInterval histogramView Nothing
366-
summaryViewSetInterval summaryView Nothing
367-
continueWith eventlogState {
368-
selection = selection',
369-
cursorPos = cursorPos'
370-
}
359+
mselection <- timelineSetSelection timelineWin selection'
360+
setSelection cursorPos' Nothing mselection
371361

372362
dispatch (EventCursorChangedSelection selection'@(RangeSelection start end))
373363
EventlogLoaded{hecs} = do
374364
let cursorPos' = timestampToEventIndex hecs start
375365
mrange = Just (cursorPos', timestampToEventIndex hecs end)
376-
timelineSetSelection timelineWin selection'
377-
eventsViewSetCursor eventsView cursorPos' mrange
378-
histogramViewSetInterval histogramView (Just (start, end))
379-
summaryViewSetInterval summaryView (Just (start, end))
380-
continueWith eventlogState {
381-
selection = selection',
382-
cursorPos = cursorPos'
383-
}
366+
mselection <- timelineSetSelection timelineWin selection'
367+
setSelection cursorPos' mrange mselection
384368

385369
dispatch (EventTracesChanged traces) _ = do
386370
timelineWindowSetTraces timelineWin traces
@@ -435,6 +419,24 @@ eventLoop uienv@UIEnv{..} eventlogState = do
435419
async doing action =
436420
forkIO (action `catch` \e -> post (EventUserError doing e))
437421

422+
setSelection cursorPos' _ (Just selection'@(PointSelection _)) = do
423+
eventsViewSetCursor eventsView cursorPos' Nothing
424+
histogramViewSetInterval histogramView Nothing
425+
summaryViewSetInterval summaryView Nothing
426+
continueWith eventlogState {
427+
selection = selection',
428+
cursorPos = cursorPos'
429+
}
430+
setSelection cursorPos' mrange (Just selection'@(RangeSelection start end)) = do
431+
eventsViewSetCursor eventsView cursorPos' mrange
432+
histogramViewSetInterval histogramView (Just (start, end))
433+
summaryViewSetInterval summaryView (Just (start, end))
434+
continueWith eventlogState {
435+
selection = selection',
436+
cursorPos = cursorPos'
437+
}
438+
setSelection _ _ Nothing = continue
439+
438440
post = postEvent eventQueue
439441
continue = continueWith eventlogState
440442
continueWith = return . Right

GUI/Timeline.hs

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import Events.HECs
3636
import Graphics.UI.Gtk
3737

3838
import Data.IORef
39+
import Data.Ord
3940
import Control.Monad
4041
import Control.Monad.Trans
4142
import qualified Data.Text as T
@@ -384,10 +385,25 @@ updateTimelineHPageSize TimelineState{..} = do
384385
-------------------------------------------------------------------------------
385386
-- Cursor / selection and mouse interaction
386387

387-
timelineSetSelection :: TimelineView -> TimeSelection -> IO ()
388+
timelineSetSelection :: TimelineView -> TimeSelection -> IO (Maybe TimeSelection)
388389
timelineSetSelection TimelineView{..} selection = do
389-
writeIORef selectionRef selection
390-
queueRedrawTimelines timelineState
390+
mhecs <- readIORef hecsIORef
391+
case mhecs >>= (adjustSelection selection . hecLastEventTime) of
392+
Nothing -> return Nothing
393+
Just selection' -> do
394+
writeIORef selectionRef selection'
395+
queueRedrawTimelines timelineState
396+
return $ Just selection'
397+
where
398+
-- Prevent selections that are out of bounds.
399+
adjustSelection (PointSelection timestamp) lastTx
400+
| timestamp < 0 || timestamp > lastTx = Nothing
401+
| otherwise = Just $ PointSelection timestamp
402+
adjustSelection (RangeSelection start end) lastTx
403+
| start < 0 && end < 0 || start > lastTx && end > lastTx = Nothing
404+
| otherwise = Just $ RangeSelection (clampSelection lastTx start) (clampSelection lastTx end)
405+
406+
clampSelection lastTx = clamp (0, lastTx)
391407

392408
-- little state machine
393409
data MouseState = None
@@ -402,8 +418,10 @@ mousePress view@TimelineView{..} state button x =
402418
case (state, button) of
403419
(None, LeftButton) -> do xv <- viewPointToTime view x
404420
-- update the view without notifying the client
405-
timelineSetSelection view (PointSelection xv)
406-
return (PressLeft x)
421+
selection <- timelineSetSelection view (PointSelection xv)
422+
case selection of
423+
Nothing -> return None
424+
Just _ -> return (PressLeft x)
407425
(None, MiddleButton) -> do widgetSetCursor timelineDrawingArea (Just cursorMove)
408426
v <- adjustmentGetValue timelineAdj
409427
return (DragMiddle x v)
@@ -424,8 +442,10 @@ mouseMove view@TimelineView{..} state x =
424442
dragThreshold = abs (x - x0) > 5
425443
DragLeft x0 -> do (xv, xv') <- viewRangeToTimeRange view (x0, x)
426444
-- update the view without notifying the client
427-
timelineSetSelection view (RangeSelection xv xv')
428-
return (DragLeft x0)
445+
selection <- timelineSetSelection view (RangeSelection xv xv')
446+
case selection of
447+
Nothing -> return None
448+
Just _ -> return (DragLeft x0)
429449
DragMiddle x0 v -> do xv <- viewPointToTimeNoClamp view x
430450
xv' <- viewPointToTimeNoClamp view x0
431451
scrollTo timelineState (v + (xv' - xv))

0 commit comments

Comments
 (0)