Skip to content

Commit 52b6540

Browse files
committed
Prevent Timeline selections that are out of bounds
timelineSetSelection now returns Nothing in case of an invalid selection that's solely outside of the TimelineView for both a PointSelection and a RangeSelection. A RangeSelection is additionally clamped to the bounds of the TimelineView to stop dragging when the bounds have been reached. The new return value is processed inside the Mouse and Event handling accordingly. Within this the EventCursorChangedIndex handling now includes updating previously omitted views. This fixes an issue where following a RangeSelection with a selection inside the EventsView would cause the previously omitted views to still display the information of the RangeSelection and not the equivalent PointSelection of the EventsView selection. Lastly, fix an issue from the previous commit that added styling usage inside the EventsView. The wrong background color was applied to a selected Event when making the second PointSelection after a RangeSelection or a PointSelection without a preceding RangeSelection. StateSelected is now always applied when selected.
1 parent 4743265 commit 52b6540

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
@@ -37,6 +37,7 @@ import Graphics.UI.Gtk
3737
import Graphics.Rendering.Cairo ( liftIO )
3838

3939
import Data.IORef
40+
import Data.Ord
4041
import Control.Monad
4142
import Control.Monad.Trans
4243
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)