@@ -60,6 +60,8 @@ pub fn init(ui: &AppWindow) {
6060 logic_cb ! ( video_editor_remove_tracks, ui) ;
6161 logic_cb ! ( video_editor_track_move_up, ui, index) ;
6262 logic_cb ! ( video_editor_track_move_down, ui, index) ;
63+ logic_cb ! ( video_editor_track_move_to_top, ui, index) ;
64+ logic_cb ! ( video_editor_track_move_to_bottom, ui, index) ;
6365 logic_cb ! ( video_editor_insert_video_track, ui, index) ;
6466 logic_cb ! ( video_editor_insert_audio_track, ui, index) ;
6567 logic_cb ! ( video_editor_insert_subtitle_track, ui, index) ;
@@ -257,6 +259,83 @@ fn video_editor_track_move_down(ui: &AppWindow, index: i32) {
257259 }
258260}
259261
262+ fn video_editor_track_move_to_top ( ui : & AppWindow , index : i32 ) {
263+ if index <= 0 {
264+ return ;
265+ }
266+
267+ if is_track_locked ( ui, index) {
268+ crate :: toast_warn!( ui, "Cannot move a locked track" ) ;
269+ return ;
270+ }
271+
272+ let idx = index as usize ;
273+
274+ let result = with_history_manager ( |state| {
275+ if idx >= state. tracks_manager . len ( ) {
276+ return Err (
277+ video_editor:: Error :: IndexOutOfBounds ( idx, state. tracks_manager . len ( ) ) . into ( ) ,
278+ ) ;
279+ }
280+
281+ let command = MoveTrackCommand :: new ( idx, 0 ) ;
282+ state
283+ . history_manager
284+ . execute ( & mut state. tracks_manager , Box :: new ( command) )
285+ } ) ;
286+
287+ match result {
288+ Ok ( execute_result) => {
289+ sync_manager_to_ui ( ui) ;
290+ if execute_result. affected_segments . tracks_changed {
291+ refresh_preview ( ui) ;
292+ }
293+ crate :: toast_success!( ui, format!( "Moved track from {} to top" , index) ) ;
294+ }
295+ Err ( e) => crate :: toast_warn!( ui, e. to_string( ) ) ,
296+ }
297+ }
298+
299+ fn video_editor_track_move_to_bottom ( ui : & AppWindow , index : i32 ) {
300+ if is_track_locked ( ui, index) {
301+ crate :: toast_warn!( ui, "Cannot move a locked track" ) ;
302+ return ;
303+ }
304+
305+ let idx = index as usize ;
306+
307+ let result = with_history_manager ( |state| {
308+ if idx >= state. tracks_manager . len ( ) {
309+ return Err (
310+ video_editor:: Error :: IndexOutOfBounds ( idx, state. tracks_manager . len ( ) ) . into ( ) ,
311+ ) ;
312+ }
313+
314+ let last_idx = state. tracks_manager . len ( ) - 1 ;
315+ if idx == last_idx {
316+ return Ok ( ExecuteResult {
317+ affected_segments : Default :: default ( ) ,
318+ } ) ;
319+ }
320+
321+ let command = MoveTrackCommand :: new ( idx, last_idx) ;
322+ state
323+ . history_manager
324+ . execute ( & mut state. tracks_manager , Box :: new ( command) )
325+ } ) ;
326+
327+ match result {
328+ Ok ( execute_result) => {
329+ sync_manager_to_ui ( ui) ;
330+ if execute_result. affected_segments . tracks_changed {
331+ refresh_preview ( ui) ;
332+ }
333+ crate :: toast_success!( ui, format!( "Moved track from {} to bottom" , index) ) ;
334+ }
335+ Err ( e) => crate :: toast_warn!( ui, e. to_string( ) ) ,
336+ }
337+ }
338+
260339fn video_editor_insert_video_track ( ui : & AppWindow , index : i32 ) {
261340 insert_track_by_type ( ui, index, UIVideoEditorTrackType :: Video ) ;
262341}
0 commit comments