undo/redo-support for track-content-objects

git-svn-id: https://lmms.svn.sf.net/svnroot/lmms/trunk/lmms@106 0778d3d1-df1d-0410-868b-ea421aaaa00d
This commit is contained in:
Tobias Doerffel
2006-03-15 08:54:33 +00:00
parent 8d5e274269
commit e81c9700c2
11 changed files with 159 additions and 40 deletions

View File

@@ -1,5 +1,19 @@
2006-03-14 Tobias Doerffel <tobydox/at/users/dot/sourceforge/dot/net>
* include/types.h:
added type for editable-object-ID
* include/track.h:
* src/core/track.cpp:
* src/tracks/bb_track.cpp:
* src/tracks/pattern.cpp:
* src/tracks/sample_track.cpp:
undo/redo-support for position- and size-changes of TCO
* include/automatable_object.h:
added methods for saving step-recording-state on stack and restoring
it
* include/automatable_object.h:
* include/automatable_button.h:
* include/knob.h:

2
TODO
View File

@@ -1,3 +1,5 @@
- implement editableSettingsObject
- unique id's for all editable objects
- add edit-history to project for making it possible to undo things even if you did them in a previous session
- make edit-history qobject and undo/redo slots -> direct connection to GUI
- restore stacking-order of windows when loading project

View File

@@ -2,8 +2,8 @@
# Process this file with autoconf to produce a configure script.
AC_PREREQ(2.50)
AC_INIT(lmms, 0.1.4-cvs20060313, tobydox/at/users/dot/sourceforge/dot/net)
AM_INIT_AUTOMAKE(lmms, 0.1.4-cvs20060313)
AC_INIT(lmms, 0.1.4-cvs20060314, tobydox/at/users/dot/sourceforge/dot/net)
AM_INIT_AUTOMAKE(lmms, 0.1.4-cvs20060314)
AM_CONFIG_HEADER(config.h)

View File

@@ -127,10 +127,9 @@ public:
inline virtual void setInitValue( const T _value )
{
const bool sr = isRecordingSteps();
setStepRecording( FALSE );
saveStepRecordingState( FALSE );
setValue( _value );
setStepRecording( sr );
restoreStepRecordingState();
}
inline virtual void setValue( const T _value )
@@ -159,11 +158,10 @@ public:
it->fittedValue( value() ) !=
it->value() )
{
const bool sr = it->isRecordingSteps();
it->setStepRecording(
it->saveStepRecordingState(
isRecordingSteps() );
it->setValue( value() );
it->setStepRecording( sr );
it->restoreStepRecordingState();
}
}
}
@@ -244,8 +242,7 @@ public:
protected:
virtual void redoStep( const editStep & _edit_step )
{
const bool sr = isRecordingSteps();
setStepRecording( FALSE );
saveStepRecordingState( FALSE );
#ifndef QT3
setValue( static_cast<T>( value() +
_edit_step.data().value<EDIT_STEP_TYPE>() ) );
@@ -253,7 +250,7 @@ protected:
setValue( static_cast<T>( value() + static_cast<EDIT_STEP_TYPE>(
_edit_step.data().toDouble() ) ) );
#endif
setStepRecording( sr );
restoreStepRecordingState();
}
virtual void undoStep( const editStep & _edit_step )

View File

@@ -57,8 +57,10 @@ class QColorGroup;
typedef int csize;
#define QListViewItem Q3ListViewItem
#define vvector QVector
#define vlist QList
#define vstack QStack
#define vvector QVector
#include <QFileInfo>
@@ -72,8 +74,10 @@ inline QString baseName( const QString & _file )
#else /* QT3 */
#define vvector QValueVector
#define vlist QValueList
#define vstack QValueStack
#define vvector QValueVector
#define QMenu QPopupMenu
#define QAbstractButton QButton

View File

