Tidied up, simplified and documented expand animation code
This commit is contained in:
parent
22c9e8b082
commit
b48d8fc49b
3 changed files with 130 additions and 59 deletions
|
|
@ -185,12 +185,6 @@ TimelineLayoutHelper::layout_headers_recursive(
|
||||||
shared_ptr<timeline::Track> timeline_track =
|
shared_ptr<timeline::Track> timeline_track =
|
||||||
lookup_timeline_track(model_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?
|
// Is the track going to be shown?
|
||||||
if(parent_expanded)
|
if(parent_expanded)
|
||||||
{
|
{
|
||||||
|
|
@ -208,6 +202,11 @@ TimelineLayoutHelper::layout_headers_recursive(
|
||||||
child_offset += track_height + TimelineWidget::TrackPadding;
|
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
|
// Recurse to children
|
||||||
const bool expand_child =
|
const bool expand_child =
|
||||||
(is_animating || timeline_track->get_expanded())
|
(is_animating || timeline_track->get_expanded())
|
||||||
|
|
@ -218,15 +217,11 @@ TimelineLayoutHelper::layout_headers_recursive(
|
||||||
header_width, indent_width, depth + 1, expand_child);
|
header_width, indent_width, depth + 1, expand_child);
|
||||||
|
|
||||||
// Do collapse animation as necessary
|
// Do collapse animation as necessary
|
||||||
if(track_animation_state != Track::NoAnimationState)
|
if(is_track_animating)
|
||||||
{
|
{
|
||||||
// Tick the track expand animation
|
|
||||||
timeline_track->tick_expand_animation();
|
|
||||||
|
|
||||||
// Calculate the height of te area which will be
|
// Calculate the height of te area which will be
|
||||||
// shown as expanded
|
// shown as expanded
|
||||||
const float a = ((float)track_animation_state /
|
const float a = timeline_track->get_expand_animation_state();
|
||||||
(float)Track::MaxExpandAnimation);
|
|
||||||
child_branch_height *= a * a;
|
child_branch_height *= a * a;
|
||||||
const int y_limit =
|
const int y_limit =
|
||||||
branch_offset + child_offset + child_branch_height;
|
branch_offset + child_offset + child_branch_height;
|
||||||
|
|
@ -248,6 +243,9 @@ TimelineLayoutHelper::layout_headers_recursive(
|
||||||
if(rect.get_y() + rect.get_height() > y_limit)
|
if(rect.get_y() + rect.get_height() > y_limit)
|
||||||
headerBoxes.erase(track);
|
headerBoxes.erase(track);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tick the track expand animation
|
||||||
|
timeline_track->tick_expand_animation();
|
||||||
}
|
}
|
||||||
|
|
||||||
child_offset += child_branch_height;
|
child_offset += child_branch_height;
|
||||||
|
|
|
||||||
|
|
@ -36,26 +36,19 @@ namespace gui {
|
||||||
namespace widgets {
|
namespace widgets {
|
||||||
namespace timeline {
|
namespace timeline {
|
||||||
|
|
||||||
const int Track::NoAnimationState = -1;
|
const float Track::ExpandAnimationPeriod = 0.15;
|
||||||
const int Track::MaxExpandAnimation = 65536;
|
|
||||||
const double Track::ExpandAnimationPeriod = 0.15;
|
|
||||||
|
|
||||||
Glib::Timer Track::timer;
|
|
||||||
|
|
||||||
Track::Track(TimelineWidget &timeline_widget,
|
Track::Track(TimelineWidget &timeline_widget,
|
||||||
shared_ptr<model::Track> track) :
|
shared_ptr<model::Track> track) :
|
||||||
timelineWidget(timeline_widget),
|
timelineWidget(timeline_widget),
|
||||||
model_track(track),
|
model_track(track),
|
||||||
expanded(true),
|
expanded(true),
|
||||||
expandAnimationState(Track::NoAnimationState),
|
expandDirection(None),
|
||||||
enableButton(Gtk::StockID("track_enabled")),
|
enableButton(Gtk::StockID("track_enabled")),
|
||||||
lockButton(Gtk::StockID("track_unlocked"))
|
lockButton(Gtk::StockID("track_unlocked"))
|
||||||
{
|
{
|
||||||
REQUIRE(model_track);
|
REQUIRE(model_track);
|
||||||
|
|
||||||
// Ensure that the timer is running
|
|
||||||
timer.start();
|
|
||||||
|
|
||||||
titleMenuButton.set_relief(RELIEF_HALF);
|
titleMenuButton.set_relief(RELIEF_HALF);
|
||||||
|
|
||||||
buttonBar.append(enableButton);
|
buttonBar.append(enableButton);
|
||||||
|
|
@ -121,71 +114,81 @@ Track::get_expanded() const
|
||||||
void
|
void
|
||||||
Track::expand_collapse(ExpandDirection direction)
|
Track::expand_collapse(ExpandDirection direction)
|
||||||
{
|
{
|
||||||
|
REQUIRE(direction != None);
|
||||||
|
|
||||||
expandDirection = direction;
|
expandDirection = direction;
|
||||||
if(direction == Expand)
|
if(direction == Expand)
|
||||||
{
|
{
|
||||||
expanded = true;
|
expanded = true;
|
||||||
expandAnimationState = 0;
|
expandAnimationState = 0.0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
expanded = false;
|
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
|
Track::get_expand_animation_state() const
|
||||||
{
|
{
|
||||||
ENSURE((expandAnimationState >= 0 &&
|
ENSURE(expandAnimationState >= 0.0 &&
|
||||||
expandAnimationState <= MaxExpandAnimation) ||
|
expandAnimationState <= 1.0);
|
||||||
expandAnimationState == NoAnimationState);
|
|
||||||
return expandAnimationState;
|
return expandAnimationState;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Track::is_expand_animating() const
|
||||||
|
{
|
||||||
|
return expandDirection != None;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Track::tick_expand_animation()
|
Track::tick_expand_animation()
|
||||||
{
|
{
|
||||||
if(expandAnimationState <= NoAnimationState)
|
REQUIRE(expandDirection != None); // tick_expand_animation should not
|
||||||
{
|
// be unless is_expand_animating
|
||||||
WARN(gui, "tick_expand_animation() was called when"
|
// returns true
|
||||||
" expandAnimationState was set to NoAnimationState");
|
REQUIRE(expand_timer);
|
||||||
return;
|
const float delta =
|
||||||
}
|
(float)expand_timer->elapsed() / ExpandAnimationPeriod;
|
||||||
|
expand_timer->reset(); // reset the timer to t=0
|
||||||
const double delta = MaxExpandAnimation * (timer.elapsed() - lastTickTime) / ExpandAnimationPeriod;
|
|
||||||
|
|
||||||
if(expandDirection == Expand)
|
if(expandDirection == Expand)
|
||||||
{
|
{
|
||||||
expandAnimationState += delta;
|
expandAnimationState += delta;
|
||||||
if(expandAnimationState >= MaxExpandAnimation)
|
if(expandAnimationState >= 1.0)
|
||||||
expandAnimationState = NoAnimationState;
|
expandDirection = None;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
expandAnimationState -= delta;
|
expandAnimationState -= delta;
|
||||||
if(expandAnimationState <= 0)
|
if(expandAnimationState <= 0.0)
|
||||||
expandAnimationState = NoAnimationState;
|
expandDirection = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
lastTickTime = timer.elapsed();
|
if(expandDirection == None)
|
||||||
|
expand_timer.reset(); // We've finished with the timer - delete it
|
||||||
ENSURE((expandAnimationState >= 0 &&
|
|
||||||
expandAnimationState <= MaxExpandAnimation) ||
|
|
||||||
expandAnimationState == NoAnimationState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Gtk::ExpanderStyle
|
Gtk::ExpanderStyle
|
||||||
Track::get_expander_style() const
|
Track::get_expander_style() const
|
||||||
{
|
{
|
||||||
const int notch = Track::MaxExpandAnimation / 3;
|
const int notch = 1.0 / 3.0;
|
||||||
if(expanded)
|
if(expanded)
|
||||||
{
|
{
|
||||||
if(expandAnimationState == Track::NoAnimationState)
|
if(expandDirection == None)
|
||||||
return EXPANDER_EXPANDED;
|
return EXPANDER_EXPANDED;
|
||||||
else if(expandAnimationState >= notch * 2)
|
else if(expandAnimationState >= notch * 2.0)
|
||||||
return EXPANDER_SEMI_EXPANDED;
|
return EXPANDER_SEMI_EXPANDED;
|
||||||
else if(expandAnimationState >= notch)
|
else if(expandAnimationState >= notch)
|
||||||
return EXPANDER_SEMI_COLLAPSED;
|
return EXPANDER_SEMI_COLLAPSED;
|
||||||
|
|
@ -194,11 +197,11 @@ Track::get_expander_style() const
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(expandAnimationState == Track::NoAnimationState)
|
if(expandDirection == None)
|
||||||
return EXPANDER_COLLAPSED;
|
return EXPANDER_COLLAPSED;
|
||||||
else if(expandAnimationState <= notch)
|
else if(expandAnimationState <= notch)
|
||||||
return EXPANDER_SEMI_COLLAPSED;
|
return EXPANDER_SEMI_COLLAPSED;
|
||||||
else if(expandAnimationState <= notch * 2)
|
else if(expandAnimationState <= notch * 2.0)
|
||||||
return EXPANDER_SEMI_EXPANDED;
|
return EXPANDER_SEMI_EXPANDED;
|
||||||
else
|
else
|
||||||
return EXPANDER_EXPANDED;
|
return EXPANDER_EXPANDED;
|
||||||
|
|
|
||||||
|
|
@ -37,12 +37,23 @@ namespace timeline {
|
||||||
|
|
||||||
class TimelineViewWindow;
|
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
|
class Track : public sigc::trackable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An enum used by the branch expand/collapse animation.
|
||||||
|
* ExpandDirection represents whether the branch us being expanded or
|
||||||
|
* collapsed, or neither.
|
||||||
|
**/
|
||||||
enum ExpandDirection
|
enum ExpandDirection
|
||||||
{
|
{
|
||||||
|
None,
|
||||||
Expand,
|
Expand,
|
||||||
Collapse
|
Collapse
|
||||||
};
|
};
|
||||||
|
|
@ -57,15 +68,48 @@ public:
|
||||||
|
|
||||||
int get_height() const;
|
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;
|
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);
|
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();
|
void tick_expand_animation();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the expander style, given the animation state.
|
||||||
|
**/
|
||||||
Gtk::ExpanderStyle get_expander_style() const;
|
Gtk::ExpanderStyle get_expander_style() const;
|
||||||
|
|
||||||
void show_header_context_menu(guint button, guint32 time);
|
void show_header_context_menu(guint button, guint32 time);
|
||||||
|
|
@ -75,9 +119,12 @@ public:
|
||||||
const = 0;
|
const = 0;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static const int NoAnimationState;
|
//----- Constants -----//
|
||||||
static const int MaxExpandAnimation;
|
|
||||||
static const double ExpandAnimationPeriod;
|
/**
|
||||||
|
* Specifies the period of the expand animation in seconds.
|
||||||
|
**/
|
||||||
|
static const float ExpandAnimationPeriod;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//----- Internals -----//
|
//----- Internals -----//
|
||||||
|
|
@ -96,13 +143,36 @@ protected:
|
||||||
boost::shared_ptr<model::Track> model_track;
|
boost::shared_ptr<model::Track> model_track;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This bool is true if this branch is expanded. false if it is
|
||||||
|
* collapsed.
|
||||||
|
**/
|
||||||
bool expanded;
|
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;
|
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;
|
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 ------//
|
//----- Header Widgets ------//
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue