Safe Haskell | Safe-Inferred |
---|
Commands dealing with selection and cursor movement.
As is typical, when it comes to selecting events, the selection represents a half-open range. However, reflecting the orientation of events, a negative event at the start of the range won't be included, and a negative event at he end of the range will be included. This is natural for events with negative duration, since they are weighted at the end.
This behaviour is actually implemented in the low level Ui.Events functions.
Synopsis
- get_view :: Cmd.M m => ViewId -> m Sel.Selection
- lookup_view :: Ui.M m => ViewId -> m (Maybe Sel.Selection)
- set_view :: Ui.M m => ViewId -> Maybe Sel.Selection -> m ()
- set :: Cmd.M m => ViewId -> Maybe Sel.Selection -> m ()
- set_without_history :: Cmd.M m => ViewId -> Maybe Sel.Selection -> m ()
- set_selnum :: Cmd.M m => ViewId -> Sel.Num -> Maybe Sel.Selection -> m ()
- get_orientation :: Cmd.M m => m Sel.Orientation
- mmc_goto_sel :: Cmd.M m => ViewId -> Sel.Selection -> Cmd.SyncConfig -> m ()
- mmc_goto :: Cmd.SyncConfig -> RealTime.RealTime -> Midi.Message
- set_current :: Cmd.M m => Sel.Num -> Maybe Sel.Selection -> m ()
- set_subs :: Cmd.M m => ViewId -> Sel.Selection -> m ()
- set_block :: Ui.M m => BlockId -> [(TrackId, ScoreTime.TrackTime)] -> m ()
- update_orientation :: Cmd.M m => m ()
- to_point :: Cmd.M m => Bool -> m ()
- find_at_before :: Ord a => a -> [a] -> Maybe a
- advance :: Cmd.M m => m ()
- data Move
- default_move :: Move
- step :: Cmd.M m => TimeStep.Direction -> Move -> m ()
- step_with :: Cmd.M m => Int -> Move -> TimeStep.TimeStep -> m ()
- shift :: Cmd.M m => Bool -> Move -> Int -> m ()
- jump_to_track :: Cmd.M m => Move -> Types.TrackNum -> m ()
- modify :: Cmd.M m => (Block.Block -> Sel.Selection -> Sel.Selection) -> m ()
- data Direction
- find_note_track :: Cmd.M m => Direction -> Bool -> m (Maybe Types.TrackNum)
- find_before :: (a -> Bool) -> [a] -> Maybe a
- get_tracks_from_selection :: Cmd.M m => Bool -> Direction -> m [Ui.TrackInfo]
- cmd_track_all :: Cmd.M m => m ()
- select_track_all :: ScoreTime.TrackTime -> Types.TrackNum -> Sel.Selection -> Sel.Selection
- cmd_toggle_extend_tracks :: Cmd.M m => m ()
- cmd_select_track :: Cmd.M m => Types.MouseButton -> Msg.Msg -> m ()
- select_tracks :: Cmd.M m => ViewId -> Types.TrackNum -> Types.TrackNum -> m ()
- select_until_end :: ScoreTime.TrackTime -> Sel.Selection -> Sel.Selection
- cmd_mouse_selection :: Cmd.M m => Types.MouseButton -> Bool -> Msg.Msg -> m ()
- cmd_snap_selection :: Cmd.M m => Types.MouseButton -> Bool -> Msg.Msg -> m ()
- mouse_drag_pos :: Cmd.M m => Types.MouseButton -> Msg.Msg -> m ((Types.TrackNum, ScoreTime.TrackTime), (Types.TrackNum, ScoreTime.TrackTime))
- mouse_drag :: Cmd.M m => Types.MouseButton -> Msg.Msg -> m ((Types.TrackNum, UiMsg.Track), (Types.TrackNum, UiMsg.Track))
- set_and_scroll :: Cmd.M m => ViewId -> Sel.Selection -> m ()
- auto_scroll :: Cmd.M m => ViewId -> Maybe Sel.Selection -> Sel.Selection -> m ()
- auto_time_scroll :: Block.View -> Maybe ScoreTime.TrackTime -> ScoreTime.TrackTime -> ScoreTime.TrackTime
- auto_track_scroll :: Block.Block -> Block.View -> Sel.Selection -> Types.Width
- mouse_mod :: Msg.Msg -> Maybe (Bool, Cmd.Modifier, (Types.TrackNum, UiMsg.Track))
- step_from :: Cmd.M m => Types.TrackNum -> ScoreTime.TrackTime -> Int -> TimeStep.TimeStep -> m ScoreTime.TrackTime
- relevant_ruler :: Block.Block -> Types.TrackNum -> Maybe RulerId
- sel_point :: Sel.Selection -> ScoreTime.TrackTime
- sel_point_track :: Sel.Selection -> Types.TrackNum
- type Point = (BlockId, Types.TrackNum, TrackId, ScoreTime.TrackTime)
- type AnyPoint = (BlockId, Types.TrackNum, ScoreTime.TrackTime)
- get_insert :: Cmd.M m => m Point
- lookup_insert :: Cmd.M m => m (Maybe Point)
- lookup_selnum_insert :: Cmd.M m => Sel.Num -> m (Maybe (ViewId, Point))
- get_any_insert :: Cmd.M m => m (ViewId, AnyPoint)
- lookup_any_insert :: Cmd.M m => m (Maybe (ViewId, AnyPoint))
- lookup_any_selnum_insert :: Cmd.M m => Sel.Num -> m (Maybe (ViewId, AnyPoint))
- lookup_block_insert :: Ui.M m => BlockId -> m (Maybe Point)
- sel_track :: Ui.M m => BlockId -> Sel.Selection -> m (Maybe TrackId)
- data Context = Context {}
- ctx_view_selection :: Context -> (ViewId, Sel.Selection)
- context :: Cmd.M m => m Context
- context_selnum :: Cmd.M m => Sel.Num -> m Context
- lookup_context :: Cmd.M m => m (Maybe Context)
- lookup_context_selnum :: Cmd.M m => Sel.Num -> m (Maybe Context)
- get :: Cmd.M m => m Sel.Selection
- lookup :: Cmd.M m => m (Maybe Sel.Selection)
- get_view_sel :: Cmd.M m => m (ViewId, Sel.Selection)
- range :: Cmd.M m => m Events.Range
- point :: Cmd.M m => m ScoreTime.TrackTime
- start :: Cmd.M m => m ScoreTime.TrackTime
- end :: Cmd.M m => m ScoreTime.TrackTime
- realtime :: Cmd.M m => m (BlockId, RealTime.RealTime, RealTime.RealTime)
- root_realtime :: Cmd.M m => BlockId -> Maybe TrackId -> ScoreTime.ScoreTime -> m (Maybe RealTime.RealTime)
- get_root_insert :: Cmd.M m => m Point
- relative_realtime :: Cmd.M m => BlockId -> m (RealTime.RealTime, RealTime.RealTime)
- local_realtime :: Cmd.M m => m (BlockId, RealTime.RealTime, RealTime.RealTime)
- relative_realtime_point :: Msg.Performance -> Maybe Point -> Point -> RealTime.RealTime
- point_to_real :: Transport.TempoFunction -> Maybe Point -> RealTime.RealTime
- type SelectedAround = [(TrackId, ([Event.Event], [Event.Event], [Event.Event]))]
- type SelectedEvents = [(TrackId, [Event.Event])]
- around_to_events :: SelectedAround -> SelectedEvents
- events :: Cmd.M m => m SelectedEvents
- ctx_events :: Ui.M m => Context -> m SelectedEvents
- track_events :: Cmd.M m => m (TrackId, [Event.Event])
- ctx_track_events :: Ui.M m => Context -> m (TrackId, [Event.Event])
- events_around :: Cmd.M m => m SelectedAround
- events_at_point :: Cmd.M m => m SelectedEvents
- ctx_events_around :: Ui.M m => Context -> m SelectedAround
- split_events_around :: Sel.Selection -> Events.Events -> ([Event.Event], [Event.Event], [Event.Event])
- select_neighbor :: Sel.Selection -> ([Event.Event], [Event.Event]) -> ([Event.Event], [Event.Event], [Event.Event])
- opposite_neighbor :: Cmd.M m => m [(TrackId, Event.Event)]
- select_opposite_neighbor :: ScoreTime.ScoreTime -> Types.Orientation -> Events.Events -> Maybe Event.Event
- type Tracks = (BlockId, [Types.TrackNum], [TrackId], Events.Range)
- tracks :: Cmd.M m => m Tracks
- track_ids :: Cmd.M m => m [TrackId]
- tracknums :: Cmd.M m => m (BlockId, [Types.TrackNum])
- event_track :: Cmd.M m => m (BlockId, TrackId)
- ctx_event_track :: Ui.M m => Context -> m (BlockId, TrackId)
- track :: Cmd.M m => m (BlockId, Maybe TrackId)
- ctx_track :: Ui.M m => Context -> m (BlockId, Maybe TrackId)
- ctx_tracks :: Ui.M m => Context -> m Tracks
- ctx_strict_tracks :: Ui.M m => Context -> m Tracks
- tracknums_of :: Block.Block -> [TrackId] -> [(Types.TrackNum, TrackId)]
- keep_history :: Int
- record_history :: Cmd.M m => m ()
- previous_selection :: Cmd.M m => Bool -> m ()
- next_selection :: Cmd.M m => Bool -> m ()
- modify_history :: Cmd.M m => (Cmd.SelectionHistory -> Cmd.SelectionHistory) -> m ()
cmds
lookup_view :: Ui.M m => ViewId -> m (Maybe Sel.Selection) Source #
set :: Cmd.M m => ViewId -> Maybe Sel.Selection -> m () Source #
Set or unset the selection.
This is the Cmd level of Ui.set_selection and should be called by any Cmd that wants to set the selection.
The insert selnum always has an orientation, so if Sel.orientation
is
Sel.None
, default to Cmd.state_note_orientation
. Otherwise, update
the note orientation, so the visible orientation and actual orientation stay
in sync.
set_without_history :: Cmd.M m => ViewId -> Maybe Sel.Selection -> m () Source #
set_selnum :: Cmd.M m => ViewId -> Sel.Num -> Maybe Sel.Selection -> m () Source #
get_orientation :: Cmd.M m => m Sel.Orientation Source #
mmc_goto_sel :: Cmd.M m => ViewId -> Sel.Selection -> Cmd.SyncConfig -> m () Source #
set_current :: Cmd.M m => Sel.Num -> Maybe Sel.Selection -> m () Source #
Set a selection in the current view.
set_subs :: Cmd.M m => ViewId -> Sel.Selection -> m () Source #
For point selections, set a play position selection on the equivalent time in sub-blocks. This makes it easier to edit the super-block relative to the sub-block.
TODO if multiple calls overlap, I should draw multiple selections, but Ui.set_selection doesn't support that, even though the underlying BlockC.set_selection does.
modify existing selection
update_orientation :: Cmd.M m => m () Source #
Update the selection's orientation to match Cmd.state_note_orientation
.
to_point :: Cmd.M m => Bool -> m () Source #
Collapse the selection to a point at its (cur_track, cur_pos).
find_at_before :: Ord a => a -> [a] -> Maybe a Source #
advance :: Cmd.M m => m () Source #
Advance the insert selection by the current step, which is a popular thing to do.
How to move a selection.
default_move :: Move Source #
Use this Move mode when you don't have a more specific idea.
step :: Cmd.M m => TimeStep.Direction -> Move -> m () Source #
Advance the given selection by the current step.
The selection will maintain its current track span, be set to a point, and advance to the next relevant mark. "next relevant mark" is the next visible mark in the ruler to the left.
shift :: Cmd.M m => Bool -> Move -> Int -> m () Source #
Move the selection across tracks by shift
, possibly skipping non-event
tracks and collapsed tracks.
jump_to_track :: Cmd.M m => Move -> Types.TrackNum -> m () Source #
modify :: Cmd.M m => (Block.Block -> Sel.Selection -> Sel.Selection) -> m () Source #
find_note_track :: Cmd.M m => Direction -> Bool -> m (Maybe Types.TrackNum) Source #
find_before :: (a -> Bool) -> [a] -> Maybe a Source #
Find the element before the predicate matches, or the last element if it never matches.
get_tracks_from_selection Source #
:: Cmd.M m | |
=> Bool | If True, start from the R or
L edge of the selection, rather than |
-> Direction | |
-> m [Ui.TrackInfo] |
Get tracks either starting from the right of the selection, or the left. Unselectable tracks are omitted.
cmd_track_all :: Cmd.M m => m () Source #
Progressive selection: select the rest of the track, then the entire track, then the whole block.
TrackNum 0, assumed to be a ruler, is omitted, since selecting the ruler is not only not useful, it tends to make cmds that want to get a TrackId abort.
select_track_all :: ScoreTime.TrackTime -> Types.TrackNum -> Sel.Selection -> Sel.Selection Source #
cmd_toggle_extend_tracks :: Cmd.M m => m () Source #
Extend the selection horizontally to encompass all tracks. If it already does, reset the track selection to the previous one.
set selection from clicks
cmd_select_track :: Cmd.M m => Types.MouseButton -> Msg.Msg -> m () Source #
Select clicked on track.
select_tracks :: Cmd.M m => ViewId -> Types.TrackNum -> Types.TrackNum -> m () Source #
select_until_end :: ScoreTime.TrackTime -> Sel.Selection -> Sel.Selection Source #
Extend the selection to the end of then block. This sets Sel.start_pos
,
with the assumption that Sel.cur_pos
is onscreen. This is so
auto_scroll
won't jump to the bottom of the block.
cmd_mouse_selection :: Cmd.M m => Types.MouseButton -> Bool -> Msg.Msg -> m () Source #
Set the selection based on a click or drag.
cmd_snap_selection :: Cmd.M m => Types.MouseButton -> Bool -> Msg.Msg -> m () Source #
Like cmd_mouse_selection
, but snap the selection to the current time
step.
mouse_drag_pos :: Cmd.M m => Types.MouseButton -> Msg.Msg -> m ((Types.TrackNum, ScoreTime.TrackTime), (Types.TrackNum, ScoreTime.TrackTime)) Source #
Like mouse_drag
but specialized for drags on the track.
:: Cmd.M m | |
=> Types.MouseButton | |
-> Msg.Msg | |
-> m ((Types.TrackNum, UiMsg.Track), (Types.TrackNum, UiMsg.Track)) | (mouse down at, mouse currently at) |
Get the clicked or dragged range, or abort if this isn't a drag Msg. This accepts clicks as well, and considers them an empty range.
implementation
auto scroll
set_and_scroll :: Cmd.M m => ViewId -> Sel.Selection -> m () Source #
Figure out how much to scroll to keep the selection visible and with reasonable space around it.
Anyone who wants to set a selection and automatically scroll the window to follow the selection should use this function.
auto_scroll :: Cmd.M m => ViewId -> Maybe Sel.Selection -> Sel.Selection -> m () Source #
If the selection has scrolled off the edge of the window, automatically scroll it so that the "current" end of the selection is in view.
auto_time_scroll :: Block.View -> Maybe ScoreTime.TrackTime -> ScoreTime.TrackTime -> ScoreTime.TrackTime Source #
auto_track_scroll :: Block.Block -> Block.View -> Sel.Selection -> Types.Width Source #
Find the track scroll that would put the given selection into view.
mouse
mouse_mod :: Msg.Msg -> Maybe (Bool, Cmd.Modifier, (Types.TrackNum, UiMsg.Track)) Source #
(mouse_down, mouse_modifier, (mouse_track, mouse_pos))
util
step_from :: Cmd.M m => Types.TrackNum -> ScoreTime.TrackTime -> Int -> TimeStep.TimeStep -> m ScoreTime.TrackTime Source #
relevant_ruler :: Block.Block -> Types.TrackNum -> Maybe RulerId Source #
Get the ruler that applies to the given track. Search left for the closest ruler that has all the given marklist names. This includes ruler tracks and the rulers of event tracks.
get selection info
sel_point :: Sel.Selection -> ScoreTime.TrackTime Source #
Get the "point" position of a Selection.
sel_point_track :: Sel.Selection -> Types.TrackNum Source #
When multiple tracks are selected, only one can be the point. This
is Sel.cur_track
, and in fact must be, because Sel.start_track
may
be an invalid tracknum. That is so a selection can maintain its shape even
if it momentarily goes out of bounds.
type Point = (BlockId, Types.TrackNum, TrackId, ScoreTime.TrackTime) Source #
A point on a track.
type AnyPoint = (BlockId, Types.TrackNum, ScoreTime.TrackTime) Source #
get_insert :: Cmd.M m => m Point Source #
Get the "insert position", which is the start track and position of the insert selection. Abort if it's not an event track.
get_any_insert :: Cmd.M m => m (ViewId, AnyPoint) Source #
Return the leftmost tracknum and trackpos, even if it's not an event track.
lookup_any_selnum_insert :: Cmd.M m => Sel.Num -> m (Maybe (ViewId, AnyPoint)) Source #
The most general insertion point function.
lookup_block_insert :: Ui.M m => BlockId -> m (Maybe Point) Source #
Given a block, get the selection on it, if any. If there are multiple views, take the one with the alphabetically first ViewId.
I'm not sure how to choose, but the first one seems reasonable for now.
sel_track :: Ui.M m => BlockId -> Sel.Selection -> m (Maybe TrackId) Source #
Get the point track of a selection.
plain Selection
The selection is in the Ui.State, but focused view is in Cmd.State. Extracting it out lets me depend only on Ui.M, not Cmd.M. Also it decouples selection functions from the current Ui.State and Cmd.State.
Context | |
|
ctx_view_selection :: Context -> (ViewId, Sel.Selection) Source #
get :: Cmd.M m => m Sel.Selection Source #
get_view_sel :: Cmd.M m => m (ViewId, Sel.Selection) Source #
range :: Cmd.M m => m Events.Range Source #
point :: Cmd.M m => m ScoreTime.TrackTime Source #
start :: Cmd.M m => m ScoreTime.TrackTime Source #
end :: Cmd.M m => m ScoreTime.TrackTime Source #
selections in RealTime
realtime :: Cmd.M m => m (BlockId, RealTime.RealTime, RealTime.RealTime) Source #
Get the real time range of the focused selection. If there's a root
block, then it will be in relative to that root, otherwise it's equivalent
to local_realtime
.
root_realtime :: Cmd.M m => BlockId -> Maybe TrackId -> ScoreTime.ScoreTime -> m (Maybe RealTime.RealTime) Source #
RealTime of the given ScoreTime, relative to the root block. This is the closest we get to an absolute real time.
get_root_insert :: Cmd.M m => m Point Source #
This is like get_insert
, except get the selection on the root block,
falling back to the current one if there is none.
relative_realtime :: Cmd.M m => BlockId -> m (RealTime.RealTime, RealTime.RealTime) Source #
Get the current selection in RealTime relative to another block.
If a block is called in multiple places, a score time on it may occur at multiple real times. Pick the real time from the given selection which is closest to the real time of the selection on the given root block.
If there's no selection on the root block then return the RealTime from the block's first occurrance.
local_realtime :: Cmd.M m => m (BlockId, RealTime.RealTime, RealTime.RealTime) Source #
Get the RealTime range of the current selection, as derived from current selection's block. This means that the top should be 0.
relative_realtime_point :: Msg.Performance -> Maybe Point -> Point -> RealTime.RealTime Source #
This is like relative_realtime
but gets a RealTime relative to a Point,
not a range.
select events
type SelectedAround = [(TrackId, ([Event.Event], [Event.Event], [Event.Event]))] Source #
Selected events per track. Gives events before, within, and after the selection. As usual, previous events are in descending order.
type SelectedEvents = [(TrackId, [Event.Event])] Source #
events :: Cmd.M m => m SelectedEvents Source #
All selected events. events_around
is the default selection behaviour.
ctx_events :: Ui.M m => Context -> m SelectedEvents Source #
track_events :: Cmd.M m => m (TrackId, [Event.Event]) Source #
Like events
, but only for the sel_point_track
.
ctx_track_events :: Ui.M m => Context -> m (TrackId, [Event.Event]) Source #
events_around :: Cmd.M m => m SelectedAround Source #
events_at_point :: Cmd.M m => m SelectedEvents Source #
Get events exactly at the point. This gets both positive and negative events, so each track may have up to 2 events.
ctx_events_around :: Ui.M m => Context -> m SelectedAround Source #
Get events in the selection, but if no events are selected, expand it
to include a neighboring event, as documented in select_neighbor
.
Normally the range is half-open by event orientation, so a positive event at the end of the selection won't be included. But there's a special hack where if the end of the selection happens to be the end of the block, a positive event there will be included anyway. Otherwise it's annoying to select a final event (unless it's negative).
This is the standard definition of a selection, and should be used in all standard selection using commands.
split_events_around :: Sel.Selection -> Events.Events -> ([Event.Event], [Event.Event], [Event.Event]) Source #
select_neighbor :: Sel.Selection -> ([Event.Event], [Event.Event]) -> ([Event.Event], [Event.Event], [Event.Event]) Source #
opposite_neighbor :: Cmd.M m => m [(TrackId, Event.Event)] Source #
This is similar to events_around
, except that the direction is reversed:
it favors the next positive event, or the previous negative one. Also this
assumes a point selection and only selects one event per track.
select_opposite_neighbor :: ScoreTime.ScoreTime -> Types.Orientation -> Events.Events -> Maybe Event.Event Source #
select tracks
type Tracks = (BlockId, [Types.TrackNum], [TrackId], Events.Range) Source #
Per-track selection info.
The TrackNums are sorted, and the TrackIds are likewise in left-to-right order. Only TrackNums for event tracks are returned, so both lists should have the same length and correspond if you zip them up.
tracks :: Cmd.M m => m Tracks Source #
Get selected event tracks along with the selection. The tracks are returned in ascending order. Only event tracks are returned, and tracks merged into the selected tracks are included.
ctx_strict_tracks :: Ui.M m => Context -> m Tracks Source #
Selected tracks, not including merged tracks.
tracknums_of :: Block.Block -> [TrackId] -> [(Types.TrackNum, TrackId)] Source #
history
keep_history :: Int Source #
Keep only this many selection history entries. This is hardcoded and low since I'm probably not interested in ancient selections.
record_history :: Cmd.M m => m () Source #
previous_selection :: Cmd.M m => Bool -> m () Source #
next_selection :: Cmd.M m => Bool -> m () Source #
modify_history :: Cmd.M m => (Cmd.SelectionHistory -> Cmd.SelectionHistory) -> m () Source #