Tidied up, simplified and documented expand animation code

This commit is contained in:
Joel Holdsworth 2009-01-05 20:03:52 +00:00
parent 22c9e8b082
commit b48d8fc49b
3 changed files with 130 additions and 59 deletions

View file

@ -185,12 +185,6 @@ TimelineLayoutHelper::layout_headers_recursive(
shared_ptr<timeline::Track> timeline_track =
lookup_timeline_track(model_track);
// Is the track animating?
const int track_animation_state =
timeline_track->get_expand_animation_state();
if(track_animation_state != Track::NoAnimationState)
is_animating = true;
// Is the track going to be shown?
if(parent_expanded)
{
@ -207,6 +201,11 @@ TimelineLayoutHelper::layout_headers_recursive(
// Offset for the next header
child_offset += track_height + TimelineWidget::TrackPadding;
}
// Is the track animating?
const bool is_track_animating =
timeline_track->is_expand_animating();
is_animating |= is_track_animating;
// Recurse to children
const bool expand_child =
@ -218,15 +217,11 @@ TimelineLayoutHelper::layout_headers_recursive(
header_width, indent_width, depth + 1, expand_child);
// Do collapse animation as necessary
if(track_animation_state != Track::NoAnimationState)
{
// Tick the track expand animation
timeline_track->tick_expand_animation();
if(is_track_animating)
{
// Calculate the height of te area which will be
// shown as expanded
const float a = ((float)track_animation_state /
(float)Track::MaxExpandAnimation);
const float a = timeline_track->get_expand_animation_state();
child_branch_height *= a * a;
const int y_limit =
branch_offset + child_offset + child_branch_height;
@ -248,6 +243,9 @@ TimelineLayoutHelper::layout_headers_recursive(
if(rect.get_y() + rect.get_height() > y_limit)
headerBoxes.erase(track);
}
// Tick the track expand animation
timeline_track->tick_expand_animation();
}
child_offset += child_branch_height;

View file

@ -36,26 +36,19 @@ namespace gui {
namespace widgets {
namespace timeline {
const int Track::NoAnimationState = -1;
const int Track::MaxExpandAnimation = 65536;
const double Track::ExpandAnimationPeriod = 0.15;
Glib::Timer Track::timer;
const float Track::ExpandAnimationPeriod = 0.15;
Track::Track(TimelineWidget &timeline_widget,
shared_ptr<model::Track> track) :
timelineWidget(timeline_widget),
model_track(track),
expanded(true),
expandAnimationState(Track::NoAnimationState),
expandDirection(None),
enableButton(Gtk::StockID("track_enabled")),
lockButton(Gtk::StockID("track_unlocked"))
{
REQUIRE(model_track);
// Ensure that the timer is running
timer.start();
titleMenuButton.set_relief(RELIEF_HALF);
buttonBar.append(enableButton);
@ -121,71 +114,81 @@ Track::get_expanded() const
void
Track::expand_collapse(ExpandDirection direction)
{
REQUIRE(direction != None);
expandDirection = direction;
if(direction == Expand)
{
expanded = true;
expandAnimationState = 0;
expandAnimationState = 0.0;
}
else
{
expanded = false;
expandAnimationState = MaxExpandAnimation;
expandAnimationState = 1.0;
}
lastTickTime = timer.elapsed();
// Create a timer if we don't already have one
if(!expand_timer)
{
expand_timer.reset(new Glib::Timer());
expand_timer->start();
}
else // Reset the timer if we do
expand_timer->reset();
}
int
float
Track::get_expand_animation_state() const
{
ENSURE((expandAnimationState >= 0 &&
expandAnimationState <= MaxExpandAnimation) ||
expandAnimationState == NoAnimationState);
ENSURE(expandAnimationState >= 0.0 &&
expandAnimationState <= 1.0);
return expandAnimationState;
}
bool
Track::is_expand_animating() const
{
return expandDirection != None;
}
void
Track::tick_expand_animation()
{
if(expandAnimationState <= NoAnimationState)
{
WARN(gui, "tick_expand_animation() was called when"
" expandAnimationState was set to NoAnimationState");
return;
}
const double delta = MaxExpandAnimation * (timer.elapsed() - lastTickTime) / ExpandAnimationPeriod;
REQUIRE(expandDirection != None); // tick_expand_animation should not
// be unless is_expand_animating
// returns true
REQUIRE(expand_timer);
const float delta =
(float)expand_timer->elapsed() / ExpandAnimationPeriod;
expand_timer->reset(); // reset the timer to t=0
if(expandDirection == Expand)
{
expandAnimationState += delta;
if(expandAnimationState >= MaxExpandAnimation)
expandAnimationState = NoAnimationState;
if(expandAnimationState >= 1.0)
expandDirection = None;
}
else
{
expandAnimationState -= delta;
if(expandAnimationState <= 0)
expandAnimationState = NoAnimationState;
if(expandAnimationState <= 0.0)
expandDirection = None;
}
lastTickTime = timer.elapsed();
ENSURE((expandAnimationState >= 0 &&
expandAnimationState <= MaxExpandAnimation) ||
expandAnimationState == NoAnimationState);
if(expandDirection == None)
expand_timer.reset(); // We've finished with the timer - delete it
}
Gtk::ExpanderStyle
Track::get_expander_style() const
{
const int notch = Track::MaxExpandAnimation / 3;
const int notch = 1.0 / 3.0;
if(expanded)
{
if(expandAnimationState == Track::NoAnimationState)
if(expandDirection == None)
return EXPANDER_EXPANDED;
else if(expandAnimationState >= notch * 2)
else if(expandAnimationState >= notch * 2.0)
return EXPANDER_SEMI_EXPANDED;
else if(expandAnimationState >= notch)
return EXPANDER_SEMI_COLLAPSED;
@ -194,11 +197,11 @@ Track::get_expander_style() const
}
else
{
if(expandAnimationState == Track::NoAnimationState)
if(expandDirection == None)
return EXPANDER_COLLAPSED;
else if(expandAnimationState <= notch)
return EXPANDER_SEMI_COLLAPSED;
else if(expandAnimationState <= notch * 2)
else if(expandAnimationState <= notch * 2.0)
return EXPANDER_SEMI_EXPANDED;
else
return EXPANDER_EXPANDED;

View file

@ -37,12 +37,23 @@ namespace timeline {
class TimelineViewWindow;
/**
* Timeline tracks are created by the timeline widget to correspond to
* model tracks. Timeline tracks are used to store UI specific state
* data.
**/
class Track : public sigc::trackable
{
public:
/**
* An enum used by the branch expand/collapse animation.
* ExpandDirection represents whether the branch us being expanded or
* collapsed, or neither.
**/
enum ExpandDirection
{
None,
Expand,
Collapse
};
@ -57,15 +68,48 @@ public:
int get_height() const;
/**
* Gets whether the descendant tracks are expanded or collapsed.
* @return Returns true if the branch is expanded, false if it's
* collapsed.
* @see expand_collapse
**/
bool get_expanded() const;
/**
* Expands or collapses this branch.
* @param direction Specifies whether this branch should be expanded
* or collapse. direction must not equal None
**/
void expand_collapse(ExpandDirection direction);
// -1 for no animation
int get_expand_animation_state() const;
/**
* The current expand state.
* @return Returns the expand state value, this value is a number
* between 0 and 1.0, and is recalculated by tick_expand_animation().
* @remarks A value of 1.0 is given when the branch is fully expanded
* (and animating), 0.0 is given when the branch is fully collapsed
* (and animating). When the branch is not animating this value has
* an indeterminate value.
* @see tick_expand_animation
**/
float get_expand_animation_state() const;
/**
* Gets whether the branch is animation.
* @return Returns true if the branch is animating, false if not.
**/
bool is_expand_animating() const;
/**
* When this track is being animated, tick_expand_animation must be
* called repeatedly to cause the animation to progress.
**/
void tick_expand_animation();
/**
* Calculates the expander style, given the animation state.
**/
Gtk::ExpanderStyle get_expander_style() const;
void show_header_context_menu(guint button, guint32 time);
@ -75,9 +119,12 @@ public:
const = 0;
public:
static const int NoAnimationState;
static const int MaxExpandAnimation;
static const double ExpandAnimationPeriod;
//----- Constants -----//
/**
* Specifies the period of the expand animation in seconds.
**/
static const float ExpandAnimationPeriod;
private:
//----- Internals -----//
@ -96,13 +143,36 @@ protected:
boost::shared_ptr<model::Track> model_track;
private:
/**
* This bool is true if this branch is expanded. false if it is
* collapsed.
**/
bool expanded;
/**
* This enum specifies which direction the expand/collapse animation
* is moving - if any.
* @remarks If no animation is occuring, expandDirection is set to
* None.
**/
ExpandDirection expandDirection;
/**
* The current expand state.
* @remarks This value is a number between 0 and 1.0,
* and is recalculated by tick_expand_animation(). This variable is
* set to 1.0 when the branch is fully expanded (and animating) and
* 0.0 when the branch is fully collapsed (and animating). When the
* branch is not animating this value has an indeterminate value.
* @see tick_expand_animation
**/
double expandAnimationState;
static Glib::Timer timer;
double lastTickTime;
/**
* An internal timer used for the expand/collapse animation.
**/
boost::scoped_ptr<Glib::Timer> expand_timer;
//----- Header Widgets ------//