2007-12-18 05:09:02 +01:00
|
|
|
|
|
|
|
|
|
/*******************************************************************************/
|
|
|
|
|
/* Copyright (C) 2007-2008 Jonathan Moore Liles */
|
|
|
|
|
/* */
|
|
|
|
|
/* This program is free software; you can redistribute it and/or modify it */
|
|
|
|
|
/* under the terms of the GNU General Public License as published by the */
|
|
|
|
|
/* Free Software Foundation; either version 2 of the License, or (at your */
|
|
|
|
|
/* option) any later version. */
|
|
|
|
|
/* */
|
|
|
|
|
/* This program is distributed in the hope that it will be useful, but WITHOUT */
|
|
|
|
|
/* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
|
|
|
|
|
/* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for */
|
|
|
|
|
/* more details. */
|
|
|
|
|
/* */
|
|
|
|
|
/* You should have received a copy of the GNU General Public License along */
|
|
|
|
|
/* with This program; see the file COPYING. If not,write to the Free Software */
|
|
|
|
|
/* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
|
|
|
|
/*******************************************************************************/
|
|
|
|
|
|
|
|
|
|
/* This is a generic double-buffering, optimizing canvas interface to
|
|
|
|
|
grids (patterns and phrases). It draws only what is necessary to keep
|
|
|
|
|
the display up-to-date. Actual drawing functions are in draw.C */
|
|
|
|
|
|
|
|
|
|
#include "canvas.H"
|
|
|
|
|
#include "pattern.H"
|
|
|
|
|
#include "gui/draw.H"
|
|
|
|
|
#include "common.h"
|
|
|
|
|
|
|
|
|
|
#include "non.H"
|
2012-10-25 23:13:23 +02:00
|
|
|
|
#include <FL/fl_draw.H>
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
extern Fl_Color velocity_colors[];
|
|
|
|
|
const int ruler_height = 14;
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
Canvas::Canvas ( int X, int Y, int W, int H, const char *L ) : Fl_Widget( X,Y,W,H,L )
|
2007-12-18 05:09:02 +01:00
|
|
|
|
{
|
2008-02-15 05:20:04 +01:00
|
|
|
|
m.origin_x = m.origin_y = m.height = m.width = m.div_w = m.div_h = m.playhead = m.margin_top = m.margin_left = m.playhead = m.w = m.h = m.p1 = m.p2 = m.p3 = m.p4 = 0;
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
|
|
|
|
m.margin_top = ruler_height;
|
|
|
|
|
|
2008-02-13 02:37:26 +01:00
|
|
|
|
m.draw = false;
|
2007-12-18 05:09:02 +01:00
|
|
|
|
m.ruler_drawn = false;
|
|
|
|
|
m.mapping_drawn = false;
|
|
|
|
|
m.grid_drawn = false;
|
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
// m.current = m.previous = NULL;
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
|
|
|
|
m.row_compact = true;
|
|
|
|
|
|
|
|
|
|
m.maxh = 128;
|
|
|
|
|
|
|
|
|
|
m.vp = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
Canvas::handle_event_change ( void )
|
|
|
|
|
{
|
|
|
|
|
/* mark the song as dirty and pass the signal on */
|
2008-03-23 05:43:40 +01:00
|
|
|
|
song.set_dirty();
|
2008-02-12 07:06:08 +01:00
|
|
|
|
|
2007-12-18 05:09:02 +01:00
|
|
|
|
signal_draw();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** change grid to /g/, returns TRUE if new grid size differs from old */
|
2008-02-11 06:20:39 +01:00
|
|
|
|
void
|
2007-12-18 05:09:02 +01:00
|
|
|
|
Canvas::grid ( Grid *g )
|
|
|
|
|
{
|
|
|
|
|
m.grid = g;
|
|
|
|
|
|
|
|
|
|
if ( ! g )
|
2008-02-11 06:20:39 +01:00
|
|
|
|
return;
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
|
|
|
|
m.vp = &g->viewport;
|
|
|
|
|
|
|
|
|
|
char *s = m.vp->dump();
|
2008-03-23 20:45:07 +01:00
|
|
|
|
DMESSAGE( "viewport: %s", s );
|
2007-12-18 05:09:02 +01:00
|
|
|
|
free( s );
|
|
|
|
|
|
2008-02-11 06:20:39 +01:00
|
|
|
|
m.ruler_drawn = false;
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
|
|
|
|
resize_grid();
|
|
|
|
|
|
2008-06-15 19:45:57 +02:00
|
|
|
|
update_mapping();
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-03-01 05:46:57 +01:00
|
|
|
|
// m.shape = m.grid->draw_shape();
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
|
|
|
|
/* connect signals */
|
|
|
|
|
/* FIXME: what happens when we do this twice? */
|
|
|
|
|
g->signal_events_change.connect( mem_fun( this, &Canvas::handle_event_change ) );
|
|
|
|
|
g->signal_settings_change.connect( signal_settings_change.make_slot() );
|
|
|
|
|
|
|
|
|
|
signal_draw();
|
|
|
|
|
signal_settings_change();
|
2012-03-01 08:00:38 +01:00
|
|
|
|
signal_pan();
|
2007-12-18 05:09:02 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** keep row compaction tables up-to-date */
|
|
|
|
|
void
|
|
|
|
|
Canvas::_update_row_mapping ( void )
|
|
|
|
|
{
|
|
|
|
|
/* reset */
|
|
|
|
|
for ( int i = 128; i-- ; )
|
|
|
|
|
m.rtn[i] = m.ntr[i] = -1;
|
|
|
|
|
|
2008-03-23 20:45:07 +01:00
|
|
|
|
DMESSAGE( "updating row mapping" );
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
|
|
|
|
/* rebuild */
|
|
|
|
|
int r = 0;
|
|
|
|
|
for ( int n = 0; n < 128; ++n )
|
|
|
|
|
{
|
|
|
|
|
if ( m.grid->row_name( n ) )
|
|
|
|
|
{
|
|
|
|
|
m.rtn[r] = n;
|
|
|
|
|
m.ntr[n] = r;
|
|
|
|
|
++r;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( m.row_compact && r )
|
|
|
|
|
m.maxh = r;
|
|
|
|
|
else
|
|
|
|
|
m.maxh = 128;
|
|
|
|
|
|
|
|
|
|
m.vp->h = min( m.vp->h, m.maxh );
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-15 19:45:57 +02:00
|
|
|
|
/** update everything about mapping, leaving the viewport alone */
|
2007-12-18 05:09:02 +01:00
|
|
|
|
void
|
2008-06-15 19:45:57 +02:00
|
|
|
|
Canvas::update_mapping ( void )
|
2007-12-18 05:09:02 +01:00
|
|
|
|
{
|
|
|
|
|
_update_row_mapping();
|
|
|
|
|
|
|
|
|
|
m.mapping_drawn = false;
|
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
adj_size();
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
|
|
|
|
int old_margin = m.margin_left;
|
|
|
|
|
|
|
|
|
|
m.margin_left = 0;
|
|
|
|
|
|
|
|
|
|
m.draw = false;
|
|
|
|
|
|
|
|
|
|
m.grid->draw_row_names( this );
|
|
|
|
|
|
2012-03-01 08:00:59 +01:00
|
|
|
|
m.draw = true;
|
|
|
|
|
|
2007-12-18 05:09:02 +01:00
|
|
|
|
if ( m.margin_left != old_margin )
|
2008-02-13 20:48:50 +01:00
|
|
|
|
{
|
2007-12-18 05:09:02 +01:00
|
|
|
|
signal_resize();
|
2008-02-13 20:48:50 +01:00
|
|
|
|
signal_draw();
|
|
|
|
|
}
|
2007-12-18 05:09:02 +01:00
|
|
|
|
else
|
|
|
|
|
signal_draw();
|
2012-03-01 08:00:38 +01:00
|
|
|
|
|
2007-12-18 05:09:02 +01:00
|
|
|
|
}
|
|
|
|
|
|
2008-06-15 19:45:57 +02:00
|
|
|
|
/** change grid mapping */
|
|
|
|
|
void
|
|
|
|
|
Canvas::changed_mapping ( void )
|
|
|
|
|
{
|
|
|
|
|
update_mapping();
|
|
|
|
|
|
|
|
|
|
m.vp->h = min( m.vp->h, m.maxh );
|
|
|
|
|
|
|
|
|
|
if ( m.vp->y + m.vp->h > m.maxh )
|
|
|
|
|
m.vp->y = (m.maxh / 2) - (m.vp->h / 2);
|
2012-03-01 08:00:38 +01:00
|
|
|
|
|
|
|
|
|
signal_pan();
|
2008-06-15 19:45:57 +02:00
|
|
|
|
}
|
|
|
|
|
|
2007-12-18 05:09:02 +01:00
|
|
|
|
Grid *
|
|
|
|
|
Canvas::grid ( void )
|
|
|
|
|
{
|
|
|
|
|
return m.grid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** recalculate node sizes based on physical dimensions */
|
|
|
|
|
void
|
2012-10-25 23:13:23 +02:00
|
|
|
|
Canvas::adj_size ( void )
|
2007-12-18 05:09:02 +01:00
|
|
|
|
{
|
|
|
|
|
if ( ! m.vp )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
m.div_w = (m.width - m.margin_left) / m.vp->w;
|
|
|
|
|
m.div_h = (m.height - m.margin_top) / m.vp->h;
|
|
|
|
|
|
|
|
|
|
m.mapping_drawn = m.ruler_drawn = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** reallocate buffers to match grid dimensions */
|
|
|
|
|
void
|
|
|
|
|
Canvas::resize_grid ( void )
|
|
|
|
|
{
|
|
|
|
|
// _update_row_mapping();
|
2012-10-25 23:13:23 +02:00
|
|
|
|
|
|
|
|
|
adj_size();
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
|
|
|
|
if ( m.vp )
|
|
|
|
|
{
|
|
|
|
|
if ( m.vp->w != m.w || m.vp->h != m.h ||
|
|
|
|
|
m.div_w != m.old_div_w || m.div_h != m.old_div_h )
|
|
|
|
|
{
|
|
|
|
|
if ( m.grid_drawn )
|
|
|
|
|
signal_resize();
|
|
|
|
|
|
|
|
|
|
m.old_div_w = m.div_w;
|
|
|
|
|
m.old_div_h = m.div_h;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2008-03-23 20:45:07 +01:00
|
|
|
|
DMESSAGE( "resizing grid %dx%d", m.vp->w, m.vp->h );
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
|
|
|
|
m.grid_drawn = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** inform the canvas with new phsyical dimensions */
|
|
|
|
|
void
|
|
|
|
|
Canvas::resize ( int x, int y, int w, int h )
|
|
|
|
|
{
|
|
|
|
|
m.origin_x = x;
|
|
|
|
|
m.origin_y = y;
|
|
|
|
|
|
|
|
|
|
m.width = w;
|
|
|
|
|
m.height = h;
|
2012-10-25 23:13:23 +02:00
|
|
|
|
|
|
|
|
|
Fl_Widget::resize(x,y,w,h);
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
adj_size();
|
2007-12-18 05:09:02 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/***********/
|
|
|
|
|
/* Drawing */
|
|
|
|
|
/***********/
|
|
|
|
|
|
|
|
|
|
/** prepare current buffer for drawing (draw "background") */
|
|
|
|
|
void
|
|
|
|
|
Canvas::clear ( void )
|
|
|
|
|
{
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* uint rule = m.grid->ppqn(); */
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* uint lx = m.grid->ts_to_x( m.grid->length() ); */
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* for ( uint y = m.vp->h; y--; ) */
|
|
|
|
|
/* for ( uint x = m.vp->w; x--; ) */
|
|
|
|
|
/* { */
|
|
|
|
|
/* m.current[ x ][ y ].color = 0; */
|
|
|
|
|
/* m.current[ x ][ y ].state = EMPTY; */
|
|
|
|
|
/* m.current[ x ][ y ].flags = 0; */
|
|
|
|
|
/* } */
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* for ( int x = m.vp->w - rule; x >= 0; x -= rule ) */
|
|
|
|
|
/* for ( uint y = m.vp->h; y-- ; ) */
|
|
|
|
|
/* m.current[ x ][ y ].state = LINE; */
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* int sx = (int)(lx - m.vp->x) >= 0 ? lx - m.vp->x : 0; */
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* for ( int x = sx; x < m.vp->w; ++x ) */
|
|
|
|
|
/* for ( int y = m.vp->h; y-- ; ) */
|
|
|
|
|
/* m.current[ x ][ y ].state = PARTIAL; */
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** is /x/ within the viewport? */
|
|
|
|
|
bool
|
|
|
|
|
Canvas::viewable_x ( int x )
|
|
|
|
|
{
|
|
|
|
|
return x >= m.vp->x && x < m.vp->x + m.vp->w;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** flush delta of last and current buffers to screen, then flip them */
|
|
|
|
|
void
|
|
|
|
|
Canvas::flip ( void )
|
|
|
|
|
{
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* /\* FIXME: should this not go in clear()? *\/ */
|
|
|
|
|
/* if ( m.p1 != m.p2 ) */
|
|
|
|
|
/* { */
|
|
|
|
|
/* if ( viewable_x( m.p1 ) ) draw_line( m.p1 - m.vp->x, F_P1 ); */
|
|
|
|
|
/* if ( viewable_x( m.p2 ) ) draw_line( m.p2 - m.vp->x, F_P2 ); */
|
|
|
|
|
/* } */
|
|
|
|
|
|
|
|
|
|
/* if ( viewable_x( m.playhead ) ) draw_line( m.playhead - m.vp->x, F_PLAYHEAD ); */
|
|
|
|
|
|
|
|
|
|
/* const int shape = m.grid->draw_shape(); */
|
|
|
|
|
|
|
|
|
|
/* for ( uint y = m.vp->h; y--; ) */
|
|
|
|
|
/* for ( uint x = m.vp->w; x--; ) */
|
|
|
|
|
/* { */
|
|
|
|
|
/* cell_t *c = &m.current[ x ][ y ]; */
|
|
|
|
|
/* cell_t *p = &m.previous[ x ][ y ]; */
|
|
|
|
|
|
|
|
|
|
/* /\* draw selection rect *\/ */
|
|
|
|
|
/* if ( m.p3 != m.p4 ) */
|
|
|
|
|
/* if ( y + m.vp->y >= m.p3 && x + m.vp->x >= m.p1 && */
|
|
|
|
|
/* y + m.vp->y <= m.p4 && x + m.vp->x < m.p2 ) */
|
|
|
|
|
/* c->flags |= F_SELECTION; */
|
|
|
|
|
|
|
|
|
|
/* if ( *c != *p ) */
|
|
|
|
|
/* gui_draw_shape( m.origin_x + m.margin_left + x * m.div_w, m.origin_y + m.margin_top + y * m.div_h, m.div_w, m.div_h, */
|
|
|
|
|
/* shape, c->state, c->flags, c->color ); */
|
|
|
|
|
/* } */
|
|
|
|
|
|
|
|
|
|
/* cell_t **tmp = m.previous; */
|
|
|
|
|
|
|
|
|
|
/* m.previous = m.current; */
|
|
|
|
|
/* m.current = tmp; */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
|
int
|
|
|
|
|
gui_draw_ruler ( int x, int y, int w, int div_w, int div, int ofs, int p1, int p2 )
|
|
|
|
|
{
|
|
|
|
|
/* Across the top */
|
|
|
|
|
|
|
|
|
|
fl_font( FL_TIMES, ruler_height );
|
|
|
|
|
|
|
|
|
|
int h = ruler_height;
|
|
|
|
|
|
|
|
|
|
fl_color( FL_BACKGROUND_COLOR );
|
|
|
|
|
|
|
|
|
|
// fl_rectf( x, y, x + (div_w * w), y + h );
|
|
|
|
|
fl_rectf( x, y, (div_w * w), h );
|
|
|
|
|
|
|
|
|
|
fl_color( FL_RED );
|
|
|
|
|
|
|
|
|
|
fl_line( x + div_w / 2, y, x + div_w * w, y );
|
|
|
|
|
|
|
|
|
|
char pat[40];
|
|
|
|
|
int z = div;
|
|
|
|
|
int i;
|
|
|
|
|
for ( i = 0; i < w; i++ )
|
|
|
|
|
if ( 0 == i % z )
|
|
|
|
|
{
|
|
|
|
|
int nx = x + (i * div_w) + (div_w / 2);
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
fl_color( FL_RED );
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
fl_line( nx, y, nx, y + h );
|
2012-03-01 05:46:57 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
int k = ofs + i;
|
|
|
|
|
sprintf( pat, "%i", 1 + (k / z ));
|
|
|
|
|
|
|
|
|
|
fl_color( FL_WHITE );
|
|
|
|
|
fl_draw( pat, nx + div_w / 2, y + h + 1 / 2 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( p1 != p2 )
|
|
|
|
|
{
|
|
|
|
|
if ( p1 >= 0 )
|
2007-12-18 05:09:02 +01:00
|
|
|
|
{
|
2012-10-25 23:13:23 +02:00
|
|
|
|
if ( p1 < p2 )
|
|
|
|
|
fl_color( FL_GREEN );
|
|
|
|
|
else
|
|
|
|
|
fl_color( FL_RED );
|
|
|
|
|
|
|
|
|
|
fl_rectf( x + (div_w * p1), y + h / 2, div_w, h / 2 );
|
|
|
|
|
|
2007-12-18 05:09:02 +01:00
|
|
|
|
}
|
2012-10-25 23:13:23 +02:00
|
|
|
|
if ( p2 >= 0 )
|
|
|
|
|
{
|
|
|
|
|
if ( p2 < p1 )
|
|
|
|
|
fl_color( FL_GREEN );
|
|
|
|
|
else
|
|
|
|
|
fl_color( FL_RED );
|
|
|
|
|
fl_rectf( x + (div_w * p2), y + h / 2, div_w, h / 2 );
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
return h;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
|
int
|
|
|
|
|
gui_draw_string ( int x, int y, int w, int h, int color, const char *s, bool draw )
|
|
|
|
|
{
|
|
|
|
|
int rw;
|
|
|
|
|
|
|
|
|
|
if ( ! s )
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
fl_font( FL_COURIER, min( h, 18 ) );
|
|
|
|
|
|
|
|
|
|
rw = fl_width( s );
|
|
|
|
|
|
|
|
|
|
if ( fl_not_clipped( x, y, rw, h ) && draw )
|
|
|
|
|
{
|
|
|
|
|
fl_rectf( x,y,w,h, FL_BACKGROUND_COLOR );
|
|
|
|
|
|
|
|
|
|
if ( color )
|
|
|
|
|
fl_color( velocity_colors[ color ] );
|
|
|
|
|
else
|
|
|
|
|
fl_color( FL_DARK_CYAN );
|
|
|
|
|
|
|
|
|
|
fl_draw( s, x, y + h / 2 + fl_descent() );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return rw;
|
2007-12-18 05:09:02 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** redraw the ruler at the top of the canvas */
|
|
|
|
|
void
|
|
|
|
|
Canvas::redraw_ruler ( void )
|
|
|
|
|
{
|
|
|
|
|
m.margin_top = gui_draw_ruler( m.origin_x + m.margin_left, m.origin_y, m.vp->w, m.div_w, m.grid->division(), m.vp->x,
|
|
|
|
|
m.p1 - m.vp->x, m.p2 - m.vp->x );
|
|
|
|
|
m.ruler_drawn = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** callback called by Grid::draw_row_names() to draw an individual row name */
|
|
|
|
|
void
|
|
|
|
|
Canvas::draw_row_name ( int y, const char *name, int color )
|
|
|
|
|
{
|
|
|
|
|
bool draw = m.draw;
|
|
|
|
|
bool clear = false;
|
|
|
|
|
|
|
|
|
|
y = ntr( y );
|
|
|
|
|
|
|
|
|
|
if ( ! m.row_compact && ! name )
|
|
|
|
|
clear = true;
|
|
|
|
|
|
|
|
|
|
y -= m.vp->y;
|
|
|
|
|
|
|
|
|
|
int bx = m.origin_x;
|
|
|
|
|
int by = m.origin_y + m.margin_top + y * m.div_h;
|
2012-03-01 08:00:59 +01:00
|
|
|
|
int bw = m.margin_left;
|
2007-12-18 05:09:02 +01:00
|
|
|
|
int bh = m.div_h;
|
|
|
|
|
|
|
|
|
|
if ( y < 0 || y >= m.vp->h )
|
|
|
|
|
draw = false;
|
|
|
|
|
|
|
|
|
|
if ( clear && draw )
|
2012-10-25 23:13:23 +02:00
|
|
|
|
fl_rectf( bx, by, bw, bh, FL_BACKGROUND_COLOR );
|
2007-12-18 05:09:02 +01:00
|
|
|
|
else
|
|
|
|
|
m.margin_left = max( m.margin_left, gui_draw_string( bx, by,
|
|
|
|
|
bw, bh,
|
|
|
|
|
color,
|
|
|
|
|
name,
|
|
|
|
|
draw ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** redraw row names */
|
|
|
|
|
void
|
|
|
|
|
Canvas::redraw_mapping ( void )
|
|
|
|
|
{
|
|
|
|
|
m.margin_left = 0;
|
|
|
|
|
|
|
|
|
|
m.draw = false;
|
|
|
|
|
|
|
|
|
|
m.grid->draw_row_names( this );
|
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
adj_size();
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
|
|
|
|
m.draw = true;
|
|
|
|
|
|
|
|
|
|
m.grid->draw_row_names( this );
|
|
|
|
|
|
|
|
|
|
m.mapping_drawn = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
Canvas::draw_mapping ( void )
|
|
|
|
|
{
|
|
|
|
|
if ( ! m.mapping_drawn ) redraw_mapping();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
Canvas::draw_ruler ( void )
|
|
|
|
|
{
|
|
|
|
|
if ( ! m.ruler_drawn ) redraw_ruler();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** "draw" a shape in the backbuffer */
|
|
|
|
|
void
|
2012-10-25 23:13:23 +02:00
|
|
|
|
Canvas::draw_shape ( int x, int y, int w, int color )
|
2007-12-18 05:09:02 +01:00
|
|
|
|
{
|
|
|
|
|
y = ntr( y );
|
|
|
|
|
|
|
|
|
|
if ( y < 0 )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
// adjust for viewport.
|
|
|
|
|
|
|
|
|
|
x -= m.vp->x;
|
|
|
|
|
y -= m.vp->y;
|
|
|
|
|
|
|
|
|
|
if ( x < 0 || y < 0 || x >= m.vp->w || y >= m.vp->h )
|
|
|
|
|
return;
|
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
fl_rectf( m.origin_x + m.margin_left + x * m.div_w,
|
|
|
|
|
m.origin_y + m.margin_top + y * m.div_h + 1,
|
|
|
|
|
m.div_w * w,
|
|
|
|
|
m.div_h - 1,
|
|
|
|
|
color );
|
2007-12-18 05:09:02 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** callback used by Grid::draw() */
|
|
|
|
|
void
|
2012-10-25 23:13:23 +02:00
|
|
|
|
Canvas::draw_dash ( int x, int y, int l, int color, void *userdata )
|
2007-12-18 05:09:02 +01:00
|
|
|
|
{
|
2012-10-25 23:13:23 +02:00
|
|
|
|
Canvas *o = (Canvas*)userdata;
|
|
|
|
|
|
|
|
|
|
color = velocity_colors[ color ];
|
|
|
|
|
|
|
|
|
|
o->draw_shape( x, y, 1, fl_color_average( FL_WHITE, color, 0.5 ) );
|
|
|
|
|
o->draw_shape( x + 1, y, l - 1, color );
|
2007-12-18 05:09:02 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** draw a vertical line with flags */
|
|
|
|
|
void
|
|
|
|
|
Canvas::draw_line ( int x, int flags )
|
|
|
|
|
{
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* for ( uint y = m.vp->h; y-- ; ) */
|
|
|
|
|
/* m.current[ x ][ y ].flags |= flags; */
|
2007-12-18 05:09:02 +01:00
|
|
|
|
}
|
|
|
|
|
|
2012-03-14 03:50:17 +01:00
|
|
|
|
int
|
|
|
|
|
Canvas::playhead_moved ( void )
|
|
|
|
|
{
|
|
|
|
|
int x = m.grid->ts_to_x( m.grid->index() );
|
|
|
|
|
|
|
|
|
|
return m.playhead != x;
|
|
|
|
|
}
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
|
|
|
|
/** draw only the playhead--without reexamining the grid */
|
|
|
|
|
int
|
|
|
|
|
Canvas::draw_playhead ( void )
|
|
|
|
|
{
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* int x = m.grid->ts_to_x( m.grid->index() ); */
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* if ( m.playhead == x ) */
|
|
|
|
|
/* return 0; */
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* m.playhead = x; */
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* if ( m.playhead < m.vp->x || m.playhead >= m.vp->x + m.vp->w ) */
|
|
|
|
|
/* { */
|
|
|
|
|
/* if ( config.follow_playhead ) */
|
|
|
|
|
/* { */
|
|
|
|
|
/* m.vp->x = m.playhead / m.vp->w * m.vp->w; */
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* m.ruler_drawn = false; */
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* signal_draw(); */
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* return 0; */
|
|
|
|
|
/* } */
|
|
|
|
|
/* } */
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* copy(); */
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* for ( uint x = m.vp->w; x-- ; ) */
|
|
|
|
|
/* for ( uint y = m.vp->h; y-- ; ) */
|
|
|
|
|
/* m.current[ x ][ y ].flags &= ~ (F_PLAYHEAD | F_P1 | F_P2 ); */
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* flip(); */
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* /\* actually if we're recording, we should draw the grid once per */
|
|
|
|
|
/* * playhead movement also *\/ */
|
|
|
|
|
/* if ( pattern::recording() == m.grid ) */
|
|
|
|
|
/* { */
|
|
|
|
|
/* draw(); */
|
|
|
|
|
/* } */
|
2012-03-01 04:57:23 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* return 1; */
|
2007-12-18 05:09:02 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** draw ONLY those nodes necessary to bring the canvas up-to-date with the grid */
|
|
|
|
|
void
|
|
|
|
|
Canvas::draw ( void )
|
|
|
|
|
{
|
2008-03-23 20:45:07 +01:00
|
|
|
|
DMESSAGE( "drawing canvas" );
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
|
|
|
|
draw_mapping();
|
|
|
|
|
draw_ruler();
|
|
|
|
|
|
|
|
|
|
m.grid_drawn = true;
|
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
fl_rectf( m.origin_x + m.margin_left, m.origin_y + m.margin_top, w(), h(), velocity_colors[10] );
|
|
|
|
|
|
|
|
|
|
/* draw grid */
|
|
|
|
|
|
|
|
|
|
fl_color( FL_BLACK );
|
|
|
|
|
for ( int gx = m.origin_x + m.margin_left;
|
|
|
|
|
gx < m.origin_x + m.margin_left + ( m.div_w * m.vp->w );
|
|
|
|
|
gx += m.div_w )
|
|
|
|
|
fl_line( gx, m.origin_y + m.margin_top, gx, m.origin_y + m.margin_top + ( m.div_w * m.vp->w ) );
|
|
|
|
|
|
|
|
|
|
for ( int gy = m.origin_y + m.margin_top;
|
|
|
|
|
gy < m.origin_y + m.margin_top + ( m.div_h * m.vp->h );
|
|
|
|
|
gy += m.div_h )
|
|
|
|
|
fl_line( m.origin_x + m.margin_left, gy, m.origin_x + m.margin_left + ( m.div_w * m.vp->w ), gy );
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
m.grid->draw_notes( draw_dash, this );
|
|
|
|
|
|
2007-12-18 05:09:02 +01:00
|
|
|
|
}
|
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* /\** redraw every node on the canvas from the buffer (without */
|
|
|
|
|
/* * necessarily reexamining the grid) *\/ */
|
|
|
|
|
/* void */
|
|
|
|
|
/* Canvas::redraw ( void ) */
|
|
|
|
|
/* { */
|
|
|
|
|
/* DMESSAGE( "redrawing canvas" ); */
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* if ( ! m.grid_drawn ) */
|
|
|
|
|
/* draw(); */
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* m.ruler_drawn = false; */
|
|
|
|
|
/* m.mapping_drawn = false; */
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* draw_mapping(); */
|
|
|
|
|
/* draw_ruler(); */
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* const int shape = m.grid->draw_shape(); */
|
2012-03-01 05:46:57 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* for ( int y = m.vp->h; y--; ) */
|
|
|
|
|
/* for ( int x = m.vp->w; x--; ) */
|
|
|
|
|
/* { */
|
|
|
|
|
/* cell_t c = m.previous[ x ][ y ]; */
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* if ( m.vp->x + x == m.playhead ) */
|
|
|
|
|
/* c.flags |= F_PLAYHEAD; */
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
2012-10-25 23:13:23 +02:00
|
|
|
|
/* gui_draw_shape( m.origin_x + m.margin_left + x * m.div_w, m.origin_y + m.margin_top + y * m.div_h, m.div_w, m.div_h, */
|
|
|
|
|
/* shape, c.state, c.flags, c.color ); */
|
|
|
|
|
/* } */
|
|
|
|
|
/* } */
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
|
|
|
|
/** convert pixel coords into grid coords. returns true if valid */
|
|
|
|
|
bool
|
2008-02-11 23:59:54 +01:00
|
|
|
|
Canvas::grid_pos ( int *x, int *y ) const
|
2007-12-18 05:09:02 +01:00
|
|
|
|
{
|
|
|
|
|
*y = (*y - m.margin_top - m.origin_y) / m.div_h;
|
|
|
|
|
*x = (*x - m.margin_left - m.origin_x) / m.div_w;
|
|
|
|
|
|
|
|
|
|
if ( *x < 0 || *y < 0 || *x >= m.vp->w || *y >= m.vp->h )
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
/* adjust for viewport */
|
|
|
|
|
*x += m.vp->x;
|
|
|
|
|
*y += m.vp->y;
|
|
|
|
|
|
|
|
|
|
/* adjust for row-compaction */
|
|
|
|
|
*y = rtn( *y );
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/******************/
|
|
|
|
|
/* Input handlers */
|
|
|
|
|
/******************/
|
|
|
|
|
|
|
|
|
|
/* These methods translate viewport pixel coords to absolute grid
|
|
|
|
|
coords and pass on to the grid. */
|
|
|
|
|
|
2008-02-11 23:59:54 +01:00
|
|
|
|
/** if coords correspond to a row name entry, return the (absolute) note number, otherwise return -1 */
|
|
|
|
|
int
|
|
|
|
|
Canvas::is_row_name ( int x, int y )
|
|
|
|
|
{
|
|
|
|
|
if ( x - m.origin_x >= m.margin_left )
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
x = m.margin_left;
|
|
|
|
|
|
|
|
|
|
grid_pos( &x, &y );
|
|
|
|
|
|
|
|
|
|
return m.grid->y_to_note( y );
|
|
|
|
|
}
|
|
|
|
|
|
2008-02-15 05:20:04 +01:00
|
|
|
|
void
|
|
|
|
|
Canvas::start_cursor ( int x, int y )
|
|
|
|
|
{
|
|
|
|
|
if ( ! grid_pos( &x, &y ) )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
m.ruler_drawn = false;
|
|
|
|
|
|
|
|
|
|
m.p1 = x;
|
|
|
|
|
m.p3 = ntr( y );
|
|
|
|
|
|
|
|
|
|
_lr();
|
|
|
|
|
|
|
|
|
|
signal_draw();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
Canvas::end_cursor ( int x, int y )
|
|
|
|
|
{
|
|
|
|
|
if ( ! grid_pos( &x, &y ) )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
m.ruler_drawn = false;
|
|
|
|
|
|
|
|
|
|
m.p2 = x;
|
|
|
|
|
m.p4 = ntr( y );
|
|
|
|
|
|
|
|
|
|
_lr();
|
|
|
|
|
|
|
|
|
|
signal_draw();
|
|
|
|
|
}
|
|
|
|
|
|
2007-12-18 05:09:02 +01:00
|
|
|
|
void
|
|
|
|
|
Canvas::set ( int x, int y )
|
|
|
|
|
{
|
|
|
|
|
if ( y - m.origin_y < m.margin_top )
|
|
|
|
|
/* looks like a click on the ruler */
|
|
|
|
|
{
|
|
|
|
|
if ( x - m.margin_left - m.origin_x >= 0 )
|
|
|
|
|
{
|
|
|
|
|
m.p1 = m.vp->x + ((x - m.margin_left - m.origin_x) / m.div_w);
|
|
|
|
|
m.ruler_drawn = false;
|
2008-02-15 05:20:04 +01:00
|
|
|
|
|
|
|
|
|
m.p3 = m.p4 = 0;
|
2007-12-18 05:09:02 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_lr();
|
|
|
|
|
|
|
|
|
|
signal_draw();
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( ! grid_pos( &x, &y ) )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
m.grid->put( x, y, 0 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
Canvas::unset ( int x, int y )
|
|
|
|
|
{
|
|
|
|
|
if ( y - m.origin_y < m.margin_top )
|
|
|
|
|
/* looks like a click on the ruler */
|
|
|
|
|
{
|
|
|
|
|
if ( x - m.margin_left - m.origin_x >= 0 )
|
|
|
|
|
{
|
|
|
|
|
m.p2 = m.vp->x + ((x - m.margin_left - m.origin_x) / m.div_w);
|
|
|
|
|
m.ruler_drawn = false;
|
2008-02-15 05:20:04 +01:00
|
|
|
|
|
|
|
|
|
m.p3 = m.p4 = 0;
|
2007-12-18 05:09:02 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_lr();
|
|
|
|
|
|
|
|
|
|
signal_draw();
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( ! grid_pos( &x, &y ) )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
m.grid->del( x, y );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
Canvas::adj_color ( int x, int y, int n )
|
|
|
|
|
{
|
|
|
|
|
if ( ! grid_pos( &x, &y ) )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
m.grid->adj_velocity( x, y, n );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
Canvas::adj_length ( int x, int y, int n )
|
|
|
|
|
{
|
|
|
|
|
if ( ! grid_pos( &x, &y ) )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
m.grid->adj_duration( x, y, n );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
Canvas::select ( int x, int y )
|
|
|
|
|
{
|
|
|
|
|
if ( ! grid_pos( &x, &y ) )
|
|
|
|
|
return;
|
|
|
|
|
|
2008-02-15 05:20:04 +01:00
|
|
|
|
m.grid->toggle_select( x, y );
|
2007-12-18 05:09:02 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
Canvas::move_selected ( int dir, int n )
|
|
|
|
|
{
|
|
|
|
|
switch ( dir )
|
|
|
|
|
{
|
|
|
|
|
case RIGHT:
|
|
|
|
|
m.grid->move_selected( n );
|
|
|
|
|
break;
|
|
|
|
|
case LEFT:
|
|
|
|
|
m.grid->move_selected( 0 - n );
|
|
|
|
|
break;
|
|
|
|
|
case UP:
|
|
|
|
|
case DOWN:
|
|
|
|
|
{
|
|
|
|
|
/* row-compaction makes this a little complicated */
|
|
|
|
|
event_list *el = m.grid->events();
|
|
|
|
|
|
|
|
|
|
/* FIXME: don't allow movement beyond the edges! */
|
|
|
|
|
|
|
|
|
|
/* int hi, lo; */
|
|
|
|
|
|
|
|
|
|
/* m.grid->selected_hi_lo_note( &hi, &lo ); */
|
|
|
|
|
|
|
|
|
|
/* hi = ntr( hi ) > 0 ? ntr( hi ) : */
|
|
|
|
|
|
|
|
|
|
/* if ( m.grid->y_to_note( ntr( hi ) ) ) */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( dir == UP )
|
|
|
|
|
for ( int y = 0; y <= m.maxh; ++y )
|
|
|
|
|
el->rewrite_selected( m.grid->y_to_note( rtn( y ) ), m.grid->y_to_note( rtn( y - n ) ) );
|
|
|
|
|
else
|
|
|
|
|
for ( int y = m.maxh; y >= 0; --y )
|
|
|
|
|
el->rewrite_selected( m.grid->y_to_note( rtn( y ) ), m.grid->y_to_note( rtn( y + n ) ) );
|
|
|
|
|
|
|
|
|
|
m.grid->events( el );
|
|
|
|
|
|
|
|
|
|
delete el;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
Canvas::randomize_row ( int y )
|
|
|
|
|
{
|
|
|
|
|
int x = m.margin_left;
|
|
|
|
|
|
|
|
|
|
if ( ! grid_pos( &x, &y ) )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
((pattern*)m.grid)->randomize_row( y, song.random.feel, song.random.probability );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
Canvas::_lr ( void )
|
|
|
|
|
{
|
|
|
|
|
int l, r;
|
|
|
|
|
|
|
|
|
|
if ( m.p2 > m.p1 )
|
|
|
|
|
{
|
|
|
|
|
l = m.p1;
|
|
|
|
|
r = m.p2;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
l = m.p2;
|
|
|
|
|
r = m.p1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m.p1 = l;
|
|
|
|
|
m.p2 = r;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
Canvas::select_range ( void )
|
|
|
|
|
{
|
2008-02-15 05:20:04 +01:00
|
|
|
|
if ( m.p3 == m.p4 )
|
|
|
|
|
m.grid->select( m.p1, m.p2 );
|
|
|
|
|
else
|
|
|
|
|
m.grid->select( m.p1, m.p2, rtn( m.p3 ), rtn( m.p4 ) );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
Canvas::invert_selection ( void )
|
|
|
|
|
{
|
|
|
|
|
m.grid->invert_selection();
|
2007-12-18 05:09:02 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
Canvas::crop ( void )
|
|
|
|
|
{
|
2008-02-15 06:07:50 +01:00
|
|
|
|
if ( m.p3 == m.p4 )
|
|
|
|
|
m.grid->crop( m.p1, m.p2 );
|
|
|
|
|
else
|
|
|
|
|
m.grid->crop( m.p1, m.p2, rtn( m.p3 ), rtn( m.p4 ) );
|
2007-12-18 05:09:02 +01:00
|
|
|
|
|
|
|
|
|
m.vp->x = 0;
|
|
|
|
|
|
|
|
|
|
m.p2 = m.p2 - m.p1;
|
|
|
|
|
m.p1 = 0;
|
|
|
|
|
|
|
|
|
|
m.ruler_drawn = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
Canvas::delete_time ( void )
|
|
|
|
|
{
|
|
|
|
|
m.grid->delete_time( m.p1, m.p2 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
Canvas::insert_time ( void )
|
|
|
|
|
{
|
|
|
|
|
m.grid->insert_time( m.p1, m.p2 );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** paste range as new grid */
|
|
|
|
|
void
|
|
|
|
|
Canvas::duplicate_range ( void )
|
|
|
|
|
{
|
|
|
|
|
Grid *g = m.grid->clone();
|
|
|
|
|
|
|
|
|
|
g->crop( m.p1, m.p2 );
|
|
|
|
|
g->viewport.x = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
Canvas::row_compact ( int n )
|
|
|
|
|
{
|
|
|
|
|
switch ( n )
|
|
|
|
|
{
|
|
|
|
|
case OFF:
|
|
|
|
|
m.row_compact = false;
|
|
|
|
|
m.maxh = 128;
|
|
|
|
|
break;
|
|
|
|
|
case ON:
|
|
|
|
|
m.row_compact = true;
|
|
|
|
|
m.vp->y = 0;
|
|
|
|
|
_update_row_mapping();
|
|
|
|
|
break;
|
|
|
|
|
case TOGGLE:
|
|
|
|
|
row_compact( m.row_compact ? OFF : ON );
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-10-25 23:13:23 +02:00
|
|
|
|
// _reset();
|
2007-12-18 05:09:02 +01:00
|
|
|
|
m.mapping_drawn = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
Canvas::pan ( int dir, int n )
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
switch ( dir )
|
|
|
|
|
{
|
|
|
|
|
case LEFT: case RIGHT: case TO_PLAYHEAD: case TO_NEXT_NOTE: case TO_PREV_NOTE:
|
|
|
|
|
/* handle horizontal movement specially */
|
|
|
|
|
n *= m.grid->division();
|
|
|
|
|
m.ruler_drawn = false;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
n *= 5;
|
|
|
|
|
m.mapping_drawn = false;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch ( dir )
|
|
|
|
|
{
|
|
|
|
|
case LEFT:
|
|
|
|
|
m.vp->x = max( m.vp->x - n, 0 );
|
|
|
|
|
break;
|
|
|
|
|
case RIGHT:
|
|
|
|
|
m.vp->x += n;
|
|
|
|
|
break;
|
|
|
|
|
case TO_PLAYHEAD:
|
|
|
|
|
m.vp->x = m.playhead - (m.playhead % m.grid->division());
|
|
|
|
|
break;
|
|
|
|
|
case UP:
|
|
|
|
|
m.vp->y = max( m.vp->y - n, 0 );
|
|
|
|
|
break;
|
|
|
|
|
case DOWN:
|
|
|
|
|
m.vp->y = min( m.vp->y + n, m.maxh - m.vp->h );
|
|
|
|
|
break;
|
|
|
|
|
case TO_NEXT_NOTE:
|
|
|
|
|
{
|
|
|
|
|
int x = m.grid->next_note_x( m.vp->x );
|
|
|
|
|
m.vp->x = x - (x % m.grid->division() );
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case TO_PREV_NOTE:
|
|
|
|
|
{
|
|
|
|
|
int x = m.grid->prev_note_x( m.vp->x );
|
|
|
|
|
m.vp->x = x - (x % m.grid->division() );
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
signal_draw();
|
2012-03-01 08:00:38 +01:00
|
|
|
|
signal_pan();
|
2007-12-18 05:09:02 +01:00
|
|
|
|
}
|
|
|
|
|
|
2012-03-01 08:00:38 +01:00
|
|
|
|
void
|
|
|
|
|
Canvas::can_scroll ( int *left, int *right, int *up, int *down )
|
|
|
|
|
{
|
|
|
|
|
*left = m.vp->x;
|
|
|
|
|
*right = -1;
|
|
|
|
|
*up = m.vp->y;
|
|
|
|
|
*down = m.maxh - ( m.vp->y + m.vp->h );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2007-12-18 05:09:02 +01:00
|
|
|
|
/** adjust horizontal zoom (* n) */
|
|
|
|
|
void
|
|
|
|
|
Canvas::h_zoom ( float n )
|
|
|
|
|
{
|
|
|
|
|
m.vp->w = max( 32, min( (int)(m.vp->w * n), 256 ) );
|
|
|
|
|
|
|
|
|
|
resize_grid();
|
2008-03-23 05:43:40 +01:00
|
|
|
|
|
|
|
|
|
song.set_dirty();
|
2007-12-18 05:09:02 +01:00
|
|
|
|
}
|
|
|
|
|
|
2008-02-13 00:04:38 +01:00
|
|
|
|
void
|
|
|
|
|
Canvas::v_zoom_fit ( void )
|
|
|
|
|
{
|
|
|
|
|
if ( ! m.grid )
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
changed_mapping();
|
|
|
|
|
|
|
|
|
|
m.vp->h = m.maxh;
|
|
|
|
|
m.vp->y = 0;
|
|
|
|
|
|
|
|
|
|
resize_grid();
|
2008-03-23 05:43:40 +01:00
|
|
|
|
|
|
|
|
|
song.set_dirty();
|
|
|
|
|
|
2008-02-13 00:04:38 +01:00
|
|
|
|
}
|
|
|
|
|
|
2007-12-18 05:09:02 +01:00
|
|
|
|
/** adjust vertical zoom (* n) */
|
|
|
|
|
void
|
|
|
|
|
Canvas::v_zoom ( float n )
|
|
|
|
|
{
|
|
|
|
|
m.vp->h = max( 1, min( (int)(m.vp->h * n), m.maxh ) );
|
|
|
|
|
|
|
|
|
|
resize_grid();
|
2008-03-23 05:43:40 +01:00
|
|
|
|
|
|
|
|
|
song.set_dirty();
|
2007-12-18 05:09:02 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
Canvas::notes ( char *s )
|
|
|
|
|
{
|
|
|
|
|
m.grid->notes( s );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *
|
|
|
|
|
Canvas::notes ( void )
|
|
|
|
|
{
|
|
|
|
|
return m.grid->notes();
|
|
|
|
|
}
|