Fixed remaining known use of uninitialized data.
[epichord.git] / src / pianoroll.cpp
blob9115fd9fb7457595d7f076f50244f2786e78f034
1 /*
2 Epichord - a midi sequencer
3 Copyright (C) 2008 Evan Rinehart
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to
18 The Free Software Foundation, Inc.
19 51 Franklin Street, Fifth Floor
20 Boston, MA 02110-1301, USA
23 #include <vector>
24 #include <fltk/Group.h>
25 #include <fltk/Widget.h>
27 #include <fltk/Scrollbar.h>
29 #include <fltk/events.h>
31 #include <stdio.h>
32 #include <unistd.h>
33 #include "ui.h"
35 #include "util.h"
37 #include "backend.h"
39 #include "uihelper.h"
41 extern UI* ui;
42 extern std::vector<track*> tracks;
44 extern struct conf config;
46 using namespace fltk;
48 #define SWAP(X,Y) tmp=X; X=Y; Y=tmp;
50 PianoRoll::PianoRoll(int x, int y, int w, int h, const char* label = 0) : fltk::Widget(x, y, w, h, label) {
51 wkeyh = 12;
52 bkeyh = 7;
53 cur_seqpat = NULL;
55 zoom = 15;
56 zoom_n = 3;
58 q_tick = 32;
60 box_flag = 0;
62 move_toffset = 0;
64 insert_flag = 0;
65 move_flag = 0;
66 delete_flag=0;
67 lresize_flag = 0;
68 rresize_flag = 0;
70 resize_arrow = 0;
71 resize_e = NULL;
72 resize_handle_width = 4;
74 fakeh = wkeyh*75;
75 fakehmin = wkeyh*75;
76 if(fakeh < h){fakeh = h;}
78 scrollx=0;
79 scrolly=0;
82 int PianoRoll::handle(int event){
83 Command* c;
84 pattern* p;
85 mevent* e;
87 int X = event_x();
88 int Y = event_y();
90 switch(event){
91 case fltk::ENTER:
92 return 1;
93 case fltk::FOCUS:
94 return 1;
95 case fltk::SHORTCUT:
96 if(event_key()==fltk::DeleteKey){
97 apply_delete();
98 delete_flag = 0;
99 redraw();
100 resize_arrow = 0;
101 ui->event_edit->redraw();
102 return 1;
104 if(event_state(CTRL) && event_key()=='c'){
105 //printf("roll copy\n");
106 return 1;
108 if(zoom_out_key(event_key(),event_state())){
109 if(zoom_n > 1){
110 zoom_n--;
111 set_zoom(30*(1<<zoom_n)/16);
112 ui->pattern_timeline->zoom = zoom;
113 ui->pattern_timeline->update(get_play_position());
114 ui->pattern_timeline->redraw();
115 ui->event_edit->zoom = zoom;
116 ui->event_edit->redraw();
118 redraw();
119 return 1;
121 if(zoom_in_key(event_key(),event_state())){
122 if(zoom_n < 8){
123 zoom_n++;
124 set_zoom(30*(1<<zoom_n)/16);
125 ui->pattern_timeline->zoom = zoom;
126 ui->pattern_timeline->update(get_play_position());
127 ui->pattern_timeline->redraw();
128 ui->event_edit->zoom = zoom;
129 ui->event_edit->redraw();
131 redraw();
132 return 1;
134 return 0;
135 case fltk::PUSH:
136 take_focus();
137 e = over_note();
138 if(event_button()==1){//left mouse
139 if(e==NULL){//new note init
140 if(event_state()&fltk::SHIFT){//begin box
141 box_flag = 1;
142 box_x1=X;
143 box_x2=X;
144 box_y1=Y;
145 box_y2=Y;
146 box_t1=xpix2tick(X+scrollx);
147 box_t2=box_t1;
148 box_n1=ypix2note(Y+scrolly,1);
149 box_n2=box_n1;
151 else{//begin insert
152 insert_flag = 1;
153 insert_torig = quantize(xpix2tick(X+scrollx));
154 insert_toffset = q_tick;
155 //new_orig_t = new_left_t;
156 insert_note = ypix2note(Y+scrolly,1);
158 last_note = insert_note;
159 if(config.playinsert){
160 ui->keyboard->play_note(last_note,0);
165 else{
167 if(!(e->selected) && !(event_state()&fltk::SHIFT)){
168 unselect_all();
170 e->selected = 1;
171 resize_arrow_color = fltk::color(128,128,0);
173 if(over_rhandle(e)){//resize
174 rresize_flag = 1;
175 rresize_torig = e->tick+e->dur;
176 rresize_toffset = 0;
178 else if(over_lhandle(e)){//resize move
179 lresize_flag = 1;
180 lresize_torig = e->tick;
181 lresize_toffset = 0;
183 else{//begin move
184 move_flag = 1;
186 move_torig = e->tick;
187 move_qoffset = e->tick - quantize(e->tick);
189 move_toffset = -move_qoffset;
191 //move_offset = quantize(xpix2tick(X)) - move_torig - move_qoffset;
192 //move_toffset = 0;
193 move_offset = X - tick2xpix(e->tick);
194 move_norig = ypix2note(Y+scrolly,1);
195 move_noffset = 0;
197 last_note = move_norig;
198 if(config.playmove){
199 ui->keyboard->play_note(last_note,0);
204 else if(event_button()==2){//middle mouse
205 //button initiates paste
207 else if(event_button()==3){//right mouse
208 if(e==NULL){
209 unselect_all();
211 ui->event_edit->redraw();
213 else{//set up for deletion
214 if(!(e->selected) && !(event_state()&fltk::SHIFT)){
215 unselect_all();
217 e->selected = 1;
218 delete_flag = 1;
219 resize_arrow_color = fltk::color(120,60,58);
223 redraw();
224 return 1;
225 case fltk::DRAG:
227 if(box_flag){
228 box_x2 = X;
229 box_y2 = Y;
230 box_t2 = xpix2tick(X+scrollx);
231 box_n2 = ypix2note(Y+scrolly,1);
233 else if(insert_flag){
234 insert_toffset = quantize(xpix2tick(X+scrollx)+q_tick) - insert_torig;
235 if(insert_toffset<=0){
236 insert_toffset -= q_tick;
238 insert_note = ypix2note(Y+scrolly,1);
239 if(insert_note != last_note){
240 if(config.playinsert){//play on insert
241 ui->keyboard->release_note(last_note,0);
242 ui->keyboard->play_note(insert_note,0);
244 last_note = insert_note;
247 else if(move_flag){
248 move_toffset = quantize(xpix2tick(X - move_offset)) - move_torig;
249 move_noffset = ypix2note(Y+scrolly,1) - move_norig;
250 int N = move_norig+move_noffset;
251 if(N != last_note){
252 if(config.playmove){//play on move
253 ui->keyboard->release_note(last_note,0);
254 ui->keyboard->play_note(N,0);
256 last_note = N;
259 else if(rresize_flag){
260 rresize_toffset = quantize(xpix2tick(X+scrollx))+q_tick-rresize_torig;
262 else if(lresize_flag){
263 lresize_toffset = quantize(xpix2tick(X+scrollx)) - lresize_torig;
265 redraw();
266 return 1;
267 case fltk::RELEASE:
268 e = over_note();
269 if(event_button()==1){
270 if(box_flag){
271 apply_box();
272 ui->event_edit->redraw();
273 box_flag=0;
275 else if(rresize_flag){
276 apply_rresize();
277 rresize_flag = 0;
278 resize_arrow = 0;
279 ui->event_edit->redraw();
281 else if(lresize_flag){
282 apply_lresize();
283 lresize_flag = 0;
284 resize_arrow = 0;
285 ui->event_edit->redraw();
287 else if(insert_flag){
288 apply_insert();
290 insert_flag = 0;
292 ui->keyboard->release_note(insert_note,0);
293 ui->keyboard->redraw();
294 ui->event_edit->has[0]=1;
295 ui->event_edit->has[1]=1;
296 ui->event_edit->redraw();
297 ui->event_menu->redraw();
299 else if(move_flag){
300 apply_move();
301 move_flag = 0;
303 midi_track_off(cur_seqpat->track);
304 ui->keyboard->release_note(last_note,0);
305 ui->keyboard->release_note(move_norig+move_noffset,0);
306 ui->keyboard->redraw();
307 ui->event_edit->redraw();
309 insert_flag=0;
310 move_flag=0;
312 if(event_button()==3){
313 mevent* over_n = over_note();
314 if(delete_flag && over_n){
315 if(over_n->selected){
316 apply_delete();
317 midi_track_off(cur_seqpat->track);
318 ui->event_edit->redraw();
321 delete_flag=0;
322 resize_arrow = 0;
324 redraw();
326 return 1;
328 case fltk::MOVE:
329 e = over_note();
330 if(e){
331 if(over_rhandle(e)){
332 if(resize_e != e || resize_arrow != 1){
333 if(e->selected){resize_arrow_color = fltk::color(128,128,0);}
334 else{resize_arrow_color = fltk::color(95,58,119);}
335 resize_e = e;
336 resize_arrow = 1;
337 resize_x = tick2xpix(e->tick + e->dur)-scrollx-resize_handle_width;
338 resize_y = note2ypix(e->value1)-scrolly;
339 redraw();
342 else if(over_lhandle(e)){
343 if(resize_e != e || resize_arrow != 1){
344 if(e->selected){resize_arrow_color = fltk::color(128,128,0);}
345 else{resize_arrow_color = fltk::color(95,58,119);}
346 resize_e = e;
347 resize_arrow = -1;
348 resize_x = tick2xpix(e->tick)+1 - scrollx;
349 resize_y = note2ypix(e->value1) - scrolly;
350 redraw();
353 else{
354 if(resize_e != e || resize_arrow != 0){
355 resize_e = e;
356 resize_arrow = 0;
357 redraw();
361 else{
362 if(resize_arrow != 0){
363 resize_arrow = 0;
364 redraw();
368 return 1;
370 return 0;
373 void PianoRoll::draw(){
375 fltk::push_clip(0,0,w(),h());
377 fltk::setcolor(fltk::GRAY05);
378 fltk::fillrect(0,0,w(),h());
380 fltk::setcolor(fltk::GRAY20);
381 for(int i=12-scrolly; i<h(); i+=12){
382 if(i>=0){
383 fltk::fillrect(0,i,w(),1);
386 for(int i=zoom-scrollx; i<w(); i+=zoom){
387 if(i>=0){
388 fltk::fillrect(i,0,1,h());
392 fltk::setcolor(fltk::GRAY30);
393 for(int i=12*5-scrolly; i<h(); i+=12*7){
394 if(i>=0){
395 fltk::fillrect(0,i,w(),1);
399 fltk::setcolor(fltk::GRAY50);
400 for(int i=zoom*4-scrollx; i<w(); i+=zoom*4){
401 if(i>=0){
402 fltk::fillrect(i,0,1,h());
406 fltk::setcolor(fltk::WHITE);
407 int M = config.beats_per_measure;
408 for(int i=zoom*4*M-scrollx; i<w(); i+=zoom*4*M){
409 if(i>=0){
410 fltk::fillrect(i,0,1,h());
414 fltk::setcolor(fltk::color(128,0,0));
415 int rightend = tick2xpix(cur_seqpat->dur)-scrollx;
416 if(rightend >=0 && rightend < w()){
417 fltk::fillrect(rightend,0,1,h());
420 fltk::setcolor(fltk::color(128,128,0));
421 fltk::fillrect(0,12*40-scrolly,w(),1);
423 int tmp;
424 if(insert_flag){
425 fltk::setcolor(fltk::BLUE);
426 int T1 = insert_torig;
427 int T2 = T1 + insert_toffset;
428 if(T1>T2){SWAP(T1,T2);}
429 int X = tick2xpix(T1)+1 - scrollx;
430 int Y = note2ypix(insert_note) - scrolly;
431 int W = tick2xpix(T2)-scrollx - X;
432 fltk::fillrect(X,Y,W,11);
435 if(move_flag){
436 fltk::setcolor(fltk::MAGENTA);
437 mevent* ptr = cur_seqpat->p->events->next;
438 while(ptr){
439 if(ptr->type == MIDI_NOTE_ON && ptr->selected){
440 int X = tick2xpix(ptr->tick+move_toffset)+1-scrollx;
441 int Y = note2ypix(ptr->value1+move_noffset)-scrolly;
442 int W = tick2xpix(ptr->dur);
443 fltk::fillrect(X,Y,W-1,1);
444 fltk::fillrect(X,Y+11,W-1,1);
445 fltk::fillrect(X,Y,1,11);
446 fltk::fillrect(X+W-2,Y,1,11);
448 ptr=ptr->next;
454 //draw all notes
455 mevent* e = cur_seqpat->p->events->next;
457 fltk::Color c1,c2,c3;
459 while(e){
460 if(e->type == MIDI_NOTE_ON){
461 //fltk::fillrect(tick2xpix(e->tick),note2ypix(e->value),e->dur,11);
463 int R1 = rresize_flag&&e->selected ? rresize_toffset : 0;
464 int R2 = lresize_flag&&e->selected ? lresize_toffset : 0;
466 int T1 = e->tick + R2;
467 int T2 = e->tick+e->dur + R1;
469 if(T1 >= T2-q_tick && e->selected){
470 if(rresize_flag){
471 T1 = e->tick;
472 T2 = T1 + q_tick;
474 else if(lresize_flag){
475 T2 = e->tick + e->dur;
476 T1 = T2 - q_tick;
480 int X = tick2xpix(T1) + 1 - scrollx;
481 int Y = note2ypix(e->value1) - scrolly;
483 int W = tick2xpix(T2)-scrollx - X;
484 get_event_color(e,&c1,&c2,&c3);
486 if(!(X+W<0 || X > w())){
488 fltk::setcolor(c1);
489 fltk::fillrect(X+1,Y+1,W-1,10);
491 fltk::setcolor(c2);
492 fltk::fillrect(X,Y+11,W,1);
493 fltk::fillrect(X+W-1,Y+1,1,11);
495 fltk::setcolor(c3);
496 fltk::fillrect(X,Y,W,1);
497 fltk::fillrect(X,Y,1,11);
500 e=e->next;
504 if(!rresize_flag && !lresize_flag){
505 if(resize_arrow > 0){
506 setcolor(resize_arrow_color);
508 int W = resize_handle_width;
509 int H = 12;
510 int X = resize_x;
511 int Y = resize_y;
513 addvertex(X,Y);
514 addvertex(X,Y+H);
515 addvertex(X+W,Y+H/2);
516 fillpath();
518 else if(resize_arrow < 0){
519 setcolor(resize_arrow_color);
521 int W = resize_handle_width;
522 int H = 12;
523 int X = resize_x;
524 int Y = resize_y;
526 addvertex(X+W,Y);
527 addvertex(X+W,Y+H);
528 addvertex(X,Y+H/2);
529 fillpath();
534 if(box_flag){
535 fltk::setcolor(fltk::GREEN);
536 int X1,X2,Y1,Y2;
537 if(box_x1>box_x2){
538 X1=box_x2;
539 X2=box_x1;
541 else{
542 X1=box_x1;
543 X2=box_x2;
545 if(box_y1>box_y2){
546 Y1=box_y2;
547 Y2=box_y1;
549 else{
550 Y1=box_y1;
551 Y2=box_y2;
553 fltk::fillrect(X1,Y1,X2-X1,1);
554 fltk::fillrect(X1,Y1,1,Y2-Y1);
555 fltk::fillrect(X2,Y1,1,Y2-Y1);
556 fltk::fillrect(X1,Y2,X2-X1,1);
559 fltk::pop_clip();
565 void PianoRoll::scrollTo(int X, int Y){
567 if(!cur_seqpat){
568 return;
571 if(is_backend_playing() && config.follow){
572 int pos = tick2xpix(get_play_position()) - cur_seqpat->tick;
573 if(pos < X || pos > X + w() - 30 - 30){
574 ui->pattern_hscroll->value(scrollx);
575 return;
579 scrollx = X;
580 scrolly = Y;
581 cur_seqpat->scrollx = X;
582 cur_seqpat->scrolly = Y;
584 redraw();
585 ui->pattern_hscroll->value(X);
586 ui->pattern_hscroll->redraw();
587 ui->pattern_vscroll->value(Y);
588 ui->pattern_timeline->scroll = X;
589 ui->pattern_timeline->redraw();
590 ui->event_edit->scroll = X;
591 ui->event_edit->redraw();
592 ui->keyboard->scroll = Y;
593 ui->keyboard->redraw();
596 static int kludge=2;
597 void PianoRoll::layout(){
598 if(kludge!=0){
599 kludge--;
600 return;
602 fakeh = 900;
603 if(fakeh<h()){
604 fakeh = h();
607 fltk::Scrollbar* sb = ui->pattern_vscroll;
609 sb->maximum(0);
610 sb->minimum(fakeh-h());
612 if(sb->value() > sb->minimum()){
613 scrollTo(scrollx,900-h());
615 int M = h() - 30;
616 int newsize = M-(fakeh-h());
617 if(newsize<20){
618 newsize=20;
620 ui->song_vscroll->slider_size(60);
623 void PianoRoll::load(seqpat* s){
624 cur_seqpat = s;
625 scrollTo(s->scrollx,s->scrolly);
626 cur_track = tracks[s->track];
627 ui->pattern_timeline->ticks_offset = s->tick;
632 int PianoRoll::note2ypix(int note){
633 int udy = 6*(note + (note+7)/12 + note/12) + 12;
634 return 900 - udy + 1;
637 int PianoRoll::tick2xpix(int tick){
638 return tick*zoom*4 / 128;
641 int PianoRoll::xpix2tick(int xpix){
642 return xpix*128 / (zoom*4);
645 int PianoRoll::quantize(int tick){
646 return tick/q_tick * q_tick;
650 void PianoRoll::set_zoom(int z){
651 zoom = z;
652 relayout();
656 mevent* PianoRoll::over_note(){
657 mevent* e = cur_seqpat->p->events->next;
659 int X = event_x()+scrollx;
660 int Y = event_y()+scrolly;
662 int cy, lx, rx;
663 while(e){
664 if(e->type == MIDI_NOTE_ON){
665 cy = note2ypix(e->value1);
666 lx = tick2xpix(e->tick);
667 rx = tick2xpix(e->tick+e->dur);
668 if(X > lx && X < rx &&
669 Y < cy+12 && Y > cy){
670 return e;
673 e = e->next;
676 return NULL;
681 void PianoRoll::update(int pos){
682 if(!is_backend_playing() || !cur_seqpat){
683 return;
685 int X1 = tick2xpix(pos-cur_seqpat->tick);
686 int X2 = X1 - scrollx;
687 if(X2 < 0){
688 scrollTo(X1-50<0?0:X1-50,scrolly);
690 if(X2 > w()-30){
691 scrollTo(X1-50,scrolly);
696 void PianoRoll::unselect_all(){
697 mevent* e = cur_seqpat->p->events;
698 while(e){
699 if(e->type == MIDI_NOTE_ON && e->selected==1){
700 e->selected = 0;
702 e = e->next;
708 void PianoRoll::get_event_color(mevent* e, fltk::Color* c1, fltk::Color* c2, fltk::Color* c3){
710 int T1,T2;
711 int tmp;
712 if(delete_flag){
713 if(e->selected){
714 *c1 = fltk::color(229,79,75);
715 *c2 = fltk::color(120,60,58);
716 *c3 = fltk::color(225,131,109);
717 return;
721 if(box_flag){
722 T1=box_t1;
723 T2=box_t2;
724 int N1 = box_n1;
725 int N2 = box_n2;
726 int N = e->value1;
727 if(T1>T2){SWAP(T1,T2);}
728 if(N1<N2){SWAP(N1,N2);}
729 if(e->tick+e->dur > T1 && e->tick < T2 && N >= N2 && N <= N1){
730 *c1 = fltk::color(108,229,75);
731 *c2 = fltk::color(71,120,59);
732 *c3 = fltk::color(108,229,75);
733 return;
737 if(e->selected){
738 *c1 = fltk::color(255,248,47);
739 *c2 = fltk::color(140,137,46);
740 *c3 = fltk::color(232,255,37);
741 return;
744 *c1 = fltk::color(169,75,229);
745 *c2 = fltk::color(95,58,119);
746 *c3 = fltk::color(198,109,225);
750 void PianoRoll::apply_box(){
751 mevent* e = cur_seqpat->p->events->next;
752 int tmp;
753 int T1=box_t1;
754 int T2=box_t2;
755 int N1 = box_n1;
756 int N2 = box_n2;
758 if(T1>T2){SWAP(T1,T2);}
759 if(N1<N2){SWAP(N1,N2);}
760 while(e){
761 int N = e->value1;
762 if(e->type == MIDI_NOTE_ON &&
763 e->tick+e->dur > T1 && e->tick < T2 &&
764 N >= N2 && N <= N1){
765 e->selected = 1;
767 e = e->next;
771 void PianoRoll::apply_insert(){
772 if(insert_note > 127 || insert_note < 0){
773 return;
776 int tmp;
777 int T1 = insert_torig;
778 int T2 = T1 + insert_toffset;
779 if(T1>T2){SWAP(T1,T2);}
781 if(T1 < 0){
782 return;
785 pattern* p = cur_seqpat->p;
786 Command* c=new CreateNote(p,insert_note,config.defaultvelocity,T1,T2-T1);
787 set_undo(c);
788 undo_push(1);
790 cur_track->restate();
793 void PianoRoll::apply_delete(){
794 Command* c;
795 mevent* e;
796 mevent* next;
797 pattern* p = cur_seqpat->p;
798 int N=0;
800 e = cur_seqpat->p->events->next;
801 while(e){
802 next = e->next;
803 if(e->selected && e->type == MIDI_NOTE_ON){
804 c=new DeleteNote(p,e);
805 set_undo(c);
806 N++;
808 e = next;
810 undo_push(N);
812 cur_track->restate();
815 void PianoRoll::apply_move(){
816 if(move_toffset==0 && move_noffset==0){
817 return;
820 pattern* p = cur_seqpat->p;
821 mevent* e = p->events->next;
822 while(e){
823 int K = e->value1+move_noffset;
824 int T = e->tick+move_toffset;
825 if(e->type == MIDI_NOTE_ON && e->selected && (T<0 || K < 0 || K > 127)){
826 return;
828 e = e->next;
832 Command* c;
833 e = p->events->next;
835 mevent* next;
836 int M=0;
837 for(int i=0; i<tracks.size(); i++){
838 e = p->events->next;
839 while(e){
840 next = e->next;
841 if(e->selected && e->modified == 0){
842 int K = e->value1 + move_noffset;
843 int T = e->tick + move_toffset;
844 e->modified = 1;
845 c=new MoveNote(p,e,T,K);
846 set_undo(c);
847 M++;
849 e = next;
852 undo_push(M);
854 e = p->events->next;
855 while(e){
856 if(e->modified){e->modified=0;}
857 e = e->next;
860 cur_track->restate();
863 void PianoRoll::apply_paste(){
869 void PianoRoll::apply_rresize(){
870 if(rresize_toffset==0){
871 return;
874 Command* c;
875 mevent* e;
876 mevent* next;
877 pattern* p = cur_seqpat->p;
878 int tmp;
879 int N=0;
881 e = p->events->next;
882 while(e){
883 next = e->next;
884 if(e->type == MIDI_NOTE_ON && e->selected && e->modified == 0){
885 e->modified = 1;
886 int W = e->dur;
887 int R = rresize_toffset;
888 if(W+R < q_tick){
889 R = q_tick-W;
891 c=new ResizeNote(p,e,W+R);
892 set_undo(c);
893 N++;
895 e = next;
898 e = p->events->next;
899 while(e){
900 if(e->modified){e->modified=0;}
901 e = e->next;
904 cur_track->restate();
905 undo_push(N);
908 void PianoRoll::apply_lresize(){
909 if(lresize_toffset==0){
910 return;
913 Command* c;
914 mevent* e;
915 mevent* next;
916 pattern* p = cur_seqpat->p;
917 int tmp;
918 int N=0;
920 e = p->events->next;
921 while(e){
922 if(e->type == MIDI_NOTE_ON && e->selected){
923 if(e->tick + lresize_toffset < 0){
924 return;
927 e = e->next;
930 e = p->events->next;
931 while(e){
932 next = e->next;
933 if(e->type == MIDI_NOTE_ON && e->selected && e->modified == 0){
934 e->modified = 1;
935 int T = e->tick;
936 int W = e->dur;
937 int R = lresize_toffset;
939 if(R > W-q_tick){
940 R = W-q_tick;
943 mevent* etmp = e->prev;
944 c=new ResizeNote(p,e,W-R);
945 set_undo(c);
947 e = etmp->next;
948 c=new MoveNote(p,e,T+R,e->value1);
949 set_undo(c);
951 N+=2;
953 e = next;
956 e = p->events->next;
957 while(e){
958 if(e->modified){e->modified=0;}
959 e = e->next;
962 cur_track->restate();
963 undo_push(N);
974 int PianoRoll::over_rhandle(mevent* e){
975 int X = event_x()+scrollx;
976 int Y = event_y()+scrolly;
977 int X1 = tick2xpix(e->tick);
978 int X2 = X1 + tick2xpix(e->dur);
979 int Y1 = note2ypix(e->value1);
980 int Y2 = Y1 + 12;
982 if(X2-X1 < resize_handle_width*3){
983 return 0;
986 return (Y > Y1 && Y < Y2 && X < X2 && X > X2 - resize_handle_width);
989 int PianoRoll::over_lhandle(mevent* e){
990 int X = event_x()+scrollx;
991 int Y = event_y()+scrolly;
992 int X1 = tick2xpix(e->tick);
993 int X2 = X1 + tick2xpix(e->dur);
994 int Y1 = note2ypix(e->value1);
995 int Y2 = Y1 + 12;
997 if(X2-X1 < resize_handle_width*3){
998 return 0;
1001 return (Y > Y1 && Y < Y2 && X < X1+ resize_handle_width +1 && X > X1 + 1);