@@ -57,6 +57,7 @@
#include "settings.h"
#include "rubberband.h"
#include "engine.h"
#include "editable_object.h"
class QMenu;
@@ -79,7 +80,7 @@ const Uint16 TCO_BORDER_WIDTH = 1;
class trackContentObject : public selectableObject, public settings,
public engineObject
public editableObject
{
Q_OBJECT
public:
@@ -129,6 +130,9 @@ protected:
void setAutoResizeEnabled( bool _e = FALSE );
float pixelsPerTact( void );
virtual void undoStep( const editStep & _edit_step );
virtual void redoStep( const editStep & _edit_step );
protected slots:
void cut( void );
@@ -153,12 +157,14 @@ private:
textFloat * m_hint;
midiTime m_oldTime;// used for undo/redo while mouse-button is pressed
} ;
class trackContentWidget : public QWidget
class trackContentWidget : public QWidget, public editableObject
{
Q_OBJECT
public:
@@ -200,8 +206,16 @@ protected:
virtual void paintEvent( QPaintEvent * _pe );
virtual void resizeEvent( QResizeEvent * _re );
virtual void undoStep( const editStep & _edit_step );
virtual void redoStep( const editStep & _edit_step );
private:
enum actions
{
ADD_TCO, REMOVE_TCO
} ;
track * getTrack( void );
midiTime getPosition( int _mouse_x );

View File

@@ -54,4 +54,6 @@ typedef Uint16 bpm_t; // tempo (MIN_BPM to MAX_BPM)
typedef Uint16 bitrate_t; // bitrate in kbps
typedef Sint8 fx_ch_t; // FX-channel (0 to MAX_EFFECT_CHANNEL)
typedef Uint32 eo_id_t; // (unique) ID of an editable object
#endif

View File

@@ -88,7 +88,8 @@ trackContentObject::trackContentObject( track * _track ) :
, Qt::WDestructiveClose
#endif
),
engineObject( _track->eng() ),
settings(),
editableObject( _track->eng() ),
m_track( _track ),
m_startPosition(),
m_length(),
@@ -110,8 +111,11 @@ trackContentObject::trackContentObject( track * _track ) :
setFocusPolicy( StrongFocus );
#endif
show();
setStepRecording( FALSE );
movePosition( 0 );
changeLength( 0 );
setStepRecording( TRUE );
setFixedHeight( parentWidget()->height() - 2 );
setAcceptDrops( TRUE );
@@ -141,9 +145,10 @@ void trackContentObject::movePosition( const midiTime & _pos )
{
if( m_startPosition != _pos )
{
getTrack()->eng()->getSongEditor()->setModified();
//getTrack()->eng()->getSongEditor()->setModified();
addStep( editStep( MOVE, m_startPosition - _pos ) );
m_startPosition = _pos;
}
m_startPosition = _pos;
m_track->getTrackWidget()->changePosition();
// moving a TCO can result in change of song-length etc.,
// therefore we update the track-container
@@ -157,34 +162,20 @@ void trackContentObject::changeLength( const midiTime & _length )
{
if( m_length != _length )
{
getTrack()->eng()->getSongEditor()->setModified();
//getTrack()->eng()->getSongEditor()->setModified();
addStep( editStep( RESIZE, m_length - _length ) );
m_length = _length;
}
m_length = _length;
setFixedWidth( static_cast<int>( m_length * pixelsPerTact() / 64 ) +
TCO_BORDER_WIDTH * 2 );
setFixedWidth( static_cast<int>( m_length * pixelsPerTact() /
64 ) + TCO_BORDER_WIDTH * 2 );
// changing length of TCO can result in change of song-length etc.,
// therefore we update the trackcontainer
// therefore we update the track-container
m_track->getTrackContainer()->update();
}
float trackContentObject::pixelsPerTact( void )
{
if( fixedTCOs() )
{
return( ( getTrack()->getTrackContentWidget()->width() -
2 * TCO_BORDER_WIDTH -
DEFAULT_SCROLLBAR_SIZE ) /
tMax<float>( length().getTact(), 1.0f ) );
}
return( getTrack()->getTrackContainer()->pixelsPerTact() );
}
void trackContentObject::dragEnterEvent( QDragEnterEvent * _dee )
{
stringPairDrag::processDragEnterEvent( _dee, "tco_" +
@@ -283,11 +274,14 @@ void trackContentObject::mousePressEvent( QMouseEvent * _me )
/* eng()->getMainWindow()->isShiftPressed() == FALSE &&*/
fixedTCOs() == FALSE )
{
setStepRecording( FALSE );
m_initialMouseX = _me->x();
if( _me->x() < width() - RESIZE_GRIP_WIDTH )
{
m_action = MOVE;
m_oldTime = m_startPosition;
QCursor c( Qt::SizeAllCursor );
QApplication::setOverrideCursor( c );
s_textFloat->setTitle( tr( "Current position" ) );
@@ -300,6 +294,7 @@ void trackContentObject::mousePressEvent( QMouseEvent * _me )
else if( m_autoResize == FALSE )
{
m_action = RESIZE;
m_oldTime = m_length;
QCursor c( Qt::SizeHorCursor );
QApplication::setOverrideCursor( c );
s_textFloat->setTitle( tr( "Current length" ) );
@@ -434,6 +429,13 @@ void trackContentObject::mouseMoveEvent( QMouseEvent * _me )
void trackContentObject::mouseReleaseEvent( QMouseEvent * _me )
{
if( m_action == MOVE || m_action == RESIZE )
{
setStepRecording( TRUE );
addStep( editStep( m_action, m_oldTime -
( ( m_action == MOVE ) ?
m_startPosition : m_length ) ) );
}
m_action = NONE;
delete m_hint;
m_hint = NULL;
@@ -476,6 +478,49 @@ void trackContentObject::contextMenuEvent( QContextMenuEvent * _cme )
float trackContentObject::pixelsPerTact( void )
{
if( fixedTCOs() )
{
return( ( getTrack()->getTrackContentWidget()->width() -
2 * TCO_BORDER_WIDTH -
DEFAULT_SCROLLBAR_SIZE ) /
tMax<float>( length().getTact(), 1.0f ) );
}
return( getTrack()->getTrackContainer()->pixelsPerTact() );
}
void trackContentObject::undoStep( const editStep & _edit_step )
{
saveStepRecordingState( FALSE );
switch( _edit_step.actionID() )
{
case MOVE:
movePosition( startPosition() +
_edit_step.data().toInt() );
break;
case RESIZE:
changeLength( length() + _edit_step.data().toInt() );
break;
}
restoreStepRecordingState();
}
void trackContentObject::redoStep( const editStep & _edit_step )
{
undoStep( editStep( _edit_step.actionID(),
-_edit_step.data().toInt() ) );
}
void trackContentObject::close( void )
{
m_track->getTrackContentWidget()->removeTCO( this, FALSE );
@@ -531,6 +576,7 @@ void trackContentObject::setAutoResizeEnabled( bool _e )
// ===========================================================================
trackContentWidget::trackContentWidget( trackWidget * _parent ) :
QWidget( _parent ),
editableObject( _parent->getTrack()->eng() ),
m_trackWidget( _parent )
{
#ifdef QT4
@@ -579,9 +625,14 @@ csize trackContentWidget::numOfTCOs( void )
trackContentObject * FASTCALL trackContentWidget::addTCO(
trackContentObject * _tco )
{
//addStep( editStep( ADD_TCO, 0 ) );
m_trackContentObjects.push_back( _tco );
_tco->move( 0, 1 );
_tco->saveStepRecordingState( FALSE );
m_trackWidget->changePosition();
_tco->restoreStepRecordingState();
getTrack()->eng()->getSongEditor()->setModified();
return( _tco ); // just for convenience
}
@@ -605,6 +656,7 @@ void trackContentWidget::removeTCO( trackContentObject * _tco,
_tco );
if( it != m_trackContentObjects.end() )
{
//addStep( editStep( REMOVE_TCO, 0 ) );
if( _also_delete )
{
delete _tco;
@@ -757,10 +809,12 @@ void trackContentWidget::mousePressEvent( QMouseEvent * _me )
else if( _me->button() == Qt::LeftButton &&
getTrack()->getTrackContainer()->fixedTCOs() == FALSE )
{
const midiTime pos = getPosition( _me->x() ).toNearestTact();
const midiTime pos = getPosition( _me->x() ).getTact() * 64;
trackContentObject * tco = addTCO( getTrack()->createTCO(
pos ) );
tco->saveStepRecordingState( FALSE );
tco->movePosition( pos );
tco->restoreStepRecordingState();
}
}
@@ -807,6 +861,31 @@ void trackContentWidget::resizeEvent( QResizeEvent * _re )
void trackContentWidget::undoStep( const editStep & _edit_step )
{
saveStepRecordingState( FALSE );
switch( _edit_step.actionID() )
{
case ADD_TCO:
break;
case REMOVE_TCO:
break;
}
restoreStepRecordingState();
}
void trackContentWidget::redoStep( const editStep & _edit_step )
{
/* undoStep( editStep( _edit_step.actionID(),
-_edit_step.data().toInt() ) );*/
}
track * trackContentWidget::getTrack( void )
{
return( m_trackWidget->getTrack() );

View File

@@ -72,7 +72,9 @@ bbTCO::bbTCO( track * _track, const QColor & _c ) :
bbTrack::numOfBBTrack( getTrack() ) );
if( t > 0 )
{
saveStepRecordingState( FALSE );
changeLength( midiTime( t, 0 ) );
restoreStepRecordingState();
}
}

View File

@@ -186,9 +186,12 @@ void pattern::init( void )
s_frozen = new QPixmap( embed::getIconPixmap( "frozen" ) );
}
saveStepRecordingState( FALSE );
ensureBeatNotes();
changeLength( length() );
restoreStepRecordingState();
#ifndef QT4
// set background-mode for flicker-free redraw

View File

@@ -64,7 +64,9 @@ sampleTCO::sampleTCO( track * _track ) :
setBackgroundMode( Qt::NoBackground );
#endif
saveStepRecordingState( FALSE );
setSampleFile( "" );
restoreStepRecordingState();
// we need to receive bpm-change-events, because then we have to
// change length of this TCO