bool FruityPerfInput::on_button_press_event (GdkEventButton * ev, perfroll & roll) { bool result = false; perform & p = roll.perf(); roll.grab_focus(); int & dropseq = roll.m_drop_sequence; /* reference needed */ sequence * seq = p.get_sequence(dropseq); if (p.is_active(dropseq)) { seq->unselect_triggers(); roll.draw_all(); } else { return false; } roll.m_drop_x = int(ev->x); roll.m_drop_y = int(ev->y); m_current_x = int(ev->x); m_current_y = int(ev->y); roll.convert_xy /* side-effects */ ( roll.m_drop_x, roll.m_drop_y, roll.m_drop_tick, dropseq ); if (SEQ64_CLICK_LEFT(ev->button)) { result = on_left_button_pressed(ev, roll); } else if (SEQ64_CLICK_RIGHT(ev->button)) { result = on_right_button_pressed(ev, roll); } else if (SEQ64_CLICK_MIDDLE(ev->button)) /* left-ctrl???, middle */ { /* * Implements some Stazed fixes now. */ if (p.is_active(dropseq)) { midipulse droptick = roll.m_drop_tick; droptick -= droptick % roll.m_snap; /* stazed fix: grid snap */ bool state = seq->get_trigger_state(droptick); if (state) /* trigger click, split it */ { roll.split_trigger(dropseq, droptick); result = true; } else /* track click, paste trig */ { p.push_trigger_undo(dropseq); seq->paste_trigger(droptick); } } } update_mouse_pointer(roll); return result; }
bool perfnames::on_button_press_event (GdkEventButton * ev) { int y = int(ev->y); int seqnum = convert_y(y); current_seq(seqnum); if (SEQ64_CLICK_LEFT(ev->button)) { if (perf().is_active(seqnum)) { guint modifiers; /* for filtering out caps/num lock etc. */ modifiers = gtk_accelerator_get_default_mod_mask(); if ((ev->state & modifiers) == SEQ64_SHIFT_MASK) { /* * \new ca 2016-03-15 * If the Shift key is pressed, mute all other sequences. * Inactive sequences are skipped. */ for (int s = 0; s < m_sequence_max; ++s) { if (s != seqnum) { sequence * seq = perf().get_sequence(s); if (not_nullptr(seq)) { bool muted = seq->get_song_mute(); seq->set_song_mute(! muted); } } } } else { sequence * seq = perf().get_sequence(seqnum); bool muted = seq->get_song_mute(); seq->set_song_mute(! muted); } enqueue_draw(); } } return true; }
bool Seq24PerfInput::on_button_release_event (GdkEventButton * ev, perfroll & roll) { bool result = false; if (SEQ64_CLICK_LEFT(ev->button)) { if (is_adding()) set_adding_pressed(false); } else if (SEQ64_CLICK_RIGHT(ev->button)) { /* * Minor new feature. If the Super (Mod4, Windows) key is * pressed when release, keep the adding-state in force. One * can then use the unadorned left-click key to add material. Right * click to reset the adding mode. This feature is enabled only * if allowed by Options / Mouse (but is true by default). * See the same code in seq24seqroll.cpp. */ bool addmode_exit = ! rc().allow_mod4_mode(); if (! addmode_exit) addmode_exit = ! is_super_key(ev); /* Mod4 held? */ if (addmode_exit) { set_adding_pressed(false); activate_adding(false, roll); } } perform & p = roll.perf(); roll.m_moving = roll.m_growing = false; set_adding_pressed(false); m_effective_tick = 0; if (p.is_active(roll.m_drop_sequence)) { roll.draw_all(); } return result; }
bool FruitySeqEventInput::on_button_release_event ( GdkEventButton * ev, seqevent & seqev ) { bool result = false; midipulse tick_s; midipulse tick_f; seqev.grab_focus(); seqev.m_current_x = int(ev->x) + seqev.m_scroll_offset_x;; if (seqev.m_moving || m_is_drag_pasting) seqev.snap_x(seqev.m_current_x); int delta_x = seqev.m_current_x - seqev.m_drop_x; midipulse delta_tick; if (SEQ64_CLICK_LEFT(ev->button)) { int current_x = seqev.m_current_x; midipulse t_s, t_f; seqev.snap_x(current_x); seqev.convert_x(current_x, t_s); t_f = t_s + (seqev.m_zoom); /* shift back a few ticks */ if (t_s < 0) t_s = 0; /* * Use the ctrl-left click button up for select/drag copy/paste; * use the left click button up for ending a move of selected notes. */ if (m_is_drag_pasting) { m_is_drag_pasting = false; m_is_drag_pasting_start = false; seqev.m_paste = false; /* convert deltas into screen coordinates */ seqev.m_seq.paste_selected(t_s, 0); result = true; } /* ctrl-left click but without movement - select a note */ if (m_is_drag_pasting_start) { m_is_drag_pasting_start = false; /* * If a ctrl-left click without movement and if the note under * cursor is selected, and ctrl is held and button-down, * just select one. */ if /* deselect the event? */ ( is_ctrl_key(ev) && ! m_justselected_one && seqev.m_seq.select_events ( t_s, t_f, seqev.m_status, seqev.m_cc, sequence::e_is_selected ) ) { (void) seqev.m_seq.select_events ( t_s, t_f, seqev.m_status, seqev.m_cc, sequence::e_deselect ); } } m_justselected_one = false; /* clear flag on left button up */ if (seqev.m_moving) { delta_x -= seqev.m_move_snap_offset_x; /* adjust for snap */ seqev.convert_x(delta_x, delta_tick); /* deltas to screen coords */ seqev.m_seq.move_selected_notes(delta_tick, 0); result = true; } } /* * Yet another stazed fix. :-) */ bool right = SEQ64_CLICK_RIGHT(ev->button); if (! right) right = is_ctrl_key(ev) && SEQ64_CLICK_LEFT(ev->button); if (right) { if (seqev.m_selecting) { int x, w; seqev.x_to_w(seqev.m_drop_x, seqev.m_current_x, x, w); seqev.convert_x(x, tick_s); seqev.convert_x(x + w, tick_f); (void) seqev.m_seq.select_events ( tick_s, tick_f, seqev.m_status, seqev.m_cc, sequence::e_toggle_selection ); #ifdef USE_STAZED_SELECTION_EXTENSIONS /* * Stazed fix */ if (event::is_strict_note_msg(seqev.m_status)) seqev.m_seq.select_linked(tick_s, tick_f, seqev.m_status); #endif /* * To update the select or unselect of notes by this action. * Not sure this makes sense, though. How does selection dirty * anything? */ seqev.m_seq.set_dirty(); } } seqev.m_selecting = false; /* turn it all off */ seqev.m_moving = false; seqev.m_growing = false; seqev.m_moving_init = false; seqev.m_painting = false; seqev.m_seq.unpaint_all(); seqev.update_pixmap(); /* if they clicked, something changed */ seqev.draw_pixmap_on_window(); update_mouse_pointer(seqev); return result; // true; }
bool FruitySeqEventInput::on_button_press_event ( GdkEventButton * ev, seqevent & seqev ) { bool result = false; midipulse tick_s, tick_w; seqev.grab_focus(); // NEW: I think this would be helpful seqev.convert_x(c_eventevent_x, tick_w); seqev.m_drop_x = seqev.m_current_x = int(ev->x) + seqev.m_scroll_offset_x; seqev.m_old.x = seqev.m_old.y = seqev.m_old.width = seqev.m_old.height = 0; if (seqev.m_paste) { seqev.snap_x(seqev.m_current_x); seqev.convert_x(seqev.m_current_x, tick_s); seqev.m_paste = false; seqev.m_seq.paste_selected(tick_s, 0); /* does undo/mod */ seqev.m_seq.set_dirty(); /* a stazed fix */ result = true; } else { int x, w; midipulse tick_f; if (SEQ64_CLICK_LEFT(ev->button)) /* Note 1 */ { seqev.convert_x(seqev.m_drop_x, tick_s); /* x,y into tick/note */ tick_f = tick_s + seqev.m_zoom; /* shift back some ticks */ tick_s -= tick_w; if (tick_s < 0) tick_s = 0; int eventcount = seqev.m_seq.select_events ( tick_s, tick_f, seqev.m_status, seqev.m_cc, sequence::e_would_select ); if (! is_ctrl_key(ev) && eventcount == 0) { seqev.m_painting = true; seqev.snap_x(seqev.m_drop_x); seqev.convert_x(seqev.m_drop_x, tick_s); /* x,y-->tick/note */ eventcount = seqev.m_seq.select_events ( tick_s, tick_f, seqev.m_status, seqev.m_cc, sequence::e_would_select ); if (eventcount == 0) { seqev.m_seq.push_undo(); /* add to add_event? */ seqev.drop_event(tick_s); /* m_seq.add_event() */ result = true; } } else /* selecting */ { eventcount = seqev.m_seq.select_events ( tick_s, tick_f, seqev.m_status, seqev.m_cc, sequence::e_is_selected ); if (eventcount == 0) { eventcount = seqev.m_seq.select_events ( tick_s, tick_f, seqev.m_status, seqev.m_cc, sequence::e_would_select ); if (eventcount > 0) /* if clicking event */ { if (! is_ctrl_key(ev)) seqev.m_seq.unselect(); } else /* clickempty space, unselect all if no Ctrl-Sh */ { if (! is_ctrl_shift_key(ev)) seqev.m_seq.unselect(); } /* on direct click select only one event */ eventcount = seqev.m_seq.select_events ( tick_s, tick_f, seqev.m_status, seqev.m_cc, sequence::e_select_one ); /* * Stazed fix: */ #ifdef USE_STAZED_SELECTION_EXTENSIONS if (event::is_strict_note_msg(seqev.m_status)) { seqev.m_seq.select_linked(tick_s, tick_f, seqev.m_status); seqev.m_seq.set_dirty(); } #endif if (eventcount) m_justselected_one = true; /* stop deselect on release */ /* if nothing selected, start the selection box */ if (is_ctrl_key(ev) && eventcount == 0) seqev.m_selecting = true; } eventcount = seqev.m_seq.select_events ( tick_s, tick_f, seqev.m_status, seqev.m_cc, sequence::e_is_selected ); if (eventcount > 0) /* if event under cursor selected */ { if (! is_ctrl_key(ev)) /* grab/move note */ { seqev.m_moving_init = true; int note; seqev.m_seq.get_selected_box(tick_s, note, tick_f, note); tick_f += tick_w; seqev.convert_t(tick_s, x); /* convert to X,Y values */ seqev.convert_t(tick_f, w); w -= x; /* w is coordinates now */ /* set the m_selected rectangle for x,y,w,h */ seqev.m_selected.x = x; seqev.m_selected.width = w; seqev.m_selected.y = (c_eventarea_y-c_eventevent_y) / 2; seqev.m_selected.height = c_eventevent_y; /* save offset that we get from the snap above */ int adjusted_selected_x = seqev.m_selected.x; seqev.snap_x(adjusted_selected_x); seqev.m_move_snap_offset_x = seqev.m_selected.x - adjusted_selected_x; /* align selection for drawing */ seqev.snap_x(seqev.m_selected.x); seqev.snap_x(seqev.m_current_x); seqev.snap_x(seqev.m_drop_x); } else if /* Ctrl-Left-click when stuff already selected */ ( is_ctrl_key(ev) && seqev.m_seq.select_events(tick_s, tick_f, seqev. m_status, seqev.m_cc, sequence::e_is_selected) ) { m_is_drag_pasting_start = true; } } } } if (SEQ64_CLICK_RIGHT(ev->button)) { seqev.convert_x(seqev.m_drop_x, tick_s); /* x,y in to tick/note */ tick_f = tick_s + seqev.m_zoom; /* shift back some ticks */ tick_s -= (tick_w); if (tick_s < 0) tick_s = 0; /* * Stazed fix: don't allow individual deletion of Note On/Off * events. Should we do the same for AfterTouch events? No, they * are not linked to Note On or Note Off events. */ if (event::is_strict_note_msg(seqev.m_status)) return true; int eventcount = seqev.m_seq.select_events ( tick_s, tick_f, seqev.m_status, seqev.m_cc, sequence::e_would_select ); if (eventcount > 0) /* erase event under cursor if there is one */ { /* remove only note under cursor, leave selection intact */ (void) seqev.m_seq.select_events ( tick_s, tick_f, seqev.m_status, seqev.m_cc, sequence::e_remove_one ); seqev.redraw(); seqev.m_seq.set_dirty(); /* take note! */ result = true; } else /* selecting */ { if (! is_ctrl_key(ev)) seqev.m_seq.unselect(); /* nothing selected */ seqev.m_selecting = true; /* start select-box */ } } } seqev.update_pixmap(); /* if they clicked, something changed */ seqev.draw_pixmap_on_window(); update_mouse_pointer(seqev); return result; // true; }
bool Seq24SeqEventInput::on_button_press_event ( GdkEventButton * ev, seqevent & seqev ) { bool result = false; midipulse tick_s, tick_w; seqev.grab_focus(); // NEW: I think this would be helpful seqev.convert_x(c_eventevent_x, tick_w); seqev.set_current_drop_x(int(ev->x + seqev.m_scroll_offset_x)); seqev.m_old.x = seqev.m_old.y = seqev.m_old.width = seqev.m_old.height = 0; if (seqev.m_paste) { seqev.snap_x(seqev.m_current_x); seqev.convert_x(seqev.m_current_x, tick_s); seqev.m_paste = false; seqev.m_seq.paste_selected(tick_s, 0); /* handles undo & modify */ result = true; } else { int x, w; midipulse tick_f; if (SEQ64_CLICK_LEFT(ev->button)) { seqev.convert_x(seqev.m_drop_x, tick_s); /* x,y in to tick/note */ tick_f = tick_s + seqev.m_zoom; /* shift back a few ticks */ tick_s -= tick_w; if (tick_s < 0) tick_s = 0; int eventcount = 0; if (m_adding) { seqev.m_painting = true; seqev.snap_x(seqev.m_drop_x); seqev.convert_x(seqev.m_drop_x, tick_s); /* x,y to tick/note */ eventcount = seqev.m_seq.select_events ( tick_s, tick_f, seqev.m_status, seqev.m_cc, sequence::e_would_select ); if (eventcount == 0) { seqev.m_seq.push_undo(); seqev.drop_event(tick_s); // CHECK! result = true; } } else /* selecting */ { eventcount = seqev.m_seq.select_events ( tick_s, tick_f, seqev.m_status, seqev.m_cc, sequence::e_is_selected ); #ifdef USE_STAZED_SELECTION_EXTENSIONS /* * Stazed fix: if we didn't select anything (user clicked empty * space), then unselect all notes, and start selecting. */ if (event::is_strict_note_msg(seqev.m_status)) { seqev.m_seq.select_linked(tick_s, tick_f, seqev.m_status); seqev.m_seq.set_dirty(); } #endif if (eventcount == 0) { if (! is_ctrl_key(ev)) seqev.m_seq.unselect(); eventcount = seqev.m_seq.select_events ( tick_s, tick_f, seqev.m_status, seqev.m_cc, sequence::e_select_one ); /* * If nothing selected (user clicked empty space), * unselect all notes, and start selecting with a new * selection box. */ if (eventcount == 0) { seqev.m_selecting = true; } else { /** * Needs update. * seqev.m_seq.unselect(); ??????? */ } } eventcount = seqev.m_seq.select_events ( tick_s, tick_f, seqev.m_status, seqev.m_cc, sequence::e_is_selected ); if (eventcount > 0) /* get box selections are in */ { seqev.m_moving_init = true; int note; seqev.m_seq.get_selected_box(tick_s, note, tick_f, note); tick_f += tick_w; seqev.convert_t(tick_s, x); /* convert box to X,Y values */ seqev.convert_t(tick_f, w); w -= x; /* w is coordinate now */ /* set the m_selected rectangle for x,y,w,h */ seqev.m_selected.x = x; seqev.m_selected.width = w; seqev.m_selected.y = (c_eventarea_y - c_eventevent_y) / 2; seqev.m_selected.height = c_eventevent_y; /* save offset that we get from the snap above */ int adjusted_selected_x = seqev.m_selected.x; seqev.snap_x(adjusted_selected_x); seqev.m_move_snap_offset_x = seqev.m_selected.x - adjusted_selected_x; /* align selection for drawing */ seqev.snap_x(seqev.m_selected.x); seqev.snap_x(seqev.m_current_x); seqev.snap_x(seqev.m_drop_x); } } } if (SEQ64_CLICK_RIGHT(ev->button)) set_adding(true, seqev); } seqev.update_pixmap(); /* if they clicked, something changed */ seqev.draw_pixmap_on_window(); return result; // true; }
bool Seq24SeqEventInput::on_button_release_event ( GdkEventButton * ev, seqevent & seqev ) { bool result = false; midipulse tick_s; midipulse tick_f; seqev.grab_focus(); seqev.m_current_x = int(ev->x) + seqev.m_scroll_offset_x; if (seqev.m_moving) seqev.snap_x(seqev.m_current_x); int delta_x = seqev.m_current_x - seqev.m_drop_x; midipulse delta_tick; if (SEQ64_CLICK_LEFT(ev->button)) { if (seqev.m_selecting) { int x, w; seqev.x_to_w(seqev.m_drop_x, seqev.m_current_x, x, w); seqev.convert_x(x, tick_s); seqev.convert_x(x + w, tick_f); (void) seqev.m_seq.select_events ( tick_s, tick_f, seqev.m_status, seqev.m_cc, sequence::e_select ); #ifdef USE_STAZED_SELECTION_EXTENSIONS /* * Stazed fix: if we did'nt select anything (user clicked empty * space), then unselect all notes, and start selecting. */ if (event::is_strict_note_msg(seqev.m_status)) { seqev.m_seq.select_linked(tick_s, tick_f, seqev.m_status); } seqev.m_seq.set_dirty(); // ??????????? Why not in brackets? #endif } if (seqev.m_moving) { delta_x -= seqev.m_move_snap_offset_x; /* adjust for snap */ seqev.convert_x(delta_x, delta_tick); /* to screen coordinates */ seqev.m_seq.move_selected_notes(delta_tick, 0); result = true; } set_adding(m_adding, seqev); } if (SEQ64_CLICK_RIGHT(ev->button)) { set_adding(false, seqev); } seqev.m_selecting = false; /* turn off */ seqev.m_moving = false; seqev.m_growing = false; seqev.m_moving_init = false; seqev.m_painting = false; seqev.m_seq.unpaint_all(); seqev.update_pixmap(); /* if a click, something changed */ seqev.draw_pixmap_on_window(); return result; // true; }
void perftime::draw_background () { draw_rectangle(white_paint(), 0, 0, m_window_x, m_window_y); draw_line(black_paint(), 0, m_window_y - 1, m_window_x, m_window_y - 1); midipulse first_measure = m_tick_offset / m_measure_length; midipulse last_measure = first_measure + (m_window_x * m_perf_scale_x / m_measure_length) + 1; #ifdef USE_STAZED_EXTRAS float bar_draw = m_measure_length / float(m_perf_scale_x); int bar_skip = 1; if (bar_draw < 24) bar_skip = 4; if (bar_draw < 12) bar_skip = 8; if (bar_draw < 6) bar_skip = 16; if (bar_draw < 3) bar_skip = 32; if (bar_draw < .75) bar_skip = 64; #endif m_gc->set_foreground(grey()); /* draw vertical lines */ #ifdef USE_STAZED_EXTRAS for (midipulse i = first_measure; i < last_measure; i += bar_skip) { int x_pos = ((i * m_measure_length) - m_tick_offset) / m_perf_scale_x; #else for (midipulse i = first_measure; i < last_measure; ++i) { int x_pos = tick_to_pixel(i * m_measure_length); #endif char bar[8]; snprintf(bar, sizeof(bar), "%ld", i + 1); /* bar numbers */ draw_line(x_pos, 0, x_pos, m_window_y); /* beat */ render_string(x_pos + 2, 0, bar, font::BLACK, true); } midipulse left = tick_to_pixel(perf().get_left_tick()); midipulse right = tick_to_pixel(perf().get_right_tick()); if (left >= 0 && left <= m_window_x) /* draw L marker */ { draw_rectangle(black_paint(), left, m_window_y - 9, 7, 10); render_string(left + 1, 9, "L", font::WHITE, true); } if (right >= 0 && right <= m_window_x) /* draw R marker */ { draw_rectangle(black_paint(), right - 6, m_window_y - 9, 7, 10); render_string(right - 6 + 1, 9, "R", font::WHITE, true); } } /** * Implement the button-press event to set the L and R ticks. Added * functionality to try to set the start-tick if ctrl-left-click is pressed. * * \param p0 * The button event. * * \return * Always returns true. */ bool perftime::on_button_press_event (GdkEventButton * p0) { midipulse tick = pixel_to_tick(long(p0->x)); tick -= tick % m_snap; /** * Why is setting the start-tick disabled? We re-enable it and see if it * works. To our surprise, it works, but it sticks between stop/pause and * the next playback in the performance editor. We added a feature where * stop sets the start-tick to the left tick (or the beginning tick). */ if (SEQ64_CLICK_MIDDLE(p0->button)) { perf().set_start_tick(tick); } else if (SEQ64_CLICK_LEFT(p0->button)) { if (is_ctrl_key(p0)) perf().set_start_tick(tick); else perf().set_left_tick(tick); } else if (SEQ64_CLICK_RIGHT(p0->button)) { perf().set_right_tick(tick + m_snap); } enqueue_draw(); return true; }
bool Seq24PerfInput::on_button_press_event (GdkEventButton * ev, perfroll & roll) { bool result = false; perform & p = roll.perf(); int & dropseq = roll.m_drop_sequence; sequence * seq = p.get_sequence(dropseq); bool dropseq_active = p.is_active(dropseq); roll.grab_focus(); if (dropseq_active) { seq->unselect_triggers(); roll.draw_all(); } roll.m_drop_x = int(ev->x); roll.m_drop_y = int(ev->y); roll.convert_drop_xy(); /* affects dropseq */ seq = p.get_sequence(dropseq); dropseq_active = p.is_active(dropseq); if (! dropseq_active) return false; /* * EXPERIMENTAL. * Let's make better use of the Ctrl key here. First, let Ctrl-Left be * handled exactly like the Middle click, then bug out. * * Note that this middle-click code ought to be folded into a function. */ if (is_ctrl_key(ev)) { if (SEQ64_CLICK_LEFT(ev->button)) { bool state = seq->get_trigger_state(roll.m_drop_tick); if (state) { roll.split_trigger(dropseq, roll.m_drop_tick); } else { p.push_trigger_undo(dropseq); seq->paste_trigger(roll.m_drop_tick); } } return true; } if (SEQ64_CLICK_LEFT(ev->button)) { midipulse droptick = roll.m_drop_tick; if (is_adding()) /* add new note if nothing selected */ { set_adding_pressed(true); midipulse seqlength = seq->get_length(); bool state = seq->get_trigger_state(droptick); if (state) { p.push_trigger_undo(dropseq); /* stazed fix */ seq->del_trigger(droptick); } else { droptick -= (droptick % seqlength); /* snap */ p.push_trigger_undo(dropseq); /* stazed fix */ seq->add_trigger(droptick, seqlength); roll.draw_all(); } result = true; } else { /* * Set this flag to tell on_motion_notify() to call * p.push_trigger_undo(). */ roll.m_have_button_press = seq->select_trigger(droptick); midipulse tick0 = seq->selected_trigger_start(); midipulse tick1 = seq->selected_trigger_end(); int wscalex = s_perfroll_size_box_click_w * c_perf_scale_x; int ydrop = roll.m_drop_y % c_names_y; if ( droptick >= tick0 && droptick <= (tick0 + wscalex) && ydrop <= s_perfroll_size_box_click_w + 1 ) { roll.m_growing = true; roll.m_grow_direction = true; roll.m_drop_tick_trigger_offset = droptick - seq->selected_trigger_start(); } else if ( droptick >= (tick1 - wscalex) && droptick <= tick1 && ydrop >= c_names_y - s_perfroll_size_box_click_w - 1 ) { roll.m_growing = true; roll.m_grow_direction = false; roll.m_drop_tick_trigger_offset = droptick - seq->selected_trigger_end(); } else { roll.m_moving = true; roll.m_drop_tick_trigger_offset = droptick - seq->selected_trigger_start(); } roll.draw_all(); } } else if (SEQ64_CLICK_RIGHT(ev->button)) { activate_adding(true, roll); // Should we add this? // result = true; } else if (SEQ64_CLICK_MIDDLE(ev->button)) /* split */ { /* * The middle click in seq24 interaction mode is either for splitting * the triggers or for setting the paste location of copy/paste. */ bool state = seq->get_trigger_state(roll.m_drop_tick); if (state) { roll.split_trigger(dropseq, roll.m_drop_tick); result = true; } else { p.push_trigger_undo(dropseq); seq->paste_trigger(roll.m_drop_tick); // Should we add this? // result = true; } } return result; }